All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bimserver.shared.ByteBufferVirtualObject Maven / Gradle / Ivy

Go to download

Shared libraries, common parent for both BIMserver and BimServerClientLib

There is a newer version: 2.0.0
Show newest version
package org.bimserver.shared;

/******************************************************************************
 * Copyright (C) 2009-2018  BIMserver.org
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see {@literal}.
 *****************************************************************************/

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.bimserver.BimserverDatabaseException;
import org.bimserver.emf.PackageMetaData;
import org.bimserver.plugins.deserializers.DatabaseInterface;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ByteBufferVirtualObject extends AbstractByteBufferVirtualObject implements ListCapableVirtualObject, VirtualObject {
	private static final Logger LOGGER = LoggerFactory.getLogger(VirtualObject.class);
	private EClass eClass;
	private long oid;
	private QueryContext reusable;
	private int currentListStart = -1;
	private int currentListSize;
	private int featureCounter = 0;
	
	public ByteBufferVirtualObject(QueryContext reusable, EClass eClass, int capacity) {
		super(capacity);
		this.reusable = reusable;
		this.eClass = eClass;
		this.oid = reusable.getDatabaseInterface().newOid(eClass);

		int unsettedLength = reusable.getPackageMetaData().getUnsettedLength(eClass);
		buffer.put(new byte[unsettedLength]);
	}

	private boolean useUnsetBit(EStructuralFeature feature) {
		// TODO non-unsettable boolean values can also be stored in these bits
		if (feature.isUnsettable()) {
			return true;
		} else {
			if (feature.isMany()) {
				return true;
			}
			if (feature.getDefaultValue() == null || (feature.getDefaultValue() != null && feature.getDefaultValue() == null)) {
				return true;
			}
		}
		return false;
	}
	
	public void eUnset(EStructuralFeature feature) throws BimserverDatabaseException {
		if (useUnsetBit(feature)) {
			int pos = featureCounter / 8;
			byte b = buffer.get(pos);
			b |= (1 << (featureCounter % 8));
			buffer.put(pos, b);
		} else {
			if (feature instanceof EReference) {
				if (feature.isMany()) {
					ensureCapacity(buffer.position(), 4);
					buffer.putInt(0);
				} else {
					ensureCapacity(buffer.position(), 2);
					buffer.order(ByteOrder.LITTLE_ENDIAN);
					buffer.putShort((short)-1);
					buffer.order(ByteOrder.BIG_ENDIAN);
				}
			} else if (feature.getEType() instanceof EEnum) {
				writeEnum(feature, null);
			} else {
				writePrimitiveValue(feature, null);
			}
		}
		incrementFeatureCounter(feature);
	}

	public void setAttribute(EStructuralFeature feature, Object value) throws BimserverDatabaseException {
		if (feature.isMany()) {
			throw new UnsupportedOperationException("Feature isMany not supported by setAttribute");
		} else {
			if (feature.getEType() instanceof EEnum) {
				writeEnum(feature, value);
			} else if (feature.getEType() instanceof EClass) {
				if (value == null) {
					ensureCapacity(buffer.position(), 2);
					buffer.order(ByteOrder.LITTLE_ENDIAN);
					buffer.putShort((short) -1);
					buffer.order(ByteOrder.BIG_ENDIAN);
				} else if (value instanceof WrappedVirtualObject) {
					ByteBuffer otherBuffer = ((WrappedVirtualObject) value).write();
					ensureCapacity(buffer.position(), otherBuffer.position());
					buffer.put(otherBuffer.array(), 0, otherBuffer.position());
//					writeWrappedValue(getPid(), getRid(), (WrappedVirtualObject) value, getPackageMetaData());
				} else {
					throw new UnsupportedOperationException("??");
				}
			} else if (feature.getEType() instanceof EDataType) {
				writePrimitiveValue(feature, value);
			}
		}
		incrementFeatureCounter(feature);
	}

	private void incrementFeatureCounter(EStructuralFeature feature) {
		featureCounter++;
	}

	private void writeEnum(EStructuralFeature feature, Object value) {
		if (value == null) {
			ensureCapacity(buffer.position(), 4);
			buffer.putInt(-1);
		} else {
			EEnum eEnum = (EEnum) feature.getEType();
			EEnumLiteral eEnumLiteral = eEnum.getEEnumLiteralByLiteral(((Enum) value).toString());
			ensureCapacity(buffer.position(), 4);
			if (eEnumLiteral != null) {
				buffer.putInt(eEnumLiteral.getValue());
			} else {
				LOGGER.error(((Enum) value).toString() + " not found");
				buffer.putInt(-1);
			}
		}
	}

	public Object eGet(EStructuralFeature feature) {
		throw new UnsupportedOperationException();
	}
	
	public EClass eClass() {
		return eClass;
	}
	
	public long getOid() {
		return oid;
	}
	
	public ByteBuffer write() throws BimserverDatabaseException {
		EClass eClass = getDatabaseInterface().getEClassForOid(getOid());
		if (!eClass.isSuperTypeOf(eClass())) {
			throw new BimserverDatabaseException("Object with oid " + getOid() + " is a " + eClass().getName() + " but it's cid-part says it's a " + eClass.getName());
		}
		int nrFeatures = getPackageMetaData().getNrDatabaseFeatures(eClass);
		if (featureCounter > nrFeatures) {
			throw new BimserverDatabaseException("Too many features seem to have been set on " + this.eClass.getName() + " " + featureCounter + " / " + nrFeatures);
		} else if (featureCounter < nrFeatures) {
			throw new BimserverDatabaseException("Not all features seem to have been set on " + this.eClass.getName() + " " + featureCounter + " / " + nrFeatures);
		}
		
		return buffer;
//
//		if (buffer.position() != bufferSize) {
//			throw new BimserverDatabaseException("Value buffer sizes do not match for " + eClass().getName() + " " + buffer.position() + "/" + bufferSize);
//		}
//		return buffer;
	}
	
	private PackageMetaData getPackageMetaData() {
		return reusable.getPackageMetaData();
	}

	private DatabaseInterface getDatabaseInterface() {
		return reusable.getDatabaseInterface();
	}

	public int getPid() {
		return reusable.getPid();
	}
	
	public int getRid() {
		return reusable.getRid();
	}
	
//	private void writeWrappedValue(int pid, int rid, WrappedVirtualObject wrappedValue, PackageMetaData packageMetaData) throws BimserverDatabaseException {
//		EStructuralFeature eStructuralFeature = wrappedValue.eClass().getEStructuralFeature("wrappedValue");
//		Short cid = getDatabaseInterface().getCidOfEClass(wrappedValue.eClass());
//		ensureCapacity(buffer.position(), 2);
//		buffer.putShort((short) -cid);
//		writePrimitiveValue(eStructuralFeature, wrappedValue.getValue(eStructuralFeature));
//		if (wrappedValue.eClass().getName().equals("IfcGloballyUniqueId")) {
//			EClass eClass = packageMetaData.getEClass("IfcGloballyUniqueId");
//			if (wrappedValue.getOid() == -1) {
//				((VirtualObject) wrappedValue).setOid(getDatabaseInterface().newOid(eClass));
//			}
//			getDatabaseInterface().save(wrappedValue);
//		}
//	}
	
	public void setOid(long oid) {
		this.oid = oid;
	}

	public void setListItem(EStructuralFeature feature, int index, Object value) throws BimserverDatabaseException {
		if (currentListStart == -1) {
			throw new BimserverDatabaseException("Not currently writing a list");
		}
		if (index + 1 > currentListSize) {
			currentListSize = index + 1;
		}
		if (value instanceof ByteBufferWrappedVirtualObject) {
			ByteBuffer otherBuffer = ((ByteBufferWrappedVirtualObject)value).write();
			ensureCapacity(buffer.position(), otherBuffer.position());
			buffer.put(otherBuffer.array(), 0, otherBuffer.position());
		} else if (value instanceof ByteBufferList) {
			ByteBuffer otherBuffer = ((ByteBufferList)value).write();
			ensureCapacity(buffer.position(), otherBuffer.position());
			buffer.put(otherBuffer.array(), 0, otherBuffer.position());
		} else if (value instanceof PrimitiveByteBufferList) {
			ByteBuffer otherBuffer = ((PrimitiveByteBufferList)value).write();
			ensureCapacity(buffer.position(), otherBuffer.position());
			buffer.put(otherBuffer.array(), 0, otherBuffer.position());
		} else {
			writePrimitiveValue(feature, value);
		}
	}
	
	public void setListItemReference(EStructuralFeature structuralFeature, int index, EClass referenceEClass, Long referencedOid, int bufferPosition) throws BimserverDatabaseException {
		int pos;
		if (bufferPosition == -1) {
			if (currentListStart == -1) {
				throw new BimserverDatabaseException("Not currently writing a list");
			}
			if (index + 1 > currentListSize) {
				currentListSize = index + 1;
			}
			pos = buffer.position();
		} else {
			pos = bufferPosition;
		}
		ensureCapacity(pos, 8);
		if (referencedOid < 0) {
			throw new BimserverDatabaseException("Writing a reference with oid " + referencedOid + ", this is not supposed to happen, referenced: " + referencedOid + " " + referencedOid + " from " + getOid() + " " + this);
		}
		buffer.order(ByteOrder.LITTLE_ENDIAN);
		buffer.putLong(pos, referencedOid);
		buffer.order(ByteOrder.BIG_ENDIAN);
		if (bufferPosition == -1) {
			buffer.position(buffer.position() + 8);
		}
	}

	public void save() throws BimserverDatabaseException {
		getDatabaseInterface().save(this);
	}

	public void saveOverwrite() throws BimserverDatabaseException {
		getDatabaseInterface().saveOverwrite(this);
	}
	
	@Override
	public int reserveSpaceForReference(EStructuralFeature feature) {
		int pos = buffer.position();
		ensureCapacity(pos, 8);
		buffer.putLong(-1);
		incrementFeatureCounter(feature);
		return pos;
	}

	@Override
	public int reserveSpaceForListReference() throws BimserverDatabaseException {
		if (currentListStart == -1) {
			throw new BimserverDatabaseException("Not currently writing a list");
		}
		currentListSize++;
		int position = buffer.position();
		ensureCapacity(position, 8);
		buffer.putLong(-1);
		return position;
	}

	@Override
	public void startList(EStructuralFeature feature) {
		ensureCapacity(buffer.position(), 4);
		buffer.putInt(0);
		currentListStart = buffer.position();
		currentListSize = 0;
		incrementFeatureCounter(feature);
	}

	public void endList() {
		buffer.putInt(currentListStart - 4, currentListSize);
		currentListStart = -1;
	}

	@Override
	public void setReference(EStructuralFeature feature, long referenceOid, int bufferPosition) throws BimserverDatabaseException {
		if (bufferPosition == -1) {
			incrementFeatureCounter(feature);
		}
		int pos = bufferPosition == -1 ? buffer.position() : bufferPosition;
		ensureCapacity(pos, 8);
		if (referenceOid < 0) {
			throw new BimserverDatabaseException("Writing a reference with oid " + referenceOid + ", this is not supposed to happen, referenced: " + referenceOid + " " + referenceOid + " from " + getOid() + " " + this);
		}
		buffer.order(ByteOrder.LITTLE_ENDIAN);
		buffer.putLong(pos, referenceOid);
		buffer.order(ByteOrder.BIG_ENDIAN);
		if (bufferPosition == -1) {
			buffer.position(buffer.position() + 8);
		}
	}

	@Override
	public boolean useFeatureForSerialization(EStructuralFeature feature) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Object get(String name) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void set(String name, Object value) throws BimserverDatabaseException {
		setAttribute(eClass.getEStructuralFeature(name), value);
	}

	@Override
	public boolean has(String string) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean useFeatureForSerialization(EStructuralFeature feature, int index) {
		throw new UnsupportedOperationException();
	}
	
	@Override
	public String toString() {
		return "ByteBufferVirtualObject/" + eClass.getName();
	}

	@Override
	public void set(EStructuralFeature eStructuralFeature, Object val) throws BimserverDatabaseException {
		// TODO Auto-generated method stub
		
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy