/*
* This code is distributed under The GNU Lesser General Public License (LGPLv3)
* Please visit GNU site for LGPLv3 http://www.gnu.org/copyleft/lesser.html
*
* Copyright Denis Pavlov 2009
* Web: http://www.genericdtoassembler.org
* SVN: https://svn.code.sf.net/p/geda-genericdto/code/trunk/
* SVN (mirror): http://geda-genericdto.googlecode.com/svn/trunk/
*/
package com.inspiresoftware.lib.dto.geda.assembler;
import com.inspiresoftware.lib.dto.geda.assembler.annotations.AnnotationProxy;
import com.inspiresoftware.lib.dto.geda.assembler.annotations.impl.AnnotationProxies;
import com.inspiresoftware.lib.dto.geda.assembler.meta.PipeMetadata;
import com.inspiresoftware.lib.dto.geda.exception.UnableToCreateInstanceException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Builder for creating chains of metadata for annotations.
*
* @author DPavlov
*/
class MetadataChainAnnotationBuilder implements MetadataChainBuilder {
/**
* Build metadata chain for this field.
* @param dtoField fiel to build pipe for
* @return metadata chain.
* @throws com.inspiresoftware.lib.dto.geda.exception.UnableToCreateInstanceException when collections/map pipe cannot create data readers/writers
*/
public List<PipeMetadata> build(final Field dtoField) throws UnableToCreateInstanceException {
final Map<String, AnnotationProxy> dtoFieldAnn = AnnotationProxies.getFieldAnnotationProxy(dtoField);
if (dtoFieldAnn.isEmpty()) {
return null;
}
if (dtoFieldAnn.containsKey("DtoField")) {
return buildFieldChain(dtoField, dtoFieldAnn.get("DtoField"), dtoFieldAnn.get("DtoParent"));
}
if (dtoFieldAnn.containsKey("DtoVirtualField")) {
return buildVirtualFieldChain(dtoField, dtoFieldAnn.get("DtoVirtualField"));
}
if (dtoFieldAnn.containsKey("DtoCollection")) {
return buildCollectionChain(dtoField, dtoFieldAnn.get("DtoCollection"));
}
if (dtoFieldAnn.containsKey("DtoMap")) {
return buildMapChain(dtoField, dtoFieldAnn.get("DtoMap"));
}
return null;
}
private List<PipeMetadata> buildVirtualFieldChain(final Field dtoField, final AnnotationProxy dtoFieldAnn) {
final String[] bindings = { "#this#" + dtoField.getName() };
final List<PipeMetadata> metas = new ArrayList<PipeMetadata>(bindings.length);
for (int index = 0; index < bindings.length; index++) {
metas.add(new FieldPipeMetadata(
dtoField.getName(),
bindings[index],
(String) dtoFieldAnn.getValue("dtoBeanKey"),
getStringFromArray((String[]) dtoFieldAnn.getValue("entityBeanKeys"), index),
(Boolean) dtoFieldAnn.getValue("readOnly"),
(String) dtoFieldAnn.getValue("converter"),
false,
null,
null
));
}
return metas;
}
private List<PipeMetadata> buildFieldChain(final Field dtoField, final AnnotationProxy dtoFieldAnn, final AnnotationProxy dtoParentAnn) {
final String[] bindings = createFieldBindingChain(getBindingFromAnnotationOrFieldName((String) dtoFieldAnn.getValue("value"), dtoField.getName()));
final List<PipeMetadata> metas = new ArrayList<PipeMetadata>(bindings.length);
for (int index = 0; index < bindings.length; index++) {
metas.add(new FieldPipeMetadata(
dtoField.getName(),
bindings[index],
(String) dtoFieldAnn.getValue("dtoBeanKey"),
getStringFromArray((String[]) dtoFieldAnn.getValue("entityBeanKeys"), index),
(Boolean) dtoFieldAnn.getValue("readOnly"),
(String) dtoFieldAnn.getValue("converter"),
dtoParentAnn != null,
dtoParentAnn != null ? (String) dtoParentAnn.getValue("value") : null,
dtoParentAnn != null ? (String) dtoParentAnn.getValue("retriever") : null
));
}
return metas;
}
@SuppressWarnings("unchecked")
private List<PipeMetadata> buildCollectionChain(final Field dtoField, final AnnotationProxy dtoCollAnn)
throws UnableToCreateInstanceException {
final String[] bindings = createFieldBindingChain(getBindingFromAnnotationOrFieldName((String) dtoCollAnn.getValue("value"), dtoField.getName()));
final List<PipeMetadata> metas = new ArrayList<PipeMetadata>(bindings.length);
for (int index = 0; index < bindings.length; index++) {
metas.add(new CollectionPipeMetadata(
dtoField.getName(),
bindings[index],
(String) dtoCollAnn.getValue("dtoBeanKey"),
getStringFromArray((String[]) dtoCollAnn.getValue("entityBeanKeys"), index),
(Boolean) dtoCollAnn.getValue("readOnly"),
(Class) dtoCollAnn.getValue("dtoCollectionClass"),
(String) dtoCollAnn.getValue("dtoCollectionClassKey"),
(Class) dtoCollAnn.getValue("entityCollectionClass"),
(String) dtoCollAnn.getValue("entityCollectionClassKey"),
(Class) dtoCollAnn.getValue("entityGenericType"),
(String) dtoCollAnn.getValue("entityGenericTypeKey"),
(Class) dtoCollAnn.getValue("dtoToEntityMatcher"),
(String) dtoCollAnn.getValue("dtoToEntityMatcherKey")
));
}
return metas;
}
@SuppressWarnings("unchecked")
private List<PipeMetadata> buildMapChain(final Field dtoField, final AnnotationProxy dtoMapAnn) throws UnableToCreateInstanceException {
final String[] bindings = createFieldBindingChain(getBindingFromAnnotationOrFieldName((String) dtoMapAnn.getValue("value"), dtoField.getName()));
final List<PipeMetadata> metas = new ArrayList<PipeMetadata>(bindings.length);
for (int index = 0; index < bindings.length; index++) {
metas.add(new MapPipeMetadata(
dtoField.getName(),
bindings[index],
(String) dtoMapAnn.getValue("dtoBeanKey"),
getStringFromArray((String[]) dtoMapAnn.getValue("entityBeanKeys"), index),
(Boolean) dtoMapAnn.getValue("readOnly"),
(Class) dtoMapAnn.getValue("dtoMapClass"),
(String) dtoMapAnn.getValue("dtoMapClassKey"),
(Class) dtoMapAnn.getValue("entityMapOrCollectionClass"),
(String) dtoMapAnn.getValue("entityMapOrCollectionClassKey"),
(Class) dtoMapAnn.getValue("entityGenericType"),
(String) dtoMapAnn.getValue("entityGenericTypeKey"),
(String) dtoMapAnn.getValue("entityCollectionMapKey"),
(Boolean) dtoMapAnn.getValue("useEntityMapKey"),
(Class) dtoMapAnn.getValue("dtoToEntityMatcher"),
(String) dtoMapAnn.getValue("dtoToEntityMatcherKey")
));
}
return metas;
}
private String getBindingFromAnnotationOrFieldName(final String annotation, final String fieldName) {
if (annotation == null || annotation.length() == 0) {
return fieldName;
}
return annotation;
}
private String[] createFieldBindingChain(final String binding) {
if (binding.indexOf('.') == -1) {
return new String[] { binding };
}
return binding.split("\\.");
}
private String getStringFromArray(final String[] array, final int index) {
if (array != null && index < array.length) {
return array[index];
}
return "";
}
}