Search in sources :

Example 6 with SourceNode

use of eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode in project hale by halestudio.

the class InstanceVisitor method visit.

/**
 * @see AbstractSourceToTargetVisitor#visit(SourceNode)
 */
@Override
public boolean visit(SourceNode source) {
    if (source.getDefinition() instanceof TypeDefinition) {
        if (instance == null)
            return false;
        // source root
        if (source.getDefinition().equals(instance.getDefinition())) {
            // check type filter (if any)
            Filter filter = source.getEntityDefinition().getFilter();
            if (filter != null && !filter.match(instance)) {
                // instance does not match filter, don't descend further
                return false;
            /*
					 * XXX What about merged instances? Will this be OK for
					 * those? A type filter should only apply to the original
					 * instance if it is merged - but most filters should
					 * evaluate the same
					 */
            } else {
                // also sets the node to defined
                source.setValue(instance);
                for (FamilyInstance child : instance.getChildren()) {
                    // Find fitting SourceNodes.
                    Collection<SourceNode> candidateNodes = tree.getRootSourceNodes(child.getDefinition());
                    if (candidateNodes.isEmpty()) {
                        /*
							 * No node found - but this may be because no
							 * property of the type is mapped, but there still
							 * might be child instances (in a Join) that have
							 * types with associated relations. To prevent those
							 * being skipped we add an artificial node
							 * representing the instance.
							 */
                        candidateNodes = new ArrayList<>();
                        EntityDefinition entityDef = new TypeEntityDefinition(child.getDefinition(), SchemaSpaceID.SOURCE, null);
                        candidateNodes.add(new SourceNodeImpl(entityDef, null, false));
                    }
                    for (SourceNode candidateNode : candidateNodes) {
                        filter = candidateNode.getEntityDefinition().getFilter();
                        if (filter == null || filter.match(child)) {
                            // XXX add to all candidates!?
                            if (candidateNode.getValue() == null) {
                                candidateNode.setAnnotatedParent(source);
                                source.addAnnotatedChild(candidateNode);
                            } else {
                                // Duplicate here, because there is no
                                // guarantee, that the Duplication
                                // Visitor will visit candidateNode after
                                // this node.
                                SourceNodeImpl duplicateNode = new SourceNodeImpl(candidateNode.getEntityDefinition(), candidateNode.getParent(), false);
                                duplicateNode.setAnnotatedParent(source);
                                source.addAnnotatedChild(duplicateNode);
                                TransformationContext context = candidateNode.getContext();
                                duplicateNode.setContext(context);
                                if (context != null) {
                                    context.duplicateContext(candidateNode, duplicateNode, Collections.<Cell>emptySet(), log);
                                } else {
                                    /*
										 * Not sure what this really means if we
										 * get here.
										 * 
										 * Best guess: Probably that we weren't
										 * able to determine how the duplication
										 * of this source can be propagted to
										 * the target. Thus the duplicated node
										 * will probably not have any
										 * connection.
										 */
                                    log.warn(log.createMessage("No transformation context for duplicated node of source " + candidateNode.getDefinition().getDisplayName(), null));
                                }
                                candidateNode = duplicateNode;
                            }
                            // run instance visitor on that annotated child
                            InstanceVisitor visitor = new InstanceVisitor(child, tree, log);
                            candidateNode.accept(visitor);
                        }
                    }
                }
                return true;
            }
        } else
            return false;
    } else {
        Object parentValue = source.getParent().getValue();
        if (parentValue == null || !(parentValue instanceof Group)) {
            source.setDefined(false);
            return false;
        } else {
            Group parentGroup = (Group) parentValue;
            Definition<?> currentDef = source.getDefinition();
            Object[] values = parentGroup.getProperty(currentDef.getName());
            if (values == null) {
                source.setDefined(false);
                return false;
            }
            // check for contexts
            EntityDefinition entityDef = source.getEntityDefinition();
            // index context
            Integer index = AlignmentUtil.getContextIndex(entityDef);
            if (index != null) {
                // only use the value at the given index, if present
                if (index < values.length) {
                    // annotate with the value at the index
                    Object value = values[index];
                    source.setValue(value);
                    return true;
                } else {
                    source.setDefined(false);
                    return false;
                }
            }
            // condition context
            Condition condition = AlignmentUtil.getContextCondition(entityDef);
            if (condition != null) {
                if (condition.getFilter() == null) {
                    // assume exclusion
                    source.setDefined(false);
                    return false;
                }
                // apply condition as filter on values and continue with
                // those values
                Collection<Object> matchedValues = new ArrayList<Object>();
                for (Object value : values) {
                    // determine parent
                    Object parent = null;
                    SourceNode parentNode = source.getParent();
                    if (parentNode != null && parentNode.isDefined()) {
                        parent = parentNode.getValue();
                    }
                    // test the condition
                    if (AlignmentUtil.matchCondition(condition, value, parent)) {
                        matchedValues.add(value);
                    }
                }
                values = matchedValues.toArray();
            }
            // default behavior (default context)
            if (values.length >= 1) {
                // annotate with the first value
                Object value = values[0];
                source.setValue(value);
                source.setAllValues(values);
            } else {
                source.setDefined(false);
                return false;
            }
            if (values.length > 1) {
                // handle additional values
                Object[] leftovers = new Object[values.length - 1];
                System.arraycopy(values, 1, leftovers, 0, leftovers.length);
                source.setLeftovers(new LeftoversImpl(source, leftovers));
            }
            return true;
        }
    }
}
Also used : Condition(eu.esdihumboldt.hale.common.align.model.Condition) Group(eu.esdihumboldt.hale.common.instance.model.Group) ArrayList(java.util.ArrayList) TransformationContext(eu.esdihumboldt.hale.common.align.model.transformation.tree.context.TransformationContext) TypeDefinition(eu.esdihumboldt.hale.common.schema.model.TypeDefinition) SourceNodeImpl(eu.esdihumboldt.hale.common.align.model.transformation.tree.impl.SourceNodeImpl) TypeEntityDefinition(eu.esdihumboldt.hale.common.align.model.impl.TypeEntityDefinition) EntityDefinition(eu.esdihumboldt.hale.common.align.model.EntityDefinition) SourceNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode) TypeEntityDefinition(eu.esdihumboldt.hale.common.align.model.impl.TypeEntityDefinition) Filter(eu.esdihumboldt.hale.common.instance.model.Filter) LeftoversImpl(eu.esdihumboldt.hale.common.align.model.transformation.tree.impl.LeftoversImpl) FamilyInstance(eu.esdihumboldt.hale.common.instance.model.FamilyInstance)

