├── LICENSE ├── README.md ├── file.csv ├── file.java ├── out └── artifacts │ └── CsvEnumGenerator_jar │ ├── CsvEnumGenerator.jar │ ├── countries.csv │ └── countries.java ├── pom.xml └── src ├── META-INF └── MANIFEST.MF └── com └── danesisinni ├── CSVEnumGenerator.java └── Main.java /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Dane Sisinni 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java Enum Generator - from CSV files 2 | Generates java Enums from CSV files 3 | 4 | ## Goals 5 | * enables seamless generation of Java enums for large datasets 6 | 7 | ## Formating the CSV file 8 | * the CSV file must be properly formatted in order for the generator to run properly 9 | * the first line of the CSV consists of all the variable types/names 10 | * one of the header cells must contain the word `VALUE` which indicates the column is reserved for the enum constant names 11 | * example header: `VALUE,String country,String code` 12 | 13 | ## Running from the Command Line 14 | * The jar file is located in `out/artificats/CsvEnumGenerator_jar` 15 | * Argument Ordering: 16 | 1. CSV file to read from 17 | 2. Name of the enum 18 | 3. output file 19 | * Running the generator from the command line: `java -jar CsvEnumGenerator.jar csvFile.csv ENUMNAME enumname.java` 20 | * if using Intellij use `Ctrl+Alt+L` to reformat the enum source code 21 | 22 | ## Sample parseable CSV 23 | ```csv 24 | VALUE,String countryName,String alpha2,String alpha3 25 | CANADA,Canada,CA,CAN 26 | UNITED_STATES,United States,US,USA 27 | ``` 28 | * aside from the reserved `VALUE` cell header, all other headers must contain a space to separate the variable type and variable name 29 | 30 | ## Generating with custom data types 31 | * whenever a custom data type is used simply create an additional constructor after the enum is generated that parses the String and converts it to the specified object type 32 | 33 | #### Custom data type example 34 | ```csv 35 | VALUE,String countryName,LocalDate foundedOn 36 | CANADA,Canada,1867-07-01 37 | UNITED_STATES,United States of America,1776-07-04 38 | ``` 39 | ##### Generated Enum: `java -jar CsvEnumGenerator.jar countries.csv COUNTRY countries.java` 40 | ```java 41 | public enum COUNTRY { 42 | 43 | CANADA("Canada","1867-07-01"), 44 | UNITED_STATES("United States Of America","1776-07-04"); 45 | 46 | private final String countryName; 47 | private final LocalDate foundedOn; 48 | 49 | 50 | COUNTRY(String countryName,LocalDate foundedOn) { 51 | this.countryName = countryName; 52 | this.foundedOn = foundedOn; 53 | } 54 | 55 | public String getCountryName() { 56 | return this.countryName; 57 | } 58 | 59 | public LocalDate getFoundedOn() { 60 | return this.foundedOn; 61 | } 62 | } 63 | ``` 64 | 65 | ##### Code to add: 66 | ```java 67 | private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); 68 | 69 | COUNTRY(String countryName, String foundedOn) { 70 | LocalDate date = LocalDate.parse(foundedOn, formatter); 71 | this(countryName, date); 72 | } 73 | ``` 74 | * As you can see for large data sets the csv-enum generator will signficantly reduce the manual work/number of lines a developer has to write 75 | 76 | ## Technologies Used 77 | * Java 8 78 | * Maven 79 | * Guava 80 | * Lombok 81 | * Apache Commons Lang 82 | * Apache Commons CSV 83 | 84 | Please feel free to reach out if there are any improvements that can be made or if you have any questions :) 85 | -------------------------------------------------------------------------------- /file.csv: -------------------------------------------------------------------------------- 1 | VALUE,String x,int y,LocalDateTime blob 2 | CANADA,canada,1,2014-05-07 14:23 3 | USA,null,2,null 4 | -------------------------------------------------------------------------------- /file.java: -------------------------------------------------------------------------------- 1 | public enum NAME { 2 | 3 | CANADA("2014-05-07 14:23","canada",1), 4 | USA(null,null,2); 5 | 6 | private final LocalDateTime blob; 7 | private final String x; 8 | private final int y; 9 | 10 | 11 | NAME(LocalDateTime blob,String x,int y) { 12 | this.blob = blob; 13 | this.x = x; 14 | this.y = y 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /out/artifacts/CsvEnumGenerator_jar/CsvEnumGenerator.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfsisinni/enum-generator-from-csv-java/fb8b561047df8c3f3b13bd3f3276448995ac04ee/out/artifacts/CsvEnumGenerator_jar/CsvEnumGenerator.jar -------------------------------------------------------------------------------- /out/artifacts/CsvEnumGenerator_jar/countries.csv: -------------------------------------------------------------------------------- 1 | VALUE,String countryName,LocalDate foundedOn 2 | CANADA,Canada,1867-07-01 3 | UNITED_STATES,United States Of America,1776-07-04 4 | -------------------------------------------------------------------------------- /out/artifacts/CsvEnumGenerator_jar/countries.java: -------------------------------------------------------------------------------- 1 | public enum COUNTRY { 2 | 3 | CANADA("1867-07-01","Canada"), 4 | UNITED_STATES("1776-07-04","United States Of America"); 5 | 6 | private final LocalDate foundedOn; 7 | private final String countryName; 8 | 9 | 10 | COUNTRY(LocalDate foundedOn,String countryName) { 11 | this.foundedOn = foundedOn; 12 | this.countryName = countryName; 13 | } 14 | 15 | public LocalDate getFoundedOn() { 16 | return this.foundedOn; 17 | } 18 | 19 | public String getCountryName() { 20 | return this.countryName; 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | groupId 8 | CsvEnumGenerator 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | org.apache.commons 14 | commons-csv 15 | 1.3 16 | 17 | 18 | org.projectlombok 19 | lombok 20 | 1.16.16 21 | provided 22 | 23 | 24 | com.google.guava 25 | guava 26 | 22.0 27 | 28 | 29 | org.apache.commons 30 | commons-lang3 31 | 3.6 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: com.danesisinni.Main 3 | 4 | -------------------------------------------------------------------------------- /src/com/danesisinni/CSVEnumGenerator.java: -------------------------------------------------------------------------------- 1 | package com.danesisinni; 2 | 3 | import com.google.common.base.Joiner; 4 | import com.google.common.collect.ImmutableList; 5 | import com.google.common.collect.ImmutableMap; 6 | import com.google.common.collect.ImmutableSet; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.val; 10 | import org.apache.commons.csv.CSVFormat; 11 | import org.apache.commons.csv.CSVRecord; 12 | import org.apache.commons.lang3.StringUtils; 13 | 14 | import java.io.FileReader; 15 | import java.io.IOException; 16 | import java.util.ArrayList; 17 | import java.util.HashMap; 18 | 19 | public class CSVEnumGenerator { 20 | 21 | private static final String ENUM_INITIALIZATION_VALUE = "VALUE"; 22 | private static final ImmutableSet NON_QUOTE_DATA_TYPES = new ImmutableSet.Builder() 23 | .add("int") 24 | .add("Integer") 25 | .add("long") 26 | .add("Long") 27 | .add("double") 28 | .add("Double") 29 | .add("Float") 30 | .add("float") 31 | .build(); 32 | 33 | private final String CSV_FILE; 34 | private final String ENUM_NAME; 35 | 36 | public CSVEnumGenerator(String CSV_FILE, String ENUM_NAME) { 37 | this.CSV_FILE = CSV_FILE; 38 | this.ENUM_NAME = ENUM_NAME; 39 | } 40 | 41 | public String getEnum() { 42 | val enumWrapper = getDataFromCSVFile(); 43 | 44 | val enumBuilder = new StringBuilder(); 45 | enumBuilder.append("public enum "); 46 | enumBuilder.append(ENUM_NAME); 47 | enumBuilder.append(" { \n\n"); 48 | 49 | val arguments = enumWrapper.getDataTypes(); 50 | val argumentOrder = arguments.keySet().asList(); 51 | 52 | 53 | val initializationList = new ArrayList(); 54 | for (EnumData entry : enumWrapper.getEnumData()) { 55 | val instanceBuilder = new StringBuilder(); 56 | instanceBuilder.append(entry.getName()); 57 | instanceBuilder.append("("); 58 | 59 | val paramsList = new ArrayList(); 60 | for (String argument : argumentOrder) { 61 | val arg = entry.getInitializationValues().get(argument); 62 | if (needsQuotes(arguments.get(argument), arg)) { 63 | paramsList.add("\"" + arg + "\""); 64 | } else { 65 | paramsList.add(arg); 66 | } 67 | } 68 | instanceBuilder.append(Joiner.on(",").join(paramsList)); 69 | instanceBuilder.append(")"); 70 | initializationList.add(instanceBuilder.toString()); 71 | } 72 | 73 | enumBuilder.append(Joiner.on(",\n").join(initializationList)); 74 | enumBuilder.append(";\n\n"); 75 | 76 | for (String argument : argumentOrder) { 77 | enumBuilder.append("private final "); 78 | enumBuilder.append(arguments.get(argument)); 79 | enumBuilder.append(" "); 80 | enumBuilder.append(argument); 81 | enumBuilder.append(";\n"); 82 | } 83 | 84 | enumBuilder.append("\n\n"); 85 | enumBuilder.append(ENUM_NAME); 86 | enumBuilder.append("("); 87 | 88 | val parameters = new ArrayList(); 89 | for (String argument : argumentOrder) { 90 | parameters.add(arguments.get(argument) + " " + argument); 91 | } 92 | enumBuilder.append(Joiner.on(",").join(parameters)); 93 | enumBuilder.append(") {\n"); 94 | 95 | val initialize = new ArrayList(); 96 | for (String argument : argumentOrder) { 97 | initialize.add("this." + argument + " = " + argument + ";"); 98 | } 99 | enumBuilder.append(Joiner.on("\n").join(initialize)); 100 | enumBuilder.append("\n}\n\n"); 101 | 102 | 103 | for (String argument : argumentOrder) { 104 | enumBuilder.append("public "); 105 | enumBuilder.append(arguments.get(argument)); 106 | enumBuilder.append(" get"); 107 | enumBuilder.append(StringUtils.capitalize(argument)); 108 | enumBuilder.append("() {\n"); 109 | enumBuilder.append("return this."); 110 | enumBuilder.append(argument); 111 | enumBuilder.append(";\n}\n\n"); 112 | } 113 | 114 | enumBuilder.append("}"); 115 | 116 | return enumBuilder.toString(); 117 | } 118 | 119 | private boolean needsQuotes(String dataType, String value) { 120 | return !(value.equals("null") || NON_QUOTE_DATA_TYPES.contains(dataType)); 121 | } 122 | 123 | private EnumWrapper getDataFromCSVFile() { 124 | final EnumWrapper data; 125 | try { 126 | data = getDataFromCSVFileThrowsException(); 127 | } catch (IOException ex) { 128 | throw new IllegalStateException(String.format("Unable to parse file: %s", CSV_FILE), ex); 129 | } 130 | return data; 131 | } 132 | 133 | private EnumWrapper getDataFromCSVFileThrowsException() throws IOException { 134 | val data = new ArrayList(); 135 | val fileReader = new FileReader(CSV_FILE); 136 | val records = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(fileReader); 137 | 138 | val headerDataTypes = new HashMap(); 139 | val headerMap = records.getHeaderMap(); 140 | 141 | for (String header : headerMap.keySet()) { 142 | if (!header.trim().equals(ENUM_INITIALIZATION_VALUE)) { 143 | val split = header.trim().split(" "); 144 | if (split.length != 2) { 145 | throw new IllegalStateException(String.format("Invalid header: %s", header)); 146 | } 147 | 148 | headerDataTypes.put(split[1], split[0]); 149 | } 150 | } 151 | 152 | for (CSVRecord record : records) { 153 | val entry = new HashMap(); 154 | for (String header : headerMap.keySet()) { 155 | if (!header.trim().equals(ENUM_INITIALIZATION_VALUE)) { 156 | entry.put(header.trim().split(" ")[1], record.get(headerMap.get(header))); 157 | } 158 | } 159 | data.add(new EnumData(record.get(headerMap.get(ENUM_INITIALIZATION_VALUE)), ImmutableMap.copyOf(entry))); 160 | } 161 | 162 | return new EnumWrapper(ImmutableList.copyOf(data), ImmutableMap.copyOf(headerDataTypes)); 163 | } 164 | 165 | @Data 166 | @AllArgsConstructor 167 | static class EnumWrapper { 168 | private ImmutableList enumData; 169 | private ImmutableMap dataTypes; 170 | } 171 | 172 | @Data 173 | @AllArgsConstructor 174 | static class EnumData { 175 | 176 | private String name; 177 | private ImmutableMap initializationValues; 178 | 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /src/com/danesisinni/Main.java: -------------------------------------------------------------------------------- 1 | package com.danesisinni; 2 | 3 | import lombok.val; 4 | 5 | import java.io.IOException; 6 | import java.nio.file.Files; 7 | import java.nio.file.Paths; 8 | 9 | public class Main { 10 | 11 | public static void main(String[] args) { 12 | String csvFile = "file.csv"; 13 | String enumName = "NAME"; 14 | String enumFile = "file.java"; 15 | 16 | if (args.length == 3) { 17 | csvFile = args[0]; 18 | enumName = args[1]; 19 | enumFile = args[2]; 20 | } 21 | 22 | CSVEnumGenerator generator = new CSVEnumGenerator(csvFile, enumName); 23 | val enumData = generator.getEnum(); 24 | writeToFile(enumData, enumFile); 25 | } 26 | 27 | public static void writeToFile(String data, String fileName) { 28 | try { 29 | val path = Paths.get(fileName); 30 | Files.createFile(path); 31 | Files.write(path, data.getBytes()); 32 | } catch (IOException e) { 33 | e.printStackTrace(); 34 | } 35 | } 36 | 37 | 38 | } 39 | --------------------------------------------------------------------------------