4040import org .springframework .util .LinkedMultiValueMap ;
4141import org .springframework .util .MultiValueMap ;
4242
43+ import com .amazonaws .services .dynamodbv2 .datamodeling .DynamoDBMapperFieldModel ;
44+ import com .amazonaws .services .dynamodbv2 .datamodeling .DynamoDBMapperTableModel ;
4345import com .amazonaws .services .dynamodbv2 .datamodeling .DynamoDBMarshaller ;
4446import com .amazonaws .services .dynamodbv2 .datamodeling .DynamoDBQueryExpression ;
4547import com .amazonaws .services .dynamodbv2 .model .AttributeValue ;
@@ -56,6 +58,7 @@ public abstract class AbstractDynamoDBQueryCriteria<T, ID extends Serializable>
5658 protected Class <T > clazz ;
5759 private DynamoDBEntityInformation <T , ID > entityInformation ;
5860 private Map <String , String > attributeNamesByPropertyName ;
61+ private final DynamoDBMapperTableModel <T > tableModel ;
5962 private String hashKeyPropertyName ;
6063
6164 protected MultiValueMap <String , Condition > attributeConditions ;
@@ -211,14 +214,15 @@ protected List<Condition> getHashKeyConditions() {
211214 return hashKeyConditions ;
212215 }
213216
214- public AbstractDynamoDBQueryCriteria (DynamoDBEntityInformation <T , ID > dynamoDBEntityInformation ) {
217+ public AbstractDynamoDBQueryCriteria (DynamoDBEntityInformation <T , ID > dynamoDBEntityInformation , final DynamoDBMapperTableModel < T > tableModel ) {
215218 this .clazz = dynamoDBEntityInformation .getJavaType ();
216219 this .attributeConditions = new LinkedMultiValueMap <String , Condition >();
217220 this .propertyConditions = new LinkedMultiValueMap <String , Condition >();
218221 this .hashKeyPropertyName = dynamoDBEntityInformation .getHashKeyPropertyName ();
219222 this .entityInformation = dynamoDBEntityInformation ;
220223 this .attributeNamesByPropertyName = new HashMap <String , String >();
221-
224+ // TODO consider adding the DynamoDBMapper table model to DynamoDBEntityInformation instead
225+ this .tableModel = tableModel ;
222226 }
223227
224228 private String getFirstDeclaredIndexNameForAttribute (Map <String ,String []> indexNamesByAttributeName ,List <String > indexNamesToCheck ,String attributeName )
@@ -479,16 +483,22 @@ public DynamoDBQueryCriteria<T, ID> withCondition(String propertyName, Condition
479483 return this ;
480484 }
481485
482- @ SuppressWarnings ("unchecked" )
483- protected <V > Object getPropertyAttributeValue (String propertyName , Object value ) {
484- DynamoDBMarshaller <V > marshaller = (DynamoDBMarshaller <V >) entityInformation .getMarshallerForProperty (propertyName );
486+ @ SuppressWarnings ({"deprecation" , "unchecked" })
487+ protected <V extends Object > Object getPropertyAttributeValue (final String propertyName , final V value ) {
488+ // TODO consider removing DynamoDBMarshaller code altogether as table model will handle accordingly
489+ final DynamoDBMarshaller <V > marshaller = (DynamoDBMarshaller <V >) entityInformation .getMarshallerForProperty (propertyName );
485490
486- if (marshaller != null ) {
487- return marshaller .marshall ((V ) value );
488- } else {
489- return value ;
490- }
491- }
491+ if (marshaller != null ) {
492+ return marshaller .marshall (value );
493+ } else if (tableModel != null ) { // purely here for testing as DynamoDBMapperTableModel cannot be mocked using Mockito
494+ DynamoDBMapperFieldModel <T ,Object > fieldModel = tableModel .field (propertyName );
495+ if (fieldModel != null ) {
496+ return fieldModel .convert (value );
497+ }
498+ }
499+
500+ return value ;
501+ }
492502
493503 protected <V > Condition createNoValueCondition (String propertyName , ComparisonOperator comparisonOperator ) {
494504
@@ -626,16 +636,19 @@ protected Condition createSingleValueCondition(String propertyName, ComparisonOp
626636 Assert .notNull (o , "Creating conditions on null property values not supported: please specify a value for '"
627637 + propertyName + "'" );
628638
639+ List <AttributeValue > attributeValueList = new ArrayList <AttributeValue >();
629640 Object attributeValue = !alreadyMarshalledIfRequired ? getPropertyAttributeValue (propertyName , o ) : o ;
641+ if (ClassUtils .isAssignableValue (AttributeValue .class , attributeValue )) {
642+ attributeValueList .add ((AttributeValue ) attributeValue );
643+ } else {
644+ boolean marshalled = !alreadyMarshalledIfRequired && attributeValue != o
645+ && !entityInformation .isCompositeHashAndRangeKeyProperty (propertyName );
630646
631- boolean marshalled = !alreadyMarshalledIfRequired && attributeValue != o
632- && !entityInformation .isCompositeHashAndRangeKeyProperty (propertyName );
647+ Class <?> targetPropertyType = marshalled ? String .class : propertyType ;
648+ attributeValueList = addAttributeValue (attributeValueList , attributeValue , propertyName , targetPropertyType , true );
649+ }
633650
634- Class <?> targetPropertyType = marshalled ? String .class : propertyType ;
635- List <AttributeValue > attributeValueList = new ArrayList <AttributeValue >();
636- attributeValueList = addAttributeValue (attributeValueList , attributeValue , propertyName , targetPropertyType , true );
637651 return new Condition ().withComparisonOperator (comparisonOperator ).withAttributeValueList (attributeValueList );
638-
639652 }
640653
641654 protected Condition createCollectionCondition (String propertyName , ComparisonOperator comparisonOperator , Iterable <?> o ,
@@ -647,12 +660,15 @@ protected Condition createCollectionCondition(String propertyName, ComparisonOpe
647660 boolean marshalled = false ;
648661 for (Object object : o ) {
649662 Object attributeValue = getPropertyAttributeValue (propertyName , object );
650- if (attributeValue != null ) {
651- marshalled = attributeValue != object && !entityInformation .isCompositeHashAndRangeKeyProperty (propertyName );
652- }
653- Class <?> targetPropertyType = marshalled ? String .class : propertyType ;
654- attributeValueList = addAttributeValue (attributeValueList , attributeValue , propertyName , targetPropertyType , false );
655-
663+ if (ClassUtils .isAssignableValue (AttributeValue .class , attributeValue )) {
664+ attributeValueList .add ((AttributeValue ) attributeValue );
665+ } else {
666+ if (attributeValue != null ) {
667+ marshalled = attributeValue != object && !entityInformation .isCompositeHashAndRangeKeyProperty (propertyName );
668+ }
669+ Class <?> targetPropertyType = marshalled ? String .class : propertyType ;
670+ attributeValueList = addAttributeValue (attributeValueList , attributeValue , propertyName , targetPropertyType , false );
671+ }
656672 }
657673
658674 return new Condition ().withComparisonOperator (comparisonOperator ).withAttributeValueList (attributeValueList );
0 commit comments