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

org.bimserver.schemaconverter.Express2EMF Maven / Gradle / Ivy

There is a newer version: 1.5.9
Show newest version
package org.bimserver.schemaconverter;

/******************************************************************************
 * 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}.
 *****************************************************************************/

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAnnotation;
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.EEnumLiteral;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import nl.tue.buildingsmart.emf.DerivedReader;
import nl.tue.buildingsmart.express.parser.SchemaLoader;
import nl.tue.buildingsmart.schema.AggregationType;
import nl.tue.buildingsmart.schema.ArrayType;
import nl.tue.buildingsmart.schema.Attribute;
import nl.tue.buildingsmart.schema.BaseType;
import nl.tue.buildingsmart.schema.BinaryType;
import nl.tue.buildingsmart.schema.BooleanType;
import nl.tue.buildingsmart.schema.DefinedType;
import nl.tue.buildingsmart.schema.DerivedAttribute2;
import nl.tue.buildingsmart.schema.EntityDefinition;
import nl.tue.buildingsmart.schema.EnumerationType;
import nl.tue.buildingsmart.schema.ExplicitAttribute;
import nl.tue.buildingsmart.schema.IntegerBound;
import nl.tue.buildingsmart.schema.IntegerType;
import nl.tue.buildingsmart.schema.InverseAttribute;
import nl.tue.buildingsmart.schema.LogicalType;
import nl.tue.buildingsmart.schema.NamedType;
import nl.tue.buildingsmart.schema.NumberType;
import nl.tue.buildingsmart.schema.RealType;
import nl.tue.buildingsmart.schema.SchemaDefinition;
import nl.tue.buildingsmart.schema.SelectType;
import nl.tue.buildingsmart.schema.SimpleType;
import nl.tue.buildingsmart.schema.StringType;
import nl.tue.buildingsmart.schema.UnderlyingType;

public class Express2EMF {
	private static final Logger LOGGER = LoggerFactory.getLogger(Express2EMF.class);
	private final SchemaDefinition schema;
	private final EcoreFactory eFactory;
	private final EcorePackage ePackage;
	private final EPackage schemaPack;
	private final Map> directSubTypes = new HashMap>();
	private final Map simpleTypeReplacementMap = new HashMap();
	private EEnum tristate;

	public Express2EMF(File schemaFileName, String modelName, String nsUri) {
		schema = new SchemaLoader(schemaFileName.getAbsolutePath()).getSchema();
		eFactory = EcoreFactory.eINSTANCE;
		ePackage = EcorePackage.eINSTANCE;
		schemaPack = eFactory.createEPackage();
		try {
			new DerivedReader(schemaFileName, schema);
		} catch (FileNotFoundException e) {
			LOGGER.error("", e);
		}
		schemaPack.setName(modelName);
		schemaPack.setNsPrefix("iai");
		schemaPack.setNsURI(nsUri);

		createTristate();

		addClasses();
		addSupertypes();
		addSimpleTypes();
		addDerivedTypes();
		addEnumerations();
		addHackedTypes();
		addSelects();
		addAttributes();
		addInverses();
		EClass ifcBooleanClass = (EClass) schemaPack.getEClassifier("IfcBoolean");
		ifcBooleanClass.getESuperTypes().add((EClass) schemaPack.getEClassifier("IfcValue"));
		doRealDerivedAttributes();
		clean();
	}

	private void addHackedTypes() {
		Iterator typeIter = schema.getTypes().iterator();
		while (typeIter.hasNext()) {
			DefinedType type = typeIter.next();
			if (type.getName().equals("IfcCompoundPlaneAngleMeasure")) {
				// IfcCompoundPlaneAngleMeasure is a type of LIST [3..4] OF INTEGER (http://www.steptools.com/support/stdev_docs/express/ifc2x3/html/t_ifcco-03.html)
				// We model this by using a wrapper class
//				EClass ifcCompoundPlaneAngleMeasure = getOrCreateEClass(type.getName());
//				DefinedType integerType = new DefinedType("Integer");
//				integerType.setDomain(new IntegerType());
//				EAttribute attribute = modifySimpleType(integerType, ifcCompoundPlaneAngleMeasure);
//				attribute.setUpperBound(4);
//				ifcCompoundPlaneAngleMeasure.getEAnnotations().add(createWrappedAnnotation());
			} else if (type.getName().equals("IfcComplexNumber")) {
				// IfcComplexNumber is a type of ARRAY [1..2] OF REAL (http://www.steptools.com/support/stdev_docs/express/ifc2x3/html/t_ifcco-07.html)
				// We model this by using a wrapper class
				EClass ifcComplexNumber = getOrCreateEClass(type.getName());
				DefinedType realType = new DefinedType("Real");
				realType.setDomain(new RealType());
				EAttribute attribute = modifySimpleType(realType, ifcComplexNumber);
				ifcComplexNumber.getEStructuralFeature("wrappedValueAsString").setUpperBound(2);
				attribute.setUpperBound(2);
				ifcComplexNumber.getEAnnotations().add(createWrappedAnnotation());
			} else if (type.getName().equals("IfcNullStyle")) {
				// IfcNullStyle is a type of ENUMERATION OF NULL (http://www.steptools.com/support/stdev_docs/express/ifc2x3/html/t_ifcnu-02.html)
				// We cannot simply make this an enum because it is defined as a subtype(select) of IfcPresentationStyleSelect, so we use a wrapper here, both the wrapper and
				EClassifier ifcNullStyleEnum = schemaPack.getEClassifier("IfcNullStyle");
				ifcNullStyleEnum.setName("IfcNullStyleEnum");
				
				EClass ifcNullStyleWrapper = getOrCreateEClass(type.getName());
				
				EAttribute wrappedValue = eFactory.createEAttribute();
				wrappedValue.setName("wrappedValue");
				wrappedValue.setEType(ifcNullStyleEnum);
				ifcNullStyleWrapper.getEAnnotations().add(createWrappedAnnotation());
				ifcNullStyleWrapper.getEStructuralFeatures().add(wrappedValue);
			}
		}
	}

