public boolean isInstance(Object obj) {
    if (obj instanceof Values) {
      Values vals = (Values) obj;
      int pos = vals.startPos();
      int n = 0;
      if (base instanceof ItemPredicate) {
        ItemPredicate pred = (ItemPredicate) base;
        for (; ; ) {
          boolean matches;
          matches = pred.isInstancePos(vals, pos);
          pos = vals.nextPos(pos);
          if (pos == 0) {
            return n >= minOccurs && (maxOccurs < 0 || n <= maxOccurs);
          }
          if (!matches) return false;
          n++;
        }
      } else {

        for (; ; ) {
          pos = vals.nextPos(pos);
          if (pos == 0) {
            return n >= minOccurs && (maxOccurs < 0 || n <= maxOccurs);
          }
          Object value = vals.getPosPrevious(pos);
          if (!base.isInstance(value)) return false;
          n++;
        }
      }
    } else {
      if (minOccurs > 1 || maxOccurs == 0) return false;
      return base.isInstance(obj);
    }
  }
 /**
  * Return a conservative estimage on the min/max number of items of a type.
  *
  * @return {@code maxCount << 12 | minCount & 0xFFF}, where a {@code maxCount} of -1 means
  *     unbounded.
  */
 public static int itemCountRange(Type type) {
   if (type instanceof SingletonType) return (1 << 12) | 1;
   if (type instanceof OccurrenceType) {
     OccurrenceType occ = (OccurrenceType) type;
     int min = occ.minOccurs();
     int max = occ.maxOccurs();
     int bnum = itemCountRange(occ.getBase());
     if ((min == 1 && max == 1) || bnum == 0) return bnum;
     if (max > 0xfffff) max = -1;
     if (max == 0) return 0;
     int bmin = bnum & 0xfff;
     int bmax = bnum >> 12;
     if (bnum != 0x1001) {
       if (min > 0xfff) min = 0xfff;
       min = min * bmin;
       if (min > 0xfff) min = 0xfff;
       if (max < 0 || bmax < 0) max = -1;
       else max = max * bmax;
       if (max > 0xfffff) max = -1;
     }
     return (max << 12) | min;
   }
   if (type instanceof PrimType) return type.isVoid() ? 0 : 0x1001;
   if (type instanceof ArrayType) return 0x1001;
   if (type instanceof ObjectType) {
     int cmp = type.compare(Compilation.typeValues);
     if (cmp == -3) return 0x1001;
   }
   return -1 << 12;
 }
 public Object coerceFromObject(Object obj) {
   if (obj instanceof Values) {
   } else {
     // Assumes that base is an item type.  FIXME.
     if (minOccurs <= 1 && maxOccurs != 0) return base.coerceFromObject(obj);
   }
   // FIXME
   if (!isInstance(obj)) throw new ClassCastException();
   return obj;
 }
 public int compare(Type other) {
   if (other instanceof OccurrenceType) {
     OccurrenceType occOther = (OccurrenceType) other;
     if (minOccurs == occOther.minOccurs && maxOccurs == occOther.maxOccurs)
       return base.compare(occOther.getBase());
   }
   /*
   Type primeThis = itemPrimeType(getBase());
   Type primeOther = itemPrimeType(other);
   FIXME: Compare primThis with primOther AND the occurrence numbers.
   */
   return -2;
 }
 public String toString() {
   String b = base.toString();
   boolean parens = b == null || b.indexOf(' ') >= 0;
   StringBuffer sbuf = new StringBuffer();
   if (parens) sbuf.append('(');
   sbuf.append(b);
   if (parens) sbuf.append(')');
   if (minOccurs == 1 && maxOccurs == 1) ;
   else if (minOccurs == 0 && maxOccurs == 1) sbuf.append('?');
   else if (minOccurs == 1 && maxOccurs == -1) sbuf.append('+');
   else if (minOccurs == 0 && maxOccurs == -1) sbuf.append('*');
   else {
     sbuf.append('{');
     sbuf.append(minOccurs);
     sbuf.append(',');
     if (maxOccurs >= 0) sbuf.append(maxOccurs);
     else sbuf.append('*');
     sbuf.append('}');
   }
   return sbuf.toString();
 }