mirror of
https://github.com/eMoflon/model-modeling-language-cli.git
synced 2024-05-20 04:00:58 +00:00
Merge pull request #1 from eMoflon/feature/deserializer
Feature/deserializer
This commit is contained in:
commit
784e2c538e
41
README.md
41
README.md
|
@ -32,3 +32,44 @@ Enter the path to the Jar file in the field provided.
|
|||
🎉 You can now use the Modeling Language to its full extent directly in VSCode!
|
||||
|
||||
### Stand-alone use
|
||||
|
||||
The CLI can also be used independently of the VSCode plugin. In this case, input and output are usually via files,
|
||||
the path of which is also specified in the command.
|
||||
|
||||
In general, the CLI can be called by executing the JAR file.
|
||||
|
||||
```shell
|
||||
java -jar ./target/model-modeling-language-cli-1.0-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
In the following we use the alias `mmlcli`.
|
||||
|
||||
```text
|
||||
Usage: mmlcli [-hV] [COMMAND]
|
||||
-h, --help Show this help message and exit.
|
||||
-V, --version Print version information and exit.
|
||||
```
|
||||
|
||||
#### Generate
|
||||
The `generate` command is used to generate Ecore and XMI files from the serialized MML format. By default, the input
|
||||
is via STDIN, the output is in the form of the generated files in a specified directory. Optionally, a file whose
|
||||
content is in serialized MML format can be specified instead of the STDIN input.
|
||||
|
||||
```text
|
||||
Usage: mmlcli generate [-f[=SERIALIZED]] <projectName> <outputDirectory>
|
||||
<projectName> Name of the entire project/workspace
|
||||
<outputDirectory> Path to the output directory
|
||||
-f, --file[=SERIALIZED] Path to the serialized workspace as json file
|
||||
```
|
||||
|
||||
#### Serialize
|
||||
The serialize command is used to serialize Ecore files into the MML format. The entry is made by specifying a path
|
||||
to an Ecore file. The output is via STDOUT by default, but optionally a path to an output file can also be specified
|
||||
in which the serialized model is to be saved.
|
||||
|
||||
```text
|
||||
Usage: mmlcli serialize [-o[=SERIALIZED]] <ecoreFile>
|
||||
<ecoreFile> Path to an Ecore file
|
||||
-o, --out[=SERIALIZED] Path to the output directory
|
||||
```
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
<exclude>META-INF/**</exclude>
|
||||
<exclude>about.html</exclude>
|
||||
<exclude>about.ini</exclude>
|
||||
<exclude>about.mappings</exclude>
|
||||
|
@ -55,6 +54,30 @@
|
|||
<exclude>plugin.xml</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>com.google.code.gson:gson</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>org.eclipse.emf:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>info.picocli:picocli</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>commons-io:commons-io</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
@ -62,6 +85,28 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
|
|
52
pom.xml
52
pom.xml
|
@ -58,7 +58,6 @@
|
|||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
<exclude>META-INF/**</exclude>
|
||||
<exclude>about.html</exclude>
|
||||
<exclude>about.ini</exclude>
|
||||
<exclude>about.mappings</exclude>
|
||||
|
@ -68,6 +67,30 @@
|
|||
<exclude>plugin.xml</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>com.google.code.gson:gson</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>org.eclipse.emf:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>info.picocli:picocli</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>commons-io:commons-io</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
@ -82,6 +105,17 @@
|
|||
<artifactId>picocli</artifactId>
|
||||
<version>4.7.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.15.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.emf</groupId>
|
||||
<artifactId>org.eclipse.emf.ecore</artifactId>
|
||||
|
@ -96,11 +130,27 @@
|
|||
<groupId>org.eclipse.emf</groupId>
|
||||
<artifactId>org.eclipse.emf.ecore.xmi</artifactId>
|
||||
<version>2.36.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.emf</groupId>
|
||||
<artifactId>org.eclipse.emf.ecore</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.emf</groupId>
|
||||
<artifactId>org.eclipse.emf.edit</artifactId>
|
||||
<version>2.20.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.emf</groupId>
|
||||
<artifactId>org.eclipse.emf.common</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.emf</groupId>
|
||||
<artifactId>org.eclipse.emf.ecore</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package de.nexus.mmlcli;
|
||||
|
||||
import de.nexus.mmlcli.generator.GeneratorCommand;
|
||||
import de.nexus.mmlcli.serializer.SerializeCommand;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "mmlcli", mixinStandardHelpOptions = true, version = "v1.0.0", description = "CLI for interaction between MML, EMF and HiPE", subcommands = {GeneratorCommand.class})
|
||||
@CommandLine.Command(name = "mmlcli", mixinStandardHelpOptions = true, version = "v1.0.0", description = "CLI for interaction between MML, EMF and HiPE", subcommands = {GeneratorCommand.class, SerializeCommand.class})
|
||||
public class ModelModelingLanguageCLI {
|
||||
public static void main(String... args) {
|
||||
int exitCode = new CommandLine(new ModelModelingLanguageCLI()).execute(args);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package de.nexus.mmlcli.entities.instance;
|
||||
|
||||
/**
|
||||
* Dataclass for an instance attribute
|
||||
*/
|
||||
public class AttributeEntry<T> {
|
||||
private String name;
|
||||
private String typeId;
|
||||
private T value;
|
||||
private boolean isEnumType;
|
||||
|
||||
public String getTypeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isEnumType() {
|
||||
return isEnumType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package de.nexus.mmlcli.entities.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Dataclass for a generator of a single XMI file
|
||||
*/
|
||||
public class GeneratorInstance {
|
||||
private String instanceName;
|
||||
private ArrayList<ObjectInstance> instances;
|
||||
|
||||
public String getInstanceName() {
|
||||
return instanceName;
|
||||
}
|
||||
|
||||
public ArrayList<ObjectInstance> getInstances() {
|
||||
return instances;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package de.nexus.mmlcli.entities.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Dataclass for list of generators for multiple XMI files
|
||||
*/
|
||||
public class GeneratorInstanceWrapper {
|
||||
private final ArrayList<GeneratorInstance> serializedInstances = new ArrayList<>();
|
||||
|
||||
public ArrayList<GeneratorInstance> getSerializedInstances() {
|
||||
return serializedInstances;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package de.nexus.mmlcli.entities.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Dataclass for an instance
|
||||
*/
|
||||
public class ObjectInstance {
|
||||
private String referenceId;
|
||||
private String referenceTypeId;
|
||||
private String name;
|
||||
private ArrayList<AttributeEntry<?>> attributes;
|
||||
private ArrayList<ReferenceEntry> references;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getReferenceTypeId() {
|
||||
return referenceTypeId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ArrayList<AttributeEntry<?>> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public ArrayList<ReferenceEntry> getReferences() {
|
||||
return references;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package de.nexus.mmlcli.entities.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Dataclass for an instance reference
|
||||
*/
|
||||
public class ReferenceEntry {
|
||||
private String name;
|
||||
private String typeId;
|
||||
private ArrayList<String> referencedIds;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getTypeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
public ArrayList<String> getReferencedIds() {
|
||||
return referencedIds;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package de.nexus.mmlcli.entities.model;
|
||||
|
||||
import de.nexus.mmlcli.serializer.EcoreIdResolver;
|
||||
import org.eclipse.emf.ecore.EAttribute;
|
||||
import org.eclipse.emf.ecore.EClass;
|
||||
import org.eclipse.emf.ecore.EReference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/***
|
||||
* Dataclass for a class-like (Abstract class, class or interface)
|
||||
*/
|
||||
public class AbstractClassEntity {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private boolean isAbstract;
|
||||
private boolean isInterface;
|
||||
private final ArrayList<AttributeEntity<?>> attributes = new ArrayList<>();
|
||||
private final ArrayList<CReferenceEntity> references = new ArrayList<>();
|
||||
private final ArrayList<String> extendsIds = new ArrayList<>();
|
||||
private final ArrayList<String> implementsIds = new ArrayList<>();
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isAbstract() {
|
||||
return isAbstract;
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return isInterface;
|
||||
}
|
||||
|
||||
public ArrayList<AttributeEntity<?>> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public ArrayList<CReferenceEntity> getReferences() {
|
||||
return references;
|
||||
}
|
||||
|
||||
public ArrayList<String> getExtendsIds() {
|
||||
return extendsIds;
|
||||
}
|
||||
|
||||
public ArrayList<String> getImplementsIds() {
|
||||
return implementsIds;
|
||||
}
|
||||
|
||||
private void setReferenceId(String referenceId) {
|
||||
this.referenceId = referenceId;
|
||||
}
|
||||
|
||||
private void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private void setAbstract(boolean anAbstract) {
|
||||
isAbstract = anAbstract;
|
||||
}
|
||||
|
||||
private void setInterface(boolean anInterface) {
|
||||
isInterface = anInterface;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String attributeString = attributes.isEmpty() ? ""
|
||||
: "\n" + attributes.stream().map(AttributeEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
String referenceString = references.isEmpty() ? ""
|
||||
: "\n" + references.stream().map(CReferenceEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
return String.format("%s(isAbstract:%b|isInterface:%b||%s||%s)", name, isAbstract, isInterface, attributeString,
|
||||
referenceString);
|
||||
}
|
||||
|
||||
|
||||
public static AbstractClassEntity fromEClass(EClass clazz, EcoreIdResolver idResolver) {
|
||||
AbstractClassEntity classEntity = new AbstractClassEntity();
|
||||
UUID uuid = idResolver.resolveId(clazz);
|
||||
classEntity.setReferenceId(uuid.toString());
|
||||
classEntity.setName(clazz.getName());
|
||||
classEntity.setAbstract(clazz.isAbstract());
|
||||
classEntity.setInterface(clazz.isInterface());
|
||||
|
||||
clazz.getEStructuralFeatures().forEach(sFeat -> {
|
||||
if (sFeat instanceof EAttribute attr) {
|
||||
classEntity.attributes.add(AttributeEntity.fromEAttribute(attr, idResolver));
|
||||
} else if (sFeat instanceof EReference ref) {
|
||||
classEntity.references.add(CReferenceEntity.fromEReference(ref, idResolver));
|
||||
}
|
||||
});
|
||||
|
||||
classEntity.extendsIds.addAll(clazz.getESuperTypes().stream().map(sClazz -> idResolver.resolveId(sClazz).toString()).toList());
|
||||
|
||||
return classEntity;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
package de.nexus.mmlcli.entities.model;
|
||||
|
||||
import de.nexus.mmlcli.generator.EmfGraphBuilderUtils;
|
||||
import de.nexus.mmlcli.serializer.EcoreIdResolver;
|
||||
import org.eclipse.emf.ecore.EAttribute;
|
||||
import org.eclipse.emf.ecore.EDataType;
|
||||
import org.eclipse.emf.ecore.EEnum;
|
||||
import org.eclipse.emf.ecore.EEnumLiteral;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Dataclass for a class attribute
|
||||
*/
|
||||
public class AttributeEntity<T> {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private String type;
|
||||
private boolean isEnumType;
|
||||
private boolean hasDefaultValue;
|
||||
private T defaultValue;
|
||||
private ClassElementModifiers modifiers;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isEnumType() {
|
||||
return isEnumType;
|
||||
}
|
||||
|
||||
public boolean isHasDefaultValue() {
|
||||
return hasDefaultValue;
|
||||
}
|
||||
|
||||
public T getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public ClassElementModifiers getModifiers() {
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
private void setReferenceId(String referenceId) {
|
||||
this.referenceId = referenceId;
|
||||
}
|
||||
|
||||
private void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private void setEnumType(boolean enumType) {
|
||||
isEnumType = enumType;
|
||||
}
|
||||
|
||||
private void setHasDefaultValue(boolean hasDefaultValue) {
|
||||
this.hasDefaultValue = hasDefaultValue;
|
||||
}
|
||||
|
||||
private void setDefaultValue(T defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
private void setModifiers(ClassElementModifiers modifiers) {
|
||||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s<%s>", name, type);
|
||||
}
|
||||
|
||||
public static AttributeEntity<?> fromEAttribute(EAttribute eAttribute, EcoreIdResolver idResolver) {
|
||||
AttributeEntity<?> attribute = new AttributeEntity<>();
|
||||
UUID uuid = idResolver.resolveId(eAttribute);
|
||||
attribute.setReferenceId(uuid.toString());
|
||||
attribute.setName(eAttribute.getName());
|
||||
if (eAttribute.getEType() instanceof EEnum) {
|
||||
attribute.setEnumType(true);
|
||||
attribute.setType(idResolver.resolveId(eAttribute.getEType()).toString());
|
||||
|
||||
if (eAttribute.getDefaultValue() != null && !EmfGraphBuilderUtils.isETypeDefaultValue((EDataType) eAttribute.getEType(), eAttribute.getDefaultValue())) {
|
||||
attribute.setHasDefaultValue(true);
|
||||
attribute.setDefaultValue(EmfGraphBuilderUtils.mapVals("-", idResolver.resolveId((EEnumLiteral) eAttribute.getDefaultValue())));
|
||||
} else {
|
||||
attribute.setHasDefaultValue(false);
|
||||
}
|
||||
} else if (eAttribute.getEType() instanceof EDataType) {
|
||||
attribute.setEnumType(false);
|
||||
attribute.setType(EmfGraphBuilderUtils.mapETypes((EDataType) eAttribute.getEType()));
|
||||
|
||||
if (eAttribute.getDefaultValue() != null && !EmfGraphBuilderUtils.isETypeDefaultValue((EDataType) eAttribute.getEType(), eAttribute.getDefaultValue())) {
|
||||
attribute.setHasDefaultValue(true);
|
||||
attribute.setDefaultValue(EmfGraphBuilderUtils.mapVals(eAttribute.getEAttributeType(), eAttribute.getDefaultValue()));
|
||||
} else {
|
||||
attribute.setHasDefaultValue(false);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected attribute type: " + eAttribute.getEType().toString());
|
||||
}
|
||||
|
||||
ClassElementModifiers modifiers = new ClassElementModifiers(!eAttribute.isChangeable(), eAttribute.isVolatile(), eAttribute.isTransient(), eAttribute.isUnsettable(), eAttribute.isDerived(), eAttribute.isUnique(), eAttribute.isOrdered(), false, false, eAttribute.isID());
|
||||
attribute.setModifiers(modifiers);
|
||||
|
||||
|
||||
return attribute;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package de.nexus.mmlcli.entities.model;
|
||||
|
||||
import de.nexus.mmlcli.serializer.EcoreIdResolver;
|
||||
import org.eclipse.emf.ecore.EReference;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Dataclass for class references
|
||||
*/
|
||||
public class CReferenceEntity {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private MultiplicityEntity multiplicity;
|
||||
private String type;
|
||||
private ClassElementModifiers modifiers;
|
||||
private boolean hasOpposite;
|
||||
private String opposite;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public MultiplicityEntity getMultiplicity() {
|
||||
return multiplicity;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public ClassElementModifiers getModifiers() {
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
public boolean isHasOpposite() {
|
||||
return hasOpposite;
|
||||
}
|
||||
|
||||
public String getOpposite() {
|
||||
return opposite;
|
||||
}
|
||||
|
||||
private void setReferenceId(String referenceId) {
|
||||
this.referenceId = referenceId;
|
||||
}
|
||||
|
||||
private void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private void setMultiplicity(MultiplicityEntity multiplicity) {
|
||||
this.multiplicity = multiplicity;
|
||||
}
|
||||
|
||||
private void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private void setModifiers(ClassElementModifiers modifiers) {
|
||||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
private void setHasOpposite(boolean hasOpposite) {
|
||||
this.hasOpposite = hasOpposite;
|
||||
}
|
||||
|
||||
private void setOpposite(String opposite) {
|
||||
this.opposite = opposite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("(%s -> %s)", name, type);
|
||||
}
|
||||
|
||||
public static CReferenceEntity fromEReference(EReference eRef, EcoreIdResolver idResolver) {
|
||||
CReferenceEntity refEntity = new CReferenceEntity();
|
||||
UUID uuid = idResolver.resolveId(eRef);
|
||||
refEntity.setReferenceId(uuid.toString());
|
||||
refEntity.setName(eRef.getName());
|
||||
refEntity.setType(idResolver.resolveId(eRef.getEType()).toString());
|
||||
MultiplicityEntity mult;
|
||||
if (eRef.getLowerBound() != 0) {
|
||||
if (eRef.getUpperBound() != 1) {
|
||||
if (eRef.getLowerBound() == 1 && eRef.getUpperBound() == -1) {
|
||||
mult = new MultiplicityEntity(false, true, false, false, false, 0, 0);
|
||||
} else {
|
||||
if (eRef.getUpperBound() == -1) {
|
||||
mult = new MultiplicityEntity(true, false, false, false, true, eRef.getLowerBound(), 0);
|
||||
} else {
|
||||
mult = new MultiplicityEntity(false, false, false, false, false, eRef.getLowerBound(), eRef.getUpperBound());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mult = new MultiplicityEntity(false, false, false, false, false, eRef.getLowerBound(), 0);
|
||||
}
|
||||
} else {
|
||||
if (eRef.getUpperBound() != 1) {
|
||||
if (eRef.getUpperBound() == -1) {
|
||||
mult = new MultiplicityEntity(false, false, true, false, false, 0, 0);
|
||||
} else {
|
||||
mult = new MultiplicityEntity(true, false, false, false, false, 0, eRef.getUpperBound());
|
||||
}
|
||||
} else {
|
||||
mult = new MultiplicityEntity(true, false, false, false, false, 0, 1);
|
||||
}
|
||||
}
|
||||
refEntity.setMultiplicity(mult);
|
||||
|
||||
|
||||
if (eRef.getEOpposite() != null) {
|
||||
refEntity.setHasOpposite(true);
|
||||
refEntity.setOpposite(idResolver.resolveId(eRef.getEOpposite()).toString());
|
||||
} else {
|
||||
refEntity.setHasOpposite(false);
|
||||
}
|
||||
|
||||
ClassElementModifiers modifiers = new ClassElementModifiers(!eRef.isChangeable(), eRef.isVolatile(), eRef.isTransient(), eRef.isUnsettable(), eRef.isDerived(), eRef.isUnique(), eRef.isOrdered(), eRef.isResolveProxies(), eRef.isContainment(), false);
|
||||
refEntity.setModifiers(modifiers);
|
||||
|
||||
return refEntity;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package de.nexus.mmlcli.entities.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Dataclass for class modifiers
|
||||
*/
|
||||
public class ClassElementModifiers {
|
||||
private boolean readonly;
|
||||
@SerializedName("volatile")
|
||||
private boolean _volatile;
|
||||
@SerializedName("transient")
|
||||
private boolean _transient;
|
||||
private boolean unsettable;
|
||||
private boolean derived;
|
||||
private boolean unique;
|
||||
private boolean ordered;
|
||||
private boolean resolve;
|
||||
private boolean containment;
|
||||
private boolean id;
|
||||
|
||||
public boolean isReadonly() {
|
||||
return readonly;
|
||||
}
|
||||
|
||||
public boolean isVolatile() {
|
||||
return _volatile;
|
||||
}
|
||||
|
||||
public boolean isTransient() {
|
||||
return _transient;
|
||||
}
|
||||
|
||||
public boolean isUnsettable() {
|
||||
return unsettable;
|
||||
}
|
||||
|
||||
public boolean isDerived() {
|
||||
return derived;
|
||||
}
|
||||
|
||||
public boolean isUnique() {
|
||||
return unique;
|
||||
}
|
||||
|
||||
public boolean isOrdered() {
|
||||
return ordered;
|
||||
}
|
||||
|
||||
public boolean isResolve() {
|
||||
return resolve;
|
||||
}
|
||||
|
||||
public boolean isContainment() {
|
||||
return containment;
|
||||
}
|
||||
|
||||
public boolean isId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public ClassElementModifiers(boolean readonly, boolean _volatile, boolean _transient, boolean unsettable, boolean derived, boolean unique, boolean ordered, boolean resolve, boolean containment, boolean id) {
|
||||
this.readonly = readonly;
|
||||
this._volatile = _volatile;
|
||||
this._transient = _transient;
|
||||
this.unsettable = unsettable;
|
||||
this.derived = derived;
|
||||
this.unique = unique;
|
||||
this.ordered = ordered;
|
||||
this.resolve = resolve;
|
||||
this.containment = containment;
|
||||
this.id = id;
|
||||
}
|
||||
}
|
62
src/main/java/de/nexus/mmlcli/entities/model/EnumEntity.java
Normal file
62
src/main/java/de/nexus/mmlcli/entities/model/EnumEntity.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
package de.nexus.mmlcli.entities.model;
|
||||
|
||||
import de.nexus.mmlcli.serializer.EcoreIdResolver;
|
||||
import org.eclipse.emf.ecore.EEnum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Dataclass for a enum
|
||||
*/
|
||||
public class EnumEntity<T> {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private String type;
|
||||
private final ArrayList<EnumEntryEntity<T>> entries = new ArrayList<>();
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public ArrayList<EnumEntryEntity<T>> getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
private void setReferenceId(String referenceId) {
|
||||
this.referenceId = referenceId;
|
||||
}
|
||||
|
||||
private void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ENUM<%s,%s>{%s}", name, type, entries.isEmpty() ? ""
|
||||
: entries.stream().map(EnumEntryEntity::toString).collect(Collectors.joining(",")));
|
||||
}
|
||||
|
||||
public static EnumEntity<Integer> fromEEnum(EEnum eenum, EcoreIdResolver idResolver) {
|
||||
EnumEntity<Integer> enumEntity = new EnumEntity<>();
|
||||
UUID uuid = idResolver.resolveId(eenum);
|
||||
enumEntity.setName(eenum.getName());
|
||||
enumEntity.setReferenceId(uuid.toString());
|
||||
enumEntity.setType("int"); // we assume type int since EMF does not allow other enum types
|
||||
enumEntity.entries.addAll(eenum.getELiterals().stream().map(lit -> EnumEntryEntity.fromEEnumLiteral(lit, idResolver)).toList());
|
||||
return enumEntity;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package de.nexus.mmlcli.entities.model;
|
||||
|
||||
import de.nexus.mmlcli.serializer.EcoreIdResolver;
|
||||
import org.eclipse.emf.ecore.EEnumLiteral;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Dataclass for a single enum entry
|
||||
*/
|
||||
public class EnumEntryEntity<T> {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private boolean hasDefaultValue;
|
||||
private T defaultValue;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isHasDefaultValue() {
|
||||
return hasDefaultValue;
|
||||
}
|
||||
|
||||
public T getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private void setReferenceId(String referenceId) {
|
||||
this.referenceId = referenceId;
|
||||
}
|
||||
|
||||
private void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private void setHasDefaultValue(boolean hasDefaultValue) {
|
||||
this.hasDefaultValue = hasDefaultValue;
|
||||
}
|
||||
|
||||
private void setDefaultValue(T defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%s|%b]", name, hasDefaultValue);
|
||||
}
|
||||
|
||||
public static EnumEntryEntity<Integer> fromEEnumLiteral(EEnumLiteral eLit, EcoreIdResolver idResolver) {
|
||||
EnumEntryEntity<Integer> enumEntry = new EnumEntryEntity<>();
|
||||
UUID uuid = idResolver.resolveId(eLit);
|
||||
enumEntry.setName(eLit.getName());
|
||||
enumEntry.setReferenceId(uuid.toString());
|
||||
enumEntry.setDefaultValue(eLit.getValue());
|
||||
enumEntry.setHasDefaultValue(true);
|
||||
return enumEntry;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package de.nexus.mmlcli.entities.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Dataclass for a complete metamodel
|
||||
*/
|
||||
public class ModelEntity {
|
||||
private final ArrayList<PackageEntity> packages = new ArrayList<>();
|
||||
|
||||
public ArrayList<PackageEntity> getPackages() {
|
||||
return packages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return packages.isEmpty() ? ""
|
||||
: "\n" + packages.stream().map(PackageEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
}
|
||||
|
||||
public static ModelEntity fromPackageEntity(PackageEntity pckgEntity) {
|
||||
ModelEntity model = new ModelEntity();
|
||||
model.packages.add(pckgEntity);
|
||||
return model;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package de.nexus.mmlcli.entities.model;
|
||||
|
||||
/**
|
||||
* Dataclass for reference multiplicities
|
||||
*/
|
||||
public class MultiplicityEntity {
|
||||
private boolean hasUpperBound;
|
||||
private boolean lowerIsN;
|
||||
private boolean lowerIsN0;
|
||||
private boolean upperIsN;
|
||||
private boolean upperIsN0;
|
||||
private int lower;
|
||||
private int upper;
|
||||
|
||||
public boolean isHasUpperBound() {
|
||||
return hasUpperBound;
|
||||
}
|
||||
|
||||
public boolean isLowerIsN() {
|
||||
return lowerIsN;
|
||||
}
|
||||
|
||||
public boolean isLowerIsN0() {
|
||||
return lowerIsN0;
|
||||
}
|
||||
|
||||
public boolean isUpperIsN() {
|
||||
return upperIsN;
|
||||
}
|
||||
|
||||
public boolean isUpperIsN0() {
|
||||
return upperIsN0;
|
||||
}
|
||||
|
||||
public int getLower() {
|
||||
return lower;
|
||||
}
|
||||
|
||||
public int getUpper() {
|
||||
return upper;
|
||||
}
|
||||
|
||||
public MultiplicityEntity(boolean hasUpperBound, boolean lowerIsN, boolean lowerIsN0, boolean upperIsN, boolean upperIsN0, int lower, int upper) {
|
||||
this.hasUpperBound = hasUpperBound;
|
||||
this.lowerIsN = lowerIsN;
|
||||
this.lowerIsN0 = lowerIsN0;
|
||||
this.upperIsN = upperIsN;
|
||||
this.upperIsN0 = upperIsN0;
|
||||
this.lower = lower;
|
||||
this.upper = upper;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package de.nexus.mmlcli.entities.model;
|
||||
|
||||
import de.nexus.mmlcli.serializer.EcoreIdResolver;
|
||||
import org.eclipse.emf.ecore.EClass;
|
||||
import org.eclipse.emf.ecore.EEnum;
|
||||
import org.eclipse.emf.ecore.EPackage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Dataclass for a package
|
||||
*/
|
||||
public class PackageEntity {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private final ArrayList<AbstractClassEntity> abstractClasses = new ArrayList<>();
|
||||
private final ArrayList<EnumEntity<?>> enums = new ArrayList<>();
|
||||
private final ArrayList<PackageEntity> subPackages = new ArrayList<>();
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ArrayList<AbstractClassEntity> getAbstractClasses() {
|
||||
return abstractClasses;
|
||||
}
|
||||
|
||||
public ArrayList<EnumEntity<?>> getEnums() {
|
||||
return enums;
|
||||
}
|
||||
|
||||
public ArrayList<PackageEntity> getSubPackages() {
|
||||
return subPackages;
|
||||
}
|
||||
|
||||
private void setReferenceId(String referenceId) {
|
||||
this.referenceId = referenceId;
|
||||
}
|
||||
|
||||
private void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String classesString = abstractClasses.isEmpty() ? ""
|
||||
: "\n" + abstractClasses.stream().map(AbstractClassEntity::toString).collect(Collectors.joining(","))
|
||||
+ "\n";
|
||||
String enumsString = enums.isEmpty() ? ""
|
||||
: "\n" + enums.stream().map(EnumEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
String subPackagesString = subPackages.isEmpty() ? ""
|
||||
: "\n" + subPackages.stream().map(PackageEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
return String.format("%s{%s %s %s}", name, classesString, enumsString, subPackagesString);
|
||||
}
|
||||
|
||||
public static PackageEntity fromEPackage(EPackage ePackage, EcoreIdResolver idResolver) {
|
||||
PackageEntity packageEntity = new PackageEntity();
|
||||
UUID uuid = idResolver.resolveId(ePackage);
|
||||
packageEntity.setName(ePackage.getName());
|
||||
packageEntity.setReferenceId(uuid.toString());
|
||||
packageEntity.subPackages.addAll(ePackage.getESubpackages().stream().map(subPackage -> fromEPackage(subPackage, idResolver)).toList());
|
||||
packageEntity.enums.addAll(ePackage.getEClassifiers().stream().filter(classifier -> classifier instanceof EEnum).map(eenum -> EnumEntity.fromEEnum((EEnum) eenum, idResolver)).toList());
|
||||
packageEntity.abstractClasses.addAll(ePackage.getEClassifiers().stream().filter(classifier -> classifier instanceof EClass).map(eclass -> AbstractClassEntity.fromEClass((EClass) eclass, idResolver)).toList());
|
||||
return packageEntity;
|
||||
}
|
||||
}
|
|
@ -2,8 +2,8 @@ package de.nexus.mmlcli.generator;
|
|||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import de.nexus.mmlcli.generator.entities.instance.GeneratorInstanceWrapper;
|
||||
import de.nexus.mmlcli.generator.entities.model.ModelEntity;
|
||||
import de.nexus.mmlcli.entities.instance.GeneratorInstanceWrapper;
|
||||
import de.nexus.mmlcli.entities.model.ModelEntity;
|
||||
|
||||
public class DeserializedDocument {
|
||||
private ModelEntity typegraph;
|
||||
|
@ -17,9 +17,24 @@ public class DeserializedDocument {
|
|||
return this.instancegraph;
|
||||
}
|
||||
|
||||
private void setTypegraph(ModelEntity typegraph) {
|
||||
this.typegraph = typegraph;
|
||||
}
|
||||
|
||||
private void setInstancegraph(GeneratorInstanceWrapper instancegraph) {
|
||||
this.instancegraph = instancegraph;
|
||||
}
|
||||
|
||||
public static DeserializedDocument build(String json) {
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
Gson gson = builder.create();
|
||||
return gson.fromJson(json, DeserializedDocument.class);
|
||||
}
|
||||
|
||||
public static DeserializedDocument build(ModelEntity model) {
|
||||
DeserializedDocument doc = new DeserializedDocument();
|
||||
doc.setTypegraph(model);
|
||||
doc.setInstancegraph(new GeneratorInstanceWrapper());
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,256 +1,242 @@
|
|||
package de.nexus.mmlcli.generator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import de.nexus.mmlcli.entities.model.*;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EAttribute;
|
||||
import org.eclipse.emf.ecore.EClass;
|
||||
import org.eclipse.emf.ecore.EEnum;
|
||||
import org.eclipse.emf.ecore.EEnumLiteral;
|
||||
import org.eclipse.emf.ecore.EPackage;
|
||||
import org.eclipse.emf.ecore.EReference;
|
||||
import org.eclipse.emf.ecore.EcoreFactory;
|
||||
import org.eclipse.emf.ecore.EcorePackage;
|
||||
import org.eclipse.emf.ecore.*;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet;
|
||||
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
|
||||
import de.nexus.mmlcli.generator.entities.model.AbstractClassEntity;
|
||||
import de.nexus.mmlcli.generator.entities.model.AttributeEntity;
|
||||
import de.nexus.mmlcli.generator.entities.model.CReferenceEntity;
|
||||
import de.nexus.mmlcli.generator.entities.model.EnumEntity;
|
||||
import de.nexus.mmlcli.generator.entities.model.EnumEntryEntity;
|
||||
import de.nexus.mmlcli.generator.entities.model.PackageEntity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* The EcoreTypeGraphBuilder contains all functions to generate a metamodel from a PackageEntity as an Ecore file.
|
||||
*/
|
||||
public class EcoreTypeGraphBuilder {
|
||||
private final EPackage ePackage;
|
||||
private final String exportPath;
|
||||
private final EcoreTypeResolver resolver;
|
||||
private final EPackage ePackage;
|
||||
private final String exportPath;
|
||||
private final EcoreTypeResolver resolver;
|
||||
|
||||
/**
|
||||
* Build an Ecore Package
|
||||
* @param pckg PackageEntity
|
||||
* @param targetUri Package URI
|
||||
* @param exportPath Path for the Ecore export
|
||||
* @param resolver EcoreTypeResolver
|
||||
*/
|
||||
public EcoreTypeGraphBuilder(PackageEntity pckg, String targetUri, String exportPath, EcoreTypeResolver resolver) {
|
||||
// create a new package
|
||||
this.ePackage = createPackage(pckg.getName(), pckg.getName(), targetUri);
|
||||
this.exportPath = exportPath;
|
||||
this.resolver = resolver;
|
||||
/**
|
||||
* Build an Ecore Package
|
||||
*
|
||||
* @param pckg PackageEntity
|
||||
* @param targetUri Package URI
|
||||
* @param exportPath Path for the Ecore export
|
||||
* @param resolver EcoreTypeResolver
|
||||
*/
|
||||
public EcoreTypeGraphBuilder(PackageEntity pckg, String targetUri, String exportPath, EcoreTypeResolver resolver) {
|
||||
// create a new package
|
||||
this.ePackage = createPackage(pckg.getName(), pckg.getName(), targetUri);
|
||||
this.exportPath = exportPath;
|
||||
this.resolver = resolver;
|
||||
|
||||
// store package in the resolver
|
||||
resolver.store(pckg.getReferenceId(), this.ePackage);
|
||||
// store package in the resolver
|
||||
resolver.store(pckg.getReferenceId(), this.ePackage);
|
||||
|
||||
// build subpackages
|
||||
pckg.getSubPackages().forEach(subPckg -> {
|
||||
EPackage subPackage = new EcoreTypeGraphBuilder(subPckg, targetUri, resolver).getAsSubpackage();
|
||||
this.ePackage.getESubpackages().add(subPackage);
|
||||
});
|
||||
|
||||
// build classes
|
||||
pckg.getAbstractClasses().forEach(ab -> {
|
||||
EClass clss = createEClass(ab);
|
||||
ab.getAttributes().forEach(attr -> addAttribute(clss, attr));
|
||||
ab.getReferences().forEach(cref -> addReference(clss, cref));
|
||||
});
|
||||
|
||||
// build enums
|
||||
pckg.getEnums().forEach(enm -> {
|
||||
EEnum enmm = createEEnum(enm);
|
||||
enm.getEntries().forEach(ee -> addEEnumLiteral(enmm, ee, enm));
|
||||
});
|
||||
}
|
||||
// build subpackages
|
||||
pckg.getSubPackages().forEach(subPckg -> {
|
||||
EPackage subPackage = new EcoreTypeGraphBuilder(subPckg, targetUri, resolver).getAsSubpackage();
|
||||
this.ePackage.getESubpackages().add(subPackage);
|
||||
});
|
||||
|
||||
/**
|
||||
* /**
|
||||
* Build an Ecore Package
|
||||
* <p>
|
||||
* Does not include an export path, since this is used for subpackages
|
||||
*
|
||||
* @param pckg PackageEntity
|
||||
* @param targetUri Package URI
|
||||
* @param resolver EcoreTypeResolver
|
||||
*/
|
||||
public EcoreTypeGraphBuilder(PackageEntity pckg, String targetUri, EcoreTypeResolver resolver) {
|
||||
this(pckg, targetUri, null, resolver);
|
||||
}
|
||||
// build classes
|
||||
pckg.getAbstractClasses().forEach(ab -> {
|
||||
EClass clss = createEClass(ab);
|
||||
ab.getAttributes().forEach(attr -> addAttribute(clss, attr));
|
||||
ab.getReferences().forEach(cref -> addReference(clss, cref));
|
||||
});
|
||||
|
||||
/**
|
||||
* Export EPackages to Ecore files
|
||||
*
|
||||
* @param graphBuilderList List of EcoreTypeGraphBuilders
|
||||
* @param resolver EcoreTypeResolver
|
||||
* @param resSet Common resource set
|
||||
*/
|
||||
public static void buildEcoreFile(List<EcoreTypeGraphBuilder> graphBuilderList, EcoreTypeResolver resolver,
|
||||
ResourceSet resSet) {
|
||||
// resolve all unresolved types
|
||||
resolver.resolveUnresovedTypes();
|
||||
// build enums
|
||||
pckg.getEnums().forEach(enm -> {
|
||||
EEnum enmm = createEEnum(enm);
|
||||
enm.getEntries().forEach(ee -> addEEnumLiteral(enmm, ee, enm));
|
||||
});
|
||||
}
|
||||
|
||||
for (EcoreTypeGraphBuilder builder : graphBuilderList) {
|
||||
builder.ePackage.eClass();
|
||||
}
|
||||
Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
|
||||
Map<String, Object> m = reg.getExtensionToFactoryMap();
|
||||
m.put(EcorePackage.eNAME, new EcoreResourceFactoryImpl());
|
||||
/**
|
||||
* /**
|
||||
* Build an Ecore Package
|
||||
* <p>
|
||||
* Does not include an export path, since this is used for subpackages
|
||||
*
|
||||
* @param pckg PackageEntity
|
||||
* @param targetUri Package URI
|
||||
* @param resolver EcoreTypeResolver
|
||||
*/
|
||||
public EcoreTypeGraphBuilder(PackageEntity pckg, String targetUri, EcoreTypeResolver resolver) {
|
||||
this(pckg, targetUri, null, resolver);
|
||||
}
|
||||
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
// create a resource
|
||||
try {
|
||||
for (EcoreTypeGraphBuilder builder : graphBuilderList) {
|
||||
Resource resource = resSet
|
||||
.createResource(URI.createFileURI(Objects.requireNonNull(builder.exportPath)));
|
||||
/*
|
||||
* add your EPackage as root, everything is hierarchical included in this first
|
||||
* node
|
||||
*/
|
||||
resource.getContents().add(builder.ePackage);
|
||||
resources.add(resource);
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
/**
|
||||
* Export EPackages to Ecore files
|
||||
*
|
||||
* @param graphBuilderList List of EcoreTypeGraphBuilders
|
||||
* @param resolver EcoreTypeResolver
|
||||
* @param resSet Common resource set
|
||||
*/
|
||||
public static void buildEcoreFile(List<EcoreTypeGraphBuilder> graphBuilderList, EcoreTypeResolver resolver,
|
||||
ResourceSet resSet) {
|
||||
// resolve all unresolved types
|
||||
resolver.resolveUnresovedTypes();
|
||||
|
||||
// now save the content.
|
||||
for (Resource resource : resources) {
|
||||
try {
|
||||
resource.save(Collections.EMPTY_MAP);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (EcoreTypeGraphBuilder builder : graphBuilderList) {
|
||||
builder.ePackage.eClass();
|
||||
}
|
||||
Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
|
||||
Map<String, Object> m = reg.getExtensionToFactoryMap();
|
||||
m.put(EcorePackage.eNAME, new EcoreResourceFactoryImpl());
|
||||
|
||||
public EPackage getAsSubpackage() {
|
||||
return this.ePackage;
|
||||
}
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
// create a resource
|
||||
try {
|
||||
for (EcoreTypeGraphBuilder builder : graphBuilderList) {
|
||||
Resource resource = resSet
|
||||
.createResource(URI.createFileURI(Objects.requireNonNull(builder.exportPath)));
|
||||
/*
|
||||
* add your EPackage as root, everything is hierarchical included in this first
|
||||
* node
|
||||
*/
|
||||
resource.getContents().add(builder.ePackage);
|
||||
resources.add(resource);
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addAttribute(EClass containerClass, AttributeEntity<?> attr) {
|
||||
final EAttribute attribute = EcoreFactory.eINSTANCE.createEAttribute();
|
||||
resolver.store(attr.getReferenceId(), attribute);
|
||||
// always add to container first
|
||||
containerClass.getEStructuralFeatures().add(attribute);
|
||||
attribute.setName(attr.getName());
|
||||
attribute.setLowerBound(0);
|
||||
attribute.setUpperBound(1);
|
||||
// now save the content.
|
||||
for (Resource resource : resources) {
|
||||
try {
|
||||
resource.save(Collections.EMPTY_MAP);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attr.isEnumType()) {
|
||||
resolver.resolveAttributeEnum(attribute, (AttributeEntity<String>) attr);
|
||||
} else {
|
||||
attribute.setEType(EmfGraphBuilderUtils.mapETypes(attr.getType()));
|
||||
public EPackage getAsSubpackage() {
|
||||
return this.ePackage;
|
||||
}
|
||||
|
||||
if (attr.isHasDefaultValue()) {
|
||||
Object val = EmfGraphBuilderUtils.mapVals(attr.getType(), attr.getDefaultValue());
|
||||
attribute.setDefaultValue(val);
|
||||
}
|
||||
}
|
||||
|
||||
attribute.setDerived(attr.getModifiers().isDerived());
|
||||
attribute.setOrdered(attr.getModifiers().isOrdered());
|
||||
attribute.setTransient(attr.getModifiers().isTransient());
|
||||
attribute.setUnique(attr.getModifiers().isUnique());
|
||||
attribute.setUnsettable(attr.getModifiers().isUnsettable());
|
||||
attribute.setVolatile(attr.getModifiers().isVolatile());
|
||||
attribute.setChangeable(!attr.getModifiers().isReadonly());
|
||||
attribute.setID(attr.getModifiers().isId());
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addAttribute(EClass containerClass, AttributeEntity<?> attr) {
|
||||
final EAttribute attribute = EcoreFactory.eINSTANCE.createEAttribute();
|
||||
resolver.store(attr.getReferenceId(), attribute);
|
||||
// always add to container first
|
||||
containerClass.getEStructuralFeatures().add(attribute);
|
||||
attribute.setName(attr.getName());
|
||||
attribute.setLowerBound(0);
|
||||
attribute.setUpperBound(1);
|
||||
|
||||
private void addReference(EClass containerClass, CReferenceEntity cref) {
|
||||
final EReference reference = EcoreFactory.eINSTANCE.createEReference();
|
||||
resolver.store(cref.getReferenceId(), reference);
|
||||
// always add to container first
|
||||
containerClass.getEStructuralFeatures().add(reference);
|
||||
reference.setName(cref.getName());
|
||||
if (attr.isEnumType()) {
|
||||
resolver.resolveAttributeEnum(attribute, (AttributeEntity<String>) attr);
|
||||
} else {
|
||||
attribute.setEType(EmfGraphBuilderUtils.mapETypes(attr.getType()));
|
||||
|
||||
resolver.resolveReference(reference, cref);
|
||||
if (attr.isHasDefaultValue()) {
|
||||
Object val = EmfGraphBuilderUtils.mapVals(attr.getType(), attr.getDefaultValue());
|
||||
attribute.setDefaultValue(val);
|
||||
}
|
||||
}
|
||||
|
||||
if (cref.getMultiplicity().isLowerIsN0()) {
|
||||
reference.setLowerBound(0);
|
||||
} else if (cref.getMultiplicity().isLowerIsN()) {
|
||||
reference.setLowerBound(1);
|
||||
} else {
|
||||
reference.setLowerBound(cref.getMultiplicity().getLower());
|
||||
}
|
||||
attribute.setDerived(attr.getModifiers().isDerived());
|
||||
attribute.setOrdered(attr.getModifiers().isOrdered());
|
||||
attribute.setTransient(attr.getModifiers().isTransient());
|
||||
attribute.setUnique(attr.getModifiers().isUnique());
|
||||
attribute.setUnsettable(attr.getModifiers().isUnsettable());
|
||||
attribute.setVolatile(attr.getModifiers().isVolatile());
|
||||
attribute.setChangeable(!attr.getModifiers().isReadonly());
|
||||
attribute.setID(attr.getModifiers().isId());
|
||||
}
|
||||
|
||||
if (cref.getMultiplicity().isHasUpperBound()) {
|
||||
if (cref.getMultiplicity().isUpperIsN0() || cref.getMultiplicity().isUpperIsN()) {
|
||||
reference.setUpperBound(-1);
|
||||
} else {
|
||||
reference.setUpperBound(cref.getMultiplicity().getUpper());
|
||||
}
|
||||
} else {
|
||||
if (cref.getMultiplicity().isLowerIsN0() || cref.getMultiplicity().isLowerIsN()) {
|
||||
reference.setUpperBound(-1);
|
||||
} else {
|
||||
reference.setUpperBound(1);
|
||||
}
|
||||
}
|
||||
private void addReference(EClass containerClass, CReferenceEntity cref) {
|
||||
final EReference reference = EcoreFactory.eINSTANCE.createEReference();
|
||||
resolver.store(cref.getReferenceId(), reference);
|
||||
// always add to container first
|
||||
containerClass.getEStructuralFeatures().add(reference);
|
||||
reference.setName(cref.getName());
|
||||
|
||||
reference.setDerived(cref.getModifiers().isDerived());
|
||||
reference.setChangeable(!cref.getModifiers().isReadonly());
|
||||
reference.setVolatile(cref.getModifiers().isVolatile());
|
||||
reference.setUnsettable(cref.getModifiers().isUnsettable());
|
||||
reference.setUnique(cref.getModifiers().isUnique());
|
||||
reference.setTransient(cref.getModifiers().isTransient());
|
||||
reference.setOrdered(cref.getModifiers().isOrdered());
|
||||
reference.setResolveProxies(cref.getModifiers().isResolve());
|
||||
}
|
||||
resolver.resolveReference(reference, cref);
|
||||
|
||||
private EPackage createPackage(final String name, final String prefix, final String uri) {
|
||||
final EPackage epackage = EcoreFactory.eINSTANCE.createEPackage();
|
||||
epackage.setName(name);
|
||||
epackage.setNsPrefix(prefix);
|
||||
epackage.setNsURI(uri);
|
||||
return epackage;
|
||||
if (cref.getMultiplicity().isLowerIsN0()) {
|
||||
reference.setLowerBound(0);
|
||||
} else if (cref.getMultiplicity().isLowerIsN()) {
|
||||
reference.setLowerBound(1);
|
||||
} else {
|
||||
reference.setLowerBound(cref.getMultiplicity().getLower());
|
||||
}
|
||||
|
||||
}
|
||||
if (cref.getMultiplicity().isHasUpperBound()) {
|
||||
if (cref.getMultiplicity().isUpperIsN0() || cref.getMultiplicity().isUpperIsN()) {
|
||||
reference.setUpperBound(-1);
|
||||
} else {
|
||||
reference.setUpperBound(cref.getMultiplicity().getUpper());
|
||||
}
|
||||
} else {
|
||||
if (cref.getMultiplicity().isLowerIsN0() || cref.getMultiplicity().isLowerIsN()) {
|
||||
reference.setUpperBound(-1);
|
||||
} else {
|
||||
reference.setUpperBound(1);
|
||||
}
|
||||
}
|
||||
|
||||
private EClass createEClass(final AbstractClassEntity ace) {
|
||||
final EClass eClass = EcoreFactory.eINSTANCE.createEClass();
|
||||
resolver.store(ace.getReferenceId(), eClass);
|
||||
eClass.setName(ace.getName());
|
||||
eClass.setAbstract(ace.isAbstract());
|
||||
eClass.setInterface(ace.isInterface());
|
||||
if (!ace.getExtendsIds().isEmpty() || !ace.getImplementsIds().isEmpty()) {
|
||||
List<String> allSupertypes = Stream.concat(ace.getExtendsIds().stream(), ace.getImplementsIds().stream())
|
||||
.toList();
|
||||
resolver.resolveSupertypes(eClass, allSupertypes);
|
||||
}
|
||||
this.ePackage.getEClassifiers().add(eClass);
|
||||
return eClass;
|
||||
}
|
||||
reference.setDerived(cref.getModifiers().isDerived());
|
||||
reference.setChangeable(!cref.getModifiers().isReadonly());
|
||||
reference.setVolatile(cref.getModifiers().isVolatile());
|
||||
reference.setUnsettable(cref.getModifiers().isUnsettable());
|
||||
reference.setUnique(cref.getModifiers().isUnique());
|
||||
reference.setTransient(cref.getModifiers().isTransient());
|
||||
reference.setOrdered(cref.getModifiers().isOrdered());
|
||||
reference.setResolveProxies(cref.getModifiers().isResolve());
|
||||
reference.setContainment(cref.getModifiers().isContainment());
|
||||
}
|
||||
|
||||
private EEnum createEEnum(final EnumEntity<?> ee) {
|
||||
final EEnum eenum = EcoreFactory.eINSTANCE.createEEnum();
|
||||
resolver.store(ee.getReferenceId(), eenum);
|
||||
eenum.setName(ee.getName());
|
||||
this.ePackage.getEClassifiers().add(eenum);
|
||||
return eenum;
|
||||
}
|
||||
private EPackage createPackage(final String name, final String prefix, final String uri) {
|
||||
final EPackage epackage = EcoreFactory.eINSTANCE.createEPackage();
|
||||
epackage.setName(name);
|
||||
epackage.setNsPrefix(prefix);
|
||||
epackage.setNsURI(uri);
|
||||
return epackage;
|
||||
|
||||
private EEnumLiteral addEEnumLiteral(final EEnum ee, final EnumEntryEntity<?> eee, final EnumEntity<?> eentity) {
|
||||
final EEnumLiteral eenumLit = EcoreFactory.eINSTANCE.createEEnumLiteral();
|
||||
resolver.store(eee.getReferenceId(), eenumLit);
|
||||
eenumLit.setName(eee.getName());
|
||||
if (eee.isHasDefaultValue()) {
|
||||
if (eentity.getType().equals("int") || eentity.getType().equals("float")
|
||||
|| eentity.getType().equals("double")) {
|
||||
int val = Double.valueOf(eee.getDefaultValue().toString()).intValue();
|
||||
eenumLit.setValue(val);
|
||||
}
|
||||
}
|
||||
ee.getELiterals().add(eenumLit);
|
||||
return eenumLit;
|
||||
}
|
||||
}
|
||||
|
||||
private EClass createEClass(final AbstractClassEntity ace) {
|
||||
final EClass eClass = EcoreFactory.eINSTANCE.createEClass();
|
||||
resolver.store(ace.getReferenceId(), eClass);
|
||||
eClass.setName(ace.getName());
|
||||
eClass.setAbstract(ace.isAbstract());
|
||||
eClass.setInterface(ace.isInterface());
|
||||
if (!ace.getExtendsIds().isEmpty() || !ace.getImplementsIds().isEmpty()) {
|
||||
List<String> allSupertypes = Stream.concat(ace.getExtendsIds().stream(), ace.getImplementsIds().stream())
|
||||
.toList();
|
||||
resolver.resolveSupertypes(eClass, allSupertypes);
|
||||
}
|
||||
this.ePackage.getEClassifiers().add(eClass);
|
||||
return eClass;
|
||||
}
|
||||
|
||||
private EEnum createEEnum(final EnumEntity<?> ee) {
|
||||
final EEnum eenum = EcoreFactory.eINSTANCE.createEEnum();
|
||||
resolver.store(ee.getReferenceId(), eenum);
|
||||
eenum.setName(ee.getName());
|
||||
this.ePackage.getEClassifiers().add(eenum);
|
||||
return eenum;
|
||||
}
|
||||
|
||||
private EEnumLiteral addEEnumLiteral(final EEnum ee, final EnumEntryEntity<?> eee, final EnumEntity<?> eentity) {
|
||||
final EEnumLiteral eenumLit = EcoreFactory.eINSTANCE.createEEnumLiteral();
|
||||
resolver.store(eee.getReferenceId(), eenumLit);
|
||||
eenumLit.setName(eee.getName());
|
||||
if (eee.isHasDefaultValue()) {
|
||||
if (eentity.getType().equals("int") || eentity.getType().equals("float")
|
||||
|| eentity.getType().equals("double")) {
|
||||
int val = Double.valueOf(eee.getDefaultValue().toString()).intValue();
|
||||
eenumLit.setValue(val);
|
||||
}
|
||||
}
|
||||
ee.getELiterals().add(eenumLit);
|
||||
return eenumLit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,208 +1,201 @@
|
|||
package de.nexus.mmlcli.generator;
|
||||
|
||||
import de.nexus.mmlcli.entities.instance.AttributeEntry;
|
||||
import de.nexus.mmlcli.entities.instance.ObjectInstance;
|
||||
import de.nexus.mmlcli.entities.instance.ReferenceEntry;
|
||||
import de.nexus.mmlcli.entities.model.AttributeEntity;
|
||||
import de.nexus.mmlcli.entities.model.CReferenceEntity;
|
||||
import org.eclipse.emf.common.util.EList;
|
||||
import org.eclipse.emf.ecore.*;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.common.util.EList;
|
||||
import org.eclipse.emf.ecore.EAttribute;
|
||||
import org.eclipse.emf.ecore.EClass;
|
||||
import org.eclipse.emf.ecore.EClassifier;
|
||||
import org.eclipse.emf.ecore.EEnumLiteral;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EPackage;
|
||||
import org.eclipse.emf.ecore.EReference;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
|
||||
import de.nexus.mmlcli.generator.entities.instance.AttributeEntry;
|
||||
import de.nexus.mmlcli.generator.entities.instance.ObjectInstance;
|
||||
import de.nexus.mmlcli.generator.entities.instance.ReferenceEntry;
|
||||
import de.nexus.mmlcli.generator.entities.model.AttributeEntity;
|
||||
import de.nexus.mmlcli.generator.entities.model.CReferenceEntity;
|
||||
|
||||
/**
|
||||
* The EcoreTypeResolver helps to resolve and link references in metamodels. MML replaces
|
||||
* all references with unique ids. To be independent of the execution order when constructing
|
||||
* the metamodel, the TypeResolver tries to resolve a reference using the id and stores the
|
||||
* missing reference otherwise. When exporting the metamodel (and thus after successful complete
|
||||
* The EcoreTypeResolver helps to resolve and link references in metamodels. MML replaces
|
||||
* all references with unique ids. To be independent of the execution order when constructing
|
||||
* the metamodel, the TypeResolver tries to resolve a reference using the id and stores the
|
||||
* missing reference otherwise. When exporting the metamodel (and thus after successful complete
|
||||
* construction) all missing references are finally resolved.
|
||||
*/
|
||||
public class EcoreTypeResolver {
|
||||
private final Map<String, EClassifier> classifiers = new HashMap<>();
|
||||
private final Map<String, EReference> references = new HashMap<>();
|
||||
private final Map<String, EAttribute> attributes = new HashMap<>();
|
||||
private final Map<String, EPackage> packages = new HashMap<>();
|
||||
private final Map<String, EEnumLiteral> elits = new HashMap<>();
|
||||
private final Map<EReference, String> unresolvedReferenceTypes = new HashMap<>();
|
||||
private final Map<EReference, String> unresolvedReferenceOpposites = new HashMap<>();
|
||||
private final Map<EAttribute, String> unresolvedAttributeEnumTypes = new HashMap<>();
|
||||
private final Map<EAttribute, String> unresolvedAttributeEnumValues = new HashMap<>();
|
||||
private final Map<EClass, List<String>> unresolvedSupertypes = new HashMap<>();
|
||||
private final Map<String, EClassifier> classifiers = new HashMap<>();
|
||||
private final Map<String, EReference> references = new HashMap<>();
|
||||
private final Map<String, EAttribute> attributes = new HashMap<>();
|
||||
private final Map<String, EPackage> packages = new HashMap<>();
|
||||
private final Map<String, EEnumLiteral> elits = new HashMap<>();
|
||||
private final Map<EReference, String> unresolvedReferenceTypes = new HashMap<>();
|
||||
private final Map<EReference, String> unresolvedReferenceOpposites = new HashMap<>();
|
||||
private final Map<EAttribute, String> unresolvedAttributeEnumTypes = new HashMap<>();
|
||||
private final Map<EAttribute, String> unresolvedAttributeEnumValues = new HashMap<>();
|
||||
private final Map<EClass, List<String>> unresolvedSupertypes = new HashMap<>();
|
||||
|
||||
public void store(String classId, EClassifier classifier) {
|
||||
this.classifiers.put(classId, classifier);
|
||||
}
|
||||
public void store(String classId, EClassifier classifier) {
|
||||
this.classifiers.put(classId, classifier);
|
||||
}
|
||||
|
||||
public void store(String refId, EReference reference) {
|
||||
this.references.put(refId, reference);
|
||||
}
|
||||
public void store(String refId, EReference reference) {
|
||||
this.references.put(refId, reference);
|
||||
}
|
||||
|
||||
public void store(String attrId, EAttribute attibute) {
|
||||
this.attributes.put(attrId, attibute);
|
||||
}
|
||||
public void store(String attrId, EAttribute attibute) {
|
||||
this.attributes.put(attrId, attibute);
|
||||
}
|
||||
|
||||
public void store(String pckgId, EPackage packagee) {
|
||||
this.packages.put(pckgId, packagee);
|
||||
}
|
||||
public void store(String pckgId, EPackage packagee) {
|
||||
this.packages.put(pckgId, packagee);
|
||||
}
|
||||
|
||||
public void store(String elitId, EEnumLiteral enumLiteral) {
|
||||
this.elits.put(elitId, enumLiteral);
|
||||
}
|
||||
public void store(String elitId, EEnumLiteral enumLiteral) {
|
||||
this.elits.put(elitId, enumLiteral);
|
||||
}
|
||||
|
||||
public void dumpResolverStorage() {
|
||||
System.out.println("================[ERROR]================");
|
||||
System.out.println("==========[EcoreTypeResolver]==========");
|
||||
System.out.println("### Packages");
|
||||
for (String key : this.packages.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("### Classifiers");
|
||||
for (String key : this.classifiers.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("### Attributes");
|
||||
for (String key : this.attributes.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("### References");
|
||||
for (String key : this.references.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("### ELits");
|
||||
for (String key : this.elits.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("================[ERROR]================");
|
||||
}
|
||||
public void dumpResolverStorage() {
|
||||
System.out.println("================[ERROR]================");
|
||||
System.out.println("==========[EcoreTypeResolver]==========");
|
||||
System.out.println("### Packages");
|
||||
for (String key : this.packages.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("### Classifiers");
|
||||
for (String key : this.classifiers.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("### Attributes");
|
||||
for (String key : this.attributes.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("### References");
|
||||
for (String key : this.references.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("### ELits");
|
||||
for (String key : this.elits.keySet()) {
|
||||
System.out.printf("\t- %s%n", key);
|
||||
}
|
||||
System.out.println("================[ERROR]================");
|
||||
}
|
||||
|
||||
public void resolveSupertypes(EClass clazz, List<String> classIds) {
|
||||
this.unresolvedSupertypes.put(clazz, classIds);
|
||||
}
|
||||
public void resolveSupertypes(EClass clazz, List<String> classIds) {
|
||||
this.unresolvedSupertypes.put(clazz, classIds);
|
||||
}
|
||||
|
||||
public void resolveReference(EReference ref, CReferenceEntity refEntity) {
|
||||
String typeId = refEntity.getType();
|
||||
if (classifiers.containsKey(typeId)) {
|
||||
ref.setEType(classifiers.get(typeId));
|
||||
} else {
|
||||
unresolvedReferenceTypes.put(ref, typeId);
|
||||
}
|
||||
public void resolveReference(EReference ref, CReferenceEntity refEntity) {
|
||||
String typeId = refEntity.getType();
|
||||
if (classifiers.containsKey(typeId)) {
|
||||
ref.setEType(classifiers.get(typeId));
|
||||
} else {
|
||||
unresolvedReferenceTypes.put(ref, typeId);
|
||||
}
|
||||
|
||||
if (refEntity.isHasOpposite()) {
|
||||
String oppositeId = refEntity.getOpposite();
|
||||
if (classifiers.containsKey(oppositeId)) {
|
||||
ref.setEType(classifiers.get(oppositeId));
|
||||
} else {
|
||||
unresolvedReferenceOpposites.put(ref, oppositeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (refEntity.isHasOpposite()) {
|
||||
String oppositeId = refEntity.getOpposite();
|
||||
if (classifiers.containsKey(oppositeId)) {
|
||||
ref.setEType(classifiers.get(oppositeId));
|
||||
} else {
|
||||
unresolvedReferenceOpposites.put(ref, oppositeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void resolveAttributeEnum(EAttribute attr, AttributeEntity<String> attrEntity) {
|
||||
if (!attrEntity.isEnumType()) {
|
||||
return;
|
||||
}
|
||||
public void resolveAttributeEnum(EAttribute attr, AttributeEntity<String> attrEntity) {
|
||||
if (!attrEntity.isEnumType()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String typeId = attrEntity.getType();
|
||||
if (classifiers.containsKey(typeId)) {
|
||||
attr.setEType(classifiers.get(typeId));
|
||||
} else {
|
||||
unresolvedAttributeEnumTypes.put(attr, typeId);
|
||||
}
|
||||
String typeId = attrEntity.getType();
|
||||
if (classifiers.containsKey(typeId)) {
|
||||
attr.setEType(classifiers.get(typeId));
|
||||
} else {
|
||||
unresolvedAttributeEnumTypes.put(attr, typeId);
|
||||
}
|
||||
|
||||
if (attrEntity.isHasDefaultValue()) {
|
||||
String valueId = attrEntity.getDefaultValue();
|
||||
if (elits.containsKey(valueId)) {
|
||||
attr.setDefaultValue(elits.get(valueId).getName());
|
||||
} else {
|
||||
unresolvedAttributeEnumValues.put(attr, valueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (attrEntity.isHasDefaultValue()) {
|
||||
String valueId = attrEntity.getDefaultValue();
|
||||
if (elits.containsKey(valueId)) {
|
||||
attr.setDefaultValue(elits.get(valueId).getName());
|
||||
} else {
|
||||
unresolvedAttributeEnumValues.put(attr, valueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EObject resolveObjectInstance(ObjectInstance objInst) {
|
||||
EClass clazz = (EClass) this.classifiers.get(objInst.getReferenceTypeId());
|
||||
return EcoreUtil.create(clazz);
|
||||
}
|
||||
public EObject resolveObjectInstance(ObjectInstance objInst) {
|
||||
EClass clazz = (EClass) this.classifiers.get(objInst.getReferenceTypeId());
|
||||
return EcoreUtil.create(clazz);
|
||||
}
|
||||
|
||||
public EAttribute resolveAttribute(AttributeEntry<?> attr) {
|
||||
return this.attributes.get(attr.getTypeId());
|
||||
}
|
||||
public EAttribute resolveAttribute(AttributeEntry<?> attr) {
|
||||
return this.attributes.get(attr.getTypeId());
|
||||
}
|
||||
|
||||
public EReference resolveReference(ReferenceEntry ref) {
|
||||
return this.references.get(ref.getTypeId());
|
||||
}
|
||||
public EReference resolveReference(ReferenceEntry ref) {
|
||||
return this.references.get(ref.getTypeId());
|
||||
}
|
||||
|
||||
public EEnumLiteral resolveAttributeEnum(AttributeEntry<?> attr) {
|
||||
return this.elits.get(attr.getValue());
|
||||
}
|
||||
public EEnumLiteral resolveAttributeEnum(AttributeEntry<?> attr) {
|
||||
return this.elits.get(attr.getValue());
|
||||
}
|
||||
|
||||
public void resolveUnresovedTypes() {
|
||||
for (Map.Entry<EReference, String> refEntry : this.unresolvedReferenceTypes.entrySet()) {
|
||||
EReference ref = refEntry.getKey();
|
||||
String typeId = refEntry.getValue();
|
||||
if (classifiers.containsKey(typeId)) {
|
||||
ref.setEType(classifiers.get(typeId));
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve classId: " + typeId);
|
||||
}
|
||||
}
|
||||
public void resolveUnresovedTypes() {
|
||||
for (Map.Entry<EReference, String> refEntry : this.unresolvedReferenceTypes.entrySet()) {
|
||||
EReference ref = refEntry.getKey();
|
||||
String typeId = refEntry.getValue();
|
||||
if (classifiers.containsKey(typeId)) {
|
||||
ref.setEType(classifiers.get(typeId));
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve classId: " + typeId);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<EReference, String> refEntry : this.unresolvedReferenceOpposites.entrySet()) {
|
||||
EReference ref = refEntry.getKey();
|
||||
String typeId = refEntry.getValue();
|
||||
if (references.containsKey(typeId)) {
|
||||
ref.setEOpposite(references.get(typeId));
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve referenceId: " + typeId);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<EReference, String> refEntry : this.unresolvedReferenceOpposites.entrySet()) {
|
||||
EReference ref = refEntry.getKey();
|
||||
String typeId = refEntry.getValue();
|
||||
if (references.containsKey(typeId)) {
|
||||
ref.setEOpposite(references.get(typeId));
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve referenceId: " + typeId);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<EAttribute, String> attrEntry : this.unresolvedAttributeEnumTypes.entrySet()) {
|
||||
EAttribute attr = attrEntry.getKey();
|
||||
String typeId = attrEntry.getValue();
|
||||
if (classifiers.containsKey(typeId)) {
|
||||
attr.setEType(classifiers.get(typeId));
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve enumId: " + typeId);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<EAttribute, String> attrEntry : this.unresolvedAttributeEnumTypes.entrySet()) {
|
||||
EAttribute attr = attrEntry.getKey();
|
||||
String typeId = attrEntry.getValue();
|
||||
if (classifiers.containsKey(typeId)) {
|
||||
attr.setEType(classifiers.get(typeId));
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve enumId: " + typeId);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<EAttribute, String> attrEntry : this.unresolvedAttributeEnumValues.entrySet()) {
|
||||
EAttribute attr = attrEntry.getKey();
|
||||
String typeId = attrEntry.getValue();
|
||||
if (elits.containsKey(typeId)) {
|
||||
attr.setDefaultValue(elits.get(typeId).getName());
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve enum valueId: " + typeId);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<EAttribute, String> attrEntry : this.unresolvedAttributeEnumValues.entrySet()) {
|
||||
EAttribute attr = attrEntry.getKey();
|
||||
String typeId = attrEntry.getValue();
|
||||
if (elits.containsKey(typeId)) {
|
||||
attr.setDefaultValue(elits.get(typeId).getName());
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve enum valueId: " + typeId);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<EClass, List<String>> supertypeEntry : this.unresolvedSupertypes.entrySet()) {
|
||||
EClass clazz = supertypeEntry.getKey();
|
||||
List<String> supertypeIds = supertypeEntry.getValue();
|
||||
EList<EClass> superTypes = clazz.getESuperTypes();
|
||||
for (String supertypeId : supertypeIds) {
|
||||
if (classifiers.containsKey(supertypeId)) {
|
||||
superTypes.add((EClass) classifiers.get(supertypeId));
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve supertype classId: " + supertypeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<EClass, List<String>> supertypeEntry : this.unresolvedSupertypes.entrySet()) {
|
||||
EClass clazz = supertypeEntry.getKey();
|
||||
List<String> supertypeIds = supertypeEntry.getValue();
|
||||
EList<EClass> superTypes = clazz.getESuperTypes();
|
||||
for (String supertypeId : supertypeIds) {
|
||||
if (classifiers.containsKey(supertypeId)) {
|
||||
superTypes.add((EClass) classifiers.get(supertypeId));
|
||||
} else {
|
||||
dumpResolverStorage();
|
||||
throw new IllegalArgumentException("Could not resolve supertype classId: " + supertypeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,30 +4,44 @@ import org.eclipse.emf.ecore.EDataType;
|
|||
import org.eclipse.emf.ecore.EcorePackage;
|
||||
|
||||
public class EmfGraphBuilderUtils {
|
||||
public static EDataType mapETypes(String mmlType) {
|
||||
return switch (mmlType) {
|
||||
case "string" -> EcorePackage.Literals.ESTRING;
|
||||
case "float" -> EcorePackage.Literals.EFLOAT;
|
||||
case "double" -> EcorePackage.Literals.EDOUBLE;
|
||||
case "int" -> EcorePackage.Literals.EINT;
|
||||
case "boolean" -> EcorePackage.Literals.EBOOLEAN;
|
||||
default -> EcorePackage.Literals.ESTRING;
|
||||
};
|
||||
}
|
||||
|
||||
public static <T,R> R mapVals(String mmlType, T value) {
|
||||
return mapVals(mapETypes(mmlType), value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T,R> R mapVals(EDataType type, T value) {
|
||||
return switch (type.getClassifierID()) {
|
||||
case EcorePackage.ESTRING -> (R) value;
|
||||
case EcorePackage.EFLOAT -> (R) Float.valueOf(value.toString());
|
||||
case EcorePackage.EDOUBLE -> (R) Double.valueOf(value.toString());
|
||||
case EcorePackage.EINT -> (R) Integer.valueOf(Double.valueOf(value.toString()).intValue());
|
||||
case EcorePackage.EBOOLEAN -> (R) Boolean.valueOf(value.toString());
|
||||
default -> (R) value.toString();
|
||||
};
|
||||
}
|
||||
public static EDataType mapETypes(String mmlType) {
|
||||
return switch (mmlType) {
|
||||
case "string" -> EcorePackage.Literals.ESTRING;
|
||||
case "float" -> EcorePackage.Literals.EFLOAT;
|
||||
case "double" -> EcorePackage.Literals.EDOUBLE;
|
||||
case "int" -> EcorePackage.Literals.EINT;
|
||||
case "boolean" -> EcorePackage.Literals.EBOOLEAN;
|
||||
default -> EcorePackage.Literals.ESTRING;
|
||||
};
|
||||
}
|
||||
|
||||
public static String mapETypes(EDataType dataType) {
|
||||
return switch (dataType.getClassifierID()) {
|
||||
case EcorePackage.EFLOAT -> "float";
|
||||
case EcorePackage.EDOUBLE -> "double";
|
||||
case EcorePackage.EINT -> "int";
|
||||
case EcorePackage.EBOOLEAN -> "boolean";
|
||||
default -> "string";
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> boolean isETypeDefaultValue(EDataType type, T value) {
|
||||
return type.getDefaultValue().equals(value);
|
||||
}
|
||||
|
||||
public static <T, R> R mapVals(String mmlType, T value) {
|
||||
return mapVals(mapETypes(mmlType), value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T, R> R mapVals(EDataType type, T value) {
|
||||
return switch (type.getClassifierID()) {
|
||||
case EcorePackage.ESTRING -> (R) value;
|
||||
case EcorePackage.EFLOAT -> (R) Float.valueOf(value.toString());
|
||||
case EcorePackage.EDOUBLE -> (R) Double.valueOf(value.toString());
|
||||
case EcorePackage.EINT -> (R) Integer.valueOf(Double.valueOf(value.toString()).intValue());
|
||||
case EcorePackage.EBOOLEAN -> (R) Boolean.valueOf(value.toString());
|
||||
default -> (R) value.toString();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package de.nexus.mmlcli.generator;
|
||||
|
||||
import de.nexus.mmlcli.generator.entities.instance.GeneratorInstance;
|
||||
import de.nexus.mmlcli.generator.entities.model.ModelEntity;
|
||||
import de.nexus.mmlcli.generator.entities.model.PackageEntity;
|
||||
import de.nexus.mmlcli.entities.instance.GeneratorInstance;
|
||||
import de.nexus.mmlcli.entities.model.ModelEntity;
|
||||
import de.nexus.mmlcli.entities.model.PackageEntity;
|
||||
import de.nexus.mmlcli.generator.diagnostic.DocumentDiagnostic;
|
||||
import de.nexus.mmlcli.generator.diagnostic.DocumentPoint;
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet;
|
||||
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
|
||||
|
||||
|
@ -13,6 +15,7 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* The EmfResourceBuilder coordinates the export of metamodels and instance graphs.
|
||||
|
@ -36,9 +39,20 @@ public class EmfResourceBuilder {
|
|||
} catch (IOException ex) {
|
||||
System.out.println("[MODEL PATH BUILDER] Could not create models directory: " + modelsDir);
|
||||
}
|
||||
ArrayList<DocumentDiagnostic> seriousDiagnostics = doc.getDiagnostics().stream().filter(x -> x.getSeverity() == 1).collect(Collectors.toCollection(ArrayList::new));
|
||||
if (!seriousDiagnostics.isEmpty()) {
|
||||
System.err.printf("[DOCUMENT SKIP] Skipping %s due to the following errors%n", doc.uri.toString());
|
||||
System.err.flush();
|
||||
seriousDiagnostics.forEach(diag -> {
|
||||
DocumentPoint startPoint = diag.getRange().getStart();
|
||||
System.err.printf("%s (%s) starting in line %d:%d%n", diag.getMessage(), diag.getCode(), startPoint.getLine(), startPoint.getCharacter());
|
||||
System.err.flush();
|
||||
});
|
||||
continue;
|
||||
}
|
||||
ModelEntity model = doc.getParsedGenerator().getTypegraph();
|
||||
for (PackageEntity pckgEntity : model.getPackages()) {
|
||||
String fileName = Path.of(doc.uri).getFileName().toString().replace(".mml", "") + "_"
|
||||
String fileName = Path.of(doc.uri).getFileName().toString().replace(".mml", "").replace(".ecore", "") + "_"
|
||||
+ pckgEntity.getName() + ".ecore";
|
||||
Path filePath = Paths.get(modelsDir.toString(), fileName);
|
||||
String packageUri = String.format("platform:/resource/%s/model/%s", projectName, fileName);
|
||||
|
|
|
@ -2,20 +2,39 @@ package de.nexus.mmlcli.generator;
|
|||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import de.nexus.mmlcli.generator.diagnostic.DocumentDiagnostic;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SerializedDocument {
|
||||
URI uri;
|
||||
String content;
|
||||
ArrayList<DocumentDiagnostic> diagnostics = new ArrayList<>();
|
||||
|
||||
public DeserializedDocument getParsedGenerator(){
|
||||
public DeserializedDocument getParsedGenerator() {
|
||||
return DeserializedDocument.build(this.content);
|
||||
}
|
||||
|
||||
public SerializedDocument(URI uri, DeserializedDocument dDoc) {
|
||||
Gson gson = new Gson();
|
||||
this.content = gson.toJson(dDoc);
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String serialize() {
|
||||
Gson gson = new Gson();
|
||||
return gson.toJson(List.of(this));
|
||||
}
|
||||
|
||||
public static SerializedDocument[] deserialize(String json) {
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
Gson gson = builder.create();
|
||||
return gson.fromJson(json, SerializedDocument[].class);
|
||||
}
|
||||
|
||||
public ArrayList<DocumentDiagnostic> getDiagnostics() {
|
||||
return diagnostics;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
package de.nexus.mmlcli.generator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import de.nexus.mmlcli.entities.instance.AttributeEntry;
|
||||
import de.nexus.mmlcli.entities.instance.ObjectInstance;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EAttribute;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
|
@ -14,77 +10,77 @@ import org.eclipse.emf.ecore.resource.ResourceSet;
|
|||
import org.eclipse.emf.ecore.xmi.XMIResource;
|
||||
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
|
||||
|
||||
import de.nexus.mmlcli.generator.entities.instance.AttributeEntry;
|
||||
import de.nexus.mmlcli.generator.entities.instance.ObjectInstance;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The XMIInstanceGraphBuilder contains all functions to generate a model instance from a ObjectInstance as an XMI file.
|
||||
*/
|
||||
public class XMIInstanceGraphBuilder {
|
||||
private final ArrayList<EObject> objects = new ArrayList<>();
|
||||
private final String exportPath;
|
||||
private final ArrayList<EObject> objects = new ArrayList<>();
|
||||
private final String exportPath;
|
||||
|
||||
public XMIInstanceGraphBuilder(List<ObjectInstance> objInsts, String exportPath, EcoreTypeResolver typeResolver,
|
||||
XMIInstanceResolver instResolver) {
|
||||
objInsts.forEach(objInst -> {
|
||||
EObject obj = typeResolver.resolveObjectInstance(objInst);
|
||||
for (AttributeEntry<?> attr : objInst.getAttributes()) {
|
||||
setAttribute(obj, attr, typeResolver, instResolver);
|
||||
}
|
||||
instResolver.registerReference(objInst.getReferenceId(), objInst.getReferences());
|
||||
|
||||
this.objects.add(obj);
|
||||
instResolver.store(objInst.getReferenceId(), obj);
|
||||
});
|
||||
|
||||
this.exportPath = exportPath;
|
||||
}
|
||||
public XMIInstanceGraphBuilder(List<ObjectInstance> objInsts, String exportPath, EcoreTypeResolver typeResolver,
|
||||
XMIInstanceResolver instResolver) {
|
||||
objInsts.forEach(objInst -> {
|
||||
EObject obj = typeResolver.resolveObjectInstance(objInst);
|
||||
for (AttributeEntry<?> attr : objInst.getAttributes()) {
|
||||
setAttribute(obj, attr, typeResolver, instResolver);
|
||||
}
|
||||
instResolver.registerReference(objInst.getReferenceId(), objInst.getReferences());
|
||||
|
||||
public static void buildXmiFile(List<XMIInstanceGraphBuilder> graphBuilderList, EcoreTypeResolver typeResolver,
|
||||
XMIInstanceResolver instanceResolver, ResourceSet resSet) {
|
||||
instanceResolver.resolveUnresolvedReferences(typeResolver);
|
||||
|
||||
Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
|
||||
Map<String, Object> m = reg.getExtensionToFactoryMap();
|
||||
m.put(XMIResource.XMI_NS, new XMIResourceFactoryImpl());
|
||||
this.objects.add(obj);
|
||||
instResolver.store(objInst.getReferenceId(), obj);
|
||||
});
|
||||
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
// create a resource
|
||||
try {
|
||||
for (XMIInstanceGraphBuilder builder : graphBuilderList) {
|
||||
Resource resource = resSet
|
||||
.createResource(URI.createFileURI(Objects.requireNonNull(builder.exportPath)));
|
||||
/*
|
||||
* add your EPackage as root, everything is hierarchical included in this first
|
||||
* node
|
||||
*/
|
||||
builder.objects.forEach(obj -> resource.getContents().add(obj));
|
||||
//System.out.println("[XMIBuilder DEBUG] Resource contains: "+resource.getContents().size());
|
||||
resources.add(resource);
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.exportPath = exportPath;
|
||||
}
|
||||
|
||||
// now save the content.
|
||||
for (Resource resource : resources) {
|
||||
try {
|
||||
resource.save(Collections.EMPTY_MAP);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setAttribute(EObject obj, AttributeEntry<?> attr,EcoreTypeResolver typeResolver,
|
||||
XMIInstanceResolver instResolver) {
|
||||
EAttribute eattr = typeResolver.resolveAttribute(attr);
|
||||
if (attr.isEnumType()) {
|
||||
obj.eSet(eattr, typeResolver.resolveAttributeEnum(attr));
|
||||
}else {
|
||||
obj.eSet(eattr, EmfGraphBuilderUtils.mapVals(eattr.getEAttributeType(), attr.getValue()));
|
||||
}
|
||||
|
||||
}
|
||||
public static void buildXmiFile(List<XMIInstanceGraphBuilder> graphBuilderList, EcoreTypeResolver typeResolver,
|
||||
XMIInstanceResolver instanceResolver, ResourceSet resSet) {
|
||||
instanceResolver.resolveUnresolvedReferences(typeResolver);
|
||||
|
||||
Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
|
||||
Map<String, Object> m = reg.getExtensionToFactoryMap();
|
||||
m.put(XMIResource.XMI_NS, new XMIResourceFactoryImpl());
|
||||
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
// create a resource
|
||||
try {
|
||||
for (XMIInstanceGraphBuilder builder : graphBuilderList) {
|
||||
Resource resource = resSet
|
||||
.createResource(URI.createFileURI(Objects.requireNonNull(builder.exportPath)));
|
||||
/*
|
||||
* add your EPackage as root, everything is hierarchical included in this first
|
||||
* node
|
||||
*/
|
||||
builder.objects.forEach(obj -> resource.getContents().add(obj));
|
||||
//System.out.println("[XMIBuilder DEBUG] Resource contains: "+resource.getContents().size());
|
||||
resources.add(resource);
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// now save the content.
|
||||
for (Resource resource : resources) {
|
||||
try {
|
||||
resource.save(Collections.EMPTY_MAP);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setAttribute(EObject obj, AttributeEntry<?> attr, EcoreTypeResolver typeResolver,
|
||||
XMIInstanceResolver instResolver) {
|
||||
EAttribute eattr = typeResolver.resolveAttribute(attr);
|
||||
if (attr.isEnumType()) {
|
||||
obj.eSet(eattr, typeResolver.resolveAttributeEnum(attr));
|
||||
} else {
|
||||
obj.eSet(eattr, EmfGraphBuilderUtils.mapVals(eattr.getEAttributeType(), attr.getValue()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,54 +1,55 @@
|
|||
package de.nexus.mmlcli.generator;
|
||||
|
||||
import de.nexus.mmlcli.entities.instance.ReferenceEntry;
|
||||
import org.eclipse.emf.common.util.EList;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EReference;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.common.util.EList;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EReference;
|
||||
|
||||
import de.nexus.mmlcli.generator.entities.instance.ReferenceEntry;
|
||||
|
||||
/**
|
||||
* XMIInstanceResolver helps to resolve and link references in instance graphs. MML replaces
|
||||
* all references with unique ids. To be independent of the execution order when constructing
|
||||
* the instance graph, the TypeResolver stores all missing references. Finally, when exporting
|
||||
* the instance graph (and thus after successful complete construction), all missing references
|
||||
* XMIInstanceResolver helps to resolve and link references in instance graphs. MML replaces
|
||||
* all references with unique ids. To be independent of the execution order when constructing
|
||||
* the instance graph, the TypeResolver stores all missing references. Finally, when exporting
|
||||
* the instance graph (and thus after successful complete construction), all missing references
|
||||
* are resolved.
|
||||
*/
|
||||
public class XMIInstanceResolver {
|
||||
private final Map<String, EObject> objects = new HashMap<>();
|
||||
private final Map<String, List<ReferenceEntry>> unresolvedReferences = new HashMap<>();
|
||||
private final Map<String, EObject> objects = new HashMap<>();
|
||||
private final Map<String, List<ReferenceEntry>> unresolvedReferences = new HashMap<>();
|
||||
|
||||
public void store(String objId, EObject obj) {
|
||||
this.objects.put(objId, obj);
|
||||
}
|
||||
public void store(String objId, EObject obj) {
|
||||
this.objects.put(objId, obj);
|
||||
}
|
||||
|
||||
public void registerReference(String objId, List<ReferenceEntry> references) {
|
||||
this.unresolvedReferences.put(objId, references);
|
||||
}
|
||||
public void registerReference(String objId, List<ReferenceEntry> references) {
|
||||
this.unresolvedReferences.put(objId, references);
|
||||
}
|
||||
|
||||
public void resolveUnresolvedReferences(EcoreTypeResolver typeResolver) {
|
||||
for (Map.Entry<String, List<ReferenceEntry>> entry : this.unresolvedReferences.entrySet()) {
|
||||
EObject base = this.objects.get(entry.getKey());
|
||||
for (ReferenceEntry ref : entry.getValue()) {
|
||||
EReference eref = typeResolver.resolveReference(ref);
|
||||
if (eref.isMany()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
EList<EObject> oldVals = (EList<EObject>) base.eGet(eref);
|
||||
for (String refId : ref.getReferencedIds()) {
|
||||
EObject target = this.objects.get(refId);
|
||||
oldVals.add(target);
|
||||
}
|
||||
} else {
|
||||
if (!ref.getReferencedIds().isEmpty()) {
|
||||
String refId = ref.getReferencedIds().get(0);
|
||||
EObject target = this.objects.get(refId);
|
||||
base.eSet(eref, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void resolveUnresolvedReferences(EcoreTypeResolver typeResolver) {
|
||||
for (Map.Entry<String, List<ReferenceEntry>> entry : this.unresolvedReferences.entrySet()) {
|
||||
EObject base = this.objects.get(entry.getKey());
|
||||
for (ReferenceEntry ref : entry.getValue()) {
|
||||
EReference eref = typeResolver.resolveReference(ref);
|
||||
if (eref.isMany()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
EList<EObject> oldVals = (EList<EObject>) base.eGet(eref);
|
||||
for (String refId : ref.getReferencedIds()) {
|
||||
EObject target = this.objects.get(refId);
|
||||
if (!oldVals.contains(target)) {
|
||||
oldVals.add(target);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!ref.getReferencedIds().isEmpty()) {
|
||||
String refId = ref.getReferencedIds().get(0);
|
||||
EObject target = this.objects.get(refId);
|
||||
base.eSet(eref, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package de.nexus.mmlcli.generator.diagnostic;
|
||||
|
||||
public class DocumentDiagnostic {
|
||||
private String message;
|
||||
private DocumentRange range;
|
||||
private int severity;
|
||||
private String code;
|
||||
private String source;
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public DocumentRange getRange() {
|
||||
return range;
|
||||
}
|
||||
|
||||
public int getSeverity() {
|
||||
return severity;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package de.nexus.mmlcli.generator.diagnostic;
|
||||
|
||||
public class DocumentPoint {
|
||||
private int character;
|
||||
private int line;
|
||||
|
||||
public int getCharacter() {
|
||||
return character;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package de.nexus.mmlcli.generator.diagnostic;
|
||||
|
||||
public class DocumentRange {
|
||||
private DocumentPoint start;
|
||||
private DocumentPoint end;
|
||||
|
||||
public DocumentPoint getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public DocumentPoint getEnd() {
|
||||
return end;
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.instance;
|
||||
|
||||
/**
|
||||
* Dataclass for an instance attribute
|
||||
*/
|
||||
public class AttributeEntry<T> {
|
||||
private String name;
|
||||
private String typeId;
|
||||
private T value;
|
||||
private boolean isEnumType;
|
||||
|
||||
public String getTypeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isEnumType() {
|
||||
return isEnumType;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Dataclass for a generator of a single XMI file
|
||||
*/
|
||||
public class GeneratorInstance {
|
||||
private String instanceName;
|
||||
private ArrayList<ObjectInstance> instances;
|
||||
|
||||
public String getInstanceName() {
|
||||
return instanceName;
|
||||
}
|
||||
|
||||
public ArrayList<ObjectInstance> getInstances() {
|
||||
return instances;
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Dataclass for list of generators for multiple XMI files
|
||||
*/
|
||||
public class GeneratorInstanceWrapper {
|
||||
private ArrayList<GeneratorInstance> serializedInstances;
|
||||
|
||||
public ArrayList<GeneratorInstance> getSerializedInstances() {
|
||||
return serializedInstances;
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Dataclass for an instance
|
||||
*/
|
||||
public class ObjectInstance {
|
||||
private String referenceId;
|
||||
private String referenceTypeId;
|
||||
private String name;
|
||||
private ArrayList<AttributeEntry<?>> attributes;
|
||||
private ArrayList<ReferenceEntry> references;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getReferenceTypeId() {
|
||||
return referenceTypeId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ArrayList<AttributeEntry<?>> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public ArrayList<ReferenceEntry> getReferences() {
|
||||
return references;
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Dataclass for an instance reference
|
||||
*/
|
||||
public class ReferenceEntry {
|
||||
private String name;
|
||||
private String typeId;
|
||||
private ArrayList<String> referencedIds;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getTypeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
public ArrayList<String> getReferencedIds() {
|
||||
return referencedIds;
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/***
|
||||
* Dataclass for a class-like (Abstract class, class or interface)
|
||||
*/
|
||||
public class AbstractClassEntity {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private boolean isAbstract;
|
||||
private boolean isInterface;
|
||||
private final ArrayList<AttributeEntity<?>> attributes = new ArrayList<>();
|
||||
private final ArrayList<CReferenceEntity> references = new ArrayList<>();
|
||||
private final ArrayList<String> extendsIds = new ArrayList<>();
|
||||
private final ArrayList<String> implementsIds = new ArrayList<>();
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isAbstract() {
|
||||
return isAbstract;
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return isInterface;
|
||||
}
|
||||
|
||||
public ArrayList<AttributeEntity<?>> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public ArrayList<CReferenceEntity> getReferences() {
|
||||
return references;
|
||||
}
|
||||
|
||||
public ArrayList<String> getExtendsIds() {
|
||||
return extendsIds;
|
||||
}
|
||||
|
||||
public ArrayList<String> getImplementsIds() {
|
||||
return implementsIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String attributeString = attributes.isEmpty() ? ""
|
||||
: "\n" + attributes.stream().map(AttributeEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
String referenceString = references.isEmpty() ? ""
|
||||
: "\n" + references.stream().map(CReferenceEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
return String.format("%s(isAbstract:%b|isInterface:%b||%s||%s)", name, isAbstract, isInterface, attributeString,
|
||||
referenceString);
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.model;
|
||||
|
||||
/**
|
||||
* Dataclass for a class attribute
|
||||
*/
|
||||
public class AttributeEntity<T> {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private String type;
|
||||
private boolean isEnumType;
|
||||
private boolean hasDefaultValue;
|
||||
private T defaultValue;
|
||||
private ClassElementModifiers modifiers;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isEnumType() {
|
||||
return isEnumType;
|
||||
}
|
||||
|
||||
public boolean isHasDefaultValue() {
|
||||
return hasDefaultValue;
|
||||
}
|
||||
|
||||
public T getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public ClassElementModifiers getModifiers() {
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s<%s>", name, type);
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.model;
|
||||
|
||||
/**
|
||||
* Dataclass for class references
|
||||
*/
|
||||
public class CReferenceEntity {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private MultiplicityEntity multiplicity;
|
||||
private String type;
|
||||
private ClassElementModifiers modifiers;
|
||||
private boolean hasOpposite;
|
||||
private String opposite;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public MultiplicityEntity getMultiplicity() {
|
||||
return multiplicity;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public ClassElementModifiers getModifiers() {
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
public boolean isHasOpposite() {
|
||||
return hasOpposite;
|
||||
}
|
||||
|
||||
public String getOpposite() {
|
||||
return opposite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("(%s -> %s)", name, type);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Dataclass for class modifiers
|
||||
*/
|
||||
public class ClassElementModifiers {
|
||||
private boolean readonly;
|
||||
@SerializedName("volatile")
|
||||
private boolean _volatile;
|
||||
@SerializedName("transient")
|
||||
private boolean _transient;
|
||||
private boolean unsettable;
|
||||
private boolean derived;
|
||||
private boolean unique;
|
||||
private boolean ordered;
|
||||
private boolean resolve;
|
||||
private boolean id;
|
||||
|
||||
public boolean isReadonly() {
|
||||
return readonly;
|
||||
}
|
||||
|
||||
public boolean isVolatile() {
|
||||
return _volatile;
|
||||
}
|
||||
|
||||
public boolean isTransient() {
|
||||
return _transient;
|
||||
}
|
||||
|
||||
public boolean isUnsettable() {
|
||||
return unsettable;
|
||||
}
|
||||
|
||||
public boolean isDerived() {
|
||||
return derived;
|
||||
}
|
||||
|
||||
public boolean isUnique() {
|
||||
return unique;
|
||||
}
|
||||
|
||||
public boolean isOrdered() {
|
||||
return ordered;
|
||||
}
|
||||
|
||||
public boolean isResolve() {
|
||||
return resolve;
|
||||
}
|
||||
|
||||
public boolean isId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Dataclass for a enum
|
||||
*/
|
||||
public class EnumEntity<T> {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private String type;
|
||||
private ArrayList<EnumEntryEntity<T>> entries;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public ArrayList<EnumEntryEntity<T>> getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ENUM<%s,%s>{%s}", name, type, entries.isEmpty() ? ""
|
||||
: entries.stream().map(EnumEntryEntity::toString).collect(Collectors.joining(",")));
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.model;
|
||||
|
||||
/**
|
||||
* Dataclass for a single enum entry
|
||||
*/
|
||||
public class EnumEntryEntity<T> {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private boolean hasDefaultValue;
|
||||
private T defaultValue;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isHasDefaultValue() {
|
||||
return hasDefaultValue;
|
||||
}
|
||||
|
||||
public T getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%s|%b]", name, hasDefaultValue);
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Dataclass for a complete metamodel
|
||||
*/
|
||||
public class ModelEntity {
|
||||
private final ArrayList<PackageEntity> packages = new ArrayList<>();
|
||||
|
||||
public ArrayList<PackageEntity> getPackages() {
|
||||
return packages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return packages.isEmpty() ? ""
|
||||
: "\n" + packages.stream().map(PackageEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.model;
|
||||
|
||||
/**
|
||||
* Dataclass for reference multiplicities
|
||||
*/
|
||||
public class MultiplicityEntity {
|
||||
private boolean hasUpperBound;
|
||||
private boolean lowerIsN;
|
||||
private boolean lowerIsN0;
|
||||
private boolean upperIsN;
|
||||
private boolean upperIsN0;
|
||||
private int lower;
|
||||
private int upper;
|
||||
|
||||
public boolean isHasUpperBound() {
|
||||
return hasUpperBound;
|
||||
}
|
||||
|
||||
public boolean isLowerIsN() {
|
||||
return lowerIsN;
|
||||
}
|
||||
|
||||
public boolean isLowerIsN0() {
|
||||
return lowerIsN0;
|
||||
}
|
||||
|
||||
public boolean isUpperIsN() {
|
||||
return upperIsN;
|
||||
}
|
||||
|
||||
public boolean isUpperIsN0() {
|
||||
return upperIsN0;
|
||||
}
|
||||
|
||||
public int getLower() {
|
||||
return lower;
|
||||
}
|
||||
|
||||
public int getUpper() {
|
||||
return upper;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package de.nexus.mmlcli.generator.entities.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Dataclass for a package
|
||||
*/
|
||||
public class PackageEntity {
|
||||
private String referenceId;
|
||||
private String name;
|
||||
private ArrayList<AbstractClassEntity> abstractClasses;
|
||||
private ArrayList<EnumEntity<?>> enums;
|
||||
private ArrayList<PackageEntity> subPackages;
|
||||
|
||||
public String getReferenceId() {
|
||||
return referenceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ArrayList<AbstractClassEntity> getAbstractClasses() {
|
||||
return abstractClasses;
|
||||
}
|
||||
|
||||
public ArrayList<EnumEntity<?>> getEnums() {
|
||||
return enums;
|
||||
}
|
||||
|
||||
public ArrayList<PackageEntity> getSubPackages() {
|
||||
return subPackages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String classesString = abstractClasses.isEmpty() ? ""
|
||||
: "\n" + abstractClasses.stream().map(AbstractClassEntity::toString).collect(Collectors.joining(","))
|
||||
+ "\n";
|
||||
String enumsString = enums.isEmpty() ? ""
|
||||
: "\n" + enums.stream().map(EnumEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
String subPackagesString = subPackages.isEmpty() ? ""
|
||||
: "\n" + subPackages.stream().map(PackageEntity::toString).collect(Collectors.joining(",")) + "\n";
|
||||
return String.format("%s{%s %s %s}", name, classesString, enumsString, subPackagesString);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package de.nexus.mmlcli.serializer;
|
||||
|
||||
import org.eclipse.emf.ecore.ENamedElement;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class EcoreIdResolver {
|
||||
private final Map<ENamedElement, UUID> elementMapping = new HashMap<>();
|
||||
|
||||
|
||||
public UUID resolveId(ENamedElement classifier) {
|
||||
UUID resolved = this.elementMapping.get(classifier);
|
||||
if (resolved == null) {
|
||||
resolved = UUID.randomUUID();
|
||||
this.elementMapping.put(classifier, resolved);
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package de.nexus.mmlcli.serializer;
|
||||
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EPackage;
|
||||
import org.eclipse.emf.ecore.EcorePackage;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet;
|
||||
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
|
||||
import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
|
||||
import org.eclipse.emf.ecore.util.ExtendedMetaData;
|
||||
import org.eclipse.emf.ecore.xmi.XMLResource;
|
||||
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class EmfResourceLoader {
|
||||
public static EPackage loadEmfResources(File ecoreFile) {
|
||||
System.out.println("Serialize model");
|
||||
System.out.println("==========[Loading resources]==========");
|
||||
|
||||
// Create a resource set.
|
||||
ResourceSet resourceSet = new ResourceSetImpl();
|
||||
|
||||
// Register the default resource factory -- only needed for stand-alone!
|
||||
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
|
||||
"ecore", new EcoreResourceFactoryImpl());
|
||||
|
||||
// enable extended metadata
|
||||
final ExtendedMetaData extendedMetaData = new BasicExtendedMetaData(resourceSet.getPackageRegistry());
|
||||
resourceSet.getLoadOptions().put(XMLResource.OPTION_EXTENDED_META_DATA,
|
||||
extendedMetaData);
|
||||
|
||||
// Register the package -- only needed for stand-alone!
|
||||
EcorePackage ecorePackage = EcorePackage.eINSTANCE;
|
||||
|
||||
// Get the URI of the model file.
|
||||
URI fileURI = URI.createFileURI(ecoreFile.getAbsolutePath());
|
||||
|
||||
// Demand load the resource for this file.
|
||||
Resource resource = resourceSet.getResource(fileURI, true);
|
||||
|
||||
EObject eObject = resource.getContents().get(0);
|
||||
if (eObject instanceof EPackage ePackage) {
|
||||
resourceSet.getPackageRegistry().put(ePackage.getNsURI(), ePackage);
|
||||
System.out.println("[Package ]" + ePackage.getName() + " | " + ePackage.getNsURI());
|
||||
return ePackage;
|
||||
}
|
||||
throw new IllegalStateException("Could not load package from ecore!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package de.nexus.mmlcli.serializer;
|
||||
|
||||
import de.nexus.mmlcli.entities.model.ModelEntity;
|
||||
import de.nexus.mmlcli.entities.model.PackageEntity;
|
||||
import de.nexus.mmlcli.generator.DeserializedDocument;
|
||||
import de.nexus.mmlcli.generator.SerializedDocument;
|
||||
import org.eclipse.emf.ecore.EPackage;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
public class MmlSerializedGenerator {
|
||||
public static PackageEntity buildEntities(EPackage pckg) {
|
||||
EcoreIdResolver resolver = new EcoreIdResolver();
|
||||
return PackageEntity.fromEPackage(pckg, resolver);
|
||||
}
|
||||
|
||||
public static String serializeEntities(PackageEntity pckgEntity, URI uri) {
|
||||
ModelEntity model = ModelEntity.fromPackageEntity(pckgEntity);
|
||||
DeserializedDocument dDoc = DeserializedDocument.build(model);
|
||||
SerializedDocument sDoc = new SerializedDocument(uri, dDoc);
|
||||
return sDoc.serialize();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package de.nexus.mmlcli.serializer;
|
||||
|
||||
import de.nexus.mmlcli.entities.model.PackageEntity;
|
||||
import org.eclipse.emf.ecore.EPackage;
|
||||
import picocli.CommandLine;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@CommandLine.Command(name = "serialize", mixinStandardHelpOptions = true, version = "v1.0.0", description = "Serializes a given Ecore")
|
||||
public class SerializeCommand implements Callable<Integer> {
|
||||
@CommandLine.Option(names = {"-o", "--out"}, paramLabel = "SERIALIZED", description = "path where the serialized model should be stored", arity = "0..1")
|
||||
File serializedTarget;
|
||||
|
||||
@CommandLine.Parameters(index = "0")
|
||||
File ecoreFile;
|
||||
|
||||
|
||||
@Override
|
||||
public Integer call() throws Exception {
|
||||
if (!ecoreFile.exists()) {
|
||||
System.err.println("Inputfile does not exist: " + ecoreFile.getAbsolutePath());
|
||||
return 2;
|
||||
}
|
||||
if (!ecoreFile.canRead()) {
|
||||
System.err.println("Could not read inputfile: " + ecoreFile.getAbsolutePath());
|
||||
return 2;
|
||||
}
|
||||
EPackage ePackage = EmfResourceLoader.loadEmfResources(ecoreFile);
|
||||
PackageEntity packageEntity = MmlSerializedGenerator.buildEntities(ePackage);
|
||||
String serialized = MmlSerializedGenerator.serializeEntities(packageEntity, ecoreFile.toURI());
|
||||
|
||||
if (serializedTarget == null) {
|
||||
System.out.println("=$MML-CONTENT-START$=");
|
||||
System.out.println(serialized);
|
||||
} else {
|
||||
try {
|
||||
Files.writeString(serializedTarget.toPath(), serialized);
|
||||
System.out.println("Written serialized file to: " + serializedTarget.getAbsolutePath());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("Could not write serialized file: " + serializedTarget.getAbsolutePath());
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
27
src/test/data/CarOwnership.ecore
Normal file
27
src/test/data/CarOwnership.ecore
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="CarOwnership" nsURI="platform:/resource/CarOwnership/model/CarOwnership_CarOwnership.ecore"
|
||||
nsPrefix="CarOwnership">
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Person">
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="alter" ordered="false"
|
||||
unique="false" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="kinder" ordered="false"
|
||||
unique="false" upperBound="-1" eType="#//Person" resolveProxies="false" eOpposite="#//Person/eltern"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="eltern" ordered="false"
|
||||
unique="false" lowerBound="2" eType="#//Person" resolveProxies="false" eOpposite="#//Person/kinder"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="autos" ordered="false"
|
||||
unique="false" upperBound="-1" eType="#//Auto" resolveProxies="false" eOpposite="#//Auto/besitzer"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Auto">
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="kennzeichen" ordered="false"
|
||||
unique="false" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="marke" ordered="false"
|
||||
unique="false" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="erstzulassung" ordered="false"
|
||||
unique="false" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="baujahr" ordered="false"
|
||||
unique="false" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="besitzer" ordered="false"
|
||||
unique="false" lowerBound="1" eType="#//Person" resolveProxies="false" eOpposite="#//Person/autos"/>
|
||||
</eClassifiers>
|
||||
</ecore:EPackage>
|
1
src/test/data/CarOwnership.json
Normal file
1
src/test/data/CarOwnership.json
Normal file
File diff suppressed because one or more lines are too long
26
src/test/data/FerrymanProblem.ecore
Normal file
26
src/test/data/FerrymanProblem.ecore
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="FerrymanProblem" nsURI="platform:/resource/FerrymanProblem/model/FerrymanProblem_FerrymanProblem.ecore"
|
||||
nsPrefix="FerrymanProblem">
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Model">
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="leftBank" ordered="false"
|
||||
unique="false" lowerBound="1" eType="#//Bank" resolveProxies="false"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="rightBank" ordered="false"
|
||||
unique="false" lowerBound="1" eType="#//Bank" resolveProxies="false"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="subjects" ordered="false"
|
||||
unique="false" upperBound="-1" eType="#//Subject" resolveProxies="false"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Bank"/>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Subject" abstract="true">
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="isAt" ordered="false" unique="false"
|
||||
lowerBound="1" eType="#//Bank" resolveProxies="false"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="FerryMan" eSuperTypes="#//Subject"/>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Thing" abstract="true" eSuperTypes="#//Subject">
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="likesToEat" ordered="false"
|
||||
unique="false" upperBound="-1" eType="#//Thing" resolveProxies="false"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Wolf" eSuperTypes="#//Thing"/>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Goat" eSuperTypes="#//Thing"/>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Cabbage" eSuperTypes="#//Thing"/>
|
||||
</ecore:EPackage>
|
1
src/test/data/FerrymanProblem.json
Normal file
1
src/test/data/FerrymanProblem.json
Normal file
File diff suppressed because one or more lines are too long
66
src/test/data/HospitalExample.ecore
Normal file
66
src/test/data/HospitalExample.ecore
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="HospitalExample" nsURI="platform:/resource/HospitalExample/model/HospitalExample_HospitalExample.ecore"
|
||||
nsPrefix="HospitalExample">
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Hospital">
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="id" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="reception" lowerBound="1"
|
||||
eType="#//Reception" containment="true"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="staff" ordered="false"
|
||||
upperBound="-1" eType="#//Staff" containment="true"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="department" upperBound="-1"
|
||||
eType="#//Department" containment="true"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Reception">
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="waits" upperBound="-1"
|
||||
eType="#//Patient" containment="true"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Staff" abstract="true">
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="staffID" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"
|
||||
defaultValueLiteral="-1"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="works" eType="#//Department"
|
||||
eOpposite="#//Department/staff"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Doctor" eSuperTypes="#//Staff">
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="patientCapacity" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="caresfor" upperBound="-1"
|
||||
eType="#//Patient" eOpposite="#//Patient/doctor"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Nurse" eSuperTypes="#//Staff">
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="responsible" eType="#//Room"
|
||||
eOpposite="#//Room/nurses"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Department">
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="dID" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"
|
||||
defaultValueLiteral="-1" iD="true"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="maxRoomCount" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="rooms" upperBound="-1"
|
||||
eType="#//Room" containment="true"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="staff" upperBound="-1"
|
||||
eType="#//Staff" eOpposite="#//Staff/works"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Patient">
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="patientID" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"
|
||||
defaultValueLiteral="-1"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="level" eType="#//Carelevel"
|
||||
defaultValueLiteral="PENDING"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="doctor" lowerBound="1"
|
||||
eType="#//Doctor" eOpposite="#//Doctor/caresfor"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EClass" name="Room">
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="capacity" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EAttribute" name="level" eType="#//Carelevel"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="lies" upperBound="-1" eType="#//Patient"
|
||||
containment="true"/>
|
||||
<eStructuralFeatures xsi:type="ecore:EReference" name="nurses" upperBound="-1"
|
||||
eType="#//Nurse" eOpposite="#//Nurse/responsible"/>
|
||||
</eClassifiers>
|
||||
<eClassifiers xsi:type="ecore:EEnum" name="Carelevel">
|
||||
<eLiterals name="WEAK"/>
|
||||
<eLiterals name="MEDIUM" value="1"/>
|
||||
<eLiterals name="STRONG" value="2"/>
|
||||
<eLiterals name="PENDING" value="3"/>
|
||||
</eClassifiers>
|
||||
</ecore:EPackage>
|
1
src/test/data/HospitalExample.json
Normal file
1
src/test/data/HospitalExample.json
Normal file
File diff suppressed because one or more lines are too long
40
src/test/java/GeneratorTests.java
Normal file
40
src/test/java/GeneratorTests.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
import de.nexus.mmlcli.generator.EmfResourceBuilder;
|
||||
import de.nexus.mmlcli.generator.SerializedDocument;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class GeneratorTests {
|
||||
private final static File TEST_DATA_FOLDER = new File("src/test/data");
|
||||
|
||||
static Stream<TestBundle> testBundleProvider() {
|
||||
return TestUtils.getTestBundles(TEST_DATA_FOLDER).stream();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("testBundleProvider")
|
||||
void testCorrectEcoreGeneration(TestBundle bundle, @TempDir File workingDir) throws IOException {
|
||||
String serializedContent = Files.readString(bundle.getSerializedFile().toPath());
|
||||
|
||||
SerializedDocument[] result = Objects.requireNonNull(SerializedDocument.deserialize(serializedContent));
|
||||
EmfResourceBuilder.buildEmfResources(result, bundle.getBundleName(), workingDir);
|
||||
|
||||
String ecoreContent = Files.readString(bundle.getEcoreFile().toPath());
|
||||
|
||||
Path generatedEcore = workingDir.toPath().resolve("model").resolve(bundle.getBundleName() + "_" + bundle.getBundleName() + ".ecore");
|
||||
|
||||
Assertions.assertTrue(generatedEcore.toFile().exists());
|
||||
|
||||
String generatedEcoreContent = Files.readString(generatedEcore);
|
||||
|
||||
Assertions.assertEquals(ecoreContent, generatedEcoreContent);
|
||||
}
|
||||
}
|
25
src/test/java/TestBundle.java
Normal file
25
src/test/java/TestBundle.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
import java.io.File;
|
||||
|
||||
public class TestBundle {
|
||||
private final String bundleName;
|
||||
private final File ecoreFile;
|
||||
private final File serializedFile;
|
||||
|
||||
public TestBundle(String bundleName, File ecoreFile, File serializedFile) {
|
||||
this.bundleName = bundleName;
|
||||
this.ecoreFile = ecoreFile;
|
||||
this.serializedFile = serializedFile;
|
||||
}
|
||||
|
||||
public String getBundleName() {
|
||||
return bundleName;
|
||||
}
|
||||
|
||||
public File getEcoreFile() {
|
||||
return ecoreFile;
|
||||
}
|
||||
|
||||
public File getSerializedFile() {
|
||||
return serializedFile;
|
||||
}
|
||||
}
|
51
src/test/java/TestUtils.java
Normal file
51
src/test/java/TestUtils.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public class TestUtils {
|
||||
public static ArrayList<TestBundle> getTestBundles(File dataFolder) {
|
||||
if (dataFolder == null || !dataFolder.exists() || !dataFolder.isDirectory()) {
|
||||
throw new IllegalArgumentException("Data folder is not directory or does not exist!");
|
||||
}
|
||||
|
||||
Set<String> knownFilenames = new HashSet<>();
|
||||
ArrayList<TestBundle> testBundles = new ArrayList<>();
|
||||
|
||||
for (File file : Objects.requireNonNull(dataFolder.listFiles())) {
|
||||
String fileName = FilenameUtils.getBaseName(file.getName());
|
||||
String extension = FilenameUtils.getExtension(file.getName());
|
||||
|
||||
if (knownFilenames.contains(fileName)) {
|
||||
continue;
|
||||
}
|
||||
knownFilenames.add(fileName);
|
||||
|
||||
File ecoreFile, jsonFile;
|
||||
|
||||
if (extension.equals("ecore")) {
|
||||
ecoreFile = file;
|
||||
jsonFile = file.toPath().resolveSibling(fileName + ".json").toFile();
|
||||
if (!jsonFile.exists() || jsonFile.isDirectory()) {
|
||||
System.err.println("Skipping file due to missing json match: " + file.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
} else if (extension.equals("json")) {
|
||||
ecoreFile = file.toPath().resolveSibling(fileName + ".ecore").toFile();
|
||||
jsonFile = file;
|
||||
if (!ecoreFile.exists() || ecoreFile.isDirectory()) {
|
||||
System.err.println("Skipping file due to missing ecore match: " + file.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
System.err.println("Skipping file due to extension mismatch: " + file.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
testBundles.add(new TestBundle(fileName, ecoreFile, jsonFile));
|
||||
}
|
||||
return testBundles;
|
||||
}
|
||||
}
|
46
src/test/java/TwoWayEcoreTests.java
Normal file
46
src/test/java/TwoWayEcoreTests.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
import de.nexus.mmlcli.entities.model.PackageEntity;
|
||||
import de.nexus.mmlcli.generator.EmfResourceBuilder;
|
||||
import de.nexus.mmlcli.generator.SerializedDocument;
|
||||
import de.nexus.mmlcli.serializer.EmfResourceLoader;
|
||||
import de.nexus.mmlcli.serializer.MmlSerializedGenerator;
|
||||
import org.eclipse.emf.ecore.EPackage;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class TwoWayEcoreTests {
|
||||
private final static File TEST_DATA_FOLDER = new File("src/test/data");
|
||||
|
||||
static Stream<TestBundle> testBundleProvider() {
|
||||
return TestUtils.getTestBundles(TEST_DATA_FOLDER).stream();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("testBundleProvider")
|
||||
void testCorrectTwowaySerialization(TestBundle bundle, @TempDir File workingDir) throws IOException {
|
||||
EPackage ePackage = EmfResourceLoader.loadEmfResources(bundle.getEcoreFile());
|
||||
PackageEntity packageEntity = MmlSerializedGenerator.buildEntities(ePackage);
|
||||
String generatedSerialization = MmlSerializedGenerator.serializeEntities(packageEntity, bundle.getEcoreFile().toURI());
|
||||
|
||||
SerializedDocument[] result = Objects.requireNonNull(SerializedDocument.deserialize(generatedSerialization));
|
||||
EmfResourceBuilder.buildEmfResources(result, bundle.getBundleName(), workingDir);
|
||||
|
||||
String ecoreContent = Files.readString(bundle.getEcoreFile().toPath());
|
||||
|
||||
Path generatedEcore = workingDir.toPath().resolve("model").resolve(bundle.getBundleName() + "_" + bundle.getBundleName() + ".ecore");
|
||||
|
||||
Assertions.assertTrue(generatedEcore.toFile().exists());
|
||||
|
||||
String generatedEcoreContent = Files.readString(generatedEcore);
|
||||
|
||||
Assertions.assertEquals(ecoreContent, generatedEcoreContent);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue