/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Florent Guillaume */ package org.eclipse.ecr.core.storage.sql; import java.io.Serializable; import java.lang.reflect.Array; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.GregorianCalendar; import org.eclipse.ecr.core.schema.types.SimpleTypeImpl; import org.eclipse.ecr.core.schema.types.Type; import org.eclipse.ecr.core.schema.types.primitives.BinaryType; import org.eclipse.ecr.core.schema.types.primitives.BooleanType; import org.eclipse.ecr.core.schema.types.primitives.DateType; import org.eclipse.ecr.core.schema.types.primitives.DoubleType; import org.eclipse.ecr.core.schema.types.primitives.IntegerType; import org.eclipse.ecr.core.schema.types.primitives.LongType; import org.eclipse.ecr.core.schema.types.primitives.StringType; /** * @author Florent Guillaume */ public enum PropertyType { STRING(String.class), // BOOLEAN(Boolean.class), // LONG(Long.class), // DOUBLE(Double.class), // DATETIME(Calendar.class), // BINARY(Binary.class), // ACL(ACLRow.class), // ARRAY_STRING(STRING, new String[0]), // ARRAY_BOOLEAN(BOOLEAN, new Boolean[0]), // ARRAY_LONG(LONG, new Long[0]), // ARRAY_DOUBLE(DOUBLE, new Double[0]), // ARRAY_DATETIME(DATETIME, new Calendar[0]), // ARRAY_BINARY(BINARY, new Binary[0]), // COLL_ACL(ACL, new ACLRow[0]); private final Class<?> klass; private final PropertyType arrayBaseType; private final Serializable[] emptyArray; PropertyType(Class<?> klass) { this.klass = klass; arrayBaseType = null; emptyArray = null; } PropertyType(PropertyType arrayBaseType, Serializable[] emptyArray) { klass = null; this.arrayBaseType = arrayBaseType; this.emptyArray = emptyArray; } public boolean isArray() { return arrayBaseType != null; } public PropertyType getArrayBaseType() { return arrayBaseType; } public Serializable[] getEmptyArray() { return emptyArray; } public Serializable[] collectionToArray(Collection<Serializable> collection) { // contrary to list.toArray(), this creates an array // of the property type instead of an Object[] Serializable[] array = (Serializable[]) Array.newInstance(klass, collection.size()); return collection.toArray(array); } /** * Normalizes a scalar value of this type. * * @param value the value to normalize * @return the normalized value * @throws IllegalArgumentException */ public Serializable normalize(Object value) { if (value == null) { return null; } switch (this) { case STRING: if (value instanceof String) { return (String) value; } throw new IllegalArgumentException("value is not a String: " + value); case BOOLEAN: if (value instanceof Boolean) { return (Boolean) value; } throw new IllegalArgumentException("value is not a Boolean: " + value); case LONG: if (value instanceof Long) { return (Long) value; } throw new IllegalArgumentException("value is not a Long: " + value); case DOUBLE: if (value instanceof Double) { return (Double) value; } throw new IllegalArgumentException("value is not a Double: " + value); case DATETIME: if (value instanceof Calendar) { return (Calendar) value; } if (value instanceof Date) { Calendar cal = new GregorianCalendar(); // XXX timezone cal.setTime((Date) value); return cal; } throw new IllegalArgumentException("value is not a Calendar: " + value); case BINARY: if (value instanceof Binary) { return (Binary) value; } throw new IllegalArgumentException("value is not a Binary: " + value); case ACL: if (value instanceof ACLRow) { return (ACLRow) value; } throw new IllegalArgumentException("value is not a ACLRow: " + value); default: throw new RuntimeException(this.toString()); } } /** * Normalizes an array value of this type. * <p> * A {@code null} value will be normalized to an empty array. * * @param value the array to normalize * @return the normalized array * @throws IllegalArgumentException */ public Serializable[] normalize(Object[] value) { if (value == null) { return emptyArray; } Serializable[] newValue; if (value instanceof Serializable[]) { // update in place newValue = (Serializable[]) value; } else { newValue = new Serializable[value.length]; } for (int i = 0; i < value.length; i++) { newValue[i] = arrayBaseType.normalize(value[i]); } return newValue; } /** * Converts a Nuxeo core schema field type into a property type. * * @param fieldType the field type to convert * @param array {@code true} if an array type is required * @return */ public static PropertyType fromFieldType(Type fieldType, boolean array) { if (fieldType instanceof StringType) { return array ? ARRAY_STRING : STRING; } else if (fieldType instanceof BooleanType) { return array ? ARRAY_BOOLEAN : BOOLEAN; } else if (fieldType instanceof LongType) { return array ? ARRAY_LONG : LONG; } else if (fieldType instanceof DoubleType) { return array ? ARRAY_DOUBLE : DOUBLE; } else if (fieldType instanceof DateType) { return array ? ARRAY_DATETIME : DATETIME; } else if (fieldType instanceof BinaryType) { return array ? ARRAY_BINARY : BINARY; } else if (fieldType instanceof IntegerType) { throw new RuntimeException("Unimplemented primitive type: " + fieldType.getClass().getName()); } else if (fieldType instanceof SimpleTypeImpl) { // simple type with constraints -- ignore constraints XXX return fromFieldType(fieldType.getSuperType(), array); } else { throw new RuntimeException("Invalid primitive type: " + fieldType.getClass().getName()); } } }