/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.core.transformer.graph;
import org.mule.runtime.api.metadata.DataType;
import org.mule.runtime.core.api.registry.ResolverException;
import org.mule.runtime.core.api.registry.TransformerResolver;
import org.mule.runtime.core.api.transformer.Converter;
import org.mule.runtime.core.api.transformer.Transformer;
import org.mule.runtime.core.config.i18n.CoreMessages;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.commons.collections.map.LRUMap;
public class GraphTransformerResolver implements TransformerResolver {
private ReentrantReadWriteLock readWriteLock;
private TransformationGraph graph;
private CompositeConverterFilter converterFilter;
private LRUMap cache;
private TransformationGraphLookupStrategy lookupStrategyTransformation;
public GraphTransformerResolver() {
this.readWriteLock = new ReentrantReadWriteLock();
this.graph = new TransformationGraph();
lookupStrategyTransformation = new TransformationGraphLookupStrategy(graph);
converterFilter = new CompositeConverterFilter(new TransformationLengthConverterFilter(),
new PriorityWeightingConverterFilter(), new NameConverterFilter());
cache = new LRUMap();
}
@Override
public Transformer resolve(DataType source, DataType result) throws ResolverException {
String cacheKey = getDataTypeSourceResultPairHash(source, result);
readWriteLock.readLock().lock();
try {
if (cache.containsKey(cacheKey)) {
return (Converter) cache.get(cacheKey);
}
} finally {
readWriteLock.readLock().unlock();
}
List<Converter> converters =
converterFilter.filter(lookupStrategyTransformation.lookupConverters(source, result), source, result);
if (converters.size() > 1) {
throw new ResolverException(CoreMessages.transformHasMultipleMatches(source.getType(), result.getType(), converters));
}
Transformer converter = (converters.size() == 0) ? null : converters.get(0);
readWriteLock.writeLock().lock();
try {
cache.put(cacheKey, converter);
} finally {
readWriteLock.writeLock().unlock();
}
return converter;
}
private String getDataTypeSourceResultPairHash(DataType source, DataType result) {
StringBuilder builder = new StringBuilder();
builder.append(source.getClass().getName());
builder.append(source.hashCode());
builder.append(":");
builder.append(result.getClass().getName());
builder.append(result.hashCode());
return builder.toString();
}
@Override
public void transformerChange(Transformer transformer, RegistryAction registryAction) {
readWriteLock.writeLock().lock();
try {
if (!(transformer instanceof Converter)) {
return;
}
cache.clear();
if (registryAction == RegistryAction.ADDED) {
graph.addConverter((Converter) transformer);
} else if (registryAction == RegistryAction.REMOVED) {
graph.removeConverter((Converter) transformer);
}
} finally {
readWriteLock.writeLock().unlock();
}
}
}