Java tutorial
/* x * 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.ArrayList; 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.Assignment; import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.BooleanLiteral; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.EnumConstantDeclaration; import org.eclipse.jdt.core.dom.EnumDeclaration; import org.eclipse.jdt.core.dom.ExpressionStatement; import org.eclipse.jdt.core.dom.FieldAccess; 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.NumberLiteral; import org.eclipse.jdt.core.dom.PackageDeclaration; import org.eclipse.jdt.core.dom.ReturnStatement; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.jdt.core.dom.ThisExpression; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Enumeration; import org.eclipse.uml2.uml.EnumerationLiteral; import org.eclipse.uml2.uml.Property; import org.eclipse.uml2.uml.Slot; import org.eclipse.uml2.uml.Type; import org.eclipse.uml2.uml.ValueSpecification; import de.crowdcode.kissmda.core.jdt.JdtHelper; import de.crowdcode.kissmda.core.uml.PackageHelper; /** * Generate enumeration from UML enumeration. * * <p> * Most important helper classes from kissmda-core which are used in this * Transformer: PackageHelper. * </p> * * @author Lofi Dewanto * @version 1.0.0 * @since 1.0.0 */ public class EnumGenerator { private static final Logger logger = Logger.getLogger(EnumGenerator.class.getName()); @Inject private PackageHelper packageHelper; @Inject private InterfaceGenerator interfaceGenerator; @Inject private JdtHelper jdtHelper; private String sourceDirectoryPackageName; private ArrayList<String> constructorParameterNames = new ArrayList<String>(); public void setConstructorParameterNames(ArrayList<String> constructorParameterNames) { this.constructorParameterNames = constructorParameterNames; } /** * Generate the Class Interface. This is the main generation part for this * SimpleJavaTransformer. * * @param Class * clazz the UML class * @return CompilationUnit the complete class with its content as a String */ public CompilationUnit generateEnum(Classifier clazz, String sourceDirectoryPackageName) { this.sourceDirectoryPackageName = sourceDirectoryPackageName; AST ast = AST.newAST(AST.JLS3); CompilationUnit cu = ast.newCompilationUnit(); generatePackage(clazz, ast, cu); EnumDeclaration ed = generateEnum(clazz, ast, cu); generateAttributes(clazz, ast, ed); generateConstructor(clazz, ast, ed); generateConstants(clazz, ast, ed); generateGetterMethod(clazz, ast, ed); logger.log(Level.INFO, "Compilation unit: \n\n" + cu.toString()); return cu; } /** * Generate the attributes. * * @param clazz * UML2 class * @param ast * JDT AST * @param ed * EnumerationDeclaration */ @SuppressWarnings("unchecked") public void generateAttributes(Classifier clazz, AST ast, EnumDeclaration ed) { EList<Property> properties = clazz.getAttributes(); for (Property property : properties) { ed.bodyDeclarations().add(generateAttribute(clazz, ast, property)); } } /** * Generate the attribute. * * @param clazz * UM2 class * @param ast * JDT AST * @param property * UML2 property * @return FieldDeclaration */ public FieldDeclaration generateAttribute(Classifier clazz, AST ast, Property property) { Type type = property.getType(); logger.log(Level.FINE, "Class: " + clazz.getName() + " - " + "Property: " + property.getName() + " - " + "Property Upper: " + property.getUpper() + " - " + "Property Lower: " + property.getLower()); String umlTypeName = type.getName(); String umlQualifiedTypeName = type.getQualifiedName(); // Check whether primitive or array type or simple type? org.eclipse.jdt.core.dom.Type chosenType = jdtHelper.getChosenType(ast, umlTypeName, umlQualifiedTypeName, sourceDirectoryPackageName); VariableDeclarationFragment fragment = ast.newVariableDeclarationFragment(); SimpleName variableName = ast.newSimpleName(property.getName()); fragment.setName(variableName); FieldDeclaration fieldDeclaration = ast.newFieldDeclaration(fragment); fieldDeclaration.setType(chosenType); return fieldDeclaration; } /** * Generate getter method. * * @param clazz * UML2 classifier * @param ast * JDT AST tree * @param ed * EnumDeclaration JDT */ @SuppressWarnings("unchecked") public void generateGetterMethod(Classifier clazz, AST ast, EnumDeclaration ed) { EList<Property> properties = clazz.getAttributes(); for (Property property : properties) { Type type = property.getType(); logger.log(Level.FINE, "Class: " + clazz.getName() + " - " + "Property: " + property.getName() + " - " + "Property Upper: " + property.getUpper() + " - " + "Property Lower: " + property.getLower()); String umlTypeName = type.getName(); String umlQualifiedTypeName = type.getQualifiedName(); MethodDeclaration methodDeclaration = interfaceGenerator.generateGetterMethod(ast, ed, property, umlTypeName, umlQualifiedTypeName, sourceDirectoryPackageName); // Public methodDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD)); // Content of getter method Block block = ast.newBlock(); ReturnStatement returnStatement = ast.newReturnStatement(); SimpleName simpleName = ast.newSimpleName(property.getName()); returnStatement.setExpression(simpleName); block.statements().add(returnStatement); methodDeclaration.setBody(block); } } /** * Generate getter method. Use this method if you need to call the method * generateGetterMethod from outside this class. * * @param clazz * UML2 classifier * @param ast * JDT AST tree * @param ed * EnumDeclaration JDT * @param sourceDirectoryPackageName * root package name of the UML model */ public void generateGetterMethod(Classifier clazz, AST ast, EnumDeclaration ed, String sourceDirectoryPackageName) { this.sourceDirectoryPackageName = sourceDirectoryPackageName; generateGetterMethod(clazz, ast, ed); } /** * Generate constructor. * * @param clazz * UML2 class * @param ast * JDT AST * @param ed * EnumDeclaration JDT */ @SuppressWarnings("unchecked") public void generateConstructor(Classifier clazz, AST ast, EnumDeclaration ed) { // Constructor MethodDeclaration md = ast.newMethodDeclaration(); md.setConstructor(true); md.setName(ast.newSimpleName(clazz.getName())); md.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD)); ed.bodyDeclarations().add(md); // We need to build contructor parameters for each properties generateContructorParameters(clazz, ast, md); // Content of constructor Block block = ast.newBlock(); EList<Property> properties = clazz.getAttributes(); for (Property property : properties) { logger.log(Level.FINE, "Class: " + clazz.getName() + " - " + "Property: " + property.getName() + " - " + "Property Upper: " + property.getUpper() + " - " + "Property Lower: " + property.getLower()); // Left expression SimpleName simpleName = ast.newSimpleName(property.getName()); ThisExpression thisExpression = ast.newThisExpression(); FieldAccess fieldAccess = ast.newFieldAccess(); fieldAccess.setName(simpleName); fieldAccess.setExpression(thisExpression); // Right expression SimpleName parameter = ast.newSimpleName(property.getName()); Assignment assignment = ast.newAssignment(); assignment.setOperator(org.eclipse.jdt.core.dom.Assignment.Operator.ASSIGN); assignment.setLeftHandSide(fieldAccess); assignment.setRightHandSide(parameter); // Expression ExpressionStatement expressionStatement = ast.newExpressionStatement(assignment); block.statements().add(expressionStatement); } // Set Body to MethodDeclaration md.setBody(block); } @SuppressWarnings("unchecked") void generateContructorParameters(Classifier clazz, AST ast, MethodDeclaration md) { // Empty the list first constructorParameterNames.clear(); EList<Property> constructorProperties = clazz.getAttributes(); for (Property constructorProperty : constructorProperties) { Type constructorType = constructorProperty.getType(); // Save the variable declaration for later use constructorParameterNames.add(constructorProperty.getName()); logger.log(Level.FINE, "Class: " + clazz.getName() + " - " + "Constructor property: " + constructorProperty.getName() + " - " + "Constructor property Upper: " + constructorProperty.getUpper() + " - " + "Constructor property Lower: " + constructorProperty.getLower()); String contructorUmlTypeName = constructorType.getName(); String constructorUmlQualifiedTypeName = constructorType.getQualifiedName(); // Check whether primitive or array type or simple type? org.eclipse.jdt.core.dom.Type constructorChosenType = jdtHelper.getChosenType(ast, contructorUmlTypeName, constructorUmlQualifiedTypeName, sourceDirectoryPackageName); SingleVariableDeclaration variableDeclaration = ast.newSingleVariableDeclaration(); variableDeclaration.setType(constructorChosenType); variableDeclaration.setName(ast.newSimpleName(constructorProperty.getName())); md.parameters().add(variableDeclaration); } } /** * Generate the Enum from UML. * * @param clazz * the UML class * @param ast * the JDT Java AST * @param cu * the generated Java compilation unit * @return EnumDeclaration */ @SuppressWarnings("unchecked") public EnumDeclaration generateEnum(Classifier clazz, AST ast, CompilationUnit cu) { String className = getClassName(clazz); EnumDeclaration ed = ast.newEnumDeclaration(); ed.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD)); ed.setName(ast.newSimpleName(className)); cu.types().add(ed); return ed; } /** * 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 */ public 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); } /** * Generate Enumeration constants. * * @param clazz * the UML class * @param ast * the JDT Java AST * @param ed * Enumeration declaration for Java JDT */ @SuppressWarnings("unchecked") public void generateConstants(Classifier clazz, AST ast, EnumDeclaration ed) { // Get all properties for this enumeration Enumeration enumeration = (Enumeration) clazz; EList<EnumerationLiteral> enumerationLiterals = enumeration.getOwnedLiterals(); for (EnumerationLiteral enumLiteral : enumerationLiterals) { EnumConstantDeclaration ec = ast.newEnumConstantDeclaration(); ec.setName(ast.newSimpleName(enumLiteral.getName().toUpperCase())); // We need to sort the arguments so that it match the // constructor arguments! if (!constructorParameterNames.isEmpty()) { for (String constructorParameterName : constructorParameterNames) { logger.log(Level.FINE, "constructorParameterName: " + constructorParameterNames.toString()); Slot slot = findSlotByName(constructorParameterName, enumLiteral); if (slot != null) { // We found a slot with the same name Property property = (Property) slot.getDefiningFeature(); Type type = property.getType(); chooseLiteralTypeAndAddToEnumConstantArguments(ast, ec, slot, type); } else { // We didn't find the slot with the same name as in the // constructor logger.log(Level.SEVERE, "EnumGenerator: Error in Generating Enum: we cannot find the correct slot by its name as it was given by the constructor!"); // Doing something intelligent... // So we are adding the literal to the EnumConstant // arguments just as it is, so this is not intelligent // at the moment... getSlotsNotIntelligent(ast, enumLiteral, ec); } } } else { // Constructor parameter types is empty // So we are adding the literal to the EnumConstant arguments // just as it is getSlotsNotIntelligent(ast, enumLiteral, ec); } ed.enumConstants().add(ec); } } private void getSlotsNotIntelligent(AST ast, EnumerationLiteral enumLiteral, EnumConstantDeclaration ec) { EList<Slot> slots = enumLiteral.getSlots(); for (Slot slot : slots) { Property property = (Property) slot.getDefiningFeature(); Type type = property.getType(); chooseLiteralTypeAndAddToEnumConstantArguments(ast, ec, slot, type); } } @SuppressWarnings("unchecked") void chooseLiteralTypeAndAddToEnumConstantArguments(AST ast, EnumConstantDeclaration ec, Slot slot, Type type) { EList<ValueSpecification> valueSpecifications = slot.getValues(); for (ValueSpecification valueSpecification : valueSpecifications) { if (type.getName().equalsIgnoreCase("Integer")) { NumberLiteral numberLiteral = ast.newNumberLiteral(); numberLiteral.setToken(String.valueOf(valueSpecification.integerValue())); ec.arguments().add(numberLiteral); } else if (type.getName().equalsIgnoreCase("Long")) { NumberLiteral numberLiteral = ast.newNumberLiteral(); numberLiteral.setToken(String.valueOf(valueSpecification.integerValue()).concat("L")); ec.arguments().add(numberLiteral); } else if (type.getName().equalsIgnoreCase("Boolean")) { BooleanLiteral booleanLiteral = ast.newBooleanLiteral(valueSpecification.booleanValue()); ec.arguments().add(booleanLiteral); } else if (type.getName().equalsIgnoreCase("String")) { StringLiteral stringLiteral = ast.newStringLiteral(); stringLiteral.setLiteralValue(valueSpecification.stringValue()); ec.arguments().add(stringLiteral); } } } Slot findSlotByName(String name, EnumerationLiteral enumLiteral) { EList<Slot> slots = enumLiteral.getSlots(); for (Slot slot : slots) { Property property = (Property) slot.getDefiningFeature(); String slotPropertyName = property.getName(); if (slotPropertyName.equals(name)) { // We found it return slot; } } // We finished but cannot find it return null; } private String getClassName(Classifier clazz) { String className = clazz.getName(); return className; } private String getFullPackageName(Classifier clazz) { String fullPackageName = packageHelper.getFullPackageName(clazz, sourceDirectoryPackageName); return fullPackageName; } }