/**
 * Base class for type objects.
 *
 * <p>
 *
 * @author fredt@users
 * @version 1.9.0
 * @since 1.9.0
 */
public abstract class Type {

  public final int type;
  final long precision;
  final int scale;

  Type(int type, long precision, int scale) {

    this.type = type;
    this.precision = (int) precision;
    this.scale = scale;
  }

  public long size() {
    return precision;
  }

  public int scale() {
    return scale;
  }

  public abstract int displaySize();

  /** Returns the JDBC type number of type, if it exists, otherwise the HSQLDB / SQL type. */
  public abstract int getJDBCTypeNumber();

  /** Returns the JDBC class name of type, if it exists, otherwise the HSQLDB class name. */
  public abstract String getJDBCClassName();

  /**
   * Returns the generic SQL CLI type number of type, if it exists, otherwise the HSQLDB type. The
   * generic type is returned for DATETIME and INTERVAL types.
   */
  public abstract int getSQLGenericTypeNumber();

  /** Returns the specific SQL CLI type number of type, if it exists, otherwise the HSQLDB type */
  public abstract int getSQLSpecificTypeNumber();

  /** Returns the name of the type */
  public abstract String getName();

  /** Returns the full definition of the type, including parameters */
  public abstract String getDefinition();

  public abstract int compare(Object a, Object b);

  public abstract Object convertToTypeLimits(Object a) throws HsqlException;

  /**
   * Explicit casts are handled by this method. SQL standard 6.12 rules for enforcement of size,
   * precision and scale are implemented. For CHARACTER values, it performs truncation in all cases
   * of long strings.
   */
  public Object castToType(Session session, Object a, Type type) throws HsqlException {
    return convertToType(session, a, type);
  }

  /**
   * Same as castToType except for CHARACTER values. Perform string truncation of trailing spaces
   * only. For other long strings, it raises an exception.
   */
  public abstract Object convertToType(Session session, Object a, Type type) throws HsqlException;

  /** Converts the object to the given type. Used for JDBC conversions. */
  public abstract Object convertToDefaultType(Object o) throws HsqlException;

  public abstract String convertToString(Object a);

  public abstract String convertToSQLString(Object a);

  public boolean isCharacterType() {
    return false;
  }

  public boolean isNumberType() {
    return false;
  }

  public boolean isIntegralType() {
    return false;
  }

  public boolean isDateTimeType() {
    return false;
  }

  public boolean isIntervalType() {
    return false;
  }

  public boolean isBinaryType() {
    return false;
  }

  public boolean isBooleanType() {
    return false;
  }

  public boolean isLobType() {
    return false;
  }

  public boolean acceptsPrecision() {
    return false;
  }

  public boolean requiresPrecision() {
    return false;
  }

  public boolean acceptsFractionalPrecision() {
    return false;
  }

  public boolean acceptsScale() {
    return false;
  }

  /** Common type used in comparison opertions. other must be comparable with this. */
  public abstract Type getAggregateType(Type other) throws HsqlException;

  /**
   * Result type of combining values of two types in different opertions. other type is not allways
   * comparable with this, but a operation should be valid without any explicit CAST
   */
  public abstract Type getCombinedType(Type other, int operation) throws HsqlException;

  public int compareToTypeRange(Object o) {
    return 0;
  }

  /** All arithmetic ops are called on the pre-determined Type object of the result */
  public Object add(Object a, Object b) throws HsqlException {
    throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type");
  }

  public Object subtract(Object a, Object b) throws HsqlException {
    throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type");
  }

  public Object multiply(Object a, Object b) throws HsqlException {
    throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type");
  }

  public Object divide(Object a, Object b) throws HsqlException {
    throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type");
  }

  public Object concat(Session session, Object a, Object b) throws HsqlException {
    throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type");
  }

  public boolean equals(Object other) {

    if (other instanceof Type) {
      return ((Type) other).type == type
          && ((Type) other).precision == precision
          && ((Type) other).scale == scale;
    }

    return false;
  }

  // null type
  public static final Type SQL_ALL_TYPES = NullType.getNullType();

  // character types
  public static final Type SQL_CHAR = new CharacterType(Types.SQL_CHAR, 0);
  public static final Type SQL_VARCHAR = new CharacterType(Types.SQL_VARCHAR, 0);
  public static final Type SQL_VARCHAR_MAX_WIDTH =
      new CharacterType(
          Types.SQL_VARCHAR,
          0); // todo - needs max implementation defined width. used for parameters
  public static final ClobType SQL_CLOB = new ClobType();
  public static final Type VARCHAR_IGNORECASE = new CharacterType(Types.VARCHAR_IGNORECASE, 0);

  // binary types
  public static final BinaryType SQL_BINARY = new BinaryType(Types.SQL_BINARY, 0);
  public static final BinaryType SQL_VARBINARY = new BinaryType(Types.SQL_VARBINARY, 0);
  public static final BlobType SQL_BLOB = new BlobType();

  // other type
  public static final OtherType OTHER = OtherType.getOtherType();

  // boolean type
  public static final BooleanType SQL_BOOLEAN = BooleanType.getBooleanType();

  // number types
  public static final NumberType SQL_NUMERIC =
      new NumberType(Types.SQL_NUMERIC, NumberType.defaultNumericPrecision, 0);
  public static final NumberType SQL_DECIMAL =
      new NumberType(Types.SQL_DECIMAL, NumberType.defaultNumericPrecision, 0);
  public static final NumberType SQL_DOUBLE = new NumberType(Types.SQL_DOUBLE, 0, 0);

