public Delta diff(Model m1, Model m2, BiMap<String, String> mapping) {
    this.namespaceMap = mapping;
    this.m1 = m1;
    this.m2 = m2;
    this.m1.updateLabels();
    this.m2.updateLabels();
    this.delta = new TripleDelta();
    RdfGraph g = GraphUtils.toGraph(m1, RdfSchema.SUBCLASSOF);
    for (RdfNode n : m1.findNodes(RdfType.CLASS)) {
      if (!g.nodeMap().containsKey(n)) {
        g.nodeMap().put(n, g.graph().newNode(n));
      }
    }
    for (RdfNode n : m1.findNodes(RdfType.METACLASS)) {
      if (!g.nodeMap().containsKey(n)) {
        g.nodeMap().put(n, g.graph().newNode(n));
      }
    }
    for (RdfNode n : m1.findNodes(RdfType.METAPROPERTY)) {
      if (!g.nodeMap().containsKey(n)) {
        g.nodeMap().put(n, g.graph().newNode(n));
      }
    }
    classMap1 = g.nodeMap();
    closureClass1 =
        Transitivity.acyclicClosure(g.graph(), SuccessorSetFactory.intervalBased(g.graph()));

    g = GraphUtils.toGraph(m1, RdfSchema.SUBPROPERTYOF);
    for (RdfNode n : m1.findNodes(RdfType.PROPERTY)) {
      if (!g.nodeMap().containsKey(n)) {
        g.nodeMap().put(n, g.graph().newNode(n));
      }
    }
    propMap1 = g.nodeMap();
    closureProp1 =
        Transitivity.acyclicClosure(g.graph(), SuccessorSetFactory.intervalBased(g.graph()));

    return compareTriples();
  }
  private Delta compareTriples() {
    Set<Triple> matchedTriples = Sets.newHashSet();
    Set<String> superTypes = Sets.newHashSet();
    Set<String> ancestors = Sets.newHashSet();

    for (Triple triple1 : m1.triples().fetch()) {
      ObjectNode mappedS = null;

      if (triple1.subject().isResource()) {
        Resource s = (Resource) triple1.subject();
        mappedS = (ObjectNode) DiffUtils.mapNodeToAnotherModel(s, m2, namespaceMap);
      }

      if (triple1.predicate().getUri().equals(Rdf.TYPE)) {
        if (!superTypes.contains(triple1.subject().getIdentifier())) {
          superTypes.add(triple1.subject().getIdentifier());
          Set<RdfNode> st =
              DiffUtils.getSuperTypes(m1, (Resource) triple1.subject(), closureClass1, classMap1);
          if (mappedS == null) {
            for (RdfNode node : st) {
              ((TripleDelta) delta)
                  .insertDeletedTriple(triple1.subject(), triple1.predicate(), node);
            }
            continue;
          }
          DiffUtils.findDeletedNeighboors(
              m1,
              m2,
              (Resource) triple1.subject(),
              (Resource) mappedS,
              triple1.predicate(),
              st,
              namespaceMap,
              delta);
        }
      } else if (triple1.predicate().getUri().equals(RdfSchema.SUBCLASSOF)) {
        if (!ancestors.contains(triple1.subject().getIdentifier())) {
          ancestors.add(triple1.subject().getIdentifier());
          Set<RdfNode> an =
              DiffUtils.getAncestors(m1, (Resource) triple1.subject(), closureClass1, classMap1);
          if (mappedS == null) {
            for (RdfNode node : an) {
              ((TripleDelta) delta)
                  .insertDeletedTriple(triple1.subject(), triple1.predicate(), node);
            }
            continue;
          }
          DiffUtils.findDeletedNeighboors(
              m1,
              m2,
              (Resource) triple1.subject(),
              (Resource) mappedS,
              triple1.predicate(),
              an,
              namespaceMap,
              delta);
        }
      } else if (triple1.predicate().getUri().equals(RdfSchema.SUBPROPERTYOF)) {
        if (!ancestors.contains(triple1.subject().getIdentifier())) {
          ancestors.add(triple1.subject().getIdentifier());
          Set<RdfNode> an =
              DiffUtils.getAncestors(m1, (Resource) triple1.subject(), closureProp1, propMap1);
          if (mappedS == null) {
            for (RdfNode node : an) {
              ((TripleDelta) delta)
                  .insertDeletedTriple(triple1.subject(), triple1.predicate(), node);
            }
            continue;
          }
          DiffUtils.findDeletedNeighboors(
              m1,
              m2,
              (Resource) triple1.subject(),
              (Resource) mappedS,
              triple1.predicate(),
              an,
              namespaceMap,
              delta);
        }
      } else {
        RdfNode mappedO = null;
        if (triple1.object().isResource()) {
          mappedO = DiffUtils.mapNodeToAnotherModel((Resource) triple1.object(), m2, namespaceMap);
        } else if (triple1.object().isLiteral()) {
          if (m2.map(triple1.object().toString()).hasTriples()) {
            mappedO = m2.map(triple1.object().toString());
          }
        }
        Resource mappedP = null;
        if (triple1.predicate().isResource()) {
          mappedP =
              (Resource) DiffUtils.mapNodeToAnotherModel(triple1.predicate(), m2, namespaceMap);
        }
        if (mappedS == null || mappedO == null || mappedP == null) {
          ((TripleDelta) delta)
              .insertDeletedTriple(triple1.subject(), triple1.predicate(), triple1.object());
          continue;
        }
        //                }else
        // if(m2.triples().s(mappedS).p(mappedP).o(mappedO).fetch().iterator().hasNext()){
        //
        // matchedTriples.add(m2.triples().s(mappedS).p(mappedP).o(mappedO).fetch().iterator().next());
        //                }
        else if (!m2.triples().s(mappedS).p(mappedP).o(mappedO).fetch().iterator().hasNext()) {
          ((TripleDelta) delta)
              .insertDeletedTriple(triple1.subject(), triple1.predicate(), triple1.object());
        }
      }
    }

    for (Triple triple2 : m2.triples().fetch()) {
      ObjectNode mappedS = null;
      RdfNode mappedO = null;
      Resource mappedP = null;

      if (triple2.subject().isResource()) {
        Resource s = (Resource) triple2.subject();
        mappedS = (ObjectNode) DiffUtils.mapNodeToAnotherModel(s, m1, namespaceMap);
      }
      if (triple2.object().isResource()) {
        Resource o = (Resource) triple2.object();
        mappedO = DiffUtils.mapNodeToAnotherModel(o, m1, namespaceMap);
      } else if (triple2.object().isLiteral()) {
        if (m1.map(triple2.object().toString()).hasTriples()) {
          mappedO = m1.map(triple2.object().toString());
        }
      }
      if (triple2.predicate().isResource()) {
        Resource p = (Resource) triple2.predicate();
        mappedP = (Resource) DiffUtils.mapNodeToAnotherModel(p, m1, namespaceMap);
      }
      if (mappedS == null || mappedP == null || mappedO == null) {
        ((TripleDelta) delta)
            .insertAddedTriple(triple2.subject(), triple2.predicate(), triple2.object());
        continue;
      }
      if (!m1.isInferable(mappedS.mappedTo(m1), mappedP.mappedTo(m1), mappedO.mappedTo(m1))) {

        ((TripleDelta) delta)
            .insertAddedTriple(triple2.subject(), triple2.predicate(), triple2.object());
      }
    }
    return delta;
  }