![JAR search and dependency download from the Maven repository](/logo.png)
net.projectmonkey.internal.MappingEngineImpl Maven / Gradle / Ivy
/*
* Copyright 2011 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 net.projectmonkey.internal;
import java.lang.reflect.Constructor;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.projectmonkey.Condition;
import net.projectmonkey.ConfigurationException;
import net.projectmonkey.Converter;
import net.projectmonkey.Provider;
import net.projectmonkey.TypeMap;
import net.projectmonkey.config.Configuration;
import net.projectmonkey.internal.converter.ConverterStore;
import net.projectmonkey.internal.util.Iterables;
import net.projectmonkey.internal.util.Primitives;
import net.projectmonkey.internal.util.Types;
import net.projectmonkey.spi.ConstantMapping;
import net.projectmonkey.spi.Mapping;
import net.projectmonkey.spi.MappingContext;
import net.projectmonkey.spi.MappingEngine;
import net.projectmonkey.spi.PropertyMapping;
import net.projectmonkey.spi.SourceMapping;
/**
* MappingEngine implementation that caches ConditionalConverters by source and destination type
* pairs.
*
* @author Jonathan Halterman
*/
public class MappingEngineImpl implements MappingEngine {
/** Cache of conditional converters */
private final Map, Converter, ?>> converterCache = new ConcurrentHashMap, Converter, ?>>();
private final Configuration configuration;
private final TypeMapStore typeMapStore;
private final ConverterStore converterStore;
public MappingEngineImpl(final InheritingConfiguration configuration) {
this.configuration = configuration;
this.typeMapStore = configuration.typeMapStore;
this.converterStore = configuration.converterStore;
}
/**
* Initial entry point.
*/
public D map(final S source, final Class sourceType, final D destination, final Class destinationType) {
MappingContextImpl context = new MappingContextImpl(source, sourceType,
destination, destinationType, this);
D result = null;
try {
result = map(context);
} catch (ConfigurationException e) {
throw e;
} catch (ErrorsException e) {
throw context.errors.toMappingException();
} catch (Throwable t) {
context.errors.errorMapping(sourceType, destinationType, t);
}
context.errors.throwMappingExceptionIfErrorsExist();
return result;
}
/**
* Performs mapping using a TypeMap if one exists, else a converter if one applies, else a newly
* created TypeMap. Recursive entry point.
*/
@Override
public D map(final MappingContext context) {
MappingContextImpl contextImpl = (MappingContextImpl) context;
Class destinationType = context.getDestinationType();
if (!Iterables.isIterable(destinationType) && contextImpl.currentlyMapping(destinationType))
throw contextImpl.errors.errorCircularReference(destinationType).toException();
D destination = null;
TypeMap typeMap = typeMapStore.get(context.getSourceType(), context.getDestinationType());
if (typeMap != null) {
destination = typeMap(context, typeMap);
} else {
Converter converter = converterFor(context);
if (converter != null) {
destination = convert(context, converter);
} else {
// Call getOrCreate in case TypeMap was created concurrently
typeMap = typeMapStore.getOrCreate(context.getSourceType(), context.getDestinationType(),
this);
destination = typeMap(context, typeMap);
}
}
contextImpl.finishedMapping(destinationType);
return destination;
}
/**
* Performs a type mapping for the {@code typeMap} and {@code context}.
*/
D typeMap(final MappingContext context, final TypeMap typeMap) {
MappingContextImpl contextImpl = (MappingContextImpl) context;
contextImpl.setTypeMap(typeMap);
if (context.getDestination() == null) {
D destination = createDestination(context);
if (destination == null)
return null;
}
@SuppressWarnings("unchecked")
Condition condition = (Condition) typeMap.getCondition();
Converter converter = typeMap.getConverter();
if (condition == null || condition.applies(context)) {
if (converter != null)
return convert(context, converter);
for (Mapping mapping : typeMap.getMappings()) {
propertyMap(mapping, contextImpl);
}
}
return context.getDestination();
}
@SuppressWarnings("unchecked")
private void propertyMap(final Mapping mapping, final MappingContextImpl context) {
MappingImpl mappingImpl = (MappingImpl) mapping;
if (context.isShaded(mappingImpl.getPath()))
return;
Condition
© 2015 - 2025 Weber Informatics LLC | Privacy Policy