  //
  public static final NumberType TINYINT =
      new NumberType(Types.TINYINT, NumberType.tinyintPrecision, 0);
  public static final NumberType SQL_SMALLINT =
      new NumberType(Types.SQL_SMALLINT, NumberType.smallintPrecision, 0);
  public static final NumberType SQL_INTEGER =
      new NumberType(Types.SQL_INTEGER, NumberType.integerPrecision, 0);
  public static final NumberType SQL_BIGINT =
      new NumberType(Types.SQL_BIGINT, NumberType.bigintPrecision, 0);

  // date time
  public static final DateTimeType SQL_DATE =
      new DateTimeType(Types.SQL_DATE, DateTimeType.defaultDatetimeFractionPrecision);
  public static final DateTimeType SQL_TIME =
      new DateTimeType(Types.SQL_TIME, DateTimeType.defaultDatetimeFractionPrecision);
  public static final DateTimeType SQL_TIMESTAMP =
      new DateTimeType(Types.SQL_TIMESTAMP, DateTimeType.defaultDatetimeFractionPrecision);

  // interval
  public static final IntervalType SQL_INTERVAL_YEAR =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_YEAR, IntervalType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_MONTH =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_MONTH, IntervalType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_DAY =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_DAY, IntervalType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_HOUR =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_HOUR, IntervalType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_MINUTE =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_MINUTE, IntervalType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_SECOND =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_SECOND,
          IntervalType.defaultIntervalPrecision,
          IntervalType.defaultIntervalFractionPrecision);
  public static final IntervalType SQL_INTERVAL_YEAR_TO_MONTH =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_YEAR_TO_MONTH, IntervalType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_DAY_TO_HOUR =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_DAY_TO_HOUR, IntervalType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_DAY_TO_MINUTE =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_DAY_TO_MINUTE, IntervalType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_DAY_TO_SECOND =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_DAY_TO_SECOND,
          IntervalType.defaultIntervalPrecision,
          IntervalType.defaultIntervalFractionPrecision);
  public static final IntervalType SQL_INTERVAL_HOUR_TO_MINUTE =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_HOUR_TO_MINUTE, IntervalType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_HOUR_TO_SECOND =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_HOUR_TO_SECOND,
          IntervalType.defaultIntervalPrecision,
          IntervalType.defaultIntervalFractionPrecision);
  public static final IntervalType SQL_INTERVAL_MINUTE_TO_SECOND =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_MINUTE_TO_SECOND,
          IntervalType.defaultIntervalPrecision,
          IntervalType.defaultIntervalFractionPrecision);

  /** For literals */
  public static Type getValueType(int type, Object value) {

    long precision = 0;
    int scale = 0;

    if (value != null) {
      switch (type) {
        case Types.SQL_INTEGER:
        case Types.SQL_BIGINT:
        case Types.SQL_DOUBLE:
        case Types.SQL_BOOLEAN:
        case Types.SQL_ALL_TYPES:
          break;

        case Types.SQL_CHAR:
          precision = value.toString().length();
          break;

        case Types.SQL_BINARY:
          precision = ((BinaryData) value).length();
          break;

        case Types.SQL_NUMERIC:
          precision = JavaSystem.precision((BigDecimal) value);
          scale = ((BigDecimal) value).scale();
          break;

        default:
          throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type");
      }
    }

    try {
      return getType(type, 0, precision, scale);
    } catch (HsqlException e) {

      // exception should never be thrown
      throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type");
    }
  }

  public static Type getDefaultType(int type) {

    try {
      return getType(type, 0, 0, 0);
    } catch (HsqlException e) {

      // exception should never be thrown
      throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type");
    }
  }

  public static int getHSQLDBTypeCode(int jdbcTypeNumber) throws HsqlException {

    switch (jdbcTypeNumber) {
      case Types.BIGINT:
        return Types.SQL_BIGINT;

      case Types.LONGVARCHAR:
        return Types.SQL_VARCHAR;

      case Types.CLOB:
        return Types.SQL_CLOB;

      case Types.BINARY:
        return Types.SQL_BINARY;

      case Types.VARBINARY:
      case Types.LONGVARBINARY:
        return Types.SQL_VARBINARY;

      case Types.BLOB:
        return Types.SQL_BLOB;

      default:
        return jdbcTypeNumber;
    }
  }

  /**
   * translate an internal type number to JDBC type number if a type is not supported internally, it
   * is returned without translation
   *
   * @param i int
   * @return int
   */
  public static int getJDBCTypeCode(int type) {

    switch (type) {
      case Types.SQL_BLOB:
        return Types.BLOB;

      case Types.SQL_CLOB:
        return Types.CLOB;

      case Types.SQL_BIGINT:
        return Types.BIGINT;

      case Types.SQL_BINARY:
        return Types.BINARY;

      case Types.SQL_VARBINARY:
        return Types.VARBINARY;

      default:
        return type;
    }
  }

  /** Enforces precision and scale limits on type */
  public static Type getType(int type, int collation, long precision, int scale)
      throws HsqlException {

    switch (type) {
      case Types.SQL_ALL_TYPES:
        return null;

        //                return SQL_ALL_TYPES; // needs changes to Expression type resolution
      case Types.SQL_CHAR:
      case Types.SQL_VARCHAR:
      case Types.VARCHAR_IGNORECASE:
      case Types.SQL_CLOB:
        return CharacterType.getCharacterType(type, precision);

      case Types.SQL_INTEGER:
        return SQL_INTEGER;

      case Types.SQL_SMALLINT:
        return SQL_SMALLINT;

      case Types.SQL_BIGINT:
        return SQL_BIGINT;

      case Types.TINYINT:
        return TINYINT;

      case Types.SQL_FLOAT:
        if (precision > 53) {
          throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE, "" + precision);
        }
      case Types.SQL_REAL:
      case Types.SQL_DOUBLE:
        return SQL_DOUBLE;

      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
        if (precision == 0) {
          precision = NumberType.defaultNumericPrecision;
        }

        return NumberType.getNumberType(type, precision, scale);

      case Types.SQL_BOOLEAN:
        return SQL_BOOLEAN;

      case Types.SQL_BINARY:
      case Types.SQL_VARBINARY:
      case Types.SQL_BLOB:
        return BinaryType.getBinaryType(type, precision);

      case Types.SQL_DATE:
      case Types.SQL_TIME:
      case Types.SQL_TIMESTAMP:
        return DateTimeType.getDateTimeType(type, scale);

      case Types.SQL_INTERVAL_YEAR:
      case Types.SQL_INTERVAL_YEAR_TO_MONTH:
      case Types.SQL_INTERVAL_MONTH:
      case Types.SQL_INTERVAL_DAY:
      case Types.SQL_INTERVAL_DAY_TO_HOUR:
      case Types.SQL_INTERVAL_DAY_TO_MINUTE:
      case Types.SQL_INTERVAL_DAY_TO_SECOND:
      case Types.SQL_INTERVAL_HOUR:
      case Types.SQL_INTERVAL_HOUR_TO_MINUTE:
      case Types.SQL_INTERVAL_HOUR_TO_SECOND:
      case Types.SQL_INTERVAL_MINUTE:
      case Types.SQL_INTERVAL_MINUTE_TO_SECOND:
      case Types.SQL_INTERVAL_SECOND:
        return IntervalType.getIntervalType(type, precision, scale);

      case Types.OTHER:
        return OTHER;

      default:
        throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type");
    }
  }

  public static Type getAggregatedType(Type add, Type existing) throws HsqlException {

    if (existing == null || existing.type == Types.SQL_ALL_TYPES) {
      return add;
    }

    if (add == null || add.type == Types.SQL_ALL_TYPES) {
      return existing;
    }

    return existing.getAggregateType(add);
  }

  public static IntValueHashMap typeAliases;
  public static IntValueHashMap typeNames;

  static {
    typeNames = new IntValueHashMap(37);

    typeNames.put("CHARACTER", Types.SQL_CHAR);
    typeNames.put("VARCHAR", Types.SQL_VARCHAR);
    typeNames.put("VARCHAR_IGNORECASE", Types.VARCHAR_IGNORECASE);
    typeNames.put("DATE", Types.SQL_DATE);
    typeNames.put("TIME", Types.SQL_TIME);
    typeNames.put("TIMESTAMP", Types.SQL_TIMESTAMP);
    typeNames.put("INTERVAL", Types.SQL_INTERVAL);
    typeNames.put("TINYINT", Types.TINYINT);
    typeNames.put("SMALLINT", Types.SQL_SMALLINT);
    typeNames.put("INTEGER", Types.SQL_INTEGER);
    typeNames.put("BIGINT", Types.SQL_BIGINT);
    typeNames.put("REAL", Types.SQL_REAL);
    typeNames.put("FLOAT", Types.SQL_FLOAT);
    typeNames.put("DOUBLE", Types.SQL_DOUBLE);
    typeNames.put("NUMERIC", Types.SQL_NUMERIC);
    typeNames.put("DECIMAL", Types.SQL_DECIMAL);
    typeNames.put("BOOLEAN", Types.SQL_BOOLEAN);
    typeNames.put("BINARY", Types.SQL_BINARY);
    typeNames.put("VARBINARY", Types.SQL_VARBINARY);
    typeNames.put("CLOB", Types.SQL_CLOB);
    typeNames.put("BLOB", Types.SQL_BLOB);
    typeNames.put("OTHER", Types.OTHER);

    //
    typeAliases = new IntValueHashMap(67, 1);

    typeAliases.put("CHAR", Types.SQL_CHAR);
    typeAliases.put("CHAR VARYING", Types.SQL_VARCHAR);
    typeAliases.put("CHARACTER VARYING", Types.SQL_VARCHAR);
    typeAliases.put("CHARACTER LARGE OBJECT", Types.SQL_CLOB);
    typeAliases.put("INT", Types.SQL_INTEGER);
    typeAliases.put("DEC", Types.SQL_DECIMAL);
    typeAliases.put("LONGVARCHAR", Types.SQL_VARCHAR);
    typeAliases.put("DATETIME", Types.SQL_TIMESTAMP);
    typeAliases.put("BIT", Types.SQL_BOOLEAN);
    typeAliases.put("LONGVARBINARY", Types.SQL_VARBINARY);
    typeAliases.put("OBJECT", Types.OTHER);
  }

  public static int getTypeNr(String name) throws HsqlException {

    int i = typeNames.get(name, Integer.MIN_VALUE);

    if (i == Integer.MIN_VALUE) {
      i = typeAliases.get(name, Integer.MIN_VALUE);
    }

    if (i == Integer.MIN_VALUE) {
      throw Trace.error(Trace.WRONG_DATA_TYPE, name);
    }

    return i;
  }

  /**
   * convertJavaToSQLType
   *
   * @param value Object
   * @param dataType Type
   * @return Object
   */
  public static Object convertJavaToSQLType(Object a, Type dataType) {

    if (a instanceof byte[]) {
      return new BinaryData((byte[]) a, false);
    } else if (a instanceof java.sql.Time) {
      return new TimeData(((java.sql.Time) a).getTime());
    }

    return a;
  }

  public static boolean isSupportedSQLType(int typeNumber) {

    try {
      if (getDefaultType(typeNumber) != null) {
        return true;
      }
    } catch (RuntimeException e) {
      return false;
    }

    return false;
  }
}
Beispiel #2
0
/**
 * Base class for type objects.
 *
 * <p>
 *
 * @author Fred Toussi (fredt@users dot sourceforge.net)
 * @version 1.9.0
 * @since 1.9.0
 */
