// Path: src/main/java/com/github/lukaszkusek/xml/comparator/comparators/children/cost/minimum/MinimumCostAssignmentCalculator.java
// public interface MinimumCostAssignmentCalculator {
//     CostMatrix getMinimumCostAssignment(CostMatrix childrenComparisonMatrix);
// }
// 
// Path: src/main/java/com/github/lukaszkusek/xml/comparator/diff/DifferenceDetails.java
// public class DifferenceDetails  {
// 
//     private Set<DifferenceInformation> differenceInformationSet;
//     private Set<DifferenceInformation> uniqueDifferenceInformationSet;
// 
//     public DifferenceDetails() {
//         differenceInformationSet = Sets.newHashSet();
//         uniqueDifferenceInformationSet = Sets.newHashSet();
//     }
// 
//     public static DifferenceDetails empty() {
//         return new DifferenceDetails();
//     }
// 
//     public static DifferenceDetails of(Node node1, Node node2, DifferenceCode differenceCode) {
//         DifferenceDetails differenceDetails = new DifferenceDetails();
//         differenceDetails.put(node1, node2, differenceCode);
// 
//         return differenceDetails;
//     }
// 
//     public DifferenceDetails put(Node node1, Node node2, DifferenceCode differenceCode) {
//         put(node1, node2, null, differenceCode);
// 
//         return this;
//     }
// 
//     public static DifferenceDetails of(Node node1, Node node2, String attributeName, DifferenceCode differenceCode) {
//         DifferenceDetails differenceDetails = new DifferenceDetails();
//         differenceDetails.put(node1, node2, attributeName, differenceCode);
// 
//         return differenceDetails;
//     }
// 
//     public DifferenceDetails put(Node node1, Node node2, String attributeName, DifferenceCode differenceCode) {
//         differenceInformationSet.add(new DifferenceInformation(node1, node2, attributeName, differenceCode));
//         uniqueDifferenceInformationSet.add(
//                 new DifferenceInformation(
//                         Optional.ofNullable(node1).map(SimpleXPathNode::new).orElse(null),
//                         Optional.ofNullable(node2).map(SimpleXPathNode::new).orElse(null),
//                         attributeName,
//                         differenceCode));
// 
//         return this;
//     }
// 
//     public DifferenceDetails putAll(DifferenceDetails differenceDetails) {
//         this.differenceInformationSet.addAll(differenceDetails.getDifferenceInformationSet());
//         this.uniqueDifferenceInformationSet.addAll(differenceDetails.getUniqueDifferenceInformationSet());
// 
//         return this;
//     }
// 
//     public Set<DifferenceInformation> getDifferenceInformationSet() {
//         return differenceInformationSet;
//     }
// 
//     public void setDifferenceInformationSet(Set<DifferenceInformation> differenceInformationSet) {
//         this.differenceInformationSet = differenceInformationSet;
//     }
// 
//     public Set<DifferenceInformation> getUniqueDifferenceInformationSet() {
//         return uniqueDifferenceInformationSet;
//     }
// 
//     public void setUniqueDifferenceInformationSet(Set<DifferenceInformation> uniqueDifferenceInformationSet) {
//         this.uniqueDifferenceInformationSet = uniqueDifferenceInformationSet;
//     }
// 
//     public DifferenceDetails filter(Predicate<DifferenceInformation> xPathsToOmitPredicate) {
//         DifferenceDetails filteredDifferenceDetails = new DifferenceDetails();
// 
//         filteredDifferenceDetails.setUniqueDifferenceInformationSet(
//                 filter(getUniqueDifferenceInformationSet(), xPathsToOmitPredicate));
// 
//         filteredDifferenceDetails.setDifferenceInformationSet(
//                 filter(getDifferenceInformationSet(), xPathsToOmitPredicate));
// 
//         return filteredDifferenceDetails;
//     }
// 
//     private Set<DifferenceInformation> filter(
//             Set<DifferenceInformation> differenceInformationSet, Predicate<DifferenceInformation> xPathsToOmitPredicate) {
// 
//         return differenceInformationSet.stream().filter(xPathsToOmitPredicate).collect(Collectors.toSet());
//     }
// 
//     public int getCount() {
//         return differenceInformationSet.size();
//     }
// 
//     public boolean isBestMatch() {
//         return getCount() == 0;
//     }
// }
// 
// Path: src/main/java/com/github/lukaszkusek/xml/comparator/node/INode.java
// public interface INode {
// 
//     boolean isNull();
// 
// }


