21
21
22
22
import com .aerospike .client .AerospikeException ;
23
23
import com .aerospike .client .Bin ;
24
+ import com .aerospike .client .Key ;
24
25
import com .aerospike .client .Record ;
26
+ import com .aerospike .client .Value ;
25
27
import com .aerospike .client .cdt .MapOrder ;
26
28
import com .aerospike .client .policy .BatchPolicy ;
27
29
import com .aerospike .client .policy .Policy ;
@@ -137,8 +139,8 @@ public ClassCacheEntry<T> construct() {
137
139
this .overrideSettings (config );
138
140
}
139
141
140
- this .loadFieldsFromClass (clazz , this . mapAll , config );
141
- this .loadPropertiesFromClass (clazz , config );
142
+ this .loadFieldsFromClass ();
143
+ this .loadPropertiesFromClass ();
142
144
this .superClazz = ClassCache .getInstance ().loadClass (this .clazz .getSuperclass (), this .mapper );
143
145
this .binCount = this .values .size () + (superClazz != null ? superClazz .binCount : 0 );
144
146
if (this .binCount == 0 ) {
@@ -538,7 +540,7 @@ private PropertyDefinition getOrCreateProperty(String name, Map<String, Property
538
540
return thisProperty ;
539
541
}
540
542
541
- private void loadPropertiesFromClass (@ NotNull Class <?> clazz , ClassConfig config ) {
543
+ private void loadPropertiesFromClass () {
542
544
Map <String , PropertyDefinition > properties = new HashMap <>();
543
545
PropertyDefinition keyProperty = null ;
544
546
KeyConfig keyConfig = config != null ? config .getKey () : null ;
@@ -617,10 +619,10 @@ private void loadPropertiesFromClass(@NotNull Class<?> clazz, ClassConfig config
617
619
}
618
620
}
619
621
620
- private void loadFieldsFromClass (Class <?> clazz , boolean mapAll , ClassConfig config ) {
622
+ private void loadFieldsFromClass () {
621
623
KeyConfig keyConfig = config != null ? config .getKey () : null ;
622
624
String keyField = keyConfig == null ? null : keyConfig .getField ();
623
- for (Field thisField : clazz .getDeclaredFields ()) {
625
+ for (Field thisField : this . clazz .getDeclaredFields ()) {
624
626
boolean isKey = false ;
625
627
BinConfig thisBin = getBinFromField (thisField );
626
628
if (thisField .isAnnotationPresent (AerospikeKey .class ) || (!StringUtils .isBlank (keyField ) && keyField .equals (thisField .getName ()))) {
@@ -643,7 +645,6 @@ private void loadFieldsFromClass(Class<?> clazz, boolean mapAll, ClassConfig con
643
645
644
646
if (this .mapAll || thisField .isAnnotationPresent (AerospikeBin .class ) || thisBin != null ) {
645
647
// This field needs to be mapped
646
- thisField .setAccessible (true );
647
648
AerospikeBin bin = thisField .getAnnotation (AerospikeBin .class );
648
649
String binName = bin == null ? null : ParserUtils .getInstance ().get (bin .name ());
649
650
if (thisBin != null && !StringUtils .isBlank (thisBin .getDerivedName ())) {
@@ -652,25 +653,81 @@ private void loadFieldsFromClass(Class<?> clazz, boolean mapAll, ClassConfig con
652
653
String name ;
653
654
if (StringUtils .isBlank (binName )) {
654
655
name = thisField .getName ();
655
- }
656
- else {
656
+ } else {
657
657
name = binName ;
658
658
}
659
659
if (isKey ) {
660
660
this .keyName = name ;
661
661
}
662
-
662
+
663
663
if (this .values .get (name ) != null ) {
664
664
throw new AerospikeException ("Class " + clazz .getName () + " cannot define the mapped name " + name + " more than once" );
665
665
}
666
- AnnotatedType annotatedType = new AnnotatedType (config , thisField );
667
- TypeMapper typeMapper = TypeUtils .getMapper (thisField .getType (), annotatedType , this .mapper );
668
- ValueType valueType = new ValueType .FieldValue (thisField , typeMapper , annotatedType );
669
- values .put (name , valueType );
666
+ if ((bin != null && bin .useAccessors ()) || (thisBin != null && thisBin .getUseAccessors () != null && thisBin .getUseAccessors ())) {
667
+ validateAccessorsForField (name , thisField );
668
+ } else {
669
+ thisField .setAccessible (true );
670
+ AnnotatedType annotatedType = new AnnotatedType (config , thisField );
671
+ TypeMapper typeMapper = TypeUtils .getMapper (thisField .getType (), annotatedType , this .mapper );
672
+ ValueType valueType = new ValueType .FieldValue (thisField , typeMapper , annotatedType );
673
+ values .put (name , valueType );
674
+ }
670
675
}
671
676
}
672
677
}
673
678
679
+ private Method findMethodWithNameAndParams (String name , Class <?> ... params ) {
680
+ try {
681
+ Method method = this .clazz .getDeclaredMethod (name , params );
682
+ // TODO: Should this ascend the inheritance hierarchy using getMethod on superclasses?
683
+ return method ;
684
+ } catch (NoSuchMethodException nsme ) {
685
+ return null ;
686
+ }
687
+ }
688
+
689
+ private void validateAccessorsForField (String binName , Field thisField ) {
690
+ String fieldName = thisField .getName ();
691
+ String methodNameBase = fieldName .substring (0 , 1 ).toUpperCase () + fieldName .substring (1 );
692
+ String getterName = "get" + methodNameBase ;
693
+ String setterName = "set" + methodNameBase ;
694
+
695
+ Method getter = findMethodWithNameAndParams (getterName );
696
+ if (getter == null ) {
697
+ throw new AerospikeException (String .format (
698
+ "Expected to find getter for field %s on class %s due to it being configured to useAccessors, but no method with the signature \" %s %s()\" was found" ,
699
+ fieldName ,
700
+ this .clazz .getSimpleName (),
701
+ thisField .getType ().getSimpleName (),
702
+ getterName ));
703
+ }
704
+
705
+ Method setter = findMethodWithNameAndParams (setterName , thisField .getType ());
706
+ if (setter == null ) {
707
+ setter = findMethodWithNameAndParams (setterName , thisField .getType (), Key .class );
708
+ }
709
+ if (setter == null ) {
710
+ setter = findMethodWithNameAndParams (setterName , thisField .getType (), Value .class );
711
+ }
712
+ if (setter == null ) {
713
+ throw new AerospikeException (String .format (
714
+ "Expected to find setter for field %s on class %s due to it being configured to useAccessors, but no method with the name \" %s\" was found" ,
715
+ fieldName ,
716
+ this .clazz .getSimpleName (),
717
+ setterName ));
718
+ }
719
+
720
+ AnnotatedType annotatedType = new AnnotatedType (config , thisField );
721
+ TypeMapper typeMapper = TypeUtils .getMapper (thisField .getType (), annotatedType , this .mapper );
722
+ PropertyDefinition property = new PropertyDefinition (binName , mapper );
723
+ property .setGetter (getter );
724
+ property .setSetter (setter );
725
+ property .validate (clazz .getName (), config , false );
726
+
727
+ ValueType value = new ValueType .MethodValue (property , typeMapper , annotatedType );
728
+ values .put (binName , value );
729
+ }
730
+
674
731
public Object translateKeyToAerospikeKey (Object key ) {
675
732
return this .key .getTypeMapper ().toAerospikeFormat (key );
676
733
}
0 commit comments