/**
* 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.mule;
import org.mule.DefaultMuleEvent;
import org.mule.DefaultMuleMessage;
import org.mule.api.MuleContext;
import org.mule.api.MuleEvent;
import org.mule.api.MuleMessage;
import org.mule.api.NestedProcessor;
import org.mule.api.context.MuleContextAware;
import org.mule.api.processor.MessageProcessor;
import org.mule.devkit.generation.AbstractModuleGenerator;
import org.mule.devkit.generation.DevKitTypeElement;
import org.mule.devkit.generation.NamingContants;
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.Variable;
import javax.lang.model.element.TypeElement;
import java.util.Map;
public class NestedProcessorChainGenerator extends AbstractModuleGenerator {
public static final String ROLE = "NestedProcessorChain";
@Override
protected boolean shouldGenerate(DevKitTypeElement typeElement) {
return typeElement.hasProcessorMethodWithParameter(NestedProcessor.class) ||
typeElement.hasProcessorMethodWithParameterListOf(NestedProcessor.class);
}
@Override
protected void doGenerate(DevKitTypeElement typeElement) {
DefinedClass callbackClass = getNestedProcessorChainClass(typeElement);
callbackClass._implements(ref(NestedProcessor.class));
FieldVariable muleContext = callbackClass.field(Modifier.PRIVATE, ref(MuleContext.class), "muleContext");
muleContext.javadoc().add("Mule Context");
generateSetter(callbackClass, muleContext);
FieldVariable chain = callbackClass.field(Modifier.PRIVATE, ref(MessageProcessor.class), "chain");
chain.javadoc().add("Chain that will be executed upon calling process");
generateSetter(callbackClass, chain);
FieldVariable event = callbackClass.field(Modifier.PRIVATE, ref(MuleEvent.class), "event");
event.javadoc().add("Event that will be cloned for dispatching");
generateSetter(callbackClass, event);
generateCallbackConstructor(callbackClass, chain, event, muleContext);
generateCallbackProcess(callbackClass, chain, event);
generateCallbackProcessWithPayload(callbackClass, chain, event, muleContext);
generateCallbackProcessWithProperties(callbackClass, chain, event);
generateCallbackProcessWithPayloadAndProperties(callbackClass, chain, event, muleContext);
context.setClassRole(ROLE, callbackClass);
}
private void generateCallbackProcessWithPayload(DefinedClass callbackClass, FieldVariable chain, FieldVariable event, FieldVariable muleContext) {
Method process = callbackClass.method(Modifier.PUBLIC, ref(Object.class), "process");
process._throws(ref(Exception.class));
Variable payload = process.param(ref(Object.class), "payload");
Variable muleMessage = process.body().decl(ref(MuleMessage.class), "muleMessage");
Invocation newMuleMessage = ExpressionFactory._new(ref(DefaultMuleMessage.class));
newMuleMessage.arg(payload);
newMuleMessage.arg(muleContext);
process.body().assign(muleMessage, newMuleMessage);
Variable muleEvent = process.body().decl(ref(MuleEvent.class), "muleEvent");
Invocation newMuleEvent = ExpressionFactory._new(ref(DefaultMuleEvent.class));
newMuleEvent.arg(muleMessage);
newMuleEvent.arg(event);
process.body().assign(muleEvent, newMuleEvent);
process.body()._return(chain.invoke("process").arg(muleEvent).invoke("getMessage").invoke("getPayload"));
}
private void generateCallbackProcessWithPayloadAndProperties(DefinedClass callbackClass, FieldVariable chain, FieldVariable event, FieldVariable muleContext) {
Method process = callbackClass.method(Modifier.PUBLIC, ref(Object.class), "process");
process._throws(ref(Exception.class));
Variable payload = process.param(ref(Object.class), "payload");
Variable properties = process.param(ref(Map.class).narrow(ref(String.class)).narrow(ref(Object.class)), "properties");
Variable muleMessage = process.body().decl(ref(MuleMessage.class), "muleMessage");
Invocation newMuleMessage = ExpressionFactory._new(ref(DefaultMuleMessage.class));
newMuleMessage.arg(payload);
newMuleMessage.arg(muleContext);
process.body().assign(muleMessage, newMuleMessage);
ForEach forEachProperty = process.body().forEach(ref(String.class), "property", properties.invoke("keySet"));
forEachProperty.body().add(muleMessage.invoke("setInvocationProperty")
.arg(forEachProperty.var())
.arg(properties.invoke("get").arg(forEachProperty.var())));
Variable muleEvent = process.body().decl(ref(MuleEvent.class), "muleEvent");
Invocation newMuleEvent = ExpressionFactory._new(ref(DefaultMuleEvent.class));
newMuleEvent.arg(muleMessage);
newMuleEvent.arg(event);
process.body().assign(muleEvent, newMuleEvent);
process.body()._return(chain.invoke("process").arg(muleEvent).invoke("getMessage").invoke("getPayload"));
}
private void generateCallbackProcessWithProperties(DefinedClass callbackClass, FieldVariable chain, FieldVariable event) {
Method process = callbackClass.method(Modifier.PUBLIC, ref(Object.class), "processWithExtraProperties");
process._throws(ref(Exception.class));
Variable properties = process.param(ref(Map.class).narrow(ref(String.class)).narrow(ref(Object.class)), "properties");
Variable muleMessage = process.body().decl(ref(MuleMessage.class), "muleMessage");
//Invocation newMuleMessage = ExpressionFactory._new(ref(DefaultMuleMessage.class));
//newMuleMessage.arg(event.invoke("getMessage").invoke("getPayload"));
//newMuleMessage.arg(muleContext);
process.body().assign(muleMessage, event.invoke("getMessage"));
ForEach forEachProperty = process.body().forEach(ref(String.class), "property", properties.invoke("keySet"));
forEachProperty.body().add(muleMessage.invoke("setInvocationProperty")
.arg(forEachProperty.var())
.arg(properties.invoke("get").arg(forEachProperty.var())));
Variable muleEvent = process.body().decl(ref(MuleEvent.class), "muleEvent");
Invocation newMuleEvent = ExpressionFactory._new(ref(DefaultMuleEvent.class));
newMuleEvent.arg(muleMessage);
newMuleEvent.arg(event);
process.body().assign(muleEvent, newMuleEvent);
process.body()._return(chain.invoke("process").arg(muleEvent).invoke("getMessage").invoke("getPayload"));
}
private void generateCallbackProcess(DefinedClass callbackClass, FieldVariable chain, FieldVariable event) {
Method process = callbackClass.method(Modifier.PUBLIC, ref(Object.class), "process");
process._throws(ref(Exception.class));
Variable muleEvent = process.body().decl(ref(MuleEvent.class), "muleEvent");
Invocation newMuleEvent = ExpressionFactory._new(ref(DefaultMuleEvent.class));
newMuleEvent.arg(event.invoke("getMessage"));
newMuleEvent.arg(event);
process.body().assign(muleEvent, newMuleEvent);
process.body()._return(chain.invoke("process").arg(muleEvent).invoke("getMessage").invoke("getPayload"));
}
private void generateCallbackConstructor(DefinedClass callbackClass, FieldVariable chain, FieldVariable event, FieldVariable muleContext) {
Method constructor = callbackClass.constructor(Modifier.PUBLIC);
Variable event2 = constructor.param(ref(MuleEvent.class), "event");
Variable muleContext2 = constructor.param(ref(MuleContext.class), "muleContext");
Variable chain2 = constructor.param(ref(MessageProcessor.class), "chain");
constructor.body().assign(ExpressionFactory._this().ref(event), event2);
constructor.body().assign(ExpressionFactory._this().ref(chain), chain2);
constructor.body().assign(ExpressionFactory._this().ref(muleContext), muleContext2);
}
private DefinedClass getNestedProcessorChainClass(TypeElement typeElement) {
String processorCallbackClassName = context.getNameUtils().generateClassNameInPackage(typeElement, NamingContants.CONFIG_NAMESPACE, NamingContants.NESTED_PROCESSOR_CHAIN_CLASS_NAME);
org.mule.devkit.model.code.Package pkg = context.getCodeModel()._package(context.getNameUtils().getPackageName(processorCallbackClassName));
DefinedClass clazz = pkg._class(context.getNameUtils().getClassName(processorCallbackClassName), new Class[]{MuleContextAware.class});
context.setClassRole(ROLE, clazz);
return clazz;
}
}