/*
* Copyright 2004-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.compass.core.config.process;
import java.util.Iterator;
import org.compass.core.accessor.AccessorUtils;
import org.compass.core.config.CompassSettings;
import org.compass.core.config.ConfigurationException;
import org.compass.core.converter.Converter;
import org.compass.core.converter.ConverterLookup;
import org.compass.core.converter.DelegateConverter;
import org.compass.core.converter.basic.FormatConverter;
import org.compass.core.converter.dynamic.DynamicConverter;
import org.compass.core.converter.json.ContextResourcePropertyJsonValueConverter;
import org.compass.core.converter.json.ResourcePropertyJsonValueConverter;
import org.compass.core.converter.json.SimpleJsonValueConverter;
import org.compass.core.converter.mapping.ContextResourcePropertyConverter;
import org.compass.core.converter.mapping.ResourcePropertyConverter;
import org.compass.core.converter.xsem.ResourcePropertyValueConverter;
import org.compass.core.converter.xsem.SimpleXmlValueConverter;
import org.compass.core.engine.naming.PropertyNamingStrategy;
import org.compass.core.mapping.AliasMapping;
import org.compass.core.mapping.CompassMapping;
import org.compass.core.mapping.Mapping;
import org.compass.core.mapping.MappingException;
import org.compass.core.mapping.ResourcePropertyMapping;
import org.compass.core.mapping.json.JsonArrayMapping;
import org.compass.core.mapping.json.JsonContentMapping;
import org.compass.core.mapping.json.JsonMapping;
import org.compass.core.mapping.json.JsonMappingIterator;
import org.compass.core.mapping.json.JsonPropertyMapping;
import org.compass.core.mapping.json.PlainJsonObjectMapping;
import org.compass.core.mapping.json.RootJsonObjectMapping;
import org.compass.core.mapping.osem.AbstractCollectionMapping;
import org.compass.core.mapping.osem.ClassDynamicPropertyMapping;
import org.compass.core.mapping.osem.ClassMapping;
import org.compass.core.mapping.osem.ClassPropertyMapping;
import org.compass.core.mapping.osem.ClassPropertyMetaDataMapping;
import org.compass.core.mapping.osem.ComponentMapping;
import org.compass.core.mapping.osem.ConstantMetaDataMapping;
import org.compass.core.mapping.osem.DynamicMetaDataMapping;
import org.compass.core.mapping.osem.OsemMappingIterator;
import org.compass.core.mapping.osem.ParentMapping;
import org.compass.core.mapping.osem.PlainCascadeMapping;
import org.compass.core.mapping.osem.ReferenceMapping;
import org.compass.core.mapping.rsem.RawResourceMapping;
import org.compass.core.mapping.xsem.XmlObjectMapping;
import org.compass.core.mapping.xsem.XmlPropertyMapping;
/**
* @author kimchy
*/
public class ConverterLookupMappingProcessor implements MappingProcessor {
private ConverterLookup converterLookup;
private CompassSettings settings;
public CompassMapping process(CompassMapping compassMapping, PropertyNamingStrategy namingStrategy,
ConverterLookup converterLookup, CompassSettings settings) throws MappingException {
this.converterLookup = converterLookup;
this.settings = settings;
for (AliasMapping aliasMapping : compassMapping.getMappings()) {
if (aliasMapping instanceof RawResourceMapping) {
lookupConverter((RawResourceMapping) aliasMapping);
} else if (aliasMapping instanceof XmlObjectMapping) {
lookupConverter((XmlObjectMapping) aliasMapping);
} else if (aliasMapping instanceof ClassMapping) {
lookupConverter((ClassMapping) aliasMapping);
} else if (aliasMapping instanceof RootJsonObjectMapping) {
lookupConverter((RootJsonObjectMapping) aliasMapping);
}
}
return compassMapping;
}
private void lookupConverter(RawResourceMapping resourceMapping) throws MappingException {
MappingProcessorUtils.lookupConverter(converterLookup, resourceMapping, true);
for (Iterator it = resourceMapping.mappingsIt(); it.hasNext();) {
MappingProcessorUtils.lookupConverter(converterLookup, (Mapping) it.next(), false);
}
}
private void lookupConverter(XmlObjectMapping xmlObjectMapping) throws MappingException {
MappingProcessorUtils.lookupConverter(converterLookup, xmlObjectMapping);
for (Iterator it = xmlObjectMapping.mappingsIt(); it.hasNext();) {
Mapping mapping = (Mapping) it.next();
MappingProcessorUtils.lookupConverter(converterLookup, mapping, true);
if (mapping instanceof XmlPropertyMapping) {
XmlPropertyMapping xmlPropertyMapping = (XmlPropertyMapping) mapping;
Converter converter;
if (xmlPropertyMapping.getValueConverterName() != null) {
String converterName = xmlPropertyMapping.getValueConverterName();
converter = converterLookup.lookupConverter(converterName);
if (xmlPropertyMapping.getValueConverter() instanceof DelegateConverter) {
((DelegateConverter) xmlPropertyMapping.getValueConverter()).setDelegatedConverter(converter);
converter = xmlPropertyMapping.getValueConverter();
}
if (converter instanceof ResourcePropertyConverter) {
converter = new ResourcePropertyValueConverter((ResourcePropertyConverter) converter);
}
if (converter == null) {
throw new ConfigurationException("Failed to find converter [" + converterName
+ "] for mapping " + "[" + xmlPropertyMapping.getName() + "]");
}
} else {
// this should probably be handled in the actual converteres
converter = new SimpleXmlValueConverter();
}
xmlPropertyMapping.setValueConverter(converter);
}
}
}
private void lookupConverter(ClassMapping classMapping) throws MappingException {
MappingProcessorUtils.lookupConverter(converterLookup, classMapping);
// initalize the managed id converter
for (Iterator<Mapping> it = classMapping.mappingsIt(); it.hasNext();) {
Mapping m = it.next();
if (m instanceof ClassPropertyMapping) {
ClassPropertyMapping classPropertyMapping = (ClassPropertyMapping) m;
if (classPropertyMapping.getManagedIdConverterName() == null) {
if (classPropertyMapping.mappingsSize() == 1) {
Mapping m2 = classPropertyMapping.mappingsIt().next();
if (m2 instanceof ClassPropertyMetaDataMapping) {
classPropertyMapping.setManagedIdConverterName(m2.getConverterName());
}
}
}
if (classPropertyMapping.getManagedIdConverter() == null) {
if (classPropertyMapping.mappingsSize() == 1) {
Mapping m2 = classPropertyMapping.mappingsIt().next();
if (m2 instanceof ClassPropertyMetaDataMapping) {
classPropertyMapping.setManagedIdConverter(m2.getConverter());
}
}
}
}
}
OsemMappingIterator.iterateMappings(new OsemConverterLookup(), classMapping, false);
}
private void lookupConverter(RootJsonObjectMapping jsonMapping) throws MappingException {
MappingProcessorUtils.lookupConverter(converterLookup, jsonMapping);
JsonMappingIterator.iterateMappings(new JsonConverterLookup(), jsonMapping, true);
}
private class JsonConverterLookup implements JsonMappingIterator.JsonMappingCallback {
public void onJsonRootObject(RootJsonObjectMapping jsonObjectMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, jsonObjectMapping);
}
public void onJsonObject(PlainJsonObjectMapping jsonObjectMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, jsonObjectMapping);
}
public void onJsonContent(JsonContentMapping jsonContentMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, jsonContentMapping);
}
public void onJsonProperty(JsonPropertyMapping mapping) {
MappingProcessorUtils.lookupConverter(converterLookup, mapping);
Converter converter;
if (mapping.getValueConverterName() != null) {
String converterName = mapping.getValueConverterName();
converter = converterLookup.lookupConverter(converterName);
if (mapping.getValueConverter() instanceof DelegateConverter) {
((DelegateConverter) mapping.getValueConverter()).setDelegatedConverter(converter);
converter = mapping.getValueConverter();
}
if (converter instanceof ContextResourcePropertyConverter) {
converter = new ContextResourcePropertyJsonValueConverter((ContextResourcePropertyConverter) converter);
} else if (converter instanceof ResourcePropertyConverter) {
converter = new ResourcePropertyJsonValueConverter((ResourcePropertyConverter) converter);
}
if (converter == null) {
throw new ConfigurationException("Failed to find converter [" + converterName
+ "] for mapping " + "[" + mapping.getName() + "]");
}
} else {
// this should probably be handled in the actual converteres
converter = new SimpleJsonValueConverter();
}
mapping.setValueConverter(converter);
}
public void onJsonArray(JsonArrayMapping jsonArrayMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, jsonArrayMapping);
}
public boolean onBeginMultipleMapping(JsonMapping mapping) {
return true;
}
public void onEndMultipleMapping(JsonMapping mapping) {
}
}
private class OsemConverterLookup implements OsemMappingIterator.ClassMappingCallback {
private ClassPropertyMapping classPropertyMapping;
public boolean onBeginClassMapping(ClassMapping classMapping) {
return true;
}
public void onEndClassMapping(ClassMapping classMapping) {
}
public boolean onBeginMultipleMapping(ClassMapping classMapping, Mapping mapping) {
return true;
}
public void onEndMultiplMapping(ClassMapping classMapping, Mapping mapping) {
}
public void onBeginCollectionMapping(AbstractCollectionMapping collectionMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, collectionMapping);
}
public void onEndCollectionMapping(AbstractCollectionMapping collectionMapping) {
}
public void onClassPropertyMapping(ClassMapping classMapping, ClassPropertyMapping classPropertyMapping) {
this.classPropertyMapping = classPropertyMapping;
MappingProcessorUtils.lookupConverter(converterLookup, classPropertyMapping);
}
public void onClassDynamicPropertyMapping(ClassMapping classMapping, ClassDynamicPropertyMapping dynamicPropertyMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, dynamicPropertyMapping);
if (dynamicPropertyMapping.getNameConverter() == null || dynamicPropertyMapping.getNameConverter() instanceof DelegateConverter) {
ResourcePropertyConverter converter = null;
if (dynamicPropertyMapping.getObjectType() == ClassDynamicPropertyMapping.ObjectType.MAP) {
Class keyType;
if (dynamicPropertyMapping.getNameGetter() != null) {
keyType = dynamicPropertyMapping.getNameGetter().getReturnType();
} else {
keyType = AccessorUtils.getMapKeyParameter(dynamicPropertyMapping.getGetter());
}
if (dynamicPropertyMapping.getNameConverterName() != null || keyType != null) {
converter = (ResourcePropertyConverter) MappingProcessorUtils.resolveConverter(dynamicPropertyMapping.getNameConverterName(), null, keyType, converterLookup);
}
} else {
converter = (ResourcePropertyConverter) MappingProcessorUtils.resolveConverter(dynamicPropertyMapping.getNameConverterName(), null, dynamicPropertyMapping.getNameGetter(), converterLookup);
}
if (dynamicPropertyMapping.getNameConverter() instanceof DelegateConverter) {
if (converter != null) {
((DelegateConverter) dynamicPropertyMapping.getNameConverter()).setDelegatedConverter(converter);
}
} else {
dynamicPropertyMapping.setNameConverter(converter);
}
}
if (dynamicPropertyMapping.getValueConverter() == null || dynamicPropertyMapping.getValueConverter() instanceof DelegateConverter) {
ResourcePropertyConverter converter = null;
if (dynamicPropertyMapping.getObjectType() == ClassDynamicPropertyMapping.ObjectType.MAP) {
Class valueType;
if (dynamicPropertyMapping.getValueGetter() != null) {
valueType = dynamicPropertyMapping.getValueGetter().getReturnType();
} else {
valueType = AccessorUtils.getMapValueParameter(dynamicPropertyMapping.getGetter());
}
if (dynamicPropertyMapping.getValueConverterName() != null || valueType != null) {
converter = (ResourcePropertyConverter) MappingProcessorUtils.resolveConverter(dynamicPropertyMapping.getValueConverterName(), null, valueType, converterLookup);
}
} else {
converter = (ResourcePropertyConverter) MappingProcessorUtils.resolveConverter(dynamicPropertyMapping.getValueConverterName(), null, dynamicPropertyMapping.getValueGetter(), converterLookup);
}
if (dynamicPropertyMapping.getValueConverter() instanceof DelegateConverter) {
if (converter != null) {
((DelegateConverter) dynamicPropertyMapping.getValueConverter()).setDelegatedConverter(converter);
}
} else {
dynamicPropertyMapping.setValueConverter(converter);
}
}
if (dynamicPropertyMapping.getValueConverter() != null) {
dynamicPropertyMapping.getResourcePropertyMapping().setConverter(dynamicPropertyMapping.getValueConverter());
}
MappingProcessorUtils.applyResourcePropertySettings(dynamicPropertyMapping.getResourcePropertyMapping(), settings);
}
public void onComponentMapping(ClassMapping classMapping, ComponentMapping componentMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, componentMapping);
}
public void onReferenceMapping(ClassMapping classMapping, ReferenceMapping referenceMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, referenceMapping);
}
public void onParentMapping(ClassMapping classMapping, ParentMapping parentMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, parentMapping);
}
public void onCascadeMapping(ClassMapping classMapping, PlainCascadeMapping cascadeMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, cascadeMapping);
}
public void onConstantMetaDataMappaing(ClassMapping classMapping, ConstantMetaDataMapping constantMetaDataMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, constantMetaDataMapping);
}
public void onClassPropertyMetaDataMapping(ClassPropertyMetaDataMapping classPropertyMetaDataMapping) {
MappingProcessorUtils.lookupConverter(converterLookup, classPropertyMetaDataMapping, classPropertyMapping);
}
public void onDynamicMetaDataMapping(ClassMapping classMapping, DynamicMetaDataMapping dynamicMetaDataMapping) {
Converter converter = converterLookup.lookupConverter(dynamicMetaDataMapping.getConverterName());
if (!(converter instanceof DynamicConverter)) {
throw new MappingException("Dynamic meta-data [" + dynamicMetaDataMapping + "] converter name [" +
dynamicMetaDataMapping.getConverterName() + "] is not a dynamic converter");
}
DynamicConverter dynamicConverter = ((DynamicConverter) converter).copy();
dynamicConverter.setType(dynamicMetaDataMapping.getType());
dynamicConverter.setExpression(dynamicMetaDataMapping.getExpression());
if (dynamicMetaDataMapping.getFormat() != null) {
converter = converterLookup.lookupConverter(dynamicMetaDataMapping.getType());
if (!(converter instanceof FormatConverter)) {
throw new MappingException("Dynamic meta data [" + dynamicMetaDataMapping.getName() +
"] type [" + dynamicMetaDataMapping.getType().getName() + "] is not a formattable type");
}
FormatConverter formatConverter = ((FormatConverter) converter).copy();
formatConverter.setFormat(dynamicMetaDataMapping.getFormat());
dynamicConverter.setFormatConverter(formatConverter);
}
dynamicMetaDataMapping.setConverter(dynamicConverter);
}
/**
* Called for any resource property mapping type (for example, {@link ClassPropertyMetaDataMapping}
* and {@link ConstantMetaDataMapping}.
*
* @param resourcePropertyMapping The mapping of the callback
*/
public void onResourcePropertyMapping(ResourcePropertyMapping resourcePropertyMapping) {
// we do it here as well as later in the processing since with OSEM, the index, for example,
// is important to be resolved as fast as possible
MappingProcessorUtils.applyResourcePropertySettings(resourcePropertyMapping, settings);
}
}
}