org.datacleaner.guice.DCModuleImpl Maven / Gradle / Ivy
/**
* DataCleaner (community edition)
* 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.datacleaner.guice;
import java.io.File;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.metamodel.util.Action;
import org.apache.metamodel.util.ImmutableRef;
import org.apache.metamodel.util.LazyRef;
import org.apache.metamodel.util.MutableRef;
import org.apache.metamodel.util.Ref;
import org.datacleaner.bootstrap.DCWindowContext;
import org.datacleaner.bootstrap.WindowContext;
import org.datacleaner.configuration.DataCleanerConfiguration;
import org.datacleaner.configuration.DataCleanerConfigurationImpl;
import org.datacleaner.configuration.DataCleanerEnvironment;
import org.datacleaner.configuration.DataCleanerEnvironmentImpl;
import org.datacleaner.configuration.DataCleanerHomeFolder;
import org.datacleaner.configuration.DatastoreXmlExternalizer;
import org.datacleaner.configuration.InjectionManager;
import org.datacleaner.configuration.InjectionManagerFactory;
import org.datacleaner.connection.DatastoreCatalog;
import org.datacleaner.descriptors.ConfiguredPropertyDescriptor;
import org.datacleaner.descriptors.DescriptorProvider;
import org.datacleaner.descriptors.PropertyDescriptor;
import org.datacleaner.extensions.ExtensionPackage;
import org.datacleaner.extensions.ExtensionReader;
import org.datacleaner.job.AnalysisJob;
import org.datacleaner.job.builder.AnalysisJobBuilder;
import org.datacleaner.job.builder.ComponentBuilder;
import org.datacleaner.job.concurrent.TaskRunner;
import org.datacleaner.lifecycle.LifeCycleHelper;
import org.datacleaner.reference.ReferenceDataCatalog;
import org.datacleaner.result.AnalysisResult;
import org.datacleaner.result.renderer.RendererFactory;
import org.datacleaner.storage.StorageProvider;
import org.datacleaner.user.DataCleanerConfigurationReader;
import org.datacleaner.user.DataCleanerHome;
import org.datacleaner.user.MutableDatastoreCatalog;
import org.datacleaner.user.MutableReferenceDataCatalog;
import org.datacleaner.user.UsageLogger;
import org.datacleaner.user.UserPreferences;
import org.datacleaner.user.UserPreferencesImpl;
import org.datacleaner.util.SystemProperties;
import org.datacleaner.util.VFSUtils;
import org.datacleaner.util.VfsResource;
import org.datacleaner.util.convert.ClasspathResourceTypeHandler;
import org.datacleaner.util.convert.DummyRepositoryResourceFileTypeHandler;
import org.datacleaner.util.convert.FileResourceTypeHandler;
import org.datacleaner.util.convert.HdfsResourceTypeHandler;
import org.datacleaner.util.convert.ResourceConverter;
import org.datacleaner.util.convert.ResourceConverter.ResourceTypeHandler;
import org.datacleaner.util.convert.UrlResourceTypeHandler;
import org.datacleaner.util.convert.VfsResourceTypeHandler;
import org.datacleaner.windows.AnalysisJobBuilderWindow;
import org.datacleaner.windows.AnalysisJobBuilderWindowImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.util.Modules;
/**
* Google Guice module for DataCleaner. Defines the main contextual components
* of a DataCleaner session.
*/
public class DCModuleImpl extends AbstractModule implements DCModule {
private static final Logger logger = LoggerFactory.getLogger(DCModuleImpl.class);
private final DataCleanerConfigurationReader _undecoratedConfigurationRef;
private final Ref _userPreferencesRef;
private final Ref _analysisJobBuilderRef;
private DataCleanerConfiguration _configuration;
private WindowContext _windowContext;
/**
* Creates a DCModule based on a parent module. This constructor is
* convenient when you want to create a module with overridden getter
* methods.
*
* @param parent
* @param analysisJobBuilder
* the AnalysisJobBuilder to use within this module, or null if a
* new AnalysisJobBuilder should be created.
*/
public DCModuleImpl(DCModule parent, final AnalysisJobBuilder analysisJobBuilder) {
final DCModuleImpl p = (DCModuleImpl) parent;
_undecoratedConfigurationRef = p._undecoratedConfigurationRef;
_userPreferencesRef = p._userPreferencesRef;
_configuration = p._configuration;
_windowContext = p._windowContext;
if (analysisJobBuilder == null) {
_analysisJobBuilderRef = new MutableRef();
} else {
_analysisJobBuilderRef = ImmutableRef.of(analysisJobBuilder);
}
}
public DCModuleImpl() {
this(defaultDataCleanerHome());
}
private static FileObject defaultDataCleanerHome() {
try {
return VFSUtils.getFileSystemManager().resolveFile(".");
} catch (FileSystemException e) {
throw new IllegalStateException(e);
}
}
public DCModuleImpl(final FileObject dataCleanerHome) {
this(dataCleanerHome, null);
}
/**
* Constructs a new DCModule based only on a DataCleaner home directory. New
* window contexts and analysis job builder will be created. Thus this
* constructor should only be used to create a completely new environment
* (at bootstrap time).
*
* @param dataCleanerHome
* @param configurationFile
* a configuration file override, or null if not requested
*/
public DCModuleImpl(final FileObject dataCleanerHome, FileObject configurationFile) {
_userPreferencesRef = createUserPreferencesRef(dataCleanerHome);
_undecoratedConfigurationRef = new DataCleanerConfigurationReader(dataCleanerHome, configurationFile,
_userPreferencesRef);
_analysisJobBuilderRef = new MutableRef();
_configuration = null;
_windowContext = null;
}
private final Ref createUserPreferencesRef(final FileObject dataCleanerHome) {
try {
if ("true".equalsIgnoreCase(System.getProperty(SystemProperties.SANDBOX))) {
return new ImmutableRef(new UserPreferencesImpl(null));
}
if (dataCleanerHome == null || !dataCleanerHome.exists()) {
logger.info("DataCleaner home was not set or does not exist. Non-persistent user preferences will be applied.");
return new ImmutableRef(new UserPreferencesImpl(null));
}
final FileObject userPreferencesFile = dataCleanerHome.resolveFile(UserPreferencesImpl.DEFAULT_FILENAME);
return new LazyRef() {
@Override
protected UserPreferences fetch() {
return UserPreferencesImpl.load(userPreferencesFile, true);
}
};
} catch (FileSystemException e) {
throw new IllegalStateException("Not able to resolve files in DataCleaner home: " + dataCleanerHome, e);
}
}
@Override
protected void configure() {
bind(AnalysisJobBuilderWindow.class).to(AnalysisJobBuilderWindowImpl.class);
bind(InjectionManagerFactory.class).to(GuiceInjectionManagerFactory.class);
bind(DCModule.class).toInstance(this);
}
@Provides
public final WindowContext getWindowContext(DataCleanerConfiguration configuration,
UserPreferences userPreferences, UsageLogger usageLogger) {
if (_windowContext == null) {
synchronized (DCModuleImpl.class) {
if (_windowContext == null) {
_windowContext = new DCWindowContext(configuration, userPreferences, usageLogger);
}
}
}
return _windowContext;
}
@Provides
public final DataCleanerEnvironment getDataCleanerEnvironment(DataCleanerConfiguration conf) {
return conf.getEnvironment();
}
@Provides
public final TaskRunner getTaskRunner(DataCleanerEnvironment environment) {
return environment.getTaskRunner();
}
@Provides
public final DescriptorProvider getDescriptorProvider(DataCleanerEnvironment environment) {
return environment.getDescriptorProvider();
}
@Provides
public final ReferenceDataCatalog getReferenceDataCatalog(DataCleanerConfiguration conf) {
return conf.getReferenceDataCatalog();
}
@Provides
public final InjectionManager getInjectionManager(InjectionManagerFactory injectionManagerFactory,
DataCleanerConfiguration configuration, @Nullable AnalysisJob job) {
return injectionManagerFactory.getInjectionManager(configuration, job);
}
@Provides
public final LifeCycleHelper getLifeCycleHelper(InjectionManager injectionManager) {
return new LifeCycleHelper(injectionManager, true);
}
@Provides
public final DatastoreCatalog getDatastoreCatalog(DataCleanerConfiguration conf) {
return conf.getDatastoreCatalog();
}
@Provides
public final MutableReferenceDataCatalog getMutableReferenceDataCatalog(ReferenceDataCatalog referenceDataCatalog) {
return (MutableReferenceDataCatalog) referenceDataCatalog;
}
@Provides
public final MutableDatastoreCatalog getMutableDatastoreCatalog(DatastoreCatalog datastoreCatalog) {
return (MutableDatastoreCatalog) datastoreCatalog;
}
@Provides
@Undecorated
public final DataCleanerConfiguration getUndecoratedAnalyzerBeansConfiguration() {
return _undecoratedConfigurationRef.get();
}
@Deprecated
@Provides
public final org.datacleaner.configuration.AnalyzerBeansConfiguration getAnalyzerBeansConfiguration(
@Undecorated DataCleanerConfiguration undecoratedConfiguration, UserPreferences userPreferences,
InjectionManagerFactory injectionManagerFactory) {
final DataCleanerConfiguration c = getDataCleanerConfiguration(undecoratedConfiguration, userPreferences,
injectionManagerFactory);
final DatastoreCatalog datastoreCatalog = c.getDatastoreCatalog();
final ReferenceDataCatalog referenceDataCatalog = c.getReferenceDataCatalog();
final DescriptorProvider descriptorProvider = c.getEnvironment().getDescriptorProvider();
final TaskRunner taskRunner = c.getEnvironment().getTaskRunner();
final StorageProvider storageProvider = c.getEnvironment().getStorageProvider();
final DataCleanerHomeFolder homeFolder = c.getHomeFolder();
return new org.datacleaner.configuration.AnalyzerBeansConfigurationImpl(datastoreCatalog, referenceDataCatalog,
descriptorProvider, taskRunner, storageProvider, injectionManagerFactory, homeFolder);
}
@Provides
public final DataCleanerConfiguration getDataCleanerConfiguration(@Undecorated DataCleanerConfiguration c,
UserPreferences userPreferences, InjectionManagerFactory injectionManagerFactory) {
if (_configuration == null) {
synchronized (DCModuleImpl.class) {
if (_configuration == null) {
// make the configuration mutable
final MutableDatastoreCatalog datastoreCatalog = new MutableDatastoreCatalog(
c.getDatastoreCatalog(), createDatastoreXmlExternalizer(), userPreferences);
final MutableReferenceDataCatalog referenceDataCatalog = new MutableReferenceDataCatalog(
c.getReferenceDataCatalog(), userPreferences, new LifeCycleHelper(
injectionManagerFactory.getInjectionManager(c, null), true));
final DescriptorProvider descriptorProvider = c.getEnvironment().getDescriptorProvider();
final ExtensionReader extensionReader = new ExtensionReader();
final List internalExtensions = extensionReader.getInternalExtensions();
for (ExtensionPackage extensionPackage : internalExtensions) {
extensionPackage.loadDescriptors(descriptorProvider);
}
final List extensionPackages = userPreferences.getExtensionPackages();
for (ExtensionPackage extensionPackage : extensionPackages) {
extensionPackage.loadDescriptors(descriptorProvider);
}
final StorageProvider storageProvider = c.getEnvironment().getStorageProvider();
final TaskRunner taskRunner = c.getEnvironment().getTaskRunner();
final DataCleanerEnvironment environment = new DataCleanerEnvironmentImpl(taskRunner,
descriptorProvider, storageProvider, injectionManagerFactory);
_configuration = new DataCleanerConfigurationImpl(environment,
DataCleanerHome.getAsDataCleanerHomeFolder(), datastoreCatalog, referenceDataCatalog);
}
}
}
if (_configuration instanceof DataCleanerConfigurationImpl) {
final DataCleanerEnvironment environment = _configuration.getEnvironment();
if (environment.getInjectionManagerFactory() != injectionManagerFactory) {
// Ticket #905 and #925: Always replace the injection manager
// factory to ensure correct scope when doing injections.
final DataCleanerEnvironment replacementEnvironment = new DataCleanerEnvironmentImpl(environment)
.withInjectionManagerFactory(injectionManagerFactory);
return ((DataCleanerConfigurationImpl) _configuration).withEnvironment(replacementEnvironment);
}
}
return _configuration;
}
private DatastoreXmlExternalizer createDatastoreXmlExternalizer() {
final FileObject configurationFile = _undecoratedConfigurationRef.getConfigurationFile();
if (configurationFile == null) {
return new DatastoreXmlExternalizer();
}
final VfsResource resource = new VfsResource(configurationFile);
return new DatastoreXmlExternalizer(resource) {
@Override
protected void onDocumentChanged(final Document document) {
resource.write(new Action() {
@Override
public void run(final OutputStream out) throws Exception {
final Source source = new DOMSource(document);
final Result outputTarget = new StreamResult(out);
final TransformerFactory transformerFactory = TransformerFactory.newInstance();
final Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(source, outputTarget);
}
});
}
};
}
@Provides
public AnalysisJob getAnalysisJob(@Nullable AnalysisJobBuilder builder) {
if (builder == null) {
return null;
}
return builder.toAnalysisJob(false);
}
@Provides
public final RendererFactory getRendererFactory(DataCleanerConfiguration configuration) {
return new RendererFactory(configuration);
}
@Provides
public AnalysisJobBuilder getAnalysisJobBuilder(DataCleanerConfiguration configuration) {
AnalysisJobBuilder ajb = _analysisJobBuilderRef.get();
if (ajb == null && _analysisJobBuilderRef instanceof MutableRef) {
ajb = new AnalysisJobBuilder(configuration);
MutableRef ref = (MutableRef) _analysisJobBuilderRef;
ref.set(ajb);
}
return ajb;
}
@Provides
@JobFile
public FileObject getJobFilename() {
return null;
}
@Provides
public final DCModuleImpl getModule() {
return this;
}
@Provides
public AnalysisResult getAnalysisResult() {
return null;
}
@Provides
public final UserPreferences getUserPreferences() {
return _userPreferencesRef.get();
}
@Provides
public CloseableHttpClient getHttpClient(UserPreferences userPreferences) {
return userPreferences.createHttpClient();
}
@Provides
public ResourceConverter getResourceConverter() {
final FileObject dataCleanerHome = DataCleanerHome.get();
final File dataCleanerHomeDirectory = VFSUtils.toFile(dataCleanerHome);
final List> handlers = new ArrayList>();
handlers.add(new FileResourceTypeHandler(dataCleanerHomeDirectory));
handlers.add(new UrlResourceTypeHandler());
handlers.add(new ClasspathResourceTypeHandler());
handlers.add(new VfsResourceTypeHandler());
handlers.add(new HdfsResourceTypeHandler());
handlers.add(new DummyRepositoryResourceFileTypeHandler());
final ResourceConverter resourceConverter = new ResourceConverter(handlers,
ResourceConverter.DEFAULT_DEFAULT_SCHEME);
return resourceConverter;
}
@Override
public InjectorBuilder createInjectorBuilder() {
return new InjectorBuilder(this, Guice.createInjector(this));
}
@Override
public Injector createChildInjectorForComponent(ComponentBuilder componentBuilder) {
final ComponentBuilderModule componentBuilderModule = new ComponentBuilderModule(componentBuilder);
final Module module = Modules.override(this).with(componentBuilderModule);
return Guice.createInjector(module);
}
@Override
public Injector createChildInjectorForProperty(ComponentBuilder componentBuilder,
ConfiguredPropertyDescriptor propertyDescriptor) {
final AdHocModule adHocModule = new AdHocModule();
adHocModule.bind(PropertyDescriptor.class, propertyDescriptor);
adHocModule.bind(ConfiguredPropertyDescriptor.class, propertyDescriptor);
final ComponentBuilderModule componentBuilderModule = new ComponentBuilderModule(componentBuilder);
final Module module = Modules.override(this).with(componentBuilderModule, adHocModule);
return Guice.createInjector(module);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy