/** * 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.lifecycle; import java.util.Set; import org.datacleaner.api.Configured; import org.datacleaner.api.Initialize; import org.datacleaner.api.Provided; import org.datacleaner.api.Validate; import org.datacleaner.configuration.DataCleanerConfiguration; import org.datacleaner.configuration.InjectionManager; import org.datacleaner.configuration.InjectionManagerFactory; import org.datacleaner.configuration.InjectionPoint; import org.datacleaner.descriptors.CloseMethodDescriptor; import org.datacleaner.descriptors.ComponentDescriptor; import org.datacleaner.descriptors.InitializeMethodDescriptor; import org.datacleaner.descriptors.ProvidedPropertyDescriptor; import org.datacleaner.descriptors.ValidateMethodDescriptor; import org.datacleaner.job.AnalysisJob; import org.datacleaner.job.ComponentConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utility/convenience class for doing simple lifecycle management and/or * mimicing the lifecycle of components lifecycle in a job execution. */ public final class LifeCycleHelper { private static final Logger logger = LoggerFactory.getLogger(LifeCycleHelper.class); private final InjectionManager _injectionManager; private final boolean _includeNonDistributedTasks; /** * @param injectionManager * * @deprecated use {@link #LifeCycleHelper(InjectionManager, boolean)} * instead */ @Deprecated public LifeCycleHelper(final InjectionManager injectionManager) { this(injectionManager, true); } /** * * @param injectionManager * @param referenceDataActivationManager * @param includeNonDistributedTasks * whether or not non-distributed methods (such as * {@link Initialize} or {@link Cloneable} methods that are * marked with distributed=false) should be included or not. On * single-node executions, this will typically be true, on slave * nodes in a cluster, this will typically be false. */ public LifeCycleHelper(final InjectionManager injectionManager, final boolean includeNonDistributedTasks) { _injectionManager = injectionManager; _includeNonDistributedTasks = includeNonDistributedTasks; } /** * * @param configuration * @param job * @param referenceDataActivationManager * @param includeNonDistributedTasks * whether or not non-distributed methods (such as * {@link Initialize} or {@link Cloneable} methods that are * marked with distributed=false) should be included or not. On * single-node executions, this will typically be true, on slave * nodes in a cluster, this will typically be false. */ public LifeCycleHelper(final DataCleanerConfiguration configuration, final AnalysisJob job, final boolean includeNonDistributedTasks) { if (configuration == null) { _injectionManager = null; } else { final InjectionManagerFactory injectionManagerFactory = configuration.getEnvironment().getInjectionManagerFactory(); if (job == null) { _injectionManager = injectionManagerFactory.getInjectionManager(configuration); } else { _injectionManager = injectionManagerFactory.getInjectionManager(configuration, job); } } _includeNonDistributedTasks = includeNonDistributedTasks; } public boolean isIncludeNonDistributedTasks() { return _includeNonDistributedTasks; } public InjectionManager getInjectionManager() { return _injectionManager; } /** * Assigns/injects {@link Configured} property values to a component. * * @param descriptor * @param component * @param componentConfiguration */ public void assignConfiguredProperties(final ComponentDescriptor<?> descriptor, final Object component, final ComponentConfiguration componentConfiguration) { final AssignConfiguredPropertiesHelper helper = new AssignConfiguredPropertiesHelper(); helper.assignProperties(component, descriptor, componentConfiguration); } /** * Assigns/injects {@link Provided} property values to a component. * * @param descriptor * @param component */ public void assignProvidedProperties(final ComponentDescriptor<?> descriptor, final Object component) { final Set<ProvidedPropertyDescriptor> providedDescriptors = descriptor.getProvidedProperties(); for (final ProvidedPropertyDescriptor providedDescriptor : providedDescriptors) { final InjectionPoint<Object> injectionPoint = new PropertyInjectionPoint(providedDescriptor, component); final Object value = _injectionManager.getInstance(injectionPoint); providedDescriptor.setValue(component, value); } } /** * Validates a component using any {@link Validate} methods. This is * typically done after * {@link #assignProvidedProperties(ComponentDescriptor, Object)} and * {@link #assignConfiguredProperties(ComponentDescriptor, Object, ComponentConfiguration)} * * Usually validation is light-weight, idempotent and quick, as compared to * {@link #initialize(ComponentDescriptor, Object, boolean)}. * * @param descriptor * @param component */ public void validate(final ComponentDescriptor<?> descriptor, final Object component) { final Set<ValidateMethodDescriptor> validateDescriptors = descriptor.getValidateMethods(); for (final ValidateMethodDescriptor validateDescriptor : validateDescriptors) { validateDescriptor.validate(component); } } /** * Initializes a component before use. This is typically done after * {@link #assignProvidedProperties(ComponentDescriptor, Object)} and * {@link #assignConfiguredProperties(ComponentDescriptor, Object, ComponentConfiguration)} * . * * This initialization also includes a validation, see * {@link #validate(ComponentDescriptor, Object)}. * * @param descriptor * @param component */ public void initialize(final ComponentDescriptor<?> descriptor, final Object component) { final Set<InitializeMethodDescriptor> initializeDescriptors = descriptor.getInitializeMethods(); for (final InitializeMethodDescriptor initializeDescriptor : initializeDescriptors) { if (_includeNonDistributedTasks || initializeDescriptor.isDistributed()) { initializeDescriptor.initialize(component); } } } /** * Closes a component after use. * * @param descriptor * @param component */ public void close(final ComponentDescriptor<?> descriptor, final Object component, final boolean success) { final Set<CloseMethodDescriptor> closeMethods = descriptor.getCloseMethods(); for (final CloseMethodDescriptor closeDescriptor : closeMethods) { if (_includeNonDistributedTasks || closeDescriptor.isDistributed()) { if (success && closeDescriptor.isEnabledOnSuccess()) { closeDescriptor.close(component); } else if (!success && closeDescriptor.isEnabledOnFailure()) { closeDescriptor.close(component); } else { logger.debug("Omitting close method {} since success={}", closeDescriptor, success); } } } } /** * Closes a component after user. * * @param descriptor * @param component * * @deprecated use {@link #close(ComponentDescriptor, Object, boolean)} * instead. */ @Deprecated public void close(final ComponentDescriptor<?> descriptor, final Object component) { close(descriptor, component, true); } }