public abstract class Type implements SchemaObject, Cloneable {

  public static final Type[] emptyArray = new Type[] {};

  //
  public final int typeComparisonGroup;
  public final int typeCode;
  public final long precision;
  public final int scale;
  public UserTypeModifier userTypeModifier;

  //
  public static final int defaultArrayCardinality = 1024;

  //
  Type(int typeGroup, int type, long precision, int scale) {

    this.typeComparisonGroup = typeGroup;
    this.typeCode = type;
    this.precision = precision;
    this.scale = scale;
  }

  // interface specific methods
  public final int getType() {

    if (userTypeModifier == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }

    return userTypeModifier.getType();
  }

  public final HsqlName getName() {

    if (userTypeModifier == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }

    return userTypeModifier.getName();
  }

  public final HsqlName getCatalogName() {

    if (userTypeModifier == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }

    return userTypeModifier.getSchemaName().schema;
  }

  public final HsqlName getSchemaName() {

    if (userTypeModifier == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }

    return userTypeModifier.getSchemaName();
  }

  public final Grantee getOwner() {

    if (userTypeModifier == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }

    return userTypeModifier.getOwner();
  }

  public final OrderedHashSet getReferences() {

    if (userTypeModifier == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }

    return userTypeModifier.getReferences();
  }

