Package edu.isi.karma.modeling.alignment

Source Code of edu.isi.karma.modeling.alignment.Alignment

/*******************************************************************************
* Copyright 2012 University of Southern California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code was developed by the Information Integration Group as part
* of the Karma project at the Information Sciences Institute of the
* University of Southern California.  For more information, publications,
* and related projects, please see: http://www.isi.edu/integration
******************************************************************************/
package edu.isi.karma.modeling.alignment;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.jgrapht.UndirectedGraph;
import org.jgrapht.graph.AsUndirectedGraph;
import org.jgrapht.graph.DirectedWeightedMultigraph;
import org.jgrapht.graph.WeightedMultigraph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.rits.cloning.Cloner;

import edu.isi.karma.config.ModelingConfiguration;
import edu.isi.karma.modeling.Namespaces;
import edu.isi.karma.modeling.Prefixes;
import edu.isi.karma.modeling.Uris;
import edu.isi.karma.modeling.alignment.learner.ModelLearner;
import edu.isi.karma.modeling.alignment.learner.ModelLearningGraph;
import edu.isi.karma.modeling.alignment.learner.ModelLearningGraphType;
import edu.isi.karma.modeling.ontology.OntologyManager;
import edu.isi.karma.modeling.ontology.OntologyUpdateListener;
import edu.isi.karma.rep.alignment.ClassInstanceLink;
import edu.isi.karma.rep.alignment.ColumnNode;
import edu.isi.karma.rep.alignment.ColumnSubClassLink;
import edu.isi.karma.rep.alignment.DataPropertyLink;
import edu.isi.karma.rep.alignment.DataPropertyOfColumnLink;
import edu.isi.karma.rep.alignment.DefaultLink;
import edu.isi.karma.rep.alignment.InternalNode;
import edu.isi.karma.rep.alignment.Label;
import edu.isi.karma.rep.alignment.LabeledLink;
import edu.isi.karma.rep.alignment.LinkKeyInfo;
import edu.isi.karma.rep.alignment.LinkPriorityComparator;
import edu.isi.karma.rep.alignment.LinkStatus;
import edu.isi.karma.rep.alignment.LinkType;
import edu.isi.karma.rep.alignment.LiteralNode;
import edu.isi.karma.rep.alignment.Node;
import edu.isi.karma.rep.alignment.NodeType;
import edu.isi.karma.rep.alignment.ObjectPropertyLink;
import edu.isi.karma.rep.alignment.ObjectPropertySpecializationLink;
import edu.isi.karma.rep.alignment.SemanticType;
import edu.isi.karma.rep.alignment.SubClassLink;



public class Alignment implements OntologyUpdateListener {

  static Logger logger = LoggerFactory.getLogger(Alignment.class);

  private OntologyManager ontologyManager;
  private GraphBuilder graphBuilder;
  private DirectedWeightedMultigraph<Node, LabeledLink> steinerTree = null;
  private Node root = null;
  private NodeIdFactory nodeIdFactory;
  private Set<ColumnNode> sourceColumnNodes;


  public Alignment(OntologyManager ontologyManager) {

    this.ontologyManager = ontologyManager;
    this.ontologyManager.subscribeListener(this);
    this.sourceColumnNodes = new HashSet<ColumnNode>();
    if (ModelingConfiguration.isLearnAlignmentEnabled()) {
      this.graphBuilder =
          ModelLearningGraph.getInstance(ontologyManager, ModelLearningGraphType.Compact).getGraphBuilderClone();
    } else {
      this.graphBuilder =  new GraphBuilder(this.ontologyManager, true);
    }
    this.nodeIdFactory = this.graphBuilder.getNodeIdFactory();
    logger.debug("loading learning graph ...");
  }

  public boolean isEmpty() {
    return (this.graphBuilder.getGraph().edgeSet().size() == 0 || this.steinerTree == null);
  }
 
  public Node GetTreeRoot() {
    return this.root;
  }
 
  public GraphBuilder getGraphBuilder() {
    return this.graphBuilder;
  }
 
 
  public Set<ColumnNode> getSourceColumnNodes() {
    return sourceColumnNodes;
  }

