Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2b522a4

Browse files
committedNov 11, 2024·
Refactor adapter to simplify it
1 parent d1ae8af commit 2b522a4

File tree

7 files changed

+780
-849
lines changed

7 files changed

+780
-849
lines changed
 

‎build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
subprojects {
22
group = 'io.opencaesar.adapters'
3-
version = '2.10.0'
3+
version = '2.11.0'
44

55
ext.versions = [
66
oml: '2.+',

‎ecore2oml-gradle/src/main/java/io/opencaesar/ecore2oml/Ecore2OmlTask.java

+15
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ public Ecore2OmlTask() {
7272
@Input
7373
public abstract Property<String> getOutputFileExtension();
7474

75+
/**
76+
* The namespace Mappings
77+
*
78+
* @return String List Property
79+
*/
80+
@Optional
81+
@Input
82+
public abstract ListProperty<String> getNamespaceMap();
83+
7584
/**
7685
* The debug flag
7786
*
@@ -110,6 +119,12 @@ public void run() {
110119
if (getOutputFileExtension().isPresent()) {
111120
args.add("-oe");
112121
args.add(getOutputFileExtension().get());
122+
}
123+
if (getNamespaceMap().isPresent()) {
124+
for (var ns : getNamespaceMap().get()) {
125+
args.add("-ns");
126+
args.add(ns);
127+
}
113128
}
114129
if (getDebug().isPresent() && getDebug().get()) {
115130
args.add("-d");

‎ecore2oml/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Args
2525
--referenced-ecore-path | -r path/to/referenced/ecore/file [Optional]
2626
--input-file-extension | -ie Extension of input file [Optional, ecore/xcore by default]
2727
--output-file-extension | -oe Extension of output file (Optional, oml by default, other options omlxmi and omljson)
28+
--namespace-map | -ns Mapping of old namespace prefix to new namespace prefix (Optional, syntax is oldNsPrefix=newNsPrefix)
2829
--debug | -d Shows debug statements
2930
--help | -h Shows help
3031
```
@@ -45,5 +46,6 @@ task ecore2oml(type:io.opencaesar.ecore2oml.Ecore2OmlTask) {
4546
referencedEcorePaths = [ file('path/to/options/file.json') ] // Optional
4647
inputFileExtensions = ['ecore', 'xcore'] // Optional
4748
outputFileExtension = 'oml' // Optional (other options, omlxmi or omljson)
49+
namespaceMap = [ 'oldNsPrefix=newNsPrefix' ] // Optional
4850
}
4951
```

‎ecore2oml/src/main/java/io/opencaesar/ecore2oml/AssociationBuilder.java

-283
This file was deleted.

‎ecore2oml/src/main/java/io/opencaesar/ecore2oml/Ecore2Oml.java

+331-484
Large diffs are not rendered by default.

‎ecore2oml/src/main/java/io/opencaesar/ecore2oml/Ecore2OmlApp.java

+114-81
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
import java.util.Arrays;
2323
import java.util.Collection;
2424
import java.util.Collections;
25-
import java.util.LinkedHashSet;
25+
import java.util.HashMap;
2626
import java.util.List;
27-
import java.util.Set;
27+
import java.util.Map;
2828

2929
import org.apache.log4j.Appender;
3030
import org.apache.log4j.AppenderSkeleton;
@@ -63,58 +63,75 @@ public class Ecore2OmlApp {
6363
private static final String ECORE = "ecore";
6464
private static final String XCORE = "xcore";
6565

66-
@Parameter(
67-
names= {"--input-folder-path","-i"},
68-
description="Location of input Ecore folder (Required)",
69-
validateWith=InputFolderPath.class,
70-
required=true,
71-
order=1)
72-
private String inputFolderPath = null;
73-
74-
@Parameter(
75-
names= {"--output-folder-path", "-o"},
76-
description="Location of the output OML folder (Required)",
77-
validateWith=OutputFolderPath.class,
78-
required=true,
79-
order=2)
80-
private String outputFolderPath;
81-
82-
@Parameter(
83-
names= {"--referenced-ecore-path", "-r"},
84-
description="Location of a referenced ecore file (Optional)",
85-
validateWith= InputEcorePath.class,
86-
required=false,
87-
order=3
88-
)
89-
private List<String> referencedEcorePaths = new ArrayList<>();
66+
static class Options {
67+
@Parameter(
68+
names= {"--input-folder-path","-i"},
69+
description="Location of input Ecore folder (Required)",
70+
validateWith=InputFolderPath.class,
71+
required=true)
72+
public String inputFolderPath = null;
9073

91-
@Parameter(
92-
names= {"--input-file-extension","-ie"},
93-
description="Extension of input file (Optional, ecore/xcore by default)",
94-
required=false,
95-
order=4)
96-
private List<String> inputFileExtensions = Arrays.asList(ECORE, XCORE);
97-
98-
@Parameter(
99-
names= {"--output-file-extension","-oe"},
100-
description="Extension of output file (Optional, oml by default)",
101-
required=false,
102-
order=5)
103-
private String outputFileExtension = OmlConstants.OML_EXTENSION;
104-
105-
@Parameter(
106-
names= {"--debug", "-d"},
107-
description="Shows debug logging statements",
108-
order=6)
109-
private boolean debug;
74+
@Parameter(
75+
names= {"--output-folder-path", "-o"},
76+
description="Location of the output OML folder (Required)",
77+
validateWith=OutputFolderPath.class,
78+
required=true)
79+
public String outputFolderPath;
80+
81+
@Parameter(
82+
names= {"--referenced-ecore-path", "-r"},
83+
description="Location of a referenced ecore file (Optional)",
84+
validateWith= InputEcorePath.class,
85+
required=false)
86+
public List<String> referencedEcorePaths = new ArrayList<>();
87+
88+
@Parameter(
89+
names= {"--input-file-extension","-ie"},
90+
description="Extension of input file (Optional, ecore/xcore by default)",
91+
required=false)
92+
public List<String> inputFileExtensions = Arrays.asList(ECORE, XCORE);
93+
94+
@Parameter(
95+
names= {"--output-file-extension","-oe"},
96+
description="Extension of output file (Optional, oml by default)",
97+
required=false)
98+
public String outputFileExtension = OmlConstants.OML_EXTENSION;
99+
100+
@Parameter(
101+
names= {"--namespace-map","-ns"},
102+
description="Mapping of existing namespace prefixes to new namespace prefixes (Optional, syntax is oldNsPrefix=newNsPrefix)",
103+
validateWith= NamespaceMapping.class,
104+
required=false)
105+
public List<String> namespaceMap = Arrays.asList(new String[] {
106+
"http://www.eclipse.org/emf/2002/Ecore#EObject=http://www.w3.org/2002/07/owl#Thing",
107+
"http://www.eclipse.org/emf/2002/Ecore#EString=http://www.w3.org/2001/XMLSchema#string",
108+
"http://www.eclipse.org/emf/2002/Ecore#EFloat=http://www.w3.org/2001/XMLSchema#float",
109+
"http://www.eclipse.org/emf/2002/Ecore#EInt=http://www.w3.org/2001/XMLSchema#int",
110+
"http://www.eclipse.org/emf/2002/Ecore#EBoolean=http://www.w3.org/2001/XMLSchema#boolean",
111+
"http://www.eclipse.org/emf/2003/XMLType#ID=http://www.w3.org/2001/XMLSchema#string",
112+
"http://www.eclipse.org/emf/2003/XMLType#QName=http://www.w3.org/2001/XMLSchema#string",
113+
"http://www.eclipse.org/emf/2003/XMLType#Int=http://www.w3.org/2001/XMLSchema#int"
114+
});
110115

111-
@Parameter(
112-
names= {"--help","-h"},
113-
description="Displays summary of options",
114-
help=true,
115-
order=7)
116-
private boolean help;
116+
/*
117+
* A map equivalent of namespaceMap
118+
*/
119+
public Map<String, String> namespaceMap2 = new HashMap<>();
117120

121+
@Parameter(
122+
names= {"--debug", "-d"},
123+
description="Shows debug logging statements")
124+
public boolean debug;
125+
126+
@Parameter(
127+
names= {"--help","-h"},
128+
description="Displays summary of options",
129+
help=true)
130+
public boolean help;
131+
}
132+
133+
private final Options options = new Options();
134+
118135
private Logger LOGGER = LogManager.getLogger(Ecore2OmlApp.class);
119136

120137
/**
@@ -124,19 +141,25 @@ public class Ecore2OmlApp {
124141
*/
125142
public static void main(String ... args) throws IOException {
126143
final Ecore2OmlApp app = new Ecore2OmlApp();
127-
final JCommander builder = JCommander.newBuilder().addObject(app).build();
144+
final JCommander builder = JCommander.newBuilder().addObject(app.options).build();
128145
builder.parse(args);
129-
if (app.help) {
146+
if (app.options.help) {
130147
builder.usage();
131148
return;
132149
}
133-
if (app.debug) {
150+
if (app.options.debug) {
134151
final Appender appender = LogManager.getRootLogger().getAppender("stdout");
135152
((AppenderSkeleton)appender).setThreshold(Level.DEBUG);
136153
}
137-
if (app.inputFolderPath.endsWith(File.separator)) {
138-
app.inputFolderPath = app.inputFolderPath.substring(0, app.inputFolderPath.length()-1);
154+
if (app.options.inputFolderPath.endsWith(File.separator)) {
155+
app.options.inputFolderPath = app.options.inputFolderPath.substring(0, app.options.inputFolderPath.length()-1);
139156
}
157+
app.options.namespaceMap.forEach(entry -> {
158+
var parts = entry.split("=");
159+
var oldNs = parts[0].trim();
160+
var newNs = parts[1].trim();
161+
app.options.namespaceMap2.put(oldNs, newNs);
162+
});
140163
app.run();
141164
}
142165

@@ -154,11 +177,11 @@ private void run() throws IOException {
154177
LOGGER.info(" S T A R T");
155178
LOGGER.info(" Ecore to Oml "+getAppVersion());
156179
LOGGER.info("=================================================================");
157-
LOGGER.info("Input Folder Path= " + inputFolderPath);
158-
LOGGER.info("Output Folder Path= " + outputFolderPath);
180+
LOGGER.info("Input Folder Path= " + options.inputFolderPath);
181+
LOGGER.info("Output Folder Path= " + options.outputFolderPath);
159182

160-
final File inputFolder = new File(inputFolderPath);
161-
final Collection<File> inputFiles = collectInputFiles(inputFolder, inputFileExtensions);
183+
final File inputFolder = new File(options.inputFolderPath);
184+
final Collection<File> inputFiles = collectInputFiles(inputFolder, options.inputFileExtensions);
162185

163186
final ResourceSet inputResourceSet = createInputResourceSet();
164187

@@ -170,7 +193,7 @@ private void run() throws IOException {
170193
LOGGER.info("Reading: "+inputURI);
171194
inputResourceSet.getResource(inputURI, true);
172195
}
173-
196+
174197
// load the Oml registries here after the input have been read
175198
OmlStandaloneSetup.doSetup();
176199
OmlXMIResourceFactory.register();
@@ -180,7 +203,7 @@ private void run() throws IOException {
180203
outputResourceSet.getLoadOptions().put(OmlConstants.RESOLVE_IRI_USING_RESOURCE_SET, Boolean.TRUE);
181204
outputResourceSet.eAdapters().add(new ECrossReferenceAdapter());
182205

183-
final File outputFolder = new File(outputFolderPath);
206+
//final File outputFolder = new File(options.outputFolderPath);
184207

185208
// create the Oml builder
186209
final OmlBuilder builder = new OmlBuilder(outputResourceSet);
@@ -189,29 +212,22 @@ private void run() throws IOException {
189212
builder.start();
190213

191214
// convert the input resources
192-
List<URI> outputResourceURIs = new ArrayList<>();
193-
Set<URI> unconvertedResourceURIs= new LinkedHashSet<>(inputResourceURIs);
194-
while (!unconvertedResourceURIs.isEmpty()) {
195-
List<URI> uris = new ArrayList<URI>(unconvertedResourceURIs);
196-
for (URI uri : uris) {
197-
Resource inputResource = inputResourceSet.getResource(uri, true);
198-
Ecore2Oml e2o = new Ecore2Oml(inputFolder, inputResource, outputFolder, outputFileExtension, builder);
199-
Set<URI> newURIs = e2o.run();
200-
assert (!outputResourceURIs.removeAll(newURIs));
201-
outputResourceURIs.addAll(newURIs);
202-
unconvertedResourceURIs.addAll(e2o.getImportedURIs());
203-
}
204-
unconvertedResourceURIs.removeAll(uris);
215+
for (URI uri : inputResourceURIs) {
216+
Resource inputResource = inputResourceSet.getResource(uri, true);
217+
Ecore2Oml e2o = new Ecore2Oml(inputResource, builder, options);
218+
e2o.run();
205219
}
206-
220+
221+
// get the output resources to save
222+
List<Resource> outputResources = new ArrayList<>(builder.getResourceSet().getResources());
223+
207224
// finish the Oml builder
208225
builder.finish();
209226

210227
// save the output resources here instead of calling builder.save in order to log
211-
for (URI outputResourceURI : outputResourceURIs) {
212-
if (outputResourceURI.fileExtension().equals("oml")) {
213-
LOGGER.info("Saving: "+outputResourceURI);
214-
final Resource outputResource = outputResourceSet.getResource(outputResourceURI, false);
228+
for (Resource outputResource : outputResources) {
229+
if (outputResource.getURI().fileExtension().equals("oml")) {
230+
LOGGER.info("Saving: "+outputResource.getURI());
215231
outputResource.save(Collections.EMPTY_MAP);
216232
}
217233
}
@@ -230,7 +246,7 @@ private ResourceSet createInputResourceSet() {
230246

231247
// load any referenced Ecore files
232248
EPackage.Registry packageRegistry = injector.getInstance(EPackage.Registry.class);
233-
for (String path : referencedEcorePaths) {
249+
for (String path : options.referencedEcorePaths) {
234250
final URI inputURI = URI.createFileURI(path);
235251
Resource inputResource = resourceSet.getResource(inputURI, true);
236252
if (inputResource != null) {
@@ -340,4 +356,21 @@ public void validate(final String name, final String value) throws ParameterExce
340356
}
341357
}
342358

359+
/**
360+
* A parameter validator for namespace mappings
361+
*/
362+
public static class NamespaceMapping implements IParameterValidator {
363+
/**
364+
* Creates a new NamespaceMapping object
365+
*/
366+
public NamespaceMapping() {
367+
}
368+
@Override
369+
public void validate(final String name, final String value) throws ParameterException {
370+
var parts = value.split("=");
371+
if (parts.length != 2) {
372+
throw new ParameterException((("Parameter " + name) + " does not follow the syntax oldNs=newNs"));
373+
}
374+
}
375+
}
343376
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
package io.opencaesar.ecore2oml;
2+
3+
import java.util.ArrayList;
4+
import java.util.Iterator;
5+
import java.util.LinkedHashMap;
6+
import java.util.LinkedHashSet;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Set;
10+
import java.util.stream.Collectors;
11+
12+
import org.eclipse.emf.ecore.EAnnotation;
13+
import org.eclipse.emf.ecore.EAttribute;
14+
import org.eclipse.emf.ecore.EClass;
15+
import org.eclipse.emf.ecore.ENamedElement;
16+
import org.eclipse.emf.ecore.EObject;
17+
import org.eclipse.emf.ecore.EReference;
18+
import org.eclipse.emf.ecore.EStructuralFeature;
19+
import org.eclipse.emf.ecore.resource.Resource;
20+
21+
class EcoreUtilities {
22+
23+
// Ecore annotation namespaces
24+
private static final String EXTENDED_META_DATA_IRI = "http:///org/eclipse/emf/ecore/util/ExtendedMetaData";
25+
private static final String GEN_MODEL_IRI = "http://www.eclipse.org/emf/2002/GenModel";
26+
27+
// Ecore metamodel namespaces
28+
private static final String Ecore_IRI = "http://www.eclipse.org/emf/2002/Ecore";
29+
30+
public static String getExtendedMetadataProperty(ENamedElement object, String property) {
31+
final EAnnotation annotation = object.getEAnnotation(EXTENDED_META_DATA_IRI);
32+
return (annotation == null) ? null : annotation.getDetails().get(property);
33+
}
34+
35+
public static String getGenModelProperty(ENamedElement object, String property) {
36+
EAnnotation annotation = object.getEAnnotation(GEN_MODEL_IRI);
37+
return (annotation == null) ? null : annotation.getDetails().get(property);
38+
}
39+
40+
public static String getEcoreProperty(String property) {
41+
return getEcoreNamespace()+property;
42+
}
43+
44+
public static String getEcoreNamespace() {
45+
return Ecore_IRI+"#";
46+
}
47+
48+
public static boolean isAbstract(EClass object) {
49+
return (object.isAbstract() || object.isInterface()) &&
50+
object.getESuperTypes().stream().allMatch(i -> isAbstract(i));
51+
}
52+
53+
public static Set<EAttribute> getSuperEAttributes(EAttribute object) {
54+
Set<EAttribute> superRefs = new LinkedHashSet<EAttribute>() ;
55+
EAnnotation ann = object.getEAnnotation("subsets");
56+
if (ann != null) {
57+
for (EObject ref : ann.getReferences()) {
58+
superRefs.add((EAttribute)ref);
59+
}
60+
}
61+
ann = object.getEAnnotation("redefines");
62+
if (ann != null) {
63+
for (EObject ref : ann.getReferences()) {
64+
superRefs.add((EAttribute)ref);
65+
}
66+
}
67+
return superRefs;
68+
}
69+
70+
public static Set<EReference> getSuperEReferences(EReference object) {
71+
Set<EReference> superRefs = new LinkedHashSet<EReference>() ;
72+
EAnnotation ann = object.getEAnnotation("subsets");
73+
if (ann != null) {
74+
for (EObject ref : ann.getReferences()) {
75+
superRefs.add((EReference)ref);
76+
}
77+
}
78+
ann = object.getEAnnotation("redefines");
79+
if (ann != null) {
80+
for (EObject ref : ann.getReferences()) {
81+
superRefs.add((EReference)ref);
82+
}
83+
}
84+
return superRefs;
85+
}
86+
87+
public static Set<EStructuralFeature> getSuperEStructuralFeatures(EStructuralFeature object) {
88+
Set<EStructuralFeature> supers = new LinkedHashSet<EStructuralFeature>() ;
89+
if (object instanceof EAttribute) {
90+
supers.addAll(getSuperEAttributes((EAttribute)object));
91+
} else if (object instanceof EReference) {
92+
supers.addAll(getSuperEReferences((EReference)object));
93+
}
94+
return supers;
95+
}
96+
97+
/**
98+
* ERelation Builder
99+
*/
100+
public static class ERelationBuilder {
101+
102+
private Map<EReference, ERelation> eRelations = new LinkedHashMap<>();
103+
104+
private List<Set<ERelation>> eRelationGroups = new ArrayList<>();
105+
106+
public class ERelation {
107+
public Set<ERelation> supers = new LinkedHashSet<>();
108+
public Set<ERelation> subs = new LinkedHashSet<>();
109+
public List<EReference> ends = new ArrayList<>();
110+
public EReference forward;
111+
public EReference reverse;
112+
@Override
113+
public String toString() {
114+
Iterator<EReference> i = ends.iterator();
115+
String name = (i.hasNext()) ? getRelationName(i.next()) + "_" : "";
116+
name = name + ((i.hasNext()) ? getRelationName(i.next()) + "_" : "");
117+
name += "A";
118+
return name;
119+
}
120+
}
121+
122+
public ERelationBuilder() {
123+
}
124+
125+
public void build(Resource inputResource) {
126+
// create eRelations
127+
var i = inputResource.getAllContents();
128+
while (i.hasNext()) {
129+
EObject o = i.next();
130+
if (o instanceof EClass) {
131+
EClass c = (EClass)o;
132+
for(EReference e : c.getEReferences()) {
133+
getERelation(e);
134+
}
135+
}
136+
}
137+
// remove redundant eRelation super types
138+
for (ERelation a : eRelations.values()) {
139+
removeRedundantSupers(a);
140+
}
141+
// calculate disjoint eRelation groups
142+
for (ERelation a : eRelations.values()) {
143+
putInERelationGroup(a, null);
144+
}
145+
146+
// determine the forward ends consistently within each group
147+
for (Set<ERelation> g : eRelationGroups) {
148+
fixOrderOfEndsInGroup(g);
149+
}
150+
}
151+
152+
public ERelation get(EReference eRef) {
153+
return eRelations.get(eRef);
154+
}
155+
156+
private void removeRedundantSupers(ERelation a) {
157+
Map<ERelation, Set<ERelation>> superMap = new LinkedHashMap<>();
158+
a.supers.forEach(i -> superMap.put(i, getAllSupers(i)));
159+
Set<ERelation> redundants = new LinkedHashSet<>();
160+
Iterator<ERelation> i = a.supers.iterator();
161+
while (i.hasNext()) {
162+
ERelation superAss = i.next();
163+
for (ERelation s : a.supers) {
164+
if (superMap.get(s).contains(superAss)) {
165+
redundants.add(superAss);
166+
}
167+
};
168+
}
169+
a.supers.removeAll(redundants);
170+
}
171+
172+
private Set<ERelation> getAllSupers(ERelation a) {
173+
Set<ERelation> allSupers = new LinkedHashSet<>();
174+
for (ERelation superAss : a.supers) {
175+
allSupers.add(superAss);
176+
allSupers.addAll(getAllSupers(superAss));
177+
}
178+
return allSupers;
179+
}
180+
181+
private ERelation getERelation(EReference e) {
182+
if (!eRelations.containsKey(e)) {
183+
ERelation a = new ERelation();
184+
eRelations.put(e, a);
185+
a.ends.add(e);
186+
for (EReference superRef : getSuperEReferences(e)) {
187+
ERelation superAss = getERelation(superRef);
188+
a.supers.add(superAss);
189+
superAss.subs.add(a);
190+
}
191+
if (e.getEOpposite() != null) {
192+
EReference o = e.getEOpposite();
193+
eRelations.put(o, a);
194+
a.ends.add(o);
195+
for (EReference superRef : getSuperEReferences(o)) {
196+
ERelation superAss = getERelation(superRef);
197+
a.supers.add(superAss);
198+
superAss.subs.add(a);
199+
}
200+
}
201+
}
202+
return eRelations.get(e);
203+
}
204+
205+
private void putInERelationGroup(ERelation a, Set<ERelation> group) {
206+
if (group == null) {
207+
for (Set<ERelation> g : eRelationGroups) {
208+
if (g.contains(a)) {
209+
return;
210+
}
211+
}
212+
group = new LinkedHashSet<>();
213+
eRelationGroups.add(group);
214+
}
215+
if (!group.contains(a)) {
216+
group.add(a);
217+
for (ERelation s : a.supers) {
218+
putInERelationGroup(s, group);
219+
};
220+
for (ERelation s : a.subs) {
221+
putInERelationGroup(s, group);
222+
};
223+
}
224+
}
225+
226+
private void fixOrderOfEndsInGroup(Set<ERelation> group) {
227+
// find the root of inheritance
228+
Set<ERelation> roots = group.stream()
229+
.filter(a -> a.supers.isEmpty())
230+
.collect(Collectors.toCollection(LinkedHashSet::new));
231+
232+
// find the first clear forward from the roots
233+
EReference forward = roots.stream()
234+
.map(a -> a.ends.iterator())
235+
.map(i -> getPreferredForward(i.next(), (i.hasNext()? i.next() : null)))
236+
.filter(i -> i != null)
237+
.findFirst()
238+
.orElse(group.iterator().next().ends.iterator().next());
239+
240+
//set the forwards consistently throughout the group
241+
ERelation a = eRelations.get(forward);
242+
a.forward = forward;
243+
a.reverse = forward.getEOpposite();
244+
a.subs.forEach(s -> setForwardSub(s, a));
245+
}
246+
247+
private void setForwardSub(ERelation ass, ERelation superAss) {
248+
if (ass.forward == null && ass.reverse == null) {
249+
Iterator<EReference> i = ass.ends.iterator();
250+
EReference ref1 = i.next();
251+
EReference ref2 = ref1.getEOpposite();
252+
if ((ref1 != null && superAss.forward != null && getSuperEReferences(ref1).contains(superAss.forward)) ||
253+
(ref2 != null && superAss.reverse != null && getSuperEReferences(ref2).contains(superAss.reverse))) {
254+
ass.forward = ref1;
255+
ass.reverse = ref1.getEOpposite();
256+
} else {
257+
ass.forward = ref1.getEOpposite();
258+
ass.reverse = ref1;
259+
}
260+
ass.subs.forEach(s -> setForwardSub(s, ass));
261+
ass.supers.forEach(s -> setForwardSuper(s, ass));
262+
}
263+
}
264+
265+
private void setForwardSuper(ERelation ass, ERelation subAss) {
266+
if (ass.forward == null && ass.reverse == null) {
267+
Iterator<EReference> i = ass.ends.iterator();
268+
EReference ref1 = i.next();
269+
EReference ref2 = ref1.getEOpposite();
270+
if ((ref1 != null && subAss.forward != null && getSuperEReferences(subAss.forward).contains(ref1)) ||
271+
(ref2 != null && subAss.reverse != null && getSuperEReferences(subAss.reverse).contains(ref2))) {
272+
ass.forward = ref1;
273+
ass.reverse = ref1.getEOpposite();
274+
} else {
275+
ass.forward = ref1.getEOpposite();
276+
ass.reverse = ref1;
277+
}
278+
ass.subs.forEach(s -> setForwardSub(s, ass));
279+
ass.supers.forEach(s -> setForwardSuper(s, ass));
280+
}
281+
}
282+
283+
private EReference getPreferredForward(EReference ref1, EReference ref2) {
284+
EReference one = null;
285+
if (ref2 == null) {
286+
one = ref1;
287+
} else {
288+
// container wins
289+
if (ref1.isContainment() && !ref2.isContainment()) {
290+
one = ref1;
291+
} else if (ref2.isContainment() && !ref1.isContainment()) {
292+
one = ref2;
293+
}
294+
// higher multiplicity wins
295+
if (one == null) {
296+
int ref1Upper = (ref1.getUpperBound() == -1) ? Integer.MAX_VALUE : ref1.getUpperBound();
297+
int ref2Upper = (ref2.getUpperBound() == -1) ? Integer.MAX_VALUE : ref2.getUpperBound();
298+
if (ref1Upper > ref2Upper) {
299+
one = ref1;
300+
} else if (ref2Upper > ref1Upper) {
301+
one = ref2;
302+
}
303+
}
304+
// higher alphabetical wins
305+
//if (one == null) {
306+
//one = ref1.getName().compareTo(ref2.getName()) > 0 ? ref1 : ref2;
307+
//}
308+
}
309+
assert (one == null);
310+
return one;
311+
}
312+
313+
private String getRelationName(EReference object) {
314+
return object.getEContainingClass().getName() + "_" + object.getName();
315+
}
316+
}
317+
}

0 commit comments

Comments
 (0)
Please sign in to comment.