  public final OrderedHashSet getComponents() {

    if (userTypeModifier == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }

    return userTypeModifier.getComponents();
  }

  public final void compile(Session session, SchemaObject parentObject) {

    if (userTypeModifier == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }

    userTypeModifier.compile(session);
  }

  /**
   * Retrieves the SQL character sequence required to (re)create the trigger, as a StringBuffer
   *
   * @return the SQL character sequence required to (re)create the trigger
   */
  public String getSQL() {

    if (userTypeModifier == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }

    return userTypeModifier.getSQL();
  }

  public long getChangeTimestamp() {
    return 0;
  }

  public Type duplicate() {

    try {
      return (Type) super.clone();
    } catch (CloneNotSupportedException e) {
      throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }
  }

  public abstract int displaySize();

  /** Returns the JDBC type number of type, if it exists, otherwise the HSQLDB / SQL type. */
  public abstract int getJDBCTypeCode();

  /** Returns the JDBC class name of type, if it exists, otherwise the HSQLDB class name. */
  public abstract String getJDBCClassName();

  public abstract Class getJDBCClass();

  public Integer getJDBCScale() {
    return acceptsScale() ? ValuePool.getInt(scale) : null;
  }

  public int getJDBCPrecision() {
    return precision > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) precision;
  }

  /**
   * Returns the generic SQL CLI type number of type, if it exists, otherwise the HSQLDB type. The
   * generic type is returned for DATETIME and INTERVAL types.
   */
  public int getSQLGenericTypeCode() {
    return typeCode;
  }

  /** Returns the name of the type */
  public abstract String getNameString();

  /** Returns the name of the type */
  public String getFullNameString() {
    return getNameString();
  }

  /** Returns the full definition of the type, including parameters */
  abstract String getDefinition();

  public final String getTypeDefinition() {

    if (userTypeModifier == null) {
      return getDefinition();
    }

    return getName().getSchemaQualifiedStatementName();
  }

  public abstract int compare(Session session, Object a, Object b);

  public abstract Object convertToTypeLimits(SessionInterface session, Object a);

  /**
   * Explicit casts are handled by this method. SQL standard 6.12 rules for enforcement of size,
   * precision and scale are implemented. For CHARACTER values, it performs truncation in all cases
   * of long strings.
   */
  public Object castToType(SessionInterface session, Object a, Type type) {
    return convertToType(session, a, type);
  }

  /**
   * Same as castToType except for CHARACTER values. Perform string truncation of trailing spaces
   * only. For other long strings, it raises an exception.
   */
  public abstract Object convertToType(SessionInterface session, Object a, Type type);

  /**
   * Convert type for JDBC reads. Same as convertToType, but supports non-standard SQL conversions
   * supported by JDBC
   */
  public Object convertToTypeJDBC(SessionInterface session, Object a, Type otherType) {

    if (otherType.isLobType()) {
      throw Error.error(ErrorCode.X_42561);
    }

    return convertToType(session, a, otherType);
  }

  public Object convertJavaToSQL(SessionInterface session, Object a) {
    return a;
  }

  public Object convertSQLToJava(SessionInterface session, Object a) {
    return a;
  }

  /** Converts the object to the given type without limit checks. Used for JDBC writes. */
  public abstract Object convertToDefaultType(SessionInterface sessionInterface, Object o);

  public abstract String convertToString(Object a);

  public abstract String convertToSQLString(Object a);

  public abstract boolean canConvertFrom(Type otherType);

  public boolean canBeAssignedFrom(Type otherType) {

    return otherType == null ? true : this.typeComparisonGroup == otherType.typeComparisonGroup;
  }

  public int arrayLimitCardinality() {
    return 0;
  }

  public Type collectionBaseType() {
    return null;
  }

  public boolean isArrayType() {
    return false;
  }

  public boolean isMultisetType() {
    return false;
  }

  public boolean isRowType() {
    return false;
  }

  public boolean isStructuredType() {
    return false;
  }

  public boolean isCharacterType() {
    return false;
  }

  public boolean isNumberType() {
    return false;
  }

  public boolean isIntegralType() {
    return false;
  }

  public boolean isExactNumberType() {
    return false;
  }

  public boolean isDateTimeType() {
    return false;
  }

  public boolean isDateTimeTypeWithZone() {
    return false;
  }

  public boolean isIntervalType() {
    return false;
  }

  public boolean isBinaryType() {
    return false;
  }

  public boolean isBooleanType() {
    return false;
  }

  public boolean isLobType() {
    return false;
  }

  public boolean isBitType() {
    return false;
  }

  public boolean isObjectType() {
    return false;
  }

  public boolean isDistinctType() {

    return userTypeModifier == null
        ? false
        : userTypeModifier.schemaObjectType == SchemaObject.TYPE;
  }

  public boolean isDomainType() {

    return userTypeModifier == null
        ? false
        : userTypeModifier.schemaObjectType == SchemaObject.DOMAIN;
  }

  public boolean acceptsPrecision() {
    return false;
  }

  public boolean requiresPrecision() {
    return false;
  }

  public long getMaxPrecision() {
    return 0;
  }

  public int getMaxScale() {
    return 0;
  }

  public int getPrecisionRadix() {
    return 0;
  }

  public boolean acceptsFractionalPrecision() {
    return false;
  }

  public boolean acceptsScale() {
    return false;
  }

  public int precedenceDegree(Type other) {

    if (other.typeCode == typeCode) {
      return 0;
    }

    return Integer.MIN_VALUE;
  }

  /** Common type used in comparison opertions. other must be comparable with this. */
  public abstract Type getAggregateType(Type other);

  /**
   * Result type of combining values of two types in different opertions. other type is not allways
   * comparable with this, but a operation should be valid without any explicit CAST
   */
  public abstract Type getCombinedType(Type other, int operation);

  public int compareToTypeRange(Object o) {
    return 0;
  }

  /** All arithmetic ops are called on the pre-determined Type object of the result */
  public Object absolute(Object a) {
    throw Error.runtimeError(ErrorCode.U_S0500, "Type");
  }

  public Object negate(Object a) {
    throw Error.runtimeError(ErrorCode.U_S0500, "Type");
  }

  public Object add(Object a, Object b, Type otherType) {
    throw Error.runtimeError(ErrorCode.U_S0500, "Type");
  }

  public Object subtract(Object a, Object b, Type otherType) {
    throw Error.runtimeError(ErrorCode.U_S0500, "Type");
  }

  public Object multiply(Object a, Object b) {
    throw Error.runtimeError(ErrorCode.U_S0500, "Type");
  }

  public Object divide(Object a, Object b) {
    throw Error.runtimeError(ErrorCode.U_S0500, "Type");
  }

  public Object concat(Session session, Object a, Object b) {
    throw Error.runtimeError(ErrorCode.U_S0500, "Type");
  }

  public int cardinality(Session session, Object a) {
    return 0;
  }

  public boolean equals(Object other) {

    if (other == this) {
      return true;
    }

    if (other instanceof Type) {
      return ((Type) other).typeCode == typeCode
          && ((Type) other).precision == precision
          && ((Type) other).scale == scale
          && ((Type) other).userTypeModifier == userTypeModifier;
    }

    return false;
  }

  public int hashCode() {
    return typeCode + (int) precision << 8 + scale << 16;
  }

  /** @todo 1.9.0 - review all needs max implementation defined lengths, used for parameters */

  // null type
  public static final Type SQL_ALL_TYPES = NullType.getNullType();

  // character types
  public static final CharacterType SQL_CHAR = new CharacterType(Types.SQL_CHAR, 1);
  public static final CharacterType SQL_CHAR_DEFAULT =
      new CharacterType(Types.SQL_CHAR, CharacterType.defaultCharPrecision);
  public static final CharacterType SQL_VARCHAR = new CharacterType(Types.SQL_VARCHAR, 0);
  public static final CharacterType SQL_VARCHAR_DEFAULT =
      new CharacterType(Types.SQL_VARCHAR, CharacterType.defaultCharPrecision);
  public static final ClobType SQL_CLOB = new ClobType(ClobType.defaultClobSize);
  public static final CharacterType VARCHAR_IGNORECASE =
      new CharacterType(Types.VARCHAR_IGNORECASE, 0);
  public static final CharacterType VARCHAR_IGNORECASE_DEFAULT =
      new CharacterType(Types.VARCHAR_IGNORECASE, CharacterType.defaultCharPrecision);

  // binary types
  public static final BitType SQL_BIT = new BitType(Types.SQL_BIT, 1);
  public static final BitType SQL_BIT_VARYING = new BitType(Types.SQL_BIT_VARYING, 1);
  public static final BitType SQL_BIT_VARYING_MAX_LENGTH =
      new BitType(Types.SQL_BIT_VARYING, BitType.maxBitPrecision);

  // binary types
  public static final BinaryType SQL_BINARY = new BinaryType(Types.SQL_BINARY, 1);
  public static final BinaryType SQL_BINARY_DEFAULT = new BinaryType(Types.SQL_BINARY, 32 * 1024);
  public static final BinaryType SQL_VARBINARY = new BinaryType(Types.SQL_VARBINARY, 0);
  public static final BinaryType SQL_VARBINARY_DEFAULT =
      new BinaryType(Types.SQL_VARBINARY, 32 * 1024);
  public static final BlobType SQL_BLOB = new BlobType(BlobType.defaultBlobSize);

  // other type
  public static final OtherType OTHER = OtherType.getOtherType();

  // boolean type
  public static final BooleanType SQL_BOOLEAN = BooleanType.getBooleanType();

  // number types
  public static final NumberType SQL_NUMERIC =
      new NumberType(Types.SQL_NUMERIC, NumberType.defaultNumericPrecision, 0);
  public static final NumberType SQL_DECIMAL =
      new NumberType(Types.SQL_DECIMAL, NumberType.defaultNumericPrecision, 0);
  public static final NumberType SQL_DECIMAL_DEFAULT =
      new NumberType(
          Types.SQL_DECIMAL, NumberType.defaultNumericPrecision, NumberType.defaultNumericScale);
  public static final NumberType SQL_DECIMAL_BIGINT_SQR =
      new NumberType(Types.SQL_DECIMAL, NumberType.bigintSquareNumericPrecision, 0);
  public static final NumberType SQL_DOUBLE = new NumberType(Types.SQL_DOUBLE, 0, 0);

  //
  public static final NumberType TINYINT =
      new NumberType(Types.TINYINT, NumberType.tinyintPrecision, 0);
  public static final NumberType SQL_SMALLINT =
      new NumberType(Types.SQL_SMALLINT, NumberType.smallintPrecision, 0);
  public static final NumberType SQL_INTEGER =
      new NumberType(Types.SQL_INTEGER, NumberType.integerPrecision, 0);
  public static final NumberType SQL_BIGINT =
      new NumberType(Types.SQL_BIGINT, NumberType.bigintPrecision, 0);

  // date time
  public static final DateTimeType SQL_DATE =
      new DateTimeType(Types.SQL_TIMESTAMP, Types.SQL_DATE, 0);
  public static final DateTimeType SQL_TIME =
      new DateTimeType(Types.SQL_TIME, Types.SQL_TIME, DTIType.defaultTimeFractionPrecision);
  public static final DateTimeType SQL_TIME_WITH_TIME_ZONE =
      new DateTimeType(
          Types.SQL_TIME, Types.SQL_TIME_WITH_TIME_ZONE, DTIType.defaultTimeFractionPrecision);
  public static final DateTimeType SQL_TIMESTAMP =
      new DateTimeType(
          Types.SQL_TIMESTAMP, Types.SQL_TIMESTAMP, DTIType.defaultTimestampFractionPrecision);
  public static final DateTimeType SQL_TIMESTAMP_WITH_TIME_ZONE =
      new DateTimeType(
          Types.SQL_TIMESTAMP,
          Types.SQL_TIMESTAMP_WITH_TIME_ZONE,
          DTIType.defaultTimestampFractionPrecision);
  public static final DateTimeType SQL_TIMESTAMP_NO_FRACTION =
      new DateTimeType(Types.SQL_TIMESTAMP, Types.SQL_TIMESTAMP, 0);

  // interval
  public static final IntervalType SQL_INTERVAL_YEAR =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_YEAR, DTIType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_MONTH =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_MONTH, DTIType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_DAY =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_DAY, DTIType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_HOUR =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_HOUR, DTIType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_MINUTE =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_MINUTE, DTIType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_SECOND =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_SECOND,
          DTIType.defaultIntervalPrecision,
          DTIType.defaultIntervalFractionPrecision);
  public static final IntervalType SQL_INTERVAL_SECOND_MAX_FRACTION =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_SECOND,
          DTIType.defaultIntervalPrecision,
          DTIType.maxFractionPrecision);
  public static final IntervalType SQL_INTERVAL_YEAR_TO_MONTH =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_YEAR_TO_MONTH, DTIType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_DAY_TO_HOUR =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_DAY_TO_HOUR, DTIType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_DAY_TO_MINUTE =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_DAY_TO_MINUTE, DTIType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_DAY_TO_SECOND =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_DAY_TO_SECOND,
          DTIType.defaultIntervalPrecision,
          DTIType.defaultIntervalFractionPrecision);
  public static final IntervalType SQL_INTERVAL_HOUR_TO_MINUTE =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_HOUR_TO_MINUTE, DTIType.defaultIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_HOUR_TO_SECOND =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_HOUR_TO_SECOND,
          DTIType.defaultIntervalPrecision,
          DTIType.defaultIntervalFractionPrecision);
  public static final IntervalType SQL_INTERVAL_MINUTE_TO_SECOND =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_MINUTE_TO_SECOND,
          DTIType.defaultIntervalPrecision,
          DTIType.defaultIntervalFractionPrecision);

  //
  public static final IntervalType SQL_INTERVAL_YEAR_MAX_PRECISION =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_YEAR, DTIType.maxIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_MONTH_MAX_PRECISION =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_MONTH, DTIType.maxIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_DAY_MAX_PRECISION =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_DAY, DTIType.maxIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_HOUR_MAX_PRECISION =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_HOUR, DTIType.maxIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_MINUTE_MAX_PRECISION =
      IntervalType.newIntervalType(Types.SQL_INTERVAL_MINUTE, DTIType.maxIntervalPrecision, 0);
  public static final IntervalType SQL_INTERVAL_SECOND_MAX_PRECISION =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_SECOND,
          DTIType.maxIntervalPrecision,
          DTIType.defaultIntervalFractionPrecision);
  public static final IntervalType SQL_INTERVAL_SECOND_MAX_FRACTION_MAX_PRECISION =
      IntervalType.newIntervalType(
          Types.SQL_INTERVAL_SECOND, DTIType.maxIntervalPrecision, DTIType.maxFractionPrecision);

  //
  public static final ArrayType SQL_ARRAY_ALL_TYPES = new ArrayType(SQL_ALL_TYPES, 0);

  public static ArrayType getDefaultArrayType(int type) {
    return new ArrayType(getDefaultType(type), Type.defaultArrayCardinality);
  }

  public static Type getDefaultType(int type) {

    try {
      return getType(type, 0, 0, 0);
    } catch (Exception e) {
      return null;
    }
  }

  public static Type getDefaultTypeWithSize(int type) {

    switch (type) {
      case Types.SQL_ALL_TYPES:
        return SQL_ALL_TYPES;

      case Types.SQL_CHAR:
        return SQL_CHAR_DEFAULT;

      case Types.SQL_VARCHAR:
        return SQL_VARCHAR_DEFAULT;

      case Types.VARCHAR_IGNORECASE:
        return VARCHAR_IGNORECASE_DEFAULT;

      case Types.SQL_CLOB:
        return SQL_CLOB;

      case Types.SQL_INTEGER:
        return SQL_INTEGER;

      case Types.SQL_SMALLINT:
        return SQL_SMALLINT;

      case Types.SQL_BIGINT:
        return SQL_BIGINT;

      case Types.TINYINT:
        return TINYINT;

      case Types.SQL_FLOAT:
      case Types.SQL_REAL:
      case Types.SQL_DOUBLE:
        return SQL_DOUBLE;

      case Types.SQL_NUMERIC:
        return SQL_NUMERIC;

      case Types.SQL_DECIMAL:
        return SQL_DECIMAL;

      case Types.SQL_BOOLEAN:
        return SQL_BOOLEAN;

      case Types.SQL_BINARY:
        return SQL_BINARY_DEFAULT;

      case Types.SQL_VARBINARY:
        return SQL_VARBINARY_DEFAULT;

      case Types.SQL_BLOB:
        return SQL_BLOB;

      case Types.SQL_BIT:
        return SQL_BIT;

      case Types.SQL_BIT_VARYING:
        return SQL_BIT_VARYING;

      case Types.SQL_DATE:
        return SQL_DATE;

      case Types.SQL_TIME:
        return SQL_TIME;

      case Types.SQL_TIME_WITH_TIME_ZONE:
        return SQL_TIME_WITH_TIME_ZONE;

      case Types.SQL_TIMESTAMP:
        return SQL_TIMESTAMP;

      case Types.SQL_TIMESTAMP_WITH_TIME_ZONE:
        return SQL_TIMESTAMP_WITH_TIME_ZONE;

      case Types.SQL_INTERVAL_YEAR:
        return SQL_INTERVAL_YEAR;

      case Types.SQL_INTERVAL_YEAR_TO_MONTH:
        return SQL_INTERVAL_YEAR_TO_MONTH;

      case Types.SQL_INTERVAL_MONTH:
        return SQL_INTERVAL_MONTH;

      case Types.SQL_INTERVAL_DAY:
        return SQL_INTERVAL_DAY;

      case Types.SQL_INTERVAL_DAY_TO_HOUR:
        return SQL_INTERVAL_DAY_TO_HOUR;

      case Types.SQL_INTERVAL_DAY_TO_MINUTE:
        return SQL_INTERVAL_DAY_TO_MINUTE;

      case Types.SQL_INTERVAL_DAY_TO_SECOND:
        return SQL_INTERVAL_DAY_TO_SECOND;

      case Types.SQL_INTERVAL_HOUR:
        return SQL_INTERVAL_HOUR;

      case Types.SQL_INTERVAL_HOUR_TO_MINUTE:
        return SQL_INTERVAL_HOUR_TO_MINUTE;

      case Types.SQL_INTERVAL_HOUR_TO_SECOND:
        return SQL_INTERVAL_HOUR_TO_SECOND;

      case Types.SQL_INTERVAL_MINUTE:
        return SQL_INTERVAL_MINUTE;

      case Types.SQL_INTERVAL_MINUTE_TO_SECOND:
        return SQL_INTERVAL_MINUTE_TO_SECOND;

      case Types.SQL_INTERVAL_SECOND:
        return SQL_INTERVAL_SECOND;

      case Types.OTHER:
        return OTHER;

      default:
        return null;
    }
  }

  public static int getHSQLDBTypeCode(int jdbcTypeNumber) {

    switch (jdbcTypeNumber) {
      case Types.BIGINT:
        return Types.SQL_BIGINT;

      case Types.LONGVARCHAR:
        return Types.SQL_VARCHAR;

      case Types.CLOB:
        return Types.SQL_CLOB;

      case Types.BINARY:
        return Types.SQL_BINARY;

      case Types.BIT:
        return Types.SQL_BIT_VARYING;

      case Types.VARBINARY:
      case Types.LONGVARBINARY:
        return Types.SQL_VARBINARY;

      case Types.BLOB:
        return Types.SQL_BLOB;

      default:
        return jdbcTypeNumber;
    }
  }

  /**
   * translate an internal type number to JDBC type number if a type is not supported internally, it
   * is returned without translation
   *
   * @param type int
   * @return int
   */
  public static int getJDBCTypeCode(int type) {

    switch (type) {
      case Types.SQL_BLOB:
        return Types.BLOB;

      case Types.SQL_CLOB:
        return Types.CLOB;

      case Types.SQL_BIGINT:
        return Types.BIGINT;

      case Types.SQL_BINARY:
        return Types.BINARY;

      case Types.SQL_VARBINARY:
        return Types.VARBINARY;

      case Types.SQL_BIT:
      case Types.SQL_BIT_VARYING:
        return Types.BIT;

      default:
        return type;
    }
  }

  /** Enforces precision and scale limits on type */
  public static Type getType(int type, int collation, long precision, int scale) {

    switch (type) {
      case Types.SQL_ALL_TYPES:
        return SQL_ALL_TYPES;

        //                return SQL_ALL_TYPES; // needs changes to Expression type resolution
      case Types.SQL_CHAR:
      case Types.SQL_VARCHAR:
      case Types.VARCHAR_IGNORECASE:
      case Types.SQL_CLOB:
        return CharacterType.getCharacterType(type, precision);

      case Types.SQL_INTEGER:
        return SQL_INTEGER;

      case Types.SQL_SMALLINT:
        return SQL_SMALLINT;

      case Types.SQL_BIGINT:
        return SQL_BIGINT;

      case Types.TINYINT:
        return TINYINT;

      case Types.SQL_FLOAT:
        if (precision > 53) {
          throw Error.error(ErrorCode.X_42592, "" + precision);
        }

        // fall through
      case Types.SQL_REAL:
      case Types.SQL_DOUBLE:
        return SQL_DOUBLE;

      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
        if (precision == 0) {
          precision = NumberType.defaultNumericPrecision;
        }

        return NumberType.getNumberType(type, precision, scale);

      case Types.SQL_BOOLEAN:
        return SQL_BOOLEAN;

      case Types.SQL_BINARY:
      case Types.SQL_VARBINARY:
      case Types.SQL_BLOB:
        return BinaryType.getBinaryType(type, precision);

      case Types.SQL_BIT:
      case Types.SQL_BIT_VARYING:
        return BitType.getBitType(type, precision);

      case Types.SQL_DATE:
      case Types.SQL_TIME:
      case Types.SQL_TIME_WITH_TIME_ZONE:
      case Types.SQL_TIMESTAMP:
      case Types.SQL_TIMESTAMP_WITH_TIME_ZONE:
        return DateTimeType.getDateTimeType(type, scale);

      case Types.SQL_INTERVAL_YEAR:
      case Types.SQL_INTERVAL_YEAR_TO_MONTH:
      case Types.SQL_INTERVAL_MONTH:
      case Types.SQL_INTERVAL_DAY:
      case Types.SQL_INTERVAL_DAY_TO_HOUR:
      case Types.SQL_INTERVAL_DAY_TO_MINUTE:
      case Types.SQL_INTERVAL_DAY_TO_SECOND:
      case Types.SQL_INTERVAL_HOUR:
      case Types.SQL_INTERVAL_HOUR_TO_MINUTE:
      case Types.SQL_INTERVAL_HOUR_TO_SECOND:
      case Types.SQL_INTERVAL_MINUTE:
      case Types.SQL_INTERVAL_MINUTE_TO_SECOND:
      case Types.SQL_INTERVAL_SECOND:
        return IntervalType.getIntervalType(type, precision, scale);

      case Types.OTHER:
        return OTHER;

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "Type");
    }
  }

  public static Type getAggregateType(Type add, Type existing) {

    if (existing == null || existing.typeCode == Types.SQL_ALL_TYPES) {
      return add;
    }

    if (add == null || add.typeCode == Types.SQL_ALL_TYPES) {
      return existing;
    }

    return existing.getAggregateType(add);
  }

  public static final IntValueHashMap typeAliases;
  public static final IntValueHashMap typeNames;

  static {
    typeNames = new IntValueHashMap(37);

    typeNames.put("CHARACTER", Types.SQL_CHAR);
    typeNames.put("VARCHAR", Types.SQL_VARCHAR);
    typeNames.put("VARCHAR_IGNORECASE", Types.VARCHAR_IGNORECASE);
    typeNames.put("DATE", Types.SQL_DATE);
    typeNames.put("TIME", Types.SQL_TIME);
    typeNames.put("TIMESTAMP", Types.SQL_TIMESTAMP);
    typeNames.put("INTERVAL", Types.SQL_INTERVAL);
    typeNames.put("TINYINT", Types.TINYINT);
    typeNames.put("SMALLINT", Types.SQL_SMALLINT);
    typeNames.put("INTEGER", Types.SQL_INTEGER);
    typeNames.put("BIGINT", Types.SQL_BIGINT);
    typeNames.put("REAL", Types.SQL_REAL);
    typeNames.put("FLOAT", Types.SQL_FLOAT);
    typeNames.put("DOUBLE", Types.SQL_DOUBLE);
    typeNames.put("NUMERIC", Types.SQL_NUMERIC);
    typeNames.put("DECIMAL", Types.SQL_DECIMAL);
    typeNames.put("BOOLEAN", Types.SQL_BOOLEAN);
    typeNames.put("BINARY", Types.SQL_BINARY);
    typeNames.put("VARBINARY", Types.SQL_VARBINARY);
    typeNames.put("CLOB", Types.SQL_CLOB);
    typeNames.put("BLOB", Types.SQL_BLOB);
    typeNames.put("BIT", Types.SQL_BIT);
    typeNames.put("OTHER", Types.OTHER);

    //
    typeAliases = new IntValueHashMap(64);

    typeAliases.put("CHAR", Types.SQL_CHAR);
    typeAliases.put("INT", Types.SQL_INTEGER);
    typeAliases.put("DEC", Types.SQL_DECIMAL);
    typeAliases.put("LONGVARCHAR", Types.LONGVARCHAR);
    typeAliases.put("DATETIME", Types.SQL_TIMESTAMP);
    typeAliases.put("LONGVARBINARY", Types.LONGVARBINARY);
    typeAliases.put("OBJECT", Types.OTHER);
  }

  public static int getTypeNr(String name) {

    int i = typeNames.get(name, Integer.MIN_VALUE);

    if (i == Integer.MIN_VALUE) {
      i = typeAliases.get(name, Integer.MIN_VALUE);
    }

    return i;
  }

  public static boolean isSupportedSQLType(int typeNumber) {

    if (getDefaultType(typeNumber) == null) {
      return false;
    }

    return true;
  }

  public static boolean matches(Type[] one, Type[] other) {

    for (int i = 0; i < one.length; i++) {
      if (one[i].typeCode != other[i].typeCode) {
        return false;
      }
    }

    return true;
  }
}