Example 7 with SourceNode

use of eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode in project hale by halestudio.

the class TGraphFactory method create.

/**
 * Create a transformation graph from a transformation tree.
 *
 * @param ttree the transformation tree
 * @param functionService the function service
 * @return an in-memory graph created from the transformation tree
 */
public static Graph create(TransformationTree ttree, FunctionService functionService) {
    TreeToGraphVisitor graphVisitor = new TreeToGraphVisitor(functionService);
    ttree.accept(graphVisitor);
    SetMultimap<String, String> connections = graphVisitor.getAllConnections();
    Set<String> ids = graphVisitor.getAllIds();
    Graph graph = new TinkerGraph();
    // add nodes to the graph
    for (String key : ids) {
        // create a vertex for each transformation node
        TransformationNode node = graphVisitor.getNode(key);
        Vertex vertex = graph.addVertex(key);
        setVertexProperties(vertex, node);
    }
    for (String key : connections.keySet()) {
        for (String value : connections.get(key)) {
            Vertex targetSide = graph.getVertex(key);
            Vertex sourceSide = graph.getVertex(value);
            TransformationNode targetSideNode = graphVisitor.getNode(key);
            TransformationNode sourceSideNode = graphVisitor.getNode(value);
            String edgeLabel;
            if (sourceSideNode instanceof SourceNode && targetSideNode instanceof SourceNode) {
                edgeLabel = EDGE_CHILD;
            } else if (sourceSideNode instanceof SourceNode && targetSideNode instanceof CellNode) {
                edgeLabel = EDGE_VARIABLE;
            } else if (sourceSideNode instanceof CellNode && targetSideNode instanceof GroupNode) {
                edgeLabel = EDGE_RESULT;
            } else if (sourceSideNode instanceof GroupNode && targetSideNode instanceof GroupNode) {
                edgeLabel = EDGE_PARENT;
            } else {
                throw new IllegalStateException("Invalid relation in transformation tree");
            }
            Edge edge = graph.addEdge(null, sourceSide, targetSide, edgeLabel);
            setEdgeProperties(edge, sourceSideNode, targetSideNode);
        }
    }
    return graph;
}
Also used : TransformationNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.TransformationNode) Vertex(com.tinkerpop.blueprints.Vertex) CellNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.CellNode) TinkerGraph(com.tinkerpop.blueprints.impls.tg.TinkerGraph) TreeToGraphVisitor(eu.esdihumboldt.hale.common.align.model.transformation.tree.visitor.TreeToGraphVisitor) GroupNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.GroupNode) SourceNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode) TinkerGraph(com.tinkerpop.blueprints.impls.tg.TinkerGraph) Graph(com.tinkerpop.blueprints.Graph) Edge(com.tinkerpop.blueprints.Edge)

