package com.thaiopensource.xml.infer;

import org.relaxng.datatype.DatatypeLibrary;
import org.relaxng.datatype.Datatype;
import org.relaxng.datatype.DatatypeException;
import org.relaxng.datatype.DatatypeLibraryFactory;
import com.thaiopensource.util.Uri;
import com.thaiopensource.xml.util.WellKnownNamespaces;

public class DatatypeRepertoire {
  static private final int TOKEN_TYPICAL_MAX_LENGTH = 32;
  static private final int BINARY_TYPICAL_MIN_LENGTH = 128;

  static private final String[] typeNames = {
    "boolean",
    // XXX add int?
    "integer",
    "decimal",
    "double",
    "NCName",
    "NMTOKEN",
    "time",
    "date",
    "dateTime",
    "duration",
    "hexBinary",
    "base64Binary",
    "anyURI"
  };

  static public class Type {
    private final Datatype dt;
    private final String name;
    private final int index;

    private Type(Datatype dt, String name, int index) {
      this.dt = dt;
      this.name = name;
      this.index = index;
    }

    public boolean matches(String value) {
      return dt.isValid(value, null);
    }

    public boolean isTypical(String value) {
      return value.length() < TOKEN_TYPICAL_MAX_LENGTH;
    }

    public String getName() {
      return name;
    }

    public int getIndex() {
      return index;
    }
  }

  static public class BinaryType extends Type {
    private BinaryType(Datatype dt, String name, int index) {
      super(dt, name, index);
    }

    public boolean isTypical(String value) {
      return value.length() > BINARY_TYPICAL_MIN_LENGTH;
    }
  }

  static public class UriType extends Type {
    private UriType(Datatype dt, String name, int index) {
      super(dt, name, index);
    }

    public boolean isTypical(String value) {
      return Uri.isAbsolute(value);
    }

  }

  private final Type[] types = new Type[typeNames.length];
  private int nTypes = 0;

  DatatypeRepertoire(DatatypeLibraryFactory factory) {
    DatatypeLibrary lib = factory.createDatatypeLibrary(WellKnownNamespaces.XML_SCHEMA_DATATYPES);
    if (lib == null)
      return;
    for (int i = 0; i < types.length; i++) {
      try {
        types[nTypes] = makeType(typeNames[i],
                                 lib.createDatatype(typeNames[i]),
                                 i);
        nTypes++;
      }
      catch (DatatypeException e) {
      }
    }
  }

  public int size() {
    return nTypes;
  }

  Type get(int i) {
    return types[i];
  }

  static private Type makeType(String typeName, Datatype dt, int index) {
    if (typeName.equals("anyURI"))
      return new UriType(dt, typeName, index);
    else if (typeName.equals("base64Binary") || typeName.equals("hexBinary"))
      return new BinaryType(dt, typeName, index);
    return new Type(dt, typeName, index);
  }

  public static String getUri() {
    return WellKnownNamespaces.XML_SCHEMA_DATATYPES;
  }
}

@@ -1297,29 +1297,30 @@
 %0A%0A  static p
-ublic
+rivate
  class Binar
@@ -1558,29 +1558,30 @@
 %0A%0A  static p
-ublic
+rivate
  class UriTy
@@ -1787,16 +1787,310 @@
 %7D%0A%0A  %7D%0A%0A
+  static private class BooleanType extends Type %7B%0A    private BooleanType(Datatype dt, String name, int index) %7B%0A      super(dt, name, index);%0A    %7D%0A%0A    public boolean isTypical(String value) %7B%0A      value = value.trim();%0A      return value.equals(%22true%22) %7C%7C value.equals(%22false%22);%0A    %7D%0A  %7D%0A%0A
   privat
@@ -2901,12 +2901,94 @@
     
-else
+if (typeName.equals(%22boolean%22))%0A      return new BooleanType(dt, typeName, index);%0A   
  if 

Recognize only true and false for boolean