org.ez18n.apt.processor.LabelBundleProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.ez18n.apt.processor.LabelBundleProcessor.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to you 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.ez18n.apt.processor;

import static java.lang.Character.isUpperCase;
import static javax.tools.StandardLocation.SOURCE_OUTPUT;
import static org.apache.commons.lang3.StringUtils.isEmpty;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.tools.Diagnostic.Kind;
import javax.tools.FileObject;

import org.ez18n.Message;
import org.ez18n.MessageBundle;
import org.ez18n.apt.LabelTemplateMethod;
import org.ez18n.apt.base.EGenerationType;
import org.ez18n.apt.base.TemplateAnnotation;
import org.ez18n.apt.base.TemplateAnnotationProcessor;
import org.ez18n.apt.base.TemplateParam;

abstract class LabelBundleProcessor extends TemplateAnnotationProcessor<LabelTemplateMethod> {
    static final String NO_VALUE = "#no_value#";
    static final String NO_MESSAGE = "###no_message###";

    private final EGenerationType generationType;

    protected LabelBundleProcessor() {
        this(EGenerationType.SOURCE);
    }

    protected LabelBundleProcessor(EGenerationType generationType) {
        this.generationType = generationType;
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (roundEnv.processingOver()) {
            return true;
        }
        final List<LabelTemplateMethod> methods = new ArrayList<LabelTemplateMethod>();
        for (Element element : roundEnv.getElementsAnnotatedWith(MessageBundle.class)) {
            if (element.getKind() != ElementKind.INTERFACE) {
                continue;
            }
            final TypeElement bundleType = (TypeElement) element;
            processLabels(bundleType, methods);
            try {

                FileObject file = null;
                switch (generationType) {
                case SOURCE:
                    file = processingEnv.getFiler().createSourceFile(getTargetClassName(bundleType), bundleType);
                    break;

                case RESSOURCE:
                    file = processingEnv.getFiler().createResource(SOURCE_OUTPUT,
                            bundleType.getEnclosingElement().toString(),
                            getTargetSimpleName(bundleType) + ".properties");
                    break;
                }

                final Writer writer = file.openWriter();
                writer.write(getCode(bundleType, methods));
                writer.close();
            } catch (IOException e) {
                processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), bundleType);
            } finally {
                methods.clear();
            }
        }
        return false;
    }

    protected abstract String getCode(TypeElement bundleType, List<LabelTemplateMethod> methods);

    private void processLabels(TypeElement resourcesType, List<LabelTemplateMethod> methods) {
        for (Element element : resourcesType.getEnclosedElements()) {
            if (element.getKind() != ElementKind.METHOD) {
                continue;
            }
            final ExecutableElement method = (ExecutableElement) element;
            Message labelAnnotation = element.getAnnotation(Message.class);
            final TemplateParam returnType = new TemplateParam(method.getReturnType().toString());
            final boolean deprecated = method.getAnnotation(Deprecated.class) != null;
            final LabelTemplateMethod labelMethod;
            try {
                labelMethod = new LabelTemplateMethod(method.getSimpleName().toString(), deprecated, returnType,
                        labelAnnotation.value(), labelAnnotation.mobile());
            } catch (Throwable t) {
                processingEnv.getMessager().printMessage(Kind.WARNING, t.getMessage(), resourcesType);
                continue;
            }

            for (VariableElement variable : method.getParameters()) {
                final String paramName = variable.getSimpleName().toString();
                final String paramType = variable.asType().toString();

                List<TemplateAnnotation> annotations = new ArrayList<TemplateAnnotation>();
                for (AnnotationMirror annotationMirrors : variable.getAnnotationMirrors()) {
                    annotations.add(new TemplateAnnotation(annotationMirrors.getAnnotationType().toString()));
                }

                labelMethod.getParams().add(new TemplateParam(paramType, paramName, annotations));
            }
            methods.add(labelMethod);
        }
    }

    protected void checkTemplateMethod(TypeElement bundleType, LabelTemplateMethod method) {
        if (isEmpty(method.getMobile())) {
            processingEnv.getMessager().printMessage(Kind.WARNING, "mobile message is empty", bundleType);
        }

        if (method.getBase().equals(method.getMobile(false))) {
            processingEnv.getMessager().printMessage(Kind.WARNING,
                    method.getName() + ": duplicate mobile & desktop messages, mobile value can be removed",
                    bundleType);
        }
    }

    protected static String toCamelCase(TypeElement typeElement) {
        return toCamelCase(typeElement.getSimpleName().toString());
    }

    protected static String toCamelCase(String string) {
        final StringBuffer result = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            final char charAt = string.charAt(i);
            if (isUpperCase(charAt)) {
                result.append(charAt);
            }
        }
        return result.toString();
    }

}