in grails-rest-transforms/src/main/groovy/org/grails/plugins/web/rest/transform/ResourceTransform.groovy [111:255]
void visit(ASTNode[] astNodes, SourceUnit source) {
if (!(astNodes[0] instanceof AnnotationNode) || !(astNodes[1] instanceof ClassNode)) {
throw new RuntimeException('Internal error: wrong types: $node.class / $parent.class')
}
ClassNode parent = (ClassNode) astNodes[1]
AnnotationNode annotationNode = (AnnotationNode) astNodes[0]
if (!MY_TYPE.equals(annotationNode.getClassNode())) {
return
}
String className = "${parent.name}${ControllerArtefactHandler.TYPE}"
final File resource = IOUtils.findSourceFile(className)
LinkableTransform.addLinkingMethods(parent)
if (resource == null) {
ClassNode superClassNode
Expression superClassAttribute = annotationNode.getMember(ATTR_SUPER_CLASS)
if(superClassAttribute instanceof ClassExpression) {
superClassNode = ((ClassExpression)superClassAttribute).getType()
} else {
superClassNode = ClassHelper.make(RestfulController)
}
final ast = source.getAST()
final newControllerClassNode = new ClassNode(className, PUBLIC, nonGeneric(superClassNode, parent))
final transactionalAnn = new AnnotationNode(TransactionalTransform.MY_TYPE)
transactionalAnn.addMember(ATTR_READY_ONLY,ConstantExpression.PRIM_TRUE)
newControllerClassNode.addAnnotation(transactionalAnn)
final readOnlyAttr = annotationNode.getMember(ATTR_READY_ONLY)
boolean isReadOnly = readOnlyAttr != null && ((ConstantExpression)readOnlyAttr).trueExpression
addConstructor(newControllerClassNode, parent, isReadOnly)
List<ClassInjector> injectors = ArtefactTypeAstTransformation.findInjectors(ControllerArtefactHandler.TYPE, GrailsAwareInjectionOperation.getClassInjectors());
ArtefactTypeAstTransformation.performInjection(source, newControllerClassNode, injectors.findAll { !(it instanceof ControllerActionTransformer) })
if(unit) {
TraitInjectionUtils.processTraitsForNode(source, newControllerClassNode, 'Controller', unit)
}
final responseFormatsAttr = annotationNode.getMember(ATTR_RESPONSE_FORMATS)
final uriAttr = annotationNode.getMember(ATTR_URI)
final namespaceAttr = annotationNode.getMember(ATTR_NAMESPACE)
final domainPropertyName = GrailsNameUtils.getPropertyName(parent.getName())
ListExpression responseFormatsExpression = new ListExpression()
boolean hasHtml = false
if (responseFormatsAttr != null) {
if (responseFormatsAttr instanceof ConstantExpression) {
if (responseFormatsExpression.text.equalsIgnoreCase('html')) {
hasHtml = true
}
responseFormatsExpression.addExpression(responseFormatsAttr)
}
else if (responseFormatsAttr instanceof ListExpression) {
responseFormatsExpression = (ListExpression)responseFormatsAttr
for(Expression expr in responseFormatsExpression.expressions) {
if (expr.text.equalsIgnoreCase('html')) hasHtml = true; break
}
}
} else {
responseFormatsExpression.addExpression(new ConstantExpression("json"))
responseFormatsExpression.addExpression(new ConstantExpression("xml"))
}
if (uriAttr != null || namespaceAttr != null) {
String uri = uriAttr?.getText()
final namespace=namespaceAttr?.getText()
if(uri || namespace) {
final urlMappingsClassNode = new ClassNode(UrlMappings).getPlainNodeReference()
final lazyInitField = new FieldNode('lazyInit', PUBLIC | STATIC | FINAL, ClassHelper.Boolean_TYPE,newControllerClassNode, new ConstantExpression(Boolean.FALSE))
newControllerClassNode.addField(lazyInitField)
final urlMappingsField = new FieldNode('$urlMappings', PRIVATE, urlMappingsClassNode,newControllerClassNode, null)
newControllerClassNode.addField(urlMappingsField)
final urlMappingsSetterParam = new Parameter(urlMappingsClassNode, "um")
final controllerMethodAnnotation = new AnnotationNode(new ClassNode(ControllerMethod).getPlainNodeReference())
MethodNode urlMappingsSetter = new MethodNode("setUrlMappings", PUBLIC, VOID_CLASS_NODE, [urlMappingsSetterParam] as Parameter[], null, new ExpressionStatement(new BinaryExpression(new VariableExpression(urlMappingsField.name),Token.newSymbol(Types.EQUAL, 0, 0), new VariableExpression(urlMappingsSetterParam))))
final autowiredAnnotation = new AnnotationNode(AUTOWIRED_CLASS_NODE)
autowiredAnnotation.addMember("required", ConstantExpression.FALSE)
final qualifierAnnotation = new AnnotationNode(new ClassNode(Qualifier).getPlainNodeReference())
qualifierAnnotation.addMember("value", new ConstantExpression("grailsUrlMappingsHolder"))
urlMappingsSetter.addAnnotation(autowiredAnnotation)
urlMappingsSetter.addAnnotation(qualifierAnnotation)
urlMappingsSetter.addAnnotation(controllerMethodAnnotation)
newControllerClassNode.addMethod(urlMappingsSetter)
AnnotatedNodeUtils.markAsGenerated(newControllerClassNode, urlMappingsSetter)
processVariableScopes(source, newControllerClassNode, urlMappingsSetter)
final methodBody = new BlockStatement()
final urlMappingsVar = new VariableExpression(urlMappingsField.name)
MapExpression map=new MapExpression()
if(uri){
map.addMapEntryExpression(new MapEntryExpression(new ConstantExpression("resources"), new ConstantExpression(domainPropertyName)))
}
if(namespace){
final namespaceField = new FieldNode('namespace', STATIC, ClassHelper.STRING_TYPE,newControllerClassNode, new ConstantExpression(namespace))
newControllerClassNode.addField(namespaceField)
if(map.getMapEntryExpressions().size()==0){
uri="/${namespace}/${domainPropertyName}"
map.addMapEntryExpression(new MapEntryExpression(new ConstantExpression("resources"), new ConstantExpression(domainPropertyName)))
}
map.addMapEntryExpression(new MapEntryExpression(new ConstantExpression("namespace"), new ConstantExpression(namespace)))
}
final resourcesUrlMapping = new MethodCallExpression(buildThisExpression(), uri, new MapExpression([ new MapEntryExpression(new ConstantExpression("resources"), new ConstantExpression(domainPropertyName))]))
final urlMappingsClosure = new ClosureExpression(null, new ExpressionStatement(resourcesUrlMapping))
def addMappingsMethodCall = applyDefaultMethodTarget(new MethodCallExpression(urlMappingsVar, "addMappings", urlMappingsClosure), urlMappingsClassNode)
methodBody.addStatement(new IfStatement(new BooleanExpression(urlMappingsVar), new ExpressionStatement(addMappingsMethodCall),new EmptyStatement()))
def initialiseUrlMappingsMethod = new MethodNode("initializeUrlMappings", PUBLIC, VOID_CLASS_NODE, ZERO_PARAMETERS, null, methodBody)
initialiseUrlMappingsMethod.addAnnotation(new AnnotationNode(new ClassNode(PostConstruct).getPlainNodeReference()))
initialiseUrlMappingsMethod.addAnnotation(controllerMethodAnnotation)
newControllerClassNode.addMethod(initialiseUrlMappingsMethod)
AnnotatedNodeUtils.markAsGenerated(newControllerClassNode, initialiseUrlMappingsMethod)
processVariableScopes(source, newControllerClassNode, initialiseUrlMappingsMethod)
}
}
final publicStaticFinal = PUBLIC | STATIC | FINAL
newControllerClassNode.addProperty("scope", publicStaticFinal, ClassHelper.STRING_TYPE, new ConstantExpression("singleton"), null, null)
newControllerClassNode.addProperty("responseFormats", publicStaticFinal, new ClassNode(List).getPlainNodeReference(), responseFormatsExpression, null, null)
ArtefactTypeAstTransformation.performInjection(source, newControllerClassNode, injectors.findAll { it instanceof ControllerActionTransformer })
new TransactionalTransform().visit(source, transactionalAnn, newControllerClassNode)
newControllerClassNode.setModule(ast)
final artefactAnnotation = new AnnotationNode(new ClassNode(Artefact))
artefactAnnotation.addMember("value", new ConstantExpression(ControllerArtefactHandler.TYPE))
newControllerClassNode.addAnnotation(artefactAnnotation)
ast.classes.add(newControllerClassNode)
}
}