| /* |
| * Copyright (c) 2010-2013, 2015 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: |
| * Ibrahim Sallam - initial API and implementation |
| */ |
| package org.eclipse.emf.cdo.server.internal.objectivity.mapper; |
| |
| import org.eclipse.emf.cdo.common.revision.CDORevision; |
| import org.eclipse.emf.cdo.server.internal.objectivity.bundle.OM; |
| import org.eclipse.emf.cdo.server.internal.objectivity.db.ObjyObject; |
| import org.eclipse.emf.cdo.server.internal.objectivity.db.ObjySchema; |
| |
| import org.eclipse.net4j.util.om.trace.ContextTracer; |
| |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| |
| import com.objy.as.app.Class_Object; |
| import com.objy.as.app.Numeric_Value; |
| import com.objy.as.app.Proposed_Basic_Attribute; |
| import com.objy.as.app.Proposed_Class; |
| import com.objy.as.app.Proposed_Property; |
| import com.objy.as.app.VArray_Object; |
| import com.objy.as.app.d_Access_Kind; |
| import com.objy.as.app.d_Attribute; |
| import com.objy.as.app.d_Class; |
| import com.objy.as.app.d_Module; |
| import com.objy.as.app.ooBaseType; |
| |
| import java.util.Date; |
| |
| /** |
| * @author Ibrahim Sallam |
| */ |
| public abstract class NumericManyTypeMapper extends BasicTypeMapper implements IManyTypeMapper |
| { |
| |
| protected abstract Object fromNumericValue(Numeric_Value numericValue, boolean isNull); |
| |
| protected abstract Numeric_Value toNumericValue(Object value); |
| |
| protected abstract ooBaseType getObjyBaseType(); |
| |
| private static final ContextTracer TRACER_DEBUG = new ContextTracer(OM.DEBUG, NumericManyTypeMapper.class); |
| |
| public static NumericManyTypeMapper.TMBoolean TMBOOLEAN = new TMBoolean(); |
| |
| public static NumericManyTypeMapper.TMByte TMBYTE = new TMByte(); |
| |
| public static NumericManyTypeMapper.TMChar TMCHAR = new TMChar(); |
| |
| public static NumericManyTypeMapper.TMDate TMDATE = new TMDate(); |
| |
| public static NumericManyTypeMapper.TMDouble TMDOUBLE = new TMDouble(); |
| |
| public static NumericManyTypeMapper.TMFloat TMFLOAT = new TMFloat(); |
| |
| public static NumericManyTypeMapper.TMInteger TMINTEGER = new TMInteger(); |
| |
| public static NumericManyTypeMapper.TMLong TMLONG = new TMLong(); |
| |
| public static NumericManyTypeMapper.TMShort TMSHORT = new TMShort(); |
| |
| // --------------------------------- |
| // Schema |
| // --------------------------------- |
| |
| private String embeddedClassName() |
| { |
| return "oo_" + getObjyBaseType() + "_Class"; |
| } |
| |
| private d_Class getEmbeddedClass() |
| { |
| d_Class embeddedClass = ObjySchema.getTopModule().resolve_class(embeddedClassName()); |
| // System.out.println("OBJY: Resolving className: " + embeddedClassName() + " - d_Class: " + embeddedClass); |
| return embeddedClass; |
| } |
| |
| private boolean createEmbeddedClass() |
| { |
| boolean bDone = true; |
| |
| d_Module top_mod = ObjySchema.getTopModule(); |
| boolean inProcess = top_mod.proposed_classes().hasNext(); |
| |
| Proposed_Class propClass = top_mod.propose_new_class(embeddedClassName()); |
| |
| propClass.add_basic_attribute(com.objy.as.app.d_Module.LAST, d_Access_Kind.d_PUBLIC, // Access kind |
| embeddedAttributeName, // Attribute name |
| 1, // # elements in fixed-size array |
| getObjyBaseType() // Type of numeric data |
| ); // Default value |
| |
| propClass.add_basic_attribute(com.objy.as.app.d_Module.LAST, d_Access_Kind.d_PUBLIC, // Access kind |
| embeddedAttributeNull, // Attribute name |
| 1, // # elements in fixed-size array |
| ooBaseType.ooBOOLEAN// Type of numeric data |
| ); // Default value |
| |
| // System.out.println("OBJY: Propose Creating new class: " + embeddedClassName()); |
| |
| // ObjySchema.getTopModule().propose_new_class(propClass); |
| if (!inProcess) |
| { |
| top_mod.activate_proposals(true, true); |
| } |
| |
| return bDone; |
| } |
| |
| /** |
| * |
| */ |
| public boolean createSchema(Proposed_Class proposedClass, EStructuralFeature feature) |
| { |
| if (TRACER_DEBUG.isEnabled()) |
| { |
| TRACER_DEBUG.trace("Adding attribute " + feature.getName() + " " + this.getClass().getName()); |
| } |
| |
| // create an embedded class (attributeType, attributeIsNull). |
| // TODO - we might need to move this to the .objectivity.schema, since it's |
| // independent of the model classes. |
| |
| if (getEmbeddedClass() == null && !createEmbeddedClass()) |
| { |
| return false; |
| } |
| |
| // create array of embedded class type. |
| proposedClass.add_varray_attribute(com.objy.as.app.d_Module.LAST, d_Access_Kind.d_PUBLIC, // Access kind |
| getAttributeName(feature), // Attribute name |
| 1, embeddedClassName()); |
| |
| return false; |
| } |
| |
| /** |
| * TODO - this is a simple change to the attribute, make it handle more complex cases. I also don't think it does |
| * handle the arrays. |
| * |
| * @param proposedooClass |
| * @param feature |
| */ |
| public void modifySchema(Proposed_Class proposedooClass, EStructuralFeature feature) |
| { |
| Proposed_Property prop = proposedooClass.resolve_property(getAttributeName(feature)); |
| |
| if (prop instanceof Proposed_Basic_Attribute) |
| { |
| Proposed_Basic_Attribute attr = (Proposed_Basic_Attribute)prop; |
| attr.change_base_type(getObjyBaseType()); |
| } |
| } |
| |
| /** |
| * TBD - Fixed size array attributes can't be accessed, so we can't validate This!!! OFJ (Fix it) |
| */ |
| public boolean validate(d_Attribute dAttribute, EStructuralFeature feature) |
| { |
| System.out.println(">>>OBJYIMPL: NumericManyTypeMapper.validate() - not implemented."); |
| return true; |
| // d_Class varrayClass = dAttribute.class_type_of(); |
| // d_Class embeddedClass = varrayClass. |
| // Class_Position position = embeddedClass.position_in_class(getAttributeName(feature)); |
| // //d_Type type = ooAttribute.type_of(); |
| // d_Type type = embeddedClass.attribute_at_position(position).type_of(); |
| // if (TRACER_DEBUG.isEnabled()) { |
| // TRACER_DEBUG.trace(getAttributeName(feature) + " " |
| // + ((Basic_Type) type).base_type() + " basic type " |
| // + type.is_basic_type() + " - " + getObjyBaseType()); |
| // } |
| // return type.is_basic_type() |
| // && ((Basic_Type) type).base_type() == getObjyBaseType(); |
| } |
| |
| // --------------------------------- |
| // Object |
| // --------------------------------- |
| |
| public void setValue(ObjyObject objyObject, EStructuralFeature feature, int index, Object newValue) |
| { |
| // System.out.println("OBJY: Set value in VArray at index: "+ index + " - value: " + newValue); |
| boolean isNull = newValue == null; |
| Numeric_Value numericValue = toNumericValue(newValue); |
| Numeric_Value isNullValue = isNull ? numericTrue : numericFalse; |
| |
| Class_Object embedded = getArray(objyObject, feature).get_class_obj(index); |
| |
| embedded.set_numeric(valueAttributePosition, numericValue); |
| embedded.set_numeric(nullAttributePosition, isNullValue); |
| } |
| |
| // get a single object/value at index. |
| public Object getValue(ObjyObject objyObject, EStructuralFeature feature, int index) |
| { |
| Numeric_Value numericValue = null; |
| |
| Class_Object embedded = getArray(objyObject, feature).get_class_obj(index); |
| |
| numericValue = embedded.get_numeric(valueAttributePosition); |
| boolean isNull = embedded.get_numeric(nullAttributePosition).booleanValue(); |
| |
| return fromNumericValue(numericValue, isNull); |
| } |
| |
| // remove a single value at index, it will set the value to default, and mark it |
| // as "null", i.e. unset. |
| public Object remove(ObjyObject objyObject, EStructuralFeature feature, int index) |
| { |
| // we'll just get the original value, and set the value to null. |
| // Numeric_Value numericValue = null; |
| |
| long size = (int)getArray(objyObject, feature).size(); |
| for (int i = index; i < size - 1; i++) |
| { |
| setValue(objyObject, feature, i, getValue(objyObject, feature, i + 1)); |
| } |
| // resize the array. |
| getArray(objyObject, feature).resize(size - 1); |
| /* |
| * Class_Object embedded = getArray(objyObject, feature).get_class_obj(index); numericValue = |
| * embedded.get_numeric(valueAttributePosition); boolean isNull = |
| * embedded.get_numeric(nullAttributePosition).booleanValue(); Object oldValue = fromNumericValue(numericValue, |
| * isNull); numericValue = toNumericValue(null); embedded.set_numeric(valueAttributePosition, numericValue); |
| * embedded.set_numeric(nullAttributePosition, numericTrue); |
| */ |
| return null; |
| } |
| |
| // add value at index (extend the collection size). |
| public void add(ObjyObject objyObject, EStructuralFeature feature, int index, Object value) |
| { |
| int arraySize = size(objyObject, feature); |
| // System.out.println("OBJY: Adding object inside VArray at index: "+ index + " - value: " + value); |
| if (index < arraySize - 1) |
| { |
| // throw new UnsupportedOperationException("adding object inside VArray?!!... Implement Me!!!"); |
| // resize the VArray. |
| VArray_Object array = getArray(objyObject, feature); |
| array.resize(arraySize + 1); |
| for (int i = arraySize; i > index; i--) |
| { |
| Class_Object newEmbedded = array.get_class_obj(i); |
| Class_Object oldEmbedded = array.get_class_obj(i - 1); |
| newEmbedded.set_numeric(valueAttributePosition, oldEmbedded.get_numeric(valueAttributePosition)); |
| newEmbedded.set_numeric(nullAttributePosition, oldEmbedded.get_numeric(nullAttributePosition)); |
| } |
| } |
| if (index != -1 && index > arraySize) |
| { |
| throw new UnsupportedOperationException("adding object beyond VArray size()?!!... Implement Me!!!"); |
| } |
| |
| getArray(objyObject, feature).resize(arraySize + 1); |
| |
| setValue(objyObject, feature, index, value); |
| } |
| |
| public// add all objects starting from an index. (extend the collection size). |
| void addAll(ObjyObject objyObject, EStructuralFeature feature, int index, Object[] values) |
| { |
| // System.out.println("OBJY: AddAll objects inside VArray at index: "+ index + " - values: " + values); |
| int arraySize = size(objyObject, feature); |
| if (index < arraySize - 1) |
| { |
| throw new UnsupportedOperationException("adding objects inside VArray?!!... Implement Me!!!"); |
| } |
| |
| if (index != -1 && index > arraySize) |
| { |
| throw new UnsupportedOperationException("adding objects beyond VArray size()?!!... Implement Me!!!"); |
| } |
| |
| int newSize = arraySize + values.length; |
| getArray(objyObject, feature).resize(newSize); |
| |
| for (int i = 0; i < values.length; i++) |
| { |
| setValue(objyObject, feature, arraySize + i, values[i]); |
| } |
| } |
| |
| // clear all collection. |
| public void clear(ObjyObject objyObject, EStructuralFeature feature) |
| { |
| // set the varray size to 0. |
| getArray(objyObject, feature).resize(0); |
| } |
| |
| // this is similar to addAll, but it replaces the existing ones. |
| public void setAll(ObjyObject objyObject, EStructuralFeature feature, int index, Object[] newValues) |
| { |
| |
| VArray_Object array = getArray(objyObject, feature); |
| |
| array.resize(newValues.length); |
| for (int i = 0; i < newValues.length; i++) |
| { |
| // TODO - we might need to optimize this!!! |
| setValue(objyObject, feature, i, newValues[i]); |
| } |
| } |
| |
| // get all objects/values starting from an index. |
| public Object[] getAll(ObjyObject objyObject, EStructuralFeature feature, int index, int chunkSize) |
| { |
| int size = size(objyObject, feature); |
| |
| if (chunkSize != CDORevision.UNCHUNKED) |
| { |
| size = Math.min(size, chunkSize); |
| } |
| |
| Object[] values = new Object[size]; |
| |
| // TODO - we might need to optimize this!!!! |
| for (int i = 0; i < size; i++) |
| { |
| values[i] = getValue(objyObject, feature, i + index); |
| } |
| return values; |
| } |
| |
| // return the size of the collection. |
| public int size(ObjyObject objyObject, EStructuralFeature feature) |
| { |
| return (int)getArray(objyObject, feature).size(); |
| } |
| |
| public void delete(ObjyObject objyObject, EStructuralFeature feature) |
| { |
| throw new UnsupportedOperationException("Implement me!!"); |
| } |
| |
| public void move(ObjyObject objyObject, EStructuralFeature feature, int targetIndex, int sourceIndex) |
| { |
| if (targetIndex == sourceIndex) |
| { |
| return; |
| } |
| |
| // get the object at sourceIndex. |
| Object value = getValue(objyObject, feature, sourceIndex); |
| |
| // long size = (int)getArray(objyObject, feature).size(); |
| // TODO - check boundaries... |
| |
| if (sourceIndex > targetIndex) |
| { |
| for (int i = sourceIndex; i > targetIndex; i--) |
| { |
| setValue(objyObject, feature, i, getValue(objyObject, feature, i - 1)); |
| } |
| } |
| else if (sourceIndex < targetIndex) |
| { |
| for (int i = sourceIndex; i < targetIndex; i++) |
| { |
| setValue(objyObject, feature, i, getValue(objyObject, feature, i + 1)); |
| } |
| } |
| // set the saved value at target |
| setValue(objyObject, feature, targetIndex, value); |
| |
| } |
| |
| public void initialize(Class_Object classObject, EStructuralFeature feature) |
| { |
| // TODO - verify if we need to do any initialization!!! |
| } |
| |
| protected VArray_Object getArray(ObjyObject objyObject, EStructuralFeature feature) |
| { |
| // Class_Position position = getAttributePosition(objyObject, feature); |
| String attributeName = getAttributeName(feature); |
| return objyObject.get_varray(attributeName/* position */); |
| } |
| |
| // ------------------------------------------------------------------------ |
| // ------------------- Various types -------------------------- |
| // ------------------------------------------------------------------------ |
| |
| // --------------------------- |
| // Boolean |
| // --------------------------- |
| public static class TMBoolean extends NumericManyTypeMapper |
| { |
| @Override |
| protected ooBaseType getObjyBaseType() |
| { |
| return ooBaseType.ooBOOLEAN; |
| } |
| |
| @Override |
| protected Object fromNumericValue(Numeric_Value numericValue, boolean isNull) |
| { |
| Boolean value = null; |
| if (!isNull) |
| { |
| value = numericValue.booleanValue(); |
| } |
| return value; |
| } |
| |
| @Override |
| protected Numeric_Value toNumericValue(Object value) |
| { |
| if (value == null) |
| { |
| return new Numeric_Value(false); |
| } |
| |
| return new Numeric_Value(((Boolean)value).booleanValue()); |
| } |
| } |
| |
| // --------------------------- |
| // Byte |
| // --------------------------- |
| public static class TMByte extends NumericManyTypeMapper |
| { |
| @Override |
| public ooBaseType getObjyBaseType() |
| { |
| return ooBaseType.ooINT8; |
| } |
| |
| @Override |
| protected Object fromNumericValue(Numeric_Value numericValue, boolean isNull) |
| { |
| Byte value = null; |
| if (!isNull) |
| { |
| value = numericValue.byteValue(); |
| } |
| return value; |
| |
| } |
| |
| @Override |
| protected Numeric_Value toNumericValue(Object value) |
| { |
| if (value == null) |
| { |
| return new Numeric_Value(0); |
| } |
| |
| return new Numeric_Value(((Byte)value).byteValue()); |
| } |
| } |
| |
| // --------------------------- |
| // Char |
| // --------------------------- |
| public static class TMChar extends NumericManyTypeMapper |
| { |
| @Override |
| public ooBaseType getObjyBaseType() |
| { |
| return ooBaseType.ooINT8; |
| } |
| |
| @Override |
| protected Object fromNumericValue(Numeric_Value numericValue, boolean isNull) |
| { |
| Character value = null; |
| if (!isNull) |
| { |
| value = numericValue.charValue(); |
| } |
| return value; |
| |
| } |
| |
| @Override |
| protected Numeric_Value toNumericValue(Object value) |
| { |
| if (value == null) |
| { |
| return new Numeric_Value(0); |
| } |
| |
| return new Numeric_Value(((Character)value).charValue()); |
| } |
| } |
| |
| // --------------------------- |
| // Date |
| // --------------------------- |
| public static class TMDate extends NumericManyTypeMapper |
| { |
| @Override |
| public ooBaseType getObjyBaseType() |
| { |
| return ooBaseType.ooINT64; |
| } |
| |
| @Override |
| protected Object fromNumericValue(Numeric_Value numericValue, boolean isNull) |
| { |
| Date value = null; |
| if (!isNull) |
| { |
| value = new Date(numericValue.longValue()); |
| } |
| return value; |
| |
| } |
| |
| @Override |
| protected Numeric_Value toNumericValue(Object value) |
| { |
| if (value == null) |
| { |
| return new Numeric_Value(0); |
| } |
| |
| return new Numeric_Value(((Date)value).getTime()); |
| } |
| } |
| |
| // --------------------------- |
| // Double |
| // --------------------------- |
| public static class TMDouble extends NumericManyTypeMapper |
| { |
| @Override |
| public ooBaseType getObjyBaseType() |
| { |
| return ooBaseType.ooFLOAT64; |
| } |
| |
| @Override |
| protected Object fromNumericValue(Numeric_Value numericValue, boolean isNull) |
| { |
| Double value = null; |
| if (!isNull) |
| { |
| value = numericValue.doubleValue(); |
| } |
| return value; |
| |
| } |
| |
| @Override |
| protected Numeric_Value toNumericValue(Object value) |
| { |
| if (value == null) |
| { |
| return new Numeric_Value(0.0); |
| } |
| |
| return new Numeric_Value(((Double)value).doubleValue()); |
| } |
| } |
| |
| // --------------------------- |
| // Float |
| // --------------------------- |
| public static class TMFloat extends NumericManyTypeMapper |
| { |
| @Override |
| protected ooBaseType getObjyBaseType() |
| { |
| return ooBaseType.ooFLOAT64; |
| } |
| |
| @Override |
| protected Object fromNumericValue(Numeric_Value numericValue, boolean isNull) |
| { |
| Float value = null; |
| if (!isNull) |
| { |
| value = numericValue.floatValue(); |
| } |
| return value; |
| |
| } |
| |
| @Override |
| protected Numeric_Value toNumericValue(Object value) |
| { |
| if (value == null) |
| { |
| return new Numeric_Value(0.0); |
| } |
| |
| return new Numeric_Value(((Float)value).floatValue()); |
| } |
| } |
| |
| // --------------------------- |
| // Integer |
| // --------------------------- |
| public static class TMInteger extends NumericManyTypeMapper |
| { |
| @Override |
| public ooBaseType getObjyBaseType() |
| { |
| return ooBaseType.ooINT32; |
| } |
| |
| @Override |
| protected Object fromNumericValue(Numeric_Value numericValue, boolean isNull) |
| { |
| Integer value = null; |
| if (!isNull) |
| { |
| value = numericValue.intValue(); |
| } |
| return value; |
| } |
| |
| @Override |
| protected Numeric_Value toNumericValue(Object value) |
| { |
| if (value == null) |
| { |
| return new Numeric_Value(0); |
| } |
| |
| return new Numeric_Value(((Integer)value).intValue()); |
| } |
| } |
| |
| // --------------------------- |
| // Long |
| // --------------------------- |
| public static class TMLong extends NumericManyTypeMapper |
| { |
| @Override |
| public ooBaseType getObjyBaseType() |
| { |
| return ooBaseType.ooINT64; |
| } |
| |
| @Override |
| protected Object fromNumericValue(Numeric_Value numericValue, boolean isNull) |
| { |
| Long value = null; |
| if (!isNull) |
| { |
| value = numericValue.longValue(); |
| } |
| return value; |
| |
| } |
| |
| @Override |
| protected Numeric_Value toNumericValue(Object value) |
| { |
| if (value == null) |
| { |
| return new Numeric_Value(0); |
| } |
| |
| return new Numeric_Value(((Long)value).longValue()); |
| } |
| } |
| |
| // --------------------------- |
| // Short |
| // --------------------------- |
| public static class TMShort extends NumericManyTypeMapper |
| { |
| @Override |
| public ooBaseType getObjyBaseType() |
| { |
| return ooBaseType.ooINT16; |
| } |
| |
| @Override |
| protected Object fromNumericValue(Numeric_Value numericValue, boolean isNull) |
| { |
| Short value = null; |
| if (!isNull) |
| { |
| value = numericValue.shortValue(); |
| } |
| return value; |
| } |
| |
| @Override |
| protected Numeric_Value toNumericValue(Object value) |
| { |
| if (value == null) |
| { |
| return new Numeric_Value(0); |
| } |
| |
| return new Numeric_Value(((Short)value).shortValue()); |
| } |
| } |
| |
| } |