package org.springframework.data.simpledb.core.entity; import java.io.Serializable; import java.lang.reflect.Field; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.simpledb.attributeutil.AttributesKeySplitter; import org.springframework.data.simpledb.attributeutil.SimpleDbAttributeValueSplitter; import org.springframework.data.simpledb.reflection.FieldType; import org.springframework.data.simpledb.reflection.FieldTypeIdentifier; import org.springframework.data.simpledb.reflection.MetadataParser; import org.springframework.data.simpledb.reflection.ReflectionUtils; import org.springframework.data.simpledb.repository.support.entityinformation.SimpleDbEntityInformation; public class EntityWrapper<T, ID extends Serializable> { /* entity metadata */ private final SimpleDbEntityInformation<T, ?> entityInformation; /* field wrappers */ private final Map<String, AbstractFieldWrapper<T, ID>> wrappedFields = new HashMap<String, AbstractFieldWrapper<T, ID>>(); private T item; public EntityWrapper(SimpleDbEntityInformation<T, ?> entityInformation, T item) { this(entityInformation, item, false); } public EntityWrapper(SimpleDbEntityInformation<T, ?> entityInformation, T item, boolean isNested) { this.entityInformation = entityInformation; this.item = item; createFieldWrappers(false, isNested); } public EntityWrapper(SimpleDbEntityInformation<T, ?> entityInformation) { this(entityInformation, false); } public EntityWrapper(SimpleDbEntityInformation<T, ?> entityInformation, boolean isNested) { this.entityInformation = entityInformation; try { this.item = entityInformation.getJavaType().newInstance(); createFieldWrappers(true, isNested); } catch(InstantiationException e) { throw new MappingException("Could not instantiate object", e); } catch(IllegalAccessException e) { throw new MappingException("Could not instantiate object", e); } } private void createFieldWrappers(final boolean isNew, final boolean isNested) { List<Field> supportedFields = MetadataParser.getSupportedFields(entityInformation.getJavaType()); for(final Field field : supportedFields) { if (! (!isNested && FieldTypeIdentifier.isOfType(field, FieldType.ID)) ) { wrappedFields.put(field.getName(), FieldWrapperFactory.createFieldWrapper(field, this, isNew)); } } } public String getDomain() { return entityInformation.getDomain(); } public String getItemName() { return entityInformation.getItemName(item); } public Map<String, String> getAttributes() { return entityInformation.getAttributes(item); } public T getItem() { return item; } public void generateIdIfNotSet() { if(entityInformation.getItemName(item) == null) { setId(UUID.randomUUID().toString()); } } public void setId(String itemName) { final Field idField; try { idField = ReflectionUtils.getDeclaredFieldInHierarchy( item.getClass(), entityInformation.getItemNameFieldName(item)); idField.setAccessible(Boolean.TRUE); idField.set(item, itemName); } catch(NoSuchFieldException e) { throw new MappingException("Could not set id field", e); } catch(IllegalAccessException e) { throw new MappingException("Could not set id field", e); } } public Map<String, String> serialize() { return serialize(""); } Map<String, String> serialize(final String fieldNamePrefix) { final Map<String, String> result = new HashMap<String, String>(); for(final AbstractFieldWrapper<T, ID> wrappedField : wrappedFields.values()) { if(wrappedField.getFieldValue() != null) { result.putAll(wrappedField.serialize(fieldNamePrefix)); } } return result; } public Object deserialize(final Map<String, String> attributes) { final Map<String, Map<String, String>> nestedFields = AttributesKeySplitter .splitNestedAttributeKeys(attributes); for(final Entry<String, Map<String, String>> nestedField : nestedFields.entrySet()) { /* call deserialize field with Map<String, String> */ final String fieldName = nestedField.getKey(); final Map<String, String> fieldAttributes = nestedField.getValue(); AbstractFieldWrapper<T, ID> fieldWrapper = getWrapper(fieldName); Object convertedValue = fieldWrapper.deserialize(fieldAttributes); fieldWrapper.setFieldValue(convertedValue); } final Map<String, String> simpleFields = AttributesKeySplitter.splitSimpleAttributesKeys(attributes); for(final Entry<String, String> simpleField : simpleFields.entrySet()) { final String fieldName = simpleField.getKey(); AbstractFieldWrapper<T, ID> fieldWrapper = getWrapper(fieldName); Map<String, String> fieldAttributes = new LinkedHashMap<String, String>(); fieldAttributes.put(fieldName, simpleField.getValue()); Object convertedValue = fieldWrapper.deserialize(fieldAttributes); fieldWrapper.setFieldValue(convertedValue); } return getItem(); } private AbstractFieldWrapper<T, ID> getWrapper(String fieldName) { return wrappedFields.get(fieldName); } public Map<String, List<String>> toMultiValueAttributes() { final Map<String, String> result = new HashMap<String, String>(); for(final AbstractFieldWrapper<T, ID> wrappedField : wrappedFields.values()) { if(wrappedField.getFieldValue() != null) { result.putAll(wrappedField.serialize("")); } } return SimpleDbAttributeValueSplitter.splitAttributeValuesWithExceedingLengths(result); } }