	private EAnnotation createWrappedAnnotation() {
		EAnnotation wrappedAnnotation = eFactory.createEAnnotation();
		wrappedAnnotation.setSource("wrapped");
		return wrappedAnnotation;
	}

	private void clean() {
		Iterator iterator = schemaPack.getEClassifiers().iterator();
		while (iterator.hasNext()) {
			EClassifier eClassifier = iterator.next();
			if (eClassifier instanceof EClass) {
				EClass eClass = (EClass) eClassifier;
				if (eClass.getEAnnotation("wrapped") != null) {
					if (eClass.getESuperTypes().size() == 1) {
//						iterator.remove();
					}
				}
			}
		}
	}

	private void doRealDerivedAttributes() {
		for (EntityDefinition entityDefinition : schema.getEntities()) {
			for (DerivedAttribute2 attributeName : entityDefinition.getDerivedAttributes().values()) {
				EClass eClass = (EClass) schemaPack.getEClassifier(entityDefinition.getName());
				// EStructuralFeature derivedAttribute =
				// eFactory.createEReference();
				if (attributeName.getType() != null && !attributeName.hasSuper()) {
					// if (attributeName.getType() instanceof EntityDefinition)
					// {
					// derivedAttribute.setEType(schemaPack.getEClassifier(((EntityDefinition)
					// attributeName.getType()).getName()));
					// } else if (attributeName.getType() instanceof
					// IntegerType) {
					// derivedAttribute.setEType(schemaPack.getEClassifier("IfcInteger"));
					// } else if (attributeName.getType() instanceof RealType) {
					// derivedAttribute.setEType(schemaPack.getEClassifier("IfcReal"));
					// } else if (attributeName.getType() instanceof
					// LogicalType) {
					// derivedAttribute.setEType(schemaPack.getEClassifier("IfcLogical"));
					if (attributeName.getType() instanceof DefinedType) {
						EClassifier eType = schemaPack.getEClassifier(((DefinedType) attributeName.getType()).getName());
						boolean found = false;
						for (EClass eSuperType : eClass.getEAllSuperTypes()) {
							if (eSuperType.getEStructuralFeature(attributeName.getName()) != null) {
								found = true;
								break;
							}
						}
						if (eType.getEAnnotation("wrapped") != null) {
							if (!found) {
								EAttribute eAttribute = eFactory.createEAttribute();
								eAttribute.setDerived(true);
								eAttribute.setName(attributeName.getName());
								if (eAttribute.getName().equals("RefLatitude") || eAttribute.getName().equals("RefLongitude")) {
									eAttribute.setUpperBound(3);
									eAttribute.setUnique(false);
								}
								EClassifier type = ((EClass) eType).getEStructuralFeature("wrappedValue").getEType();
								eAttribute.setEType(type);
								eAttribute.setUnsettable(true); // TODO find out
																// if its
																// optional
								eClass.getEStructuralFeatures().add(eAttribute);
								if (type == EcorePackage.eINSTANCE.getEDouble()) {
									EAttribute doubleStringAttribute = eFactory.createEAttribute();
									doubleStringAttribute.setName(attributeName.getName() + "AsString");
									doubleStringAttribute.getEAnnotations().add(createAsStringAnnotation());
									doubleStringAttribute.getEAnnotations().add(createHiddenAnnotation());
									doubleStringAttribute.setUnsettable(true); // TODO
																				// find
																				// out
																				// if
																				// its
																				// optional
									doubleStringAttribute.setEType(EcorePackage.eINSTANCE.getEString());
									eClass.getEStructuralFeatures().add(doubleStringAttribute);
								}
							}
						} else {
							if (!found) {
								EReference eReference = eFactory.createEReference();
								eReference.setName(attributeName.getName());
								eReference.setDerived(true);
								eReference.setUnsettable(true);
								eReference.setEType(eType);
								eClass.getEStructuralFeatures().add(eReference);
							}
						}
						// derivedAttribute.setEType(eType);
					}
				}
				// derivedAttribute.setName(attributeName.getName());
				// derivedAttribute.setDerived(true);
				// derivedAttribute.setTransient(true);
				// derivedAttribute.setVolatile(true);
				// if (attributeName.isCollection()) {
				// derivedAttribute.setUpperBound(-1);
				// }
				// EAnnotation annotation = eFactory.createEAnnotation();
				// annotation.setSource("http://www.iso.org/iso10303-11/EXPRESS");
				// annotation.getDetails().put("code",
				// attributeName.getExpressCode());
				// derivedAttribute.getEAnnotations().add(annotation);
				// if (eClass.getEStructuralFeature(derivedAttribute.getName())
				// == null) {
				// eClass.getEStructuralFeatures().add(derivedAttribute);
				// }
			}
		}
	}

