/**
* 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.windows;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import org.datacleaner.descriptors.ConfiguredPropertyDescriptor;
import org.datacleaner.job.builder.AnalysisJobBuilder;
import org.datacleaner.job.builder.ComponentBuilder;
import org.datacleaner.reference.Dictionary;
import org.datacleaner.reference.ReferenceData;
import org.datacleaner.reference.StringPattern;
import org.datacleaner.reference.SynonymCatalog;
import org.datacleaner.user.ReferenceDataChangeListener;
/**
* It contains all the listeners for ReferenceData type used in
* {@link AnalysisJobBuilderWindowImpl}
*/
public class ReferenceDataAnalysisJobWindowImplListeners {
class WindowChangeSynonymCatalogListener implements ReferenceDataChangeListener<SynonymCatalog> {
@Override
public void onAdd(final SynonymCatalog referenceData) {
// DO NOTHING (because we do not want to automatically select the
// reference data to be used in the job)
}
@Override
public void onChange(final SynonymCatalog oldReferenceData, final SynonymCatalog newReferenceData) {
changeReferenceDataValuesInComponents(oldReferenceData, newReferenceData, SynonymCatalog.class);
}
@Override
public void onRemove(final SynonymCatalog referenceData) {
removeReferenceDataValuesInComponents(referenceData, SynonymCatalog.class);
}
}
class WindowChangeDictionaryListener implements ReferenceDataChangeListener<Dictionary> {
@Override
public void onAdd(final Dictionary referenceData) {
// DO NOTHING (because we do not want to automatically select the
// reference data to be used in the job)
}
@Override
public void onChange(final Dictionary oldReferenceData, final Dictionary newReferenceData) {
changeReferenceDataValuesInComponents(oldReferenceData, newReferenceData, Dictionary.class);
}
@Override
public void onRemove(final Dictionary referenceData) {
removeReferenceDataValuesInComponents(referenceData, Dictionary.class);
}
}
class WindowChangeStringPatternListener implements ReferenceDataChangeListener<StringPattern> {
@Override
public void onAdd(final StringPattern referenceData) {
// DO NOTHING (because we do not want to automatically select the
// reference data to be used in the job)
}
@Override
public void onChange(final StringPattern oldReferenceData, final StringPattern newReferenceData) {
changeReferenceDataValuesInComponents(oldReferenceData, newReferenceData, StringPattern.class);
}
@Override
public void onRemove(final StringPattern referenceData) {
removeReferenceDataValuesInComponents(referenceData, StringPattern.class);
}
}
private final AnalysisJobBuilder _analysisJobBuilder;
ReferenceDataAnalysisJobWindowImplListeners(final AnalysisJobBuilder analysisJobBuilder) {
_analysisJobBuilder = analysisJobBuilder;
}
/**
* Method used to change the reference data(String Patterns, Dictionaries,
* Synonyms) components' values in components
*
* @param oldReferenceData
* @param newReferenceData
* @param referenceDataClass
*/
private void changeReferenceDataValuesInComponents(final ReferenceData oldReferenceData,
final ReferenceData newReferenceData, final Class<?> referenceDataClass) {
final Collection<ComponentBuilder> componentBuilders = _analysisJobBuilder.getComponentBuilders();
for (final ComponentBuilder componentBuilder : componentBuilders) {
final Map<ConfiguredPropertyDescriptor, Object> configuredProperties =
componentBuilder.getConfiguredProperties();
for (final Map.Entry<ConfiguredPropertyDescriptor, Object> entry : configuredProperties.entrySet()) {
final ConfiguredPropertyDescriptor propertyDescriptor = entry.getKey();
if (referenceDataClass.isAssignableFrom(propertyDescriptor.getBaseType())) {
final Object valueObject = entry.getValue();
// In some cases the configured property is an array
if (valueObject.getClass().isArray()) {
final Object[] values = (Object[]) valueObject;
for (int i = 0; i < values.length; i++) {
if (oldReferenceData.equals(values[i])) {
// change the old value of the pattern in the
// array with the new value
values[i] = newReferenceData;
}
}
} else {
if (oldReferenceData.equals(valueObject)) {
componentBuilder.setConfiguredProperty(propertyDescriptor, newReferenceData);
}
}
}
}
}
}
/**
* Method used to remove the reference data(String Patterns, Dictionaries,
* Synonyms) components' values in components
*
* @param referenceData
* @param referenceDataClass
*/
private void removeReferenceDataValuesInComponents(final ReferenceData referenceData,
final Class<?> referenceDataClass) {
final Collection<ComponentBuilder> componentBuilders = _analysisJobBuilder.getComponentBuilders();
for (final ComponentBuilder componentBuilder : componentBuilders) {
final Map<ConfiguredPropertyDescriptor, Object> configuredProperties =
componentBuilder.getConfiguredProperties();
for (final Map.Entry<ConfiguredPropertyDescriptor, Object> entry : configuredProperties.entrySet()) {
final ConfiguredPropertyDescriptor propertyDescriptor = entry.getKey();
if (referenceDataClass.isAssignableFrom(propertyDescriptor.getBaseType())) {
final Object valueObject = entry.getValue();
// In some cases the configured property is an array
if (valueObject.getClass().isArray()) {
final Object[] values = (Object[]) valueObject;
final Class<?> componentType = valueObject.getClass().getComponentType();
// create the new array
final Object[] newArray = (Object[]) Array.newInstance(componentType, values.length - 1);
int j = 0;
for (int i = 0; i < values.length; i++) {
if (!referenceData.equals(values[i])) {
// keep only the values different than the one select to be removed
newArray[j] = values[i];
j++;
}
}
componentBuilder.setConfiguredProperty(propertyDescriptor, newArray);
} else {
if (referenceData.equals(valueObject)) {
componentBuilder.setConfiguredProperty(propertyDescriptor, null);
}
}
}
}
}
}
}