use of eu.esdihumboldt.hale.common.align.model.transformation.tree.impl.CellNodeImpl in project hale by halestudio.
the class TargetContext method duplicateTree.
/**
* Duplicates the transformation tree for the given source node to the given
* duplicate source node.
*
* @param source the original source node
* @param duplicate the duplication target
* @param info the duplication info object
* @param log the transformation log
* @param serviceProvider service provider for resolving functions
*/
private static void duplicateTree(SourceNode source, SourceNode duplicate, DuplicationInformation info, TransformationLog log, ServiceProvider serviceProvider) {
// Duplicate relations.
for (CellNode cell : source.getRelations(false)) {
// check whether the cell is eager for the source node
if (TransformationTreeUtil.isEager(cell, source, log, serviceProvider))
continue;
// Check whether the cell is ignored.
if (info.isIgnoreCell(cell.getCell()))
continue;
// XXX prioritize already created cell nodes (in this run) over old
// nodes?
// First check whether an old cell node with a missing source
// exists.
// If so, add this source to the first so found cell.
boolean usedOld = false;
for (IdentityWrapper<CellNode> wrapper : info.getOldCellNodes(cell.getCell())) {
CellNode oldCellNode = wrapper.getValue();
// Skip the cell if it's full.
if (oldCellNode.getSources().size() == cell.getSources().size())
continue;
// Check whether out duplicate source node is missing...
if (!oldCellNode.getSources().contains(duplicate)) {
usedOld = true;
// Has to be a cell created with the cell constructor.
((CellNodeImpl) oldCellNode).addSource(cell.getSourceNames(source), duplicate);
duplicate.addRelation(oldCellNode);
break;
}
}
// If no old cell was used, use a newly created one / create one.
if (!usedOld) {
CellNodeImpl duplicatedCell = info.getNewCellNode(cell.getCell());
if (duplicatedCell == null) {
// Create a new cell, augment it with existing sources, add
// it to info and duplicate targets.
duplicatedCell = new CellNodeImpl(cell.getCell());
augmentCell(cell, duplicatedCell, info);
info.addNewCellNode(cell.getCell(), duplicatedCell);
duplicateTree(cell, duplicatedCell, info, log);
}
// Add as relation/source.
duplicate.addRelation(duplicatedCell);
duplicatedCell.addSource(cell.getSourceNames(source), duplicate);
}
}
// Duplicate children.
for (SourceNode child : source.getChildren(false)) {
SourceNode duplicatedChild = new SourceNodeImpl(child.getEntityDefinition(), duplicate, true);
duplicatedChild.setContext(child.getContext());
duplicateTree(child, duplicatedChild, info, log, serviceProvider);
}
}
use of eu.esdihumboldt.hale.common.align.model.transformation.tree.impl.CellNodeImpl in project hale by halestudio.
the class TargetContext method duplicateCell.
/**
* Get the duplicated cell node.
*
* @param relation the original cell node
* @param duplicateSource the duplicated source node to be associated with
* the duplicated cell node, may be <code>null</code> if the cell
* is an augmentation
* @param duplicationContext the context of the current duplication process
* @return the duplicated cell node or <code>null</code> if duplication was
* prohibited
*/
private CellNode duplicateCell(CellNode relation, SourceNode duplicateSource, DuplicationContext duplicationContext) {
if (duplicationContext.getIgnoreCells().contains(relation.getCell())) {
// already handled)
return null;
}
// try to retrieve cell node from context
CellNodeImpl duplicate = duplicationContext.getNode(relation.getCell());
if (duplicate == null) {
// if not already done, create a duplicate of the cell
duplicate = new CellNodeImpl(relation.getCell());
// duplicate the target nodes as necessary
List<TargetNode> targets = new ArrayList<TargetNode>(relation.getTargets().size());
for (TargetNode target : relation.getTargets()) {
TargetNode duplicatedTarget = duplicateTarget(target, duplicate, duplicationContext);
if (duplicatedTarget != null) {
targets.add(duplicatedTarget);
}
}
if (targets.isEmpty()) {
// exit if there are no targets nodes
return null;
// FIXME if a cell has different associated sources the cell
// node will be repeatedly created and discarded
}
// add duplicated targets to duplicated cell
for (TargetNode target : targets) {
duplicate.addTarget(target);
}
// store duplicate in duplication context
duplicationContext.addNode(duplicate, relation);
}
// add the duplicated source
if (duplicateSource != null) {
duplicate.addSource(relation.getSourceNames(duplicateSource), duplicateSource);
}
return duplicate;
}
use of eu.esdihumboldt.hale.common.align.model.transformation.tree.impl.CellNodeImpl in project hale by halestudio.
the class TargetContext method augmentationTrackback.
/**
* Track back target nodes and duplicate any augmentation cells.
*
* @param tree the tree to work on
*/
public static void augmentationTrackback(TransformationTree tree) {
final Map<EntityDefinition, TargetNode> targetNodesWithAugmentations = new HashMap<EntityDefinition, TargetNode>();
// Search for original target nodes
tree.accept(new AbstractTargetToSourceVisitor() {
Deque<Boolean> hasAugmentation = new ArrayDeque<Boolean>();
/**
* @see eu.esdihumboldt.hale.common.align.model.transformation.tree.visitor.AbstractTransformationNodeVisitor#visit(eu.esdihumboldt.hale.common.align.model.transformation.tree.CellNode)
*/
@Override
public boolean visit(CellNode cell) {
// hasAugmentation to true.
if (cell.getSources().isEmpty()) {
if (!hasAugmentation.getLast()) {
hasAugmentation.pop();
hasAugmentation.push(true);
}
}
return false;
}
/**
* @see eu.esdihumboldt.hale.common.align.model.transformation.tree.visitor.AbstractTransformationNodeVisitor#visit(eu.esdihumboldt.hale.common.align.model.transformation.tree.TargetNode)
*/
@Override
public boolean visit(TargetNode target) {
// Simply add a new level to hasAugmentation starting with
// false.
hasAugmentation.push(false);
return true;
}
/**
* @see eu.esdihumboldt.hale.common.align.model.transformation.tree.visitor.AbstractTransformationNodeVisitor#leave(eu.esdihumboldt.hale.common.align.model.transformation.tree.TargetNode)
*/
@Override
public void leave(TargetNode target) {
// If this nodes level in hasAugmentation is true...
if (hasAugmentation.pop()) {
// ... add it to targetNodesWithAugmentations and set
// parents level to true, too.
targetNodesWithAugmentations.put(target.getEntityDefinition(), target);
if (!hasAugmentation.isEmpty() && !hasAugmentation.getLast()) {
hasAugmentation.pop();
hasAugmentation.push(true);
}
}
}
/**
* @see eu.esdihumboldt.hale.common.align.model.transformation.tree.TransformationNodeVisitor#includeAnnotatedNodes()
*/
@Override
public boolean includeAnnotatedNodes() {
// Only look for original target nodes.
return false;
}
});
// Add augmentations to all target nodes (no copied target node got them
// yet)
tree.accept(new AbstractTargetToSourceVisitor() {
/**
* @see eu.esdihumboldt.hale.common.align.model.transformation.tree.visitor.AbstractTransformationNodeVisitor#visit(eu.esdihumboldt.hale.common.align.model.transformation.tree.CellNode)
*/
@Override
public boolean visit(CellNode cell) {
return false;
}
/**
* @see eu.esdihumboldt.hale.common.align.model.transformation.tree.visitor.AbstractTransformationNodeVisitor#visit(eu.esdihumboldt.hale.common.align.model.transformation.tree.TargetNode)
*/
@Override
public boolean visit(TargetNode target) {
// TODO more intelligent behavior of when NOT to create the
// augmentation.
// For example if the augmentation belongs to a complex
// structure that can
// occur 0..n times, it should not be created for the first time
// due to an
// augmentation.
TargetNode originalTarget = targetNodesWithAugmentations.get(target.getEntityDefinition());
// Only have to do something if the node is present in the map.
if (originalTarget != null && originalTarget != target) {
// sources are missing).
for (CellNode originalAssignment : originalTarget.getAssignments()) {
if (originalAssignment.getSources().isEmpty()) {
CellNodeImpl duplicatedAssignment = new CellNodeImpl(originalAssignment.getCell());
duplicatedAssignment.addTarget(target);
((TargetNodeImpl) target).addAssignment(originalTarget.getAssignmentNames(originalAssignment), duplicatedAssignment);
}
}
// Check for missing children.
for (TargetNode child : originalTarget.getChildren(false)) {
// Only add missing children that need an augmentation.
if (targetNodesWithAugmentations.containsKey(child.getEntityDefinition()) && !target.getChildren(false).contains(child)) {
TargetNodeImpl duplicatedChild = new TargetNodeImpl(child.getEntityDefinition(), target);
((TargetNodeImpl) target).addChild(duplicatedChild);
// The child will be handled by this visior later.
}
}
return true;
} else
return false;
}
@Override
public boolean includeAnnotatedNodes() {
return true;
}
});
}
Aggregations