/** * 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.panels.datastructures; import java.awt.BorderLayout; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import org.apache.metamodel.util.EqualsBuilder; import org.datacleaner.beans.datastructures.SelectFromMapTransformer; import org.datacleaner.descriptors.ConfiguredPropertyDescriptor; import org.datacleaner.job.builder.ComponentBuilder; import org.datacleaner.panels.DCPanel; import org.datacleaner.util.DCDocumentListener; import org.datacleaner.util.StringUtils; import org.datacleaner.widgets.DCComboBox; import org.datacleaner.widgets.properties.MinimalPropertyWidget; import org.datacleaner.widgets.properties.MultipleStringPropertyWidget; import org.datacleaner.widgets.properties.PropertyWidget; import org.datacleaner.widgets.properties.SingleClassPropertyWidget; import org.jdesktop.swingx.JXTextField; /** * Specialized {@link PropertyWidget} for the key/type mapping of * {@link SelectFromMapTransformer}. */ public class KeysAndTypesPropertyWidget extends MultipleStringPropertyWidget { private final ConfiguredPropertyDescriptor _typesProperty; private final List<DCComboBox<Class<?>>> _comboBoxes; @SuppressWarnings("rawtypes") private final MinimalPropertyWidget<Class[]> _typesPropertyWidget; @SuppressWarnings("rawtypes") public KeysAndTypesPropertyWidget(final ConfiguredPropertyDescriptor keysProperty, final ConfiguredPropertyDescriptor typesProperty, final ComponentBuilder componentBuilder) { super(keysProperty, componentBuilder); _comboBoxes = new ArrayList<>(); _typesProperty = typesProperty; _typesPropertyWidget = new MinimalPropertyWidget<Class[]>(getComponentBuilder(), _typesProperty) { @Override public JComponent getWidget() { return null; } @Override public Class[] getValue() { final String[] keys = KeysAndTypesPropertyWidget.this.getValue(); final List<Class<?>> result = new ArrayList<>(); for (int i = 0; i < keys.length; i++) { if (!StringUtils.isNullOrEmpty(keys[i])) { final DCComboBox<Class<?>> comboBox = _comboBoxes.get(i); result.add(comboBox.getSelectedItem()); } } return result.toArray(new Class[result.size()]); } @Override protected void setValue(Class[] value) { if (EqualsBuilder.equals(value, getValue())) { return; } if (value == null) { value = new Class[0]; } final String[] keys = KeysAndTypesPropertyWidget.this.getValue(); if (keys.length != value.length) { // disregard this invalid value update return; } for (int i = 0; i < keys.length; i++) { final DCComboBox<Class<?>> comboBox = _comboBoxes.get(i); final Class<?> selectedClass = value[i]; comboBox.setSelectedItem(selectedClass); } } @Override public boolean isSet() { if (_comboBoxes.isEmpty()) { return false; } for (final DCComboBox<Class<?>> comboBox : _comboBoxes) { if (comboBox.getSelectedItem() == null) { return false; } } return true; } }; final String[] currentKeysValue = getCurrentValue(); final Class[] currentTypesValue = (Class[]) componentBuilder.getConfiguredProperty(typesProperty); if (currentTypesValue != null) { // first create textfields, then set keys value for (int i = 0; i < currentTypesValue.length; i++) { final Class<?> type = currentTypesValue[i]; createComboBox(type); } setValue(currentKeysValue); _typesPropertyWidget.onValueTouched(currentTypesValue); } } private DCComboBox<Class<?>> createComboBox(final Class<?> type) { final DCComboBox<Class<?>> comboBox = SingleClassPropertyWidget.createClassComboBox(true); if (type != null) { comboBox.setSelectedItem(type); } _comboBoxes.add(comboBox); return comboBox; } @Override protected JComponent decorateTextField(final JXTextField textField, final int index) { final DCComboBox<Class<?>> comboBox; if (index < _comboBoxes.size()) { comboBox = _comboBoxes.get(index); } else { comboBox = createComboBox(null); } comboBox.addListener(item -> _typesPropertyWidget.fireValueChanged()); textField.getDocument().addDocumentListener(new DCDocumentListener() { @Override protected void onChange(final DocumentEvent event) { // invoke later, because document events are fired before the // textfield.getText() returns the new value SwingUtilities.invokeLater(() -> { setUpdating(true); _typesPropertyWidget.fireValueChanged(); setUpdating(false); }); } }); final DCPanel panel = new DCPanel(); panel.setLayout(new BorderLayout()); panel.add(textField, BorderLayout.CENTER); panel.add(comboBox, BorderLayout.EAST); return panel; } public PropertyWidget<?> getTypesPropertyWidget() { return _typesPropertyWidget; } @Override protected boolean isEmptyStringValid() { return false; } }