de.crowdcode.kissmda.cartridges.simplejava.ExceptionGenerator.java Source code

Java tutorial

Introduction

Here is the source code for de.crowdcode.kissmda.cartridges.simplejava.ExceptionGenerator.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 de.crowdcode.kissmda.cartridges.simplejava;

import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.inject.Inject;

import org.eclipse.emf.common.util.EList;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NumberLiteral;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Generalization;

import de.crowdcode.kissmda.core.TransformerException;
import de.crowdcode.kissmda.core.jdt.JdtHelper;
import de.crowdcode.kissmda.core.uml.PackageHelper;

/**
 * Generate Exception from UML class.
 * 
 * <p>
 * Most important helper classes from kissmda-core which are used in this
 * Transformer: InterfaceGenerator, JdtHelper.
 * </p>
 * 
 * @author Lofi Dewanto
 * @version 1.1.0
 * @since 1.1.0
 */
public class ExceptionGenerator {

    private static final Logger logger = Logger.getLogger(ExceptionGenerator.class.getName());

    @Inject
    private InterfaceGenerator interfaceGenerator;

    @Inject
    private PackageHelper packageHelper;

    @Inject
    private JdtHelper jdtHelper;

    private String sourceDirectoryPackageName;

    private boolean isCheckedException = true;

    /**
     * Set this exception as checked exception.
     * 
     * @param isCheckedException
     *            boolean
     */
    public void setCheckedException(boolean isCheckedException) {
        this.isCheckedException = isCheckedException;
    }

    /**
     * Generate the Class Exception.
     * 
     * @param Class
     *            clazz the UML class
     * @return CompilationUnit the complete class with its content as a String
     * @throws TransformerException
     */
    public CompilationUnit generateCheckedException(Classifier clazz, String sourceDirectoryPackageName) {
        this.sourceDirectoryPackageName = sourceDirectoryPackageName;
        this.isCheckedException = true;
        CompilationUnit cu = generateException(clazz);
        return cu;
    }

    /**
     * Generate the Class RuntimeException.
     * 
     * @param Class
     *            clazz the UML class
     * @return CompilationUnit the complete class with its content as a String
     */
    public CompilationUnit generateUncheckedException(Classifier clazz, String sourceDirectoryPackageName) {
        this.sourceDirectoryPackageName = sourceDirectoryPackageName;
        this.isCheckedException = false;
        CompilationUnit cu = generateException(clazz);
        return cu;
    }

    /**
     * Generate general Exception. This will be called by Unchecked and Checked
     * Exception generation.
     * 
     * @param clazz
     *            UML class
     * @return JDT compilation unit
     */
    private CompilationUnit generateException(Classifier clazz) {
        AST ast = AST.newAST(AST.JLS3);
        CompilationUnit cu = ast.newCompilationUnit();

        generatePackage(clazz, ast, cu);
        TypeDeclaration td = generateClass(clazz, ast, cu);
        generateSerialVersionUID(clazz, ast, td);
        generateMethods(clazz, ast, td);
        generateConstructors(clazz, ast, td);

        logger.log(Level.INFO, "Compilation unit: \n\n" + cu.toString());
        return cu;
    }