import com.github.lukaszkusek.xml.comparator.node.INode;
import com.google.common.collect.ArrayTable;
import com.google.common.collect.Table;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import com.github.lukaszkusek.xml.comparator.comparators.children.cost.minimum.MinimumCostAssignmentCalculator;
import com.github.lukaszkusek.xml.comparator.diff.DifferenceDetails;
            costMatrix.put(child1, child2, CostEntry.of(differenceDetails));
        }
    }

    public void setBestMatch(INode child1, INode child2) {
        setBestMatch(child1, child2, costMatrix.get(child1, child2).getDifferenceDetails());
    }

    private void setBestMatch(INode child1, INode child2, DifferenceDetails differenceDetails) {
        takeRow(child1);
        takeColumn(child2);
        assign(child1, child2, differenceDetails);
    }

    private void takeColumn(INode child2) {
        costMatrix.rowKeyList().forEach(child1ForChild2 -> take(child1ForChild2, child2));
    }

    private void takeRow(INode child1) {
        costMatrix.columnKeyList().forEach(child2ForChild1 -> take(child1, child2ForChild1));
    }

    private void take(INode child1, INode child2) {
        costMatrix.put(child1, child2, CostEntry.taken());
    }

    private void assign(INode child1, INode child2, DifferenceDetails differenceDetails) {
        costMatrix.put(child1, child2, CostEntry.assign(differenceDetails));
    }