  public Alignment getAlignmentClone() {
    Cloner cloner = new Cloner();
//    cloner.setDumpClonedClasses(true);
    cloner.dontClone(OntologyManager.class);
    cloner.dontCloneInstanceOf(OntologyManager.class);
    cloner.dontClone(DirectedWeightedMultigraph.class);
    cloner.dontCloneInstanceOf(DirectedWeightedMultigraph.class);
    return cloner.deepClone(this);
  }
 
  public DirectedWeightedMultigraph<Node, LabeledLink> getSteinerTree() {
    if (this.steinerTree == null) align();
    // GraphUtil.printGraph(this.steinerTree);
    return this.steinerTree;
  }
 
  public DirectedWeightedMultigraph<Node, DefaultLink> getGraph() {
    return this.graphBuilder.getGraph();
  }
 
  public void setGraph(DirectedWeightedMultigraph<Node, DefaultLink> graph) {
    this.graphBuilder.setGraph(graph);
  }
 
  public Set<Node> getGraphNodes() {
    return this.graphBuilder.getGraph().vertexSet();
  }
 
//  public Set<DefaultLink> getGraphLinks() {
//    return this.graphBuilder.getGraph().edgeSet();
//  }
 
  public Node getNodeById(String nodeId) {
    return this.graphBuilder.getIdToNodeMap().get(nodeId);
  }
 
  public Set<Node> getNodesByUri(String uri) {
    return this.graphBuilder.getUriToNodesMap().get(uri);
  }
 
  public Set<Node> getNodesByType(NodeType type) {
    return this.graphBuilder.getTypeToNodesMap().get(type);
  }
 
  public Set<Node> getForcedNodes() {
    return this.graphBuilder.getForcedNodes();
  }
 
  public LabeledLink getLinkById(String linkId) {
    return this.graphBuilder.getIdToLinkMap().get(linkId);
  }
 
  public Set<LabeledLink> getLinksByUri(String uri) {
    return this.graphBuilder.getUriToLinksMap().get(uri);
  }
 
  public Set<LabeledLink> getLinksByType(LinkType type) {
    return this.graphBuilder.getTypeToLinksMap().get(type);
  }
 
  public Set<LabeledLink> getLinksByStatus(LinkStatus status) {
    return this.graphBuilder.getStatusToLinksMap().get(status);
  }

  public int getLastIndexOfNodeUri(String uri) {
    return this.nodeIdFactory.lastIndexOf(uri);
  }
 
//  public int getLastIndexOfLinkUri(String uri) {
//    return this.linkIdFactory.lastIndexOf(uri);
//  }

  public ColumnNode getColumnNodeByHNodeId(String hNodeId) {

    Node n = this.graphBuilder.getIdToNodeMap().get(hNodeId);
    if (n != null && n instanceof ColumnNode)   
      return (ColumnNode)n;
    else
      return null;
   
//    List<Node> columnNodes = this.getNodesByType(NodeType.ColumnNode);
//    if (columnNodes == null) return null;
//    for (Node cNode : columnNodes) {
//      if (((ColumnNode)cNode).getHNodeId().equals(hNodeId))
//        return (ColumnNode)cNode;
//    }
//    return null;
  }
 
  // AddNode methods
 
  public ColumnNode addColumnNode(String hNodeId, String columnName, Label rdfLiteralType) {
   
    // use hNodeId as id of the node
    ColumnNode node = new ColumnNode(hNodeId, hNodeId, columnName, rdfLiteralType);
    if (this.graphBuilder.addNodeAndUpdate(node)) {
      this.sourceColumnNodes.add(node);
      return node;
    }
    return null;
  }
 
  public InternalNode addInternalNode(Label label) {
   
    String id = nodeIdFactory.getNodeId(label.getUri());
    InternalNode node = new InternalNode(id, label);
    if (this.graphBuilder.addNodeAndUpdate(node)) return node;
    return null
  }
 
  public InternalNode addForcedInternalNode(Label label) {
    String id = nodeIdFactory.getNodeId(label.getUri());
    InternalNode node = new InternalNode(id, label);
    node.setForced(true);
    if (this.graphBuilder.addNodeAndUpdate(node)) return node;
    return null;
  }
 