Example 8 with SourceNode

use of eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode in project hale by halestudio.

the class TransformationTreeLabelProvider method getText.

/**
 * @see GraphLabelProvider#getText(Object)
 */
@Override
public String getText(Object element) {
    if (element instanceof IdentityWrapper<?>) {
        element = ((IdentityWrapper<?>) element).getValue();
    }
    if (element instanceof EntityConnectionData) {
        // text for connections
        EntityConnectionData connection = (EntityConnectionData) element;
        Set<String> names = null;
        Object source = connection.source;
        if (source instanceof IdentityWrapper<?>) {
            source = ((IdentityWrapper<?>) source).getValue();
        }
        Object dest = connection.dest;
        if (dest instanceof IdentityWrapper<?>) {
            dest = ((IdentityWrapper<?>) dest).getValue();
        }
        if (source instanceof TargetNode && dest instanceof CellNode) {
            names = ((TargetNode) source).getAssignmentNames((CellNode) dest);
        }
        if (source instanceof CellNode && dest instanceof SourceNode) {
            names = ((CellNode) source).getSourceNames((SourceNode) dest);
        }
        if (names != null && !names.isEmpty()) {
            if (names.contains(null)) {
                names = new HashSet<String>(names);
                names.remove(null);
                if (!names.isEmpty()) {
                    names.add("(unnamed)");
                }
            }
            // build name string
            Joiner joiner = Joiner.on(',');
            return joiner.join(names);
        }
        return "";
    }
    if (hasTransformationAnnotations(element)) {
        if (element instanceof SourceNode) {
            SourceNode node = (SourceNode) element;
            if (node.isDefined()) {
                Object value = node.getValue();
                if (value == null) {
                    // no value
                    return "(not set)";
                } else if (value instanceof Instance) {
                    // use the instance value if present
                    value = ((Instance) value).getValue();
                }
                if (value != null && !(value instanceof Group)) {
                    // TODO shorten if needed?
                    return value.toString();
                }
            // otherwise, just display the definition name
            }
        }
    }
    element = TransformationTreeUtil.extractObject(element);
    return super.getText(element);
}
Also used : Group(eu.esdihumboldt.hale.common.instance.model.Group) CellNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.CellNode) SourceNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode) TargetNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.TargetNode) Joiner(com.google.common.base.Joiner) EntityConnectionData(org.eclipse.zest.core.viewers.EntityConnectionData) Instance(eu.esdihumboldt.hale.common.instance.model.Instance) IdentityWrapper(eu.esdihumboldt.util.IdentityWrapper)

Example 9 with SourceNode

use of eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode in project hale by halestudio.

the class TreeGraphMLProvider method setVertexProperty.

/**
 * sets the property of a [@link]Vertex from a [@link]TransformationNode
 *
 * @param node the node-object to get the name from
 * @param vertex the vertex to set the property
 */
