/* * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Florent Guillaume */ package org.nuxeo.ecm.core.storage.sql; import java.io.Serializable; import org.nuxeo.ecm.core.schema.types.Field; import org.nuxeo.ecm.core.schema.types.SimpleTypeImpl; import org.nuxeo.ecm.core.schema.types.Type; import org.nuxeo.ecm.core.schema.types.primitives.BinaryType; import org.nuxeo.ecm.core.schema.types.primitives.BooleanType; import org.nuxeo.ecm.core.schema.types.primitives.DateType; import org.nuxeo.ecm.core.schema.types.primitives.DoubleType; import org.nuxeo.ecm.core.schema.types.primitives.IntegerType; import org.nuxeo.ecm.core.schema.types.primitives.LongType; import org.nuxeo.ecm.core.schema.types.primitives.StringType; /** * The database-level column types, including per-type parameters like length. */ public class ColumnType implements Serializable { private static final long serialVersionUID = 1L; /** Length used internally to flag a string to use CLOB. */ public static final int CLOB_LENGTH = 999999999; public static final ColumnType STRING = new ColumnType(ColumnSpec.STRING); public static final ColumnType CLOB = new ColumnType(ColumnSpec.STRING, CLOB_LENGTH); public static final ColumnType BOOLEAN = new ColumnType(ColumnSpec.BOOLEAN); public static final ColumnType LONG = new ColumnType(ColumnSpec.LONG); public static final ColumnType DOUBLE = new ColumnType(ColumnSpec.DOUBLE); public static final ColumnType TIMESTAMP = new ColumnType(ColumnSpec.TIMESTAMP); public static final ColumnType BLOBID = new ColumnType(ColumnSpec.BLOBID); public static final ColumnType ARRAY_STRING = new ColumnType(ColumnSpec.ARRAY_STRING, -1, true); public static final ColumnType ARRAY_CLOB = new ColumnType(ColumnSpec.ARRAY_STRING, CLOB_LENGTH, true); public static final ColumnType ARRAY_BOOLEAN = new ColumnType(ColumnSpec.ARRAY_BOOLEAN, -1, true); public static final ColumnType ARRAY_LONG = new ColumnType(ColumnSpec.ARRAY_LONG, -1, true); public static final ColumnType ARRAY_DOUBLE = new ColumnType(ColumnSpec.ARRAY_DOUBLE, -1, true); public static final ColumnType ARRAY_TIMESTAMP = new ColumnType(ColumnSpec.ARRAY_TIMESTAMP, -1, true); public static final ColumnType ARRAY_BLOBID = new ColumnType(ColumnSpec.ARRAY_BLOBID, -1, true); public static final ColumnType ARRAY_INTEGER = new ColumnType(ColumnSpec.ARRAY_INTEGER, -1, true); public static final ColumnType NODEID = new ColumnType(ColumnSpec.NODEID); public static final ColumnType NODEIDFK = new ColumnType(ColumnSpec.NODEIDFK); public static final ColumnType NODEIDFKNP = new ColumnType(ColumnSpec.NODEIDFKNP); public static final ColumnType NODEIDFKMUL = new ColumnType(ColumnSpec.NODEIDFKMUL); public static final ColumnType NODEIDFKNULL = new ColumnType(ColumnSpec.NODEIDFKNULL); public static final ColumnType NODEIDPK = new ColumnType(ColumnSpec.NODEIDPK); public static final ColumnType NODEVAL = new ColumnType(ColumnSpec.NODEVAL); public static final ColumnType NODEARRAY = new ColumnType(ColumnSpec.NODEARRAY, -1, true); public static final ColumnType SYSNAME = new ColumnType(ColumnSpec.SYSNAME); public static final ColumnType SYSNAMEARRAY = new ColumnType(ColumnSpec.SYSNAMEARRAY, -1, true); public static final ColumnType TINYINT = new ColumnType(ColumnSpec.TINYINT); public static final ColumnType INTEGER = new ColumnType(ColumnSpec.INTEGER); public static final ColumnType AUTOINC = new ColumnType(ColumnSpec.AUTOINC); public static final ColumnType FTINDEXED = new ColumnType(ColumnSpec.FTINDEXED); public static final ColumnType FTSTORED = new ColumnType(ColumnSpec.FTSTORED); public static final ColumnType CLUSTERNODE = new ColumnType(ColumnSpec.CLUSTERNODE); public static final ColumnType CLUSTERFRAGS = new ColumnType(ColumnSpec.CLUSTERFRAGS); public final ColumnSpec spec; public final int length; public final boolean array; public ColumnType(ColumnSpec spec, int length, boolean array) { this.spec = spec; this.length = length; this.array = array; } public ColumnType(ColumnSpec spec, int length) { this(spec, length, false); } public ColumnType(ColumnSpec spec) { this(spec, -1); } public boolean isUnconstrained() { return length == -1; } public boolean isClob() { return length == CLOB_LENGTH; } public boolean isArray() { return array; } /** * Checks if this column holds a Nuxeo unique id (usually UUID). */ public boolean isId() { return spec.isId(); } /** * Wraps a string that needs to be mapped to an id column in prepared statements. * * @since 5.7 */ public static class WrappedId implements Serializable { private static final long serialVersionUID = 1L; public final String string; public WrappedId(String string) { this.string = string; } @Override public String toString() { return string; } } @Override public String toString() { if (isUnconstrained()) { return spec.toString(); } else if (isClob()) { return isArray() ? "ARRAY_CLOB" : "CLOB"; } else { return spec.toString() + '(' + length + ')'; } } /** * Gets the column type from a Nuxeo Schema field, including its constrained length if any. */ public static ColumnType fromField(Field field) { return fromFieldType(field.getType(), field.getMaxLength()); } /** * Gets the column type from a Nuxeo Schema field type (unconstrained). */ public static ColumnType fromFieldType(Type type) { return fromFieldType(type, -1); } /** * Gets the column type from a Nuxeo Schema field type (unconstrained) with array {@code true} if an array type is * required */ public static ColumnType fromFieldType(Type type, boolean array) { return fromFieldType(type, -1, array); } protected static ColumnType fromFieldType(Type type, int maxLength) { return fromFieldType(type, maxLength, false); } protected static ColumnType fromFieldType(Type type, int maxLength, boolean array) { if (type instanceof StringType) { if (maxLength == -1) { return array ? ARRAY_STRING : STRING; // unconstrained } else { return new ColumnType(ColumnSpec.STRING, maxLength, array); } } else if (type instanceof BooleanType) { return array ? ARRAY_BOOLEAN : BOOLEAN; } else if (type instanceof LongType) { return array ? ARRAY_LONG : LONG; } else if (type instanceof DoubleType) { return array ? ARRAY_DOUBLE : DOUBLE; } else if (type instanceof DateType) { return array ? ARRAY_TIMESTAMP : TIMESTAMP; } else if (type instanceof BinaryType) { return array ? ARRAY_BLOBID : BLOBID; } else if (type instanceof IntegerType) { return array ? ARRAY_INTEGER : INTEGER; } else if (type instanceof SimpleTypeImpl) { // comes from a constraint return fromFieldType(type.getSuperType(), maxLength); } else { throw new RuntimeException("Invalid primitive type: " + type.getClass().getName()); } } }