  public LiteralNode addLiteralNode(String value, String type, boolean isUri) {
   
    type = type.replace(Prefixes.XSD + ":", Namespaces.XSD);
    Label literalType = new Label(type, Namespaces.XSD, Prefixes.XSD);
   
    String id = nodeIdFactory.getNodeId(value);
   
    LiteralNode node = new LiteralNode(id, value, literalType, isUri);
    if(this.graphBuilder.addNode(node)) return node;
    return null;
  }
 
  public void updateLiteralNode(String nodeId, String value, String type, boolean isUri) {
    LiteralNode node = (LiteralNode) getNodeById(nodeId);
    type = type.replace(Prefixes.XSD + ":", Namespaces.XSD);
    Label literalType = new Label(type, Namespaces.XSD, Prefixes.XSD);
   
    node.setDatatype(literalType);
    node.setValue(value);
    node.setUri(isUri);
  }
 
  public void deleteForcedInternalNode(String nodeId) {
    Node node = getNodeById(nodeId);
    if(node != null) {
      this.graphBuilder.removeNode(node);
    }
  }
 
  // AddLink methods

  public DataPropertyLink addDataPropertyLink(Node source, Node target, Label label) {
   
    String id = LinkIdFactory.getLinkId(label.getUri(), source.getId(), target.getId())
    DataPropertyLink link = new DataPropertyLink(id, label);
    if (this.graphBuilder.addLink(source, target, link)) return link;
    return null;
  }
 

    public ObjectPropertyLink addObjectPropertyLink(Node source, Node target, Label label) {
           
            String id = LinkIdFactory.getLinkId(label.getUri(), source.getId(), target.getId());       
            ObjectPropertyLink link = new ObjectPropertyLink(id, label,
                this.graphBuilder.getOntologyManager().getObjectPropertyType(source.getLabel().getUri(), target.getLabel().getUri(), label.getUri()));
            if (this.graphBuilder.addLink(source, target, link))
            {
              return link;
            }
            else if(this.graphBuilder.getIdToLinkMap().containsKey(link.getId()))
            {
              return (ObjectPropertyLink) this.graphBuilder.getIdToLinkMap().get(link.getId());
            }
            else
            {
              return null;
            }
    }
 
  // Probably we don't need this function in the interface to GUI
  public SubClassLink addSubClassOfLink(Node source, Node target) {
   
    String id = LinkIdFactory.getLinkId(Uris.RDFS_SUBCLASS_URI, source.getId(), target.getId());
    SubClassLink link = new SubClassLink(id);
    if (this.graphBuilder.addLink(source, target, link)) return link;
    return null
  }
 
  public ClassInstanceLink addClassInstanceLink(Node source, Node target, LinkKeyInfo keyInfo) {
   
    String id = LinkIdFactory.getLinkId(Uris.CLASS_INSTANCE_LINK_URI, source.getId(), target.getId());
    ClassInstanceLink link = new ClassInstanceLink(id, keyInfo);
    if (this.graphBuilder.addLink(source, target, link)) return link;
    return null;
  }
 
  public DataPropertyOfColumnLink addDataPropertyOfColumnLink(Node source, Node target, String specializedColumnHNodeId, String specializedLinkId) {
   
    String id = LinkIdFactory.getLinkId(Uris.DATAPROPERTY_OF_COLUMN_LINK_URI, source.getId(), target.getId());
    DataPropertyOfColumnLink link = new DataPropertyOfColumnLink(id, specializedColumnHNodeId, specializedLinkId);
    if (this.graphBuilder.addLink(source, target, link)) return link;
    return null
  }
 
  public ObjectPropertySpecializationLink addObjectPropertySpecializationLink(Node source, Node target, String specializedLinkId) {
    String id = LinkIdFactory.getLinkId(Uris.OBJECTPROPERTY_SPECIALIZATION_LINK_URI, source.getId(), target.getId());
    ObjectPropertySpecializationLink link = new ObjectPropertySpecializationLink(id, specializedLinkId);
    if (this.graphBuilder.addLink(source, target, link)) return link;
    return null;
  }

  public ColumnSubClassLink addColumnSubClassOfLink(Node source, Node target) {
   
    String id = LinkIdFactory.getLinkId(Uris.COLUMN_SUBCLASS_LINK_URI, source.getId(), target.getId());
    ColumnSubClassLink link = new ColumnSubClassLink(id);
    if (this.graphBuilder.addLink(source, target, link)) return link;
    return null
  }
 