	private EAnnotation createHiddenAnnotation() {
		EAnnotation hiddenAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
		hiddenAnnotation.setSource("hidden");
		return hiddenAnnotation;
	}

	private EAnnotation createAsStringAnnotation() {
		EAnnotation asStringAnnotation = eFactory.createEAnnotation();
		asStringAnnotation.setSource("asstring");
		return asStringAnnotation;
	}

	private void createTristate() {
		tristate = eFactory.createEEnum();
		tristate.setName("Tristate");
		EEnumLiteral trueLiteral = eFactory.createEEnumLiteral();
		trueLiteral.setName("TRUE");
		trueLiteral.setValue(0);
		EEnumLiteral falseLiteral = eFactory.createEEnumLiteral();
		falseLiteral.setName("FALSE");
		falseLiteral.setValue(1);
		EEnumLiteral undefinedLiteral = eFactory.createEEnumLiteral();
		undefinedLiteral.setName("UNDEFINED");
		undefinedLiteral.setValue(2);
		tristate.getELiterals().add(trueLiteral);
		tristate.getELiterals().add(falseLiteral);
		tristate.getELiterals().add(undefinedLiteral);
		schemaPack.getEClassifiers().add(tristate);
	}

	private void addInverses() {
		Iterator entIter = schema.getEntities().iterator();
		while (entIter.hasNext()) {
			EntityDefinition ent = (EntityDefinition) entIter.next();
			Iterator attribIter = ent.getAttributes(false).iterator();
			EClass cls = (EClass) schemaPack.getEClassifier(ent.getName());
			// if (ent.getName().equals("IfcRepresentation")) {
			// InverseAttribute attrib = new
			// InverseAttribute("LayerAssignments", ent);
			// EntityDefinition entityBN =
			// schema.getEntityBN("IfcPresentationLayerAssignment");
			// attrib.setDomain(entityBN);
			// attrib.setInverted_attr((ExplicitAttribute)entityBN.getAttributeBN
			// ("AssignedItems"));
			// addInverseAttribute(attrib, cls);

			// EClass ifcLayeredItem =
			// (EClass)schemaPack.getEClassifier("IfcLayeredItem");
			// EReference createEReference = eFactory.createEReference();
			// createEReference.setName("LayerAssignments");
			// EClassifier classifier =
			// schemaPack.getEClassifier("IfcPresentationLayerAssignment");
			// createEReference.setEType(classifier);
			// EReference structuralFeature =
			// (EReference)((EClass)classifier).getEStructuralFeature
			// ("AssignedItems");
			// createEReference.setEOpposite(structuralFeature);
			// structuralFeature.setEOpposite(createEReference);
			// ifcLayeredItem.getEStructuralFeatures().add(createEReference);
			// }
			while (attribIter.hasNext()) {
				Attribute attrib = (Attribute) attribIter.next();
				// if (ent.getName().equals("IfcRepresentationItem") &&
				// attrib.getName().equals("LayerAssignments")) {
				//
				// } else {
				if (attrib instanceof InverseAttribute) {
					addInverseAttribute(attrib, cls);
				}
				// }
			}
		}
	}

	private void addInverseAttribute(Attribute attrib, EClass cls) {
		InverseAttribute inverseAttribute = (InverseAttribute) attrib;
		EReference eRef = eFactory.createEReference();
		eRef.setUnsettable(true); // Inverses are always optional?
		eRef.getEAnnotations().add(createInverseAnnotation());
		eRef.setName(attrib.getName());
		if (inverseAttribute.getMax_cardinality() != null) {
			IntegerBound max_cardinality = (IntegerBound) inverseAttribute.getMax_cardinality();
			if (max_cardinality.getBound_value() == -1) {
				eRef.setUpperBound(max_cardinality.getBound_value());
			} else {
				eRef.setUpperBound(max_cardinality.getBound_value() + 1);
			}
		}
		String type = (inverseAttribute).getDomain().getName();
		EClass classifier = (EClass) schemaPack.getEClassifier(type);
		eRef.setEType(classifier);
		String reverseName = inverseAttribute.getInverted_attr().getName();
		EReference reference = (EReference) classifier.getEStructuralFeature(reverseName);
		reference.getEAnnotations().add(createInverseAnnotation());
		if (eRef.getEType() == classifier && reference.getEType() == cls) {
			if (eRef.isMany()) {
				eRef.setUnique(true);
			}
			if (reference.isMany()) {
				reference.setUnique(true);
			}
			reference.setEOpposite(eRef);
			eRef.setEOpposite(reference);
		} else {
			LOGGER.info("Inverse mismatch");
			LOGGER.info(classifier.getName() + "." + reference.getName() + " => " + cls.getName() + "." + eRef.getName());
		}
		cls.getEStructuralFeatures().add(eRef);
	}

	private EAnnotation createInverseAnnotation() {
		EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
		eAnnotation.setSource("inverse");
		return eAnnotation;
	}

	private void addAttributes() {
		Iterator entIter = schema.getEntities().iterator();
		while (entIter.hasNext()) {
			EntityDefinition ent = (EntityDefinition) entIter.next();
			Iterator attribIter = ent.getAttributes(false).iterator();
			while (attribIter.hasNext()) {
				Attribute attrib = (Attribute) attribIter.next();
				if (attrib instanceof ExplicitAttribute) {
					processAttribute(ent, attrib);
				}
			}
		}
	}

