/**
* 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;
import org.apache.commons.lang.StringUtils;
import org.mule.api.Capability;
import org.mule.api.MuleContext;
import org.mule.api.annotations.Connect;
import org.mule.api.annotations.ConnectionIdentifier;
import org.mule.api.annotations.Disconnect;
import org.mule.api.annotations.ValidateConnection;
import org.mule.api.annotations.oauth.OAuth;
import org.mule.api.annotations.oauth.OAuth2;
import org.mule.devkit.model.code.Conditional;
import org.mule.devkit.model.code.DefinedClass;
import org.mule.devkit.model.code.Expression;
import org.mule.devkit.model.code.ExpressionFactory;
import org.mule.devkit.model.code.FieldRef;
import org.mule.devkit.model.code.FieldVariable;
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.Type;
import org.mule.devkit.model.code.TypeReference;
import org.mule.devkit.model.code.Variable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import java.lang.annotation.Annotation;
import java.util.List;
public abstract class AbstractModuleGenerator extends AbstractGenerator {
protected static final String MULE_CONTEXT_FIELD_NAME = "muleContext";
public Type ref(TypeMirror typeMirror) {
return context.getCodeModel().ref(typeMirror);
}
public TypeReference ref(Class<?> clazz) {
return context.getCodeModel().ref(clazz);
}
public Type ref(String fullyQualifiedClassName) {
return context.getCodeModel().ref(fullyQualifiedClassName);
}
protected FieldVariable generateLoggerField(DefinedClass clazz) {
return clazz.field(Modifier.PRIVATE | Modifier.STATIC, ref(Logger.class), "logger",
ref(LoggerFactory.class).staticInvoke("getLogger").arg(clazz.dotclass()));
}
protected Method generateSetter(DefinedClass clazz, FieldVariable field) {
Method setter = clazz.method(Modifier.PUBLIC, context.getCodeModel().VOID, "set" + StringUtils.capitalize(field.name()));
setter.javadoc().add("Sets " + field.name());
setter.javadoc().addParam("value Value to set");
Variable value = setter.param(field.type(), "value");
setter.body().assign(ExpressionFactory._this().ref(field), value);
return setter;
}
protected Method generateGetter(DefinedClass clazz, FieldVariable field) {
Method setter = clazz.method(Modifier.PUBLIC, field.type(), "get" + StringUtils.capitalize(field.name()));
setter.javadoc().add("Retrieves " + field.name());
setter.body()._return(ExpressionFactory._this().ref(field));
return setter;
}
protected FieldVariable generateFieldForMuleContext(DefinedClass messageProcessorClass) {
FieldVariable muleContext = messageProcessorClass.field(Modifier.PRIVATE, ref(MuleContext.class), MULE_CONTEXT_FIELD_NAME);
muleContext.javadoc().add("Mule Context");
return muleContext;
}
protected Expression isNull(Expression expression) {
return Op.eq(expression, ExpressionFactory._null());
}
protected String getterMethodForFieldAnnotatedWith(TypeElement typeElement, Class<? extends Annotation> annotation) {
return methodForFieldAnnotatedWith(typeElement, annotation, "get");
}
private String methodForFieldAnnotatedWith(TypeElement typeElement, Class<? extends Annotation> annotation, String prefix) {
List<VariableElement> fields = ElementFilter.fieldsIn(typeElement.getEnclosedElements());
for (VariableElement field : fields) {
if (field.getAnnotation(annotation) != null) {
return prefix + StringUtils.capitalize(field.getSimpleName().toString());
}
}
return null;
}
protected ExecutableElement connectMethodForClass(DevKitTypeElement typeElement) {
List<ExecutableElement> connectMethods = typeElement.getMethodsAnnotatedWith(Connect.class);
return !connectMethods.isEmpty() ? connectMethods.get(0) : null;
}
protected ExecutableElement validateConnectionMethodForClass(DevKitTypeElement typeElement) {
List<ExecutableElement> connectMethods = typeElement.getMethodsAnnotatedWith(ValidateConnection.class);
return !connectMethods.isEmpty() ? connectMethods.get(0) : null;
}
protected ExecutableElement disconnectMethodForClass(DevKitTypeElement typeElement) {
List<ExecutableElement> disconnectMethods = typeElement.getMethodsAnnotatedWith(Disconnect.class);
return !disconnectMethods.isEmpty() ? disconnectMethods.get(0) : null;
}
protected ExecutableElement connectionIdentifierMethodForClass(DevKitTypeElement typeElement) {
List<ExecutableElement> connectionIdentifierMethods = typeElement.getMethodsAnnotatedWith(ConnectionIdentifier.class);
return !connectionIdentifierMethods.isEmpty() ? connectionIdentifierMethods.get(0) : null;
}
protected ExecutableElement connectForMethod(ExecutableElement executableElement) {
return connectMethodForClass(new DefaultDevKitTypeElement((TypeElement) executableElement.getEnclosingElement()));
}
protected ExecutableElement connectionIdentifierForMethod(ExecutableElement executableElement) {
return connectionIdentifierMethodForClass(new DefaultDevKitTypeElement((TypeElement) executableElement.getEnclosingElement()));
}
protected void generateIsCapableOf(DevKitTypeElement typeElement, DefinedClass capabilitiesAdapter) {
Method isCapableOf = capabilitiesAdapter.method(Modifier.PUBLIC, context.getCodeModel().BOOLEAN, "isCapableOf");
Variable capability = isCapableOf.param(ref(Capability.class), "capability");
isCapableOf.javadoc().add("Returns true if this module implements such capability");
addCapability(isCapableOf, capability, ref(Capability.class).staticRef("LIFECYCLE_CAPABLE"));
if (typeElement.hasAnnotation(OAuth2.class)) {
addCapability(isCapableOf, capability, ref(Capability.class).staticRef("OAUTH2_CAPABLE"));
}
if (typeElement.hasAnnotation(OAuth.class)) {
addCapability(isCapableOf, capability, ref(Capability.class).staticRef("OAUTH1_CAPABLE"));
}
if (typeElement.isPoolable()) {
addCapability(isCapableOf, capability, ref(Capability.class).staticRef("POOLING_CAPABLE"));
}
ExecutableElement connectMethod = connectMethodForClass(typeElement);
ExecutableElement disconnectMethod = disconnectMethodForClass(typeElement);
if (connectMethod != null && disconnectMethod != null) {
addCapability(isCapableOf, capability, ref(Capability.class).staticRef("CONNECTION_MANAGEMENT_CAPABLE"));
}
isCapableOf.body()._return(ExpressionFactory.FALSE);
}
private void addCapability(Method capableOf, Variable capability, FieldRef capabilityToCheckFor) {
Conditional isCapable = capableOf.body()._if(Op.eq(capability, capabilityToCheckFor));
isCapable._then()._return(ExpressionFactory.TRUE);
}
}