  public void changeLinkWeight(String linkId, double weight) {
   
    LabeledLink link = this.getLinkById(linkId);
    if (link == null) {
      logger.error("Could not find the link with the id " + linkId);
      return;
    }
   
    this.graphBuilder.changeLinkWeight(link, weight);
  }
 
  public void changeLinkStatus(String linkId, LinkStatus newStatus) {

    logger.debug("changing the status of link " + linkId + " to " + newStatus.name());
    LabeledLink link = this.getLinkById(linkId);
    if (link == null) {
      if (newStatus == LinkStatus.ForcedByUser) {
        Node source = this.getNodeById(LinkIdFactory.getLinkSourceId(linkId));
        Node target = this.getNodeById(LinkIdFactory.getLinkTargetId(linkId));
        String linkUri = LinkIdFactory.getLinkUri(linkId);
        LabeledLink newLink;
        if (linkUri.equalsIgnoreCase(Uris.RDFS_SUBCLASS_URI))
          newLink = new SubClassLink(linkId);
        else
          newLink = new ObjectPropertyLink(linkId,
              this.graphBuilder.getOntologyManager().getUriLabel(linkUri),
              this.graphBuilder.getOntologyManager().getObjectPropertyType(source.getLabel().getUri(), target.getLabel().getUri(), linkUri));
       
        newLink.setStatus(LinkStatus.ForcedByUser);
        this.graphBuilder.addLink(source, target, newLink);
      }
    } else
      this.graphBuilder.changeLinkStatus(link, newStatus);
  }
 
//  /**
//   * This method removes a node from the graph and also all the links and the nodes that
//   * are added to the graph by adding the specified node.
//   * This method is useful when the user changes the semantic type assigned to a column.
//   * The GUI needs to call the method by sending a Column Node 
//   * @param nodeId
//   */
//  public boolean removeNode(String nodeId) {
//
//    Node node = this.getNodeById(nodeId);
//    if (node == null) {
//      logger.debug("Cannot find the node " + nodeId + " in the graph.");
//      return false;
//    }
//     
//    this.graphBuilder.removeNode(node);
//
//    return false;
//  }

  /**
   * This method just deletes the specified link from the graph and leaves the rest of the graph untouched.
   * @param linkId
   * @return
   */
  public boolean removeLink(String linkId) {
   
    LabeledLink link = this.getLinkById(linkId);
    if (link != null)
      return this.graphBuilder.removeLink(link);
    logger.debug("Cannot find the link " + linkId + " in the graph.");
    return false;
  }
 
  public Set<LabeledLink> getCurrentIncomingLinksToNode(String nodeId) {
   
    Node node = this.getNodeById(nodeId);
    if (node == null) return null;
    if (this.steinerTree == null || !this.steinerTree.containsVertex(node)) return null;
     
    return this.steinerTree.incomingEdgesOf(node);
  }
 
  public Set<LabeledLink> getCurrentOutgoingLinksToNode(String nodeId) {
   
    Node node = this.getNodeById(nodeId);
    if (node == null) return null;
    if (this.steinerTree == null || !this.steinerTree.containsVertex(node)) return null;
     
    return this.steinerTree.outgoingEdgesOf(node);
  }

  public List<LabeledLink> getLinks(String sourceId, String targetId) {
    return this.graphBuilder.getPossibleLinks(sourceId, targetId);
  }

