package org.compass.core.converter.dynamic; import java.lang.reflect.Array; import java.util.Collection; import java.util.Iterator; import org.compass.core.Property; import org.compass.core.Resource; import org.compass.core.converter.ConversionException; import org.compass.core.converter.basic.AbstractBasicConverter; import org.compass.core.converter.basic.FormatConverter; import org.compass.core.mapping.Mapping; import org.compass.core.mapping.ResourcePropertyMapping; import org.compass.core.marshall.MarshallingContext; /** * A simple base class for {@link DynamicConverter}. Requires implementation of * {@link #evaluate(Object,org.compass.core.mapping.ResourcePropertyMapping)}. * * <p>Also holds a {@link FormatConverter} for expression that return formatable * objects (like Date). * * @author kimchy */ public abstract class AbstractDynamicConverter extends AbstractBasicConverter implements DynamicConverter { private FormatConverter formatConverter; private Class type; public DynamicConverter copy() { try { DynamicConverter converter = getClass().newInstance(); converter.setType(getType()); converter.setFormatConverter(formatConverter); return converter; } catch (Exception e) { throw new ConversionException("This should not happen", e); } } public void setFormatConverter(FormatConverter formatConverter) { this.formatConverter = formatConverter; } public boolean marshall(Resource resource, Object root, Mapping mapping, MarshallingContext context) throws ConversionException { ResourcePropertyMapping resourcePropertyMapping = (ResourcePropertyMapping) mapping; if (root == null) { return false; } Object value = evaluate(root, resourcePropertyMapping); if (value == null) { if (resourcePropertyMapping.hasNullValue()) { addProperty(resourcePropertyMapping.getNullValue(), resourcePropertyMapping, root, context, resource); } return false; } // save the value in the search engine. Handle array/collection and single values if (value.getClass().isArray()) { int length = Array.getLength(value); for (int i = 0; i < length; i++) { addProperty(Array.get(value, i), resourcePropertyMapping, root, context, resource); } } else if (value instanceof Collection) { Collection colValues = (Collection) value; for (Iterator it = colValues.iterator(); it.hasNext();) { addProperty(it.next(), resourcePropertyMapping, root, context, resource); } } else { addProperty(value, resourcePropertyMapping, root, context, resource); } return resourcePropertyMapping.getStore() != Property.Store.NO; } protected void addProperty(Object value, ResourcePropertyMapping resourcePropertyMapping, Object root, MarshallingContext context, Resource resource) { String sValue; if (formatConverter == null) { sValue = value.toString(); } else { sValue = formatConverter.toString(value, resourcePropertyMapping); } addProperty(sValue, resourcePropertyMapping, root, context, resource); } private void addProperty(String value, ResourcePropertyMapping resourcePropertyMapping, Object root, MarshallingContext context, Resource resource) { Property p = context.getResourceFactory().createProperty(value, resourcePropertyMapping); doSetBoost(p, root, resourcePropertyMapping, context); resource.addProperty(p); } /** * Evaluates the given data object using the configured expression. * * @param o The data object * @param resourcePropertyMapping The resource mapping * @return The object returned as a result of expression evaluation * @throws ConversionException */ protected abstract Object evaluate(Object o, ResourcePropertyMapping resourcePropertyMapping) throws ConversionException; /** * Does nothing since there is no meaning for un-marshalling for dynamic converters */ public Object unmarshall(Resource resource, Mapping mapping, MarshallingContext context) throws ConversionException { // nothing to do here return null; } /** * Does nothing since there is no meaning for un-marshalling for dynamic converters */ protected Object doFromString(String str, ResourcePropertyMapping resourcePropertyMapping, MarshallingContext context) throws ConversionException { // do nothing here return null; } public Class getType() { return type; } public void setType(Class type) { this.type = type; } public Property.Index suggestIndex() { if (formatConverter != null) { return formatConverter.suggestIndex(); } return super.suggestIndex(); } public Property.TermVector suggestTermVector() { if (formatConverter != null) { return formatConverter.suggestTermVector(); } return super.suggestTermVector(); } public Property.Store suggestStore() { if (formatConverter != null) { return formatConverter.suggestStore(); } return super.suggestStore(); } public Boolean suggestOmitNorms() { if (formatConverter != null) { return formatConverter.suggestOmitNorms(); } return super.suggestOmitNorms(); } public Boolean suggestOmitTf() { if (formatConverter != null) { return formatConverter.suggestOmitTf(); } return super.suggestOmitTf(); } }