/** * Mule Development Kit * Copyright 2010-2011 (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mule.devkit.generation.spring; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.UnhandledException; import org.mule.api.annotations.Configurable; import org.mule.api.annotations.Connector; import org.mule.api.annotations.Module; import org.mule.api.annotations.Processor; import org.mule.api.annotations.Source; import org.mule.api.annotations.SourceThreadingModel; import org.mule.api.annotations.oauth.OAuth; import org.mule.api.annotations.oauth.OAuth2; import org.mule.api.callback.HttpCallback; import org.mule.api.callback.SourceCallback; import org.mule.api.lifecycle.Disposable; import org.mule.api.lifecycle.Initialisable; import org.mule.config.PoolingProfile; import org.mule.config.spring.MuleHierarchicalBeanDefinitionParserDelegate; import org.mule.config.spring.factories.MessageProcessorChainFactoryBean; import org.mule.config.spring.parsers.generic.AutoIdUtils; import org.mule.config.spring.util.SpringXMLUtils; import org.mule.devkit.generation.AbstractMessageGenerator; import org.mule.devkit.generation.DevKitTypeElement; import org.mule.devkit.generation.adapter.HttpCallbackAdapterGenerator; import org.mule.devkit.generation.mule.oauth.DefaultRestoreAccessTokenCallbackFactoryGenerator; import org.mule.devkit.generation.mule.oauth.DefaultSaveAccessTokenCallbackFactoryGenerator; import org.mule.devkit.model.code.Block; import org.mule.devkit.model.code.CatchBlock; import org.mule.devkit.model.code.Conditional; import org.mule.devkit.model.code.DefinedClass; import org.mule.devkit.model.code.ExpressionFactory; import org.mule.devkit.model.code.FieldVariable; import org.mule.devkit.model.code.ForEach; import org.mule.devkit.model.code.Invocation; import org.mule.devkit.model.code.Method; import org.mule.devkit.model.code.Modifier; import org.mule.devkit.model.code.Op; import org.mule.devkit.model.code.TryStatement; import org.mule.devkit.model.code.TypeReference; import org.mule.devkit.model.code.Variable; import org.mule.util.TemplateParser; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.xml.DomUtils; import javax.inject.Inject; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.StringWriter; import java.util.List; public class BeanDefinitionParserGenerator extends AbstractMessageGenerator { @Override protected boolean shouldGenerate(DevKitTypeElement typeElement) { return typeElement.hasAnnotation(Module.class) || typeElement.hasAnnotation(Connector.class); } @Override protected void doGenerate(DevKitTypeElement typeElement) { generateConfigBeanDefinitionParserFor(typeElement); for (ExecutableElement executableElement : typeElement.getMethodsAnnotatedWith(Processor.class)) { generateBeanDefinitionParserForProcessor(executableElement); } for (ExecutableElement executableElement : typeElement.getMethodsAnnotatedWith(Source.class)) { generateBeanDefinitionParserForSource(executableElement); } } private void generateConfigBeanDefinitionParserFor(DevKitTypeElement typeElement) { DefinedClass beanDefinitionparser = getConfigBeanDefinitionParserClass(typeElement); DefinedClass pojo = context.getClassForRole(context.getNameUtils().generateModuleObjectRoleKey(typeElement)); context.note("Generating config element definition parser as " + beanDefinitionparser.fullName() + " for class " + typeElement.getSimpleName().toString()); FieldVariable patternInfo = generateFieldForPatternInfo(beanDefinitionparser); Method constructor = beanDefinitionparser.constructor(Modifier.PUBLIC); constructor.body().assign(patternInfo, ref(TemplateParser.class).staticInvoke("createMuleStyleParser").invoke("getStyle")); Method parse = beanDefinitionparser.method(Modifier.PUBLIC, ref(BeanDefinition.class), "parse"); Variable element = parse.param(ref(org.w3c.dom.Element.class), "element"); Variable parserContext = parse.param(ref(ParserContext.class), "parserContent"); Variable name = parse.body().decl(ref(String.class), "name", element.invoke("getAttribute").arg("name")); Conditional ifNotNamed = parse.body()._if(Op.cor(Op.eq(name, ExpressionFactory._null()), ref(StringUtils.class).staticInvoke("isBlank").arg(name))); ifNotNamed._then().add(element.invoke("setAttribute") .arg("name") .arg(ref(AutoIdUtils.class).staticInvoke("getUniqueName").arg(element).arg("mule-bean"))); Variable builder = parse.body().decl(ref(BeanDefinitionBuilder.class), "builder", ref(BeanDefinitionBuilder.class).staticInvoke("rootBeanDefinition").arg(pojo.dotclass().invoke("getName"))); Conditional isInitialisable = parse.body()._if(ref(Initialisable.class).dotclass() .invoke("isAssignableFrom").arg(pojo.dotclass())); isInitialisable._then().add(builder.invoke("setInitMethodName").arg(ref(Initialisable.class).staticRef("PHASE_NAME"))); Conditional isDisposable = parse.body()._if(ref(Disposable.class).dotclass() .invoke("isAssignableFrom").arg(pojo.dotclass())); isDisposable._then().add(builder.invoke("setDestroyMethodName").arg(ref(Disposable.class).staticRef("PHASE_NAME"))); for (VariableElement variable : typeElement.getFieldsAnnotatedWith(Configurable.class)) { String fieldName = variable.getSimpleName().toString(); if (SchemaTypeConversion.isSupported(variable.asType().toString())) { generateParseSupportedType(parse.body(), element, builder, fieldName); } else if (context.getTypeMirrorUtils().isXmlType(variable.asType())) { generateParseXmlType(parse.body(), element, builder, fieldName); } else if (context.getTypeMirrorUtils().isArrayOrList(variable.asType())) { Variable listElement = parse.body().decl(ref(org.w3c.dom.Element.class), fieldName + "ListElement", ExpressionFactory._null()); parse.body().assign(listElement, ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element) .arg(context.getNameUtils().uncamel(fieldName))); UpperBlockClosure managedList = generateParseArrayOrList(parse.body(), variable.asType(), listElement, builder, fieldName, patternInfo, parserContext); managedList.getNotRefBlock().add(builder.invoke("addPropertyValue").arg(fieldName).arg(managedList.getManagedCollection())); } else if (context.getTypeMirrorUtils().isMap(variable.asType())) { Variable listElement = parse.body().decl(ref(org.w3c.dom.Element.class), fieldName + "ListElement", ExpressionFactory._null()); parse.body().assign(listElement, ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element) .arg(context.getNameUtils().uncamel(fieldName))); UpperBlockClosure managedMap = generateParseMap(parse.body(), variable.asType(), listElement, builder, fieldName, patternInfo, parserContext); managedMap.getNotRefBlock().add(builder.invoke("addPropertyValue").arg(fieldName).arg(managedMap.getManagedCollection())); } else if (context.getTypeMirrorUtils().isEnum(variable.asType())) { generateParseEnum(parse.body(), element, builder, fieldName); } else { // not supported use the -ref approach Invocation getAttribute = element.invoke("getAttribute").arg(fieldName + "-ref"); Conditional ifNotNull = parse.body()._if(Op.cand(Op.ne(getAttribute, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg( getAttribute )))); ifNotNull._then().add(builder.invoke("addPropertyValue").arg(fieldName).arg( ExpressionFactory._new(ref(RuntimeBeanReference.class)).arg(element.invoke("getAttribute").arg(fieldName + "-ref")) )); } } for (VariableElement variable : typeElement.getFieldsAnnotatedWith(Inject.class)) { if (variable.asType().toString().equals("org.mule.api.store.ObjectStore")) { Invocation getAttribute = element.invoke("getAttribute").arg("objectStore-ref"); Conditional ifNotNull = parse.body()._if(Op.cand(Op.ne(getAttribute, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg( getAttribute )))); ifNotNull._then().add(builder.invoke("addPropertyValue").arg(variable.getSimpleName().toString()).arg( ExpressionFactory._new(ref(RuntimeBeanReference.class)).arg(element.invoke("getAttribute").arg("objectStore-ref")) )); } } ExecutableElement connect = connectMethodForClass(typeElement); if (connect != null) { for (VariableElement variable : connect.getParameters()) { String fieldName = variable.getSimpleName().toString(); if (SchemaTypeConversion.isSupported(variable.asType().toString())) { generateParseSupportedType(parse.body(), element, builder, fieldName); } else if (context.getTypeMirrorUtils().isArrayOrList(variable.asType())) { Variable listElement = parse.body().decl(ref(org.w3c.dom.Element.class), fieldName + "ListElement", ExpressionFactory._null()); parse.body().assign(listElement, ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element) .arg(context.getNameUtils().uncamel(fieldName))); UpperBlockClosure managedList = generateParseArrayOrList(parse.body(), variable.asType(), listElement, builder, fieldName, patternInfo, parserContext); managedList.getNotRefBlock().add(builder.invoke("addPropertyValue").arg(fieldName).arg(managedList.getManagedCollection())); } else if (context.getTypeMirrorUtils().isMap(variable.asType())) { Variable listElement = parse.body().decl(ref(org.w3c.dom.Element.class), fieldName + "ListElement", ExpressionFactory._null()); parse.body().assign(listElement, ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element) .arg(context.getNameUtils().uncamel(fieldName))); UpperBlockClosure managedMap = generateParseMap(parse.body(), variable.asType(), listElement, builder, fieldName, patternInfo, parserContext); managedMap.getNotRefBlock().add(builder.invoke("addPropertyValue").arg(fieldName).arg(managedMap.getManagedCollection())); } else if (context.getTypeMirrorUtils().isEnum(variable.asType())) { generateParseEnum(parse.body(), element, builder, fieldName); } } } if (typeElement.hasAnnotation(OAuth.class) || typeElement.hasAnnotation(OAuth2.class)) { generateParseHttpCallback(SchemaGenerator.OAUTH_CALLBACK_CONFIG_ELEMENT_NAME, parse, element, builder); DefinedClass saveAccessTokenCallbackFactory = context.getClassForRole(DefaultSaveAccessTokenCallbackFactoryGenerator.ROLE); DefinedClass restoreAccessTokenCallbackFactory = context.getClassForRole(DefaultRestoreAccessTokenCallbackFactoryGenerator.ROLE); generateParseNestedProcessor(parse.body(), element, parserContext, builder, "oauthSaveAccessToken", false, false, false, saveAccessTokenCallbackFactory); generateParseNestedProcessor(parse.body(), element, parserContext, builder, "oauthRestoreAccessToken", false, false, false, restoreAccessTokenCallbackFactory); generateGenerateChildBeanNameMethod(beanDefinitionparser); } if (typeElement.hasProcessorMethodWithParameter(HttpCallback.class)) { generateParseHttpCallback(SchemaGenerator.HTTP_CALLBACK_CONFIG_ELEMENT_NAME, parse, element, builder); } if (connect != null) { generateParsePoolingProfile("connection-pooling-profile", "connectionPoolingProfile", parse, element, builder); } if (typeElement.isPoolable()) { generateParsePoolingProfile("pooling-profile", "poolingProfile", parse, element, builder); } Variable definition = parse.body().decl(ref(BeanDefinition.class), "definition", builder.invoke("getBeanDefinition")); parse.body().add(definition.invoke("setAttribute").arg( ref(MuleHierarchicalBeanDefinitionParserDelegate.class).staticRef("MULE_NO_RECURSE")).arg(ref(Boolean.class).staticRef("TRUE"))); parse.body()._return(definition); } private void generateParseHttpCallback(String elementName, Method parse, Variable element, Variable builder) { Variable httpCallbackConfigElement = parse.body().decl(ref(org.w3c.dom.Element.class), "httpCallbackConfigElement", ref(DomUtils.class).staticInvoke("getChildElementByTagName"). arg(element).arg(elementName)); Block ifHttpCallbackConfigPresent = parse.body()._if(Op.ne(httpCallbackConfigElement, ExpressionFactory._null()))._then(); generateParseSupportedType(ifHttpCallbackConfigPresent, httpCallbackConfigElement, builder, HttpCallbackAdapterGenerator.DOMAIN_FIELD_NAME); generateParseSupportedType(ifHttpCallbackConfigPresent, httpCallbackConfigElement, builder, HttpCallbackAdapterGenerator.LOCAL_PORT_FIELD_NAME); generateParseSupportedType(ifHttpCallbackConfigPresent, httpCallbackConfigElement, builder, HttpCallbackAdapterGenerator.REMOTE_PORT_FIELD_NAME); generateParseSupportedType(ifHttpCallbackConfigPresent, httpCallbackConfigElement, builder, HttpCallbackAdapterGenerator.ASYNC_FIELD_NAME); Invocation getAttribute = httpCallbackConfigElement.invoke("getAttribute").arg(HttpCallbackAdapterGenerator.CONNECTOR_FIELD_NAME + "-ref"); Conditional ifNotNull = ifHttpCallbackConfigPresent._if(Op.cand(Op.ne(getAttribute, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg( getAttribute )))); ifNotNull._then().add(builder.invoke("addPropertyValue").arg(HttpCallbackAdapterGenerator.CONNECTOR_FIELD_NAME).arg( ExpressionFactory._new(ref(RuntimeBeanReference.class)).arg(httpCallbackConfigElement.invoke("getAttribute").arg(HttpCallbackAdapterGenerator.CONNECTOR_FIELD_NAME + "-ref")) )); } private void generateParsePoolingProfile(String elementName, String propertyName, Method parse, Variable element, Variable builder) { Variable poolingProfileBuilder = parse.body().decl(ref(BeanDefinitionBuilder.class), propertyName + "Builder", ref(BeanDefinitionBuilder.class).staticInvoke("rootBeanDefinition").arg(ref(PoolingProfile.class).dotclass().invoke("getName"))); Variable poolingProfileElement = parse.body().decl(ref(org.w3c.dom.Element.class), propertyName + "Element", ref(DomUtils.class).staticInvoke("getChildElementByTagName").arg(element).arg(elementName)); Conditional ifElementNotNull = parse.body()._if(Op.ne(poolingProfileElement, ExpressionFactory._null())); generateParseSupportedType(ifElementNotNull._then(), poolingProfileElement, poolingProfileBuilder, "maxActive"); generateParseSupportedType(ifElementNotNull._then(), poolingProfileElement, poolingProfileBuilder, "maxIdle"); generateParseSupportedType(ifElementNotNull._then(), poolingProfileElement, poolingProfileBuilder, "maxWait"); Invocation getAttribute = poolingProfileElement.invoke("getAttribute").arg("exhaustedAction"); Conditional ifNotNull = ifElementNotNull._then()._if(Op.cand(Op.ne(getAttribute, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg( getAttribute )))); ifNotNull._then().add(poolingProfileBuilder.invoke("addPropertyValue").arg("exhaustedAction").arg( ref(PoolingProfile.class).staticRef("POOL_EXHAUSTED_ACTIONS").invoke("get").arg(poolingProfileElement.invoke("getAttribute").arg("exhaustedAction")) )); getAttribute = poolingProfileElement.invoke("getAttribute").arg("exhaustedAction"); ifNotNull = ifElementNotNull._then()._if(Op.cand(Op.ne(getAttribute, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg( getAttribute )))); ifNotNull._then().add(poolingProfileBuilder.invoke("addPropertyValue").arg("initialisationPolicy").arg( ref(PoolingProfile.class).staticRef("POOL_INITIALISATION_POLICIES").invoke("get").arg(poolingProfileElement.invoke("getAttribute").arg("initialisationPolicy")) )); ifElementNotNull._then().add(builder.invoke("addPropertyValue").arg(propertyName).arg( poolingProfileBuilder.invoke("getBeanDefinition") )); } private void generateBeanDefinitionParserForSource(ExecutableElement executableElement) { // get class Source sourceAnnotation = executableElement.getAnnotation(Source.class); DefinedClass beanDefinitionparser = getBeanDefinitionParserClass(executableElement); DefinedClass messageSourceClass = getMessageSourceClass(executableElement, sourceAnnotation.threadingModel() == SourceThreadingModel.SINGLE_THREAD); FieldVariable patternInfo = generateFieldForPatternInfo(beanDefinitionparser); context.note("Generating bean definition parser as " + beanDefinitionparser.fullName() + " for message source " + messageSourceClass.fullName()); Method constructor = beanDefinitionparser.constructor(Modifier.PUBLIC); constructor.body().assign(patternInfo, ref(TemplateParser.class).staticInvoke("createMuleStyleParser").invoke("getStyle")); generateSourceParseMethod(beanDefinitionparser, messageSourceClass, executableElement, patternInfo); generateGenerateChildBeanNameMethod(beanDefinitionparser); } private void generateBeanDefinitionParserForProcessor(ExecutableElement executableElement) { DefinedClass beanDefinitionparser = getBeanDefinitionParserClass(executableElement); DefinedClass messageProcessorClass; if (executableElement.getAnnotation(Processor.class).intercepting()) { messageProcessorClass = getInterceptingMessageProcessorClass(executableElement); } else { messageProcessorClass = getMessageProcessorClass(executableElement); } context.note("Generating bean definition parser as " + beanDefinitionparser.fullName() + " for message processor " + messageProcessorClass.fullName()); FieldVariable patternInfo = generateFieldForPatternInfo(beanDefinitionparser); Method constructor = beanDefinitionparser.constructor(Modifier.PUBLIC); constructor.body().assign(patternInfo, ref(TemplateParser.class).staticInvoke("createMuleStyleParser").invoke("getStyle")); generateProcessorParseMethod(beanDefinitionparser, messageProcessorClass, executableElement, patternInfo); generateGenerateChildBeanNameMethod(beanDefinitionparser); } private void generateProcessorParseMethod(DefinedClass beanDefinitionparser, DefinedClass messageProcessorClass, ExecutableElement executableElement, Variable patternInfo) { Method parse = beanDefinitionparser.method(Modifier.PUBLIC, ref(BeanDefinition.class), "parse"); Variable element = parse.param(ref(org.w3c.dom.Element.class), "element"); Variable parserContext = parse.param(ref(ParserContext.class), "parserContent"); Variable definition = generateParseCommon(beanDefinitionparser, messageProcessorClass, executableElement, parse, element, patternInfo, parserContext); generateAttachMessageProcessor(parse, definition, parserContext); parse.body()._return(definition); } private void generateSourceParseMethod(DefinedClass beanDefinitionparser, DefinedClass messageProcessorClass, ExecutableElement executableElement, Variable patternInfo) { Method parse = beanDefinitionparser.method(Modifier.PUBLIC, ref(BeanDefinition.class), "parse"); Variable element = parse.param(ref(org.w3c.dom.Element.class), "element"); Variable parserContext = parse.param(ref(ParserContext.class), "parserContent"); Variable definition = generateParseCommon(beanDefinitionparser, messageProcessorClass, executableElement, parse, element, patternInfo, parserContext); generateAttachMessageSource(parse, definition, parserContext); parse.body()._return(definition); } private Variable generateParseCommon(DefinedClass beanDefinitionparser, DefinedClass messageProcessorClass, ExecutableElement executableElement, Method parse, Variable element, Variable patternInfo, Variable parserContext) { Variable builder = parse.body().decl(ref(BeanDefinitionBuilder.class), "builder", ref(BeanDefinitionBuilder.class).staticInvoke("rootBeanDefinition").arg(messageProcessorClass.dotclass().invoke("getName"))); Variable configRef = parse.body().decl(ref(String.class), "configRef", element.invoke("getAttribute").arg("config-ref")); Conditional ifConfigRef = parse.body()._if(Op.cand(Op.ne(configRef, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg(configRef)))); ifConfigRef._then().add(builder.invoke("addPropertyValue").arg("moduleObject").arg( configRef)); Method getAttributeValue = generateGetAttributeValue(beanDefinitionparser); int requiredChildElements = 0; for (VariableElement variable : executableElement.getParameters()) { if (context.getTypeMirrorUtils().ignoreParameter(variable)) { continue; } if (context.getTypeMirrorUtils().isNestedProcessor(variable.asType())) { requiredChildElements++; } else if (context.getTypeMirrorUtils().isXmlType(variable.asType())) { requiredChildElements++; } else if (context.getTypeMirrorUtils().isCollection(variable.asType())) { requiredChildElements++; } } for (VariableElement variable : executableElement.getParameters()) { if (variable.asType().toString().startsWith(SourceCallback.class.getName())) { continue; } String fieldName = variable.getSimpleName().toString(); if (context.getTypeMirrorUtils().isNestedProcessor(variable.asType())) { boolean isList = context.getTypeMirrorUtils().isArrayOrList(variable.asType()); if (requiredChildElements == 1) { generateParseNestedProcessor(parse.body(), element, parserContext, builder, fieldName, true, isList, true, ref(MessageProcessorChainFactoryBean.class)); } else { generateParseNestedProcessor(parse.body(), element, parserContext, builder, fieldName, false, isList, true, ref(MessageProcessorChainFactoryBean.class)); } } else if (SchemaTypeConversion.isSupported(variable.asType().toString())) { generateParseSupportedType(parse.body(), element, builder, fieldName); } else if (context.getTypeMirrorUtils().isXmlType(variable.asType())) { generateParseXmlType(parse.body(), element, builder, fieldName); } else if (context.getTypeMirrorUtils().isArrayOrList(variable.asType())) { Variable listElement = parse.body().decl(ref(org.w3c.dom.Element.class), fieldName + "ListElement", ExpressionFactory._null()); parse.body().assign(listElement, ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element) .arg(context.getNameUtils().uncamel(fieldName))); UpperBlockClosure managedList = generateParseArrayOrList(parse.body(), variable.asType(), listElement, builder, fieldName, patternInfo, parserContext); managedList.getNotRefBlock().add(builder.invoke("addPropertyValue").arg(fieldName).arg(managedList.getManagedCollection())); } else if (context.getTypeMirrorUtils().isMap(variable.asType())) { Variable listElement = parse.body().decl(ref(org.w3c.dom.Element.class), fieldName + "ListElement", ExpressionFactory._null()); parse.body().assign(listElement, ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element) .arg(context.getNameUtils().uncamel(fieldName))); UpperBlockClosure managedMap = generateParseMap(parse.body(), variable.asType(), listElement, builder, fieldName, patternInfo, parserContext); managedMap.getNotRefBlock().add(builder.invoke("addPropertyValue").arg(fieldName).arg(managedMap.getManagedCollection())); } else if (context.getTypeMirrorUtils().isEnum(variable.asType())) { generateParseEnum(parse.body(), element, builder, fieldName); } else if (variable.asType().toString().startsWith(HttpCallback.class.getName())) { Variable callbackFlowName = parse.body().decl(ref(String.class), fieldName + "CallbackFlowName", ExpressionFactory.invoke(getAttributeValue).arg(element).arg(context.getNameUtils().uncamel(fieldName) + "-flow-ref")); Block block = parse.body()._if(Op.ne(callbackFlowName, ExpressionFactory._null()))._then(); block.invoke(builder, "addPropertyValue").arg(fieldName + "CallbackFlow").arg(ExpressionFactory._new(ref(RuntimeBeanReference.class)).arg(callbackFlowName)); } else { // not supported use the -ref approach Invocation getAttribute = element.invoke("getAttribute").arg(fieldName + "-ref"); Conditional ifNotNull = parse.body()._if(Op.cand(Op.ne(getAttribute, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg( getAttribute )))); Conditional ifNotExpression = ifNotNull._then()._if(getAttribute.invoke("startsWith").arg("#")); ifNotExpression._else().add(builder.invoke("addPropertyValue").arg(fieldName).arg( Op.plus(Op.plus(ExpressionFactory.lit("#[registry:"), element.invoke("getAttribute").arg(fieldName + "-ref")), ExpressionFactory.lit("]")) )); ifNotExpression._then().add(builder.invoke("addPropertyValue").arg(fieldName).arg( element.invoke("getAttribute").arg(fieldName + "-ref") )); } } ExecutableElement connectMethod = connectForMethod(executableElement); if (connectMethod != null) { generateParseSupportedType(parse.body(), element, builder, "retryMax"); for (VariableElement variable : connectMethod.getParameters()) { String fieldName = variable.getSimpleName().toString(); if (SchemaTypeConversion.isSupported(variable.asType().toString())) { generateParseSupportedType(parse.body(), element, builder, fieldName); } else if (context.getTypeMirrorUtils().isArrayOrList(variable.asType())) { Variable listElement = parse.body().decl(ref(org.w3c.dom.Element.class), fieldName + "ListElement", ExpressionFactory._null()); parse.body().assign(listElement, ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element) .arg(context.getNameUtils().uncamel(fieldName))); UpperBlockClosure managedList = generateParseArrayOrList(parse.body(), variable.asType(), listElement, builder, fieldName, patternInfo, parserContext); managedList.getNotRefBlock().add(builder.invoke("addPropertyValue").arg(fieldName).arg(managedList.getManagedCollection())); } else if (context.getTypeMirrorUtils().isMap(variable.asType())) { Variable listElement = parse.body().decl(ref(org.w3c.dom.Element.class), fieldName + "ListElement", ExpressionFactory._null()); parse.body().assign(listElement, ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element) .arg(context.getNameUtils().uncamel(fieldName))); UpperBlockClosure managedMap = generateParseMap(parse.body(), variable.asType(), listElement, builder, fieldName, patternInfo, parserContext); managedMap.getNotRefBlock().add(builder.invoke("addPropertyValue").arg(fieldName).arg(managedMap.getManagedCollection())); } else if (context.getTypeMirrorUtils().isEnum(variable.asType())) { generateParseEnum(parse.body(), element, builder, fieldName); } } } Variable definition = parse.body().decl(ref(BeanDefinition.class), "definition", builder.invoke("getBeanDefinition")); parse.body().add(definition.invoke("setAttribute").arg( ref(MuleHierarchicalBeanDefinitionParserDelegate.class).staticRef("MULE_NO_RECURSE")).arg(ref(Boolean.class).staticRef("TRUE"))); return definition; } private void generateParseNestedProcessor(Block block, Variable element, Variable parserContext, Variable builder, String fieldName, boolean skipElement, boolean isList, boolean allowTextAttribute, TypeReference factoryBean) { Variable elements = element; if (!skipElement) { elements = block.decl(ref(org.w3c.dom.Element.class), fieldName + "Element", ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element).arg(context.getNameUtils().uncamel(fieldName))); } Conditional ifNotNull = block._if(Op.ne(elements, ExpressionFactory._null())); Block beanDefinitionBuidlerBlock = null; if (allowTextAttribute) { Variable text = ifNotNull._then().decl(ref(String.class), "text", elements.invoke("getAttribute").arg("text")); Conditional ifTextElement = ifNotNull._then()._if(Op.cand(Op.ne(text, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg(text)))); ifTextElement._then().add(builder.invoke("addPropertyValue") .arg(fieldName).arg(text)); beanDefinitionBuidlerBlock = ifTextElement._else(); } else { beanDefinitionBuidlerBlock = ifNotNull._then(); } Variable beanDefinitionBuilder = beanDefinitionBuidlerBlock.decl(ref(BeanDefinitionBuilder.class), fieldName + "BeanDefinitionBuilder", ref(BeanDefinitionBuilder.class).staticInvoke("rootBeanDefinition") .arg(factoryBean.dotclass())); Variable beanDefinition = beanDefinitionBuidlerBlock.decl(ref(BeanDefinition.class), fieldName + "BeanDefinition", beanDefinitionBuilder.invoke("getBeanDefinition")); beanDefinitionBuidlerBlock.add(parserContext.invoke("getRegistry").invoke("registerBeanDefinition") .arg(ExpressionFactory.invoke("generateChildBeanName").arg(elements)) .arg(beanDefinition)); beanDefinitionBuidlerBlock.add(elements.invoke("setAttribute") .arg("name").arg(ExpressionFactory.invoke("generateChildBeanName").arg(elements))); beanDefinitionBuidlerBlock.add(beanDefinitionBuilder.invoke("setSource").arg(parserContext.invoke("extractSource") .arg(elements))); beanDefinitionBuidlerBlock.add(beanDefinitionBuilder.invoke("setScope") .arg(ref(BeanDefinition.class).staticRef("SCOPE_SINGLETON"))); Variable list = beanDefinitionBuidlerBlock.decl(ref(List.class), fieldName + "List", parserContext.invoke("getDelegate").invoke("parseListElement") .arg(elements).arg(beanDefinitionBuilder.invoke("getBeanDefinition"))); beanDefinitionBuidlerBlock.add(parserContext.invoke("getRegistry").invoke("removeBeanDefinition") .arg(ExpressionFactory.invoke("generateChildBeanName").arg(elements))); if (!isList) { beanDefinitionBuidlerBlock.add(builder.invoke("addPropertyValue").arg(fieldName) .arg(beanDefinition)); } else { beanDefinitionBuidlerBlock.add(builder.invoke("addPropertyValue").arg(fieldName) .arg(list)); } } private void generateParseXmlType(Block block, Variable element, Variable builder, String fieldName) { Variable xmlElement = block.decl(ref(org.w3c.dom.Element.class), fieldName + "xmlElement", ExpressionFactory._null()); block.assign(xmlElement, ref(DomUtils.class).staticInvoke("getChildElementByTagName") .arg(element) .arg(context.getNameUtils().uncamel(fieldName))); Conditional xmlElementNotNull = block._if(Op.ne(xmlElement, ExpressionFactory._null())); TryStatement tryBlock = xmlElementNotNull._then()._try(); Variable xmlElementChilds = tryBlock.body().decl(ref(List.class).narrow(org.w3c.dom.Element.class), "xmlElementChilds", ref(DomUtils.class).staticInvoke("getChildElements").arg(xmlElement)); Conditional xmlElementChildsNotEmpty = tryBlock.body()._if(Op.gt(xmlElementChilds.invoke("size"), ExpressionFactory.lit(0))); Variable domSource = xmlElementChildsNotEmpty._then().decl(ref(DOMSource.class), "domSource", ExpressionFactory._new(ref(DOMSource.class)).arg( xmlElementChilds.invoke("get").arg(ExpressionFactory.lit(0)))); Variable stringWriter = xmlElementChildsNotEmpty._then().decl(ref(StringWriter.class), "stringWriter", ExpressionFactory._new(ref(StringWriter.class))); Variable streamResult = xmlElementChildsNotEmpty._then().decl(ref(StreamResult.class), "result", ExpressionFactory._new(ref(StreamResult.class)).arg(stringWriter)); Variable tf = xmlElementChildsNotEmpty._then().decl(ref(TransformerFactory.class), "tf", ref(TransformerFactory.class).staticInvoke("newInstance")); Variable transformer = xmlElementChildsNotEmpty._then().decl(ref(Transformer.class), "transformer", tf.invoke("newTransformer")); Invocation transform = transformer.invoke("transform"); transform.arg(domSource); transform.arg(streamResult); xmlElementChildsNotEmpty._then().add(transform); xmlElementChildsNotEmpty._then().add(stringWriter.invoke("flush")); xmlElementChildsNotEmpty._then().add(builder.invoke("addPropertyValue").arg(fieldName).arg( stringWriter.invoke("toString"))); generateReThrow(tryBlock, TransformerConfigurationException.class); generateReThrow(tryBlock, TransformerException.class); generateReThrow(tryBlock, TransformerFactoryConfigurationError.class); } private void generateReThrow(TryStatement tryBlock, Class<?> clazz) { CatchBlock catchBlock = tryBlock._catch(ref(clazz).boxify()); Variable e = catchBlock.param("e"); catchBlock.body()._throw(ExpressionFactory._new(ref(UnhandledException.class)).arg(e)); } private void generateParseSupportedType(Block block, Variable element, Variable builder, String fieldName) { Invocation getAttribute = element.invoke("getAttribute").arg(fieldName); Conditional ifNotNull = block._if(Op.cand(Op.ne(getAttribute, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg( getAttribute )))); ifNotNull._then().add(builder.invoke("addPropertyValue").arg(fieldName).arg( element.invoke("getAttribute").arg(fieldName) )); } private void generateParseEnum(Block block, Variable element, Variable builder, String fieldName) { Invocation hasAttribute = element.invoke("hasAttribute").arg(fieldName); Conditional ifNotNull = block._if(hasAttribute); ifNotNull._then().add(builder.invoke("addPropertyValue").arg(fieldName).arg( element.invoke("getAttribute").arg(fieldName) )); } private UpperBlockClosure generateParseMap(Block body, TypeMirror typeMirror, Variable listElement, Variable builder, String fieldName, Variable patternInfo, Variable parserContext) { DeclaredType variableType = (DeclaredType) typeMirror; List<? extends TypeMirror> variableTypeParameters = variableType.getTypeArguments(); Variable listChilds = body.decl(ref(List.class).narrow(ref(org.w3c.dom.Element.class)), fieldName.replace("-", "") + "ListChilds", ExpressionFactory._null()); Conditional listElementNotNull = body._if(Op.ne(listElement, ExpressionFactory._null())); Invocation getElementRef = listElement.invoke("getAttribute").arg("ref"); Variable ref = listElementNotNull._then().decl(ref(String.class), fieldName.replace("-", "") + "Ref", getElementRef); Conditional ifRef = listElementNotNull._then()._if( Op.cand( Op.ne(ref, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg(ref)) ) ); Conditional ifRefNotExpresion = ifRef._then()._if(Op.cand( Op.not(ref.invoke("startsWith").arg(patternInfo.invoke("getPrefix"))), Op.not(ref.invoke("endsWith").arg(patternInfo.invoke("getSuffix"))) )); ifRefNotExpresion._then().add(builder.invoke("addPropertyValue").arg(fieldName).arg( ExpressionFactory._new(ref(RuntimeBeanReference.class)).arg(ref) )); ifRefNotExpresion._else().add(builder.invoke("addPropertyValue").arg(fieldName).arg( ref)); Variable managedMap = ifRef._else().decl(ref(ManagedMap.class), fieldName.replace("-", ""), ExpressionFactory._new(ref(ManagedMap.class))); ifRef._else().assign(listChilds, ref(DomUtils.class).staticInvoke("getChildElementsByTagName") .arg(listElement) .arg(context.getNameUtils().uncamel(context.getNameUtils().singularize(fieldName)))); String childName = context.getNameUtils().uncamel(context.getNameUtils().singularize(fieldName)); Conditional listChildsNotNull = ifRef._else()._if(Op.ne(listChilds, ExpressionFactory._null())); Conditional isListEmpty = listChildsNotNull._then()._if(Op.eq(listChilds.invoke("size"), ExpressionFactory.lit(0))); isListEmpty._then().assign(listChilds, ref(DomUtils.class).staticInvoke("getChildElements").arg( listElement )); ForEach forEach = listChildsNotNull._then().forEach(ref(org.w3c.dom.Element.class), fieldName.replace("-", "") + "Child", listChilds); Invocation getValueRef = forEach.var().invoke("getAttribute").arg("value-ref"); Invocation getKeyRef = forEach.var().invoke("getAttribute").arg("key-ref"); Variable valueRef = forEach.body().decl(ref(String.class), fieldName.replace("-", "") + "ValueRef", getValueRef); Variable keyRef = forEach.body().decl(ref(String.class), fieldName.replace("-", "") + "KeyRef", getKeyRef); Variable valueObject = forEach.body().decl(ref(Object.class), "valueObject", ExpressionFactory._null()); Variable keyObject = forEach.body().decl(ref(Object.class), "keyObject", ExpressionFactory._null()); Conditional ifValueRef = forEach.body()._if(Op.cand(Op.ne(valueRef, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg(valueRef)))); Conditional ifValueRefNotExpresion = ifValueRef._then()._if(Op.cand( Op.not(valueRef.invoke("startsWith").arg(patternInfo.invoke("getPrefix"))), Op.not(valueRef.invoke("endsWith").arg(patternInfo.invoke("getSuffix"))) )); ifValueRefNotExpresion._then().assign(valueObject, ExpressionFactory._new(ref(RuntimeBeanReference.class)).arg(valueRef)); ifValueRefNotExpresion._else().assign(valueObject, valueRef); Block ifNotValueRef = ifValueRef._else(); if (variableTypeParameters.size() > 1 && context.getTypeMirrorUtils().isArrayOrList(variableTypeParameters.get(1))) { UpperBlockClosure subList = generateParseArrayOrList(ifNotValueRef, variableTypeParameters.get(1), forEach.var(), builder, "inner-" + childName, patternInfo, parserContext); subList.getNotRefBlock().assign(valueObject, subList.getManagedCollection()); } else if (variableTypeParameters.size() > 1 && context.getTypeMirrorUtils().isMap(variableTypeParameters.get(1))) { UpperBlockClosure subMap = generateParseMap(ifNotValueRef, variableTypeParameters.get(1), forEach.var(), builder, "inner-" + childName, patternInfo, parserContext); subMap.getNotRefBlock().assign(valueObject, subMap.getManagedCollection()); } else { ifNotValueRef.assign(valueObject, forEach.var().invoke("getTextContent")); } Conditional ifKeyRef = forEach.body()._if(Op.cand(Op.ne(keyRef, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg(keyRef)))); ifKeyRef._then().assign(keyObject, ExpressionFactory._new(ref(RuntimeBeanReference.class)).arg(keyRef)); ifKeyRef._else().assign(keyObject, forEach.var().invoke("getAttribute").arg("key")); Conditional noKey = forEach.body()._if(Op.cor( Op.eq(keyObject, ExpressionFactory._null()), Op.cand(Op._instanceof(keyObject, ref(String.class)), ref(StringUtils.class).staticInvoke("isBlank").arg( ExpressionFactory.cast(ref(String.class), keyObject) )) )); noKey._then().assign(keyObject, forEach.var().invoke("getTagName")); forEach.body().add(managedMap.invoke("put").arg(keyObject).arg(valueObject)); return new UpperBlockClosure(managedMap, ifRef._else()); } private UpperBlockClosure generateParseArrayOrList(Block body, TypeMirror typeMirror, Variable listElement, Variable builder, String fieldName, Variable patternInfo, Variable parserContext) { DeclaredType variableType = (DeclaredType) typeMirror; List<? extends TypeMirror> variableTypeParameters = variableType.getTypeArguments(); Variable listChilds = body.decl(ref(List.class).narrow(ref(org.w3c.dom.Element.class)), fieldName.replace("-", "") + "ListChilds", ExpressionFactory._null()); Conditional listElementNotNull = body._if(Op.ne(listElement, ExpressionFactory._null())); Invocation getElementRef = listElement.invoke("getAttribute").arg("ref"); Variable ref = listElementNotNull._then().decl(ref(String.class), fieldName.replace("-", "") + "Ref", getElementRef); Conditional ifRef = listElementNotNull._then()._if(Op.cand(Op.ne(ref, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg(ref)))); Conditional ifRefNotExpresion = ifRef._then()._if(Op.cand( Op.not(ref.invoke("startsWith").arg(patternInfo.invoke("getPrefix"))), Op.not(ref.invoke("endsWith").arg(patternInfo.invoke("getSuffix"))) )); ifRefNotExpresion._then().add(builder.invoke("addPropertyValue").arg(fieldName).arg( ExpressionFactory._new(ref(RuntimeBeanReference.class)).arg(ref) )); ifRefNotExpresion._else().add(builder.invoke("addPropertyValue").arg(fieldName).arg( ref)); Variable managedList = ifRef._else().decl(ref(ManagedList.class), fieldName.replace("-", ""), ExpressionFactory._new(ref(ManagedList.class))); String childName = context.getNameUtils().uncamel(context.getNameUtils().singularize(fieldName)); ifRef._else().assign(listChilds, ref(DomUtils.class).staticInvoke("getChildElementsByTagName") .arg(listElement) .arg(childName)); Conditional listChildsNotNull = ifRef._else()._if(Op.ne(listChilds, ExpressionFactory._null())); ForEach forEach = listChildsNotNull._then().forEach(ref(org.w3c.dom.Element.class), fieldName.replace("-", "") + "Child", listChilds); Invocation getValueRef = forEach.var().invoke("getAttribute").arg("value-ref"); Variable valueRef = forEach.body().decl(ref(String.class), "valueRef", getValueRef); Conditional ifValueRef = forEach.body()._if(Op.cand(Op.ne(valueRef, ExpressionFactory._null()), Op.not(ref(StringUtils.class).staticInvoke("isBlank").arg(valueRef)))); Conditional ifValueRefNotExpresion = ifValueRef._then()._if(Op.cand( Op.not(valueRef.invoke("startsWith").arg(patternInfo.invoke("getPrefix"))), Op.not(valueRef.invoke("endsWith").arg(patternInfo.invoke("getSuffix"))) )); ifValueRefNotExpresion._then().add( managedList.invoke("add").arg( ExpressionFactory._new(ref(RuntimeBeanReference.class)).arg(valueRef))); ifValueRefNotExpresion._else().add(managedList.invoke("add").arg(valueRef)); if (!variableTypeParameters.isEmpty() && context.getTypeMirrorUtils().isArrayOrList(variableTypeParameters.get(0))) { UpperBlockClosure subList = generateParseArrayOrList(ifValueRef._else(), variableTypeParameters.get(0), forEach.var(), builder, "inner-" + childName, patternInfo, parserContext); subList.getNotRefBlock().add( managedList.invoke("add").arg(subList.getManagedCollection())); } else if (!variableTypeParameters.isEmpty() && context.getTypeMirrorUtils().isMap(variableTypeParameters.get(0))) { UpperBlockClosure subMap = generateParseMap(ifValueRef._else(), variableTypeParameters.get(0), forEach.var(), builder, "inner-" + childName, patternInfo, parserContext); subMap.getNotRefBlock().add( managedList.invoke("add").arg(subMap.getManagedCollection())); } else { ifValueRef._else().add( managedList.invoke("add").arg(forEach.var().invoke("getTextContent"))); } return new UpperBlockClosure(managedList, ifRef._else()); } private void generateAttachMessageSource(Method parse, Variable definition, Variable parserContext) { Variable propertyValues = parse.body().decl(ref(MutablePropertyValues.class), "propertyValues", parserContext.invoke("getContainingBeanDefinition").invoke("getPropertyValues")); parse.body().add(propertyValues.invoke("addPropertyValue").arg("messageSource").arg( definition )); } private void generateGenerateChildBeanNameMethod(DefinedClass beanDefinitionparser) { Method generateChildBeanName = beanDefinitionparser.method(Modifier.PRIVATE, ref(String.class), "generateChildBeanName"); Variable element = generateChildBeanName.param(ref(org.w3c.dom.Element.class), "element"); Variable id = generateChildBeanName.body().decl(ref(String.class), "id", ref(SpringXMLUtils.class).staticInvoke("getNameOrId").arg(element)); Conditional isBlank = generateChildBeanName.body()._if(ref(StringUtils.class).staticInvoke("isBlank").arg(id)); Invocation getParentName = ref(SpringXMLUtils.class).staticInvoke("getNameOrId").arg(ExpressionFactory.cast( ref(org.w3c.dom.Element.class), element.invoke("getParentNode") )); Variable parentId = isBlank._then().decl(ref(String.class), "parentId", getParentName); isBlank._then()._return(Op.plus(Op.plus(Op.plus(ExpressionFactory.lit("."), parentId), ExpressionFactory.lit(":")), element.invoke("getLocalName"))); isBlank._else()._return(id); } private class UpperBlockClosure { private Variable managedCollection; private Block notRefBlock; private UpperBlockClosure(Variable managedCollection, Block notRefBlock) { this.managedCollection = managedCollection; this.notRefBlock = notRefBlock; } public Variable getManagedCollection() { return managedCollection; } public void setManagedCollection(Variable managedCollection) { this.managedCollection = managedCollection; } public Block getNotRefBlock() { return notRefBlock; } public void setNotRefBlock(Block notRefBlock) { this.notRefBlock = notRefBlock; } } }