diff --git a/src/main/jastadd/JastAddAPIExtension.jadd b/src/main/jastadd/JastAddAPIExtension.jadd new file mode 100644 index 0000000000000000000000000000000000000000..a2a97601f956515551eea2dfc9779029a057a934 --- /dev/null +++ b/src/main/jastadd/JastAddAPIExtension.jadd @@ -0,0 +1,47 @@ +aspect JastAddAPIExtension { + + /** + * removes the object from the AST, i.e. removes the reference from its parent to the object + * + * Please note that any intrinsic non-containment relations to the object are not removed. + * @return true, if the object had a parent. + */ + public boolean ASTNode.removeSelf() { + if (getParent() == null) { + return false; + } else { + for (int childIndex = 0; childIndex < getParent().numChildren(); childIndex++) { + if (getParent().getChild(childIndex) == this) { + getParent().removeChild(childIndex); + return true; + } + } + } + throw new RuntimeException("unable to remove child, because it was not contained in its parent!"); + } + + public int ASTNode.containedChildren() { + int result = 0; + for (ASTNode child: this.astChildren()) { + if (child instanceof JastAddList) { + result += child.numChildren(); + } else if (child instanceof Opt) { + if (getChild(0).numChildren() != 0) { + result += 1; + } + } else { + result += 1; + } + } + return result; + } + + public ASTNode ASTNode.root() { + if (getParent() == null) { + return this; + } else { + return getParent().root(); + } + } + +} diff --git a/src/main/jastadd/XMI/XMIWriter.jadd b/src/main/jastadd/XMI/XMIWriter.jadd index 4096a537a60ef290e36e44c4bfb5fcbd07d102d9..cc0714b8af6c8a1bde07789859117abbcffac159 100644 --- a/src/main/jastadd/XMI/XMIWriter.jadd +++ b/src/main/jastadd/XMI/XMIWriter.jadd @@ -31,12 +31,25 @@ aspect XMIWriter { // 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"); + // attributes + // from ENamedElement + b.append(" name=\"").append(getName()).append("\""); + // from EPackage + b.append(" nsURI=\"").append(getNsURI()).append("\"") + .append(" nsPrefix=\"").append(getNsPrefix()).append("\""); + if (containedChildren() == 0) { + b.append("/>\n"); + return; + } + b.append(">\n"); + // child nodes + // from EModelElement + for (EAnnotation eAnnotation : getEAnnotationList()) { + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + } + // from EPackage for (EClassifier eClassifier : getEClassifierList()) { eClassifier.writeXMI(b, "eClassifiers", indentationLevel + 1); } @@ -56,10 +69,44 @@ aspect XMIWriter { b.append(indentString(indentationLevel)).append("<"); startXMIElement(b, "ecore:EClass", context); // attributes + // from ENamedElement b.append(" name=\"").append(getName()).append("\""); - + // from EClassifier + if (getInstanceClassName() != "") { + b.append(" instanceClassName=\"").append(getInstanceClassName()).append("\""); + } + // from EClass + if (getAbstract() == true) { + b.append(" abstract=\"true\""); + } + if (getInterface() == true) { + b.append(" interface=\"true\""); + } + if (containedChildren() == 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); + } + // from EClass + for (EStructuralFeature eStructuralFeature : getEStructuralFeatureList()) { + eStructuralFeature.writeXMI(b, "eStructuralFeatures", indentationLevel + 1); + } + for (EOperation eOperation : getEOperationList()) { + eOperation.writeXMI(b, "eOperations", indentationLevel + 1); + } + for (EGenericType eGenericSuperType : getEGenericSuperTypeList()) { + eGenericSuperType.writeXMI(b, "eGenericSuperTypes", indentationLevel + 1); + } // closing tag b.append(indentString(indentationLevel)).append("</"); @@ -73,12 +120,165 @@ aspect XMIWriter { // attributes b.append(" name=\"").append(getName()).append("\""); + if (containedChildren() == 0) { + b.append("/>\n"); + return; + } + b.append(">\n"); + // child nodes + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "ecore:EPackage", context); + b.append(">\n"); + } + + void EGenericType.writeXMI(StringBuilder b, String context, int indentationLevel) { + // TODO implement + } + + void EOperation.writeXMI(StringBuilder b, String context, int indentationLevel) { + // TODO implement + } + + abstract void EStructuralFeature.writeXMI(StringBuilder b, String context, int indentationLevel); + + void EReference.writeXMI(StringBuilder b, String context, int indentationLevel) { + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "ecore:EReference", 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() + "\""); + } + // from EStructuralFEature + if (getChangeable() == false) { + b.append(" changeable=\"false\""); + } + if (getVolatile() == true) { + b.append(" volatile=\"true\""); + } + if (getTransient() == true) { + b.append(" transient=\"true\""); + } + if (getDefaultValueLiteral() != "") { + b.append(" defaultValueLiteral=\"").append(getDefaultValueLiteral()).append("\""); + } + if (getUnsettable() == true) { + b.append(" unsettable=\"true\""); + } + if (getDerived() == true) { + b.append(" derived=\"true\""); + } + // from EReference + if (getContainment() == true) { + b.append(" containment=\"true\""); + } + if (getResolveProxies() == false) { + b.append(" resolveProxies=\"false\""); + } + if (getNumChild() == 0) { + b.append("/>\n"); + return; + } + if (containedChildren() == 0) { + b.append("/>\n"); + return; + } + System.out.println(containedChildren()); + b.append(">\n"); + // child nodes + // from EModelElement + for (EAnnotation eAnnotation : getEAnnotationList()) { + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + } + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "ecore:EPackage", context); + b.append(">\n"); + } + + void EAttribute.writeXMI(StringBuilder b, String context, int indentationLevel) { + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "ecore:EAttribute", 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() + "\""); + } + // from EStructuralFEature + if (getChangeable() == false) { + b.append(" changeable=\"false\""); + } + if (getVolatile() == true) { + b.append(" volatile=\"true\""); + } + if (getTransient() == true) { + b.append(" transient=\"true\""); + } + if (getDefaultValueLiteral() != "") { + b.append(" defaultValueLiteral=\"").append(getDefaultValueLiteral()).append("\""); + } + if (getUnsettable() == true) { + b.append(" unsettable=\"true\""); + } + if (getDerived() == true) { + b.append(" derived=\"true\""); + } + // from EAttribute + if (getID() == true) { + b.append(" iD=\"true\""); + } + if (getNumChild() == 0) { + b.append("/>\n"); + return; + } + if (containedChildren() == 0) { + b.append("/>\n"); + return; + } + System.out.println(containedChildren()); b.append(">\n"); // child nodes + // from EModelElement + for (EAnnotation eAnnotation : getEAnnotationList()) { + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + } // closing tag b.append(indentString(indentationLevel)).append("</"); endXMIElement(b, "ecore:EPackage", context); b.append(">\n"); } + + void EAnnotation.writeXMI(StringBuilder b, String context, int indentationLevel) { + // TODO implement + } + + void ETypeParameter.writeXMI(StringBuilder b, String context, int indentationLevel) { + // TODO implement + } } diff --git a/src/main/jastadd/ecore.relast b/src/main/jastadd/ecore.relast index f03a19a331f43e12098574f511500fa95440e1c6..a3cc7bb64606ad7520f8ce1ba1f9b1a3afd1b699 100644 --- a/src/main/jastadd/ecore.relast +++ b/src/main/jastadd/ecore.relast @@ -18,7 +18,7 @@ EClass : EClassifier ::= EStructuralFeature* EOperation* EGenericSuperType:EGene EDataType : EClassifier; EEnum : EDataType ::= ELiteral:EEnumLiteral*; -EStructuralFeature : ETypedElement ::= <Changeable:boolean> <Volatile:boolean> <Transient:boolean> <defaultValueLiteral:String> <Unsettable:boolean> <Derived:boolean>; +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*; 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 33848110e7309a2780e7d8f5865b17e3f3056aa9..d05d28cda590632892347e9b57ba448084260f8d 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 @@ -286,6 +286,12 @@ public class EcoreParser { EAttribute eAttribute = new EAttribute(); + // set default values + eAttribute.setOrdered(true); + eAttribute.setUnique(true); + eAttribute.setUpperBound(1); + eAttribute.setChangeable(true); + // get all the properties out of the element StartElement startElement = reader.nextEvent().asStartElement(); @@ -319,6 +325,7 @@ public class EcoreParser { break; case "eType": eAttribute.setEType(EClassifier.createRefDirection(attribute.getValue())); + break; // from EStructuralFeature case "changeable": eAttribute.setChangeable(Boolean.valueOf(attribute.getValue())); @@ -330,7 +337,7 @@ public class EcoreParser { eAttribute.setTransient(Boolean.valueOf(attribute.getValue())); break; case "defaultValueLiteral": - eAttribute.setdefaultValueLiteral(attribute.getValue()); + eAttribute.setDefaultValueLiteral(attribute.getValue()); break; case "defaultValue": logger.warn("ignoring attribute 'defaultValue' with value '{}'", attribute.getValue()); @@ -375,6 +382,13 @@ public class EcoreParser { EReference eReference = new EReference(); + // set default values + eReference.setOrdered(true); + eReference.setUnique(true); + eReference.setUpperBound(1); + eReference.setChangeable(true); + eReference.setResolveProxies(true); + // get all the properties out of the element StartElement startElement = reader.nextEvent().asStartElement(); @@ -409,6 +423,7 @@ public class EcoreParser { break; case "eType": eReference.setEType(EClassifier.createRefDirection(attribute.getValue())); + break; // from EStructuralFeature case "changeable": eReference.setChangeable(Boolean.valueOf(attribute.getValue())); @@ -420,7 +435,7 @@ public class EcoreParser { eReference.setTransient(Boolean.valueOf(attribute.getValue())); break; case "defaultValueLiteral": - eReference.setdefaultValueLiteral(attribute.getValue()); + eReference.setDefaultValueLiteral(attribute.getValue()); break; case "unsettable": eReference.setUnsettable(Boolean.valueOf(attribute.getValue()));