  public List<LabeledLink> getIncomingLinks(String nodeId) {
   
    List<LabeledLink> possibleLinks  = new ArrayList<LabeledLink>();
    List<DefaultLink> tempDefault = null;
    List<LabeledLink> tempLabeled = null;
    HashSet<DefaultLink> allLinks = new HashSet<DefaultLink>();

    Node node = this.getNodeById(nodeId);
    if (node == null) return possibleLinks;
   
    Set<DefaultLink> incomingLinks = this.graphBuilder.getGraph().incomingEdgesOf(node);
    if (incomingLinks != null) {
      tempDefault = Arrays.asList(incomingLinks.toArray(new DefaultLink[0]));
      allLinks.addAll(tempDefault);
    }
   
    if (node instanceof ColumnNode) {
      if (tempDefault != null) {
        for (DefaultLink l : tempDefault)
          if (l instanceof LabeledLink)
            possibleLinks.add((LabeledLink)l);
      }
    } else {
      Set<DefaultLink> outgoingLinks = this.graphBuilder.getGraph().outgoingEdgesOf(node);
      if (outgoingLinks != null) {
        tempDefault = Arrays.asList(outgoingLinks.toArray(new DefaultLink[0]));
        allLinks.addAll(outgoingLinks);
      }
     
      if (allLinks.size() == 0)
        return possibleLinks;
     
      String sourceId, targetId;
      for (DefaultLink e : allLinks) {
        if (e.getSource().getId().equals(nodeId)) { // outgoing link
          sourceId = e.getTarget().getId();
          targetId = nodeId;
        } else { // incoming link
          sourceId = e.getSource().getId();
          targetId = nodeId;
        }
        tempLabeled = getLinks(sourceId, targetId);
        if (tempLabeled != null)
          possibleLinks.addAll(tempLabeled);
      }
    }
   
    Collections.sort(possibleLinks, new LinkPriorityComparator());
   
//    for (Link l : possibleLinks) {
//      StringBuilder sb = new StringBuilder();
//      sb.append(l.getId() + " === ");
//      sb.append(l.getSource().getId() + " === ");
//      sb.append(l.getSource().getLabel().getNs() + " === ");
//      sb.append(l.getSource().getLocalId() + " === ");
//      sb.append(l.getSource().getDisplayId());
//      sb.append("\n");
//      sb.append(l.getTarget().getId() + " === ");
//      sb.append(l.getLabel().getUri() + " === ");
//      sb.append("\n");
//      logger.debug(sb.toString());
//    }
    logger.debug("Finished obtaining the incoming links.");
    return possibleLinks;
  }
 
  public List<LabeledLink> getOutgoingLinks(String nodeId) {
   
    List<LabeledLink> possibleLinks  = new ArrayList<LabeledLink>();
    List<DefaultLink> tempDefault = null;
    List<LabeledLink> tempLabeled = null;
    HashSet<DefaultLink> allLinks = new HashSet<DefaultLink>();

    Node node = this.getNodeById(nodeId);
    if (node == null || node instanceof ColumnNode) return possibleLinks;
   
    Set<DefaultLink> incomingLinks = this.graphBuilder.getGraph().incomingEdgesOf(node);
    if (incomingLinks != null) {
      tempDefault = Arrays.asList(incomingLinks.toArray(new DefaultLink[0]));
      allLinks.addAll(tempDefault);
    }
    Set<DefaultLink> outgoingLinks = this.graphBuilder.getGraph().outgoingEdgesOf(node);
    if (outgoingLinks != null) {
      tempDefault = Arrays.asList(outgoingLinks.toArray(new DefaultLink[0]));
      allLinks.addAll(outgoingLinks);
    }
   
    if (allLinks.size() == 0)
      return possibleLinks;
   
    String sourceId, targetId;
    for (DefaultLink e : allLinks) {
      if (e.getSource().getId().equals(nodeId)) { // outgoing link
        sourceId = nodeId;
        targetId = e.getTarget().getId();
      } else { // incoming link
        sourceId = nodeId;
        targetId = e.getSource().getId();
      }
      tempLabeled = getLinks(sourceId, targetId);
      if (tempLabeled != null)
        possibleLinks.addAll(tempLabeled);
    }
   
    Collections.sort(possibleLinks, new LinkPriorityComparator());

    logger.debug("Finished obtaining the outgoing links.");
    return possibleLinks;
  }
 
  private void updateLinksPreferredByUI() {
   
    if (this.steinerTree == null)
      return;
   
    // Change the status of previously preferred links to normal
    Set<LabeledLink> linksInPreviousTree = this.getLinksByStatus(LinkStatus.PreferredByUI);
    if (linksInPreviousTree != null) {
      LabeledLink[] links = linksInPreviousTree.toArray(new LabeledLink[0]);
      for (LabeledLink link : links)
        this.graphBuilder.changeLinkStatus(link, LinkStatus.Normal);
    }
   
    Set<LabeledLink> linksForcedByUser = this.getLinksByStatus(LinkStatus.ForcedByUser);
    for (LabeledLink link: this.steinerTree.edgeSet()) {
      if (linksForcedByUser == null || !linksForcedByUser.contains(link)) {
        this.graphBuilder.changeLinkStatus(link, LinkStatus.PreferredByUI);
        logger.debug("link " + link.getId() + " has been added to preferred UI links.");
      }
    }
  }
 
