org.mule.devkit.apt.model.AnnotationProcessorIdentifiable.java Source code

Java tutorial

Introduction

Here is the source code for org.mule.devkit.apt.model.AnnotationProcessorIdentifiable.java

Source

/**
 * 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.apt.model;

import com.sun.source.util.Trees;
import org.apache.commons.lang.StringUtils;
import org.mule.api.NestedProcessor;
import org.mule.api.callback.HttpCallback;
import org.mule.devkit.model.Identifiable;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.xml.bind.annotation.XmlType;
import java.lang.annotation.Annotation;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

public class AnnotationProcessorIdentifiable<T extends Element, P extends Identifiable>
        implements Identifiable<T, P> {
    protected T innerElement;
    protected P parent;
    protected Types types;
    protected Elements elements;
    protected Trees trees;

    public AnnotationProcessorIdentifiable(T element, P parent, Types types, Elements elements, Trees trees) {
        this.innerElement = element;
        this.parent = parent;
        this.types = types;
        this.elements = elements;
        this.trees = trees;
    }

    public P parent() {
        return this.parent;
    }

    public T unwrap() {
        return innerElement;
    }

    @Override
    public TypeMirror asType() {
        return innerElement.asType();
    }

    @Override
    public List<? extends AnnotationMirror> getAnnotationMirrors() {
        return innerElement.getAnnotationMirrors();
    }

    @Override
    public <A extends Annotation> A getAnnotation(Class<A> aClass) {
        return (A) innerElement.getAnnotation(aClass);
    }

    @Override
    public Name getSimpleName() {
        return innerElement.getSimpleName();
    }

    @Override
    public boolean isXmlType() {
        if (asType().getKind() == TypeKind.DECLARED) {

            DeclaredType declaredType = (DeclaredType) asType();
            XmlType xmlType = declaredType.asElement().getAnnotation(XmlType.class);

            if (xmlType != null) {
                return true;
            }
        }

        return false;
    }

    @Override
    public boolean isPublic() {
        return innerElement.getModifiers().contains(Modifier.PUBLIC);
    }

    @Override
    public boolean isPrivate() {
        return innerElement.getModifiers().contains(Modifier.PRIVATE);
    }

    @Override
    public boolean isProtected() {
        return innerElement.getModifiers().contains(Modifier.PROTECTED);
    }

    @Override
    public boolean isAbstract() {
        return innerElement.getModifiers().contains(Modifier.PROTECTED);
    }

    @Override
    public boolean isFinal() {
        return innerElement.getModifiers().contains(Modifier.FINAL);
    }

    @Override
    public boolean isStatic() {
        return innerElement.getModifiers().contains(Modifier.STATIC);
    }

    @Override
    public boolean isCollection() {
        return isArrayOrList(asType()) || isMap(asType());
    }

    @Override
    public boolean isNestedProcessor() {
        if (asType().toString().startsWith(NestedProcessor.class.getName())) {
            return true;
        }

        if (asType().toString().startsWith(List.class.getName())) {
            DeclaredType variableType = (DeclaredType) asType();
            List<? extends TypeMirror> variableTypeParameters = variableType.getTypeArguments();
            if (variableTypeParameters.isEmpty()) {
                return false;
            }

            if (variableTypeParameters.get(0).toString().startsWith(NestedProcessor.class.getName())) {
                return true;
            }
        }

        return false;
    }

    @Override
    public boolean isArrayOrList() {
        return isArrayOrList(asType());
    }

    private boolean isArrayOrList(TypeMirror type) {
        if (type.toString().equals("byte[]")) {
            return false;
        }

        if (type.getKind() == TypeKind.ARRAY) {
            return true;
        }

        if (type.toString().startsWith(List.class.getName())) {
            return true;
        }

        List<? extends TypeMirror> inherits = types.directSupertypes(type);
        for (TypeMirror inherit : inherits) {
            if (isArrayOrList(inherit)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public boolean isMap() {
        return isMap(asType());
    }

    private boolean isMap(TypeMirror type) {
        if (type.toString().startsWith(Map.class.getName())) {
            return true;
        }

        List<? extends TypeMirror> inherits = types.directSupertypes(type);
        for (TypeMirror inherit : inherits) {
            if (isMap(inherit)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public boolean isEnum() {
        return isEnum(asType());
    }

    private boolean isEnum(TypeMirror type) {
        if (type.toString().startsWith(Enum.class.getName())) {
            return true;
        }

        List<? extends TypeMirror> inherits = types.directSupertypes(type);
        for (TypeMirror inherit : inherits) {
            if (isEnum(inherit)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public List<Identifiable> getTypeArguments() {
        List<Identifiable> typeArguments = new ArrayList<Identifiable>();
        DeclaredType declaredType = (DeclaredType) asType();
        for (TypeMirror typeMirror : declaredType.getTypeArguments()) {
            if (typeMirror instanceof WildcardType || typeMirror instanceof TypeVariable) {
                continue;
            }
            Element element = types.asElement(typeMirror);
            if (element instanceof TypeElement) {
                typeArguments.add(new AnnotationProcessorType((TypeElement) element, types, elements, trees));
            } else {
                typeArguments.add(new AnnotationProcessorIdentifiable(element, this, types, elements, trees));
            }
        }

        return typeArguments;
    }

    @Override
    public boolean hasTypeArguments() {
        return getTypeArguments().size() > 0;
    }

    @Override
    public boolean isString() {
        String className = innerElement.asType().toString();
        return className.startsWith(String.class.getName());
    }

    @Override
    public boolean isBoolean() {
        String className = innerElement.asType().toString();
        return className.startsWith(Boolean.class.getName()) || className.startsWith("boolean");
    }

    @Override
    public boolean isInteger() {
        String className = innerElement.asType().toString();
        return className.startsWith(Integer.class.getName()) || className.startsWith("int");
    }

    @Override
    public boolean isLong() {
        String className = innerElement.asType().toString();
        return className.startsWith(Long.class.getName()) || className.startsWith("long");
    }

    @Override
    public boolean isFloat() {
        String className = innerElement.asType().toString();
        return className.startsWith(Float.class.getName()) || className.startsWith("float");
    }

    @Override
    public boolean isDouble() {
        String className = innerElement.asType().toString();
        return className.startsWith(Double.class.getName()) || className.startsWith("double");
    }

    @Override
    public boolean isChar() {
        String className = innerElement.asType().toString();
        return className.startsWith(Character.class.getName()) || className.startsWith("char");
    }

    @Override
    public boolean isHttpCallback() {
        return innerElement.asType().toString().startsWith(HttpCallback.class.getName());
    }

    @Override
    public boolean isURL() {
        return innerElement.asType().toString().startsWith(URL.class.getName());
    }

    @Override
    public boolean isDate() {
        return innerElement.asType().toString().startsWith(Date.class.getName());
    }

    @Override
    public boolean isBigDecimal() {
        return innerElement.asType().toString().startsWith(BigDecimal.class.getName());
    }

    @Override
    public boolean isBigInteger() {
        return innerElement.asType().toString().startsWith(BigInteger.class.getName());
    }

    @Override
    public String getJavaDocSummary() {
        String comment = elements.getDocComment(innerElement);
        if (comment == null || StringUtils.isBlank(comment)) {
            return null;
        }

        comment = comment.trim();

        String parsedComment = "";
        boolean tagsBegan = false;
        StringTokenizer st = new StringTokenizer(comment, "\n\r");
        while (st.hasMoreTokens()) {
            String nextToken = st.nextToken().trim();
            if (nextToken.startsWith("@")) {
                tagsBegan = true;
            }
            if (!tagsBegan) {
                parsedComment = parsedComment + nextToken + "\n";
            }
        }

        String strippedComments = "";
        boolean insideTag = false;
        for (int i = 0; i < parsedComment.length(); i++) {
            if (parsedComment.charAt(i) == '{' && parsedComment.charAt(i + 1) == '@') {
                insideTag = true;
            } else if (parsedComment.charAt(i) == '}') {
                insideTag = false;
            } else {
                if (!insideTag) {
                    strippedComments += parsedComment.charAt(i);
                }
            }
        }

        strippedComments = strippedComments.trim();
        while (strippedComments.length() > 0 && strippedComments.charAt(strippedComments.length() - 1) == '\n') {
            strippedComments = StringUtils.chomp(strippedComments);
        }

        return strippedComments;
    }

    @Override
    public boolean hasJavaDocTag(String tagName) {
        String comment = elements.getDocComment(innerElement);
        if (StringUtils.isBlank(comment)) {
            return false;
        }

        StringTokenizer st = new StringTokenizer(comment.trim(), "\n\r");
        while (st.hasMoreTokens()) {
            String nextToken = st.nextToken().trim();
            if (nextToken.startsWith("@" + tagName)) {
                String tagContent = StringUtils.difference("@" + tagName, nextToken);
                return !StringUtils.isBlank(tagContent);
            }
            if (nextToken.startsWith("{@" + tagName)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public String getJavaDocTagContent(String tagName) {
        String comment = elements.getDocComment(innerElement);
        if (StringUtils.isBlank(comment)) {
            return "";
        }

        StringTokenizer st = new StringTokenizer(comment.trim(), "\n\r");
        boolean insideTag = false;
        StringBuilder tagContent = new StringBuilder();
        while (st.hasMoreTokens()) {
            String nextToken = st.nextToken().trim();
            if (nextToken.startsWith("@" + tagName)) {
                return StringUtils.difference("@" + tagName, nextToken).trim();
            }
            if (nextToken.startsWith("{@" + tagName)) {
                if (nextToken.endsWith("}")) {
                    return StringUtils.difference("{@" + tagName, nextToken).replaceAll("}", "").trim();
                } else {
                    tagContent.append(StringUtils.difference("{@" + tagName, nextToken).replaceAll("}", "").trim());
                    insideTag = true;
                }
            } else if (insideTag) {
                if (nextToken.endsWith("}")) {
                    tagContent.append(' ').append(nextToken.replaceAll("}", ""));
                    insideTag = false;
                } else {
                    tagContent.append(' ').append(nextToken);
                }
            }
        }

        return tagContent.toString();
    }

    @Override
    public String getJavaDocParameterSummary(String paramName) {
        String comment = elements.getDocComment(innerElement);
        if (StringUtils.isBlank(comment)) {
            return null;
        }

        comment = comment.trim();

        StringBuilder parameterCommentBuilder = new StringBuilder();
        boolean insideParameter = false;
        StringTokenizer st = new StringTokenizer(comment, "\n\r");
        while (st.hasMoreTokens()) {
            String nextToken = st.nextToken().trim();
            if (nextToken.startsWith("@param " + paramName + " ") || nextToken.equals("@param " + paramName)) {
                insideParameter = true;
            } else if (nextToken.startsWith("@")) {
                insideParameter = false;
            }
            if (insideParameter) {
                parameterCommentBuilder.append(nextToken).append(" ");
            }
        }

        int startIndex = 7 + paramName.length() + 1;
        if (parameterCommentBuilder.length() < startIndex) {
            return null;
        }

        String parameterComment = parameterCommentBuilder.substring(startIndex);

        StringBuilder strippedCommentBuilder = new StringBuilder();
        boolean insideTag = false;
        for (int i = 0; i < parameterComment.length(); i++) {
            if (parameterComment.charAt(i) == '{' && parameterComment.charAt(i + 1) == '@') {
                insideTag = true;
            } else if (parameterComment.charAt(i) == '}') {
                insideTag = false;
            } else {
                if (!insideTag) {
                    strippedCommentBuilder.append(parameterComment.charAt(i));
                }
            }
        }

        String strippedComment = strippedCommentBuilder.toString().trim();
        while (strippedComment.length() > 0 && strippedComment.charAt(strippedComment.length() - 1) == '\n') {
            strippedComment = StringUtils.chomp(strippedComment);
        }

        return strippedComment;
    }
}