org.bimserver.ifc.step.serializer.IfcStepStreamingSerializer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ifcplugins Show documentation
Show all versions of ifcplugins Show documentation
BIMserver plugin that provides IFC serializers/deserializers
The newest version!
package org.bimserver.ifc.step.serializer;
/******************************************************************************
* 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 }.
*****************************************************************************/
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.bimserver.BimserverDatabaseException;
import org.bimserver.emf.PackageMetaData;
import org.bimserver.ifc.step.deserializer.IfcParserWriterUtils;
import org.bimserver.models.geometry.GeometryPackage;
import org.bimserver.models.store.IfcHeader;
import org.bimserver.plugins.PluginConfiguration;
import org.bimserver.plugins.PluginManagerInterface;
import org.bimserver.plugins.serializers.ObjectProvider;
import org.bimserver.plugins.serializers.OidConvertingSerializer;
import org.bimserver.plugins.serializers.ProjectInfo;
import org.bimserver.plugins.serializers.SerializerException;
import org.bimserver.plugins.serializers.SerializerInputstream;
import org.bimserver.plugins.serializers.StreamingReader;
import org.bimserver.plugins.serializers.StreamingSerializer;
import org.bimserver.shared.AbstractHashMapVirtualObject;
import org.bimserver.shared.HashMapVirtualObject;
import org.bimserver.shared.HashMapWrappedVirtualObject;
import org.bimserver.shared.MinimalVirtualObject;
import org.bimserver.utils.StringUtils;
import org.bimserver.utils.UTF8PrintWriter;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
import nl.tue.buildingsmart.schema.EntityDefinition;
import nl.tue.buildingsmart.schema.SchemaDefinition;
public abstract class IfcStepStreamingSerializer implements StreamingSerializer, StreamingReader, OidConvertingSerializer {
private static final EcorePackage ECORE_PACKAGE_INSTANCE = EcorePackage.eINSTANCE;
private static final String NULL = "NULL";
private static final String OPEN_CLOSE_PAREN = "()";
private static final String ASTERISK = "*";
private static final String PAREN_CLOSE_SEMICOLON = ");";
private static final String DASH = "#";
private static final String IFC_LOGICAL = "IfcLogical";
private static final String IFC_BOOLEAN = "IfcBoolean";
private static final String DOT = ".";
private static final String COMMA = ",";
private static final String OPEN_PAREN = "(";
private static final String CLOSE_PAREN = ")";
private static final String BOOLEAN_UNDEFINED = ".U.";
private static final String DOLLAR = "$";
private static final String WRAPPED_VALUE = "wrappedValue";
private String headerSchema;
private ObjectProvider objectProvider;
private final Map oidToEid = new Long2LongOpenHashMap();
private long oidCounter = 1;
protected static enum Mode {
HEADER, BODY, FOOTER, FINISHED
}
private Mode mode = Mode.HEADER;
private IfcHeader ifcHeader;
private PackageMetaData packageMetaData;
private PrintWriter printWriter;
@Override
public boolean write(OutputStream outputStream) throws SerializerException, BimserverDatabaseException {
if (this.printWriter == null) {
this.printWriter = new UTF8PrintWriter(outputStream);
}
boolean result = false;
try {
result = processMode();
} catch (IOException e) {
throw new SerializerException(e);
}
return result;
}
public Map getOidToEid() {
return oidToEid;
}
public Mode getMode() {
return mode;
}
public void setMode(Mode mode) {
this.mode = mode;
}
@Override
public InputStream getInputStream() {
return new SerializerInputstream(this);
}
public IfcStepStreamingSerializer(PluginConfiguration pluginConfiguration) {
}
protected void setHeaderSchema(String headerSchema) {
this.headerSchema = headerSchema;
}
@Override
public void init(ObjectProvider objectProvider, ProjectInfo projectInfo, IfcHeader ifcHeader, PluginManagerInterface pluginManager, PackageMetaData packageMetaData) throws SerializerException {
this.objectProvider = objectProvider;
this.ifcHeader = ifcHeader;
this.packageMetaData = packageMetaData;
}
public void writeToOutputStream(OutputStream outputStream) throws SerializerException, BimserverDatabaseException {
this.printWriter = new UTF8PrintWriter(outputStream);
try {
while (mode != Mode.FINISHED) {
processMode();
}
} catch (Exception e) {
throw new SerializerException(e);
}
}
private boolean processMode() throws IOException, BimserverDatabaseException, SerializerException {
if (getMode() == Mode.HEADER) {
writeHeader();
setMode(Mode.BODY);
} else if (getMode() == Mode.BODY) {
HashMapVirtualObject next = objectProvider.next();
if (next != null) {
write(next);
} else {
setMode(Mode.FOOTER);
}
} else if (getMode() == Mode.FOOTER) {
writeFooter();
setMode(Mode.FINISHED);
if (printWriter != null) {
printWriter.flush();
}
} else if (getMode() == Mode.FINISHED) {
return false;
}
return true;
}
private void writeFooter() throws IOException {
println("ENDSEC;");
println("END-ISO-10303-21;");
}
private void writeHeader() throws IOException {
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
println("ISO-10303-21;");
println("HEADER;");
if (ifcHeader == null) {
Date date = new Date();
println("FILE_DESCRIPTION ((''), '2;1');");
println("FILE_NAME ('', '" + dateFormatter.format(date) + "', (''), (''), '', 'BIMserver', '');");
println("FILE_SCHEMA (('" + headerSchema + "'));");
} else {
print("FILE_DESCRIPTION ((");
print(StringUtils.concat(ifcHeader.getDescription(), "'", ", "));
println("), '" + ifcHeader.getImplementationLevel() + "');");
println("FILE_NAME ('" + ifcHeader.getFilename().replace("\\", "\\\\") + "', '" + dateFormatter.format(ifcHeader.getTimeStamp()) + "', (" + StringUtils.concat(ifcHeader.getAuthor(), "'", ", ") + "), (" + StringUtils.concat(ifcHeader.getOrganization(), "'", ", ") + "), '" + ifcHeader.getPreProcessorVersion() + "', '" + ifcHeader.getOriginatingSystem() + "', '" + ifcHeader.getAuthorization() + "');");
// println("FILE_SCHEMA (('" + ifcHeader.getIfcSchemaVersion() + "'));");
println("FILE_SCHEMA (('" + headerSchema + "'));");
}
println("ENDSEC;");
println("DATA;");
// println("//This program comes with ABSOLUTELY NO WARRANTY.");
// println("//This is free software, and you are welcome to redistribute it under certain conditions. See www.bimserver.org ");
}
private void println(String line) throws IOException {
printWriter.println(line);
}
private void print(String text) throws IOException {
printWriter.write(text);
}
private void write(HashMapVirtualObject object) throws SerializerException, IOException {
EClass eClass = object.eClass();
if (eClass.getEPackage() == GeometryPackage.eINSTANCE) {
return;
}
if (eClass.getEAnnotation("hidden") != null) {
return;
}
print(DASH);
long convertedKey = getExpressId(object);
if (convertedKey == -1) {
throw new SerializerException("Going to serialize an object with id -1 (" + object.eClass().getName() + ")");
}
print(String.valueOf(convertedKey));
print("= ");
String upperCase = packageMetaData.getUpperCase(eClass);
if (upperCase == null) {
throw new SerializerException("Type not found: " + eClass.getName());
}
print(upperCase);
print(OPEN_PAREN);
boolean isFirst = true;
EntityDefinition entityBN = getSchemaDefinition().getEntityBN(object.eClass().getName());
for (EStructuralFeature feature : eClass.getEAllStructuralFeatures()) {
if (feature.getEAnnotation("hidden") == null && (entityBN != null && (!entityBN.isDerived(feature.getName()) || entityBN.isDerivedOverride(feature.getName())))) {
EClassifier type = feature.getEType();
if (type instanceof EEnum) {
if (!isFirst) {
print(COMMA);
}
writeEnum(object, feature);
isFirst = false;
} else if (type instanceof EClass) {
EReference eReference = (EReference)feature;
if (!packageMetaData.isInverse(eReference)) {
if (!isFirst) {
print(COMMA);
}
writeEClass(object, feature);
isFirst = false;
}
} else if (type instanceof EDataType) {
if (!isFirst) {
print(COMMA);
}
writeEDataType(object, entityBN, feature);
isFirst = false;
}
}
}
println(PAREN_CLOSE_SEMICOLON);
}
private long getExpressId(HashMapVirtualObject object) {
return getExpressId(object.getOid());
}
private long getExpressId(long oid) {
if (oidToEid.containsKey(oid)) {
return oidToEid.get(oid);
} else {
long eid = oidCounter++;
oidToEid.put(oid, eid);
return eid;
}
}
private void writeEDataType(HashMapVirtualObject object, EntityDefinition entityBN, EStructuralFeature feature) throws SerializerException, IOException {
if (entityBN != null && entityBN.isDerived(feature.getName())) {
print(ASTERISK);
} else if (feature.isMany()) {
writeList(object, feature, false);
} else {
writeObject(object, feature);
}
}
private void writeEClass(HashMapVirtualObject object, EStructuralFeature feature) throws SerializerException, IOException {
Object referencedObject = object.eGet(feature);
if (referencedObject instanceof AbstractHashMapVirtualObject && ((AbstractHashMapVirtualObject)referencedObject).eClass().getEAnnotation("wrapped") != null) {
writeWrappedValue(object, feature, ((AbstractHashMapVirtualObject)referencedObject).eClass());
} else {
if (referencedObject instanceof Long) {
if (object.useFeatureForSerialization(feature)) {
print(DASH);
print(String.valueOf(getExpressId((Long) referencedObject)));
} else {
print(DOLLAR);
}
} else {
EntityDefinition entityBN = getSchemaDefinition().getEntityBN(object.eClass().getName());
if (entityBN != null && entityBN.isDerived(feature.getName())) {
print(ASTERISK);
} else if (feature.isMany()) {
writeList(object, feature, false);
} else {
writeObject(object, feature);
}
}
}
}
private void writeObject(HashMapVirtualObject object, EStructuralFeature feature) throws SerializerException, IOException {
Object ref = object.eGet(feature);
if (ref == null || (feature.isUnsettable() && !object.eIsSet(feature))) {
EClassifier type = feature.getEType();
if (type instanceof EClass) {
EStructuralFeature structuralFeature = ((EClass) type).getEStructuralFeature(WRAPPED_VALUE);
if (structuralFeature != null) {
String name = structuralFeature.getEType().getName();
if (name.equals(IFC_BOOLEAN) || name.equals(IFC_LOGICAL) || structuralFeature.getEType() == EcorePackage.eINSTANCE.getEBoolean()) {
print(BOOLEAN_UNDEFINED);
} else {
print(DOLLAR);
}
} else {
print(DOLLAR);
}
} else {
if (type == EcorePackage.eINSTANCE.getEBoolean()) {
print(BOOLEAN_UNDEFINED);
} else if (feature.isMany()) {
print("()");
} else {
print(DOLLAR);
}
}
} else {
if (ref instanceof HashMapWrappedVirtualObject) {
writeEmbedded((HashMapWrappedVirtualObject) ref);
} else if (feature.getEType() == ECORE_PACKAGE_INSTANCE.getEDouble()) {
EStructuralFeature asStringFeature = object.eClass().getEStructuralFeature(feature.getName() + "AsString");
String asString = (String) object.eGet(asStringFeature);
writeDoubleValue((Double)ref, asString, feature);
} else {
IfcParserWriterUtils.writePrimitive(ref, printWriter);
}
}
}
private void writeDoubleValue(double value, String asString, EStructuralFeature feature) throws SerializerException, IOException {
if (asString != null) {
print((String)asString);
return;
}
IfcParserWriterUtils.writePrimitive(value, printWriter);
}
private void writeEmbedded(HashMapWrappedVirtualObject eObject) throws SerializerException, IOException {
EClass class1 = eObject.eClass();
print(packageMetaData.getUpperCase(class1));
print(OPEN_PAREN);
EStructuralFeature structuralFeature = class1.getEStructuralFeature(WRAPPED_VALUE);
if (structuralFeature != null) {
Object realVal = eObject.eGet(structuralFeature);
if (structuralFeature.getEType() == ECORE_PACKAGE_INSTANCE.getEDouble()) {
EStructuralFeature asStringFeature = eObject.eClass().getEStructuralFeature(structuralFeature.getName() + "AsString");
String asString = (String) eObject.eGet(asStringFeature);
writeDoubleValue((Double)realVal, asString, structuralFeature);
} else {
IfcParserWriterUtils.writePrimitive(realVal, printWriter);
}
}
print(CLOSE_PAREN);
}
/*
* Use force when you want to force serialization (usually when serializing the second child of twodimensionalarray)
*/
private void writeList(MinimalVirtualObject object, EStructuralFeature feature, boolean force) throws SerializerException, IOException {
List> list = (List>) object.eGet(feature);
if (list == null) {
if (feature.isUnsettable()) {
print(DOLLAR);
} else {
print(OPEN_CLOSE_PAREN);
}
return;
}
List> doubleStingList = null;
if (feature.getEType() == EcorePackage.eINSTANCE.getEDouble()) {
EStructuralFeature doubleStringFeature = feature.getEContainingClass().getEStructuralFeature(feature.getName() + "AsString");
if (doubleStringFeature == null) {
throw new SerializerException("Field " + feature.getName() + "AsString" + " not found");
}
doubleStingList = (List>) object.eGet(doubleStringFeature);
}
if (list.isEmpty() || (!object.useFeatureForSerialization(feature) && feature.getEAnnotation("twodimensionalarray") == null && !force)) {
if (!feature.isUnsettable()) {
print(OPEN_CLOSE_PAREN);
} else {
print("$");
}
} else {
print(OPEN_PAREN);
boolean first = true;
int index = 0;
for (Object listObject : list) {
if (object.useFeatureForSerialization(feature, index) || (feature.getEAnnotation("twodimensionalarray") != null || force)) {
if (!first) {
print(COMMA);
}
if (feature instanceof EReference && listObject instanceof Long) {
print(DASH);
print(String.valueOf(getExpressId((Long)listObject)));
} else {
if (listObject == null) {
print(DOLLAR);
} else {
if (listObject instanceof HashMapWrappedVirtualObject && feature.getEType().getEAnnotation("wrapped") != null) {
HashMapWrappedVirtualObject eObject = (HashMapWrappedVirtualObject) listObject;
Object realVal = eObject.eGet(eObject.eClass().getEStructuralFeature("wrappedValue"));
if (realVal instanceof Double) {
Object stringVal = eObject.eGet(eObject.eClass().getEStructuralFeature("wrappedValueAsString"));
if (stringVal != null) {
print((String) stringVal);
} else {
IfcParserWriterUtils.writePrimitive(realVal, printWriter);
}
} else {
IfcParserWriterUtils.writePrimitive(realVal, printWriter);
}
} else if (listObject instanceof HashMapVirtualObject && feature.getEAnnotation("twodimensionalarray") != null) {
HashMapVirtualObject td = (HashMapVirtualObject)listObject;
writeList(td, td.eClass().getEStructuralFeature("List"), true);
} else if (listObject instanceof HashMapVirtualObject) {
HashMapVirtualObject td = (HashMapVirtualObject)listObject;
print(packageMetaData.getUpperCase(td.eClass()));
print(OPEN_PAREN);
writeList(td, td.eClass().getEStructuralFeature("wrappedValue"), false);
print(CLOSE_PAREN);
} else if (listObject instanceof HashMapWrappedVirtualObject) {
HashMapWrappedVirtualObject eObject = (HashMapWrappedVirtualObject) listObject;
EClass class1 = eObject.eClass();
EStructuralFeature structuralFeature = class1.getEStructuralFeature(WRAPPED_VALUE);
if (structuralFeature != null) {
Object realVal = eObject.eGet(structuralFeature);
print(packageMetaData.getUpperCase(class1));
print(OPEN_PAREN);
if (realVal instanceof Double) {
EStructuralFeature asStringFeature = eObject.eClass().getEStructuralFeature(structuralFeature.getName() + "AsString");
String asString = (String) eObject.eGet(asStringFeature);
writeDoubleValue((Double)realVal, asString, structuralFeature);
} else {
IfcParserWriterUtils.writePrimitive(realVal, printWriter);
}
print(CLOSE_PAREN);
} else {
if (feature.getEAnnotation("twodimensionalarray") != null) {
writeList(eObject, eObject.eClass().getEStructuralFeature("List"), true);
} else {
// LOGGER.info("Unfollowable reference found from " + object + "(" + object.getOid() + ")." + feature.getName() + " to " + eObject + "(" + eObject.getOid() + ")");
}
}
} else {
if (doubleStingList != null) {
if (index < doubleStingList.size()) {
String val = (String)doubleStingList.get(index);
if (val == null) {
IfcParserWriterUtils.writePrimitive(listObject, printWriter);
} else {
print(val);
}
} else {
IfcParserWriterUtils.writePrimitive(listObject, printWriter);
}
} else {
IfcParserWriterUtils.writePrimitive(listObject, printWriter);
}
}
}
}
first = false;
}
index++;
}
print(CLOSE_PAREN);
}
}
private void writeWrappedValue(HashMapVirtualObject object, EStructuralFeature feature, EClass ec) throws SerializerException, IOException {
Object get = object.eGet(feature);
boolean isWrapped = ec.getEAnnotation("wrapped") != null;
EStructuralFeature structuralFeature = ec.getEStructuralFeature(WRAPPED_VALUE);
if (get instanceof HashMapWrappedVirtualObject) {
boolean isDefinedWrapped = feature.getEType().getEAnnotation("wrapped") != null;
HashMapWrappedVirtualObject betweenObject = (HashMapWrappedVirtualObject) get;
if (betweenObject != null) {
if (isWrapped && isDefinedWrapped) {
Object val = betweenObject.eGet(structuralFeature);
String name = structuralFeature.getEType().getName();
if ((name.equals(IFC_BOOLEAN) || name.equals(IFC_LOGICAL)) && val == null) {
print(BOOLEAN_UNDEFINED);
} else if (structuralFeature.getEType() == ECORE_PACKAGE_INSTANCE.getEDouble()) {
EStructuralFeature asStringFeature = betweenObject.eClass().getEStructuralFeature(feature.getName() + "AsString");
String asString = (String) betweenObject.eGet(asStringFeature);
writeDoubleValue((Double)val, asString, feature);
} else {
IfcParserWriterUtils.writePrimitive(val, printWriter);
}
} else {
writeEmbedded(betweenObject);
}
}
} else if (get instanceof EList>) {
EList> list = (EList>) get;
if (list.isEmpty()) {
if (!feature.isUnsettable()) {
print(OPEN_CLOSE_PAREN);
} else {
print("$");
}
} else {
print(OPEN_PAREN);
boolean first = true;
for (Object o : list) {
if (!first) {
print(COMMA);
}
HashMapVirtualObject object2 = (HashMapVirtualObject) o;
Object val = object2.eGet(structuralFeature);
if (structuralFeature.getEType() == ECORE_PACKAGE_INSTANCE.getEDouble()) {
EStructuralFeature asStringFeature = object2.eClass().getEStructuralFeature(feature.getName() + "AsString");
String asString = (String) object2.eGet(asStringFeature);
writeDoubleValue((Double)val, asString, structuralFeature);
} else {
IfcParserWriterUtils.writePrimitive(val, printWriter);
}
first = false;
}
print(CLOSE_PAREN);
}
} else if (get == null) {
EClassifier type = structuralFeature.getEType();
if (type.getName().equals("IfcBoolean") || type.getName().equals("IfcLogical") || type == ECORE_PACKAGE_INSTANCE.getEBoolean()) {
print(BOOLEAN_UNDEFINED);
} else {
EntityDefinition entityBN = getSchemaDefinition().getEntityBN(object.eClass().getName());
if (entityBN != null && entityBN.isDerived(feature.getName())) {
print(ASTERISK);
} else {
print(DOLLAR);
}
}
} else {
System.out.println("Unimplemented?");
}
}
private SchemaDefinition getSchemaDefinition() {
return packageMetaData.getSchemaDefinition();
}
private void writeEnum(HashMapVirtualObject object, EStructuralFeature feature) throws SerializerException, IOException {
Object val = object.eGet(feature);
if (feature.getEType().getName().equals("Tristate")) {
if (val == null) {
print(DOLLAR);
} else {
IfcParserWriterUtils.writePrimitive(val, printWriter);
}
} else {
if (val == null) {
print(DOLLAR);
} else {
if (((Enum>) val).toString().equals(NULL)) {
print(DOLLAR);
} else {
print(DOT);
print(val.toString());
print(DOT);
}
}
}
}
}