/*
* Copyright (c) 2012 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.common.align.model.transformation.tree.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import eu.esdihumboldt.hale.common.align.model.Cell;
import eu.esdihumboldt.hale.common.align.model.transformation.tree.Leftovers;
import eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode;
import eu.esdihumboldt.util.Pair;
/**
* Default {@link Leftovers} implementation.
*
* @author Simon Templer
*/
public class LeftoversImpl implements Leftovers {
/**
* Pairs source nodes for left over values with the cells it has been
* consumed for. If the cell set is <code>null</code> this means a leftover
* has been consumed completely.
*/
private final List<Pair<SourceNode, Set<Cell>>> values = new ArrayList<Pair<SourceNode, Set<Cell>>>();
private final SourceNode originalSource;
private int firstNotConsumed = 0;
/**
* Constructor
*
* @param originalSource the original source node to be duplicated
* @param leftovers the left over values
*/
public LeftoversImpl(SourceNode originalSource, Object... leftovers) {
this.originalSource = originalSource;
// for each leftover create a source node duplicate
for (Object value : leftovers)
addLeftover(value, originalSource.getAnnotatedParent());
}
/**
* Adds the given value to the leftovers.
*
* @param value the leftover value
* @param annotatedParent the value for the annotated parent field of the
* duplicate nodes
*/
public void addLeftover(Object value, SourceNode annotatedParent) {
SourceNode duplicate = new SourceNodeImpl(originalSource.getEntityDefinition(),
originalSource.getParent(), false);
duplicate.setAnnotatedParent(annotatedParent);
// assign context
duplicate.setContext(originalSource.getContext());
// add as annotated child to original parent
if (originalSource.getParent() != null)
originalSource.getParent().addAnnotatedChild(duplicate);
// set the value
duplicate.setValue(value);
// XXX where should eventual children be created?
// store the leftover
values.add(new Pair<SourceNode, Set<Cell>>(duplicate, new HashSet<Cell>()));
}
/**
* @see Leftovers#consumeValue()
*/
@Override
public Pair<SourceNode, Set<Cell>> consumeValue() {
if (firstNotConsumed < values.size()) {
return unmodifiablePair(values.get(firstNotConsumed++));
}
return null;
}
private Pair<SourceNode, Set<Cell>> unmodifiablePair(Pair<SourceNode, Set<Cell>> pair) {
return new Pair<SourceNode, Set<Cell>>(pair.getFirst(), Collections.unmodifiableSet(pair
.getSecond()));
}
/**
* @see Leftovers#consumeValue(Cell)
*/
@Override
public SourceNode consumeValue(Cell cell) {
for (int i = firstNotConsumed; i < values.size(); i++) {
Pair<SourceNode, Set<Cell>> leftover = values.get(i);
Set<Cell> consumedCells = leftover.getSecond();
if (consumedCells != null && !consumedCells.contains(cell)) {
// cell has not been consumed for the node
consumedCells.add(cell);
return leftover.getFirst();
}
}
return null;
}
}