diff --git a/src/main/jastadd/XMI/XMIPathConstruction.jrag b/src/main/jastadd/XMI/XMIPathConstruction.jrag index a2bbe0b94eab4bcd5fb53a8dad49dfab047292bf..d2189bbd7d50cc40b8b94a92ae0b5ff88a6186d0 100644 --- a/src/main/jastadd/XMI/XMIPathConstruction.jrag +++ b/src/main/jastadd/XMI/XMIPathConstruction.jrag @@ -3,24 +3,79 @@ aspect XMIPathConstruction { syn String EModelElement.xmiReference() = xmiPath() + localName(); + eq EClass.xmiReference() { + if (getParent() == null) { + if (this == eObject()) + return "ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject"; + else + throw new RuntimeException("Unable to create reference to EClass " + getName()); + + } else { + return super.xmiReference(); + } + } + eq EDataType.xmiReference() { 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()); - } + if (this == eInt()) + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"; + else if (this == eString()) + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"; + else if (this == eBoolean()) + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"; + else if (this == eJavaObject()) + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EJavaObject"; + else if (this == eEnumerator()) + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EEnumerator"; + else if (this == eResource()) + return "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EResource"; + else if (this == xmlDateTime()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//DateTime"; + else if (this == xmlBoolean()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Boolean"; + else if (this == xmlByte()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Byte"; + else if (this == xmlNormalizedString()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//NormalizedString"; + else if (this == xmlString()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//String"; + else if (this == xmlInteger()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Integer"; + else if (this == xmlDate()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Date"; + else if (this == xmlDecimal()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Decimal"; + else if (this == xmlDuration()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Duration"; + else if (this == xmlLanguage()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Language"; + else if (this == xmlInt()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Int"; + else if (this == xmlLong()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Long"; + else if (this == xmlAnyURI()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//AnyURI"; + else if (this == xmlBase64Binary()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Base64Binary"; + else if (this == xmlNegativeInteger()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//NegativeInteger"; + else if (this == xmlNonNegativeInteger()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//NonNegativeInteger"; + else if (this == xmlNonPositiveInteger()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//NonPositiveInteger"; + else if (this == xmlToken()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Token"; + else if (this == xmlPositiveInteger()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//PositiveInteger"; + else if (this == xmlShort()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Short"; + else if (this == xmlTime()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Time"; + else if (this == xmlUnsignedByte()) + return "ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//UnsignedByte"; + else + throw new RuntimeException("Unable to create reference to EDataType " + getName()); + } else { return super.xmiReference(); } @@ -31,7 +86,20 @@ aspect XMIPathConstruction { if (getParent() != null) { return xmiPath() + localName(); } else { - return "#/"; + if (this instanceof EPackage) { + EPackage ePackage = ((EPackage)this); + int numPackages = ePackage.getPackageList().size(); + if (numPackages > 1) { + for (int index = 0; index < numPackages; index++) { + if (ePackage.getPackageList().get(index) == this) return "/" + index; + } + throw new RuntimeException("Unable to create reference to EPackage, because it is not in the list of packages."); + } else { + return "#/"; + } + } else { + return "#/"; + } } } diff --git a/src/main/jastadd/XMI/XMIPathResolution.jrag b/src/main/jastadd/XMI/XMIPathResolution.jrag index e72245b0b1d0abac93f2ff612bb3b826ea04da21..b331f19d05ece3eaabf0017d2114649a7642c9e2 100644 --- a/src/main/jastadd/XMI/XMIPathResolution.jrag +++ b/src/main/jastadd/XMI/XMIPathResolution.jrag @@ -22,6 +22,15 @@ aspect XMIPathResolution { return (EClassifier) resolve(id); } + private static EClass EClass.eObject; + public static final EClass EClass.eObject() { + if (eObject == null) { + eObject = new EClass(); + eObject.setName("EObject"); + } + return eObject; + } + private static EDataType EDataType.eInt; public static final EDataType EDataType.eInt() { if (eInt == null) { @@ -82,11 +91,239 @@ aspect XMIPathResolution { return eResource; } + private static EDataType EDataType.xmlDateTime; + public static final EDataType EDataType.xmlDateTime() { + if (xmlDateTime == null) { + xmlDateTime = new EDataType(); + xmlDateTime.setInstanceClassName("javax.xml.datatype.XMLGregorianCalendar"); + xmlDateTime.setName("DateTime"); + } + return xmlDateTime; + } + + private static EDataType EDataType.xmlBoolean; + public static final EDataType EDataType.xmlBoolean() { + if (xmlBoolean == null) { + xmlBoolean = new EDataType(); + xmlBoolean.setInstanceClassName("boolean"); + xmlBoolean.setName("Boolean"); + } + return xmlBoolean; + } + + private static EDataType EDataType.xmlByte; + public static final EDataType EDataType.xmlByte() { + if (xmlByte == null) { + xmlByte = new EDataType(); + xmlByte.setInstanceClassName("byte"); + xmlByte.setName("Byte"); + } + return xmlBoolean; + } + + private static EDataType EDataType.xmlNormalizedString; + public static final EDataType EDataType.xmlNormalizedString() { + if (xmlNormalizedString == null) { + xmlNormalizedString = new EDataType(); + xmlNormalizedString.setInstanceClassName("java.lang.String"); + xmlNormalizedString.setName("NormalizedString"); + } + return xmlNormalizedString; + } + + private static EDataType EDataType.xmlString; + public static final EDataType EDataType.xmlString() { + if (xmlString == null) { + xmlString = new EDataType(); + xmlString.setInstanceClassName("java.lang.String"); + xmlString.setName("String"); + } + return xmlString; + } + + private static EDataType EDataType.xmlInteger; + public static final EDataType EDataType.xmlInteger() { + if (xmlInteger == null) { + xmlInteger = new EDataType(); + xmlInteger.setInstanceClassName("java.lang.Integer"); + xmlInteger.setName("Integer"); + } + return xmlInteger; + } + + private static EDataType EDataType.xmlDate; + public static final EDataType EDataType.xmlDate() { + if (xmlDate == null) { + xmlDate = new EDataType(); + xmlDate.setInstanceClassName("javax.xml.datatype.XMLGregorianCalendar"); + xmlDate.setName("Date"); + } + return xmlDate; + } + + private static EDataType EDataType.xmlDecimal; + public static final EDataType EDataType.xmlDecimal() { + if (xmlDecimal == null) { + xmlDecimal = new EDataType(); + xmlDecimal.setInstanceClassName("java.math.BigDecimal"); + xmlDecimal.setName("Decimal"); + } + return xmlDecimal; + } + + private static EDataType EDataType.xmlDuration; + public static final EDataType EDataType.xmlDuration() { + if (xmlDuration == null) { + xmlDuration = new EDataType(); + xmlDuration.setInstanceClassName("javax.xml.datatype.Duration"); + xmlDuration.setName("Duration"); + } + return xmlDuration; + } + + private static EDataType EDataType.xmlLanguage; + public static final EDataType EDataType.xmlLanguage() { + if (xmlLanguage == null) { + xmlLanguage = new EDataType(); + xmlLanguage.setInstanceClassName("java.lang.String"); + xmlLanguage.setName("Language"); + } + return xmlLanguage; + } + + private static EDataType EDataType.xmlInt; + public static final EDataType EDataType.xmlInt() { + if (xmlInt == null) { + xmlInt = new EDataType(); + xmlInt.setInstanceClassName("int"); + xmlInt.setName("Int"); + } + return xmlInt; + } + + private static EDataType EDataType.xmlLong; + public static final EDataType EDataType.xmlLong() { + if (xmlLong == null) { + xmlLong = new EDataType(); + xmlLong.setInstanceClassName("long"); + xmlLong.setName("Long"); + } + return xmlLong; + } + + private static EDataType EDataType.xmlAnyURI; + public static final EDataType EDataType.xmlAnyURI() { + if (xmlAnyURI == null) { + xmlAnyURI = new EDataType(); + xmlAnyURI.setInstanceClassName("java.lang.String"); + xmlAnyURI.setName("AnyURI"); + } + return xmlAnyURI; + } + + private static EDataType EDataType.xmlBase64Binary; + public static final EDataType EDataType.xmlBase64Binary() { + if (xmlBase64Binary == null) { + xmlBase64Binary = new EDataType(); + xmlBase64Binary.setInstanceClassName("byte[]"); + xmlBase64Binary.setName("Base64Binary"); + } + return xmlBase64Binary; + } + + private static EDataType EDataType.xmlNegativeInteger; + public static final EDataType EDataType.xmlNegativeInteger() { + if (xmlNegativeInteger == null) { + xmlNegativeInteger = new EDataType(); + xmlNegativeInteger.setInstanceClassName("java.math.BigInteger"); + xmlNegativeInteger.setName("NegativeInteger"); + } + return xmlNegativeInteger; + } + + private static EDataType EDataType.xmlNonNegativeInteger; + public static final EDataType EDataType.xmlNonNegativeInteger() { + if (xmlNonNegativeInteger == null) { + xmlNonNegativeInteger = new EDataType(); + xmlNonNegativeInteger.setInstanceClassName("java.math.BigInteger"); + xmlNonNegativeInteger.setName("NonNegativeInteger"); + } + return xmlNonNegativeInteger; + } + + private static EDataType EDataType.xmlPositiveInteger; + public static final EDataType EDataType.xmlPositiveInteger() { + if (xmlPositiveInteger == null) { + xmlPositiveInteger = new EDataType(); + xmlPositiveInteger.setInstanceClassName("java.math.BigInteger"); + xmlPositiveInteger.setName("PositiveInteger"); + } + return xmlPositiveInteger; + } + + private static EDataType EDataType.xmlNonPositiveInteger; + public static final EDataType EDataType.xmlNonPositiveInteger() { + if (xmlNonPositiveInteger == null) { + xmlNonPositiveInteger = new EDataType(); + xmlNonPositiveInteger.setInstanceClassName("java.math.BigInteger"); + xmlNonPositiveInteger.setName("NonPositiveInteger"); + } + return xmlNonPositiveInteger; + } + + private static EDataType EDataType.xmlToken; + public static final EDataType EDataType.xmlToken() { + if (xmlToken == null) { + xmlToken = new EDataType(); + xmlToken.setInstanceClassName("java.lang.String"); + xmlToken.setName("Token"); + } + return xmlToken; + } + + private static EDataType EDataType.xmlShort; + public static final EDataType EDataType.xmlShort() { + if (xmlShort == null) { + xmlShort = new EDataType(); + xmlShort.setInstanceClassName("short"); + xmlShort.setName("Short"); + } + return xmlShort; + } + + private static EDataType EDataType.xmlTime; + public static final EDataType EDataType.xmlTime() { + if (xmlTime == null) { + xmlTime = new EDataType(); + xmlTime.setInstanceClassName("javax.xml.datatype.XMLGregorianCalendar"); + xmlTime.setName("Time"); + } + return xmlTime; + } + + private static EDataType EDataType.xmlUnsignedByte; + public static final EDataType EDataType.xmlUnsignedByte() { + if (xmlUnsignedByte == null) { + xmlUnsignedByte = new EDataType(); + xmlUnsignedByte.setInstanceClassName("short"); + xmlUnsignedByte.setName("UnsignedByte"); + } + return xmlUnsignedByte; + } + syn ASTNode ASTNode.resolve(String uriString) { // built-in data types - if (uriString.startsWith("ecore:EDataType ")) { + if (uriString.startsWith("ecore:EClass ")) { + switch (uriString.substring(13)) { + case "http://www.eclipse.org/emf/2002/Ecore#//EObject": + return EClass.eObject(); + default: + throw new RuntimeException("Unable to resolve built-in class '" + uriString + "'"); + } + } else if (uriString.startsWith("ecore:EDataType ")) { switch (uriString.substring(16)) { + case "http://www.eclipse.org/emf/2002/Ecore#//EObject": case "http://www.eclipse.org/emf/2002/Ecore#//EInt": return EDataType.eInt(); case "http://www.eclipse.org/emf/2002/Ecore#//EString": @@ -99,6 +336,48 @@ aspect XMIPathResolution { return EDataType.eEnumerator(); case "http://www.eclipse.org/emf/2002/Ecore#//EResource": return EDataType.eResource(); + case "http://www.eclipse.org/emf/2003/XMLType#//DateTime": + return EDataType.xmlDateTime(); + case "http://www.eclipse.org/emf/2003/XMLType#//Boolean": + return EDataType.xmlBoolean(); + case "http://www.eclipse.org/emf/2003/XMLType#//Byte": + return EDataType.xmlByte(); + case "http://www.eclipse.org/emf/2003/XMLType#//Integer": + return EDataType.xmlInteger(); + case "http://www.eclipse.org/emf/2003/XMLType#//Date": + return EDataType.xmlDate(); + case "http://www.eclipse.org/emf/2003/XMLType#//Decimal": + return EDataType.xmlDecimal(); + case "http://www.eclipse.org/emf/2003/XMLType#//Duration": + return EDataType.xmlDuration(); + case "http://www.eclipse.org/emf/2003/XMLType#//Language": + return EDataType.xmlLanguage(); + case "http://www.eclipse.org/emf/2003/XMLType#//Int": + return EDataType.xmlInt(); + case "http://www.eclipse.org/emf/2003/XMLType#//Long": + return EDataType.xmlLong(); + case "http://www.eclipse.org/emf/2003/XMLType#//AnyURI": + return EDataType.xmlAnyURI(); + case "http://www.eclipse.org/emf/2003/XMLType#//Base64Binary": + return EDataType.xmlBase64Binary(); + case "http://www.eclipse.org/emf/2003/XMLType#//NegativeInteger": + return EDataType.xmlNegativeInteger(); + case "http://www.eclipse.org/emf/2003/XMLType#//NonNegativeInteger": + return EDataType.xmlNonNegativeInteger(); + case "http://www.eclipse.org/emf/2003/XMLType#//NonPositiveInteger": + return EDataType.xmlNonPositiveInteger(); + case "http://www.eclipse.org/emf/2003/XMLType#//Token": + return EDataType.xmlToken(); + case "http://www.eclipse.org/emf/2003/XMLType#//PositiveInteger": + return EDataType.xmlPositiveInteger(); + case "http://www.eclipse.org/emf/2003/XMLType#//Short": + return EDataType.xmlShort(); + case "http://www.eclipse.org/emf/2003/XMLType#//UnsignedByte": + return EDataType.xmlUnsignedByte(); + case "http://www.eclipse.org/emf/2003/XMLType#//NormalizedString": + return EDataType.xmlNormalizedString(); + case "http://www.eclipse.org/emf/2003/XMLType#//String": + return EDataType.xmlString(); default: throw new RuntimeException("Unable to resolve built-in data type '" + uriString + "'"); } @@ -158,7 +437,19 @@ aspect XMIPathResolution { syn ASTNode ASTNode.resolvePathRootFragment(String fragment) { // This method is only relevant if there are multiple roots, and in this case, in general, it is not possible to // select the right one (because we cannot navigate to them) - return root(); + + ASTNode root = root(); + + if (root instanceof EPackage) { + EPackage ownPackage = (EPackage) root; + if (ownPackage.getPackageList().size() == 1) { + return root; + } else { + return ownPackage.getPackageList().get(Integer.valueOf(fragment)); + } + } else { + return root; + } } syn ASTNode ASTNode.resolvePathFragment(String fragment) { @@ -257,7 +548,7 @@ aspect XMIPathResolution { } } - throw new RuntimeException("Unable to find number '" + index + "'child with name '" + name + "'"); + throw new RuntimeException("Unable to find child number '" + index + "' with name '" + name + "'"); } // public static String getID(EObject eObject) { diff --git a/src/main/jastadd/XMI/XMIWriter.jadd b/src/main/jastadd/XMI/XMIWriter.jadd index 62c69554cfbe23d671c482b6dd7bc6db0422d1bd..96c54a409b35488b241f727e47adae89a04b4747 100644 --- a/src/main/jastadd/XMI/XMIWriter.jadd +++ b/src/main/jastadd/XMI/XMIWriter.jadd @@ -7,20 +7,38 @@ aspect XMIWriter { } public void EPackage.writeXMI(StringBuilder b) { - b.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); - this.writeXMI(b, null, 0); + writeXMI(b, "UTF-8"); } - void ASTNode.startXMIElement(StringBuilder b, String type, String context) { + public void EPackage.writeXMI(StringBuilder b, String encoding) { + b.append("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n"); + if (getPackageList().size() > 1) { + b.append("<xmi:XMI 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\">\n"); + for (EPackage p : getPackageList()) { + p.writeXMI(b, null, 1, false, false); + } + b.append("</xmi:XMI>\n"); + } else { + this.writeXMI(b, null, 0, true, false); + } + } + + void ASTNode.startXMIElement(StringBuilder b, String type, String context, boolean topLevel, boolean requiresType) { 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\""); + b.append(type); + if (topLevel) { + // we have a top-level element that is not contained in anything + b.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); - if (!"".equals(type)) { + if (requiresType) { // TODO whether to print the type can be determined by static analysis! b.append(" xsi:type=\"").append(type).append("\""); } @@ -31,17 +49,22 @@ aspect XMIWriter { b.append((context == null) ? type : context); } - void EPackage.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EPackage.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { // opening tag b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "ecore:EPackage", context); + startXMIElement(b, "ecore:EPackage", context, topLevel, requiresType); // attributes // from ENamedElement b.append(" name=\"").append(getName()).append("\""); // from EPackage - b.append(" nsURI=\"").append(getNsURI()).append("\"") - .append(" nsPrefix=\"").append(getNsPrefix()).append("\""); + if (getNsURI() != null && !getNsURI().equals("")) { + b.append(" nsURI=\"").append(getNsURI()).append("\""); + } + if (getNsPrefix() != null && !getNsPrefix().equals("")) { + b.append(" nsPrefix=\"").append(getNsPrefix()).append("\""); + } + if (numContainedChildren() == 0) { b.append("/>\n"); return; @@ -51,14 +74,14 @@ aspect XMIWriter { // child nodes // from EModelElement for (EAnnotation eAnnotation : getEAnnotationList()) { - eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1, false, false); } // from EPackage for (EClassifier eClassifier : getEClassifierList()) { - eClassifier.writeXMI(b, "eClassifiers", indentationLevel + 1); + eClassifier.writeXMI(b, "eClassifiers", indentationLevel + 1, false, true); } for (EPackage eSubpackage : getESubPackageList()) { - eSubpackage.writeXMI(b, "eSubpackages", indentationLevel + 1); + eSubpackage.writeXMI(b, "eSubpackages", indentationLevel + 1, false, false); } // closing tag @@ -67,11 +90,11 @@ aspect XMIWriter { b.append(">\n"); } - abstract void EClassifier.writeXMI(StringBuilder b, String context, int indentationLevel); + abstract void EClassifier.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType); - void EClass.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EClass.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "ecore:EClass", context); + startXMIElement(b, "ecore:EClass", context, topLevel, requiresType); // attributes // from ENamedElement b.append(" name=\"").append(getName()).append("\""); @@ -108,21 +131,21 @@ aspect XMIWriter { // child nodes // from EModelElement for (EAnnotation eAnnotation : getEAnnotationList()) { - eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1, false, false); } // from EClassifier for (ETypeParameter eTypeParameter : getETypeParameterList()) { - eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1); + eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1, false, false); } // from EClass for (EOperation eOperation : getEOperationList()) { - eOperation.writeXMI(b, "eOperations", indentationLevel + 1); + eOperation.writeXMI(b, "eOperations", indentationLevel + 1, false, false); } for (EStructuralFeature eStructuralFeature : getEStructuralFeatureList()) { - eStructuralFeature.writeXMI(b, "eStructuralFeatures", indentationLevel + 1); + eStructuralFeature.writeXMI(b, "eStructuralFeatures", indentationLevel + 1, false, true); } for (EGenericType eGenericSuperType : getEGenericSuperTypeList()) { - eGenericSuperType.writeXMI(b, "eGenericSuperTypes", indentationLevel + 1); + eGenericSuperType.writeXMI(b, "eGenericSuperTypes", indentationLevel + 1, false, false); } // closing tag @@ -131,9 +154,9 @@ aspect XMIWriter { b.append(">\n"); } - void EDataType.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EDataType.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "ecore:EDataType", context); + startXMIElement(b, "ecore:EDataType", context, topLevel, requiresType); // attributes b.append(" name=\"").append(getName()).append("\""); // from EClassifier @@ -154,11 +177,11 @@ aspect XMIWriter { // child nodes // from EModelElement for (EAnnotation eAnnotation : getEAnnotationList()) { - eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1, false, false); } // from EClassifier for (ETypeParameter eTypeParameter : getETypeParameterList()) { - eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1); + eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1, false, false); } // closing tag @@ -167,9 +190,78 @@ aspect XMIWriter { b.append(">\n"); } - void EGenericType.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EEnum.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "ecore:EEnum", context, topLevel, requiresType); + // 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, false, false); + } + // from EClassifier + for (ETypeParameter eTypeParameter : getETypeParameterList()) { + eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1, false, false); + } + // from EEnum + for (EEnumLiteral eLiteral : getELiteralList()) { + eLiteral.writeXMI(b, "eLiterals", indentationLevel + 1, false, false); + } + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "ecore:EEnum", context); + b.append(">\n"); + } + + void EEnumLiteral.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { + b.append(indentString(indentationLevel)).append("<"); + startXMIElement(b, "", context, topLevel, requiresType); + // attributes + // from ENamedElement + if (getName() != null && !getName().equals("")) { + b.append(" name=\"").append(getName()).append("\""); + } + // from ENamedElement + b.append(" value=\"").append(getValue()).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, false, false); + } + + // closing tag + b.append(indentString(indentationLevel)).append("</"); + endXMIElement(b, "", context); + b.append(">\n"); + } + + void EGenericType.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "", context); + startXMIElement(b, "", context, topLevel, requiresType); // attributes if (hasETypeParameter()) { b.append(" eTypeParameter=\"").append(getETypeParameter().xmiReference()).append("\""); @@ -185,13 +277,13 @@ aspect XMIWriter { // child nodes // from EGenericType if (hasEUpperBound()) { - getEUpperBound().writeXMI(b, "eUpperBound", indentationLevel + 1); + getEUpperBound().writeXMI(b, "eUpperBound", indentationLevel + 1, false, false); } if (hasELowerBound()) { - getELowerBound().writeXMI(b, "eLowerBound", indentationLevel + 1); + getELowerBound().writeXMI(b, "eLowerBound", indentationLevel + 1, false, false); } for (EGenericType eTypeArgument : getETypeArgumentList()) { - eTypeArgument.writeXMI(b, "eTypeArguments", indentationLevel + 1); + eTypeArgument.writeXMI(b, "eTypeArguments", indentationLevel + 1, false, false); } // closing tag @@ -200,9 +292,9 @@ aspect XMIWriter { b.append(">\n"); } - void EOperation.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EOperation.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "", context); + startXMIElement(b, "", context, topLevel, requiresType); // attributes // from ENamedElement b.append(" name=\"").append(getName()).append("\""); @@ -234,21 +326,21 @@ aspect XMIWriter { // child nodes // from EModelElement for (EAnnotation eAnnotation : getEAnnotationList()) { - eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1, false, false); } // from ETypedElement if (hasEGenericType()) { - getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1); + getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1, false, false); } // from EOperation for (EGenericType eGenericException : getEGenericExceptionList()) { - eGenericException.writeXMI(b, "eGenericExceptions", indentationLevel + 1); + eGenericException.writeXMI(b, "eGenericExceptions", indentationLevel + 1, false, false); } for (ETypeParameter eTypeParameter : getETypeParameterList()) { - eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1); + eTypeParameter.writeXMI(b, "eTypeParameters", indentationLevel + 1, false, false); } for (EParameter eParameter : getEParameterList()) { - eParameter.writeXMI(b, "eParameters", indentationLevel + 1); + eParameter.writeXMI(b, "eParameters", indentationLevel + 1, false, false); } // closing tag @@ -257,9 +349,9 @@ aspect XMIWriter { b.append(">\n"); } - void EParameter.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EParameter.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "", context); + startXMIElement(b, "", context, topLevel, requiresType); // attributes // from ENamedElement b.append(" name=\"").append(getName()).append("\""); @@ -287,11 +379,11 @@ aspect XMIWriter { // child nodes // from EModelElement for (EAnnotation eAnnotation : getEAnnotationList()) { - eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1, false, false); } // from ETypedElement if (hasEGenericType()) { - getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1); + getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1, false, false); } // closing tag @@ -301,11 +393,11 @@ aspect XMIWriter { } - abstract void EStructuralFeature.writeXMI(StringBuilder b, String context, int indentationLevel); + abstract void EStructuralFeature.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType); - void EReference.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EReference.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "ecore:EReference", context); + startXMIElement(b, "ecore:EReference", context, topLevel, requiresType); // attributes // from ENamedElement b.append(" name=\"").append(getName()).append("\""); @@ -362,11 +454,11 @@ aspect XMIWriter { // child nodes // from EModelElement for (EAnnotation eAnnotation : getEAnnotationList()) { - eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1, false, false); } // from ETypedElement if (hasEGenericType()) { - getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1); + getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1, false, false); } // closing tag @@ -375,9 +467,9 @@ aspect XMIWriter { b.append(">\n"); } - void EAttribute.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EAttribute.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "ecore:EAttribute", context); + startXMIElement(b, "ecore:EAttribute", context, topLevel, requiresType); // attributes // from ENamedElement b.append(" name=\"").append(getName()).append("\""); @@ -428,11 +520,11 @@ aspect XMIWriter { // child nodes // from EModelElement for (EAnnotation eAnnotation : getEAnnotationList()) { - eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1, false, false); } // from ETypedElement if (hasEGenericType()) { - getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1); + getEGenericType().writeXMI(b, "eGenericType", indentationLevel + 1, false, false); } // closing tag @@ -441,9 +533,9 @@ aspect XMIWriter { b.append(">\n"); } - void EAnnotation.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EAnnotation.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "", context); + startXMIElement(b, "", context, topLevel, requiresType); // attributes b.append(" source=\"").append(getSource()).append("\""); @@ -454,7 +546,7 @@ aspect XMIWriter { b.append(">\n"); // child nodes for (EStringToStringMapEntry detail : getDetailList()) { - detail.writeXMI(b, "details", indentationLevel + 1); + detail.writeXMI(b, "details", indentationLevel + 1, false, false); } // closing tag @@ -463,9 +555,9 @@ aspect XMIWriter { b.append(">\n"); } - void EStringToStringMapEntry.writeXMI(StringBuilder b, String context, int indentationLevel) { + void EStringToStringMapEntry.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "", context); + startXMIElement(b, "", context, topLevel, requiresType); // attributes b.append(" key=\"").append(getKey()).append("\""); b.append(" value=\"").append(getValue()).append("\""); @@ -473,9 +565,9 @@ aspect XMIWriter { b.append("/>\n"); } - void ETypeParameter.writeXMI(StringBuilder b, String context, int indentationLevel) { + void ETypeParameter.writeXMI(StringBuilder b, String context, int indentationLevel, boolean topLevel, boolean requiresType) { b.append(indentString(indentationLevel)).append("<"); - startXMIElement(b, "", context); + startXMIElement(b, "", context, topLevel, requiresType); // attributes // from ENamedElement b.append(" name=\"").append(getName()).append("\""); @@ -487,11 +579,11 @@ aspect XMIWriter { // child nodes // from EModelElement for (EAnnotation eAnnotation : getEAnnotationList()) { - eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1); + eAnnotation.writeXMI(b, "eAnnotations", indentationLevel + 1, false, false); } // from ETypeParameter for (EGenericType eGenericType : getEBoundList()) { - eGenericType.writeXMI(b, "eTypeParameters", indentationLevel + 1); + eGenericType.writeXMI(b, "eTypeParameters", indentationLevel + 1, false, false); } // closing tag 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 53a6c3e4b75cbc7c39c1d7271b622dc80ed70b8f..a1bcae043d7973793d0ad07eadc1d61d434b1eeb 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 @@ -14,10 +14,7 @@ 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; +import java.util.*; public class EcoreParser { @@ -27,7 +24,7 @@ public class EcoreParser { private static Logger logger = LogManager.getLogger(EcoreParser.class); private final XMLInputFactory factory = XMLInputFactory.newInstance(); - public EObject parse(InputStream stream) throws XMIParseException { + public List<EObject> parse(InputStream stream) throws XMIParseException { try { final XMLEventReader reader = factory.createXMLEventReader(stream); @@ -43,8 +40,12 @@ public class EcoreParser { StartElement root = event.asStartElement(); switch (root.getName().getLocalPart()) { + case "XMI": + return parseXMI(reader, Collections.EMPTY_MAP); case "EPackage": - return parseEPackage(reader, Collections.EMPTY_MAP); + EPackage ePackage = parseEPackage(reader, Collections.EMPTY_MAP); + ePackage.addPackage(ePackage); + return Collections.singletonList(ePackage); default: throw new XMIParseException("Unable to parse root element " + root.getName().toString()); } @@ -75,6 +76,76 @@ public class EcoreParser { return result; } + private List<EPackage> parseXMI(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + List<EPackage> contents = new ArrayList<>(); + + + // 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()) { + default: + logger.warn("ignoring attribute {}:{}", attribute.getName().getPrefix(), attribute.getName().getLocalPart()); + } + } + + // parse the contained elements + while (reader.hasNext()) { + XMLEvent nextEvent = reader.peek(); +// logger.debug("looking at ({}:{}) :'{};.", nextEvent.getLocation().getLineNumber(), nextEvent.getLocation().getColumnNumber(), nextEvent); + if (nextEvent.isStartElement()) { + if (nextEvent.isStartDocument()) { + reader.nextEvent(); + } else if (nextEvent.isStartElement()) { + StartElement root = nextEvent.asStartElement(); + + switch (root.getName().getLocalPart()) { + case "EPackage": + contents.add(parseEPackage(reader, Collections.EMPTY_MAP)); + break; + default: + throw new XMIParseException("Unable to parse root element " + root.getName().toString()); + } + } else { + logger.error("the element is a {}", nextEvent.getEventType()); + throw new XMIParseException("Element is not a start element!"); + } + + } else if (nextEvent.isEndElement() && nextEvent.asEndElement().getName().equals(startElement.getName())) { + reader.nextEvent(); + + for (EPackage ePackage: contents) { + for (EPackage sibling : contents) { + ePackage.addPackage(sibling); + } + } + + return contents; + } else { + // ignore all other events + if (nextEvent.getEventType() != XMLStreamConstants.CHARACTERS) + logger.warn("ignoring event at ({}:{}) {}", nextEvent.getLocation().getLineNumber(), nextEvent.getLocation().getColumnNumber(), nextEvent); + reader.nextEvent(); + } + } + + // TODO throw exception + + for (EPackage ePackage: contents) { + for (EPackage sibling : contents) { + ePackage.addPackage(sibling); + } + } + + return contents; + } + private EPackage parseEPackage(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { EPackage ePackage = new EPackage(); @@ -115,6 +186,10 @@ public class EcoreParser { case "eAnnotations": ePackage.addEAnnotation(parseEAnnotation(reader, nameSpaces)); break; + // from EPackage + case "eSubpackages": + ePackage.addESubPackage(parseEPackage(reader, nameSpaces)); + break; default: logger.warn("ignoring element at ({}:{}) {}:{}", nextEvent.getLocation().getLineNumber(), nextEvent.getLocation().getColumnNumber(), nextElement.getName().getPrefix(), nextElement.getName().getLocalPart()); } @@ -378,9 +453,142 @@ public class EcoreParser { } } - private EClassifier parseEEnum(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { - // TODO implement - return null; + private EEnum parseEEnum(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + EEnum eEnum = new EEnum(); + + // set default values + eEnum.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:EEnum")) { + throw new XMIParseException("Expected ecore:EEnum but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // from ENamedElement + case "name": + eEnum.setName(attribute.getValue()); + break; + // from EClassifier + case "instanceClassName": + eEnum.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": + eEnum.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": + eEnum.addETypeParameter(parseETypeParameter(reader, nameSpaces)); + break; + case "eAnnotations": + eEnum.addEAnnotation(parseEAnnotation(reader, nameSpaces)); + break; + case "eLiterals": + eEnum.addELiteral(parseEEnumLiteral(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 eEnum; + } 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 EEnumLiteral parseEEnumLiteral(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { + + EEnumLiteral eEnumLiteral = new EEnumLiteral(); + + // 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:EEnumLiteral")) { + throw new XMIParseException("Expected ecore:EEnumLiteral but found " + attribute.getValue(), attribute.getLocation()); + } + } else { + switch (attribute.getName().getLocalPart()) { + // from ENamedElement + case "name": + eEnumLiteral.setName(attribute.getValue()); + break; + // from EEnumLiteral + case "value": + eEnumLiteral.setValue(Integer.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 "eAnnotations": + eEnumLiteral.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 eEnumLiteral; + } 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 ETypeParameter parseETypeParameter(final XMLEventReader reader, Map<String, String> nameSpaces) throws XMLStreamException { 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 index 47b654ffa269bc23c6958070acdb5a3f60820e01..6635beae0bb32768a8d394ae7e05561000fdb026 100644 --- a/src/test/java/de/tudresden/inf/st/e2j/parser/ParserTest.java +++ b/src/test/java/de/tudresden/inf/st/e2j/parser/ParserTest.java @@ -2,16 +2,61 @@ 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.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.stream.Stream; class ParserTest { + + private static Logger logger = LogManager.getLogger(ParserTest.class); + + @ParameterizedTest + @ArgumentsSource(EcoreFileProvider.class) + void parseEcore(String fileName) { + + logger.info("Parsing file src/test/resources/ecore/zoo/{}", fileName); + + EObject ePackage = null; + + EcoreParser parser = new EcoreParser(); + + try (InputStream stream = this.getClass().getResourceAsStream("/ecore/zoo/" + fileName)) { + Assertions.assertNotNull(stream, "unable to load resource '" + fileName + "'"); + ePackage = parser.parse(stream).get(0); + } catch (IOException | XMIParseException e) { + Assertions.fail(e); + } + + Assertions.assertNotNull(ePackage); + + Assertions.assertTrue(ePackage instanceof EPackage); + + EPackage p = (EPackage) ePackage; + + StringBuilder b = new StringBuilder(); + + logger.info("writing {} packages", p.getPackageList().size()); + p.writeXMI(b, "ISO-8859-1"); + + try (PrintWriter out = new PrintWriter("src/test/resources/ecore/zoo-gen/" + fileName, StandardCharsets.ISO_8859_1.name())) { + out.print(b.toString()); + } catch (FileNotFoundException | UnsupportedEncodingException e) { + Assertions.fail("unable to write output file", e); + } + + } + @Test void parseBigraph() { @@ -23,7 +68,7 @@ class ParserTest { try (InputStream stream = this.getClass().getResourceAsStream(fileName)) { Assertions.assertNotNull(stream, "unable to load resource '" + fileName + "'"); - ePackage = parser.parse(stream); + ePackage = parser.parse(stream).get(0); } catch (IOException | XMIParseException e) { Assertions.fail(e); } @@ -58,7 +103,7 @@ class ParserTest { try (InputStream stream = this.getClass().getResourceAsStream(fileName)) { Assertions.assertNotNull(stream, "unable to load resource '" + fileName + "'"); - ePackage = parser.parse(stream); + ePackage = parser.parse(stream).get(0); } catch (IOException | XMIParseException e) { Assertions.fail(e); } @@ -82,4 +127,23 @@ class ParserTest { System.out.println(b.toString()); } + public static class EcoreFileProvider implements ArgumentsProvider { + + @Override + public Stream<? extends Arguments> provideArguments(ExtensionContext context) { + + try (InputStream stream = this.getClass().getResourceAsStream("/ecore/zoo")) { + return new BufferedReader(new InputStreamReader(stream)) + .lines() + .filter(fileName -> fileName.endsWith(".ecore")) + .map(Arguments::of); + } catch (IOException e) { + Assertions.fail(e); + } + + // no stream if something fails + return Stream.empty(); + } + } + }