/**
* 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.job.builder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import org.eobjects.analyzer.beans.api.Filter;
import org.eobjects.analyzer.descriptors.FilterBeanDescriptor;
import org.eobjects.analyzer.job.AnalysisJobImmutabilizer;
import org.eobjects.analyzer.job.ComponentRequirement;
import org.eobjects.analyzer.job.FilterJob;
import org.eobjects.analyzer.job.FilterOutcome;
import org.eobjects.analyzer.job.HasFilterOutcomes;
import org.eobjects.analyzer.job.ImmutableBeanConfiguration;
import org.eobjects.analyzer.job.ImmutableFilterJob;
public final class FilterJobBuilder<F extends Filter<C>, C extends Enum<C>> extends
AbstractBeanWithInputColumnsBuilder<FilterBeanDescriptor<F, C>, F, FilterJobBuilder<F, C>> implements
HasFilterOutcomes {
// We keep a cached version of the resulting filter job because of
// references coming from other objects, particular LazyFilterOutcome.
private FilterJob _cachedJob;
private EnumMap<C, FilterOutcome> _outcomes;
private final List<FilterChangeListener> _localChangeListeners;
public FilterJobBuilder(AnalysisJobBuilder analysisJobBuilder, FilterBeanDescriptor<F, C> descriptor) {
super(analysisJobBuilder, descriptor, FilterJobBuilder.class);
_outcomes = new EnumMap<C, FilterOutcome>(descriptor.getOutcomeCategoryEnum());
EnumSet<C> categories = descriptor.getOutcomeCategories();
for (C category : categories) {
_outcomes.put(category, new LazyFilterOutcome(this, category));
}
_localChangeListeners = new ArrayList<FilterChangeListener>(0);
}
public FilterJob toFilterJob() {
return toFilterJob(true);
}
public FilterJob toFilterJob(AnalysisJobImmutabilizer immutabilizer) {
return toFilterJob(true, immutabilizer);
}
public FilterJob toFilterJob(final boolean validate) {
return toFilterJob(validate, new AnalysisJobImmutabilizer());
}
public FilterJob toFilterJob(final boolean validate, final AnalysisJobImmutabilizer immutabilizer) {
if (validate && !isConfigured(true)) {
throw new IllegalStateException("Filter job is not correctly configured");
}
final ComponentRequirement componentRequirement = immutabilizer.load(getComponentRequirement());
if (_cachedJob == null) {
_cachedJob = new ImmutableFilterJob(getName(), getDescriptor(), new ImmutableBeanConfiguration(
getConfiguredProperties()), componentRequirement, getMetadataProperties());
} else {
final ImmutableFilterJob newFilterJob = new ImmutableFilterJob(getName(), getDescriptor(),
new ImmutableBeanConfiguration(getConfiguredProperties()), componentRequirement, getMetadataProperties());
if (!newFilterJob.equals(_cachedJob)) {
_cachedJob = newFilterJob;
}
}
return _cachedJob;
}
/**
* Builds a temporary list of all listeners, both global and local
*
* @return
*/
private List<FilterChangeListener> getAllListeners() {
List<FilterChangeListener> globalChangeListeners = getAnalysisJobBuilder().getFilterChangeListeners();
List<FilterChangeListener> list = new ArrayList<FilterChangeListener>(globalChangeListeners.size()
+ _localChangeListeners.size());
list.addAll(globalChangeListeners);
list.addAll(_localChangeListeners);
return list;
}
@Override
public String toString() {
return "FilterJobBuilder[filter=" + getDescriptor().getDisplayName() + ",inputColumns=" + getInputColumns()
+ "]";
}
@Override
public void onConfigurationChanged() {
super.onConfigurationChanged();
List<FilterChangeListener> listeners = getAllListeners();
for (FilterChangeListener listener : listeners) {
listener.onConfigurationChanged(this);
}
}
@Override
public void onRequirementChanged() {
super.onRequirementChanged();
final List<FilterChangeListener> listeners = getAllListeners();
for (final FilterChangeListener listener : listeners) {
listener.onRequirementChanged(this);
}
}
@Override
public Collection<FilterOutcome> getFilterOutcomes() {
final Collection<FilterOutcome> outcomes = _outcomes.values();
return outcomes;
}
/**
* @deprecated use {@link #getFilterOutcome(Enum)} instead
*/
@Deprecated
public FilterOutcome getOutcome(C category) {
return getFilterOutcome(category);
}
public FilterOutcome getFilterOutcome(C category) {
final FilterOutcome outcome = _outcomes.get(category);
if (outcome == null) {
throw new IllegalArgumentException(category + " is not a valid category for " + this);
}
return outcome;
}
/**
* @deprecated use {@link #getFilterOutcome(Object)} instead
*/
@Deprecated
public FilterOutcome getOutcome(Object category) {
return getFilterOutcome(category);
}
public FilterOutcome getFilterOutcome(Object category) {
final FilterOutcome outcome = _outcomes.get(category);
if (outcome == null) {
throw new IllegalArgumentException(category + " is not a valid category for " + this);
}
return outcome;
}
/**
* Notification method invoked when transformer is removed.
*/
protected void onRemoved() {
List<FilterChangeListener> listeners = getAllListeners();
for (FilterChangeListener listener : listeners) {
listener.onRemove(this);
}
}
/**
* Adds a change listener to this component
*
* @param listener
*/
public void addChangeListener(FilterChangeListener listener) {
_localChangeListeners.add(listener);
}
/**
* Removes a change listener from this component
*
* @param listener
* @return whether or not the listener was found and removed.
*/
public boolean removeChangeListener(FilterChangeListener listener) {
return _localChangeListeners.remove(listener);
}
}