diff --git a/src/main/jastadd/XMI/XMIPathConstruction.jrag b/src/main/jastadd/XMI/XMIPathConstruction.jrag index b85806c7c23d45664b5f241781d639793ac0ca2e..a2bbe0b94eab4bcd5fb53a8dad49dfab047292bf 100644 --- a/src/main/jastadd/XMI/XMIPathConstruction.jrag +++ b/src/main/jastadd/XMI/XMIPathConstruction.jrag @@ -4,13 +4,25 @@ aspect XMIPathConstruction { syn String EModelElement.xmiReference() = xmiPath() + localName(); eq EDataType.xmiReference() { - switch (getName()) { - case "EInt": - return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"; - case "EString": - return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"; - default: - throw new RuntimeException("Unable to create reference to EDataType " + getName()); + if (getParent() == null) { + switch (getName()) { + case "EInt": + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"; + case "EString": + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"; + case "EBoolean": + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"; + case "EJavaObject": + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EJavaObject"; + case "EEnumerator": + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EEnumerator"; + case "EResource": + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EResource"; + default: + throw new RuntimeException("Unable to create reference to EDataType " + getName()); + } + } else { + return super.xmiReference(); } } @@ -56,7 +68,7 @@ aspect XMIPathConstruction { eq EEnum.getELiteral(int i).localRelativeName() = "/@eLiterals." + i; - eq EOperation.getGenericException(int i).localRelativeName() = "/@eGenericExceptions." + i; + eq EOperation.getEGenericException(int i).localRelativeName() = "/@eGenericExceptions." + i; eq EOperation.getETypeParameter(int i).localRelativeName() = "/@eTypeParameters." + i; eq EOperation.getEParameter(int i).localRelativeName() = "/@eParameters." + i; diff --git a/src/main/jastadd/XMI/XMIPathResolution.jrag b/src/main/jastadd/XMI/XMIPathResolution.jrag index 47a4bb7f3849b835d557d6024b7e20a11ebd1cdd..e72245b0b1d0abac93f2ff612bb3b826ea04da21 100644 --- a/src/main/jastadd/XMI/XMIPathResolution.jrag +++ b/src/main/jastadd/XMI/XMIPathResolution.jrag @@ -1,7 +1,9 @@ aspect XMIPathResolution { refine RefResolverStubs eq ETypedElement.resolveETypeByToken(String id) { - return (EClassifier) resolve(id); + + EClassifier result = (EClassifier) resolve(id); + return result; } refine RefResolverStubs eq EReference.resolveEOppositeByToken(String id) { @@ -12,6 +14,14 @@ aspect XMIPathResolution { return (EClass) resolve(id); } + refine RefResolverStubs eq EGenericType.resolveEClassifierByToken(String id) { + return (EClassifier) resolve(id); + } + + refine RefResolverStubs eq EOperation.resolveEExceptionsByToken(String id, int position) { + return (EClassifier) resolve(id); + } + private static EDataType EDataType.eInt; public static final EDataType EDataType.eInt() { if (eInt == null) { @@ -32,6 +42,46 @@ aspect XMIPathResolution { return eString; } + private static EDataType EDataType.eBoolean; + public static final EDataType EDataType.eBoolean() { + if (eBoolean == null) { + eBoolean = new EDataType(); + eBoolean.setInstanceClassName("boolean"); + eBoolean.setName("EBoolean"); + } + return eBoolean; + } + + private static EDataType EDataType.eJavaObject; + public static final EDataType EDataType.eJavaObject() { + if (eJavaObject == null) { + eJavaObject = new EDataType(); + eJavaObject.setInstanceClassName("java.lang.Object"); + eJavaObject.setName("EJavaObject"); + } + return eBoolean; + } + + private static EDataType EDataType.eEnumerator; + public static final EDataType EDataType.eEnumerator() { + if (eEnumerator == null) { + eEnumerator = new EDataType(); + eEnumerator.setInstanceClassName("org.eclipse.emf.common.util.Enumerator"); + eEnumerator.setName("EEnumerator"); + } + return eBoolean; + } + + private static EDataType EDataType.eResource; + public static final EDataType EDataType.eResource() { + if (eResource == null) { + eResource = new EDataType(); + eResource.setInstanceClassName("org.eclipse.emf.ecore.resource.Resource"); + eResource.setName("EResource"); + } + return eResource; + } + syn ASTNode ASTNode.resolve(String uriString) { // built-in data types @@ -41,6 +91,14 @@ aspect XMIPathResolution { return EDataType.eInt(); case "http://www.eclipse.org/emf/2002/Ecore#//EString": return EDataType.eString(); + case "http://www.eclipse.org/emf/2002/Ecore#//EBoolean": + return EDataType.eBoolean(); + case "http://www.eclipse.org/emf/2002/Ecore#//EJavaObject": + return EDataType.eJavaObject(); + case "http://www.eclipse.org/emf/2002/Ecore#//EEnumerator": + return EDataType.eEnumerator(); + case "http://www.eclipse.org/emf/2002/Ecore#//EResource": + return EDataType.eResource(); default: throw new RuntimeException("Unable to resolve built-in data type '" + uriString + "'"); } diff --git a/src/main/jastadd/XMI/XMIWriter.jadd b/src/main/jastadd/XMI/XMIWriter.jadd index 189c42511c94ab710081ba027053ed961b91c62c..62c69554cfbe23d671c482b6dd7bc6db0422d1bd 100644 --- a/src/main/jastadd/XMI/XMIWriter.jadd +++ b/src/main/jastadd/XMI/XMIWriter.jadd @@ -19,7 +19,11 @@ aspect XMIWriter { " 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("\""); + b.append(context); + if (!"".equals(type)) { + // TODO whether to print the type can be determined by static analysis! + b.append(" xsi:type=\"").append(type).append("\""); + } } } @@ -111,12 +115,12 @@ aspect XMIWriter { eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1); } // from EClass - for (EStructuralFeature eStructuralFeature : getEStructuralFeatureList()) { - eStructuralFeature.writeXMI(b, "eStructuralFeatures", indentationLevel + 1); - } for (EOperation eOperation : getEOperationList()) { eOperation.writeXMI(b, "eOperations", indentationLevel + 1); } + for (EStructuralFeature eStructuralFeature : getEStructuralFeatureList()) { + eStructuralFeature.writeXMI(b, "eStructuralFeatures", indentationLevel + 1); + } for (EGenericType eGenericSuperType : getEGenericSuperTypeList()) { eGenericSuperType.writeXMI(b, "eGenericSuperTypes", indentationLevel + 1); } @@ -132,13 +136,30 @@ aspect XMIWriter { startXMIElement(b, "ecore:EDataType", context); // attributes b.append(" name=\"").append(getName()).append("\""); + // from EClassifier + if (getInstanceClassName() != "") { + b.append(" instanceClassName=\"").append(getInstanceClassName()).append("\""); + } + // from EDataType + if (getSerializable() == false) { + b.append(" serializable=\"false\""); + } if (numContainedChildren() == 0) { b.append("/>\n"); return; } b.append(">\n"); + // child nodes + // from EModelElement + for (EAnnotation eAnnotation : getEAnnotationList()) { + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + } + // from EClassifier + for (ETypeParameter eTypeParameter : getETypeParameterList()) { + eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1); + } // closing tag b.append(indentString(indentationLevel)).append("</"); @@ -147,13 +168,139 @@ aspect XMIWriter { } void EGenericType.writeXMI(StringBuilder b, String context, int indentationLevel) { - // TODO implement + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "", context); + // attributes + if (hasETypeParameter()) { + b.append(" eTypeParameter=\"").append(getETypeParameter().xmiReference()).append("\""); + } + if (hasEClassifier()) { + b.append(" eClassifier=\"").append(getEClassifier().xmiReference()).append("\""); + } + if (numContainedChildren() == 0) { + b.append("/>\n"); + return; + } + b.append(">\n"); + // child nodes + // from EGenericType + if (hasEUpperBound()) { + getEUpperBound().writeXMI(b, "eUpperBound", indentationLevel + 1); + } + if (hasELowerBound()) { + getELowerBound().writeXMI(b, "eLowerBound", indentationLevel + 1); + } + for (EGenericType eTypeArgument : getETypeArgumentList()) { + eTypeArgument.writeXMI(b, "eTypeArguments", indentationLevel + 1); + } + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "", context); + b.append(">\n"); } void EOperation.writeXMI(StringBuilder b, String context, int indentationLevel) { - // TODO implement + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "", context); + // attributes + // from ENamedElement + b.append(" name=\"").append(getName()).append("\""); + // from ETypedElement + if (getOrdered() == false) { + b.append(" ordered=\"false\""); + } + if (getUnique() == false) { + b.append(" unique=\"false\""); + } + if (getLowerBound() != 0) { + b.append(" lowerBound=\"" + getLowerBound() + "\""); + } + if (getUpperBound() != 1) { + b.append(" upperBound=\"" + getUpperBound() + "\""); + } + if (hasEType()) { + b.append(" eType=\"").append(getEType().xmiReference()).append("\""); + } + // from EOperation + for (EClassifier eException : getEExceptionsList()) { + b.append(" eExceptions=\"").append(eException.xmiReference()).append("\""); + } + if (numContainedChildren() == 0) { + b.append("/>\n"); + return; + } + b.append(">\n"); + // child nodes + // from EModelElement + for (EAnnotation eAnnotation : getEAnnotationList()) { + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + } + // from ETypedElement + if (hasEGenericType()) { + getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1); + } + // from EOperation + for (EGenericType eGenericException : getEGenericExceptionList()) { + eGenericException.writeXMI(b, "eGenericExceptions", indentationLevel + 1); + } + for (ETypeParameter eTypeParameter : getETypeParameterList()) { + eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1); + } + for (EParameter eParameter : getEParameterList()) { + eParameter.writeXMI(b, "eParameters", indentationLevel + 1); + } + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "", context); + b.append(">\n"); + } + + void EParameter.writeXMI(StringBuilder b, String context, int indentationLevel) { + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "", context); + // attributes + // from ENamedElement + b.append(" name=\"").append(getName()).append("\""); + // from ETypedElement + if (getOrdered() == false) { + b.append(" ordered=\"false\""); + } + if (getUnique() == false) { + b.append(" unique=\"false\""); + } + if (getLowerBound() != 0) { + b.append(" lowerBound=\"" + getLowerBound() + "\""); + } + if (getUpperBound() != 1) { + b.append(" upperBound=\"" + getUpperBound() + "\""); + } + if (hasEType()) { + b.append(" eType=\"").append(getEType().xmiReference()).append("\""); + } + if (numContainedChildren() == 0) { + b.append("/>\n"); + return; + } + b.append(">\n"); + // child nodes + // from EModelElement + for (EAnnotation eAnnotation : getEAnnotationList()) { + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + } + // from ETypedElement + if (hasEGenericType()) { + getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1); + } + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "", context); + b.append(">\n"); } + abstract void EStructuralFeature.writeXMI(StringBuilder b, String context, int indentationLevel); void EReference.writeXMI(StringBuilder b, String context, int indentationLevel) { @@ -175,7 +322,9 @@ aspect XMIWriter { if (getUpperBound() != 1) { b.append(" upperBound=\"" + getUpperBound() + "\""); } - b.append(" eType=\"").append(getEType().xmiReference()).append("\""); + if (hasEType()) { + b.append(" eType=\"").append(getEType().xmiReference()).append("\""); + } // from EStructuralFEature if (getChangeable() == false) { b.append(" changeable=\"false\""); @@ -205,21 +354,20 @@ aspect XMIWriter { if (hasEOpposite()) { b.append(" eOpposite=\"").append(getEOpposite().xmiReference()).append("\""); } - if (getNumChild() == 0) { - b.append("/>\n"); - return; - } if (numContainedChildren() == 0) { b.append("/>\n"); return; } - System.out.println(numContainedChildren()); b.append(">\n"); // child nodes // from EModelElement for (EAnnotation eAnnotation : getEAnnotationList()) { eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); } + // from ETypedElement + if (hasEGenericType()) { + getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1); + } // closing tag b.append(indentString(indentationLevel)).append("</"); @@ -246,7 +394,9 @@ aspect XMIWriter { if (getUpperBound() != 1) { b.append(" upperBound=\"" + getUpperBound() + "\""); } - b.append(" eType=\"").append(getEType().xmiReference()).append("\""); + if (hasEType()) { + b.append(" eType=\"").append(getEType().xmiReference()).append("\""); + } // from EStructuralFEature if (getChangeable() == false) { b.append(" changeable=\"false\""); @@ -270,10 +420,6 @@ aspect XMIWriter { if (getID() == true) { b.append(" iD=\"true\""); } - if (getNumChild() == 0) { - b.append("/>\n"); - return; - } if (numContainedChildren() == 0) { b.append("/>\n"); return; @@ -284,6 +430,10 @@ aspect XMIWriter { for (EAnnotation eAnnotation : getEAnnotationList()) { eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); } + // from ETypedElement + if (hasEGenericType()) { + getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1); + } // closing tag b.append(indentString(indentationLevel)).append("</"); @@ -292,10 +442,61 @@ aspect XMIWriter { } void EAnnotation.writeXMI(StringBuilder b, String context, int indentationLevel) { - // TODO implement + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "", context); + // attributes + b.append(" source=\"").append(getSource()).append("\""); + + if (numContainedChildren() == 0) { + b.append("/>\n"); + return; + } + b.append(">\n"); + // child nodes + for (EStringToStringMapEntry detail : getDetailList()) { + detail.writeXMI(b, "details", indentationLevel + 1); + } + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "", context); + b.append(">\n"); + } + + void EStringToStringMapEntry.writeXMI(StringBuilder b, String context, int indentationLevel) { + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "", context); + // attributes + b.append(" key=\"").append(getKey()).append("\""); + b.append(" value=\"").append(getValue()).append("\""); + + b.append("/>\n"); } void ETypeParameter.writeXMI(StringBuilder b, String context, int indentationLevel) { - // TODO implement + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "", context); + // attributes + // from ENamedElement + b.append(" name=\"").append(getName()).append("\""); + if (numContainedChildren() == 0) { + b.append("/>\n"); + return; + } + b.append(">\n"); + // child nodes + // from EModelElement + for (EAnnotation eAnnotation : getEAnnotationList()) { + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + } + // from ETypeParameter + for (EGenericType eGenericType : getEBoundList()) { + eGenericType.writeXMI(b, "eTypeParameters", indentationLevel + 1); + } + + // 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 bc96c0f0060429088aaaea9f4eb7be9f4e4a5b25..cb8a91d7a2fd76c22babbb05043068d1a85b6392 100644 --- a/src/main/jastadd/ecore.relast +++ b/src/main/jastadd/ecore.relast @@ -15,13 +15,13 @@ 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; +EDataType : EClassifier ::= <Serializable:boolean>; EEnum : EDataType ::= ELiteral:EEnumLiteral*; abstract EStructuralFeature : ETypedElement ::= <Changeable:boolean> <Volatile:boolean> <Transient:boolean> <DefaultValueLiteral:String> <Unsettable:boolean> <Derived:boolean>; EAttribute : EStructuralFeature ::= <ID:boolean>; EReference : EStructuralFeature ::= <Containment:boolean> <ResolveProxies:boolean>; -EOperation : ETypedElement ::= GenericException:EGenericType* ETypeParameter* EParameter*; +EOperation : ETypedElement ::= EGenericException:EGenericType* ETypeParameter* EParameter*; EParameter : ETypedElement; EStringToStringMapEntry ::= <Key:String> <Value:String>; @@ -29,14 +29,12 @@ EStringToStringMapEntry ::= <Key:String> <Value:String>; ETypeParameter : ENamedElement ::= EBound:EGenericType*; EGenericType ::= [EUpperBound:EGenericType] [ELowerBound:EGenericType] ETypeArgument:EGenericType*; -rel ETypedElement.EType -> EClassifier; +rel ETypedElement.EType? -> EClassifier; rel EOperation.EExceptions* -> EClassifier; rel EClass.ESuperTypes* -> EClass; rel EReference.EOpposite? -> EReference; rel EAnnotation.References* -> EObject; -rel ETypeParameter.GenericTypes* <-> EGenericType.ETypeParameter?; - - +rel EGenericType.ETypeParameter? -> ETypeParameter; rel EGenericType.EClassifier? -> EClassifier; // transient stuff (the inverse directions of the containment relations are missing) 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 index 16ff7abc76fe965d15cd30c40a19a3636f995ce2..53a6c3e4b75cbc7c39c1d7271b622dc80ed70b8f 100644 --- a/src/main/java/de/tudresden/inf/st/e2j/parser/EcoreParser.java +++ b/src/main/java/de/tudresden/inf/st/e2j/parser/EcoreParser.java @@ -105,21 +105,26 @@ public class EcoreParser { // parse the contained elements XMLEvent nextEvent = reader.peek(); while (true) { +// logger.debug("looking at ({}:{}) :'{};.", nextEvent.getLocation().getLineNumber(), nextEvent.getLocation().getColumnNumber(), nextEvent); if (nextEvent.isStartElement()) { final StartElement nextElement = nextEvent.asStartElement(); switch (nextElement.getName().getLocalPart()) { case "eClassifiers": ePackage.addEClassifier(parseEClassifier(reader, nameSpaces)); break; + case "eAnnotations": + ePackage.addEAnnotation(parseEAnnotation(reader, nameSpaces)); + break; default: - logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + logger.warn("ignoring element at ({}:{}) {}:{}", nextEvent.getLocation().getLineNumber(), nextEvent.getLocation().getColumnNumber(), nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); } } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); return ePackage; } else { // ignore all other events if (nextEvent.getEventType() != XMLStreamConstants.CHARACTERS) - logger.warn("ignoring event {}: '{}'", nextEvent.getEventType(), nextEvent.toString().replace("\n", "\\n")); + logger.warn("ignoring event at ({}:{}) {}", nextEvent.getLocation().getLineNumber(), nextEvent.getLocation().getColumnNumber(), nextEvent); } reader.nextEvent(); nextEvent = reader.peek(); @@ -222,11 +227,69 @@ public class EcoreParser { case "eGenericSuperTypes": eClass.addEGenericSuperType(parseEGenericSuperType(reader, nameSpaces)); break; + case "eAnnotations": + eClass.addEAnnotation(parseEAnnotation(reader, nameSpaces)); + break; default: logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); } } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); return eClass; + } else { + // ignore all other events + if (nextEvent.getEventType() != XMLStreamConstants.CHARACTERS) + logger.warn("in start element {}: ignoring event {}: '{}'",startElement.getName(), nextEvent.getEventType(), nextEvent.toString().replace("\n", "\\n")); + } + + reader.nextEvent(); + nextEvent = reader.peek(); + } + } + + private EAnnotation parseEAnnotation(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + EAnnotation eAnnotation = new EAnnotation(); + + // 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:EAnnotation")) { + throw new XMIParseException("Expected ecore:EAnnotation but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // from EAnnotation + case "source": + eAnnotation.setSource(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 "details": + eAnnotation.addDetail(parseEStringToMapEntry(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); + return eAnnotation; } else { // ignore all other events if (nextEvent.getEventType() != XMLStreamConstants.CHARACTERS) @@ -239,8 +302,80 @@ public class EcoreParser { } private EClassifier parseEDataType(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { - // TODO implement - return null; + + EDataType eDataType = new EDataType(); + + // set default values + eDataType.setSerializable(true); + + // 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:EDataType")) { + throw new XMIParseException("Expected ecore:EDataType but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // from ENamedElement + case "name": + eDataType.setName(attribute.getValue()); + break; + // from EClassifier + case "instanceClassName": + eDataType.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 EDataType + case "serializable": + eDataType.setSerializable(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.isStartElement()) { + final StartElement nextElement = nextEvent.asStartElement(); + switch (nextElement.getName().getLocalPart()) { + case "eTypeParameters": + eDataType.addETypeParameter(parseETypeParameter(reader, nameSpaces)); + break; + case "eAnnotations": + eDataType.addEAnnotation(parseEAnnotation(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); + return eDataType; + } else { + // ignore all other events + if (nextEvent.getEventType() != XMLStreamConstants.CHARACTERS) + logger.warn("in start element {}: ignoring event {}: '{}'",startElement.getName(), nextEvent.getEventType(), nextEvent.toString().replace("\n", "\\n")); + } + + reader.nextEvent(); + nextEvent = reader.peek(); + } } private EClassifier parseEEnum(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { @@ -249,8 +384,199 @@ public class EcoreParser { } private ETypeParameter parseETypeParameter(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { - // TODO implement - return null; + + ETypeParameter eTypeParameter = new ETypeParameter(); + + // 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:ETypeParameter")) { + throw new XMIParseException("Expected ecore:ETypeParameter but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // from ENamedElement + case "name": + eTypeParameter.setName(attribute.getValue()); + break; + // from ETypeParameter + 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 "eBounds": + eTypeParameter.addEBound(parseEGenericType(reader, nameSpaces)); + break; + case "eAnnotations": + eTypeParameter.addEAnnotation(parseEAnnotation(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); + return eTypeParameter; + } 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 EParameter parseEParameter(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + EParameter eParameter = new EParameter(); + + // set default values + eParameter.setOrdered(true); + eParameter.setUnique(true); + eParameter.setUpperBound(1); + + // 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:EParameter")) { + throw new XMIParseException("Expected ecore:EParameter but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // from ENamedElement + case "name": + eParameter.setName(attribute.getValue()); + break; + // from ETypedElement + case "ordered": + eParameter.setOrdered(Boolean.valueOf(attribute.getValue())); + break; + case "unique": + eParameter.setUnique(Boolean.valueOf(attribute.getValue())); + break; + case "lowerBound": + eParameter.setLowerBound(Integer.valueOf(attribute.getValue())); + break; + case "upperBound": + eParameter.setUpperBound(Integer.valueOf(attribute.getValue())); + break; + case "eType": + eParameter.setEType(EClassifier.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 "eGenericType": + eParameter.setEGenericType(parseEGenericType(reader, nameSpaces)); + break; + case "eAnnotations": + eParameter.addEAnnotation(parseEAnnotation(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); + return eParameter; + } 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 EGenericType parseEGenericType(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + EGenericType eGenericType = new EGenericType(); + + // 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:EGenericType")) { + throw new XMIParseException("Expected ecore:EGenericType but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // relations + case "eClassifier": + eGenericType.setEClassifier(EClassifier.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 "eUpperBound": + eGenericType.setEUpperBound(parseEGenericType(reader, nameSpaces)); + break; + case "eLowerBound": + eGenericType.setELowerBound(parseEGenericType(reader, nameSpaces)); + break; + case "eTypeArguments": + eGenericType.addETypeArgument(parseEGenericType(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); + return eGenericType; + } 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 EStructuralFeature parseEStructuralFeature(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { @@ -275,13 +601,102 @@ public class EcoreParser { } private EOperation parseEOperation(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { - // TODO implement - return null; + + EOperation eOperation = new EOperation(); + + // set default values + eOperation.setOrdered(true); + eOperation.setUnique(true); + eOperation.setUpperBound(1); + + // 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:EOperation")) { + throw new XMIParseException("Expected ecore:EOperation but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // from ENamedElement + case "name": + eOperation.setName(attribute.getValue()); + break; + // from ETypedElement + case "ordered": + eOperation.setOrdered(Boolean.valueOf(attribute.getValue())); + break; + case "unique": + eOperation.setUnique(Boolean.valueOf(attribute.getValue())); + break; + case "lowerBound": + eOperation.setLowerBound(Integer.valueOf(attribute.getValue())); + break; + case "upperBound": + eOperation.setUpperBound(Integer.valueOf(attribute.getValue())); + break; + case "eType": + eOperation.setEType(EClassifier.createRefDirection(attribute.getValue())); + break; + // from EOperation + case "eExceptions": + for (String eException : attribute.getValue().split(" ")) { + eOperation.addEExceptions(EClassifier.createRefDirection(eException)); + } + 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 "eGenericType": + eOperation.setEGenericType(parseEGenericType(reader, nameSpaces)); + logger.info("setting EGenericType in EOperation {} to {}", eOperation.getName(), eOperation.getEGenericType()); + break; + case "eGenericExceptions": + eOperation.addEGenericException(parseEGenericType(reader, nameSpaces)); + break; + case "eTypeParameters": + eOperation.addETypeParameter(parseETypeParameter(reader, nameSpaces)); + break; + case "eParameters": + eOperation.addEParameter(parseEParameter(reader, nameSpaces)); + break; + case "eAnnotations": + eOperation.addEAnnotation(parseEAnnotation(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); + return eOperation; + } 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 EGenericType parseEGenericSuperType(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { // TODO implement - return null; + throw new RuntimeException("This feature is not implemented yet!"); } private EAttribute parseEAttribute(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { @@ -328,7 +743,7 @@ public class EcoreParser { case "eType": eAttribute.setEType(EClassifier.createRefDirection(attribute.getValue())); break; - // from EStructuralFeature + // from EStructuralFeature case "changeable": eAttribute.setChangeable(Boolean.valueOf(attribute.getValue())); break; @@ -367,7 +782,20 @@ public class EcoreParser { // parse the contained elements XMLEvent nextEvent = reader.peek(); while (true) { - if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + if (nextEvent.isStartElement()) { + final StartElement nextElement = nextEvent.asStartElement(); + switch (nextElement.getName().getLocalPart()) { + case "eGenericType": + eAttribute.setEGenericType(parseEGenericType(reader, nameSpaces)); + break; + case "eAnnotations": + eAttribute.addEAnnotation(parseEAnnotation(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); return eAttribute; } else { // ignore all other events @@ -426,7 +854,7 @@ public class EcoreParser { case "eType": eReference.setEType(EClassifier.createRefDirection(attribute.getValue())); break; - // from EStructuralFeature + // from EStructuralFeature case "changeable": eReference.setChangeable(Boolean.valueOf(attribute.getValue())); break; @@ -467,7 +895,20 @@ public class EcoreParser { // parse the contained elements XMLEvent nextEvent = reader.peek(); while (true) { - if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + if (nextEvent.isStartElement()) { + final StartElement nextElement = nextEvent.asStartElement(); + switch (nextElement.getName().getLocalPart()) { + case "eGenericType": + eReference.setEGenericType(parseEGenericType(reader, nameSpaces)); + break; + case "eAnnotations": + eReference.addEAnnotation(parseEAnnotation(reader, nameSpaces)); + break; + default: + logger.warn("ignoring element {}:{}", nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); + } + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); return eReference; } else { // ignore all other events @@ -479,4 +920,56 @@ public class EcoreParser { nextEvent = reader.peek(); } } + + // special methods + + private EStringToStringMapEntry parseEStringToMapEntry(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + EStringToStringMapEntry eStringToStringMapEntry = new EStringToStringMapEntry(); + + + // 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:EStringToStringMapEntry")) { + throw new XMIParseException("Expected ecore:EReference but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + + switch (attribute.getName().getLocalPart()) { + // from EStringToStringMapEntry + case "key": + eStringToStringMapEntry.setKey(attribute.getValue()); + break; + // from EStringToStringMapEntry + case "value": + eStringToStringMapEntry.setValue(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())) { + reader.nextEvent(); + return eStringToStringMapEntry; + } 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(); + } + } }