// Path: src/main/java/org/edmcouncil/rdf_toolkit/comparator/ComparisonUtils.java
// public static int compareSimpleValue(Literal literal1, Literal literal2) {
//   // TODO: support natural ordering of non-string literals
//   int cmp = literal1.stringValue().compareTo(literal2.stringValue());
//   if (cmp != 0) {
//     return cmp;
//   } else {
//     if (literal1.getLanguage().isPresent()) {
//       if (literal2.getLanguage().isPresent()) {
//         int cmp2 = literal1.getLanguage().toString().compareTo(literal2.getLanguage().toString());
//         if (cmp2 != 0) {
//           return cmp2;
//         }
//       } else { // !literal2.getLanguage().isPresent()
//         return -1; // literal1 with language comes before literal2 without language
//       }
//     } else { // !literal1.getLanguage().isPresent()
//       if (literal2.getLanguage().isPresent()) {
//         return 1; // literal1 without language comes after literal2 with language
//       } else { // !literal2.getLanguage().isPresent()
//         // neither literal has a language to compare
//       }
//     }
//     if (literal1.getDatatype() != null) {
//       if (literal2.getDatatype() != null) {
//         int cmp2 = literal1.getDatatype().stringValue().compareTo(literal2.getDatatype().stringValue());
//         if (cmp2 != 0) {
//           return cmp2;
//         }
//       } else { // literal2.getDatatype() == null
//         return -1; // literal1 with data type comes before literal2 without data type
//       }
//     } else { // literal1.getDatatype() == null
//       if (literal2.getDatatype() != null) {
//         return 1; // literal1 without data type comes after literal2 with data type
//       } else { // literal2.getDatatype().isPresent() == null
//         // neither literal has a data type to compare
//       }
//     }
//     return 0; // no difference in value, language nor datatype
//   }
// }


import java.util.List;
import static org.edmcouncil.rdf_toolkit.comparator.ComparisonUtils.compareSimpleValue;
import org.eclipse.rdf4j.model.BNode;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
import java.util.ArrayList;
import java.util.Comparator;
      } else {
        return -1; // null/excluded value comes before non-null/excluded value
      }
    } else {
      if ((value2 == null) || excludedList.contains(value2)) {
        return 1; // non-null/excluded value comes before null/excluded value
      }
    }

    return compareExistingValues(value1, value2, excludedList);
  }

  public int compareExistingValues(Value value1, Value value2, List<Object> excludedList) {
    // We assume here that both blank nodes are non-null/excluded
    if (value1 == null || value2 == null || excludedList.contains(value1) || excludedList.contains(value2)) {
      throw new IllegalStateException("value1 and value2 should not be null or in the excluded list.");
    }

    // Order blank nodes so that they come after other values.
    if (value1 instanceof BNode) {
      if (value2 instanceof BNode) {
        return compareTwoBlankNodes((BNode) value1, (BNode) value2, excludedList);
      } else {
        return 1; // blank node value1 comes after value2.
      }
    } else {
      if (value2 instanceof BNode) {
        return -1; // value1 comes before blank node value2.
      } else { // compare non-blank-node values.
        if ((value1 instanceof Literal) && (value2 instanceof Literal)) {
// Path: src/main/java/org/edmcouncil/rdf_toolkit/comparator/ComparisonUtils.java
// public static int compareSimpleValue(Literal literal1, Literal literal2) {
//   // TODO: support natural ordering of non-string literals
//   int cmp = literal1.stringValue().compareTo(literal2.stringValue());
//   if (cmp != 0) {
//     return cmp;
//   } else {
//     if (literal1.getLanguage().isPresent()) {
//       if (literal2.getLanguage().isPresent()) {
//         int cmp2 = literal1.getLanguage().toString().compareTo(literal2.getLanguage().toString());
//         if (cmp2 != 0) {
//           return cmp2;
//         }
//       } else { // !literal2.getLanguage().isPresent()
//         return -1; // literal1 with language comes before literal2 without language
//       }
//     } else { // !literal1.getLanguage().isPresent()
//       if (literal2.getLanguage().isPresent()) {
//         return 1; // literal1 without language comes after literal2 with language
//       } else { // !literal2.getLanguage().isPresent()
//         // neither literal has a language to compare
//       }
//     }
//     if (literal1.getDatatype() != null) {
//       if (literal2.getDatatype() != null) {
//         int cmp2 = literal1.getDatatype().stringValue().compareTo(literal2.getDatatype().stringValue());
//         if (cmp2 != 0) {
//           return cmp2;
//         }
//       } else { // literal2.getDatatype() == null
//         return -1; // literal1 with data type comes before literal2 without data type
//       }
//     } else { // literal1.getDatatype() == null
//       if (literal2.getDatatype() != null) {
//         return 1; // literal1 without data type comes after literal2 with data type
//       } else { // literal2.getDatatype().isPresent() == null
//         // neither literal has a data type to compare
//       }
//     }
//     return 0; // no difference in value, language nor datatype
//   }
// }


// Path: src/main/java/org/edmcouncil/rdf_toolkit/comparator/ValueComparator.java
import java.util.List;
import static org.edmcouncil.rdf_toolkit.comparator.ComparisonUtils.compareSimpleValue;
import org.eclipse.rdf4j.model.BNode;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
import java.util.ArrayList;
import java.util.Comparator;

      } else {
        return -1; // null/excluded value comes before non-null/excluded value
      }
    } else {
      if ((value2 == null) || excludedList.contains(value2)) {
        return 1; // non-null/excluded value comes before null/excluded value
      }
    }

    return compareExistingValues(value1, value2, excludedList);
  }

  public int compareExistingValues(Value value1, Value value2, List<Object> excludedList) {
    // We assume here that both blank nodes are non-null/excluded
    if (value1 == null || value2 == null || excludedList.contains(value1) || excludedList.contains(value2)) {
      throw new IllegalStateException("value1 and value2 should not be null or in the excluded list.");
    }

    // Order blank nodes so that they come after other values.
    if (value1 instanceof BNode) {
      if (value2 instanceof BNode) {
        return compareTwoBlankNodes((BNode) value1, (BNode) value2, excludedList);
      } else {
        return 1; // blank node value1 comes after value2.
      }
    } else {
      if (value2 instanceof BNode) {
        return -1; // value1 comes before blank node value2.
      } else { // compare non-blank-node values.
        if ((value1 instanceof Literal) && (value2 instanceof Literal)) {
          return compareSimpleValue((Literal) value1, (Literal) value2);