Skip to content

Commit

Permalink
fix handling of two-dimensional arrays in JSON deserializer
Browse files Browse the repository at this point in the history
This is used in Java BIMserver client and the respective test had been
failing. It seems that dangling references in two-dimensional arrays are
not yet handled in the JSON deserializer (they are in IFC).
  • Loading branch information
hlg committed Dec 9, 2024
1 parent acaaa4e commit b27aa20
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ public void test() throws Exception {
for (IfcBSplineSurfaceWithKnots bSplineSurface: bSplineSurfaces){
Assert.assertEquals(4, bSplineSurface.getControlPointsList().size());
for(ListOfIfcCartesianPoint pointList: bSplineSurface.getControlPointsList()){
// This assertion fails, error seems to be in client.
// 1st pointlist is of size 1, 2nd of size 2 and so on
// with duplication of the first point's coordinates
Assert.assertEquals(7, pointList.getList().size());
for(IfcCartesianPoint point: pointList.getList()){
Assert.assertNotNull(point);
Expand Down
241 changes: 124 additions & 117 deletions PluginBase/src/org/bimserver/emf/SharedJsonDeserializer.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package org.bimserver.emf;

/******************************************************************************
* Copyright (C) 2009-2019 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.BufferedReader;

package org.bimserver.emf;

/******************************************************************************
* Copyright (C) 2009-2019 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.BufferedReader;

/******************************************************************************
* Copyright (C) 2009-2018 BIMserver.org
*
Expand All @@ -36,53 +36,53 @@
* 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 java.util.UUID;

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.geometry.GeometryFactory;
import org.bimserver.models.geometry.Vector3f;
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.plugins.deserializers.DeserializerErrorCode;
import org.bimserver.shared.ListWaitingObject;
import org.bimserver.shared.WaitingList;
import org.bimserver.shared.exceptions.BimServerClientException;
import org.eclipse.emf.common.util.AbstractEList;
import org.eclipse.emf.common.util.EList;
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 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 java.util.UUID;

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.geometry.GeometryFactory;
import org.bimserver.models.geometry.Vector3f;
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.plugins.deserializers.DeserializerErrorCode;
import org.bimserver.shared.ListWaitingObject;
import org.bimserver.shared.WaitingList;
import org.bimserver.shared.exceptions.BimServerClientException;
import org.eclipse.emf.common.util.AbstractEList;
import org.eclipse.emf.common.util.EList;
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 {
Expand Down Expand Up @@ -186,11 +186,11 @@ private IdEObject processObject(IfcModelInterface model, WaitingList<Long> waiti
IdEObjectImpl object = null;
jsonReader.beginObject();
if (jsonReader.nextName().equals("_i")) {
long oid = jsonReader.nextLong();
if (jsonReader.nextName().equals("_u")) {
UUID uuid = UUID.fromString(jsonReader.nextString());
if (jsonReader.nextName().equals("_r")) {
int rid = jsonReader.nextInt();
long oid = jsonReader.nextLong();
if (jsonReader.nextName().equals("_u")) {
UUID uuid = UUID.fromString(jsonReader.nextString());
if (jsonReader.nextName().equals("_r")) {
int rid = jsonReader.nextInt();
if (jsonReader.nextName().equals("_t")) {
String type = jsonReader.nextString();
if (eClass == null) {
Expand All @@ -205,13 +205,13 @@ private IdEObject processObject(IfcModelInterface model, WaitingList<Long> waiti
if (eClass == StorePackage.eINSTANCE.getIfcHeader()) {
object = (IdEObjectImpl) StoreFactory.eINSTANCE.createIfcHeader();
} else {
object = (IdEObjectImpl) model.create(eClass, oid);
object = model.create(eClass, oid);
}
}

object.useInverses(false);
((IdEObjectImpl)object).setUuid(uuid);
((IdEObjectImpl)object).setRid(rid);
object.useInverses(false);
object.setUuid(uuid);
object.setRid(rid);

if (jsonReader.nextName().equals("_s")) {
int state = jsonReader.nextInt();
Expand Down Expand Up @@ -280,34 +280,42 @@ private IdEObject processObject(IfcModelInterface model, WaitingList<Long> waiti
innerList.add(readPrimitive(jsonReader, listFeature));
}
} else {
int innerIndex = 0;
while (jsonReader.hasNext()){
jsonReader.beginObject();
jsonReader.beginObject();
String nextName = jsonReader.nextName();
if (nextName.equals("_t")){
String t = jsonReader.nextString();
IdEObject wrappedObject = model.create(model.getPackageMetaData().getEClass(t), -1);
EList<EStructuralFeature> eAllStructuralFeatures = wrappedObject.eClass().getEAllStructuralFeatures();
for (EStructuralFeature eStructuralFeature2 : eAllStructuralFeatures) {
if (jsonReader.nextName().contentEquals(eStructuralFeature2.getName())) {
wrappedObject.eSet(eStructuralFeature2, readPrimitive(jsonReader, eStructuralFeature2));
} else {
// trouble
EList<EStructuralFeature> eAllStructuralFeatures = wrappedObject.eClass().getEAllStructuralFeatures();
for (EStructuralFeature eStructuralFeature2 : eAllStructuralFeatures) {
if (jsonReader.nextName().contentEquals(eStructuralFeature2.getName())) {
wrappedObject.eSet(eStructuralFeature2, readPrimitive(jsonReader, eStructuralFeature2));
} else {
// trouble
}
}
}
innerList.add(wrappedObject);
} else if (nextName.equals("_r")) {
// Reference
long referenceOid = jsonReader.nextLong();
if (jsonReader.nextName().equals("_t")) {
String refType = jsonReader.nextString();
IdEObject refObject = (IdEObject) model.create(model.getPackageMetaData().getEClassIncludingDependencies(refType), referenceOid);
((IdEObjectImpl)refObject).setLoadingState(State.OPPOSITE_SETTING);
model.add(refObject.getOid(), refObject);
addToList(listFeature, index, innerList, refObject);
((IdEObjectImpl)refObject).setLoadingState(State.TO_BE_LOADED);
}
} else if (nextName.equals("_r")) {
// Reference
long referenceOid = jsonReader.nextLong();
if (jsonReader.nextName().equals("_t")) {
String refType = jsonReader.nextString();
if(model.containsNoFetch(referenceOid)){
addToList(listFeature, innerIndex, innerList, model.get(referenceOid));
} else {
IdEObject refObject;
refObject = model.create(model.getPackageMetaData().getEClassIncludingDependencies(refType), referenceOid);
((IdEObjectImpl)refObject).setLoadingState(State.OPPOSITE_SETTING);
model.add(refObject.getOid(), refObject);
addToList(listFeature, innerIndex, innerList, refObject);
((IdEObjectImpl)refObject).setLoadingState(State.TO_BE_LOADED);
// TODO use waiting list to track dangling references? - see processRef method which currently does not work for 2D lists
}
}
}
jsonReader.endObject();
innerIndex++;
}
}
jsonReader.endArray();
Expand All @@ -318,24 +326,24 @@ private IdEObject processObject(IfcModelInterface model, WaitingList<Long> waiti
String t = jsonReader.nextString();
if (jsonReader.nextName().equals("_v")) {
if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) {
// Embedded array
jsonReader.beginArray();

// Here we are, IfcLineIndex should implement IfcSegmentIndexSelect, just as IfcArcIndex should

IdEObjectImpl listObject = model.create(model.getPackageMetaData().getEClassIncludingDependencies(t));
// addToList(eStructuralFeature, index, list, listObject);
EStructuralFeature listFeature = listObject.eClass().getEStructuralFeature("wrappedValue");
AbstractEList innerList = (AbstractEList) listObject.eGet(listFeature);
while (jsonReader.hasNext()){
innerList.add(readPrimitive(jsonReader, listFeature));
}
jsonReader.endArray();
list.add(listObject);
} else {
IdEObject wrappedObject = (IdEObject) model.create(model.getPackageMetaData().getEClass(t), -1);
EStructuralFeature wv = wrappedObject.eClass().getEStructuralFeature("wrappedValue");
wrappedObject.eSet(wv, readPrimitive(jsonReader, wv));
// Embedded array
jsonReader.beginArray();

// Here we are, IfcLineIndex should implement IfcSegmentIndexSelect, just as IfcArcIndex should

IdEObjectImpl listObject = model.create(model.getPackageMetaData().getEClassIncludingDependencies(t));
// addToList(eStructuralFeature, index, list, listObject);
EStructuralFeature listFeature = listObject.eClass().getEStructuralFeature("wrappedValue");
AbstractEList innerList = (AbstractEList) listObject.eGet(listFeature);
while (jsonReader.hasNext()){
innerList.add(readPrimitive(jsonReader, listFeature));
}
jsonReader.endArray();
list.add(listObject);
} else {
IdEObject wrappedObject = (IdEObject) model.create(model.getPackageMetaData().getEClass(t), -1);
EStructuralFeature wv = wrappedObject.eClass().getEStructuralFeature("wrappedValue");
wrappedObject.eSet(wv, readPrimitive(jsonReader, wv));
list.add(wrappedObject);
}
} else {
Expand Down Expand Up @@ -364,7 +372,6 @@ private IdEObject processObject(IfcModelInterface model, WaitingList<Long> waiti
if (jsonReader.nextName().equals("_t")) {
String refType = jsonReader.nextString();
EClass referenceEClass = model.getPackageMetaData().getEClassIncludingDependencies(refType);

if (model.getNoFetch(refOid) != null) {
processRef(model, waitingList, object, eStructuralFeature, index, list, refOid);
} else {
Expand Down Expand Up @@ -486,7 +493,7 @@ private IdEObject processObject(IfcModelInterface model, WaitingList<Long> waiti
}
} else {
LOGGER.info("_r expected");
}
}
} else {
LOGGER.info("_u expected");
}
Expand Down Expand Up @@ -583,7 +590,7 @@ private Object readPrimitive(JsonReader jsonReader, EStructuralFeature eStructur
return eEnum.getEEnumLiteral(jsonReader.nextString()).getInstance();
}
} else {
throw new DeserializeException(DeserializerErrorCode.UNIMPLEMENTED_BIMSERVER_FEATURE, "Unimplemented type " + eStructuralFeature.getEType().getName());
throw new DeserializeException(DeserializerErrorCode.UNIMPLEMENTED_BIMSERVER_FEATURE, "Unimplemented type " + eStructuralFeature.getEType().getName());
}
}
}

0 comments on commit b27aa20

Please sign in to comment.