| /* |
| * Copyright (c) 2004 - 2013 Eike Stepper (Berlin, Germany) 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: |
| * Eike Stepper - initial API and implementation |
| * Stefan Winkler - Bug 299194: unsettable features inconsistent between revisions |
| * Erdal Karaca - added support for HASHMAP CDO Type |
| * Christian W. Damus (CEA) - 378620 support unsettable features of custom data type |
| */ |
| package org.eclipse.emf.cdo.internal.common.model; |
| |
| import org.eclipse.emf.cdo.common.id.CDOID; |
| import org.eclipse.emf.cdo.common.lob.CDOBlob; |
| import org.eclipse.emf.cdo.common.lob.CDOClob; |
| import org.eclipse.emf.cdo.common.lob.CDOLobUtil; |
| import org.eclipse.emf.cdo.common.model.CDOModelUtil; |
| import org.eclipse.emf.cdo.common.model.CDOType; |
| import org.eclipse.emf.cdo.common.protocol.CDODataInput; |
| import org.eclipse.emf.cdo.common.protocol.CDODataOutput; |
| import org.eclipse.emf.cdo.common.revision.CDORevision; |
| import org.eclipse.emf.cdo.common.revision.CDORevisionData; |
| import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; |
| import org.eclipse.emf.cdo.internal.common.messages.Messages; |
| import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; |
| import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster; |
| |
| import org.eclipse.emf.common.util.Enumerator; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EDataType; |
| import org.eclipse.emf.ecore.EEnum; |
| import org.eclipse.emf.ecore.EEnumLiteral; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.EStructuralFeature.Internal.DynamicValueHolder; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.util.FeatureMap; |
| |
| import java.io.IOException; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public abstract class CDOTypeImpl implements CDOType |
| { |
| private static CDOTypeImpl[] ids = new CDOTypeImpl[Byte.MAX_VALUE - Byte.MIN_VALUE + 1]; |
| |
| private static final byte OPCODE_NORMAL = 0; |
| |
| private static final byte OPCODE_NULL = 1; |
| |
| private static final byte OPCODE_NIL = 2; |
| |
| private static final byte BOOLEAN_DEFAULT_PRIMITIVE = 0; |
| |
| private static final char CHARACTER_DEFAULT_PRIMITIVE = 0; |
| |
| private static final short SHORT_DEFAULT_PRIMITIVE = 0; |
| |
| public static final Boolean BOOLEAN_DEFAULT = new Boolean(false); |
| |
| public static final Byte BYTE_DEFAULT = new Byte(BOOLEAN_DEFAULT_PRIMITIVE); |
| |
| public static final Character CHARACTER_DEFAULT = new Character(CHARACTER_DEFAULT_PRIMITIVE); |
| |
| public static final Double DOUBLE_DEFAULT = new Double(0.0); |
| |
| public static final Float FLOAT_DEFAULT = new Float(0.0); |
| |
| public static final Integer INTEGER_DEFAULT = new Integer(0); |
| |
| public static final Long LONG_DEFAULT = new Long(0L); |
| |
| public static final Short SHORT_DEFAULT = new Short(SHORT_DEFAULT_PRIMITIVE); |
| |
| public static final CDOType BOOLEAN = new CDOTypeImpl("BOOLEAN", EcorePackage.EBOOLEAN, false, BOOLEAN_DEFAULT) //$NON-NLS-1$ |
| { |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| boolean v = (Boolean)(value == null ? getDefaultValue() : value); |
| out.writeBoolean(v); |
| } |
| |
| public Boolean readValue(CDODataInput in) throws IOException |
| { |
| return in.readBoolean(); |
| } |
| }; |
| |
| public static final CDOType BYTE = new CDOTypeImpl("BYTE", EcorePackage.EBYTE, false, BYTE_DEFAULT) //$NON-NLS-1$ |
| { |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeByte((Byte)(value == null ? getDefaultValue() : value)); |
| } |
| |
| public Byte readValue(CDODataInput in) throws IOException |
| { |
| return in.readByte(); |
| } |
| }; |
| |
| public static final CDOType CHAR = new CDOTypeImpl("CHAR", EcorePackage.ECHAR, false, CHARACTER_DEFAULT) //$NON-NLS-1$ |
| { |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeChar(((Character)(value == null ? getDefaultValue() : value)).charValue()); |
| } |
| |
| public Character readValue(CDODataInput in) throws IOException |
| { |
| return in.readChar(); |
| } |
| }; |
| |
| public static final CDOType DOUBLE = new CDOTypeImpl("DOUBLE", EcorePackage.EDOUBLE, false, DOUBLE_DEFAULT) //$NON-NLS-1$ |
| { |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeDouble((Double)(value == null ? getDefaultValue() : value)); |
| } |
| |
| public Double readValue(CDODataInput in) throws IOException |
| { |
| return in.readDouble(); |
| } |
| }; |
| |
| public static final CDOType FLOAT = new CDOTypeImpl("FLOAT", EcorePackage.EFLOAT, false, FLOAT_DEFAULT) //$NON-NLS-1$ |
| { |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeFloat((Float)(value == null ? getDefaultValue() : value)); |
| } |
| |
| public Float readValue(CDODataInput in) throws IOException |
| { |
| return in.readFloat(); |
| } |
| }; |
| |
| public static final CDOType INT = new CDOTypeImpl("INT", EcorePackage.EINT, false, INTEGER_DEFAULT) //$NON-NLS-1$ |
| { |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeInt((Integer)(value == null ? getDefaultValue() : value)); |
| } |
| |
| public Integer readValue(CDODataInput in) throws IOException |
| { |
| return in.readInt(); |
| } |
| }; |
| |
| public static final CDOType LONG = new CDOTypeImpl("LONG", EcorePackage.ELONG, false, LONG_DEFAULT) //$NON-NLS-1$ |
| { |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeLong((Long)(value == null ? getDefaultValue() : value)); |
| } |
| |
| public Long readValue(CDODataInput in) throws IOException |
| { |
| return in.readLong(); |
| } |
| }; |
| |
| public static final CDOType SHORT = new CDOTypeImpl("SHORT", EcorePackage.ESHORT, false, SHORT_DEFAULT) //$NON-NLS-1$ |
| { |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeShort((Short)(value == null ? getDefaultValue() : value)); |
| } |
| |
| public Short readValue(CDODataInput in) throws IOException |
| { |
| return in.readShort(); |
| } |
| }; |
| |
| public static final CDOType BIG_DECIMAL = new ObjectType("BIG_DECIMAL", EcorePackage.EBIG_DECIMAL) //$NON-NLS-1$ |
| { |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| BigDecimal bigDecimal = (BigDecimal)value; |
| out.writeByteArray(bigDecimal.unscaledValue().toByteArray()); |
| out.writeInt(bigDecimal.scale()); |
| } |
| |
| @Override |
| public BigDecimal doReadValue(CDODataInput in) throws IOException |
| { |
| byte[] array = in.readByteArray(); |
| BigInteger unscaled = new BigInteger(array); |
| int scale = in.readInt(); |
| return new BigDecimal(unscaled, scale); |
| } |
| }; |
| |
| public static final CDOType BIG_INTEGER = new ObjectType("BIG_INTEGER", EcorePackage.EBIG_INTEGER) //$NON-NLS-1$ |
| { |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeByteArray(((BigInteger)value).toByteArray()); |
| } |
| |
| @Override |
| public BigInteger doReadValue(CDODataInput in) throws IOException |
| { |
| byte[] array = in.readByteArray(); |
| return new BigInteger(array); |
| } |
| }; |
| |
| public static final CDOType OBJECT = new CDOTypeImpl("OBJECT", EcorePackage.EOBJECT, true, CDOID.NULL) //$NON-NLS-1$ |
| { |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| if (value instanceof CDORevision) |
| { |
| out.writeCDOID(((CDORevision)value).getID()); |
| } |
| else |
| { |
| out.writeCDOID((CDOID)value); |
| } |
| } |
| |
| public CDOID readValue(CDODataInput in) throws IOException |
| { |
| return in.readCDOID(); |
| } |
| |
| @Override |
| public Object doAdjustReferences(CDOReferenceAdjuster adjuster, Object value, EStructuralFeature feature, int index) |
| { |
| return adjuster.adjustReference(value, feature, index); |
| } |
| }; |
| |
| public static final CDOType BOOLEAN_OBJECT = new ObjectType("BOOLEAN_OBJECT", EcorePackage.EBOOLEAN_OBJECT) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeBoolean((Boolean)value); |
| } |
| |
| @Override |
| protected Boolean doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readBoolean(); |
| } |
| }; |
| |
| public static final CDOType BYTE_OBJECT = new ObjectType("BYTE_OBJECT", EcorePackage.EBYTE_OBJECT) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeByte((Byte)value); |
| } |
| |
| @Override |
| protected Byte doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readByte(); |
| } |
| }; |
| |
| public static final CDOType CHARACTER_OBJECT = new ObjectType("CHARACTER_OBJECT", EcorePackage.ECHARACTER_OBJECT) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeChar((Character)value); |
| } |
| |
| @Override |
| protected Character doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readChar(); |
| } |
| }; |
| |
| public static final CDOType DATE = new ObjectType("DATE", EcorePackage.EDATE) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeLong(((Date)value).getTime()); |
| } |
| |
| @Override |
| protected Date doReadValue(CDODataInput in) throws IOException |
| { |
| return new Date(in.readLong()); |
| } |
| }; |
| |
| public static final CDOType DOUBLE_OBJECT = new ObjectType("DOUBLE_OBJECT", EcorePackage.EDOUBLE_OBJECT) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeDouble((Double)value); |
| } |
| |
| @Override |
| protected Double doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readDouble(); |
| } |
| }; |
| |
| public static final CDOType FLOAT_OBJECT = new ObjectType("FLOAT_OBJECT", EcorePackage.EFLOAT_OBJECT) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeFloat((Float)value); |
| } |
| |
| @Override |
| protected Float doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readFloat(); |
| } |
| }; |
| |
| public static final CDOType INTEGER_OBJECT = new ObjectType("INTEGER_OBJECT", EcorePackage.EINTEGER_OBJECT) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeInt((Integer)value); |
| } |
| |
| @Override |
| protected Integer doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readInt(); |
| } |
| }; |
| |
| public static final CDOType LONG_OBJECT = new ObjectType("LONG_OBJECT", EcorePackage.ELONG_OBJECT) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeLong((Long)value); |
| } |
| |
| @Override |
| protected Long doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readLong(); |
| } |
| }; |
| |
| public static final CDOType SHORT_OBJECT = new ObjectType("SHORT_OBJECT", EcorePackage.ESHORT_OBJECT) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeShort((Short)value); |
| } |
| |
| @Override |
| protected Short doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readShort(); |
| } |
| }; |
| |
| public static final CDOType STRING = new ObjectType("STRING", EcorePackage.ESTRING) //$NON-NLS-1$ |
| { |
| @Override |
| protected String doCopyValue(Object value) |
| { |
| return (String)value; |
| } |
| |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeString((String)value); |
| } |
| |
| @Override |
| public String doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readString(); |
| } |
| }; |
| |
| public static final CDOType BYTE_ARRAY = new ObjectType("BYTE_ARRAY", EcorePackage.EBYTE_ARRAY) //$NON-NLS-1$ |
| { |
| @Override |
| protected byte[] doCopyValue(Object value) |
| { |
| byte[] array = (byte[])value; |
| byte[] result = new byte[array.length]; |
| System.arraycopy(value, 0, result, 0, array.length); |
| return result; |
| } |
| |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeByteArray((byte[])value); |
| } |
| |
| @Override |
| public byte[] doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readByteArray(); |
| } |
| }; |
| |
| public static final CDOType FEATURE_MAP_ENTRY = new CDOTypeImpl("FEATURE_MAP_ENTRY", EcorePackage.EFEATURE_MAP_ENTRY, //$NON-NLS-1$ |
| false) |
| { |
| @Override |
| protected FeatureMap.Entry doCopyValue(Object value) |
| { |
| FeatureMap.Entry entry = (FeatureMap.Entry)value; |
| EStructuralFeature innerFeature = entry.getEStructuralFeature(); |
| Object innerValue = entry.getValue(); |
| CDOType innerType = CDOModelUtil.getType(innerFeature.getEType()); |
| |
| Object innerCopy = innerType.copyValue(innerValue); |
| return CDORevisionUtil.createFeatureMapEntry(innerFeature, innerCopy); |
| } |
| |
| public void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public FeatureMap.Entry readValue(CDODataInput in) throws IOException |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public Object doAdjustReferences(CDOReferenceAdjuster adjuster, Object value, EStructuralFeature feature, int index) |
| { |
| FeatureMap.Entry entry = (FeatureMap.Entry)value; |
| EStructuralFeature innerFeature = entry.getEStructuralFeature(); |
| Object innerValue = entry.getValue(); |
| CDOType innerType = CDOModelUtil.getType(innerFeature.getEType()); |
| |
| Object innerCopy = innerType.adjustReferences(adjuster, innerValue, feature, index); |
| if (innerCopy != innerValue) // Just an optimization for NOOP adjusters |
| { |
| value = CDORevisionUtil.createFeatureMapEntry(innerFeature, innerCopy); |
| } |
| |
| return value; |
| } |
| }; |
| |
| public static final CDOType JAVA_CLASS = new ObjectType("JAVA_CLASS", EcorePackage.EJAVA_CLASS) //$NON-NLS-1$ |
| { |
| @Override |
| protected String doCopyValue(Object value) |
| { |
| return (String)value; |
| } |
| |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeString((String)value); |
| } |
| |
| @Override |
| public String doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readString(); |
| } |
| |
| @Override |
| public Object convertToEMF(EClassifier eType, Object value) |
| { |
| return EcoreUtil.createFromString((EDataType)eType, (String)value); |
| } |
| |
| @Override |
| public Object convertToCDO(EClassifier eType, Object value) |
| { |
| return EcoreUtil.convertToString((EDataType)eType, value); |
| } |
| }; |
| |
| public static final CDOType JAVA_OBJECT = new ObjectType("JAVA_OBJECT", EcorePackage.EJAVA_CLASS) //$NON-NLS-1$ |
| { |
| @Override |
| protected Object doCopyValue(Object value) |
| { |
| return value; |
| } |
| |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeByteArray((byte[])value); |
| } |
| |
| @Override |
| public byte[] doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readByteArray(); |
| } |
| |
| @Override |
| public Object convertToEMF(EClassifier eType, Object value) |
| { |
| return EcoreUtil.createFromString((EDataType)eType, (String)value); |
| } |
| |
| @Override |
| public Object convertToCDO(EClassifier eType, Object value) |
| { |
| return EcoreUtil.convertToString((EDataType)eType, value); |
| } |
| }; |
| |
| public static final CDOType CUSTOM = new ObjectType("CUSTOM", 0) //$NON-NLS-1$ |
| { |
| @Override |
| protected String doCopyValue(Object value) |
| { |
| return (String)value; |
| } |
| |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeString((String)value); |
| } |
| |
| @Override |
| public String doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readString(); |
| } |
| |
| @Override |
| public Object convertToEMF(EClassifier eType, Object value) |
| { |
| return value == CDORevisionData.NIL ? DynamicValueHolder.NIL : EcoreUtil.createFromString((EDataType)eType, |
| (String)value); |
| } |
| |
| @Override |
| public Object convertToCDO(EClassifier eType, Object value) |
| { |
| return value == DynamicValueHolder.NIL ? CDORevisionData.NIL : EcoreUtil.convertToString((EDataType)eType, value); |
| } |
| }; |
| |
| /** |
| * TODO Transfer integers! |
| */ |
| public static final CDOType ENUM_ORDINAL = new ObjectType("ENUM_ORDINAL", -1) //$NON-NLS-1$ |
| { |
| @Override |
| protected Integer doCopyValue(Object value) |
| { |
| return (Integer)value; |
| } |
| |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| out.writeInt((Integer)value); |
| } |
| |
| @Override |
| public Integer doReadValue(CDODataInput in) throws IOException |
| { |
| return in.readInt(); |
| } |
| |
| @Override |
| public Object convertToCDO(EClassifier type, Object value) |
| { |
| for (EEnumLiteral literal : ((EEnum)type).getELiterals()) |
| { |
| if (literal == value || literal.getInstance() == value) |
| { |
| return literal.getValue(); |
| } |
| } |
| |
| throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOTypeImpl.23"), value)); //$NON-NLS-1$ |
| } |
| |
| @Override |
| public Object convertToEMF(EClassifier type, Object value) |
| { |
| return ((EEnum)type).getEEnumLiteral((Integer)value).getInstance(); |
| } |
| }; |
| |
| public static final CDOType ENUM_LITERAL = new ObjectType("ENUM_LITERAL", -2) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| EEnum eEnum; |
| if (value instanceof EEnumLiteral) |
| { |
| eEnum = ((EEnumLiteral)value).getEEnum(); |
| } |
| else |
| { |
| eEnum = findEnum((InternalCDOPackageRegistry)out.getPackageRegistry(), value); |
| } |
| |
| out.writeCDOClassifierRef(eEnum); |
| out.writeInt(((Enumerator)value).getValue()); |
| } |
| |
| @Override |
| protected Object doReadValue(CDODataInput in) throws IOException |
| { |
| EEnum eEnum = (EEnum)in.readCDOClassifierRefAndResolve(); |
| int ordinal = in.readInt(); |
| |
| EEnumLiteral literal = eEnum.getEEnumLiteral(ordinal); |
| if (literal == null) |
| { |
| throw new IllegalArgumentException("Enum literal " + ordinal + " not found in " + eEnum); |
| } |
| |
| return literal.getInstance(); |
| } |
| |
| private EEnum findEnum(InternalCDOPackageRegistry registry, Object value) |
| { |
| Set<String> keys = registry.getAllKeys(); |
| |
| // First try all the packages that are already resolved |
| for (String nsURI : keys) |
| { |
| Object possiblePackage = registry.getWithDelegation(nsURI, false); |
| if (possiblePackage instanceof EPackage) |
| { |
| EPackage ePackage = (EPackage)possiblePackage; |
| EEnum eEnum = findEnum(ePackage, value); |
| if (eEnum != null) |
| { |
| return eEnum; |
| } |
| } |
| } |
| |
| // Then try all the package descriptors |
| for (String nsURI : keys) |
| { |
| Object possiblePackage = registry.getWithDelegation(nsURI, false); |
| if (possiblePackage instanceof EPackage.Descriptor) |
| { |
| EPackage ePackage = registry.getEPackage(nsURI); |
| EEnum eEnum = findEnum(ePackage, value); |
| if (eEnum != null) |
| { |
| return eEnum; |
| } |
| } |
| } |
| |
| throw new IllegalArgumentException("EENum instance " + value.getClass().getName() + " not supported"); |
| } |
| |
| private EEnum findEnum(EPackage ePackage, Object value) |
| { |
| for (EClassifier eClassifier : ePackage.getEClassifiers()) |
| { |
| if (eClassifier instanceof EEnum) |
| { |
| EEnum eEnum = (EEnum)eClassifier; |
| if (eEnum.getInstanceClass() != null && eEnum.getInstanceClass() == value.getClass()) |
| { |
| return eEnum; |
| } |
| } |
| } |
| |
| return null; |
| } |
| }; |
| |
| public static final CDOType BLOB = new ObjectType("BLOB", -3) //$NON-NLS-1$ |
| { |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| CDOLobUtil.write(out, (CDOBlob)value); |
| } |
| |
| @Override |
| public CDOBlob doReadValue(CDODataInput in) throws IOException |
| { |
| return CDOLobUtil.readBlob(in); |
| } |
| }; |
| |
| public static final CDOType CLOB = new ObjectType("CLOB", -4) //$NON-NLS-1$ |
| { |
| @Override |
| public void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| CDOLobUtil.write(out, (CDOClob)value); |
| } |
| |
| @Override |
| public CDOClob doReadValue(CDODataInput in) throws IOException |
| { |
| return CDOLobUtil.readClob(in); |
| } |
| }; |
| |
| public static final CDOType OBJECT_ARRAY = new ObjectType("OBJECT_ARRAY", -5) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| Object[] objects = (Object[])value; |
| out.writeInt(objects.length); |
| for (Object object : objects) |
| { |
| writeTypeAndValue(out, object); |
| } |
| } |
| |
| @Override |
| protected Object[] doReadValue(CDODataInput in) throws IOException |
| { |
| int size = in.readInt(); |
| Object[] objects = new Object[size]; |
| for (int i = 0; i < size; i++) |
| { |
| objects[i] = readTypeAndValue(in); |
| } |
| |
| return objects; |
| } |
| |
| @Override |
| public Object doAdjustReferences(CDOReferenceAdjuster adjuster, Object value, EStructuralFeature feature, int index) |
| { |
| Object[] objects = (Object[])value; |
| int i = 0; |
| for (Object object : objects) |
| { |
| if (object instanceof CDOID) |
| { |
| objects[i] = adjuster.adjustReference(object, feature, i); |
| } |
| else |
| { |
| objects[i] = object; |
| } |
| |
| ++i; |
| } |
| |
| return objects; |
| } |
| }; |
| |
| public static final CDOType MAP = new ObjectType("MAP", -6) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| @SuppressWarnings("unchecked") |
| Map<Object, Object> map = (Map<Object, Object>)value; |
| out.writeInt(map.size()); |
| |
| for (Entry<Object, Object> entry : map.entrySet()) |
| { |
| writeTypeAndValue(out, entry.getKey()); |
| writeTypeAndValue(out, entry.getValue()); |
| } |
| } |
| |
| @Override |
| protected Map<Object, Object> doReadValue(CDODataInput in) throws IOException |
| { |
| Map<Object, Object> result = new HashMap<Object, Object>(); |
| int size = in.readInt(); |
| for (int i = 0; i < size; i++) |
| { |
| Object key = readTypeAndValue(in); |
| Object value = readTypeAndValue(in); |
| result.put(key, value == CDOID.NULL ? null : value); |
| } |
| |
| return result; |
| } |
| }; |
| |
| public static final CDOType SET = new ObjectType("SET", -7) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| @SuppressWarnings("unchecked") |
| Set<Object> set = (Set<Object>)value; |
| out.writeInt(set.size()); |
| for (Object element : set) |
| { |
| writeTypeAndValue(out, element); |
| } |
| } |
| |
| @Override |
| protected Set<Object> doReadValue(CDODataInput in) throws IOException |
| { |
| Set<Object> result = new HashSet<Object>(); |
| int size = in.readInt(); |
| for (int i = 0; i < size; i++) |
| { |
| Object element = readTypeAndValue(in); |
| result.add(element == CDOID.NULL ? null : element); |
| } |
| |
| return result; |
| } |
| }; |
| |
| public static final CDOType LIST = new ObjectType("LIST", -8) //$NON-NLS-1$ |
| { |
| @Override |
| protected void doWriteValue(CDODataOutput out, Object value) throws IOException |
| { |
| @SuppressWarnings("unchecked") |
| List<Object> list = (List<Object>)value; |
| out.writeInt(list.size()); |
| for (Object element : list) |
| { |
| writeTypeAndValue(out, element); |
| } |
| } |
| |
| @Override |
| protected List<Object> doReadValue(CDODataInput in) throws IOException |
| { |
| List<Object> result = new ArrayList<Object>(); |
| int size = in.readInt(); |
| for (int i = 0; i < size; i++) |
| { |
| Object element = readTypeAndValue(in); |
| result.add(element == CDOID.NULL ? null : element); |
| } |
| |
| return result; |
| } |
| }; |
| |
| private String name; |
| |
| private byte typeID; |
| |
| private boolean canBeNull; |
| |
| private Object defaultValue; |
| |
| private CDOTypeImpl(String name, int typeID, boolean canBeNull, Object defaultValue) |
| { |
| ids[typeID - Byte.MIN_VALUE] = this; |
| |
| this.name = name; |
| this.typeID = (byte)typeID; |
| this.canBeNull = canBeNull; |
| this.defaultValue = defaultValue; |
| } |
| |
| private CDOTypeImpl(String name, int typeID, boolean canBeNull) |
| { |
| this(name, typeID, canBeNull, null); |
| } |
| |
| public String getName() |
| { |
| return name; |
| } |
| |
| public byte getTypeID() |
| { |
| return typeID; |
| } |
| |
| public boolean canBeNull() |
| { |
| return canBeNull; |
| } |
| |
| public Object getDefaultValue() |
| { |
| return defaultValue; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return name; |
| } |
| |
| public final Object copyValue(Object value) |
| { |
| if (value == null || value == CDORevisionData.NIL) |
| { |
| return value; |
| } |
| |
| return doCopyValue(value); |
| } |
| |
| protected Object doCopyValue(Object value) |
| { |
| return value; |
| } |
| |
| public void write(CDODataOutput out) throws IOException |
| { |
| out.writeByte(typeID); |
| } |
| |
| final public Object adjustReferences(CDOReferenceAdjuster adjuster, Object value, EStructuralFeature feature, |
| int index) |
| { |
| return value == null ? null : doAdjustReferences(adjuster, value, feature, index); |
| } |
| |
| protected Object doAdjustReferences(CDOReferenceAdjuster adjuster, Object value, EStructuralFeature feature, |
| int indexs) |
| { |
| return value; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public Object convertToEMF(EClassifier feature, Object value) |
| { |
| return value; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public Object convertToCDO(EClassifier feature, Object value) |
| { |
| return value; |
| } |
| |
| protected void writeTypeAndValue(CDODataOutput out, Object object) throws IOException |
| { |
| CDOType cdoType = CDOModelUtil.getTypeOfObject(object); |
| out.writeByte(cdoType.getTypeID()); |
| cdoType.writeValue(out, object); |
| } |
| |
| protected Object readTypeAndValue(CDODataInput in) throws IOException |
| { |
| byte typeID = in.readByte(); |
| CDOType cdoType = CDOModelUtil.getType(typeID); |
| return cdoType.readValue(in); |
| } |
| |
| public static CDOType getType(byte typeID) |
| { |
| CDOTypeImpl type = ids[typeID - Byte.MIN_VALUE]; |
| if (type == null) |
| { |
| throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOModelUtil.6"), typeID)); |
| } |
| |
| return type; |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private static abstract class ObjectType extends CDOTypeImpl |
| { |
| public ObjectType(String name, int typeID) |
| { |
| super(name, typeID, true); |
| } |
| |
| public final void writeValue(CDODataOutput out, Object value) throws IOException |
| { |
| if (value == null) |
| { |
| out.writeByte(OPCODE_NULL); |
| } |
| else if (value == CDORevisionData.NIL) |
| { |
| out.writeByte(OPCODE_NIL); |
| } |
| else |
| { |
| out.writeByte(OPCODE_NORMAL); |
| doWriteValue(out, value); |
| } |
| } |
| |
| protected abstract void doWriteValue(CDODataOutput out, Object value) throws IOException; |
| |
| public final Object readValue(CDODataInput in) throws IOException |
| { |
| byte opcode = in.readByte(); |
| switch (opcode) |
| { |
| case OPCODE_NORMAL: |
| return doReadValue(in); |
| |
| case OPCODE_NULL: |
| return null; |
| |
| case OPCODE_NIL: |
| return CDORevisionData.NIL; |
| |
| default: |
| throw new IllegalStateException("Illegal opcode: " + opcode); |
| } |
| } |
| |
| protected abstract Object doReadValue(CDODataInput in) throws IOException; |
| } |
| } |