  // FIXME: What if a column node has more than one domain?
  public List<Node> computeSteinerNodes() {
    Set<Node> steinerNodes = new HashSet<Node>();
   
    // Add column nodes and their domain
    // it is better to set isForced flag when setting a semantic type
    Set<ColumnNode> columnNodes = this.sourceColumnNodes;
    if (columnNodes != null) {
      for (ColumnNode n : columnNodes) {
        steinerNodes.add(n);
        if (n.hasUserType())
          steinerNodes.add(n.getDomainNode());
      }
    }

    Set<Node> forcedNodes = this.getForcedNodes();
    for (Node n : forcedNodes) {
      if (!steinerNodes.contains(n))
        steinerNodes.add(n);
    }
   
    // Add source and target of the links forced by the user
    Set<LabeledLink> linksForcedByUser = this.getLinksByStatus(LinkStatus.ForcedByUser);
    if (linksForcedByUser != null) {
      for (LabeledLink link : linksForcedByUser) {
       
        if (!steinerNodes.contains(link.getSource()))
          steinerNodes.add(link.getSource());
 
        if (!steinerNodes.contains(link.getTarget()))
          steinerNodes.add(link.getTarget());     
      }
    }
   
    ArrayList<Node> result = new ArrayList<>();
    result.addAll(steinerNodes);
    return result;
  }
 
  public void align() {
   
//      logger.debug("*** Graph ***");
//    GraphUtil.printGraphSimple(this.graphBuilder.getGraph());

    long start = System.currentTimeMillis();
   
    logger.debug("updating UI preferred links ...");
    this.updateLinksPreferredByUI();

    logger.debug("forced links ...");
    if (this.getLinksByStatus(LinkStatus.ForcedByUser) != null) {
      for (LabeledLink link: this.getLinksByStatus(LinkStatus.ForcedByUser))
        logger.debug("\t" + link.getId());
    }
   
    if (ModelingConfiguration.isLearnAlignmentEnabled())
      learnFromKnownSemanticModels();
    else
      learnFromOntology();
   
    long elapsedTimeMillis = System.currentTimeMillis() - start;
    float elapsedTimeSec = elapsedTimeMillis/1000F;
   
    if (this.steinerTree != null) {
      logger.debug("total number of nodes in steiner tree: " + this.steinerTree.vertexSet().size());
      logger.debug("total number of edges in steiner tree: " + this.steinerTree.edgeSet().size());
    }
    logger.debug("time to compute steiner tree: " + elapsedTimeSec);
  }

  @Override
  public void ontologyModelUpdated() {
    this.graphBuilder.resetOntologyMaps();
   
  }

  public void cleanup() {
    this.ontologyManager.unsubscribeListener(this);
  }
 
  private void learnFromOntology() {
   
    logger.debug("preparing G Prime for steiner algorithm input ...");
   
//    GraphPreProcess graphPreProcess = new GraphPreProcess(this.graphBuilder.getGraph(),
//        this.getLinksByStatus(LinkStatus.PreferredByUI),
//        this.getLinksByStatus(LinkStatus.ForcedByUser));   
    UndirectedGraph<Node, DefaultLink> undirectedGraph = new AsUndirectedGraph<Node, DefaultLink>(this.getGraph());

    logger.debug("computing steiner nodes ...");
    List<Node> steinerNodes = this.computeSteinerNodes();

    logger.debug("steiner nodes ...");
    if (steinerNodes != null) {
      for (Node node: steinerNodes)
        logger.debug("\t" + node.getId());
    }

    logger.debug("computing steiner tree ...");
    SteinerTree steinerTree = new SteinerTree(undirectedGraph, steinerNodes);
    WeightedMultigraph<Node, DefaultLink> tree = steinerTree.getDefaultSteinerTree();
    if (tree == null) {
      logger.debug("resulting tree is null ...");
      return;
    }

    logger.info("*** steiner tree before post processing step ***");
    logger.info(GraphUtil.defaultGraphToString(tree));
    TreePostProcess treePostProcess = new TreePostProcess(this.graphBuilder, tree, getLinksByStatus(LinkStatus.ForcedByUser), true);

    this.steinerTree = treePostProcess.getTree();
    this.root = treePostProcess.getRoot();

    logger.info("*** steiner tree after post processing step ***");
    logger.info(GraphUtil.labeledGraphToString(this.steinerTree));
  }
 
