/* * 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: * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.common.align.tgraph.impl.internal; import java.util.Set; import com.google.common.collect.SetMultimap; import com.tinkerpop.blueprints.Edge; import com.tinkerpop.blueprints.Graph; import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.blueprints.impls.tg.TinkerGraph; import eu.esdihumboldt.hale.common.align.model.impl.TypeEntityDefinition; import eu.esdihumboldt.hale.common.align.model.transformation.tree.CellNode; import eu.esdihumboldt.hale.common.align.model.transformation.tree.GroupNode; import eu.esdihumboldt.hale.common.align.model.transformation.tree.SourceNode; import eu.esdihumboldt.hale.common.align.model.transformation.tree.TargetNode; import eu.esdihumboldt.hale.common.align.model.transformation.tree.TransformationNode; import eu.esdihumboldt.hale.common.align.model.transformation.tree.TransformationTree; import eu.esdihumboldt.hale.common.align.model.transformation.tree.visitor.TreeToGraphVisitor; import eu.esdihumboldt.hale.common.align.service.FunctionService; import eu.esdihumboldt.hale.common.align.tgraph.TGraphConstants; import eu.esdihumboldt.hale.common.schema.SchemaSpaceID; /** * Helper for transformation graphs based on a {@link TransformationTree}. * * @author Simon Templer */ public class TGraphFactory implements TGraphConstants { /** * 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; } /** * Set the edge properties based on the source and target node. * * @param edge the edge * @param sourceSideNode the source node * @param targetSideNode the target node */ private static void setEdgeProperties(Edge edge, TransformationNode sourceSideNode, TransformationNode targetSideNode) { if (sourceSideNode instanceof SourceNode && targetSideNode instanceof SourceNode) { setEdgeProperties(edge, (SourceNode) sourceSideNode, (SourceNode) targetSideNode); } else if (sourceSideNode instanceof SourceNode && targetSideNode instanceof CellNode) { setEdgeProperties(edge, (SourceNode) sourceSideNode, (CellNode) targetSideNode); } else if (sourceSideNode instanceof CellNode && targetSideNode instanceof GroupNode) { setEdgeProperties(edge, (CellNode) sourceSideNode, (GroupNode) targetSideNode); } else if (sourceSideNode instanceof GroupNode && targetSideNode instanceof GroupNode) { setEdgeProperties(edge, (GroupNode) sourceSideNode, (GroupNode) targetSideNode); } } @SuppressWarnings("unused") private static void setEdgeProperties(Edge edge, SourceNode sourceSideNode, SourceNode targetSideNode) { // do nothing } private static void setEdgeProperties(Edge edge, SourceNode sourceSideNode, CellNode targetSideNode) { // do nothing edge.setProperty(P_VAR_NAMES, targetSideNode.getSourceNames(sourceSideNode)); } @SuppressWarnings("unused") private static void setEdgeProperties(Edge edge, CellNode sourceSideNode, GroupNode targetSideNode) { // do nothing } @SuppressWarnings("unused") private static void setEdgeProperties(Edge edge, GroupNode sourceSideNode, GroupNode targetSideNode) { // do nothing } /** * Set the vertex properties based on the associated transformation tree * node. * * @param node the transformation tree node * @param vertex the vertex to update */ private static void setVertexProperties(Vertex vertex, TransformationNode node) { vertex.setProperty(P_ORG_NODE, node); if (node instanceof CellNode) { setVertexProperties(vertex, (CellNode) node); } if (node instanceof SourceNode) { setVertexProperties(vertex, (SourceNode) node); } if (node instanceof GroupNode) { setVertexProperties(vertex, (GroupNode) node); } } private static void setVertexProperties(Vertex vertex, CellNode node) { vertex.setProperty(P_TYPE, NodeType.Cell); vertex.setProperty(P_CELL, node.getCell()); } private static void setVertexProperties(Vertex vertex, SourceNode node) { vertex.setProperty(P_TYPE, NodeType.Source); vertex.setProperty(P_ENTITY, node.getEntityDefinition()); } private static void setVertexProperties(Vertex vertex, GroupNode node) { vertex.setProperty(P_TYPE, NodeType.Target); if (node instanceof TargetNode) { setVertexProperties(vertex, (TargetNode) node); } if (node instanceof TransformationTree) { setVertexProperties(vertex, (TransformationTree) node); } } private static void setVertexProperties(Vertex vertex, TargetNode node) { vertex.setProperty(P_ENTITY, node.getEntityDefinition()); } private static void setVertexProperties(Vertex vertex, TransformationTree node) { // create a type entity definition // TODO also include the filter TypeEntityDefinition ted = new TypeEntityDefinition(node.getType(), SchemaSpaceID.TARGET, null); vertex.setProperty(P_ENTITY, ted); } }