/**
* AnalyzerBeans
* Copyright (C) 2014 Neopost - Customer Information Management
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.eobjects.analyzer.configuration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.metamodel.DataContext;
import org.apache.metamodel.util.LazyRef;
import org.apache.metamodel.util.Ref;
import org.eobjects.analyzer.beans.api.OutputRowCollector;
import org.eobjects.analyzer.beans.api.Provided;
import org.eobjects.analyzer.connection.Datastore;
import org.eobjects.analyzer.connection.DatastoreCatalog;
import org.eobjects.analyzer.connection.DatastoreConnection;
import org.eobjects.analyzer.job.AnalysisJob;
import org.eobjects.analyzer.job.concurrent.TaskRunner;
import org.eobjects.analyzer.job.concurrent.ThreadLocalOutputRowCollector;
import org.eobjects.analyzer.reference.ReferenceDataCatalog;
import org.eobjects.analyzer.result.renderer.RendererFactory;
import org.eobjects.analyzer.storage.CollectionFactory;
import org.eobjects.analyzer.storage.CollectionFactoryImpl;
import org.eobjects.analyzer.storage.RowAnnotation;
import org.eobjects.analyzer.storage.RowAnnotationFactory;
import org.eobjects.analyzer.util.SchemaNavigator;
import org.eobjects.analyzer.util.convert.StringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Simple injection manager implementation, which is aware of catalogs used
* within the {@link AnalyzerBeansConfiguration}, but not anymore.
*/
public class InjectionManagerImpl implements InjectionManager {
private static final Logger logger = LoggerFactory.getLogger(InjectionManagerImpl.class);
private final AnalyzerBeansConfiguration _configuration;
private final AnalysisJob _job;
private final Ref<RowAnnotationFactory> _rowAnntationFactoryRef;
/**
* Constructs an {@link InjectionManager} for use within the scope of a job
* execution.
*
* @param configuration
* @param job
*/
public InjectionManagerImpl(AnalyzerBeansConfiguration configuration, AnalysisJob job) {
_configuration = configuration;
_job = job;
_rowAnntationFactoryRef = createRowAnnotationFactoryRef();
}
/**
* Creates a new {@link InjectionManager} without any job-context.
* Convenient for use outside of an actual job, mimicing a job situation
* etc.
*
* @param configuration
*/
public InjectionManagerImpl(AnalyzerBeansConfiguration configuration) {
this(configuration, null);
}
private Ref<RowAnnotationFactory> createRowAnnotationFactoryRef() {
return new LazyRef<RowAnnotationFactory>() {
@Override
protected RowAnnotationFactory fetch() {
logger.info("Creating RowAnnotationFactory for job: {}", _job);
RowAnnotationFactory rowAnnotationFactory = _configuration.getStorageProvider()
.createRowAnnotationFactory();
if (rowAnnotationFactory == null) {
throw new IllegalStateException("Storage provider returned null RowAnnotationFactory!");
}
return rowAnnotationFactory;
}
};
}
@SuppressWarnings("unchecked")
@Override
public final <E> E getInstance(InjectionPoint<E> injectionPoint) {
Object instance = getInstanceInternal(injectionPoint);
if (instance == null) {
logger.debug("Could not handle injection for injection point: {}", injectionPoint);
}
return (E) instance;
}
protected Object getInstanceInternal(InjectionPoint<?> injectionPoint) {
final Class<?> baseType = injectionPoint.getBaseType();
if (baseType == ReferenceDataCatalog.class) {
return _configuration.getReferenceDataCatalog();
} else if (baseType == OutputRowCollector.class) {
return new ThreadLocalOutputRowCollector();
} else if (baseType == DatastoreCatalog.class) {
return _configuration.getDatastoreCatalog();
} else if (baseType == CollectionFactory.class) {
return new CollectionFactoryImpl(_configuration.getStorageProvider());
} else if (baseType == RendererFactory.class) {
return new RendererFactory(_configuration);
} else if (baseType == RowAnnotationFactory.class) {
return _rowAnntationFactoryRef.get();
} else if (baseType == AnalyzerBeansConfiguration.class) {
return _configuration;
} else if (baseType == TaskRunner.class) {
return _configuration.getTaskRunner();
} else if (baseType == AnalysisJob.class) {
return _job;
} else if (baseType == StringConverter.class) {
// create a child injection manager (instead of using 'this') to
// ensure that any wrapping/decoration is preserved
final InjectionManager childInjectionManager = (_configuration == null ? this : _configuration
.getInjectionManager(_job));
return new StringConverter(childInjectionManager);
} else if (baseType == RowAnnotation.class) {
return _rowAnntationFactoryRef.get().createAnnotation();
} else if (baseType == Datastore.class && _job != null) {
return _job.getDatastore();
} else if (baseType == DatastoreConnection.class && _job != null) {
throw new UnsupportedOperationException(
"DatastoreConnections cannot be injected as of AnalyzerBeans 0.16. Inject a Datastore and manage a connection instead.");
} else if (baseType == DataContext.class && _job != null) {
throw new UnsupportedOperationException(
"DataContext cannot be injected as of AnalyzerBeans 0.16. Inject a Datastore and manage a connection instead.");
} else if (baseType == SchemaNavigator.class && _job != null) {
throw new UnsupportedOperationException(
"SchemaNavigator cannot be injected as of AnalyzerBeans 0.16. Inject a Datastore and manage a connection instead.");
} else {
// only inject persistent lists, sets, maps into @Provided fields.
if (injectionPoint.getAnnotation(Provided.class) != null && injectionPoint.isGenericType()) {
final Class<?> clazz1 = injectionPoint.getGenericTypeArgument(0);
if (baseType == List.class) {
List<?> list = _configuration.getStorageProvider().createList(clazz1);
return list;
} else if (baseType == Set.class) {
Set<?> set = _configuration.getStorageProvider().createSet(clazz1);
return set;
} else if (baseType == Map.class) {
Class<?> clazz2 = (Class<?>) injectionPoint.getGenericTypeArgument(1);
Map<?, ?> map = _configuration.getStorageProvider().createMap(clazz1, clazz2);
return map;
}
}
}
// unsupported injection type
return null;
}
}