/** * 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.data; import java.io.IOException; import java.io.ObjectInputStream; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.datacleaner.api.InputColumn; import org.datacleaner.api.InputRow; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Represents a row with transformed values as well as a delegate row (typically * a {@link MetaModelInputRow} delegate). */ public final class TransformedInputRow extends AbstractLegacyAwareInputRow { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(TransformedInputRow.class); private final InputRow _delegate; private final Map<InputColumn<?>, Object> _values; private final long _id; /** * Constructs a {@link TransformedInputRow} based on another row. * * @param delegate * * @deprecated use {@link TransformedInputRow#of(InputRow)} instead */ @Deprecated public TransformedInputRow(final InputRow delegate) { this(delegate, null); } /** * Constructs a {@link TransformedInputRow} based on another row and a row * ID. * * @param delegate * @param rowId */ public TransformedInputRow(final InputRow delegate, final Number rowId) { if (delegate == null) { throw new IllegalArgumentException("Delegate cannot be null"); } _delegate = delegate; if (rowId == null) { _id = delegate.getId(); } else { _id = rowId.longValue(); } _values = new LinkedHashMap<>(); } public TransformedInputRow(final InputRow delegate, final long rowId) { if (delegate == null) { throw new IllegalArgumentException("Delegate cannot be null"); } _delegate = delegate; _id = rowId; _values = new LinkedHashMap<>(); } /** * Constructs a {@link TransformedInputRow} based on another row, or returns * the row if it is already a {@link TransformedInputRow}. * * @param row * @return */ public static TransformedInputRow of(final InputRow row) { if (row instanceof TransformedInputRow) { // re-use existing transformed input row. return (TransformedInputRow) row; } else { return new TransformedInputRow(row, row.getId()); } } @Override protected String getFieldNameForNewId() { return "_id"; } @Override protected String getFieldNameForOldId() { return "_rowId"; } @Override protected Collection<String> getFieldNamesInAdditionToId() { return Arrays.asList("_delegate", "_values"); } private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException { doReadObject(stream); } @Override public long getId() { return _id; } @Override public boolean containsInputColumn(final InputColumn<?> inputColumn) { if (inputColumn.isVirtualColumn() && _values.containsKey(inputColumn)) { return true; } return _delegate.containsInputColumn(inputColumn); } public void addValue(final InputColumn<?> inputColumn, final Object value) { if (inputColumn.isPhysicalColumn()) { throw new IllegalArgumentException("Cannot add physical column values to transformed InputRow."); } _values.put(inputColumn, value); } @SuppressWarnings("unchecked") @Override public <E> E getValueInternal(final InputColumn<E> column) { if (column.isPhysicalColumn()) { logger.debug("Column is physical, delegating."); return _delegate.getValue(column); } if (_values.containsKey(column)) { return (E) _values.get(column); } return _delegate.getValue(column); } public InputRow getDelegate() { return _delegate; } @Override public List<InputColumn<?>> getInputColumns() { final List<InputColumn<?>> inputColumns = _delegate.getInputColumns(); inputColumns.addAll(_values.keySet()); return inputColumns; } public Set<InputColumn<?>> getTransformedInputColumns() { return _values.keySet(); } @Override public String toString() { return "TransformedInputRow[values=" + _values + ",delegate=" + _delegate + "]"; } }