/*
 NeoDatis ODB : Native Object Database (odb.info@neodatis.org)
 Copyright (C) 2007 NeoDatis Inc. http://www.neodatis.org

 "This file is part of the NeoDatis ODB open source object database".

 NeoDatis ODB is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 NeoDatis ODB is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.neodatis.odb.core.layers.layer2.meta;

import java.util.Map;

import org.neodatis.odb.ODBRuntimeException;
import org.neodatis.odb.OID;
import org.neodatis.odb.core.NeoDatisError;
import org.neodatis.odb.impl.core.layers.layer3.engine.StorageEngineConstant;
import org.neodatis.tool.wrappers.OdbClassUtil;
import org.neodatis.tool.wrappers.OdbString;
import org.neodatis.tool.wrappers.list.IOdbList;
import org.neodatis.tool.wrappers.list.OdbArrayList;

/**
 * To keep info about a non native object. The NonNativeObjectInfo is the meta representation and is a class of the Layer in NeoDatis architecture (http://wiki.neodatis.org/odb-layers).
 * 
 * The NonNativeObjectInfo (nnoi) contains all the data of the attributes of an objects. 
 * 
 * 
 * 
 *      * The object
 * The type of the object (org.neodatis.odb.core.meta.ODBType)
 * The ClassInfo of the object
 * The list of attributes (list of AbstractObjectInfo)
 * The ObjectInfoHeader that holds :
 *           o The object position (in the ODB file)
 *           o The Object OID
 *           o The previous Object OID
 *           o The next object OID
 *           o The ClassInfo OID
 *           o The ids (local id, to idenitfy the attribute) of the attributes
 *           o The OID or position of the attributes
 * 
 * 
* * @author olivier s * */ public class NonNativeObjectInfo extends AbstractObjectInfo { /** The object being represented */ protected transient Object object; private ClassInfo classInfo; // private List attributeValues; private ObjectInfoHeader objectHeader; private AbstractObjectInfo[] attributeValues; /** To keep track of all non native objects , not used for instance */ private IOdbList allNonNativeObjects; private int maxNbattributes; public NonNativeObjectInfo() { super(null); } public NonNativeObjectInfo(ObjectInfoHeader oip, ClassInfo classInfo) { super(null); this.classInfo = classInfo; this.objectHeader = oip; if (classInfo != null) { this.maxNbattributes = classInfo.getMaxAttributeId(); this.attributeValues = new AbstractObjectInfo[maxNbattributes]; } this.allNonNativeObjects = null;// new // OdbArrayList(); } public NonNativeObjectInfo(ClassInfo classInfo) { super(null); this.classInfo = classInfo; this.objectHeader = new ObjectInfoHeader(-1, null, null, (classInfo != null ? classInfo.getId() : null), null, null); if (classInfo != null) { this.maxNbattributes = classInfo.getMaxAttributeId(); this.attributeValues = new AbstractObjectInfo[maxNbattributes]; } this.allNonNativeObjects = null;// new // OdbArrayList(); } public NonNativeObjectInfo(Object object, ClassInfo info, AbstractObjectInfo[] values, long[] attributesIdentification, int[] attributeIds) { super(ODBType.getFromName(info.getFullClassName())); this.object = object; this.classInfo = info; this.attributeValues = values; this.maxNbattributes = classInfo.getMaxAttributeId(); if (attributeValues == null) { this.attributeValues = new AbstractObjectInfo[maxNbattributes]; } this.objectHeader = new ObjectInfoHeader(-1, null, null, (classInfo != null ? classInfo.getId() : null), attributesIdentification, attributeIds); this.allNonNativeObjects = new OdbArrayList(); } public ObjectInfoHeader getHeader() { return objectHeader; } /** * Return The meta representation of an attribute from its attribute id. Attribute ids are sequencial number(starting from 1) set by the classIntropector to identify attributes * @param attributeId * @return */ public AbstractObjectInfo getAttributeValueFromId(int attributeId) { return attributeValues[attributeId - 1]; } /** * Return the class info of the object. The Class Info is a meta representation of the java class * @return */ public ClassInfo getClassInfo() { return classInfo; } public void setClassInfo(ClassInfo classInfo) { if (classInfo != null) { this.classInfo = classInfo; this.objectHeader.setClassInfoId(classInfo.getId()); } } public String toString() { StringBuffer buffer = new StringBuffer(classInfo.getFullClassName()).append("(").append(getOid()).append(")="); if (attributeValues == null) { buffer.append("null attribute values"); return buffer.toString(); } for (int i = 0; i < attributeValues.length; i++) { if (i != 0) { buffer.append(","); } String attributeName = (classInfo != null ? (classInfo.getAttributeInfo(i)).getName() : "?"); buffer.append(attributeName).append("="); Object object = attributeValues[i]; if (object == null) { buffer.append(" null java object - should not happen , "); } else { ODBType type = ODBType.getFromClass(attributeValues[i].getClass()); if (object instanceof NonNativeNullObjectInfo) { buffer.append("null"); continue; } if (object instanceof NonNativeDeletedObjectInfo) { buffer.append("deleted object"); continue; } if (object instanceof NativeObjectInfo) { NativeObjectInfo noi = (NativeObjectInfo) object; buffer.append(noi.toString()); continue; } if (object instanceof ObjectReference) { buffer.append(object.toString()); continue; } if (object instanceof NonNativeObjectInfo) { NonNativeObjectInfo nnoi = (NonNativeObjectInfo) object; buffer.append("@").append(nnoi.getClassInfo().getFullClassName()).append("(id=").append(nnoi.getOid()).append(")"); continue; } buffer.append("@").append(OdbClassUtil.getClassName(type.getName())); } } return buffer.toString(); } /** Returns the oid of the next object of the same type * * @return */ public OID getNextObjectOID() { return objectHeader.getNextObjectOID(); } public void setNextObjectOID(OID nextObjectOID) { this.objectHeader.setNextObjectOID(nextObjectOID); } /** Returns the oid of the previous object of the same type * * @return */ public OID getPreviousObjectOID() { return objectHeader.getPreviousObjectOID(); } public void setPreviousInstanceOID(OID previousObjectOID) { this.objectHeader.setPreviousObjectOID(previousObjectOID); } /** Gets the physical position of the object in the NeoDatis database file * */ public long getPosition() { return objectHeader.getPosition(); } public void setPosition(long position) { objectHeader.setPosition(position); } /** Gets the actual java object. May return null on client server mode as Client Server mode does work with java objects (layer1) * */ public Object getObject() { return object; } /** * Return the value of the attribute 'attribute name' * *
	 * For example, if  the class User has 2 attributes (name of type String, and profile of type Profile) calling getValueOf("name") on a nnoi (NonNativeObjectInfo) 
	 * that represents an instance of User will return its name
	 * 
* @param attributeName * @return */ public Object getValueOf(String attributeName) { int attributeId = -1; boolean isRelation = attributeName.indexOf(".") != -1; if (!isRelation) { attributeId = getClassInfo().getAttributeId(attributeName); return getAttributeValueFromId(attributeId).getObject(); } int firstDotIndex = attributeName.indexOf("."); String firstAttributeName = OdbString.substring(attributeName, 0, firstDotIndex); attributeId = getClassInfo().getAttributeId(firstAttributeName); Object object = attributeValues[attributeId]; if (object instanceof NonNativeObjectInfo) { NonNativeObjectInfo nnoi = (NonNativeObjectInfo) object; return nnoi.getValueOf(OdbString.substring(attributeName, firstDotIndex + 1, attributeName.length())); } throw new ODBRuntimeException(NeoDatisError.CLASS_INFO_DO_NOT_HAVE_THE_ATTRIBUTE.addParameter(getClassInfo().getFullClassName()) .addParameter(attributeName)); } /** * Return the value of the attribute 'attribute name'. Same as getValueOf, except that the object return is a meta representation of the real object : an AbstractObjectInfo (NonNative ObjectInfo, * NativeObjectnfo,....) * * *
	 * For example, if  the class User has 2 attributes (name of type String, and profile of type Profile) calling getValueOf("name") on a nnoi (NonNativeObjectInfo) 
	 * that represents an instance of User will return its name
	 * 
* @param attributeName * @return */ public AbstractObjectInfo getMetaValueOf(String attributeName) { int attributeId = -1; boolean isRelation = attributeName.indexOf(".") != -1; if (!isRelation) { attributeId = getClassInfo().getAttributeId(attributeName); return getAttributeValueFromId(attributeId); } int firstDotIndex = attributeName.indexOf("."); String firstAttributeName = OdbString.substring(attributeName, 0, firstDotIndex); attributeId = getClassInfo().getAttributeId(firstAttributeName); Object object = attributeValues[attributeId]; if (object instanceof NonNativeObjectInfo) { NonNativeObjectInfo nnoi = (NonNativeObjectInfo) object; return nnoi.getMetaValueOf(OdbString.substring(attributeName, firstDotIndex + 1, attributeName.length())); } throw new ODBRuntimeException(NeoDatisError.CLASS_INFO_DO_NOT_HAVE_THE_ATTRIBUTE.addParameter(getClassInfo().getFullClassName()) .addParameter(attributeName)); } /** * Used to change the value of an attribute * * @param attributeName * @param aoi */ public void setValueOf(String attributeName, AbstractObjectInfo aoi) { int attributeId = -1; boolean isRelation = attributeName.indexOf(".") != -1; if (!isRelation) { attributeId = getClassInfo().getAttributeId(attributeName); setAttributeValue(attributeId, aoi); return; } int firstDotIndex = attributeName.indexOf("."); String firstAttributeName = OdbString.substring(attributeName, 0, firstDotIndex); attributeId = getClassInfo().getAttributeId(firstAttributeName); Object object = attributeValues[attributeId]; if (object instanceof NonNativeObjectInfo) { NonNativeObjectInfo nnoi = (NonNativeObjectInfo) object; nnoi.setValueOf(OdbString.substring(attributeName, firstDotIndex + 1, attributeName.length()), aoi); } throw new ODBRuntimeException(NeoDatisError.CLASS_INFO_DO_NOT_HAVE_THE_ATTRIBUTE.addParameter(getClassInfo().getFullClassName()) .addParameter(attributeName)); } /** * Return the oid of the object * @return The oid */ public OID getOid() { if (getHeader() == null) { throw new ODBRuntimeException(NeoDatisError.UNEXPECTED_SITUATION.addParameter("Null Object Info Header")); } return getHeader().getOid(); } /** * Sets the oid of the object * @param oid */ public void setOid(OID oid) { if (getHeader() != null) { getHeader().setOid(oid); } } /** To indicate that this is a non native object info * */ public boolean isNonNativeObject() { return true; } public boolean isNull() { return false; } public void clear() { attributeValues = null; } /** * Create a copy oh this meta object * * @param onlyData * if true, only copy attributes values * @return */ public AbstractObjectInfo createCopy(Map cache, boolean onlyData) { NonNativeObjectInfo nnoi = (NonNativeObjectInfo) cache.get(objectHeader.getOid()); if (nnoi != null) { return nnoi; } if (onlyData) { ObjectInfoHeader oih = new ObjectInfoHeader(); nnoi = new NonNativeObjectInfo(object, classInfo, null, oih.getAttributesIdentification(), oih.getAttributeIds()); } else { nnoi = new NonNativeObjectInfo(object, classInfo, null, objectHeader.getAttributesIdentification(), objectHeader .getAttributeIds()); nnoi.getHeader().setOid(getHeader().getOid()); } AbstractObjectInfo[] newAttributeValues = new AbstractObjectInfo[attributeValues.length]; for (int i = 0; i < attributeValues.length; i++) { newAttributeValues[i] = attributeValues[i].createCopy(cache, onlyData); } nnoi.attributeValues = newAttributeValues; cache.put(objectHeader.getOid(), nnoi); return nnoi; } public void setAttributeValue(int attributeId, AbstractObjectInfo aoi) { attributeValues[attributeId - 1] = aoi; /* * if (aoi.isNonNativeObject()) { * allNonNativeObjects.add((NonNativeObjectInfo) aoi); } else if * (aoi.isGroup()) { // isGroup = if IsCollection || IsMap || IsArray * GroupObjectInfo goi = (GroupObjectInfo) aoi; * allNonNativeObjects.addAll(goi.getNonNativeObjects()); } */ } public AbstractObjectInfo[] getAttributeValues() { return attributeValues; } public int getMaxNbattributes() { return maxNbattributes; } /** * The performance of this method is bad. But it is not used by the engine, * only in the ODBExplorer * * @param aoi * @return */ public int getAttributeId(AbstractObjectInfo aoi) { for (int i = 0; i < attributeValues.length; i++) { if (aoi == attributeValues[i]) { return i + 1; } } return -1; } /** * Return the position where the position of an attribute is stored. * *
	 * 	If a object has 3 attributes and if it is stored at position x
	 * Then the number of attributes (3) is stored at x+StorageEngineConstant.OBJECT_OFFSET_NB_ATTRIBUTES
	 * and first attribute id definition is stored at x+StorageEngineConstant.OBJECT_OFFSET_NB_ATTRIBUTES+size-of(int)
	 * and first attribute position is stored at x+StorageEngineConstant.OBJECT_OFFSET_NB_ATTRIBUTES+size-of(int)+size-of(int)
	 * 
	 * the second attribute id is stored at x+StorageEngineConstant.OBJECT_OFFSET_NB_ATTRIBUTES+size-of(int)+size-of(int)+size-of(long)
	 * the second attribute position is stored at x+StorageEngineConstant.OBJECT_OFFSET_NB_ATTRIBUTES+size-of(int)+size-of(int)+size-of(long)+size-of(int)
	 * 
	 * 
	 * FIXME Remove dependency of StorageEngineConstant!
	 * 
	 * @param attributeId
	 * @return The position where this attribute is stored
	 */
	public long getAttributeDefinitionPosition(int attributeId) {
		long offset = StorageEngineConstant.OBJECT_OFFSET_NB_ATTRIBUTES;
		// delta =
		// Skip NbAttribute (int) +
		// Delta attribute (attributeId-1) * attribute definition size =
		// INT+LONG
		// Skip attribute Id (int)
		long delta = ODBType.INTEGER.getSize() + (attributeId - 1) * (ODBType.INTEGER.getSize() + ODBType.LONG.getSize())
				+ ODBType.INTEGER.getSize();
		return getPosition() + offset + delta;
	}

	public void setObject(Object object) {
		this.object = object;
	}

	public boolean equals(Object obj) {
		return super.equals(obj);
	}

	public int hashCode() {
		// This happens when the object is deleted
		if (objectHeader == null) {
			return -1;
		}
		return objectHeader.hashCode();
	}

	/*
	 * public IOdbList getAllNonNativeAttributes() { return
	 * allNonNativeObjects; }
	 */

	/**
	 * @param header
	 */
	public void setHeader(ObjectInfoHeader header) {
		this.objectHeader = header;

	}

}

 

Ads help maintain this website.