Java tutorial
/** * Mogwai ERDesigner. Copyright (C) 2002 The Mogwai Project. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. */ package de.erdesignerng.generator.openxava; import de.erdesignerng.dialect.DataType; import de.erdesignerng.model.Attribute; import de.erdesignerng.model.Model; import de.erdesignerng.model.Relation; import de.erdesignerng.model.Table; import japa.parser.ASTHelper; import japa.parser.JavaParser; import japa.parser.ParseException; import japa.parser.ast.CompilationUnit; import japa.parser.ast.ImportDeclaration; import japa.parser.ast.PackageDeclaration; import japa.parser.ast.body.*; import japa.parser.ast.expr.*; import japa.parser.ast.expr.AssignExpr.Operator; import japa.parser.ast.stmt.BlockStmt; import japa.parser.ast.stmt.ReturnStmt; import japa.parser.ast.type.ClassOrInterfaceType; import japa.parser.ast.type.Type; import japa.parser.ast.visitor.VoidVisitorAdapter; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import java.io.*; import java.util.ArrayList; import java.util.List; public class OpenXavaGenerator { private static final String JAVA_ENCODING = "UTF-8"; private static final Logger LOGGER = Logger.getLogger(OpenXavaGenerator.class); public OpenXavaGenerator() { } private CompilationUnit createNewCompilationUnit(String aPackageName, String aMainTypeName) { CompilationUnit theUnit = new CompilationUnit(); if (!StringUtils.isEmpty(aPackageName)) { theUnit.setPackage(new PackageDeclaration(ASTHelper.createNameExpr(aPackageName))); } List<ImportDeclaration> theImports = new ArrayList<>(); theImports.add(new ImportDeclaration(ASTHelper.createNameExpr("java.util"), false, true)); theImports.add(new ImportDeclaration(ASTHelper.createNameExpr("javax.persistence"), false, true)); theImports.add(new ImportDeclaration(ASTHelper.createNameExpr("org.openxava.annotations"), false, true)); theUnit.setImports(theImports); ClassOrInterfaceDeclaration theType = new ClassOrInterfaceDeclaration(ModifierSet.PUBLIC, false, aMainTypeName); ASTHelper.addTypeDeclaration(theUnit, theType); return theUnit; } private CompilationUnit createCompilationUnitFromFile(File aFile) throws IOException { FileInputStream theStream = null; try { theStream = new FileInputStream(aFile); return JavaParser.parse(theStream); } catch (ParseException e) { throw new IOException(e); } finally { if (theStream != null) { theStream.close(); } } } public void generate(Model aModel, OpenXavaOptions aOptions) throws IOException { String thePackageName = aOptions.getPackageName(); File theTargetDirectory = new File(aOptions.getSrcDirectory()); if (!StringUtils.isEmpty(thePackageName)) { theTargetDirectory = new File(theTargetDirectory, thePackageName.replace('.', File.separatorChar)); } if (theTargetDirectory.exists()) { LOGGER.info("Target directory " + theTargetDirectory + " exists"); } else { LOGGER.info("Target directory " + theTargetDirectory + " will be created"); theTargetDirectory.mkdirs(); } for (Table theTable : aModel.getTables()) { String theTableClassName = aOptions.createTableName(theTable.getName()); LOGGER.info("Processing generated code for " + theTableClassName); File theTargetFile = new File(theTargetDirectory, theTableClassName + ".java"); CompilationUnit theUnit; if (!theTargetFile.exists()) { LOGGER.info("Creating new file for " + theTableClassName + " at " + theTargetFile); theUnit = createNewCompilationUnit(thePackageName, theTableClassName); } else { theUnit = createCompilationUnitFromFile(theTargetFile); } updateCompilationUnit(aModel, aOptions, theTable, theUnit); PrintWriter theWriter = new PrintWriter( new OutputStreamWriter(new FileOutputStream(theTargetFile), JAVA_ENCODING)); theWriter.print(theUnit.toString()); theWriter.close(); } } private void updateCompilationUnit(Model aModel, OpenXavaOptions aOptions, Table aTable, CompilationUnit aUnit) { ClassOrInterfaceDeclaration theType = null; for (TypeDeclaration theDeclaration : aUnit.getTypes()) { if (theDeclaration instanceof ClassOrInterfaceDeclaration) { theType = (ClassOrInterfaceDeclaration) theDeclaration; break; } } if (theType == null) { throw new RuntimeException("Cannot find main type"); } // Check the fields theType.accept(new VoidVisitorAdapter() { @Override public void visit(FieldDeclaration aField, Object aArg) { ClassOrInterfaceDeclaration theClass = (ClassOrInterfaceDeclaration) aArg; if (aField.getVariables().size() != 1) { throw new RuntimeException("Cannot parse Java Type : " + theClass.getName() + ". Please make sure to declare only one field per statement!"); } } }, theType); List<FieldDeclaration> thePersistentFields = new ArrayList<>(); OpenXavaASTHelper.addMarkerAnnotationTo("Entity", theType); for (Attribute<Table> theAttribute : aTable.getAttributes()) { String theFieldName = aOptions.createFieldName(theAttribute.getName()); if (!theAttribute.isForeignKey()) { DataType theDataType = theAttribute.getDatatype(); OpenXavaTypeMap theMap = aOptions.getTypeMapping().get(theDataType); String theJavaType = aOptions.getJavaType(theDataType, theAttribute.isNullable(), theAttribute.isPrimaryKey()); String theStereoType = theMap.getStereoType(); FieldDeclaration theDeclaration = OpenXavaASTHelper.findFieldDeclaration(theFieldName, theType); if (theDeclaration == null) { theDeclaration = ASTHelper.createFieldDeclaration(ModifierSet.PRIVATE, new ClassOrInterfaceType(theJavaType), theFieldName); ASTHelper.addMember(theType, theDeclaration); } else { theDeclaration.setType(new ClassOrInterfaceType(theJavaType)); } thePersistentFields.add(theDeclaration); if (theAttribute.isPrimaryKey()) { OpenXavaASTHelper.addMarkerAnnotationTo("Id", theDeclaration); } else { OpenXavaASTHelper.removeAnnotationFrom("Id", theDeclaration); } if (!theAttribute.isNullable()) { OpenXavaASTHelper.addMarkerAnnotationTo("Required", theDeclaration); } else { OpenXavaASTHelper.removeAnnotationFrom("Required", theDeclaration); } if (!StringUtils.isEmpty(theStereoType)) { OpenXavaASTHelper.addSingleMemberAnnotationTo("Stereotype", new StringLiteralExpr(theStereoType), theDeclaration); } else { OpenXavaASTHelper.removeAnnotationFrom("Stereotype", theDeclaration); } List<MemberValuePair> theValues = new ArrayList<>(); theValues.add(new MemberValuePair("name", new StringLiteralExpr(theAttribute.getName()))); if (theDataType.supportsSize() && theAttribute.getSize() != null) { theValues.add(new MemberValuePair("length", new IntegerLiteralExpr(Integer.toString(theAttribute.getSize())))); } if (theDataType.supportsFraction() && theAttribute.getFraction() != null) { theValues.add(new MemberValuePair("precision", new IntegerLiteralExpr(Integer.toString(theAttribute.getFraction())))); } if (theDataType.supportsScale()) { theValues.add(new MemberValuePair("scale", new IntegerLiteralExpr(Integer.toString(theAttribute.getScale())))); } if (!theAttribute.isNullable() && !theAttribute.isPrimaryKey()) { theValues.add(new MemberValuePair("nullable", new BooleanLiteralExpr(false))); } else { theValues.add(new MemberValuePair("nullable", new BooleanLiteralExpr(true))); } OpenXavaASTHelper.overwriteNormalAnnotation("Column", theValues, theDeclaration); } } // Generate the associations for (Relation theRelation : aModel.getRelations().getExportedKeysFor(aTable)) { if (theRelation.getMapping().size() == 1 && !theRelation.getExportingTable().equals(theRelation.getImportingTable())) { Table theImportingTable = theRelation.getImportingTable(); String theImpFieldName = aOptions.createFieldName(theImportingTable.getName()); String theImpTableClassName = aOptions.createTableName(theImportingTable.getName()); FieldDeclaration theDeclaration = OpenXavaASTHelper.findFieldDeclaration(theImpFieldName, theType); if (theDeclaration == null) { ClassOrInterfaceType theRelationType = new ClassOrInterfaceType("Set"); List<Type> theTypeArgs = new ArrayList<>(); theTypeArgs.add(new ClassOrInterfaceType(theImpTableClassName)); theRelationType.setTypeArgs(theTypeArgs); theDeclaration = ASTHelper.createFieldDeclaration(ModifierSet.PRIVATE, theRelationType, theImpFieldName); ASTHelper.addMember(theType, theDeclaration); } else { ClassOrInterfaceType theRelationType = new ClassOrInterfaceType("Set"); List<Type> theTypeArgs = new ArrayList<>(); theTypeArgs.add(new ClassOrInterfaceType(theImpTableClassName)); theRelationType.setTypeArgs(theTypeArgs); theDeclaration.setType(theRelationType); } thePersistentFields.add(theDeclaration); OpenXavaASTHelper.addMarkerAnnotationTo("OneToMany", theDeclaration); } else { LOGGER.warn("Ignoring relation " + theRelation.getName() + " is there are either more than one mapping attribute or it is a self reference"); } } if (theType.getMembers() != null) { List<FieldDeclaration> theFieldsToRemove = new ArrayList<>(); // Test if the field is marked as persistent and is not a // persistent attribute theType.getMembers().stream().filter(theDeclaration -> theDeclaration instanceof FieldDeclaration) .forEach(theDeclaration -> { FieldDeclaration theField = (FieldDeclaration) theDeclaration; // Test if the field is marked as persistent and is not a // persistent attribute if (OpenXavaASTHelper.hasAnnotation("Column", theDeclaration) && !thePersistentFields.contains(theField)) { theFieldsToRemove.add(theField); } }); theType.getMembers().removeAll(theFieldsToRemove); // Remove the getter and setter for the removed fields List<MethodDeclaration> theMethodsToRemove = new ArrayList<>(); for (FieldDeclaration theField : theFieldsToRemove) { String theName = theField.getVariables().get(0).getId().getName(); String thePropertyName = aOptions.createPropertyName(theName); boolean isBoolean = "boolean".equals(theField.getType().toString()); String theMethodName = "set" + thePropertyName; MethodDeclaration theMethod = OpenXavaASTHelper.findMethodDeclaration(theMethodName, theType); if (theMethod != null) { theMethodsToRemove.add(theMethod); } if (isBoolean) { theMethodName = "is" + thePropertyName; } else { theMethodName = "get" + thePropertyName; } theMethod = OpenXavaASTHelper.findMethodDeclaration(theMethodName, theType); if (theMethod != null) { theMethodsToRemove.add(theMethod); } } theType.getMembers().removeAll(theMethodsToRemove); } for (FieldDeclaration theField : thePersistentFields) { String theName = theField.getVariables().get(0).getId().getName(); String thePropertyName = aOptions.createPropertyName(theName); boolean isBoolean = "boolean".equals(theField.getType().toString()); String theMethodName = "set" + thePropertyName; MethodDeclaration theSetMethod = OpenXavaASTHelper.findMethodDeclaration(theMethodName, theType); if (theSetMethod == null) { theSetMethod = new MethodDeclaration(ModifierSet.PUBLIC, ASTHelper.VOID_TYPE, theMethodName); List<Parameter> theParams = new ArrayList<>(); theParams.add(ASTHelper.createParameter(theField.getType(), "aValue")); theSetMethod.setParameters(theParams); BlockStmt theBlock = new BlockStmt(); ASTHelper.addStmt(theBlock, new AssignExpr(new NameExpr(theName), new NameExpr("aValue"), Operator.assign)); theSetMethod.setBody(theBlock); ASTHelper.addMember(theType, theSetMethod); } else { List<Parameter> theParams = new ArrayList<>(); theParams.add(ASTHelper.createParameter(theField.getType(), "aValue")); theSetMethod.setParameters(theParams); } if (isBoolean) { theMethodName = "is" + thePropertyName; } else { theMethodName = "get" + thePropertyName; } MethodDeclaration theGetMethod = OpenXavaASTHelper.findMethodDeclaration(theMethodName, theType); if (theGetMethod == null) { theGetMethod = new MethodDeclaration(ModifierSet.PUBLIC, theField.getType(), theMethodName); BlockStmt theBlock = new BlockStmt(); ASTHelper.addStmt(theBlock, new ReturnStmt(new NameExpr(theName))); theGetMethod.setBody(theBlock); ASTHelper.addMember(theType, theGetMethod); } else { theGetMethod.setType(theField.getType()); } } } }