  private void learnFromKnownSemanticModels() {
   
    if (!ModelingConfiguration.isLearnAlignmentEnabled())
      return;
   
    List<Node> steinerNodes = this.computeSteinerNodes();
    if (steinerNodes == null || steinerNodes.isEmpty()) {
      return;
    }
   
    ModelLearner modelLearner = new ModelLearner(this.graphBuilder, steinerNodes);

    SemanticModel model = modelLearner.getModel();
    if (model == null) {
      logger.error("could not learn any model for this source!");
      return ;
    }

    this.updateAlignment(model, null);
  }
 
  private void addForcedLinks() {
    Set<LabeledLink> forcedLinks = getLinksByStatus(LinkStatus.ForcedByUser);
    if (forcedLinks != null)
    for (LabeledLink link : forcedLinks) {
      if (!this.steinerTree.containsEdge(link) &&
          this.steinerTree.containsVertex(link.getSource()) &&
          this.steinerTree.containsVertex(link.getTarget())) {
            this.steinerTree.addEdge(link.getSource(), link.getTarget(), link);
      }
    }
  }
 
  public void updateAlignment(SemanticModel model, List<SemanticType> semanticTypes) {
   
    if (model == null)
      return;
   
    if (semanticTypes == null) semanticTypes = new LinkedList<SemanticType>();
   
    DirectedWeightedMultigraph<Node, LabeledLink> tree =
        new DirectedWeightedMultigraph<Node, LabeledLink>(LabeledLink.class);

    HashMap<Node, Node> modelToAlignmentNode = new HashMap<Node, Node>();
    for (Node n : model.getGraph().vertexSet()) {
      if (n instanceof InternalNode) {

        InternalNode iNode;

        iNode = (InternalNode)this.getNodeById(n.getId());
        if (iNode != null) {
          modelToAlignmentNode.put(n, iNode);
        } else {
          iNode = this.addInternalNode(n.getLabel());
          modelToAlignmentNode.put(n, iNode);
        }
       
        tree.addVertex(iNode);
      }
     
      if (n instanceof ColumnNode) {
        if (model.getMappingToSourceColumns() != null) {
          ColumnNode cn = model.getMappingToSourceColumns().get(n);
          modelToAlignmentNode.put(n, cn);
          tree.addVertex(cn);
        }
      }
    }
   
    Node source, target;
    for (LabeledLink l : model.getGraph().edgeSet()) {
     
      if (!(l.getSource() instanceof InternalNode)) {
        logger.error("column node cannot have an outgoing link!");
        return;
      }

      source = modelToAlignmentNode.get(l.getSource());
      target = modelToAlignmentNode.get(l.getTarget());
     
      if (source == null || target == null)
        continue;

      String id = LinkIdFactory.getLinkId(l.getUri(), source.getId(), target.getId());
      LabeledLink newLink = l.copy(id);
     
        if (newLink == null) continue;
     
      this.getGraphBuilder().addLink(source, target, newLink); // returns false if link already exists
      tree.addEdge(source, target, newLink);
           
      if (target instanceof ColumnNode) {
        SemanticType st = new SemanticType(((ColumnNode)target).getHNodeId(),
            newLink.getLabel(), source.getLabel(), SemanticType.Origin.User, 1.0);
        semanticTypes.add(st);
      }
     
    }

    this.steinerTree = tree;
    this.addForcedLinks();
    this.root = TreePostProcess.selectRoot(GraphUtil.asDefaultGraph(tree));

  }
 
}
TOP

Related Classes of edu.isi.karma.modeling.alignment.Alignment

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.