Skip to content

Commit 3cc3c8f

Browse files
committed
EDIT: Implemented generator patter for more adaptive list setters.
1 parent 1f4d2cc commit 3cc3c8f

4 files changed

Lines changed: 107 additions & 93 deletions

File tree

src/main/java/jce/generators/WrapperGenerator.xtend

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import static jce.properties.TextProperty.WRAPPER_PACKAGE
2020
*/
2121
final class WrapperGenerator extends ClassGenerator {
2222
IJavaProject javaProject
23+
GeneratedEcoreMetamodel metamodel
2324

2425
/**
2526
* Basic constructor, sets the properties.
@@ -36,6 +37,7 @@ final class WrapperGenerator extends ClassGenerator {
3637
def void buildWrappers(GeneratedEcoreMetamodel metamodel, IProject project) {
3738
logger.info("Starting the wrapper generation...")
3839
this.javaProject = JavaCore.create(project)
40+
this.metamodel = metamodel
3941
createFolder(wrapperFolder, project) // build wrapper base folder
4042
buildWrappers(metamodel.root, "")
4143
ResourceRefresher.refresh(project, SOURCE_FOLDER.get) // makes wrappers visible in the Eclipse IDE
@@ -80,7 +82,7 @@ final class WrapperGenerator extends ClassGenerator {
8082
* Creates a Xtend Wrapper in a package path with a specific name.
8183
*/
8284
def private void createXtendWrapper(EClass eClass, String path) {
83-
val wrapper = new WrapperRepresentation(eClass, javaProject, properties) // build wrapper representation
85+
val wrapper = new WrapperRepresentation(eClass, javaProject, metamodel.intermediateModel, properties) // build wrapper representation
8486
val wrapperPath = append(WRAPPER_PACKAGE.get, path) // add wrapper prefix
8587
createClass(wrapperPath, '''«wrapper.name».xtend''', wrapper.content, javaProject.project) // create wrapper
8688
}

src/main/java/jce/generators/WrapperRepresentation.xtend

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ import static jce.properties.TextProperty.WRAPPER_SUFFIX
1919
import org.eclipse.emf.ecore.InternalEObject
2020
import org.eclipse.emf.ecore.EObject
2121
import org.eclipse.emf.common.notify.Notifier
22+
import jce.util.IntermediateModelSearcher
23+
import eme.model.IntermediateModel
24+
import org.eclipse.emf.ecore.EStructuralFeature
2225

2326
/**
2427
* This class models a wrapper class which unifies an origin code type with its Ecore counterparts in the Ecore model
@@ -29,41 +32,28 @@ class WrapperRepresentation {
2932
extension PathHelper nameUtil
3033
extension EcorificationProperties properties
3134

32-
final String packageName
33-
final String superClass
35+
String packageName
36+
String superClass
3437
final EClass eClass
35-
final String wrapperName
36-
final String factoryName
37-
final List<TypeParameterRepresentation> typeParameters
38-
final List<ConstructorRepresentation> wrapperConstructors
39-
final Set<String> importDeclarations
40-
final String ecoreInterface
41-
final String ecoreImplementation
38+
String wrapperName
39+
String factoryName
40+
List<TypeParameterRepresentation> typeParameters
41+
List<ConstructorRepresentation> wrapperConstructors
42+
Set<String> importDeclarations
43+
String ecoreInterface
44+
String ecoreImplementation
45+
final IntermediateModel model
4246

4347
/**
4448
* Creates a new wrapper representation from an EClass and the EcorificationProperties. The EClass specifies which
4549
* types are unified. The properties specify the employed naming scheme.
4650
*/
47-
new(EClass eClass, IJavaProject project, EcorificationProperties properties) {
51+
new(EClass eClass, IJavaProject project, IntermediateModel model, EcorificationProperties properties) {
4852
this.eClass = eClass
53+
this.model = model
4954
this.properties = properties
5055
nameUtil = new PathHelper('.')
51-
packageName = getPackage(eClass)
52-
wrapperName = WRAPPER_PREFIX.get + eClass.name + WRAPPER_SUFFIX.get // name of the wrapper class
53-
factoryName = '''«PathHelper.capitalize(packageName.getLastSegment)»Factory«FACTORY_SUFFIX.get»'''
54-
superClass = getSuperClassName(eClass)
55-
wrapperConstructors = ConstructorGenerator.generate(superClass, project, properties)
56-
ecoreInterface = append(ECORE_PACKAGE.get, packageName, eClass.name)
57-
ecoreImplementation = append(ECORE_PACKAGE.get, packageName, "impl", eClass.name + "Impl")
58-
typeParameters = TypeParameterGenerator.generate(eClass.ETypeParameters, ecoreImplementation, project, properties)
59-
importDeclarations = new HashSet // add import declarations:
60-
if(superClass === null) {
61-
importDeclarations += InternalEObject.name
62-
importDeclarations += EObject.name
63-
importDeclarations += Notifier.name
64-
}
65-
wrapperConstructors.forEach[constructor|importDeclarations.addAll(constructor.imports)]
66-
typeParameters.forEach[parameter|importDeclarations.addAll(parameter.imports)]
56+
createContent(project) // creates the important parts
6757
}
6858

6959
/**
@@ -109,6 +99,25 @@ class WrapperRepresentation {
10999
def String getPackage() {
110100
return packageName
111101
}
102+
103+
def private createContent(IJavaProject project) {
104+
packageName = getPackage(eClass)
105+
wrapperName = WRAPPER_PREFIX.get + eClass.name + WRAPPER_SUFFIX.get // name of the wrapper class
106+
factoryName = '''«PathHelper.capitalize(packageName.getLastSegment)»Factory«FACTORY_SUFFIX.get»'''
107+
superClass = getSuperClassName(eClass)
108+
wrapperConstructors = ConstructorGenerator.generate(superClass, project, properties)
109+
ecoreInterface = append(ECORE_PACKAGE.get, packageName, eClass.name)
110+
ecoreImplementation = append(ECORE_PACKAGE.get, packageName, "impl", eClass.name + "Impl")
111+
typeParameters = TypeParameterGenerator.generate(eClass.ETypeParameters, ecoreImplementation, project, properties)
112+
importDeclarations = new HashSet // add import declarations:
113+
if(superClass === null) {
114+
importDeclarations += InternalEObject.name
115+
importDeclarations += EObject.name
116+
importDeclarations += Notifier.name
117+
}
118+
wrapperConstructors.forEach[constructor|importDeclarations.addAll(constructor.imports)]
119+
typeParameters.forEach[parameter|importDeclarations.addAll(parameter.imports)]
120+
}
112121
113122
/**
114123
* Builds the super type declaration of a wrapper from a String that is either the super type or null.
@@ -196,16 +205,23 @@ class WrapperRepresentation {
196205
* Returns a special setter for every field which was extracted using multiplicities.
197206
*/
198207
def private String getSpecialSetters() '''
199-
«FOR field : eClass.EStructuralFeatures»
208+
«FOR field : eClass.EStructuralFeatures SEPARATOR blankLine»
200209
«IF field.upperBound == -1»
201-
def protected void set«field.name.toFirstUpper» (List «field.name») {
210+
def protected void set«field.name.toFirstUpper» (ListgetGenericArguments(field)»> «field.name») {
202211
get«field.name.toFirstUpper».clear
203212
get«field.name.toFirstUpper».addAll(«field.name»)
204213
}
205-
206214
«ENDIF»
207215
«ENDFOR»
208216
''' // TODO (HIGH) replace raw type parameter and add imports
217+
218+
def private String getGenericArguments(EStructuralFeature feature) {
219+
var String result = ""
220+
for (argument : IntermediateModelSearcher.findField(feature, model).genericArguments) {
221+
result += argument.typeString
222+
}
223+
return result
224+
}
209225
210226
/**
211227
* Returns the fully qualified name of the super class of an EClass.

src/main/java/jce/util/EcoreToJavaUtil.xtend

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package jce.util
2+
3+
import eme.model.IntermediateModel
4+
import org.eclipse.emf.ecore.EClass
5+
import org.eclipse.emf.ecore.EStructuralFeature
6+
import eme.model.ExtractedType
7+
import eme.model.datatypes.ExtractedField
8+
import org.eclipse.emf.ecore.ETypeParameter
9+
import eme.model.datatypes.ExtractedTypeParameter
10+
import org.eclipse.emf.ecore.EPackage
11+
12+
/**
13+
* Utility for finding the counterparts of Ecore elements in an intermediate model.
14+
*/
15+
final class IntermediateModelSearcher {
16+
17+
private new() {
18+
throw new AssertionError("Suppress default constructor for noninstantiability")
19+
}
20+
21+
/**
22+
* Finds the correlating ExtractedType of an EClass in an intermediate model.
23+
*/
24+
def static ExtractedType findType(EClass eClass, IntermediateModel model) {
25+
val PathHelper helper = new PathHelper('.')
26+
var String fullyQualifiedName = ""
27+
var EPackage current = eClass.EPackage
28+
while (current !== null) { // iterate through package hierarchy
29+
fullyQualifiedName = helper.append(current.name, fullyQualifiedName) // concatenate package with super package name
30+
current = current.ESuperPackage
31+
}
32+
fullyQualifiedName = helper.append(helper.cutFirstSegment(fullyQualifiedName), eClass.name) // cut Ecore package name
33+
return model.getType(fullyQualifiedName);
34+
}
35+
36+
/**
37+
* Finds the correlating ExtractedField of an EStructuralFeature in an intermediate model.
38+
*/
39+
def static ExtractedField findField(EStructuralFeature feature, IntermediateModel model) {
40+
for (field : findType(feature.EContainingClass, model)?.fields) { // find correlating extracted class
41+
if (field.identifier.equals(feature.name)) { // find correlating extracted field
42+
return field
43+
}
44+
}
45+
return null
46+
}
47+
48+
/**
49+
* Finds the correlating ExtractedTypeParameter of an ETypeParameter in an intermediate model.
50+
*/
51+
def static ExtractedTypeParameter findTypeParameter(ETypeParameter eTypeParameter, EClass eClass, IntermediateModel model) {
52+
for (parameter : findType(eClass, model)?.typeParameters) {
53+
if (parameter.identifier.equals(eTypeParameter.name)) {
54+
return parameter
55+
}
56+
}
57+
return null
58+
}
59+
}

0 commit comments

Comments
 (0)