doanduyhai / Achilles

An advanced Java Object Mapper/Query DSL generator for Cassandra
http://achilles.archinnov.info
Apache License 2.0
241 stars 92 forks source link

Add support for specifying the name of the getter and setter that corresponds to a mapped field. #347

Closed ccarpenter04 closed 5 years ago

ccarpenter04 commented 5 years ago

It would be nice to be able to specify the name of the getter and setter that corresponds to mapped fields instead of Achilles making the assumption that all getters and setters will use javabean-style naming conventions. For example, for part of my project we're using fields of type Boolean (not the primitive). For these fields, my team decided to use the isX naming convention even though it's debatable whether or not that actually conforms to javabean naming conventions. It would be nice to be able to specify the name of the getter/setter directly instead of being forced into using naming conventions that deriveGetterName/deriveSetterName are capable of deriving from the fieldName.

doanduyhai commented 5 years ago

Better idea, forget about getter/setter and embrace immutability:

https://github.com/doanduyhai/Achilles/wiki/Table-Mapping#immutable-entity

https://github.com/doanduyhai/Achilles/wiki/Achilles-Annotations#entitycreator

ccarpenter04 commented 5 years ago

Unfortunately that's not a change I can make, I considered it before making this issue.

doanduyhai commented 5 years ago

In this case, instead of bending Achilles, try this pattern:


public Boolean isX()  {
   return this.getX();
}

//Default getter detected by Achilles
public Boolean getX() {
   return this.X;
}
ccarpenter04 commented 5 years ago

I can do that, it just creates some redundancy. Is there a reason you're so against expanding Achilles to have this functionality? It seems like a pretty basic request with use cases. It would just be a matter of making it read a value from an annotation instead of using the deriveGetterName/deriveSetterName methods. It would allow developers to have more control.

doanduyhai commented 5 years ago

I don't want Achilles to become like Jackson with plenty of different ways to do the same thing. Java beans convention support and immutable entity support is good enough for 90% of use cases

ccarpenter04 commented 5 years ago

This isn't just adding a new way to do the same thing though, there is currently no way to provide the name of a getter and setter for a given field. That's something rather basic that in my opinion should be customizable, because modifying the naming conventions being used by an entire project is not always viable.

doanduyhai commented 5 years ago

If you really want this feature for your team, you're welcomed to push a pull-request.

For the record, the parsing of getter is done here: https://github.com/doanduyhai/Achilles/blob/master/achilles-core/src/main/java/info/archinnov/achilles/internals/apt/AptUtils.java#L444-L455

The getterName is computed here:

https://github.com/doanduyhai/Achilles/blob/master/achilles-core/src/main/java/info/archinnov/achilles/internals/parser/FieldInfoParser.java#L146-L155

    protected List<String> deriveGetterName(VariableElement elm) {
        final String fieldName = elm.getSimpleName().toString();
        final TypeMirror typeMirror = elm.asType();
        String camelCase = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        if (typeMirror.getKind() == TypeKind.BOOLEAN) {
            return asList("is" + camelCase, "get" + camelCase);
        } else {
            return asList("get" + camelCase);
        }
    }

As you can see, we detect isXXX whenever the type of the field is a primitive boolean, otherwise we look for getXXX.

To change this behavior, it's easier to modify this deriveGetterName than to introduce a cumbersome annotation system just to meet your requirements.

You can for example create a new configuration parameter (something like PARSE_BOOLEAN_FIELD_GETTER_PREFIX_WITH_IS), declares it at the EntityParsingContext level. The EntityParsingContext is injected into the FieldInfoParser so basically you just need to check a flag inside the deriveGetterName method