blob: daf729349fc0a0a85b728f489766d6212cc73088 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 RCP Vision (http://www.rcp-vision.com) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Lorenzo Bettini - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.parsley.dsl.jvmmodel
import com.google.inject.Inject
import com.google.inject.Provider
import java.util.List
import org.eclipse.core.databinding.DataBindingContext
import org.eclipse.core.databinding.observable.value.IObservableValue
import org.eclipse.emf.common.notify.AdapterFactory
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EStructuralFeature
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider
import org.eclipse.emf.parsley.EmfParsleyGuiceModule
import org.eclipse.emf.parsley.binding.DialogControlFactory
import org.eclipse.emf.parsley.binding.FormControlFactory
import org.eclipse.emf.parsley.binding.ProposalCreator
import org.eclipse.emf.parsley.dsl.model.AbstractControlFactory
import org.eclipse.emf.parsley.dsl.model.AbstractFeatureCaptionProviderWithLabel
import org.eclipse.emf.parsley.dsl.model.AbstractFeatureProvider
import org.eclipse.emf.parsley.dsl.model.BindingsSpecification
import org.eclipse.emf.parsley.dsl.model.ControlFactorySpecification
import org.eclipse.emf.parsley.dsl.model.FeatureAssociatedExpression
import org.eclipse.emf.parsley.dsl.model.LabelSpecification
import org.eclipse.emf.parsley.dsl.model.Module
import org.eclipse.emf.parsley.dsl.model.ProviderBinding
import org.eclipse.emf.parsley.dsl.model.TypeBinding
import org.eclipse.emf.parsley.dsl.model.ValueBinding
import org.eclipse.emf.parsley.dsl.model.WithExtendsClause
import org.eclipse.emf.parsley.dsl.model.WithFields
import org.eclipse.emf.parsley.edit.action.EditingMenuBuilder
import org.eclipse.emf.parsley.edit.action.IMenuContributionSpecification
import org.eclipse.emf.parsley.edit.ui.provider.ViewerContentProvider
import org.eclipse.emf.parsley.ui.provider.DialogFeatureCaptionProvider
import org.eclipse.emf.parsley.ui.provider.EClassToEStructuralFeatureAsStringsMap
import org.eclipse.emf.parsley.ui.provider.FeatureCaptionProvider
import org.eclipse.emf.parsley.ui.provider.FeaturesProvider
import org.eclipse.emf.parsley.ui.provider.FormFeatureCaptionProvider
import org.eclipse.emf.parsley.ui.provider.TableColumnLabelProvider
import org.eclipse.emf.parsley.ui.provider.TableFeaturesProvider
import org.eclipse.emf.parsley.ui.provider.ViewerLabelProvider
import org.eclipse.jface.viewers.IContentProvider
import org.eclipse.jface.viewers.ILabelProvider
import org.eclipse.swt.widgets.Composite
import org.eclipse.swt.widgets.Control
import org.eclipse.swt.widgets.Label
import org.eclipse.ui.plugin.AbstractUIPlugin
import org.eclipse.xtext.common.types.JvmAnnotationTarget
import org.eclipse.xtext.common.types.JvmDeclaredType
import org.eclipse.xtext.common.types.JvmExecutable
import org.eclipse.xtext.common.types.JvmGenericType
import org.eclipse.xtext.common.types.JvmOperation
import org.eclipse.xtext.common.types.JvmTypeReference
import org.eclipse.xtext.common.types.JvmVisibility
import org.eclipse.xtext.common.types.TypesFactory
import org.eclipse.xtext.common.types.util.TypeReferences
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.util.IAcceptor
import org.eclipse.xtext.xbase.XExpression
import org.eclipse.xtext.xbase.annotations.xAnnotations.XAnnotation
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
/**
* <p>Infers a JVM model from the source model.</p>
*
* <p>The JVM model should contain all elements that would appear in the Java code
* which is generated from the source model. Other models link against the JVM model rather than the source model.</p>
*/
class EmfParsleyDslJvmModelInferrer extends AbstractModelInferrer {
/**
* convenience API to build and initialize JVM types and their members.
*/
@Inject extension JvmTypesBuilder
@Inject extension IQualifiedNameProvider
@Inject extension TypeReferences
@Inject extension TypesFactory
@Inject extension GeneratorUtils
/**
* The dispatch method {@code infer} is called for each instance of the
* given element's type that is contained in a resource.
*
* @param element
* the model to create one or more
* {@link JvmDeclaredType declared
* types} from.
* @param acceptor
* each created
* {@link JvmDeclaredType type}
* without a container should be passed to the acceptor in order
* get attached to the current resource. The acceptor's
* {@link IJvmDeclaredTypeAcceptor#accept(org.eclipse.xtext.common.types.JvmDeclaredType)
* accept(..)} method takes the constructed empty type for the
* pre-indexing phase. This one is further initialized in the
* indexing phase using the closure you pass as the last argument.
* @param isPreIndexingPhase
* whether the method is called in a pre-indexing phase, i.e.
* when the global index is not yet fully updated. You must not
* rely on linking using the index if isPreIndexingPhase is
* <code>true</code>.
*/
def dispatch void infer(Module element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
if (element.name.empty)
return
val moduleClass = element.toClass(element.moduleQN)
val labelProviderClass = element.inferLabelProvider(acceptor)
val tableLabelProviderClass = element.inferTableLabelProvider(acceptor)
val featureCaptionProviderClass = element.inferFeatureCaptionProvider(acceptor)
val formFeatureCaptionProviderClass = element.inferFormFeatureCaptionProvider(acceptor)
val dialogFeatureCaptionProviderClass = element.inferDialogFeatureCaptionProvider(acceptor)
val featureProviderClass = element.inferFeatureProvider(acceptor)
val tableFeatureProviderClass = element.inferTableFeatureProvider(acceptor)
val formControlFactoryClass = element.inferFormControlFactory(acceptor)
val dialogControlFactoryClass = element.inferDialogControlFactory(acceptor)
val viewerContentProviderClass = element.inferViewerContentProvider(acceptor)
val proposalCreatorClass = element.inferProposalCreator(acceptor)
val menuBuilderClass = element.inferMenuBuilder(acceptor)
acceptor.accept(moduleClass) [
documentation = element.documentation
moduleClass.setSuperClassType(element, typeof(EmfParsleyGuiceModule))
members += element.toConstructor() [
parameters += element.toParameter("plugin", typeRef(AbstractUIPlugin))
body = [it.append("super(plugin);")]
]
val bindingsSpecification = element.bindingsSpecification
if (element.bindingsSpecification != null) {
handleBindingsSpecification(it, bindingsSpecification)
}
if (labelProviderClass != null)
members += element.labelProvider.genBindMethod(labelProviderClass, typeof(ILabelProvider))
if (tableLabelProviderClass != null)
members += element.tableLabelProvider.genBindMethod(tableLabelProviderClass, typeof(TableColumnLabelProvider)
)
if (featureCaptionProviderClass != null)
members += element.featureCaptionProvider.genBindMethod(featureCaptionProviderClass, typeof(FeatureCaptionProvider))
if (formFeatureCaptionProviderClass != null)
members += element.formFeatureCaptionProvider.genBindMethod(formFeatureCaptionProviderClass, typeof(FormFeatureCaptionProvider))
if (dialogFeatureCaptionProviderClass != null)
members += element.dialogFeatureCaptionProvider.genBindMethod(dialogFeatureCaptionProviderClass, typeof(DialogFeatureCaptionProvider))
if (featureProviderClass != null)
members += element.featuresProvider.genBindMethod(featureProviderClass, typeof(FeaturesProvider))
if (tableFeatureProviderClass != null)
members += element.tableFeaturesProvider.genBindMethod(tableFeatureProviderClass, typeof(TableFeaturesProvider))
if (formControlFactoryClass != null)
members += element.formControlFactory.genBindMethod(formControlFactoryClass, typeof(FormControlFactory))
if (dialogControlFactoryClass != null)
members += element.dialogControlFactory.genBindMethod(dialogControlFactoryClass, typeof(DialogControlFactory))
if (viewerContentProviderClass != null)
members += element.viewerContentProvider.genBindMethod(viewerContentProviderClass, typeof(IContentProvider))
if (proposalCreatorClass != null)
members += element.proposalCreator.genBindMethod(proposalCreatorClass, typeof(ProposalCreator))
if (menuBuilderClass != null)
members += element.menuBuilder.genBindMethod(menuBuilderClass, typeof(EditingMenuBuilder))
]
}
def private setSuperClassType(JvmGenericType e, WithExtendsClause dslElement, Class<?> defaultSuperClass) {
if (dslElement.extendsClause != null)
e.superTypes += dslElement.extendsClause.superType.cloneWithProxies
else
e.superTypes += typeRef(defaultSuperClass)
}
def private setSuperClassTypeAndFields(JvmGenericType e, WithFields dslElement, Class<?> defaultSuperClass) {
e.setSuperClassType(dslElement, defaultSuperClass)
e.processFields(dslElement)
}
def private processFields(JvmGenericType it, WithFields dslElement) {
for (f : dslElement.fields) {
var type = f.type
val name = f.name
val initialExp = f.right
members += f.toField(name, type) => [
final = !f.writeable
visibility = JvmVisibility.PRIVATE
translateAnnotations(f.annotations)
if (f.extension) {
annotations += annotationRef(Extension)
}
initializer = initialExp
]
members += f.toGetter(name, type)
if (f.writeable) {
members += f.toSetter(name, type)
}
}
}
def private void translateAnnotations(JvmAnnotationTarget target, List<XAnnotation> annotations) {
target.addAnnotations(annotations.filterNull.filter[annotationType != null])
}
def private moduleQN(Module element) {
element.fullyQualifiedName + ".EmfParsleyGuiceModuleGen"
}
def private labelProviderQN(Module element) {
element.fullyQualifiedName + ".ui.provider.LabelProviderGen"
}
def private tableLabelProviderQN(Module element) {
element.fullyQualifiedName + ".ui.provider.TableLabelProviderGen"
}
def private featureCaptionProviderQN(Module element) {
element.fullyQualifiedName + ".ui.provider.FeatureCaptionProviderGen"
}
def private formFeatureCaptionProviderQN(Module element) {
element.fullyQualifiedName + ".ui.provider.FormFeatureCaptionProviderGen"
}
def private dialogFeatureCaptionProviderQN(Module element) {
element.fullyQualifiedName + ".ui.provider.DialogFeatureCaptionProviderGen"
}
def private featuresProviderQN(Module element) {
element.fullyQualifiedName + ".ui.provider.FeaturesProviderGen"
}
def private tableFeaturesProviderQN(Module element) {
element.fullyQualifiedName + ".ui.provider.TableFeaturesProviderGen"
}
def private formControlFactoryQN(Module element) {
element.fullyQualifiedName + ".binding.FormControlFactoryGen"
}
def private dialogControlFactoryQN(Module element) {
element.fullyQualifiedName + ".binding.DialogControlFactoryGen"
}
def private viewerContentProviderQN(Module element) {
element.fullyQualifiedName + ".edit.ui.provider.ViewerContentProviderGen"
}
def private proposalCreatorQN(Module element) {
element.fullyQualifiedName + ".binding.ProposalCreatorGen"
}
def private menuBuilderQN(Module element) {
element.fullyQualifiedName + ".edit.action.MenuBuilderGen"
}
def private inferLabelProvider(Module element, IJvmDeclaredTypeAcceptor acceptor) {
if (element.labelProvider == null)
null
else {
val labelProvider = element.labelProvider
val labelProviderClass = labelProvider.toClass(element.labelProviderQN)
acceptor.accept(labelProviderClass) [
setSuperClassTypeAndFields(labelProvider, typeof(ViewerLabelProvider))
members += labelProvider.toConstructor() [
parameters += labelProvider.
toParameter("delegate",
typeRef(AdapterFactoryLabelProvider)
)
body = [it.append("super(delegate);")]
annotations += annotationRef(Inject)
]
for (labelSpecification : labelProvider.labelSpecifications) {
members += labelSpecification.specificationToMethod("text", typeRef(String))
}
for (imageSpecification : labelProvider.imageSpecifications) {
members += imageSpecification.specificationToMethod("image", typeRef(Object))
}
]
labelProviderClass
}
}
def private inferTableLabelProvider(Module element, IJvmDeclaredTypeAcceptor acceptor) {
if (element.tableLabelProvider == null)
null
else {
val tableLabelProvider = element.tableLabelProvider
val tableLabelProviderClass = tableLabelProvider.toClass(element.tableLabelProviderQN)
acceptor.accept(tableLabelProviderClass) [
setSuperClassTypeAndFields(tableLabelProvider, typeof(TableColumnLabelProvider))
for (labelSpecification : tableLabelProvider.labelSpecifications) {
if (labelSpecification.feature?.simpleName != null) {
members += labelSpecification.toMethod("text_" +
labelSpecification.parameterType.simpleName + "_" +
labelSpecification.feature.simpleName.propertyNameForGetterSetterMethod
, typeRef(String)
) [
parameters += labelSpecification.toParameter(
"it"
, labelSpecification.parameterType
)
body = labelSpecification.expression
]
}
}
for (imageSpecification : tableLabelProvider.imageSpecifications) {
if (imageSpecification.feature?.simpleName != null) {
members += imageSpecification.toMethod("image_" +
imageSpecification.parameterType.simpleName + "_" +
imageSpecification.feature.simpleName.propertyNameForGetterSetterMethod
, typeRef(Object)) [
parameters += imageSpecification.toParameter(
"it"
, imageSpecification.parameterType
)
body = imageSpecification.expression
]
}
}
]
tableLabelProviderClass
}
}
def private inferFeatureCaptionProvider(Module element, IJvmDeclaredTypeAcceptor acceptor) {
if (element.featureCaptionProvider == null)
null
else {
val featureCaptionProvider = element.featureCaptionProvider
val propertyDescriptionProviderClass = featureCaptionProvider.toClass(element.featureCaptionProviderQN)
acceptor.accept(propertyDescriptionProviderClass) [
setSuperClassTypeAndFields(featureCaptionProvider, typeof(FeatureCaptionProvider))
inferMethodsForTextCaptionSpecifications(element, it, featureCaptionProvider.specifications)
]
propertyDescriptionProviderClass
}
}
def private inferFormFeatureCaptionProvider(Module element, IJvmDeclaredTypeAcceptor acceptor) {
element.formFeatureCaptionProvider.inferDialogFeatureCaptionProviderWithLabel(
element.formFeatureCaptionProviderQN, typeof(FormFeatureCaptionProvider), acceptor)
}
def private inferDialogFeatureCaptionProvider(Module element, IJvmDeclaredTypeAcceptor acceptor) {
element.dialogFeatureCaptionProvider.inferDialogFeatureCaptionProviderWithLabel(
element.dialogFeatureCaptionProviderQN, typeof(DialogFeatureCaptionProvider), acceptor)
}
def private inferDialogFeatureCaptionProviderWithLabel(AbstractFeatureCaptionProviderWithLabel element, String name, Class<?> superClass, IJvmDeclaredTypeAcceptor acceptor) {
if (element == null)
null
else {
val descriptionProviderClass = element.toClass(name)
acceptor.accept(descriptionProviderClass) [
setSuperClassTypeAndFields(element, superClass)
inferMethodsForTextCaptionSpecifications(element, it, element.specifications)
inferMethodsForLabelCaptionSpecifications(element, it, element.labelSpecifications)
]
descriptionProviderClass
}
}
def private inferMethodsForTextCaptionSpecifications(EObject element, JvmGenericType it, Iterable<FeatureAssociatedExpression> specifications) {
inferMethodsForCaptionSpecifications(
it, specifications, "text_", typeRef(String)
) [
it, spec |
parameters += spec.toParameter(
"it", typeRef(EStructuralFeature)
)
]
}
def private inferMethodsForLabelCaptionSpecifications(EObject element, JvmGenericType it, Iterable<FeatureAssociatedExpression> specifications) {
inferMethodsForCaptionSpecifications(
it, specifications, "label_", typeRef(Label)
) [
it, spec |
parameters += spec.toParameter(
"parent", typeRef(Composite)
)
parameters += spec.toParameter(
"it", typeRef(EStructuralFeature)
)
]
}
def private inferMethodsForCaptionSpecifications(JvmGenericType it, Iterable<FeatureAssociatedExpression> specifications,
String prefix, JvmTypeReference returnType, (JvmOperation, FeatureAssociatedExpression) => void parameterCreator
) {
for (spec : specifications) {
featureAssociatedExpressionToMethod(spec, prefix, returnType, parameterCreator)
}
}
def private featureAssociatedExpressionToMethod(JvmGenericType it, FeatureAssociatedExpression spec,
String prefix, JvmTypeReference returnType, (JvmOperation, FeatureAssociatedExpression) => void parameterCreator) {
if (spec.feature?.simpleName != null) {
// associate the method to the expression, not to the whole
// spec, otherwise the 'feature' is logically
// contained in a method which should return a label
// and the validator would complain
members += spec.expression.toMethod
(prefix +
spec.parameterType.simpleName + "_" +
spec.feature.simpleName.propertyNameForGetterSetterMethod,
returnType
) [
parameterCreator.apply(it, spec)
body = spec.expression
]
}
}
def private inferFeatureProvider(Module element, IJvmDeclaredTypeAcceptor acceptor) {
element.featuresProvider.inferFeatureProviderCommon(
element.featuresProviderQN, typeof(FeaturesProvider), acceptor)
}
def private inferTableFeatureProvider(Module element, IJvmDeclaredTypeAcceptor acceptor) {
element.tableFeaturesProvider.
inferFeatureProviderCommon(element.tableFeaturesProviderQN, typeof(TableFeaturesProvider), acceptor)
}
def private inferFeatureProviderCommon(AbstractFeatureProvider element, String name, Class<?> superClass, IJvmDeclaredTypeAcceptor acceptor) {
if (element == null)
null
else {
val featureProviderClass = element.toClass(name)
acceptor.accept(featureProviderClass) [
setSuperClassTypeAndFields(element, superClass)
documentation = element.documentation
members += element.
toMethod("buildStringMap", Void::TYPE.getTypeForName(element)) [
annotations += annotationRef(Override)
parameters += element.toParameter("stringMap",
typeRef(EClassToEStructuralFeatureAsStringsMap)
)
body = [
append("super.buildStringMap(stringMap);").newLine
for (featureSpecification : element.featureSpecifications) {
newLine.
append('''stringMap.mapTo("«featureSpecification.parameterType.identifier»",''').
increaseIndentation.newLine
val fs = featureSpecification.features.map [
feature |
'"' + feature.simpleName.propertyNameForGetterSetterMethod
+ '"'
]
append(fs.join(", "))
append(");").decreaseIndentation
}
]
]
]
featureProviderClass
}
}
def private inferFormControlFactory(Module e, IJvmDeclaredTypeAcceptor acceptor) {
e.formControlFactory.inferControlFactory(e.formControlFactoryQN, typeof(FormControlFactory), acceptor)
}
def private inferDialogControlFactory(Module e, IJvmDeclaredTypeAcceptor acceptor) {
e.dialogControlFactory.inferControlFactory(e.dialogControlFactoryQN, typeof(DialogControlFactory), acceptor)
}
def private inferControlFactory(AbstractControlFactory e, String name, Class<?> superClass, IJvmDeclaredTypeAcceptor acceptor) {
if (e == null)
null
else {
val controlFactoryClass = e.toClass(name)
acceptor.accept(controlFactoryClass) [
setSuperClassTypeAndFields(e, superClass)
documentation = e.documentation
inferMethodsForControlFactory(e, it, e.controlSpecifications)
]
controlFactoryClass
}
}
def private inferMethodsForControlFactory(AbstractControlFactory e, JvmGenericType it, Iterable<ControlFactorySpecification> specifications) {
for (spec: specifications) {
if (spec.feature?.simpleName != null) {
if (spec.target == null)
members += spec.
control_EClass_EStructuralFeature(spec.expression) [
parameters += spec.toParameter(
"it", spec.parameterType
)
body = spec.expression
]
else {
val createControlMethodName = spec.methodNameForFormFeatureSpecification("createControl_")
val createTargetMethodName = spec.methodNameForFormFeatureSpecification("createTarget_")
members += spec.
control_EClass_EStructuralFeature(spec.expression) [
parameters += spec.toParameter(
"dataBindingContext", typeRef(DataBindingContext)
)
parameters += spec.toParameter(
"observableValue", typeRef(IObservableValue)
)
body = [
append(typeRef(Control).type)
append(''' control = «createControlMethodName»();''').newLine
append(
'''
dataBindingContext.bindValue(
«createTargetMethodName»(control),
observableValue);'''
).newLine
append('''return control;''')
]
]
members += spec.toMethod
(createControlMethodName,
typeRef(Control)) [
visibility = JvmVisibility::PROTECTED
body = spec.expression
]
members += spec.toMethod
(createTargetMethodName,
typeRef(IObservableValue)) [
visibility = JvmVisibility::PROTECTED
parameters += spec.toParameter(
"it", typeRef(Control)
)
body = spec.target
]
}
}
}
}
def private inferViewerContentProvider(Module element, IJvmDeclaredTypeAcceptor acceptor) {
if (element.viewerContentProvider == null)
null
else {
val viewerContentProvider = element.viewerContentProvider
val viewerContentProviderClass = viewerContentProvider.toClass(element.viewerContentProviderQN)
acceptor.accept(viewerContentProviderClass) [
setSuperClassTypeAndFields(viewerContentProvider, typeof(ViewerContentProvider))
members += viewerContentProvider.toConstructor() [
parameters += element.viewerContentProvider.
toParameter("adapterFactory",
typeRef(AdapterFactory)
)
body = [it.append("super(adapterFactory);")]
annotations += annotationRef(Inject)
]
for (specification : viewerContentProvider.elementsSpecifications) {
members += specification.specificationToMethod("elements", typeRef(Object))
}
for (specification : viewerContentProvider.childrenSpecifications) {
members += specification.specificationToMethod("children", typeRef(Object))
}
]
viewerContentProviderClass
}
}
def private inferProposalCreator(Module element, IJvmDeclaredTypeAcceptor acceptor) {
if (element.proposalCreator == null)
null
else {
val proposalCreator = element.proposalCreator
val proposalCreatorClass = proposalCreator.toClass(element.proposalCreatorQN)
acceptor.accept(proposalCreatorClass) [
setSuperClassTypeAndFields(proposalCreator, typeof(ProposalCreator))
for (specification : proposalCreator.proposalsSpecifications) {
featureAssociatedExpressionToMethod(specification, "proposals_", typeRef(List).type.createTypeRef(wildCard)) [
it, spec |
parameters += spec.toParameter(
"it", spec.parameterType
)
parameters += spec.toParameter(
"feature", typeRef(EStructuralFeature)
)
]
}
]
proposalCreatorClass
}
}
def private inferMenuBuilder(Module element, IJvmDeclaredTypeAcceptor acceptor) {
if (element.menuBuilder == null)
null
else {
val menuBuilder = element.menuBuilder
val menuBuilderClass = menuBuilder.toClass(element.menuBuilderQN)
acceptor.accept(menuBuilderClass) [
setSuperClassTypeAndFields(menuBuilder, EditingMenuBuilder)
val returnType = typeRef(List, typeRef(IMenuContributionSpecification))
for (specification : menuBuilder.menuSpecifications) {
members += specification.specificationToMethod("menuContributions", returnType)
}
for (specification : menuBuilder.emfMenuSpecifications) {
members += specification.specificationToMethod("emfMenuContributions", returnType)
}
]
menuBuilderClass
}
}
def private specificationToMethod(LabelSpecification specification, String methodName, JvmTypeReference returnType) {
specification.toMethod(methodName, returnType) [
parameters += specification.specificationParameter
body = specification.expression
]
}
def private specificationParameter(LabelSpecification specification) {
specification.toParameter(
if (specification.name != null)
specification.name
else
"it"
, specification.parameterType
)
}
def private control_EClass_EStructuralFeature(
ControlFactorySpecification spec, XExpression exp, (JvmOperation)=>void init
) {
exp.toMethod
(spec.methodNameForFormFeatureSpecification("control_"),
typeRef(Control)
, init)
}
def private methodNameForFormFeatureSpecification(ControlFactorySpecification spec, String prefix) {
prefix +
spec.parameterType.simpleName + "_" +
spec.feature.simpleName.propertyNameForGetterSetterMethod
}
def private genBindMethod(EObject element, JvmGenericType type, Class<?> clazz) {
genBindMethod(element, typeRef(clazz), true) [
body = [
append("return ")
append(type)
append(".class;")
]
]
}
def private handleBindingsSpecification(JvmGenericType it, BindingsSpecification bindingsSpecification) {
for (binding : bindingsSpecification.bindings) {
var JvmOperation method = null
if (binding instanceof TypeBinding) {
method = genBindMethod(binding)
} else if (binding instanceof ProviderBinding) {
method = genProvideMethod(binding)
} else if (binding instanceof ValueBinding) {
method = genValueMethod(binding)
}
if (method != null) {
members += method
}
}
}
def private genBindMethod(JvmGenericType it, TypeBinding typeBinding) {
if (typeBinding.typeToBind == null) {
return null
}
// we must trigger resolution of JvmTypeReference
// otherwise the parameterized Class type with wildcard
// will contain an unresolved type reference
genBindMethod(typeBinding, typeBinding.typeToBind.type.typeRef) [
body = typeBinding.getTo
]
}
def private genProvideMethod(JvmGenericType it, ProviderBinding binding) {
if (binding.type == null) {
return null
}
// we must trigger resolution of JvmTypeReference
// otherwise the parameterized Class type with wildcard
// will contain an unresolved type reference
genProvideMethod(binding, binding.type.type.typeRef) [
body = binding.getTo
]
}
def private genValueMethod(JvmGenericType it, ValueBinding binding) {
if (binding.typeDecl == null || binding.id == null) {
return null
}
genValueMethod(binding, binding.id, binding.typeDecl) [
body = binding.getTo
]
}
def private genBindMethod(EObject element, JvmTypeReference typeRefToBind, boolean shouldOverride, IAcceptor<JvmExecutable> acceptor) {
element.genMethodForGuiceModuleWithWildcard("bind" + typeRefToBind.simpleName,
typeRefToBind.cloneWithProxies, shouldOverride, acceptor
)
}
def private genBindMethod(JvmGenericType it, EObject element, JvmTypeReference typeRefToBind, IAcceptor<JvmExecutable> acceptor) {
val methodName = "bind" + typeRefToBind.simpleName
element.genMethodForGuiceModuleWithWildcard(methodName,
typeRefToBind.cloneWithProxies, shouldOverride(methodName), acceptor
)
}
def private genProvideMethod(JvmGenericType it, EObject element, JvmTypeReference typeRefToBind, IAcceptor<JvmExecutable> acceptor) {
val methodName = "provide" + typeRefToBind.simpleName
element.genMethodForGuiceModuleWithWildcard(methodName,
typeRef(Provider, typeRefToBind.cloneWithProxies), shouldOverride(methodName), acceptor
)
}
def private genValueMethod(JvmGenericType it, EObject element, String name, JvmTypeReference typeRefToBind, IAcceptor<JvmExecutable> acceptor) {
val methodName = "value" + name
element.genMethodForGuiceModule(methodName, typeRefToBind.cloneWithProxies, shouldOverride(methodName), acceptor)
}
def private genMethodForGuiceModuleWithWildcard(EObject element, String methodName,
JvmTypeReference typeRefToBind, boolean shouldOverride, IAcceptor<JvmExecutable> acceptor
) {
val wildCard = createJvmWildcardTypeReference
val upperBound = createJvmUpperBound
upperBound.typeReference = typeRefToBind.cloneWithProxies
wildCard.constraints += upperBound
element.genMethodForGuiceModule(methodName, typeRef(Class, wildCard), shouldOverride, acceptor)
}
def private genMethodForGuiceModule(EObject element, String methodName, JvmTypeReference typeRefToBind, boolean shouldOverride, IAcceptor<JvmExecutable> acceptor) {
element.toMethod(methodName, typeRefToBind) [
if (shouldOverride) {
annotations += annotationRef(Override)
}
acceptor.accept(it)
]
}
def private shouldOverride(JvmGenericType it, String methodName) {
allFeatures.filter(JvmOperation).exists[simpleName == methodName]
}
}