public class GraphContainerUtils {
  private static final Node RDFtype = RDF.type.asNode();
  private static final Node BAG = RDF.Bag.asNode();
  private static final Node ALT = RDF.Alt.asNode();
  private static final Node SEQ = RDF.Seq.asNode();
  private static final String membershipPattern = RDF.getURI() + "_(\\d+)";
  private static final int NOT_FOUND = -9999;

  public static Collection<Node> containerMembers(Graph graph, Node container) {
    return containerMembers(graph, container, null);
  }

  public static Collection<Node> containerMembers(Graph graph, Node container, Node containerType) {
    if (!isContainer(graph, container, containerType)) return null;

    ExtendedIterator<Triple> iter = graph.find(container, Node.ANY, Node.ANY);

    SortedMap<Integer, Node> triples = new TreeMap<Integer, Node>(order);
    try {
      for (; iter.hasNext(); ) {
        Triple t = iter.next();
        int index = getIndex(t);
        if (index == NOT_FOUND) continue;
        // Insert
        triples.put(new Integer(index), t.getObject());
      }
    } finally {
      iter.close();
    }
    return triples.values();
  }

  //            List x = new ArrayList() ;
  //            try {
  //              for ( ; iter.hasNext() ; )
  //              {
  //                  // Sort triples in a sorted set.
  //                  // Then extract.
  //                  Triple t = (Triple)iter.next() ;
  //                  String p = t.getPredicate().getURI() ;
  //
  //                  if ( p.matches(membershipPattern) )
  //                      x.add(t.getObject()) ;
  //              }
  //          } finally { iter.close() ; }
  //          return x ;
  //      }

  public static boolean isContainerMember(
      Graph graph, Node container, Node containerType, Node member) {
    return countContainerMember(graph, container, containerType, member, true) != 0;
  }

  public static int countContainerMember(
      Graph graph, Node container, Node containerType, Node member) {
    return countContainerMember(graph, container, containerType, member, false);
  }

  private static int countContainerMember(
      Graph graph, Node container, Node containerType, Node member, boolean stopEarly) {
    if (graph == null) {
      Log.warn(GraphContainerUtils.class, "containerMember called with null graph");
      return 0;
    }

    if (container == null) {
      Log.warn(GraphContainerUtils.class, "containerMember called with null list");
      return 0;
    }
    if (member == null) {
      Log.warn(GraphContainerUtils.class, "containerMember called with null member");
      return 0;
    }

    if (!isContainer(graph, container, containerType)) return 0;

    int count = 0;
    ExtendedIterator<Triple> iter = graph.find(container, Node.ANY, member);
    try {
      for (; iter.hasNext(); ) {
        Triple t = iter.next();
        Node p = t.getPredicate();
        String u = p.getURI();

        if (u.matches(membershipPattern)) {
          count++;
          if (stopEarly) return count;
        }
      }
    } finally {
      iter.close();
    }
    return count;
  }

  //    public static boolean isContainer(Graph graph, Node container)
  //    { return isContainer(graph, container, null) ; }

  public static boolean isContainer(Graph graph, Node container, Node containerType) {
    //        if ( container.isLiteral() )
    //            return false ;

    if (containerType == null)
      return isContainer(graph, container, BAG)
          || isContainer(graph, container, ALT)
          || isContainer(graph, container, SEQ);

    return graph.contains(container, RDFtype, containerType);
  }

  static Pattern pattern = Pattern.compile(membershipPattern);

  private static int getIndex(Triple triple) {
    String u = triple.getPredicate().getURI();
    // Must be _nnn.
    Matcher m = pattern.matcher(u);
    if (!m.find()) return NOT_FOUND;
    String index = m.group(1);
    return Integer.parseInt(index);
  }

  static ContainerOrder order = new ContainerOrder();

  private static class ContainerOrder implements java.util.Comparator<Integer> {
    public int compare(Integer i1, Integer i2) {
      int index1 = i1.intValue();
      int index2 = i2.intValue();

      if (index1 < index2) return Expr.CMP_LESS;
      if (index1 > index2) return Expr.CMP_GREATER;
      return Expr.CMP_EQUAL;
    }
  }
}
 public alt() {
   super(RDF.Alt.asNode());
 }