/**
   * Answer the lowest common ancestor of two classes in a given ontology. This is the class that is
   * farthest from the root concept (defaulting to <code>owl:Thing</code> which is a super-class of
   * both <code>u</code> and <code>v</code>. The algorithm is based on <a
   * href="http://en.wikipedia.org/wiki/Tarjan's_off-line_least_common_ancestors_algorithm">Tarjan's
   * off-line LCA</a>. The current implementation expects that the given model:
   *
   * <ul>
   *   <li>is transitively closed over the <code>subClassOf</code> relation
   *   <li>can cheaply determine <em>direct sub-class</em> relations
   * </ul>
   *
   * <p>Both of these conditions are true of the built-in Jena OWL reasoners, such as {@link
   * OntModelSpec#OWL_MEM_MICRO_RULE_INF}, and external DL reasoners such as Pellet.
   *
   * @param m The ontology model being queried to find the LCA, which should conform to the reasoner
   *     capabilities described above
   * @param u An ontology class
   * @param v An ontology class
   * @return The LCA of <code>u</code> and <code>v</code>
   * @exception JenaException if the language profile of the given model does not define a top
   *     concept (e.g. <code>owl:Thing</code>)
   */
  public static OntClass getLCA(OntModel m, OntClass u, OntClass v) {
    Resource root = m.getProfile().THING();
    if (root == null) {
      throw new JenaException(
          "The given OntModel has a language profile that does not define a generic root class (such as owl:Thing)");
    }

    root = root.inModel(m);
    return getLCA(m, root.as(OntClass.class), u, v);
  }
  /**
   * Answer a list of the named hierarchy roots of a given {@link OntModel}. This will be similar to
   * the results of {@link OntModel#listHierarchyRootClasses()}, with the added constraint that
   * every member of the returned iterator will be a named class, not an anonymous class expression.
   * The named root classes are calculated from the root classes, by recursively replacing every
   * anonymous class with its direct sub-classes. Thus it can be seen that the values in the list
   * consists of the shallowest fringe of named classes in the hierarchy.
   *
   * @param m An ontology model
   * @return A list of classes whose members are the named root classes of the class hierarchy in
   *     <code>m</code>
   */
  public static List<OntClass> namedHierarchyRoots(OntModel m) {
    List<OntClass> nhr = new ArrayList<OntClass>(); // named roots
    List<OntClass> ahr = new ArrayList<OntClass>(); // anon roots

    // do the initial partition of the root classes
    partitionByNamed(m.listHierarchyRootClasses(), nhr, ahr);

    // now push the fringe down until we have only named classes
    while (!ahr.isEmpty()) {
      OntClass c = ahr.remove(0);
      partitionByNamed(c.listSubClasses(true), nhr, ahr);
    }

    return nhr;
  }