Java tutorial
package org.bimserver.emf; /****************************************************************************** * Copyright (C) 2009-2016 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<http://www.gnu.org/licenses/>}. *****************************************************************************/ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.bimserver.emf.IdEObjectImpl.State; import org.bimserver.models.ifc2x3tc1.Ifc2x3tc1Factory; import org.bimserver.models.ifc2x3tc1.IfcGloballyUniqueId; import org.bimserver.models.store.IfcHeader; import org.bimserver.models.store.StoreFactory; import org.bimserver.models.store.StorePackage; import org.bimserver.plugins.deserializers.DeserializeException; import org.bimserver.shared.ListWaitingObject; import org.bimserver.shared.SingleWaitingObject; import org.bimserver.shared.WaitingList; import org.bimserver.shared.exceptions.BimServerClientException; import org.eclipse.emf.common.util.AbstractEList; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcorePackage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Charsets; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import nl.tue.buildingsmart.schema.Attribute; import nl.tue.buildingsmart.schema.EntityDefinition; import nl.tue.buildingsmart.schema.InverseAttribute; public class SharedJsonDeserializer { private static final Logger LOGGER = LoggerFactory.getLogger(SharedJsonDeserializer.class); private boolean skipInverses; public SharedJsonDeserializer(boolean skipInverses) { this.skipInverses = skipInverses; } @SuppressWarnings("rawtypes") public IfcModelInterface read(InputStream in, IfcModelInterface model, boolean checkWaitingList) throws DeserializeException { if (model.getPackageMetaData().getSchemaDefinition() == null) { throw new DeserializeException("No SchemaDefinition available"); } WaitingList<Long> waitingList = new WaitingList<Long>(); final boolean log = false; if (log) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { IOUtils.copy(in, baos); File file = new File("debug.json"); System.out.println(file.getAbsolutePath()); FileUtils.writeByteArrayToFile(file, baos.toByteArray()); } catch (IOException e) { e.printStackTrace(); } in = new ByteArrayInputStream(baos.toByteArray()); } JsonReader jsonReader = new JsonReader(new InputStreamReader(in, Charsets.UTF_8)); int nrObjects = 0; try { JsonToken peek = jsonReader.peek(); if (peek != null && peek == JsonToken.BEGIN_OBJECT) { jsonReader.beginObject(); peek = jsonReader.peek(); while (peek == JsonToken.NAME) { String nextName = jsonReader.nextName(); if (nextName.equals("objects")) { jsonReader.beginArray(); while (jsonReader.hasNext()) { nrObjects++; processObject(model, waitingList, jsonReader, null); } jsonReader.endArray(); } else if (nextName.equals("header")) { IfcHeader ifcHeader = (IfcHeader) processObject(model, waitingList, jsonReader, StorePackage.eINSTANCE.getIfcHeader()); model.getModelMetaData().setIfcHeader(ifcHeader); } peek = jsonReader.peek(); } jsonReader.endObject(); } } catch (IOException e) { LOGGER.error("", e); } catch (IfcModelInterfaceException e) { LOGGER.error("", e); } finally { LOGGER.info("# Objects: " + nrObjects); try { jsonReader.close(); } catch (IOException e) { LOGGER.error("", e); } } boolean checkUnique = false; if (checkUnique) { for (IdEObject idEObject : model.getValues()) { for (EStructuralFeature eStructuralFeature : idEObject.eClass().getEAllStructuralFeatures()) { Object value = idEObject.eGet(eStructuralFeature); if (eStructuralFeature instanceof EReference) { if (eStructuralFeature.isMany()) { List list = (List) value; if (eStructuralFeature.isUnique()) { Set<Object> t = new HashSet<>(); for (Object v : list) { if (t.contains(v)) { // LOGGER.error("NOT UNIQUE " + idEObject.eClass().getName() + "." + eStructuralFeature.getName()); } t.add(v); } } } } } } } if (checkWaitingList && waitingList.size() > 0) { try { waitingList.dumpIfNotEmpty(); } catch (BimServerClientException e) { e.printStackTrace(); } throw new DeserializeException("Waitinglist should be empty (" + waitingList.size() + ")"); } return model; } @SuppressWarnings({ "rawtypes", "unchecked" }) private IdEObject processObject(IfcModelInterface model, WaitingList<Long> waitingList, JsonReader jsonReader, EClass eClass) throws IOException, DeserializeException, IfcModelInterfaceException { IdEObjectImpl object = null; jsonReader.beginObject(); if (jsonReader.nextName().equals("_i")) { long oid = jsonReader.nextLong(); if (jsonReader.nextName().equals("_t")) { String type = jsonReader.nextString(); if (eClass == null) { eClass = model.getPackageMetaData().getEClassIncludingDependencies(type); } if (eClass == null) { throw new DeserializeException("No class found with name " + type); } if (model.containsNoFetch(oid)) { object = (IdEObjectImpl) model.getNoFetch(oid); } else { if (eClass == StorePackage.eINSTANCE.getIfcHeader()) { object = (IdEObjectImpl) StoreFactory.eINSTANCE.createIfcHeader(); } else { object = (IdEObjectImpl) model.create(eClass, oid); } } if (jsonReader.nextName().equals("_s")) { int state = jsonReader.nextInt(); if (state == 1) { object.setLoadingState(State.LOADED); while (jsonReader.hasNext()) { String featureName = jsonReader.nextName(); boolean embedded = false; if (featureName.startsWith("_r")) { featureName = featureName.substring(2); } else if (featureName.startsWith("_e")) { embedded = true; featureName = featureName.substring(2); } EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(featureName); if (eStructuralFeature == null) { throw new DeserializeException( "Unknown field (" + featureName + ") on class " + eClass.getName()); } if (eStructuralFeature.isMany()) { jsonReader.beginArray(); if (eStructuralFeature instanceof EAttribute) { List list = (List) object.eGet(eStructuralFeature); List<String> stringList = null; if (eStructuralFeature.getEType() == EcorePackage.eINSTANCE.getEDoubleObject() || eStructuralFeature.getEType() == EcorePackage.eINSTANCE .getEDouble()) { EStructuralFeature asStringFeature = eClass .getEStructuralFeature(eStructuralFeature.getName() + "AsString"); stringList = (List<String>) object.eGet(asStringFeature); } while (jsonReader.hasNext()) { Object e = readPrimitive(jsonReader, eStructuralFeature); list.add(e); if (eStructuralFeature.getEType() == EcorePackage.eINSTANCE.getEDouble()) { double val = (Double) e; stringList.add("" + val); // TODO // this // is // losing // precision, // maybe // also // send // the // string // value? } } } else if (eStructuralFeature instanceof EReference) { int index = 0; AbstractEList list = (AbstractEList) object.eGet(eStructuralFeature); while (jsonReader.hasNext()) { if (embedded) { JsonToken peek = jsonReader.peek(); if (peek == JsonToken.NUMBER) { long refOid = jsonReader.nextLong(); processRef(model, waitingList, object, eStructuralFeature, index, list, refOid); } else { jsonReader.beginObject(); String nextName = jsonReader.nextName(); if (nextName.equals("_t")) { String t = jsonReader.nextString(); IdEObject wrappedObject = (IdEObject) model .create(model.getPackageMetaData().getEClass(t), -1); if (jsonReader.nextName().equals("_v")) { EStructuralFeature wv = wrappedObject.eClass() .getEStructuralFeature("wrappedValue"); wrappedObject.eSet(wv, readPrimitive(jsonReader, wv)); list.add(wrappedObject); } else { // error } } else if (nextName.equals("_i")) { // Not all are embedded... long refOid = jsonReader.nextLong(); processRef(model, waitingList, object, eStructuralFeature, index, list, refOid); } jsonReader.endObject(); } } else { long refOid = jsonReader.nextLong(); processRef(model, waitingList, object, eStructuralFeature, index, list, refOid); } index++; } } jsonReader.endArray(); } else { if (eStructuralFeature instanceof EAttribute) { Object x = readPrimitive(jsonReader, eStructuralFeature); if (eStructuralFeature.getEType() == EcorePackage.eINSTANCE.getEDouble()) { EStructuralFeature asStringFeature = object.eClass() .getEStructuralFeature(eStructuralFeature.getName() + "AsString"); if (asStringFeature != null) { object.eSet(asStringFeature, "" + x); // TODO } // this // is // losing // precision, // maybe // also // send // the // string // value? } object.eSet(eStructuralFeature, x); } else if (eStructuralFeature instanceof EReference) { if (eStructuralFeature.getName().equals("GlobalId")) { IfcGloballyUniqueId globallyUniqueId = Ifc2x3tc1Factory.eINSTANCE .createIfcGloballyUniqueId(); globallyUniqueId.setWrappedValue(jsonReader.nextString()); object.eSet(eStructuralFeature, globallyUniqueId); } else if (embedded) { jsonReader.beginObject(); if (jsonReader.nextName().equals("_t")) { String t = jsonReader.nextString(); IdEObject wrappedObject = (IdEObject) model.create( model.getPackageMetaData().getEClassIncludingDependencies(t), -1); if (eStructuralFeature.getEAnnotation("dbembed") != null) { for (EStructuralFeature eStructuralFeature2 : wrappedObject.eClass() .getEAllStructuralFeatures()) { String fn = jsonReader.nextName(); if (fn.equals(eStructuralFeature2.getName())) { wrappedObject.eSet(eStructuralFeature2, readPrimitive(jsonReader, eStructuralFeature2)); } else { throw new DeserializeException( fn + " / " + eStructuralFeature2.getName()); } } object.eSet(eStructuralFeature, wrappedObject); } else { if (jsonReader.nextName().equals("_v")) { EStructuralFeature wv = wrappedObject.eClass() .getEStructuralFeature("wrappedValue"); wrappedObject.eSet(wv, readPrimitive(jsonReader, wv)); object.eSet(eStructuralFeature, wrappedObject); } } } jsonReader.endObject(); } else { long refOid = jsonReader.nextLong(); boolean isInverse = false; EntityDefinition entityBN = model.getPackageMetaData().getSchemaDefinition() .getEntityBN(object.eClass().getName()); if (entityBN != null) { // Some entities like GeometryInfo/Data are not in IFC schema, but valid Attribute attributeBN = entityBN .getAttributeBNWithSuper(eStructuralFeature.getName()); if (attributeBN != null) { if (attributeBN instanceof InverseAttribute) { isInverse = true; } } } if (!isInverse) { if (model.contains(refOid)) { object.eSet(eStructuralFeature, model.get(refOid)); } else { waitingList.add(refOid, new SingleWaitingObject(-1, object, (EReference) eStructuralFeature)); } } } } } } } else { // state not_loaded } if (waitingList.containsKey(oid)) { waitingList.updateNode(oid, eClass, object); } model.add(object.getOid(), object); } else { LOGGER.info("_s expected"); } } else { LOGGER.info("_t expected"); } } else { LOGGER.info("_i expected"); } jsonReader.endObject(); return object; } @SuppressWarnings({ "unchecked", "rawtypes" }) private void processRef(IfcModelInterface model, WaitingList<Long> waitingList, IdEObjectImpl object, EStructuralFeature eStructuralFeature, int index, AbstractEList list, long refOid) throws DeserializeException { EntityDefinition entityBN = model.getPackageMetaData().getSchemaDefinition() .getEntityBN(object.eClass().getName()); Attribute attributeBN = entityBN.getAttributeBNWithSuper(eStructuralFeature.getName()); if (skipInverses && attributeBN instanceof InverseAttribute && ((EReference) eStructuralFeature).getEOpposite() != null) { // skip } else { if (model.contains(refOid)) { EObject referencedObject = model.get(refOid); if (referencedObject != null) { EClass referenceEClass = referencedObject.eClass(); if (((EClass) eStructuralFeature.getEType()).isSuperTypeOf(referenceEClass)) { while (list.size() <= index) { list.addUnique(referencedObject); } } else { throw new DeserializeException(-1, referenceEClass.getName() + " cannot be stored in " + eStructuralFeature.getName()); } } } else { waitingList.add(refOid, new ListWaitingObject(-1, object, (EReference) eStructuralFeature, index)); } } } private Object readPrimitive(JsonReader jsonReader, EStructuralFeature eStructuralFeature) throws IOException { EClassifier eClassifier = eStructuralFeature.getEType(); if (eClassifier == EcorePackage.eINSTANCE.getEString()) { return jsonReader.nextString(); } else if (eClassifier == EcorePackage.eINSTANCE.getEDouble()) { return jsonReader.nextDouble(); } else if (eClassifier == EcorePackage.eINSTANCE.getEBoolean()) { return jsonReader.nextBoolean(); } else if (eClassifier == EcorePackage.eINSTANCE.getEInt()) { return jsonReader.nextInt(); } else if (eClassifier == EcorePackage.eINSTANCE.getELong()) { return jsonReader.nextLong(); } else if (eClassifier == EcorePackage.eINSTANCE.getEIntegerObject()) { return jsonReader.nextInt(); } else if (eClassifier == EcorePackage.eINSTANCE.getEByteArray()) { return Base64.decodeBase64(jsonReader.nextString()); } else if (eClassifier == EcorePackage.eINSTANCE.getEDate()) { long timestamp = jsonReader.nextLong(); return new Date(timestamp); } else if (eClassifier == EcorePackage.eINSTANCE.getEFloat()) { return (float) jsonReader.nextDouble(); } else if (eClassifier == EcorePackage.eINSTANCE.getEEnum()) { EEnum eEnum = (EEnum) eStructuralFeature.getEType(); return eEnum.getEEnumLiteral(jsonReader.nextString()).getInstance(); } else if (eClassifier instanceof EClass) { if (eStructuralFeature.getEType().getName().equals("IfcGloballyUniqueId")) { IfcGloballyUniqueId ifcGloballyUniqueId = Ifc2x3tc1Factory.eINSTANCE.createIfcGloballyUniqueId(); ifcGloballyUniqueId.setWrappedValue(jsonReader.nextString()); return ifcGloballyUniqueId; } else { throw new RuntimeException(); } } else if (eClassifier instanceof EEnum) { EEnum eEnum = (EEnum) eStructuralFeature.getEType(); if (jsonReader.peek() == JsonToken.BOOLEAN) { return eEnum.getEEnumLiteral(jsonReader.nextBoolean() ? "TRUE" : "FALSE").getInstance(); } else { return eEnum.getEEnumLiteral(jsonReader.nextString()).getInstance(); } } else { throw new RuntimeException("Unimplemented type " + eStructuralFeature.getEType().getName()); } } }