private void setVertexProperty(TransformationNode node, Vertex vertex) {
    if (node instanceof TransformationTree) {
        vertex.setProperty("name", ((TransformationTree) node).getType().getDisplayName());
        vertex.setProperty("type", "root");
    }
    if (node instanceof TargetNode) {
        vertex.setProperty("name", ((TargetNode) node).getDefinition().getDisplayName());
        vertex.setProperty("type", "target");
    }
    if (node instanceof SourceNode) {
        SourceNode snode = (SourceNode) node;
        Object value = snode.getValue();
        String name = ((SourceNode) node).getDefinition().getDisplayName();
        if (value instanceof Group) {
            vertex.setProperty("name", name);
            vertex.setProperty("group", getChildrencountString(value));
            vertex.setProperty("type", "source");
        }
        if (value instanceof Instance) {
            if (((Instance) value).getValue() != null) {
                vertex.setProperty("group", getChildrencountString(value));
                vertex.setProperty("value", ((Instance) value).getValue().toString());
                vertex.setProperty("type", "source");
            }
        } else {
            vertex.setProperty("name", name);
            vertex.setProperty("type", "source");
            if (value instanceof String) {
                vertex.setProperty("value", value);
            }
        }
    }
    if (node instanceof CellNode) {
        vertex.setProperty("name", FunctionUtil.getFunction(((CellNode) node).getCell().getTransformationIdentifier(), null).getDisplayName());
        vertex.setProperty("type", "cell");
    }
}
Also used : Group(eu.esdihumboldt.hale.common.instance.model.Group) SourceNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode) CellNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.CellNode) TargetNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.TargetNode) Instance(eu.esdihumboldt.hale.common.instance.model.Instance) TransformationTree(eu.esdihumboldt.hale.common.align.model.transformation.tree.TransformationTree)

Example 10 with SourceNode

use of eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode in project hale by halestudio.

the class FunctionExecutor method executeTransformation.

/**
 * Execute a property transformation.
 *
 * @param transformation the transformation factory
 * @param cell the alignment cell
 * @param sources the named source entities and nodes
 * @param targets the named target entities and nodes
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
protected void executeTransformation(PropertyTransformationFactory transformation, Cell cell, ListMultimap<String, Pair<SourceNode, Entity>> sources, ListMultimap<String, Pair<TargetNode, Entity>> targets) {
    TransformationLog cellLog = new CellLog(reporter, cell);
    PropertyTransformation<?> function;
    try {
        // TODO cache function objects?
        function = transformation.createExtensionObject();
    } catch (Exception e) {
        cellLog.error(cellLog.createMessage("Error creating transformation function.", e));
        return;
    }
    TransformationEngine engine = engines.get(transformation.getEngineId(), cellLog);
    if (engine == null) {
        // TODO instead try another transformation
        cellLog.error(cellLog.createMessage("Skipping property transformation: No matching transformation engine found", null));
        return;
    }
    // configure function
    // set expected result
    ListMultimap<String, PropertyEntityDefinition> expectedResult = ArrayListMultimap.create(targets.keySet().size(), 1);
    for (Entry<String, Pair<TargetNode, Entity>> targetEntry : targets.entries()) {
        EntityDefinition def = targetEntry.getValue().getSecond().getDefinition();
        expectedResult.put(targetEntry.getKey(), toPropertyEntityDefinition(def));
    }
    function.setExpectedResult(expectedResult);
    // set source variables
    ListMultimap<String, PropertyValue> variables = ArrayListMultimap.create();
    for (Entry<String, Pair<SourceNode, Entity>> sourceEntry : sources.entries()) {
        EntityDefinition def = sourceEntry.getValue().getSecond().getDefinition();
        SourceNode sourceNode = sourceEntry.getValue().getFirst();
        if (TransformationTreeUtil.isEager(cell, sourceNode, cellLog, context.getServiceProvider())) {
            // eager source - all values
            Object[] values = sourceNode.getAllValues();
            if (values != null) {
                for (int i = 0; i < values.length; i++) {
                    PropertyValue propertyValue = new PropertyValueImpl(values[i], toPropertyEntityDefinition(def));
                    variables.put(sourceEntry.getKey(), propertyValue);
                }
            }
        } else {
            // non-eager source - one value
            Object value = sourceNode.getValue();
            PropertyValue propertyValue = new PropertyValueImpl(value, toPropertyEntityDefinition(def));
            variables.put(sourceEntry.getKey(), propertyValue);
        }
    }
    function.setVariables(variables);
    // set parameters
    function.setParameters(cell.getTransformationParameters());
    // set context
    function.setExecutionContext(context.getCellContext(cell));
    // set target type
    TypeDefinition targetType = null;
    if (!targets.isEmpty()) {
        TargetNode target = targets.values().iterator().next().getFirst();
        targetType = target.getEntityDefinition().getType();
    }
    function.setTargetType(targetType);
    function.setTypeCell(typeCell.get());
    // execute function
    try {
        ((PropertyTransformation) function).execute(transformation.getIdentifier(), engine, transformation.getExecutionParameters(), cellLog, cell);
    } catch (Throwable e) {
        // TODO instead try another transformation?
        cellLog.error(cellLog.createMessage("Skipping property transformation: Executing property transformation failed.", e));
        return;
    }
    // apply function results
    ListMultimap<String, Object> results = function.getResults();
    if (results != null) {
        for (String name : results.keySet()) {
            List<Object> values = results.get(name);
            List<Pair<TargetNode, Entity>> nodes = targets.get(name);
            if (nodes.size() > values.size()) {
                cellLog.warn(cellLog.createMessage(MessageFormat.format("Transformation result misses values for result with name {0}", name), null));
            }
            if (values.size() > nodes.size()) {
                cellLog.warn(cellLog.createMessage(MessageFormat.format("More transformation results than target nodes for result with name {0}", name), null));
            }
            int count = Math.min(values.size(), nodes.size());
            // node...
            for (int i = 0; i < count; i++) {
                Object value = values.get(i);
                TargetNode node = nodes.get(i).getFirst();
                if (value instanceof MultiValue) {
                    MultiValue originalValue = (MultiValue) value;
                    MultiValue processedValue = new MultiValue(originalValue.size());
                    for (Object o : originalValue) {
                        processedValue.add(processValue(cellLog, function, o, node));
                    }
                    value = processedValue;
                } else {
                    value = processValue(cellLog, function, value, node);
                }
                /*
					 * TODO
					 * 
					 * set node value only if no result has already been set. If
					 * a value is already there and we are in a lower priority
					 * executor, we do not overwrite.
					 */
                if (!node.isDefined()) {
                    node.setResult(value);
                }
            }
        }
    }
}
Also used : TargetNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.TargetNode) TypeDefinition(eu.esdihumboldt.hale.common.schema.model.TypeDefinition) SourceNode(eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode) PropertyTransformation(eu.esdihumboldt.hale.common.align.transformation.function.PropertyTransformation) CellLog(eu.esdihumboldt.hale.common.align.transformation.report.impl.CellLog) MultiValue(eu.esdihumboldt.cst.MultiValue) Pair(eu.esdihumboldt.util.Pair) PropertyValueImpl(eu.esdihumboldt.hale.common.align.transformation.function.impl.PropertyValueImpl) PropertyValue(eu.esdihumboldt.hale.common.align.transformation.function.PropertyValue) ConversionException(org.springframework.core.convert.ConversionException) TransformationEngine(eu.esdihumboldt.hale.common.align.transformation.engine.TransformationEngine) PropertyEntityDefinition(eu.esdihumboldt.hale.common.align.model.impl.PropertyEntityDefinition) EntityDefinition(eu.esdihumboldt.hale.common.align.model.EntityDefinition) PropertyEntityDefinition(eu.esdihumboldt.hale.common.align.model.impl.PropertyEntityDefinition) TransformationLog(eu.esdihumboldt.hale.common.align.transformation.report.TransformationLog)

Aggregations

SourceNode (eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode)15 CellNode (eu.esdihumboldt.hale.common.align.model.transformation.tree.CellNode)6 TargetNode (eu.esdihumboldt.hale.common.align.model.transformation.tree.TargetNode)6 Group (eu.esdihumboldt.hale.common.instance.model.Group)4 EntityDefinition (eu.esdihumboldt.hale.common.align.model.EntityDefinition)3 TransformationTree (eu.esdihumboldt.hale.common.align.model.transformation.tree.TransformationTree)3 SourceNodeImpl (eu.esdihumboldt.hale.common.align.model.transformation.tree.impl.SourceNodeImpl)3 IdentityWrapper (eu.esdihumboldt.util.IdentityWrapper)3 ArrayList (java.util.ArrayList)3 TransformationContext (eu.esdihumboldt.hale.common.align.model.transformation.tree.context.TransformationContext)2 Instance (eu.esdihumboldt.hale.common.instance.model.Instance)2 TypeDefinition (eu.esdihumboldt.hale.common.schema.model.TypeDefinition)2 Pair (eu.esdihumboldt.util.Pair)2 Set (java.util.Set)2 Joiner (com.google.common.base.Joiner)1 Edge (com.tinkerpop.blueprints.Edge)1 Graph (com.tinkerpop.blueprints.Graph)1 Vertex (com.tinkerpop.blueprints.Vertex)1 TinkerGraph (com.tinkerpop.blueprints.impls.tg.TinkerGraph)1 MultiValue (eu.esdihumboldt.cst.MultiValue)1