/**
* 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.studio.editor;
import org.apache.commons.lang.WordUtils;
import org.mule.api.annotations.Processor;
import org.mule.api.annotations.Source;
import org.mule.api.annotations.display.FriendlyName;
import org.mule.api.annotations.display.Icons;
import org.mule.api.annotations.display.Password;
import org.mule.api.annotations.display.Summary;
import org.mule.api.annotations.param.Default;
import org.mule.api.annotations.param.Optional;
import org.mule.devkit.GeneratorContext;
import org.mule.devkit.generation.DevKitTypeElement;
import org.mule.devkit.generation.spring.SchemaGenerator;
import org.mule.devkit.generation.spring.SchemaTypeConversion;
import org.mule.devkit.model.studio.AttributeType;
import org.mule.devkit.model.studio.Booleantype;
import org.mule.devkit.model.studio.EncodingType;
import org.mule.devkit.model.studio.EnumType;
import org.mule.devkit.model.studio.FlowRefType;
import org.mule.devkit.model.studio.IntegerType;
import org.mule.devkit.model.studio.NestedElementReference;
import org.mule.devkit.model.studio.ObjectFactory;
import org.mule.devkit.model.studio.PasswordType;
import org.mule.devkit.model.studio.StringAttributeType;
import org.mule.devkit.model.studio.TextType;
import org.mule.devkit.model.studio.UrlType;
import org.mule.devkit.utils.JavaDocUtils;
import org.mule.devkit.utils.NameUtils;
import org.mule.devkit.utils.TypeMirrorUtils;
import org.mule.util.StringUtils;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.xml.bind.JAXBElement;
import java.util.ArrayList;
import java.util.List;
public class MuleStudioUtils {
private static final String IMAGE_PREFIX = "icons/large/";
private static final String ICON_PREFIX = "icons/small/";
private NameUtils nameUtils;
private JavaDocUtils javaDocUtils;
private TypeMirrorUtils typeMirrorUtils;
public MuleStudioUtils(GeneratorContext context) {
nameUtils = context.getNameUtils();
javaDocUtils = context.getJavaDocUtils();
typeMirrorUtils = context.getTypeMirrorUtils();
}
public String formatCaption(String caption) {
return WordUtils.capitalizeFully(caption);
}
public String formatDescription(String description) {
if (Character.isLowerCase(description.charAt(0))) {
description = StringUtils.capitalize(description);
}
if (!description.endsWith(".")) {
description += '.';
}
return description.replaceAll("\\<.*?\\>", "");
}
public String getConnectorImage(DevKitTypeElement typeElement) {
Icons icons = typeElement.getAnnotation(Icons.class);
String image;
if(icons != null) {
image = icons.connectorLarge();
} else {
image = String.format(Icons.GENERIC_CLOUD_CONNECTOR_LARGE, typeElement.name());
}
if(image.contains("/")) {
image = image.substring(image.lastIndexOf("/") +1);
}
return IMAGE_PREFIX + image;
}
public String getConnectorIcon(DevKitTypeElement typeElement) {
Icons icons = typeElement.getAnnotation(Icons.class);
String icon;
if(icons != null) {
icon = icons.connectorSmall();
} else {
icon = String.format(Icons.GENERIC_CLOUD_CONNECTOR_SMALL, typeElement.name());
}
if(icon.contains("/")) {
icon = icon.substring(icon.lastIndexOf("/") +1);
}
return ICON_PREFIX + icon;
}
public String getEndpointImage(DevKitTypeElement typeElement) {
Icons icons = typeElement.getAnnotation(Icons.class);
String image;
if(icons != null) {
image = icons.endpointLarge();
} else {
image = String.format(Icons.GENERIC_ENDPOINT_LARGE, typeElement.name());
}
if(image.contains("/")) {
image = image.substring(image.lastIndexOf("/") +1);
}
return IMAGE_PREFIX + image;
}
public String getEndpointIcon(DevKitTypeElement typeElement) {
Icons icons = typeElement.getAnnotation(Icons.class);
String icon;
if(icons != null) {
icon = icons.endpointSmall();
} else {
icon = String.format(Icons.GENERIC_ENDPOINT_SMALL, typeElement.name());
}
if(icon.contains("/")) {
icon = icon.substring(icon.lastIndexOf("/") +1);
}
return ICON_PREFIX + icon;
}
public String getTransformerImage(DevKitTypeElement typeElement) {
Icons icons = typeElement.getAnnotation(Icons.class);
String image;
if(icons != null) {
image = icons.transformerLarge();
} else {
image = String.format(Icons.GENERIC_TRANSFORMER_LARGE, typeElement.name());
}
if(image.contains("/")) {
image = image.substring(image.lastIndexOf("/") +1);
}
return IMAGE_PREFIX + image;
}
public String getTransformerIcon(DevKitTypeElement typeElement) {
Icons icons = typeElement.getAnnotation(Icons.class);
String icon;
if(icons != null) {
icon = icons.transformerSmall();
} else {
icon = String.format(Icons.GENERIC_TRANSFORMER_SMALL, typeElement.name());
}
if(icon.contains("/")) {
icon = icon.substring(icon.lastIndexOf("/") +1);
}
return ICON_PREFIX + icon;
}
public String getGlobalRefId(String moduleName) {
return "abstract" + StringUtils.capitalize(moduleName) + "ConnectorGeneric";
}
public List<JAXBElement<? extends AttributeType>> createJAXBElements(List<AttributeType> attributeTypes) {
List<JAXBElement<? extends AttributeType>> jaxbElements = new ArrayList<JAXBElement<? extends AttributeType>>();
for (AttributeType attributeType : attributeTypes) {
JAXBElement<? extends AttributeType> jaxbElement = createJAXBElement(attributeType);
if (jaxbElement != null) {
jaxbElements.add(jaxbElement);
}
}
return jaxbElements;
}
public JAXBElement<? extends AttributeType> createJAXBElement(AttributeType attributeType) {
ObjectFactory objectFactory = new ObjectFactory();
if (attributeType instanceof PasswordType) {
return objectFactory.createGroupPassword((PasswordType) attributeType);
}
if (attributeType instanceof UrlType) {
return objectFactory.createGroupUrl((UrlType) attributeType);
}
if (attributeType instanceof StringAttributeType) {
return objectFactory.createGroupString((StringAttributeType) attributeType);
}
if (attributeType instanceof IntegerType) { // TODO: Studio has a problem with LongType, until that's resolved map longs to integer
return objectFactory.createGroupInteger((IntegerType) attributeType);
}
if (attributeType instanceof EnumType) {
return objectFactory.createGroupEnum((EnumType) attributeType);
}
if (attributeType instanceof Booleantype) {
return objectFactory.createGroupBoolean((Booleantype) attributeType);
}
if (attributeType instanceof TextType) {
return objectFactory.createGroupText((TextType) attributeType);
}
if (attributeType instanceof FlowRefType) {
return objectFactory.createGroupFlowRef((FlowRefType) attributeType);
}
if (attributeType instanceof EncodingType) {
return objectFactory.createGroupEncoding((EncodingType) attributeType);
}
if (attributeType instanceof NestedElementReference) {
return objectFactory.createNestedElementTypeChildElement((NestedElementReference) attributeType);
}
return null;
}
public AttributeType createAttributeTypeIgnoreEnumsAndCollections(Element element) {
if (skipAttributeTypeGeneration(element)) {
return null;
} else if (SchemaTypeConversion.isSupported(element.asType().toString())) {
return createAttributeTypeOfSupportedType(element);
} else if (typeMirrorUtils.isHttpCallback(element)) {
FlowRefType flowRefType = new FlowRefType();
flowRefType.setSupportFlow(true);
flowRefType.setSupportSubflow(true);
return flowRefType;
} else {
return new StringAttributeType();
}
}
private boolean skipAttributeTypeGeneration(Element element) {
return typeMirrorUtils.isCollection(element.asType()) || typeMirrorUtils.isEnum(element.asType()) || typeMirrorUtils.ignoreParameter(element);
}
private AttributeType createAttributeTypeOfSupportedType(Element element) {
if (element.getAnnotation(Password.class) != null) {
return new PasswordType();
}
if (typeMirrorUtils.isString(element) || typeMirrorUtils.isDate(element) || typeMirrorUtils.isChar(element) ||
typeMirrorUtils.isFloat(element) || typeMirrorUtils.isDouble(element)) {
return new StringAttributeType();
} else if (typeMirrorUtils.isBoolean(element)) {
Booleantype booleantype = new Booleantype();
booleantype.setSupportsExpressions(true);
return booleantype;
} else if (typeMirrorUtils.isInteger(element) || typeMirrorUtils.isLong(element)) {
IntegerType integerType = new IntegerType();
integerType.setMin(0);
integerType.setStep(1);
return integerType;
} else if (typeMirrorUtils.isURL(element)) {
return new UrlType();
} else {
throw new RuntimeException("Failed to create Studio XML, type not recognized: type=" + element.asType().toString() + " name=" + element.getSimpleName().toString());
}
}
public void setAttributeTypeInfo(VariableElement variableElement, AttributeType attributeType) {
String parameterName = variableElement.getSimpleName().toString();
attributeType.setCaption(getFormattedCaption(variableElement));
attributeType.setDescription(getFormattedDescription(variableElement));
if (attributeType instanceof StringAttributeType && !SchemaTypeConversion.isSupported(variableElement.asType().toString())) {
attributeType.setName(parameterName + SchemaGenerator.REF_SUFFIX);
} else if (attributeType instanceof FlowRefType) {
attributeType.setName(nameUtils.uncamel(parameterName) + SchemaGenerator.FLOW_REF_SUFFIX);
} else {
attributeType.setName(parameterName);
}
attributeType.setRequired(variableElement.getAnnotation(Optional.class) == null);
attributeType.setJavaType(typeMirrorUtils.getJavaType(variableElement));
setDefaultValueIfAvailable(variableElement, attributeType);
}
public void setDefaultValueIfAvailable(VariableElement variableElement, AttributeType parameter) {
Default annotation = variableElement.getAnnotation(Default.class);
if (annotation != null) {
if (parameter instanceof Booleantype) {
((Booleantype) parameter).setDefaultValue(Boolean.valueOf(annotation.value()));
} else if (parameter instanceof IntegerType) {
((IntegerType) parameter).setDefaultValue(Integer.valueOf(annotation.value()));
} else if (parameter instanceof StringAttributeType) {
((StringAttributeType) parameter).setDefaultValue(annotation.value());
} else if (parameter instanceof EnumType) {
((EnumType) parameter).setDefaultValue(annotation.value());
}
}
}
public String getLocalId(ExecutableElement executableElement, VariableElement variableElement) {
if (executableElement != null) {
return nameUtils.uncamel(executableElement.getSimpleName().toString()) + '-' + nameUtils.uncamel(variableElement.getSimpleName().toString());
} else {
return "configurable-" + nameUtils.uncamel(variableElement.getSimpleName().toString());
}
}
public String getFormattedDescription(VariableElement element) {
Summary description = element.getAnnotation(Summary.class);
if (description != null && StringUtils.isNotBlank(description.value())) {
return formatDescription(description.value());
}
if (element.getKind() == ElementKind.PARAMETER) {
Element executableElement = element.getEnclosingElement();
return formatDescription(javaDocUtils.getParameterSummary(element.getSimpleName().toString(), executableElement));
}
return formatDescription(javaDocUtils.getSummary(element));
}
public String getFormattedDescription(DevKitTypeElement typeElement) {
if(StringUtils.isNotBlank(typeElement.description())) {
return typeElement.description();
}
return formatDescription(javaDocUtils.getSummary(typeElement));
}
public String getFormattedCaption(DevKitTypeElement typeElement) {
if(StringUtils.isNotBlank(typeElement.friendlyName())) {
return typeElement.friendlyName();
}
return formatCaption(typeElement.name().replaceAll("-", " "));
}
public String getFormattedCaption(ExecutableElement element) {
return formatCaption(getFriendlyName(element));
}
public String getFormattedCaption(VariableElement element) {
FriendlyName caption = element.getAnnotation(FriendlyName.class);
if (caption != null && StringUtils.isNotBlank(caption.value())) {
return caption.value();
}
String friendlyName = nameUtils.friendlyNameFromCamelCase(element.getSimpleName().toString());
if (typeMirrorUtils.isHttpCallback(element)) {
return formatCaption(friendlyName + " Flow");
}
if (!isKnownType(element)) {
return formatCaption(friendlyName + " Reference");
}
return formatCaption(friendlyName);
}
public String getFriendlyName(ExecutableElement element) {
Processor processor = element.getAnnotation(Processor.class);
if(processor != null && StringUtils.isNotBlank(processor.friendlyName())) {
return processor.friendlyName();
}
Source source = element.getAnnotation(Source.class);
if(source != null && StringUtils.isNotBlank(source.friendlyName())) {
return source.friendlyName();
}
return nameUtils.friendlyNameFromCamelCase(element.getSimpleName().toString());
}
public boolean isKnownType(VariableElement variable) {
return typeMirrorUtils.isString(variable) ||
typeMirrorUtils.isChar(variable) ||
typeMirrorUtils.isDate(variable) ||
typeMirrorUtils.isDouble(variable) ||
typeMirrorUtils.isFloat(variable) ||
typeMirrorUtils.isLong(variable) ||
typeMirrorUtils.isHttpCallback(variable) ||
typeMirrorUtils.isInteger(variable) ||
typeMirrorUtils.isBoolean(variable) ||
typeMirrorUtils.isEnum(variable) ||
typeMirrorUtils.isCollection(variable) ||
typeMirrorUtils.isURL(variable);
}
}