	private void processAttribute(EntityDefinition ent, Attribute attrib) {
		ExplicitAttribute expAttrib = (ExplicitAttribute) attrib;
		BaseType domain = expAttrib.getDomain();
		if (ent.getName().equals("IfcRelConnectsPathElements") && (attrib.getName().equals("RelatingPriorities") || attrib.getName().equals("RelatedPriorities"))) {
			// HACK, express parser does not recognize LIST [0:?] OF NUMBER
			EClass cls = (EClass) schemaPack.getEClassifier(ent.getName());			
			EAttribute eAttribute = eFactory.createEAttribute();
			eAttribute.setName(attrib.getName());
			eAttribute.setUpperBound(-1);
			eAttribute.setUnique(false);
			eAttribute.setEType(EcorePackage.eINSTANCE.getEInt());
			eAttribute.setUnsettable(expAttrib.isOptional());
			cls.getEStructuralFeatures().add(eAttribute);
			return;
		}
		if (domain instanceof NamedType) {
			NamedType nt = (NamedType) domain;
			if (nt instanceof EnumerationType) {
				EAttribute enumAttrib = eFactory.createEAttribute();
				enumAttrib.setUnsettable(expAttrib.isOptional());
				enumAttrib.setName(attrib.getName());
				EClassifier eType = schemaPack.getEClassifier(nt.getName());
				enumAttrib.setEType(eType);
				EClass cls = (EClass) schemaPack.getEClassifier(ent.getName());
				cls.getEStructuralFeatures().add(enumAttrib);
			} else {
				EClass eType = (EClass) schemaPack.getEClassifier(nt.getName());
				EClass cls = (EClass) schemaPack.getEClassifier(ent.getName());
				// If the DEFINED type is already a wrapped value, we prefer not to use wrappedValue indirection
				boolean wrapped = superTypeIsWrapped(eType);
				if (wrapped) {
					EAttribute eAttribute = eFactory.createEAttribute();
					eAttribute.setUnsettable(expAttrib.isOptional());
					eAttribute.setName(attrib.getName());
					if (eAttribute.getName().equals("RefLatitude") || eAttribute.getName().equals("RefLongitude")) {
						eAttribute.setUpperBound(3);
						eAttribute.setUnique(false);
					}
					EClassifier type = ((EClass) eType).getEStructuralFeature("wrappedValue").getEType();
					eAttribute.setEType(type);
					cls.getEStructuralFeatures().add(eAttribute);
					if (type == EcorePackage.eINSTANCE.getEDouble()) {
						EAttribute doubleStringAttribute = eFactory.createEAttribute();
						doubleStringAttribute.setName(attrib.getName() + "AsString");
						doubleStringAttribute.getEAnnotations().add(createAsStringAnnotation());
						doubleStringAttribute.getEAnnotations().add(createHiddenAnnotation());
						doubleStringAttribute.setEType(EcorePackage.eINSTANCE.getEString());
						doubleStringAttribute.setUnsettable(expAttrib.isOptional());
						cls.getEStructuralFeatures().add(doubleStringAttribute);
					}
				} else {
					EReference eRef = eFactory.createEReference();
					eRef.setName(attrib.getName());
					// Hardcoded hack to fix multiplicity for
					// IfcSpatialStructureElement which references
					// RefLatitude and RefLongitude
					eRef.setUnsettable(expAttrib.isOptional());
					eRef.setEType(eType);
					cls.getEStructuralFeatures().add(eRef);
				}
			}
		} else if (domain instanceof AggregationType) {
			BaseType bt = ((AggregationType) domain).getElement_type();
			EClass cls = (EClass) schemaPack.getEClassifier(ent.getName());
			if (bt instanceof NamedType) {
				NamedType nt = (NamedType) bt;
				EClassifier eType = schemaPack.getEClassifier(nt.getName());
				if (superTypeIsWrapped((EClass) eType)) {
					EAttribute eAttribute = eFactory.createEAttribute();
					eAttribute.setName(attrib.getName());
					if (eAttribute.getName().equals("RefLatitude") || eAttribute.getName().equals("RefLongitude")) {
						eAttribute.setUpperBound(3);
					} else {
						eAttribute.setUpperBound(-1);
					}
					EClassifier type = ((EClass) eType).getEStructuralFeature("wrappedValue").getEType();
					eAttribute.setEType(type);
					eAttribute.setUnsettable(expAttrib.isOptional());
					eAttribute.setUnique(false);
					cls.getEStructuralFeatures().add(eAttribute);
					if (type == EcorePackage.eINSTANCE.getEDouble()) {
						EAttribute doubleStringAttribute = eFactory.createEAttribute();
						doubleStringAttribute.setName(attrib.getName() + "AsString");
						doubleStringAttribute.getEAnnotations().add(createAsStringAnnotation());
						doubleStringAttribute.getEAnnotations().add(createHiddenAnnotation());
						doubleStringAttribute.setEType(EcorePackage.eINSTANCE.getEString());
						doubleStringAttribute.setUpperBound(-1);
						doubleStringAttribute.setUnsettable(expAttrib.isOptional());
						doubleStringAttribute.setUpperBound(eAttribute.getUpperBound());
						doubleStringAttribute.setUnique(false);
						cls.getEStructuralFeatures().add(doubleStringAttribute);
					}
				} else if (eType == EcorePackage.eINSTANCE.getEDouble()) {
					EAttribute eAttribute = eFactory.createEAttribute();
					eAttribute.setName(attrib.getName());
					eAttribute.setUnsettable(expAttrib.isOptional());
					eAttribute.setUnique(false);
					eAttribute.setEType(EcorePackage.eINSTANCE.getEAttribute());
					cls.getEStructuralFeatures().add(eAttribute);

					EAttribute doubleStringAttribute = eFactory.createEAttribute();
					doubleStringAttribute.getEAnnotations().add(createHiddenAnnotation());
					doubleStringAttribute.getEAnnotations().add(createAsStringAnnotation());
					doubleStringAttribute.setName(attrib.getName() + "AsString");
					doubleStringAttribute.setUpperBound(-1);
					doubleStringAttribute.setEType(EcorePackage.eINSTANCE.getEString());
					doubleStringAttribute.setUnsettable(expAttrib.isOptional());
					doubleStringAttribute.setUpperBound(eAttribute.getUpperBound());
					doubleStringAttribute.setUnique(false);
					cls.getEStructuralFeatures().add(doubleStringAttribute);
				} else {
					EReference eRef = eFactory.createEReference();
					eRef.setUpperBound(-1);
					eRef.setName(attrib.getName());
					// Hardcoded hack to fix multiplicity for
					// IfcSpatialStructureElement which references
					// RefLatitude and RefLongitude
					eRef.setUnsettable(expAttrib.isOptional());
					eRef.setEType(eType);
					eRef.setUnique(false);
					// EClass cls = (EClass)
					// schemaPack.getEClassifier(ent.getName());
					cls.getEStructuralFeatures().add(eRef);
				}

				// EClassifier eType = schemaPack.getEClassifier(nt.getName());
				// eRef.setEType(eType);
				// cls.getEStructuralFeatures().add(eRef);
			} else if (bt instanceof RealType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setUnsettable(expAttrib.isOptional());
				eAttribute.setName(attrib.getName());
				eAttribute.setUpperBound(-1);
				eAttribute.setUnique(false);
				eAttribute.setEType(EcorePackage.eINSTANCE.getEDouble());
				cls.getEStructuralFeatures().add(eAttribute);

				EAttribute doubleStringAttribute = eFactory.createEAttribute();
				doubleStringAttribute.getEAnnotations().add(createHiddenAnnotation());
				doubleStringAttribute.getEAnnotations().add(createAsStringAnnotation());
				doubleStringAttribute.setName(attrib.getName() + "AsString");
				doubleStringAttribute.setUpperBound(-1);
				doubleStringAttribute.setEType(EcorePackage.eINSTANCE.getEString());
				doubleStringAttribute.setUnsettable(expAttrib.isOptional());
				doubleStringAttribute.setUpperBound(eAttribute.getUpperBound());
				doubleStringAttribute.setUnique(false);
				cls.getEStructuralFeatures().add(doubleStringAttribute);
			} else if (bt instanceof IntegerType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setName(attrib.getName());
				eAttribute.setUpperBound(-1);
				eAttribute.setUnique(false);
				eAttribute.setEType(EcorePackage.eINSTANCE.getEInt());
				eAttribute.setUnsettable(expAttrib.isOptional());
				cls.getEStructuralFeatures().add(eAttribute);
			} else if (bt instanceof NumberType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setName(attrib.getName());
				eAttribute.setUpperBound(-1);
				eAttribute.setUnique(false);
				eAttribute.setEType(EcorePackage.eINSTANCE.getEInt());
				eAttribute.setUnsettable(expAttrib.isOptional());
				cls.getEStructuralFeatures().add(eAttribute);
			} else if (bt instanceof LogicalType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setName(attrib.getName());
				eAttribute.setUpperBound(-1);
				eAttribute.setUnique(false);
				eAttribute.setEType(EcorePackage.eINSTANCE.getEBoolean());
				eAttribute.setUnsettable(expAttrib.isOptional());
				cls.getEStructuralFeatures().add(eAttribute);
			} else if (bt instanceof BinaryType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setUnsettable(expAttrib.isOptional());
				eAttribute.setUpperBound(-1);
				eAttribute.setName(attrib.getName());
				eAttribute.setUnique(false);
				eAttribute.setEType(EcorePackage.eINSTANCE.getEByteArray());
				cls.getEStructuralFeatures().add(eAttribute);
			} else if (bt == null) {
				// These are the new 2-dimensional arrays in IFC4, there are 10 of them
				addTwoDimensionalArray(ent.getName(), attrib.getName());
			}
			if (domain instanceof ArrayType) {
				// TODO this is not yet implmented in simpelSDAI
				// eAttrib.setLowerBound(((nl.tue.buildingsmart.express.dictionary
				// .ArrayType)domain).getLower_index());

				// One fix for this has been implemented in addHackedTypes
			}
		} else {
			EClass cls = (EClass) schemaPack.getEClassifier(ent.getName());
			if (domain == null) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setUnsettable(expAttrib.isOptional());
				eAttribute.setName(attrib.getName());
				eAttribute.setEType(tristate);
				cls.getEStructuralFeatures().add(eAttribute);
			} else if (domain instanceof IntegerType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setUnsettable(expAttrib.isOptional());
				eAttribute.setName(attrib.getName());
				eAttribute.setEType(EcorePackage.eINSTANCE.getEInt());
				cls.getEStructuralFeatures().add(eAttribute);
			} else if (domain instanceof LogicalType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setUnsettable(expAttrib.isOptional());
				eAttribute.setName(attrib.getName());
				eAttribute.setEType(EcorePackage.eINSTANCE.getEBoolean());
				cls.getEStructuralFeatures().add(eAttribute);
			} else if (domain instanceof RealType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setUnsettable(expAttrib.isOptional());
				eAttribute.setName(attrib.getName());
				eAttribute.setEType(EcorePackage.eINSTANCE.getEDouble());
				cls.getEStructuralFeatures().add(eAttribute);
				EAttribute eAttributeAsString = eFactory.createEAttribute();
				eAttributeAsString.getEAnnotations().add(createAsStringAnnotation());
				eAttributeAsString.getEAnnotations().add(createHiddenAnnotation());
				eAttributeAsString.setUnsettable(expAttrib.isOptional());
				eAttributeAsString.setName(attrib.getName() + "AsString");
				eAttributeAsString.setEType(EcorePackage.eINSTANCE.getEString());
				cls.getEStructuralFeatures().add(eAttributeAsString);
			} else if (domain instanceof StringType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setUnsettable(expAttrib.isOptional());
				eAttribute.setName(attrib.getName());
				eAttribute.setEType(EcorePackage.eINSTANCE.getEString());
				cls.getEStructuralFeatures().add(eAttribute);
			} else if (domain instanceof BinaryType) {
				EAttribute eAttribute = eFactory.createEAttribute();
				eAttribute.setUnsettable(expAttrib.isOptional());
				eAttribute.setName(attrib.getName());
				eAttribute.setEType(EcorePackage.eINSTANCE.getEByteArray());
				cls.getEStructuralFeatures().add(eAttribute);
			} else {
				throw new RuntimeException("Unknown type: " + domain);
			}
		}
	}

	private void addTwoDimensionalArray(String entityName, String attribName) {
		EClassifier finalType = null;
		if (entityName.equals("IfcBSplineSurface") && attribName.equals("ControlPointsList")) {
			finalType = schemaPack.getEClassifier("IfcCartesianPoint");
		} else if (entityName.equals("IfcCartesianPointList3D") && attribName.equals("CoordList")) {
			finalType = schemaPack.getEClassifier("IfcLengthMeasure");
		} else if (entityName.equals("IfcColourRgbList") && attribName.equals("ColourList")) {
			finalType = schemaPack.getEClassifier("IfcNormalisedRatioMeasure");
		} else if (entityName.equals("IfcIndexedTriangleTextureMap") && attribName.equals("TexCoordIndex")) {
			finalType = EcorePackage.eINSTANCE.getEInt();
		} else if (entityName.equals("IfcRationalBSplineSurfaceWithKnots") && attribName.equals("WeightsData")) {
			finalType = EcorePackage.eINSTANCE.getEDouble();
		} else if (entityName.equals("IfcStructuralLoadConfiguration") && attribName.equals("Locations")) {
			finalType = schemaPack.getEClassifier("IfcLengthMeasure");
		} else if (entityName.equals("IfcTessellatedFaceSet") && attribName.equals("Normals")) {
			finalType = schemaPack.getEClassifier("IfcParameterValue");
		} else if (entityName.equals("IfcTextureVertexList") && attribName.equals("TexCoordsList")) {
			finalType = schemaPack.getEClassifier("IfcParameterValue");
		} else if (entityName.equals("IfcTriangulatedFaceSet") && attribName.equals("CoordIndex")) {
			finalType = EcorePackage.eINSTANCE.getEInt();
		} else if (entityName.equals("IfcTriangulatedFaceSet") && attribName.equals("NormalIndex")) {
			finalType = EcorePackage.eINSTANCE.getEInt();
		} else {
			System.out.println("Unimplemented " + entityName + "." + attribName);
		}
		EClass containerClass = (EClass) schemaPack.getEClassifier("ListOf" + finalType.getName());
		if (containerClass == null) {
			containerClass = EcoreFactory.eINSTANCE.createEClass();
			containerClass.setName("ListOf" + finalType.getName());

			if (finalType.getEPackage() == EcorePackage.eINSTANCE) {
				EAttribute finalAttribute = EcoreFactory.eINSTANCE.createEAttribute();
				finalAttribute.setName("List");
				finalAttribute.setEType(finalType);
				finalAttribute.setUpperBound(-1);
				containerClass.getEAttributes().add(finalAttribute);
			} else {
				EReference finalReference = EcoreFactory.eINSTANCE.createEReference();
				finalReference.setName("List");
				finalReference.setEType(finalType);
				finalReference.setUpperBound(-1);
				containerClass.getEReferences().add(finalReference);
			}

			schemaPack.getEClassifiers().add(containerClass);
		}
		
		EReference eReference = EcoreFactory.eINSTANCE.createEReference();
		eReference.getEAnnotations().add(createTwoDimensionalArrayAnnotation());
		eReference.setName(attribName);
		eReference.setUpperBound(-1);
		eReference.setEType(containerClass);
		
		EClass cls = (EClass) schemaPack.getEClassifier(entityName);
		cls.getEStructuralFeatures().add(eReference);
	}

	private EAnnotation createTwoDimensionalArrayAnnotation() {
		EAnnotation asStringAnnotation = eFactory.createEAnnotation();
		asStringAnnotation.setSource("twodimensionalarray");
		return asStringAnnotation;
	}

	private boolean superTypeIsWrapped(EClass eType) {
		if (eType.getEAnnotation("wrapped") != null) {
			return true;
		}
		for (EClass superClass : eType.getESuperTypes()) {
			if (superTypeIsWrapped(superClass)) {
				return true;
			}
		}
		return false;
	}

	private void addClasses() {
		Iterator entIter = schema.getEntities().iterator();
		while (entIter.hasNext()) {
			getOrCreateEClass(entIter.next().getName());
		}
	}

	private void addSupertypes() {
		Iterator entIter = schema.getEntities().iterator();
		while (entIter.hasNext()) {
			EntityDefinition ent = entIter.next();
			if (ent.getSupertypes().size() > 0) {
				EClass cls = getOrCreateEClass(ent.getName());
				if (ent.getSupertypes().size() > 0) {
					EClass parent = getOrCreateEClass(ent.getSupertypes().get(0).getName());
					if (!directSubTypes.containsKey(parent)) {
						directSubTypes.put(parent, new HashSet());
					}
					directSubTypes.get(parent).add(cls);
					cls.getESuperTypes().add(parent);
				}
			}
		}
	}

	private void addSelects() {
		Iterator typeIter = schema.getTypes().iterator();
		while (typeIter.hasNext()) {
			DefinedType type = typeIter.next();
			if (type instanceof SelectType) {
				EClass selectType = getOrCreateEClass(type.getName());
				selectType.setInterface(true);
				selectType.setAbstract(true);
				Iterator entIter = ((SelectType) type).getSelections().iterator();
				while (entIter.hasNext()) {
					NamedType nt = entIter.next();
					if (nt instanceof EntityDefinition) {
						EClass choice = getOrCreateEClass(nt.getName());
						choice.getESuperTypes().add(selectType);
					} else if (nt instanceof DefinedType) {
						UnderlyingType domain = ((DefinedType) nt).getDomain();
						if (domain instanceof RealType || domain instanceof StringType || domain instanceof IntegerType || domain instanceof NumberType
								|| domain instanceof LogicalType) {
							EClass choice = getOrCreateEClass(nt.getName());
							choice.getESuperTypes().add(selectType);
						} else if (domain instanceof DefinedType) {
							DefinedType dt2 = (DefinedType) (domain);
							if (dt2.getDomain() instanceof RealType) {
								EClass choice = getOrCreateEClass(nt.getName());
								choice.getESuperTypes().add(selectType);
							}
						} else if (nt instanceof SelectType) {
						} else {
							if (nt.getName().equals("IfcComplexNumber") || nt.getName().equals("IfcCompoundPlaneAngleMeasure") || nt.getName().equals("IfcBoolean") || nt.getName().equals("IfcNullStyle")) {
								EClass choice = getOrCreateEClass(nt.getName());
								choice.getESuperTypes().add(selectType);
							} else {
								System.out.println("The domain is null for " + selectType.getName() + " " + nt.getName());
							}
						}
					}
				}
			}
		}
		typeIter = schema.getTypes().iterator();
		while (typeIter.hasNext()) {
			DefinedType type = typeIter.next();
			if (type instanceof SelectType) {
				EClass selectType = (EClass) schemaPack.getEClassifier(type.getName());
				Iterator entIter = ((SelectType) type).getSelections().iterator();
				while (entIter.hasNext()) {
					NamedType nt = entIter.next();
					if (nt instanceof SelectType) {
						EClass choice = getOrCreateEClass(nt.getName());
						choice.getESuperTypes().add(selectType);
					}
				}
			}
		}
	}

	private EAttribute modifySimpleType(DefinedType type, EClass testType) {
		if (directSubTypes.containsKey(testType)) {
			for (EClass subType : directSubTypes.get(testType)) {
				x(type, subType);
			}
		}
 		EAttribute wrapperAttrib = x(type, testType);
		return wrapperAttrib;
	}

	private EAttribute x(DefinedType type, EClass testType) {
		EAttribute wrapperAttrib = eFactory.createEAttribute();
		wrapperAttrib.setName("wrappedValue");
		if (type.getDomain() instanceof IntegerType) {
			wrapperAttrib.setEType(ePackage.getEInt());
		} else if (type.getDomain() instanceof RealType) {
			wrapperAttrib.setEType(ePackage.getEDouble());
		} else if (type.getDomain() instanceof StringType) {
			wrapperAttrib.setEType(ePackage.getEString());
		} else if (type.getDomain() instanceof BooleanType) {
			wrapperAttrib.setEType(schemaPack.getEClassifier("Tristate"));
		} else if (type.getDomain() instanceof NumberType) {
			wrapperAttrib.setEType(ePackage.getEDouble());
		} else if (type.getDomain() instanceof LogicalType) {
			wrapperAttrib.setEType(schemaPack.getEClassifier("Tristate"));
		}
		wrapperAttrib.setUnsettable(true);
		testType.getEStructuralFeatures().add(wrapperAttrib);
		if (wrapperAttrib.getEType() == ePackage.getEDouble()) {
			EAttribute doubleStringAttribute = eFactory.createEAttribute();
			doubleStringAttribute.setEType(ePackage.getEString());
			doubleStringAttribute.setName("wrappedValueAsString");
			doubleStringAttribute.getEAnnotations().add(createAsStringAnnotation());
			doubleStringAttribute.getEAnnotations().add(createHiddenAnnotation());
			doubleStringAttribute.setUnsettable(true);
			testType.getEStructuralFeatures().add(doubleStringAttribute);
		}
		return wrapperAttrib;
	}

	private void addSimpleTypes() {
		Iterator typeIter = schema.getTypes().iterator();
		while (typeIter.hasNext()) {
			DefinedType type = typeIter.next();
			if (type.getDomain() instanceof SimpleType) {
				EClass testType = getOrCreateEClass(type.getName());
				testType.getEAnnotations().add(createWrappedAnnotation());
				modifySimpleType(type, testType);
			}
		}
	}

	private EClass getOrCreateEClass(String name) {
		EClassifier eClassifier = schemaPack.getEClassifier(name);
		if (eClassifier == null) {
			eClassifier = eFactory.createEClass();
			eClassifier.setName(name);
			schemaPack.getEClassifiers().add(eClassifier);
		}
		return (EClass) eClassifier;
	}
	
	/**
	 * constructs the EXPRESS TYPEs like IfcPositiveLength measure that are not
	 * simple types but derived types: 
	 * TYPE IfcPositiveLengthMeasure = IfcLengthMeasure;
	 * WHERE
	 *  WR1 : SELF > 0.;
	 * END_TYPE;
	 * 
	 */
	private void addDerivedTypes() {
		Iterator typeIter = schema.getTypes().iterator();
		while (typeIter.hasNext()) {
			DefinedType type = typeIter.next();
			// debug (type.getName()+":"+type.getDomain(true).toString());
			// if ((type.getDomain() instanceof SimpleType)==false &&
			// (type instanceof EnumerationType)==false &&
			// (type instanceof SelectType)==false){

			/*
			 * one of the hard things TODO : TYPE IfcCompoundPlaneAngleMeasure =
			 * LIST [3:3] OF INTEGER; WHERE WR1 : { -360 <= SELF[1] < 360 }; WR2
			 * : { -60 <= SELF[2] < 60 }; WR3 : { -60 <= SELF[3] < 60 }; WR4 :
			 * ((SELF[1] >= 0) AND (SELF[2] >= 0) AND (SELF[3] >= 0)) OR
			 * ((SELF[1] <= 0) AND (SELF[2] <= 0) AND (SELF[3] <= 0)); END_TYPE;
			 * 
			 * I am skipping this for now, it only occurs once in the model
			 * future versions should definitely find an answer to this
			 * 
			 * A fix for this has been implemented in addHackedTypes
			 */
			if (type.getName().equalsIgnoreCase("IfcCompoundPlaneAngleMeasure")) {
				EClass testType = getOrCreateEClass(type.getName());
				DefinedType type2 = new DefinedType("Integer");
				type2.setDomain(new IntegerType());
				modifySimpleType(type2, testType);
				testType.getEAnnotations().add(createWrappedAnnotation());
			} else if (type.getDomain() instanceof DefinedType) {
				if (schemaPack.getEClassifier(type.getName()) != null) {
					EClass testType = (EClass) schemaPack.getEClassifier(type.getName());
					DefinedType domain = (DefinedType) type.getDomain();
					EClassifier classifier = schemaPack.getEClassifier(domain.getName());
					testType.getESuperTypes().add((EClass) classifier);
					testType.setInstanceClass(classifier.getInstanceClass());
				} else {
					EClass testType = getOrCreateEClass(type.getName());
					DefinedType domain = (DefinedType) type.getDomain();
					if (simpleTypeReplacementMap.containsKey(domain.getName())) {
						// We can't subclass because it's a 'primitive' type
						simpleTypeReplacementMap.put(type.getName(), simpleTypeReplacementMap.get(domain.getName()));
					} else {
						EClass classifier = getOrCreateEClass(domain.getName());
						testType.getESuperTypes().add((EClass) classifier);
						if (classifier.getEAnnotation("wrapped") != null) {
							testType.getEAnnotations().add(createWrappedAnnotation());
						}
						testType.setInstanceClass(classifier.getInstanceClass());
					}
				}
			}
		}
	}

	private void addEnumerations() {
		Iterator typeIter = schema.getTypes().iterator();
		while (typeIter.hasNext()) {
			DefinedType type = typeIter.next();
			if (type instanceof EnumerationType) {
				EEnum enumeration = eFactory.createEEnum();
				enumeration.setName(type.getName());

				EEnumLiteral nullValue = eFactory.createEEnumLiteral();
				nullValue.setName("NULL");
				nullValue.setLiteral("NULL");
				nullValue.setValue(0);
				enumeration.getELiterals().add(nullValue);

				int counter = 1;
				Iterator values = ((EnumerationType) type).getElements().iterator();
				while (values.hasNext()) {
					String stringVal = values.next();
					if (!stringVal.equals("NULL")) {
						EEnumLiteral value = eFactory.createEEnumLiteral();
						value.setName(stringVal);
						value.setLiteral(stringVal);
						value.setValue(counter);
						counter++;
						enumeration.getELiterals().add(value);
					}
				}
				schemaPack.getEClassifiers().add(enumeration);
			}
		}
	}

	public void writeEMF(String fileName) {
		ResourceSet metaResourceSet = new ResourceSetImpl();
		metaResourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new XMLResourceFactoryImpl());

		URI resUri = URI.createURI(fileName);
		Resource metaResource = metaResourceSet.createResource(resUri);
		metaResource.getContents().add(schemaPack);
		try {
			metaResource.save(null);
		} catch (Exception e) {
			LOGGER.error("", e);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy