From 4b3d36f6897fd64d4101416ab472924f23f63fe9 Mon Sep 17 00:00:00 2001 From: shafaat Date: Wed, 8 Sep 2021 21:21:47 +0800 Subject: [PATCH] Adding generator app --- .gitignore | 135 +++++++++++++++++++++++ README.md | 15 +++ pom.xml | 51 +++++++++ src/main/java/App.java | 139 ++++++++++++++++++++++++ src/main/java/Constants.java | 33 ++++++ src/main/resources/Data_Dictionary.xlsx | Bin 0 -> 10789 bytes 6 files changed, 373 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/java/App.java create mode 100644 src/main/java/Constants.java create mode 100644 src/main/resources/Data_Dictionary.xlsx diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..54a6e95 --- /dev/null +++ b/.gitignore @@ -0,0 +1,135 @@ +###################### +# Project Specific +###################### +/src/main/webapp/content/css/main.css +/target/classes/static/** +/src/test/javascript/coverage/ + + + +###################### +# Eclipse +###################### +*.pydevproject +.project +.metadata +tmp/ +tmp/**/* +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath +.factorypath +/src/main/resources/rebel.xml + +# External tool builders +.externalToolBuilders/** + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + +# STS-specific +/.sts4-cache/* + +###################### +# IntelliJ +###################### +.idea/ +*.iml +*.iws +*.ipr +*.ids +*.orig +classes/ +out/ + +###################### +# Visual Studio Code +###################### +.vscode/ + +###################### +# Maven +###################### +/log/ +/target/ + +###################### +# Gradle +###################### +.gradle/ +/build/ + +###################### +# Package Files +###################### +*.jar +*.war +*.ear +*.db + +###################### +# Windows +###################### +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + +###################### +# Mac OSX +###################### +.DS_Store +.svn + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +###################### +# Directories +###################### +/bin/ +/deploy/ + +###################### +# Logs +###################### +*.log* + +###################### +# Others +###################### +*.class +*.*~ +*~ +.merge_file* + +###################### +# Gradle Wrapper +###################### +!gradle/wrapper/gradle-wrapper.jar + +###################### +# Maven Wrapper +###################### +!.mvn/wrapper/maven-wrapper.jar + +###################### +# ESLint +###################### +.eslintcache diff --git a/README.md b/README.md new file mode 100644 index 0000000..85b47ef --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Script Generator + +This small app helps to generate DDL statements from the excel file + +## Usage + +Before you start to generate the scripts, follow below +1. Java: The running machine should have at least java 8 installed +2. File: The sample xlxs file is located in resources folder. This can be modified as but the format should remain the same +3. Open the application in any IDE (eclipse / Intellij) +4. Right click on App.java and run +5. The scripts will be generated in the console log + + +> Note: `id` column will be auto generated for all tables \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5970382 --- /dev/null +++ b/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + org.example + scripts-generator + 1.0-SNAPSHOT + + + 8 + 8 + + + + + + org.apache.poi + poi + 4.1.2 + + + + + commons-io + commons-io + 2.4 + + + + + org.apache.poi + poi-ooxml + 4.1.2 + + + + + org.apache.poi + poi-ooxml-schemas + 4.1.2 + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/App.java b/src/main/java/App.java new file mode 100644 index 0000000..ced2ff5 --- /dev/null +++ b/src/main/java/App.java @@ -0,0 +1,139 @@ +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; + +public class App { + public static void main(String args[]) throws IOException + { + //obtaining input bytes from a file + App tc = new App(); + + InputStream fis = tc.getClass().getClassLoader().getResourceAsStream("Data_Dictionary.xlsx"); + + //creating workbook instance that refers to .xls file + XSSFWorkbook wb=new XSSFWorkbook(fis); + //creating a Sheet object to retrieve the object + XSSFSheet sheet = wb.getSheetAt(0); //creating a Sheet object to retrieve object + Iterator itr = sheet.iterator(); //iterating over excel file + + String prevTableName = ""; + + int rowCount = 0; + + StringBuilder sb = new StringBuilder(); + StringBuilder foreignKeyBuilder = new StringBuilder(); + + while (itr.hasNext()) + { + + Row row = itr.next(); + + // Skip first row. It's header + if(rowCount == 0){ + rowCount++; + continue; + } + + String tempTableName = ""; + + + + tempTableName = row.getCell(0).getStringCellValue(); + + if(tempTableName !=null && tempTableName.length() > 0){ + + if(!tempTableName.equals(prevTableName)){ + + + System.out.println(_finishOffCreate(sb.append(foreignKeyBuilder.toString()))); + sb = new StringBuilder(); + foreignKeyBuilder = new StringBuilder(); + + + sb.append(Constants.CREATE_TABLE + + tempTableName + + Constants.BRACKET_OPEN + + Constants.NEW_LINE); + + sb.append(Constants.constructColumn( + "id", + "bigint,\n" + )); + + + sb.append(Constants.constructColumn( + row.getCell(1).getStringCellValue(), + row.getCell(2).getStringCellValue() + )); + sb.append(Constants.COMMA + Constants.NEW_LINE); + + _buildForeignKeys(row, foreignKeyBuilder); + + prevTableName = tempTableName; + }else{ + sb.append(Constants.constructColumn( + row.getCell(1).getStringCellValue(), + row.getCell(2).getStringCellValue() + )); + + _buildForeignKeys(row, foreignKeyBuilder); + + sb.append(Constants.COMMA + Constants.NEW_LINE); + } + + } + rowCount++; + } + } + + private static void _buildForeignKeys(Row row, StringBuilder foreignKeyBuilder) { + // Check for any foreign keys + if( row.getCell(3) != null && "Y".equalsIgnoreCase(row.getCell(3).getStringCellValue()) ){ + String currentTableName = row.getCell(0).getStringCellValue(); + String parentTableName = row.getCell(4).getStringCellValue(); + + foreignKeyBuilder.append( + Constants.SPACE + Constants.SPACE + Constants.SPACE + + + Constants.CONSTRAINT + Constants.SPACE + + + (Constants.FK_PREFIX + Constants.UNDERSCORE + + currentTableName.substring(0,8) + Constants.UNDERSCORE + + parentTableName.substring(0,8) + + Constants.SPACE + Constants.NEW_LINE ) + + + Constants.SPACE + Constants.SPACE + Constants.SPACE + Constants.SPACE + + + Constants.FOREIGN_KEY+ + + (Constants.BRACKET_OPEN + row.getCell(1).getStringCellValue() + Constants.BRACKET_CLOSE)+ Constants.SPACE + + + Constants.REFERENCES + Constants.SPACE + + + (row.getCell(5).getStringCellValue() + Constants.BRACKET_OPEN + row.getCell(1).getStringCellValue() + Constants.BRACKET_CLOSE)+ + + Constants.COMMA + Constants.NEW_LINE); + } + } + + private static String _finishOffCreate(StringBuilder createStatement){ + + if(createStatement.length() > 0){ +// System.out.println(createStatement.toString()); + int lastIndexOfComma=createStatement.lastIndexOf(Constants.COMMA); + + createStatement.deleteCharAt(lastIndexOfComma); + + createStatement.append( Constants.BRACKET_CLOSE + Constants.SEMI_COLON + Constants.NEW_LINE); + + + createStatement.replace(lastIndexOfComma, lastIndexOfComma, ""); + return createStatement.toString(); + } + return ""; + } +} diff --git a/src/main/java/Constants.java b/src/main/java/Constants.java new file mode 100644 index 0000000..339b59f --- /dev/null +++ b/src/main/java/Constants.java @@ -0,0 +1,33 @@ +import com.sun.org.apache.bcel.internal.generic.NEW; + +public class Constants { + public static final String CREATE_TABLE="CREATE TABLE "; + public static final String BRACKET_OPEN="("; + public static final String BRACKET_CLOSE=")"; + public static final String SPACE="\t"; + public static final String NEW_LINE="\n"; + public static final String COMMA=","; + + + //Data types + public static final String TYPE_VARCHAR="VARCHAR"; + public static final String TYPE_INT="INT"; + public static final String TYPE_DECIMAL="DECIMAL"; + public static final String TYPE_DATETIME="DATETIME"; + public static final String TYPE_DATE="DATE"; + public static final String BIT="bit"; + public static final String SEMI_COLON = ";"; + + + //Foreign Key Constraint + public static final String REFERENCES = "REFERENCES"; + public static final String CONSTRAINT = "CONSTRAINT"; + public static final String FOREIGN_KEY = "FOREIGN KEY"; + public static final String FK_PREFIX = "fk"; + public static final String UNDERSCORE = "_"; + + + public static String constructColumn(String columnName, String dataType){ + return SPACE + SPACE + SPACE + columnName + SPACE + dataType; + } +} diff --git a/src/main/resources/Data_Dictionary.xlsx b/src/main/resources/Data_Dictionary.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2093e6de15a62310a20b13da4a0047977dc440e2 GIT binary patch literal 10789 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 k@V}eDzrrV}{sRBQAgahigLfAIKmdQ