org.bimserver.ifc.xml.serializer.IfcXmlSerializer 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.xml.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.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringEscapeUtils;
import org.bimserver.emf.IfcModelInterface;
import org.bimserver.ifc.IfcSerializer;
import org.bimserver.models.ifc2x3tc1.Tristate;
import org.bimserver.models.store.StringType;
import org.bimserver.plugins.serializers.ProgressReporter;
import org.bimserver.plugins.serializers.ProjectInfo;
import org.bimserver.plugins.serializers.SerializerException;
import org.bimserver.utils.UTF8PrintWriter;
import org.eclipse.emf.common.util.AbstractEList;
import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.ecore.EAttribute;
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.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import nl.tue.buildingsmart.schema.Attribute;
import nl.tue.buildingsmart.schema.BaseType;
import nl.tue.buildingsmart.schema.DefinedType;
import nl.tue.buildingsmart.schema.EntityDefinition;
import nl.tue.buildingsmart.schema.ExplicitAttribute;
import nl.tue.buildingsmart.schema.IntegerType;
import nl.tue.buildingsmart.schema.ListType;
import nl.tue.buildingsmart.schema.RealType;
import nl.tue.buildingsmart.schema.SetType;
public abstract class IfcXmlSerializer extends IfcSerializer {
private PrintWriter out;
private Map objectToOidMap;
private int tabs;
@Override
public void init(IfcModelInterface model, ProjectInfo projectInfo, boolean normalizeOids) throws SerializerException {
super.init(model, projectInfo, normalizeOids);
objectToOidMap = new HashMap((int) model.size());
for (Long key : model.keySet()) {
objectToOidMap.put(model.get(key), key);
}
}
@Override
public boolean write(OutputStream out, ProgressReporter progressReporter) throws SerializerException {
switch (getMode()) {
case HEADER:
setMode(Mode.BODY);
case BODY: {
this.out = new UTF8PrintWriter(out);
printLineTabbed("");
tabs = 0;
printLineTabbed("");
tabs++;
printLineTabbed("");
tabs++;
Set keySet = model.getObjects().keySet();
int progress = 0;
for (Long key : keySet) {
EObject object = model.getObjects().get(key);
if (object.eClass().getEStructuralFeature("wrappedValue") == null) {
store(key, object);
}
if (progressReporter != null) progressReporter.update(progress++, keySet.size());
}
tabs--;
printLineTabbed(" ");
tabs--;
printLineTabbed(" ");
this.out.flush();
setMode(Mode.FINISHED);
return true;
}
case FINISHED: {
return false;
}
case FOOTER:
return false;
default:
break;
}
return false;
}
public void write(File file, ProgressReporter progressReporter) throws FileNotFoundException, SerializerException {
write(new FileOutputStream(file), progressReporter);
}
/**
* Writes the XML structural equivalent of each IFC "record" in an IFC file.
*
* @param key
* record ID
* @param object
* IFC object with this record ID
* @throws SerializerException
*/
/*
* Because of insufficient info in the EMF model a few hacks were necessary
* to guarantee XML code that obeys the IFC XML schema. When these
* shortcomings are solved the hacks will be removed. (PW)
*/
private void store(Long key, EObject object) throws SerializerException {
if (object.eClass().getEAnnotation("hidden") != null) {
return;
}
printLineTabbed("<" + object.eClass().getName() + " id=\"i" + key + "\">");
tabs++;
for (EStructuralFeature structuralFeature : object.eClass().getEAllStructuralFeatures()) {
if (structuralFeature.getEAnnotation("hidden") != null) {
continue;
}
EntityDefinition entityBN = getPackageMetaData().getSchemaDefinition().getEntityBN(object.eClass().getName().toUpperCase());
Attribute attributeBN = entityBN != null ? entityBN.getAttributeBNWithSuper(structuralFeature.getName()) : null;
boolean derived = entityBN.isDerived(structuralFeature.getName());
if (structuralFeature instanceof EAttribute || (!getPackageMetaData().isInverse((EReference)structuralFeature) && !structuralFeature.isDerived() && !derived)) {
// Because of small deviations in the string/float/string
// conversions some float attributes are also stored in the
// original string representations. These auxiliary attribute
// types should be skipped in the XML output. Though their value
// must be used instead of the original attribute types.
if (structuralFeature.getEAnnotation("hidden") != null) {
continue;
}
Object value = object.eGet(structuralFeature);
if (value == null) {
} else {
EClassifier classifier = structuralFeature.getEType();
if (!structuralFeature.isMany()) {
if (classifier instanceof EClass) {
EObject eObject = (EObject) value;
EClass type = eObject.eClass();
printTabbed("<" + structuralFeature.getName() + ">");
if (type.getEAnnotation("wrapped") != null) {
// Only references should print the type,
// GlobalId is an exception, because in EMF we
// chose to create a Class for GlobalId, because
// of the (added) backreference to IfcRoot
boolean showTag = (structuralFeature instanceof EReference && !(structuralFeature.getName().equals("GlobalId")));
if (showTag) {
print("<" + type.getName() + ">");
}
EStructuralFeature wrappedFeature = type.getEStructuralFeature("wrappedValue");
Object get = ((EObject) value).eGet(wrappedFeature);
if (wrappedFeature.getEType() == EcorePackage.eINSTANCE.getEString()) {
printEscaped((String) get);
} else {
if (!type.getName().equals("IfcLogical") && !type.getName().equals("IfcBoolean")) {
print(get.toString());
} else {
writeValue(get);
}
}
if (showTag) {
print("" + type.getName() + ">");
}
} else {
String ref = "i" + objectToOidMap.get(value);
print("<" + type.getName() + " xsi:nil=\"true\" ref=\"" + ref + "\"/>");
}
printLine("" + structuralFeature.getName() + ">");
} else if (classifier instanceof EEnum) {
Enumerator enumerator = (Enumerator) value;
if (enumerator.getName().equals("NULL")) {
continue;
}
printTabbed("<" + structuralFeature.getName() + ">");
writeValue(value);
printLine("" + structuralFeature.getName() + ">");
} else if (classifier instanceof EDataType) {
printTabbed("<" + structuralFeature.getName() + ">");
print(value.toString());
printLine("" + structuralFeature.getName() + ">");
}
} else {
AbstractEList> list = (AbstractEList>) value;
String type = "set";
if (attributeBN instanceof ExplicitAttribute) {
ExplicitAttribute explicitAttribute = (ExplicitAttribute) attributeBN;
if (list.isEmpty() && explicitAttribute.isOptional())
continue;
BaseType domain = explicitAttribute.getDomain(true);
if (domain == null) {
domain = explicitAttribute.getDomain();
if (domain instanceof DefinedType) {
if (((DefinedType) domain).getName().equals("IfcCompoundPlaneAngleMeasure")) {
type = "list";
}
}
}
if (domain instanceof SetType) {
type = "set";
} else if (domain instanceof ListType) {
type = "list";
if (structuralFeature.getName().equals("Polygon")) {
type = "list-unique";
}
}
}
printLineTabbed("<" + structuralFeature.getName() + " ex:cType=\"" + type + "\" >");
tabs++;
int i = 0;
for (Object o : list) {
if (o instanceof EObject) {
EObject eObject = (EObject) o;
EStructuralFeature wrappedFeature = eObject.eClass().getEStructuralFeature("wrappedValue");
if (wrappedFeature != null) {
Object val = eObject.eGet(wrappedFeature);
printLineTabbed("<" + eObject.eClass().getName() + " pos=\"" + i + "\">" + val + "" + eObject.eClass().getName() + ">");
} else {
String ref = "i" + objectToOidMap.get(eObject);
printLineTabbed("<" + eObject.eClass().getName() + " pos=\"" + i + "\" xsi:nil=\"true\" ref=\"" + ref + "\" />");
}
i++;
} else {
if (attributeBN instanceof ExplicitAttribute) {
BaseType domain = ((ExplicitAttribute) attributeBN).getDomain(true);
if (attributeBN.getName().equals("RefLatitude") || attributeBN.getName().equals("RefLongitude")) {
printLineTabbed("" + o + " ");
} else if (domain instanceof ListType) {
BaseType elementType = ((ListType) domain).getElement_type();
if (elementType instanceof DefinedType) {
DefinedType def = (DefinedType) elementType;
printLineTabbed("<" + def.getName() + ">" + o + "" + def.getName() + ">");
} else if (elementType instanceof RealType) {
printLineTabbed("" + o + " ");
} else if (elementType instanceof IntegerType) {
printLineTabbed("" + o + " ");
} else if (elementType instanceof StringType) {
printLineTabbed("" + o + " ");
}
}
}
}
}
tabs--;
printLineTabbed("" + structuralFeature.getName() + ">");
// }
}
}
}
}
tabs--;
printLineTabbed("" + object.eClass().getName() + ">");
}
private void writeValue(Object value) {
if (value instanceof Tristate && value == Tristate.UNDEFINED) {
print("unknown");
} else {
print(value.toString().toLowerCase());
}
}
private void printEscaped(String value) {
out.print(StringEscapeUtils.escapeXml(value));
}
private void writeTabs(int tabs) {
for (int i = 0; i < tabs; i++) {
out.print("\t");
}
}
private void printTabbed(String str) {
writeTabs(tabs);
out.print(str);
}
private void printLineTabbed(String str) {
writeTabs(tabs);
out.println(str);
}
private void print(String str) {
out.print(str);
}
private void printLine(String str) {
out.println(str);
}
}