// Path: src/main/java/com/github/lukaszkusek/xml/comparator/comparators/children/cost/minimum/MinimumCostAssignmentCalculator.java
// public interface MinimumCostAssignmentCalculator {
//     CostMatrix getMinimumCostAssignment(CostMatrix childrenComparisonMatrix);
// }
// 
// Path: src/main/java/com/github/lukaszkusek/xml/comparator/diff/DifferenceDetails.java
// public class DifferenceDetails  {
// 
//     private Set<DifferenceInformation> differenceInformationSet;
//     private Set<DifferenceInformation> uniqueDifferenceInformationSet;
// 
//     public DifferenceDetails() {
//         differenceInformationSet = Sets.newHashSet();
//         uniqueDifferenceInformationSet = Sets.newHashSet();
//     }
// 
//     public static DifferenceDetails empty() {
//         return new DifferenceDetails();
//     }
// 
//     public static DifferenceDetails of(Node node1, Node node2, DifferenceCode differenceCode) {
//         DifferenceDetails differenceDetails = new DifferenceDetails();
//         differenceDetails.put(node1, node2, differenceCode);
// 
//         return differenceDetails;
//     }
// 
//     public DifferenceDetails put(Node node1, Node node2, DifferenceCode differenceCode) {
//         put(node1, node2, null, differenceCode);
// 
//         return this;
//     }
// 
//     public static DifferenceDetails of(Node node1, Node node2, String attributeName, DifferenceCode differenceCode) {
//         DifferenceDetails differenceDetails = new DifferenceDetails();
//         differenceDetails.put(node1, node2, attributeName, differenceCode);
// 
//         return differenceDetails;
//     }
// 
//     public DifferenceDetails put(Node node1, Node node2, String attributeName, DifferenceCode differenceCode) {
//         differenceInformationSet.add(new DifferenceInformation(node1, node2, attributeName, differenceCode));
//         uniqueDifferenceInformationSet.add(
//                 new DifferenceInformation(
//                         Optional.ofNullable(node1).map(SimpleXPathNode::new).orElse(null),
//                         Optional.ofNullable(node2).map(SimpleXPathNode::new).orElse(null),
//                         attributeName,
//                         differenceCode));
// 
//         return this;
//     }
// 
//     public DifferenceDetails putAll(DifferenceDetails differenceDetails) {
//         this.differenceInformationSet.addAll(differenceDetails.getDifferenceInformationSet());
//         this.uniqueDifferenceInformationSet.addAll(differenceDetails.getUniqueDifferenceInformationSet());
// 
//         return this;
//     }
// 
//     public Set<DifferenceInformation> getDifferenceInformationSet() {
//         return differenceInformationSet;
//     }
// 
//     public void setDifferenceInformationSet(Set<DifferenceInformation> differenceInformationSet) {
//         this.differenceInformationSet = differenceInformationSet;
//     }
// 
//     public Set<DifferenceInformation> getUniqueDifferenceInformationSet() {
//         return uniqueDifferenceInformationSet;
//     }
// 
//     public void setUniqueDifferenceInformationSet(Set<DifferenceInformation> uniqueDifferenceInformationSet) {
//         this.uniqueDifferenceInformationSet = uniqueDifferenceInformationSet;
//     }
// 
//     public DifferenceDetails filter(Predicate<DifferenceInformation> xPathsToOmitPredicate) {
//         DifferenceDetails filteredDifferenceDetails = new DifferenceDetails();
// 
//         filteredDifferenceDetails.setUniqueDifferenceInformationSet(
//                 filter(getUniqueDifferenceInformationSet(), xPathsToOmitPredicate));
// 
//         filteredDifferenceDetails.setDifferenceInformationSet(
//                 filter(getDifferenceInformationSet(), xPathsToOmitPredicate));
// 
//         return filteredDifferenceDetails;
//     }
// 
//     private Set<DifferenceInformation> filter(
//             Set<DifferenceInformation> differenceInformationSet, Predicate<DifferenceInformation> xPathsToOmitPredicate) {
// 
//         return differenceInformationSet.stream().filter(xPathsToOmitPredicate).collect(Collectors.toSet());
//     }
// 
//     public int getCount() {
//         return differenceInformationSet.size();
//     }
// 
//     public boolean isBestMatch() {
//         return getCount() == 0;
//     }
// }
// 
// Path: src/main/java/com/github/lukaszkusek/xml/comparator/node/INode.java
// public interface INode {
// 
//     boolean isNull();
// 
// }


// Path: src/main/java/com/github/lukaszkusek/xml/comparator/comparators/children/cost/CostMatrix.java
import com.github.lukaszkusek.xml.comparator.node.INode;
import com.google.common.collect.ArrayTable;
import com.google.common.collect.Table;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import com.github.lukaszkusek.xml.comparator.comparators.children.cost.minimum.MinimumCostAssignmentCalculator;
import com.github.lukaszkusek.xml.comparator.diff.DifferenceDetails;

            costMatrix.put(child1, child2, CostEntry.of(differenceDetails));
        }
    }

    public void setBestMatch(INode child1, INode child2) {
        setBestMatch(child1, child2, costMatrix.get(child1, child2).getDifferenceDetails());
    }

    private void setBestMatch(INode child1, INode child2, DifferenceDetails differenceDetails) {
        takeRow(child1);
        takeColumn(child2);
        assign(child1, child2, differenceDetails);
    }

    private void takeColumn(INode child2) {
        costMatrix.rowKeyList().forEach(child1ForChild2 -> take(child1ForChild2, child2));
    }

    private void takeRow(INode child1) {
        costMatrix.columnKeyList().forEach(child2ForChild1 -> take(child1, child2ForChild1));
    }

    private void take(INode child1, INode child2) {
        costMatrix.put(child1, child2, CostEntry.taken());
    }

    private void assign(INode child1, INode child2, DifferenceDetails differenceDetails) {
        costMatrix.put(child1, child2, CostEntry.assign(differenceDetails));
    }

    public DifferenceDetails getDifferenceDetails() {