    /**
     * Generate the serial version UID for the Exception class.
     * 
     * @param clazz
     *            UML class
     * @param ast
     *            JDT AST tree
     * @param td
     *            JDT type declaration (Class)
     */
    @SuppressWarnings("unchecked")
    public void generateSerialVersionUID(Classifier clazz, AST ast, TypeDeclaration td) {
        VariableDeclarationFragment fragment = ast.newVariableDeclarationFragment();
        SimpleName variableName = ast.newSimpleName("serialVersionUID");
        fragment.setName(variableName);
        NumberLiteral initializer = ast.newNumberLiteral();
        initializer.setToken("1L");
        fragment.setInitializer(initializer);

        FieldDeclaration fieldDeclaration = ast.newFieldDeclaration(fragment);
        fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD));
        fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.STATIC_KEYWORD));
        fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
        fieldDeclaration.setType(ast.newPrimitiveType(PrimitiveType.LONG));

        td.bodyDeclarations().add(fieldDeclaration);
    }

    /**
     * Generate the Exception Class.
     * 
     * @param clazz
     *            the UML class
     * @param ast
     *            the JDT Java AST
     * @param cu
     *            the generated Java compilation unit
     * @return TypeDeclaration JDT
     */
    @SuppressWarnings("unchecked")
    public TypeDeclaration generateClass(Classifier clazz, AST ast, CompilationUnit cu) {
        String className = getClassName(clazz);
        TypeDeclaration td = ast.newTypeDeclaration();
        td.setInterface(false);
        td.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
        td.setName(ast.newSimpleName(className));

        // Add inheritance
        generateClassInheritance(clazz, ast, td);
        // Add template params
        generateClassTemplateParams(clazz, ast, td);

        cu.types().add(td);

        return td;
    }

    /**
     * {@link InterfaceGenerator #generateClassTemplateParams(Classifier, AST, TypeDeclaration)}
     */
    private void generateClassTemplateParams(Classifier clazz, AST ast, TypeDeclaration td) {
        interfaceGenerator.generateClassTemplateParams(clazz, ast, td);
    }

    /**
     * Generate the inheritance for the Exception Class "extends". Important:
     * Java only supports single inheritance!
     * 
     * @param clazz
     *            the UML class
     * @param ast
     *            the JDT Java AST
     * @param td
     *            TypeDeclaration JDT
     */
    private void generateClassInheritance(Classifier clazz, AST ast, TypeDeclaration td) {
        EList<Generalization> generalizations = clazz.getGeneralizations();
        if (generalizations != null) {
            if (!generalizations.isEmpty()) {
                if (generalizations.size() == 1) {
                    // Java only supports one Generatlization
                    for (Generalization generalization : generalizations) {
                        Classifier interfaceClassifier = generalization.getGeneral();
                        String fullQualifiedInterfaceName = interfaceClassifier.getQualifiedName();
                        Name name = jdtHelper.createFullQualifiedTypeAsName(ast, fullQualifiedInterfaceName,
                                sourceDirectoryPackageName);
                        SimpleType simpleType = ast.newSimpleType(name);
                        td.setSuperclassType(simpleType);
                    }
                } else {
                    throw new TransformerException(
                            "Java only supports single inheritance! Wrong modeling in class: "
                                    + clazz.getQualifiedName());
                }
            } else {
                // Empty, we extend from java.lang.Exception or
                // java.lang.RuntimeException
                String exceptionToBeInherited = "Exception";
                if (!isCheckedException) {
                    exceptionToBeInherited = "RuntimeException";
                }
                SimpleType simpleType = ast.newSimpleType(ast.newSimpleName(exceptionToBeInherited));
                td.setSuperclassType(simpleType);
            }
        }
    }

    /**
     * Generate the Java package from UML package.
     * 
     * @param clazz
     *            the UML class
     * @param ast
     *            the JDT Java AST
     * @param cu
     *            the generated Java compilation unit
     */
    private void generatePackage(Classifier clazz, AST ast, CompilationUnit cu) {
        PackageDeclaration pd = ast.newPackageDeclaration();
        String fullPackageName = getFullPackageName(clazz);
        pd.setName(ast.newName(fullPackageName));

        Date now = new Date();
        String commentDate = "Generation date: " + now.toString() + ".";

        interfaceGenerator.generatePackageJavadoc(ast, pd, PackageComment.CONTENT_1.getValue(),
                PackageComment.CONTENT_2.getValue(), " ", PackageComment.CONTENT_3.getValue(), " ", commentDate);

        cu.setPackage(pd);
    }

    /**
     * {@link InterfaceGenerator #generateMethods(Classifier, AST, TypeDeclaration)}
     */
    private void generateMethods(Classifier clazz, AST ast, TypeDeclaration td) {
        interfaceGenerator.generateMethods(clazz, ast, td);
    }

    /**
     * Generate the constructors for Exception.
     * 
     * @param clazz
     *            the UML class
     * @param ast
     *            the JDT Java AST
     * @param td
     *            TypeDeclaration JDT
     */
    public void generateConstructors(Classifier clazz, AST ast, TypeDeclaration td) {
        // Default constructor
        generateConstructorDefault(clazz, ast, td);
        // Param: Throwable exception
        generateConstructorWithParams(clazz, ast, td, new String[] { "Throwable" }, new String[] { "cause" });
        // Param: String message
        generateConstructorWithParams(clazz, ast, td, new String[] { "String" }, new String[] { "message" });
        // Param: String message, Throwable throwable
        generateConstructorWithParams(clazz, ast, td, new String[] { "String", "Throwable" },
                new String[] { "message", "cause" });
    }

    @SuppressWarnings("unchecked")
    public void generateConstructorWithParams(Classifier clazz, AST ast, TypeDeclaration td, String[] varTypes,
            String[] varNames) {
        MethodDeclaration constructor = ast.newMethodDeclaration();
        constructor.setConstructor(true);
        constructor.setName(ast.newSimpleName(clazz.getName()));
        constructor.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));

        for (int index = 0; index < varTypes.length; index++) {
            SingleVariableDeclaration variableDeclaration = ast.newSingleVariableDeclaration();
            variableDeclaration.setType(ast.newSimpleType(ast.newSimpleName(varTypes[index])));
            variableDeclaration.setName(ast.newSimpleName(varNames[index]));
            constructor.parameters().add(variableDeclaration);
        }

        Block block = ast.newBlock();
        SuperConstructorInvocation constructorInvocation = ast.newSuperConstructorInvocation();

        for (int index = 0; index < varNames.length; index++) {
            constructorInvocation.arguments().add(ast.newSimpleName(varNames[index]));
        }

        block.statements().add(constructorInvocation);
        constructor.setBody(block);
        td.bodyDeclarations().add(constructor);
    }

    @SuppressWarnings("unchecked")
    private void generateConstructorDefault(Classifier clazz, AST ast, TypeDeclaration td) {
        MethodDeclaration constructor = ast.newMethodDeclaration();
        constructor.setConstructor(true);
        constructor.setName(ast.newSimpleName(clazz.getName()));
        constructor.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
        Block block = ast.newBlock();

        constructor.setBody(block);
        td.bodyDeclarations().add(constructor);
    }

    private String getClassName(Classifier clazz) {
        String className = clazz.getName();
        return className;
    }

    private String getFullPackageName(Classifier clazz) {
        String fullPackageName = packageHelper.getFullPackageName(clazz, sourceDirectoryPackageName);
        return fullPackageName;
    }
}