Search code examples
javaxtextxtend

Xtext & Xtend - Adding more parameters to RequestMapping


I have been trying to generate Java spring code like the following.

@RequestMapping(method=RequestMethod.DELETE, value="/message/{id}")
public void reject(@PathVariable final Long id) {
    return;
}

I have provided the following code in the xtend file.

members += event.toMethod(event.action.name, typeRef(void)) [
    var dataType = map.get(method.action.name)
    parameters += event.toParameter(method.type.parameter.name, dataType.javaType) => [
        annotations += annotationRef("org.springframework.web.bind.annotation.PathVariable");
    ]
    annotations += annotationRef("org.springframework.web.bind.annotation.RequestMapping", "method=RequestMethod.DELETE", "/message/{id}");
    body = '''
        return;
    '''
]

and the output I am getting is

@RequestMapping({ "method=RequestMethod.DELETE", "/message/{id}" })
public void reject(@PathVariable final Long id) {
    return;
}

I am confused how to provide the xtend code so that I could get the RequestMapping format as @RequestMapping(method=RequestMethod.DELETE, value="/message/{id}")


Solution

  • the api has no convenience for that usecase so you have to do it yourself

    package org.eclipse.xtext.example.domainmodel.jvmmodel

    import com.google.inject.Inject
    import org.eclipse.emf.ecore.EObject
    import org.eclipse.xtext.common.types.JvmAnnotationReference
    import org.eclipse.xtext.common.types.JvmAnnotationType
    import org.eclipse.xtext.common.types.JvmType
    import org.eclipse.xtext.common.types.TypesFactory
    import org.eclipse.xtext.common.types.util.TypeReferences
    import org.eclipse.xtext.example.domainmodel.domainmodel.Entity
    import org.eclipse.xtext.naming.IQualifiedNameProvider
    import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
    import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
    import org.eclipse.xtext.xbase.jvmmodel.JvmAnnotationReferenceBuilder
    import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
    import org.eclipse.xtext.common.types.JvmStringAnnotationValue
    
    class DomainmodelJvmModelInferrer extends AbstractModelInferrer {
    
        @Inject extension JvmTypesBuilder
        @Inject extension IQualifiedNameProvider
    
        def dispatch infer(Entity entity, extension IJvmDeclaredTypeAcceptor acceptor, boolean prelinkingPhase) {
            accept(entity.toClass(entity.fullyQualifiedName)) [
                documentation = entity.documentation
                members += entity.toMethod("demo", Void.TYPE.typeRef) [
                    annotations +=
                        entity.toAnnotationRef("org.eclipse.xtext.example.domainmodel.lib.Demo", "a" -> "Hallo",
                            "b" -> "Welt", "c" -> "!")
                    body = ''''''
                ]
            ]
        }
    
        @Inject
        private TypesFactory typesFactory;
    
        @Inject
        private TypeReferences references;
    
        def toAnnotationRef(EObject context, String annotationTypeName, Pair<String, String> ... values) {
            val JvmAnnotationReference result = typesFactory.createJvmAnnotationReference();
            val JvmType jvmType = references.findDeclaredType(annotationTypeName, context);
            if (jvmType == null) {
                throw new IllegalArgumentException("The type " + annotationTypeName + " is not on the classpath.");
            }
            if (!(jvmType instanceof JvmAnnotationType)) {
                throw new IllegalArgumentException("The given class " + annotationTypeName + " is not an annotation type.");
            }
            val jvmAnnotationType = jvmType as JvmAnnotationType
    
            result.setAnnotation(jvmAnnotationType);
            for (value : values) {
                val JvmStringAnnotationValue annoValue = typesFactory.createJvmStringAnnotationValue
                annoValue.values += value.value
                annoValue.operation = jvmAnnotationType.declaredOperations.findFirst[simpleName == value.key]
                result.explicitValues.add(annoValue)
            }
            return result
    
        }
    
    }