diff --git a/src/main/jastadd/XMI/XMIWriter.jadd b/src/main/jastadd/XMI/XMIWriter.jadd new file mode 100644 index 0000000000000000000000000000000000000000..4096a537a60ef290e36e44c4bfb5fcbd07d102d9 --- /dev/null +++ b/src/main/jastadd/XMI/XMIWriter.jadd @@ -0,0 +1,84 @@ +aspect XMIWriter { + + public static String ASTNode.indentString(int n) { + char[] chars = new char[2*n]; + java.util.Arrays.fill(chars, ' '); + return new String(chars); + } + + public void EPackage.writeXMI(StringBuilder b) { + b.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + this.writeXMI(b, null, 0); + } + + void ASTNode.startXMIElement(StringBuilder b, String type, String context) { + if (context == null) { + // we have a top-level element that is not contained in anything + b.append(type).append(" xmi:version=\"2.0\"" + + " xmlns:xmi=\"http://www.omg.org/XMI\"" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ecore=\"http://www.eclipse.org/emf/2002/Ecore\""); + } else { + b.append(context).append(" xsi:type=\"").append(type).append("\""); + } + } + + void ASTNode.endXMIElement(StringBuilder b, String type, String context) { + b.append((context == null) ? type : context); + } + + void EPackage.writeXMI(StringBuilder b, String context, int indentationLevel) { + // opening tag + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "ecore:EPackage", context); + b.append(" name=\"").append(getName()).append("\"") + .append(" nsURI=\"").append(getNsURI()).append("\"") + .append(" nsPrefix=\"").append(getNsPrefix()).append("\"") + .append(">\n"); + + + for (EClassifier eClassifier : getEClassifierList()) { + eClassifier.writeXMI(b, "eClassifiers", indentationLevel + 1); + } + for (EPackage eSubpackage : getESubPackageList()) { + eSubpackage.writeXMI(b, "eSubpackages", indentationLevel + 1); + } + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "ecore:EPackage", context); + b.append(">\n"); + } + + abstract void EClassifier.writeXMI(StringBuilder b, String context, int indentationLevel); + + void EClass.writeXMI(StringBuilder b, String context, int indentationLevel) { + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "ecore:EClass", context); + // attributes + b.append(" name=\"").append(getName()).append("\""); + + b.append(">\n"); + // child nodes + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "ecore:EPackage", context); + b.append(">\n"); + } + + void EDataType.writeXMI(StringBuilder b, String context, int indentationLevel) { + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "ecore:EDataType", context); + // attributes + b.append(" name=\"").append(getName()).append("\""); + + b.append(">\n"); + // child nodes + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "ecore:EPackage", context); + b.append(">\n"); + } +} diff --git a/src/main/jastadd/ecore.relast b/src/main/jastadd/ecore.relast index db51685be5146d365e220cc9c995d614aa4fa2ac..f03a19a331f43e12098574f511500fa95440e1c6 100644 --- a/src/main/jastadd/ecore.relast +++ b/src/main/jastadd/ecore.relast @@ -1,6 +1,6 @@ // root -EPackage : ENamedElement ::= EClassifier ESubPackage:EPackage* <NsURI:String> <NsPrefix:String>; +EPackage : ENamedElement ::= EClassifier* ESubPackage:EPackage* <NsURI:String> <NsPrefix:String>; EObject; abstract EModelElement : EObject ::= EAnnotation*; @@ -10,17 +10,17 @@ abstract ENamedElement : EModelElement ::= <Name:String>; EAnnotation : EModelElement ::= <Source:String> Detail:EStringToStringMapEntry*; -abstract EClassifier : ENamedElement ::= ETypeParameter* <InstanceClassName:String> <InstanceClass:Class> <DefaultValue:Object>; -EEnumLiteral : ENamedElement ::= <Value:int> <Instance:Enumerator>; -abstract ETypedElement : ENamedElement ::= [EGenericType] <Ordered:boolean> <Unique:boolean> <LowerBound:int> <UpperBound:int> <Many:boolean> <Required:boolean>; +abstract EClassifier : ENamedElement ::= ETypeParameter* <InstanceClassName:String>; +EEnumLiteral : ENamedElement ::= <Value:int>; +abstract ETypedElement : ENamedElement ::= [EGenericType] <Ordered:boolean> <Unique:boolean> <LowerBound:int> <UpperBound:int>; EClass : EClassifier ::= EStructuralFeature* EOperation* EGenericSuperType:EGenericType* <Abstract:boolean> <Interface:boolean>; EDataType : EClassifier; EEnum : EDataType ::= ELiteral:EEnumLiteral*; -EStructuralFeature : ETypedElement ::= <Changeable:boolean> <Volatile:boolean> <Transient:boolean> <defaultValueLiteral:String> <DefaultValue:Object> <Unsettable:boolean> <Derived:boolean>; +EStructuralFeature : ETypedElement ::= <Changeable:boolean> <Volatile:boolean> <Transient:boolean> <defaultValueLiteral:String> <Unsettable:boolean> <Derived:boolean>; EAttribute : EStructuralFeature ::= <ID:boolean>; -EReference : EStructuralFeature ::= <Containment:boolean> <Container:boolean> <ResolveProxies:boolean>; +EReference : EStructuralFeature ::= <Containment:boolean> <ResolveProxies:boolean>; EOperation : ETypedElement ::= GenericException:EGenericType* ETypeParameter* EParameter*; EParameter : ETypedElement; @@ -29,25 +29,39 @@ EStringToStringMapEntry ::= <Key:String> <Value:String>; ETypeParameter : ENamedElement ::= EBounds:EGenericType*; EGenericType ::= [EUpperBound:EGenericType] [ELowerBound:EGenericType] [ETypeArguments:EGenericType]; -rel EFactory.EPackage <-> EPackage.EFactoryInstance; rel ETypedElement.EType -> EClassifier; rel EOperation.EExceptions* -> EClassifier; -rel EClass.EAllOperations* -> EOperation; -rel EClass.EAllStructuralFeatures* -> EStructuralFeature; -rel EClass.EAllContainments* -> EReference; -rel EClass.EAllReferences* -> EReference; -rel EClass.EAllAttributes* -> EAttribute; -rel EClass.EAttributes* -> EAttribute; -rel EClass.EIDAttribute -> EAttribute; rel EClass.ESuperTypes* -> EClass; -rel EClass.EAllSuperTypes* -> EClass; -rel EClass.EAllGenericSuperTypes* -> EGenericType; - -rel EAttribute.EAttributeType -> EDataType; - +rel EReference.EOpposite? -> EReference; rel EAnnotation.References* -> EObject; - rel ETypeParameter.GenericTypes* <-> EGenericType.ETypeParameter?; -rel EGenericType.ERawType -> EClassifier; + rel EGenericType.EClassifier? -> EClassifier; + +// transient stuff (the inverse directions of the containment relations are missing) + +// EClassifier : ENamedElement ::= <InstanceClass:Class> <DefaultValue:Object>; +// EEnumLiteral : ENamedElement ::= <Instance:Enumerator>; +// EReference : EStructuralFeature ::= <Container:boolean>; +// EStructuralFeature : ETypedElement ::= <DefaultValue:Object> ; +// abstract ETypedElement : ENamedElement ::= <Many:boolean> <Required:boolean>; + +// rel EAttribute.EAttributeType -> EDataType; + +// rel EClass.EAllAttributes* -> EAttribute; +// rel EClass.EAllReferences* -> EReference; +// rel EClass.EReferences* -> EReference; +// rel EClass.EAttributes* -> EAttribute; +// rel EClass.EAllStructuralFeatures* -> EStructuralFeature; +// rel EClass.EAllContainments* -> EReference; +// rel EClass.EAllSuperTypes* -> EClass; +// rel EClass.EAllOperations* -> EOperation; +// rel EClass.EAllGenericSuperTypes* -> EGenericType; +// rel EClass.EIDAttribute -> EAttribute; + +// rel EReference.EReferenceType -> EClass; + +// rel EFactory.EPackage <-> EPackage.EFactoryInstance; + +// rel EGenericType.ERawType -> EClassifier; diff --git a/src/main/java/de/tudresden/inf/st/e2j/parser/EcoreParser.java b/src/main/java/de/tudresden/inf/st/e2j/parser/EcoreParser.java new file mode 100644 index 0000000000000000000000000000000000000000..33848110e7309a2780e7d8f5865b17e3f3056aa9 --- /dev/null +++ b/src/main/java/de/tudresden/inf/st/e2j/parser/EcoreParser.java @@ -0,0 +1,465 @@ +package de.tudresden.inf.st.e2j.parser; + +import de.tudresden.inf.st.e2j.jastadd.model.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import java.io.InputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class EcoreParser { + + private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance"; + private static final QName XSI_TYPE = new QName(XSI_NS, "type"); + + private static Logger logger = LogManager.getLogger(EcoreParser.class); + private final XMLInputFactory factory = XMLInputFactory.newInstance(); + + public EObject parse(InputStream stream) throws XMIParseException { + + try { + final XMLEventReader reader = factory.createXMLEventReader(stream); + + // TODO there may be one or more elements in the root, if so, the top level element is called XMI (?) + + while (reader.hasNext()) { + final XMLEvent event = reader.peek(); + + if (event.isStartDocument()) { + reader.nextEvent(); + } else if (event.isStartElement()) { + StartElement root = event.asStartElement(); + + switch (root.getName().getLocalPart()) { + case "EPackage": + return parseEPackage(reader, Collections.EMPTY_MAP); + default: + throw new XMIParseException("Unable to parse root element " + root.getName().toString()); + } + } else { + logger.error("the element is a {}", event.getEventType()); + throw new XMIParseException("Element is not a start element!"); + } + + } + } catch (XMLStreamException e) { + throw new XMIParseException("Exception thrown while parsing XML!", e); + } + + throw new XMIParseException("No contents in XMI file found!"); + } + + private Map<String, String> parseNameSpaces(StartElement element, Map<String, String> previousMap) { + Iterator namespaceIterator = element.getNamespaces(); + if (!namespaceIterator.hasNext()) { + return previousMap; + } + Map<String, String> result = new HashMap<>(previousMap); + while (namespaceIterator.hasNext()) { + Namespace namespace = (Namespace) namespaceIterator.next(); + logger.info("found Namespace {}:{}", namespace.getPrefix(), namespace.getNamespaceURI()); + result.put(namespace.getPrefix(), namespace.getNamespaceURI()); + } + return result; + } + + private EPackage parseEPackage(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + EPackage ePackage = new EPackage(); + + // get all the properties out of the element + StartElement startElement = reader.nextEvent().asStartElement(); + + nameSpaces = parseNameSpaces(startElement, nameSpaces); + + for (Iterator attributeIterator = startElement.getAttributes(); attributeIterator.hasNext(); ) { + Attribute attribute = (Attribute) attributeIterator.next(); + + switch (attribute.getName().getLocalPart()) { + case "nsURI": + ePackage.setNsURI(attribute.getValue()); + break; + case "nsPrefix": + ePackage.setNsPrefix(attribute.getValue()); + break; + case "name": + ePackage.setName(attribute.getValue()); + break; + default: + logger.warn("ignoring attribute {}:{}", attribute.getName().getPrefix(), attribute.getName().getLocalPart()); + } + } + + // parse the contained elements + XMLEvent nextEvent = reader.peek(); + while (true) { + if (nextEvent.isStartElement()) { + final StartElement nextElement = nextEvent.asStartElement(); + switch (nextElement.getName().getLocalPart()) { + case "eClassifiers": + ePackage.addEClassifier(parseEClassifier(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + return ePackage; + } else { + // ignore all other events + if (nextEvent.getEventType() != XMLStreamConstants.CHARACTERS) + logger.warn("ignoring event {}: '{}'", nextEvent.getEventType(), nextEvent.toString().replace("\n", "\\n")); + } + reader.nextEvent(); + nextEvent = reader.peek(); + } + } + + private EClassifier parseEClassifier(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + StartElement startElement = reader.peek().asStartElement(); + + EClassifier eClassifier; + + final String type = startElement.getAttributeByName(XSI_TYPE).getValue(); + switch (type) { + case "ecore:EClass": + eClassifier = parseEClass(reader, nameSpaces); + break; + case "ecore:EDataType": + eClassifier = parseEDataType(reader, nameSpaces); + break; + case "ecore:EEnum": + eClassifier = parseEEnum(reader, nameSpaces); + break; + default: + logger.error("Unknown subclass '{}' of EClassifier found", type); + throw new XMIParseException("Unknown subclass '" + type + "' of EClassifier found"); + } + + return eClassifier; + + } + + private EClassifier parseEClass(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + EClass eClass = new EClass(); + + // get all the properties out of the element + StartElement startElement = reader.nextEvent().asStartElement(); + + nameSpaces = parseNameSpaces(startElement, nameSpaces); + + for (Iterator attributeIterator = startElement.getAttributes(); attributeIterator.hasNext(); ) { + Attribute attribute = (Attribute) attributeIterator.next(); + + if (attribute.getName().equals(XSI_TYPE)) { + if (!attribute.getValue().equals("ecore:EClass")) { + throw new XMIParseException("Expected ecore:EClass but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // from ENamedElement + case "name": + eClass.setName(attribute.getValue()); + break; + // from EClassifier + case "instanceClassName": + eClass.setInstanceClassName(attribute.getValue()); + break; + case "instanceClass": + logger.warn("ignoring transient attribute 'instanceClass' with value '{}'", attribute.getValue()); + break; + case "defaultValue": + logger.warn("ignoring transient attribute 'defaultValue' with value '{}'", attribute.getValue()); + break; + case "ePackage": + logger.warn("ignoring parent relation 'ePackage' with value '{}'", attribute.getValue()); + break; + // from EClass + case "abstract": + eClass.setAbstract(Boolean.valueOf(attribute.getValue())); + break; + case "interface": + eClass.setInterface(Boolean.valueOf(attribute.getValue())); + break; + case "eSuperTypes": + eClass.addESuperTypes(EClass.createRefDirection(attribute.getValue())); + break; + default: + logger.warn("ignoring attribute {}:{}", attribute.getName().getPrefix(), attribute.getName().getLocalPart()); + } + } + } + + // parse the contained elements + XMLEvent nextEvent = reader.peek(); + while (true) { + if (nextEvent.isStartElement()) { + final StartElement nextElement = nextEvent.asStartElement(); + switch (nextElement.getName().getLocalPart()) { + case "eTypeParameters": + eClass.addETypeParameter(parseETypeParameter(reader, nameSpaces)); + break; + case "eStructuralFeatures": + eClass.addEStructuralFeature(parseEStructuralFeature(reader, nameSpaces)); + break; + case "eOperations": + eClass.addEOperation(parseEOperation(reader, nameSpaces)); + break; + case "eGenericSuperTypes": + eClass.addEGenericSuperType(parseEGenericSuperType(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + return eClass; + } else { + // ignore all other events + if (nextEvent.getEventType() != XMLStreamConstants.CHARACTERS) + logger.warn("ignoring event {}: '{}'", nextEvent.getEventType(), nextEvent.toString().replace("\n", "\\n")); + } + + reader.nextEvent(); + nextEvent = reader.peek(); + } + } + + private EClassifier parseEDataType(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + // TODO implement + return null; + } + + private EClassifier parseEEnum(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + // TODO implement + return null; + } + + private ETypeParameter parseETypeParameter(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + // TODO implement + return null; + } + + private EStructuralFeature parseEStructuralFeature(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + StartElement startElement = reader.peek().asStartElement(); + + EStructuralFeature eStructuralFeature; + + final String type = startElement.getAttributeByName(XSI_TYPE).getValue(); + switch (type) { + case "ecore:EAttribute": + eStructuralFeature = parseEAttribute(reader, nameSpaces); + break; + case "ecore:EReference": + eStructuralFeature = parseEReference(reader, nameSpaces); + break; + default: + logger.error("Unknown subclass '{}' of EStructuralFeature found", type); + throw new XMIParseException("Unknown subclass '" + type + "' of EClassifier found"); + } + + return eStructuralFeature; + } + + private EOperation parseEOperation(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + // TODO implement + return null; + } + + private EGenericType parseEGenericSuperType(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + // TODO implement + return null; + } + + private EAttribute parseEAttribute(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + EAttribute eAttribute = new EAttribute(); + + // get all the properties out of the element + StartElement startElement = reader.nextEvent().asStartElement(); + + nameSpaces = parseNameSpaces(startElement, nameSpaces); + + for (Iterator attributeIterator = startElement.getAttributes(); attributeIterator.hasNext(); ) { + Attribute attribute = (Attribute) attributeIterator.next(); + + if (attribute.getName().equals(XSI_TYPE)) { + if (!attribute.getValue().equals("ecore:EAttribute")) { + throw new XMIParseException("Expected ecore:EAttribute but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // from ENamedElement + case "name": + eAttribute.setName(attribute.getValue()); + break; + // from ETypedElement + case "ordered": + eAttribute.setOrdered(Boolean.valueOf(attribute.getValue())); + break; + case "unique": + eAttribute.setUnique(Boolean.valueOf(attribute.getValue())); + break; + case "lowerBound": + eAttribute.setLowerBound(Integer.valueOf(attribute.getValue())); + break; + case "upperBound": + eAttribute.setUpperBound(Integer.valueOf(attribute.getValue())); + break; + case "eType": + eAttribute.setEType(EClassifier.createRefDirection(attribute.getValue())); + // from EStructuralFeature + case "changeable": + eAttribute.setChangeable(Boolean.valueOf(attribute.getValue())); + break; + case "volatile": + eAttribute.setVolatile(Boolean.valueOf(attribute.getValue())); + break; + case "transient": + eAttribute.setTransient(Boolean.valueOf(attribute.getValue())); + break; + case "defaultValueLiteral": + eAttribute.setdefaultValueLiteral(attribute.getValue()); + break; + case "defaultValue": + logger.warn("ignoring attribute 'defaultValue' with value '{}'", attribute.getValue()); + break; + case "unsettable": + eAttribute.setUnsettable(Boolean.valueOf(attribute.getValue())); + break; + case "derived": + eAttribute.setDerived(Boolean.valueOf(attribute.getValue())); + break; + case "eContainingClass": + logger.warn("ignoring parent relation 'eContainingClass' with value '{}'", attribute.getValue()); + break; + // from EAttribute + case "iD": + eAttribute.setID(Boolean.valueOf(attribute.getValue())); + break; + default: + logger.warn("ignoring attribute {}:{}", attribute.getName().getPrefix(), attribute.getName().getLocalPart()); + } + } + + } + + // parse the contained elements + XMLEvent nextEvent = reader.peek(); + while (true) { + if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + return eAttribute; + } else { + // ignore all other events + if (nextEvent.getEventType() != XMLStreamConstants.CHARACTERS) + logger.warn("ignoring event {}: '{}'", nextEvent.getEventType(), nextEvent.toString().replace("\n", "\\n")); + } + + reader.nextEvent(); + nextEvent = reader.peek(); + } + } + + private EReference parseEReference(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + EReference eReference = new EReference(); + + // get all the properties out of the element + StartElement startElement = reader.nextEvent().asStartElement(); + + nameSpaces = parseNameSpaces(startElement, nameSpaces); + + for (Iterator attributeIterator = startElement.getAttributes(); attributeIterator.hasNext(); ) { + Attribute attribute = (Attribute) attributeIterator.next(); + + if (attribute.getName().equals(XSI_TYPE)) { + if (!attribute.getValue().equals("ecore:EReference")) { + throw new XMIParseException("Expected ecore:EReference but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + + switch (attribute.getName().getLocalPart()) { + // from ENamedElement + case "name": + eReference.setName(attribute.getValue()); + break; + // from ETypedElement + case "ordered": + eReference.setOrdered(Boolean.valueOf(attribute.getValue())); + break; + case "unique": + eReference.setUnique(Boolean.valueOf(attribute.getValue())); + break; + case "lowerBound": + eReference.setLowerBound(Integer.valueOf(attribute.getValue())); + break; + case "upperBound": + eReference.setUpperBound(Integer.valueOf(attribute.getValue())); + break; + case "eType": + eReference.setEType(EClassifier.createRefDirection(attribute.getValue())); + // from EStructuralFeature + case "changeable": + eReference.setChangeable(Boolean.valueOf(attribute.getValue())); + break; + case "volatile": + eReference.setVolatile(Boolean.valueOf(attribute.getValue())); + break; + case "transient": + eReference.setTransient(Boolean.valueOf(attribute.getValue())); + break; + case "defaultValueLiteral": + eReference.setdefaultValueLiteral(attribute.getValue()); + break; + case "unsettable": + eReference.setUnsettable(Boolean.valueOf(attribute.getValue())); + break; + case "derived": + eReference.setDerived(Boolean.valueOf(attribute.getValue())); + break; + case "eContainingClass": + logger.warn("ignoring parent relation 'eContainingClass' with value '{}'", attribute.getValue()); + break; + // from EReference + case "containment": + eReference.setContainment(Boolean.valueOf(attribute.getValue())); + break; + case "resolveProxies": + eReference.setResolveProxies(Boolean.valueOf(attribute.getValue())); + break; + case "eOpposite": + eReference.setEOpposite(EReference.createRefDirection(attribute.getValue())); + break; + default: + logger.warn("ignoring attribute {}:{}", attribute.getName().getPrefix(), attribute.getName().getLocalPart()); + } + } + } + + // parse the contained elements + XMLEvent nextEvent = reader.peek(); + while (true) { + if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + return eReference; + } else { + // ignore all other events + if (nextEvent.getEventType() != XMLStreamConstants.CHARACTERS) + logger.warn("ignoring event {}: '{}'", nextEvent.getEventType(), nextEvent.toString().replace("\n", "\\n")); + } + + reader.nextEvent(); + nextEvent = reader.peek(); + } + } +} diff --git a/src/main/java/de/tudresden/inf/st/e2j/parser/XMIParseException.java b/src/main/java/de/tudresden/inf/st/e2j/parser/XMIParseException.java new file mode 100644 index 0000000000000000000000000000000000000000..14e66f9ddcdf2e303eefaa2ecd1303b00a83a03a --- /dev/null +++ b/src/main/java/de/tudresden/inf/st/e2j/parser/XMIParseException.java @@ -0,0 +1,29 @@ +package de.tudresden.inf.st.e2j.parser; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +public class XMIParseException extends XMLStreamException { + public XMIParseException() { + } + + public XMIParseException(String msg) { + super(msg); + } + + public XMIParseException(Throwable th) { + super(th); + } + + public XMIParseException(String msg, Throwable th) { + super(msg, th); + } + + public XMIParseException(String msg, Location location, Throwable th) { + super(msg, location, th); + } + + public XMIParseException(String msg, Location location) { + super(msg, location); + } +} diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 37f93cadef70ad8a48a74027a71e5a9d09910142..c243823993c50f06c43c520f94e0720d02eb6c2e 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -2,7 +2,7 @@ <Configuration> <Appenders> <Console name="Console"> - <PatternLayout pattern="%highlight{%d{HH:mm:ss.SSS} %-5level} %c{1.} - %msg%n"/> + <PatternLayout pattern="%highlight{%d{HH:mm:ss.SSS} %-5level} %c{1.}:%M() - %msg%n"/> </Console> <RollingFile name="RollingFile" fileName="logs/jastadd-ttc19.log" filePattern="logs/jastadd-ttc19-%i.log"> diff --git a/src/test/java/de/tudresden/inf/st/e2j/parser/ParserTest.java b/src/test/java/de/tudresden/inf/st/e2j/parser/ParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7c8b0244919bc62b1913efb429c6eab521d28723 --- /dev/null +++ b/src/test/java/de/tudresden/inf/st/e2j/parser/ParserTest.java @@ -0,0 +1,42 @@ +package de.tudresden.inf.st.e2j.parser; + +import de.tudresden.inf.st.e2j.jastadd.model.EObject; +import de.tudresden.inf.st.e2j.jastadd.model.EPackage; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; + +class ParserTest { + + @Test + void parsePackage() { + + EObject ePackage = null; + + final String fileName = "/ecore/bigraph.ecore"; + + EcoreParser parser = new EcoreParser(); + + try (InputStream stream = this.getClass().getResourceAsStream(fileName)) { + Assertions.assertNotNull(stream, "unable to load resource '" + fileName + "'"); + ePackage = parser.parse(stream); + } catch (IOException | XMIParseException e) { + Assertions.fail(e); + } + + Assertions.assertNotNull(ePackage); + + Assertions.assertTrue(ePackage instanceof EPackage); + + EPackage p = (EPackage) ePackage; + + StringBuilder b = new StringBuilder(); + + p.writeXMI(b); + + System.out.println(b.toString()); + } + +} diff --git a/src/test/resources/ecore/bigraph.ecore b/src/test/resources/ecore/bigraph.ecore new file mode 100644 index 0000000000000000000000000000000000000000..db72fd127a191003ed74e6712a973bcf759409dd --- /dev/null +++ b/src/test/resources/ecore/bigraph.ecore @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="bigraphBaseModel" + nsURI="http://de.tudresden.inf.st.bigraphs.models" + nsPrefix="bigraphBaseModel"> + <eClassifiers xsi:type="ecore:EClass" name="BPlace" abstract="true"> + <eStructuralFeatures xsi:type="ecore:EReference" name="bChild" upperBound="-1" + eType="#//BPlace" containment="true" eOpposite="#//BPlace/bPrnt"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="bPrnt" eType="#//BPlace" + eOpposite="#//BPlace/bChild"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="BRoot" eSuperTypes="#//BPlace"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="index" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="BNode" eSuperTypes="#//BPlace #//NameableType"> + <eStructuralFeatures xsi:type="ecore:EReference" name="bPorts" upperBound="-1" + eType="#//BPort" containment="true" eOpposite="#//BPort/bNode"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="BSite" eSuperTypes="#//BPlace"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="index" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="BPoint" abstract="true"> + <eStructuralFeatures xsi:type="ecore:EReference" name="bLink" lowerBound="1" eType="#//BLink" + eOpposite="#//BLink/bPoints"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="BLink" abstract="true" eSuperTypes="#//NameableType"> + <eStructuralFeatures xsi:type="ecore:EReference" name="bPoints" lowerBound="1" + upperBound="-1" eType="#//BPoint" eOpposite="#//BPoint/bLink"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="BPort" eSuperTypes="#//BPoint"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="index" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="bNode" lowerBound="1" eType="#//BNode" + eOpposite="#//BNode/bPorts"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="BInnerName" eSuperTypes="#//BPoint #//NameableType"/> + <eClassifiers xsi:type="ecore:EClass" name="BEdge" eSuperTypes="#//BLink"/> + <eClassifiers xsi:type="ecore:EClass" name="BOuterName" eSuperTypes="#//BLink"/> + <eClassifiers xsi:type="ecore:EClass" name="NameableType" abstract="true" interface="true"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" + iD="true"/> + </eClassifiers> +</ecore:EPackage> diff --git a/src/test/resources/ecore/package.ecore b/src/test/resources/ecore/package.ecore new file mode 100644 index 0000000000000000000000000000000000000000..fe80565bfd5aa6d17796f87fde98b3f126961493 --- /dev/null +++ b/src/test/resources/ecore/package.ecore @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="bigraphBaseModel" + nsURI="http://de.tudresden.inf.st.bigraphs.models" + nsPrefix="bigraphBaseModel"> +</ecore:EPackage>