├── .gitignore ├── .project ├── .travis.yml ├── LICENSE ├── README.md ├── TemplateVariables.md ├── pom.xml └── src ├── main ├── java │ ├── configuration │ │ ├── ClassContainerAdjuster.java │ │ ├── ClassProvider.java │ │ ├── DefaultAdjusters.java │ │ ├── DefaultConfigurations.java │ │ ├── FreeMarkerConfiguration.java │ │ ├── JavaForgerConfiguration.java │ │ ├── PathConverter.java │ │ └── StaticJavaForgerConfiguration.java │ ├── execution │ │ └── TemplateExecutor.java │ ├── generator │ │ ├── CodeSnipit.java │ │ ├── Generator.java │ │ ├── JavaForger.java │ │ ├── JavaForgerException.java │ │ └── TemplateInputParametersService.java │ ├── initialization │ │ ├── InitConverter.java │ │ ├── InitDefaultValues.java │ │ ├── InitValue.java │ │ └── InitializationService.java │ ├── logback.xml │ ├── merger │ │ ├── CodeSnipitInserter.java │ │ ├── CodeSnipitLocater.java │ │ ├── CodeSnipitLocation.java │ │ ├── CodeSnipitMerger.java │ │ ├── CodeSnipitReader.java │ │ ├── JavaParserMerger.java │ │ ├── LineMerger.java │ │ └── NodeComparator.java │ ├── reader │ │ ├── ClassContainerReader.java │ │ ├── ImportResolver.java │ │ ├── MethodDefinitionFactory.java │ │ ├── Parser.java │ │ └── VariableDefintionFactory.java │ └── templateInput │ │ ├── ClassContainer.java │ │ ├── StringConverter.java │ │ ├── TemplateInputDefaults.java │ │ ├── TemplateInputParameters.java │ │ └── definition │ │ ├── ClassDefinition.java │ │ ├── FlowReceiverDefinition.java │ │ ├── InitializedTypeDefinition.java │ │ ├── MethodDefinition.java │ │ ├── TypeDefinition.java │ │ └── VariableDefinition.java └── resources │ └── templates │ ├── common │ ├── classTypeImports.javat │ ├── header.javat │ ├── package.javat │ └── typeImports.javat │ ├── equals.javat │ ├── equalsTest.javat │ ├── extendableInnerBuilder.javat │ ├── getterSetter.javat │ ├── hashCode.javat │ ├── hashCodeTest.javat │ ├── innerBuilder.javat │ ├── innerBuilderTest.javat │ ├── test │ ├── common │ │ ├── createAndFillBuilderWithStaticFields.javat │ │ ├── emptyTestClass.javat │ │ ├── imports.javat │ │ ├── staticFieldInit.javat │ │ └── testClassDefinition.javat │ └── generic │ │ ├── stateFullClassTest.javat │ │ └── statelessClassTest.javat │ └── toString.javat └── test ├── java ├── common │ ├── AbstractFileChangingTest.java │ └── SymbolSolverSetup.java ├── generator │ ├── CodeSnipitTest.java │ └── GeneratorTest.java ├── initialization │ ├── InitConverterTest.java │ └── InitializationServiceTest.java ├── inputClassesForTests │ ├── ClassWithEverything.java │ ├── ClassWithEverythingTest.java │ ├── ExtendedProduct.java │ ├── Product.java │ └── TestInterface.java ├── logback-test.xml ├── merger │ ├── CodeSnipitInserterTest.java │ ├── CodeSnipitLocaterTest.java │ ├── CodeSnipitLocationTest.java │ ├── CodeSnipitReaderTest.java │ ├── JavaParserMergerTest.java │ ├── LineMergerTest.java │ └── NodeComparatorTest.java ├── reader │ ├── ClassContainerReaderTest.java │ ├── GraphBuilder.java │ ├── MethodDefinitionFactoryTest.java │ ├── NodeBuilder.java │ └── VariableDefintionFactoryTest.java ├── templateInput │ ├── StringConverterTest.java │ └── definition │ │ └── MethodDefinitionTest.java └── templateTests │ ├── DataFlowGraphTemplateIntegrationTest.java │ └── TemplateIntegrationTest.java └── resources ├── stateFullClassTest ├── verify-stateFullClassTest.java ├── verify-statelessClassTest-facade.java └── verify-statelessClassTest-outputMethodCall.java ├── templateTestOutcomes ├── CodeSnipitInserterTest │ ├── verify-inserted.java │ ├── verify-nothingHappend.java │ └── verify-overriden.java ├── LineMergerTest │ ├── verify-addInnerClass.java │ ├── verify-constructor.java │ ├── verify-field.java │ ├── verify-import.java │ ├── verify-mergeInnerClass.java │ └── verify-package.java ├── verify-equals.java ├── verify-equalsTest.java ├── verify-extendableInnerBuilder.java ├── verify-hashCode.java ├── verify-hashCodeTest.java ├── verify-innerBuilder.java ├── verify-innerBuilderTest.java └── verify-toString.java └── templates ├── classFields.ftlh ├── condition.ftlh ├── include.ftlh ├── object.ftlh ├── sequence.ftlh └── simple.ftlh /.gitignore: -------------------------------------------------------------------------------- 1 | **/target 2 | **/.classpath 3 | **/.project 4 | **/.settings 5 | /bin/ 6 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | JavaForger 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | install: mvn install -DskipTests=true 3 | dist: trusty 4 | jdk: 5 | - oraclejdk8 6 | -------------------------------------------------------------------------------- /TemplateVariables.md: -------------------------------------------------------------------------------- 1 | 2 | ## Template Variables 3 | 4 | The variable below are accessible directly within a template, with the FreeMarker syntax. 5 | The value of a template can be used with the syntax ${value}. 6 | Elements within a list can be accessed with the syntax <#list values as value> ... . 7 | Subvalues can be used by concatenating it with a single dot; ${value.subvalue}. 8 | The name of a type t can be accessed by either ${t} or ${t.name}, converting it to for instance snake casing can be done with ${t.snakeCase}. 9 | More advanced expressions like conditionals can be found at [freemarker.apache.org](https://freemarker.apache.org/). 10 | 11 | ``` 12 | |- class ClassDefinition containing data defined by a class. 13 | |- fields list, usage: <#list fields as field> ... 14 | |- constructors list, usage: <#list constructors as constructor> ... 15 | |- methods list, usage: <#list methods as method> ... 16 | |- package The package of the class to which the code will be merged 17 | ``` 18 | The fields, constructors and methods of a class are accessible directly as well as via the class. 19 | This is to support both easy access as well as using multiple classes as input for a template. 20 | Note that a constructor is modelled as a method where the type and the name are equal. 21 | The different types are described below. 22 | 23 | ``` 24 | ClassDefinition 25 | |- extend The extended class, can be null and should be checked via <#if class.extend??> ... 26 | |- interfaces List containing the interfaces implemented by this class. 27 | |- fields list, usage: <#list class.fields as field> ... 28 | |- constructors list, usage: <#list class.constructors as constructor> ... 29 | |- methods list, usage: <#list class.methods as method> ... 30 | |- *TypeDefinition The accessible Name and Type fields of the class are descibed under TypeDefinition. 31 | 32 | VariableDefinition 33 | |- originalInit The original assignment to a variable, can be null and should be checked first. 34 | |- *TypeDefinition The accessible Name and Type fields of the class are descibed under TypeDefinition. 35 | 36 | MethodDefinition 37 | |- parameters List containing the input parameters. 38 | |- *TypeDefinition The accessible Name and Type fields of the class are descibed under TypeDefinition. 39 | 40 | TypeDefinition 41 | |- name Name of the type, conversion of this name possible via StringConverter interface. 42 | |- type Type of the variable or method return type, conversion possible via StringConverter interface. 43 | |- nonPrimitiveType The non-primitive version of the type, gives the same type if it's already non-primitive. 44 | |- typeImports List containing the java imports required for this type. 45 | |- lineNumber The line number where this type starts. 46 | |- column The column where this type starts. 47 | |- annotations List containing the annotations for this type. 48 | |- accessModifiers List containing the access modifiers. 49 | |- defaultInit The default initialization for this type, typically used for initializing empty collections. 50 | |- init1 An initialisation value for the current type. 51 | |- init2 An initialisation value for the current type, distinct from init1. 52 | |- noInit Contains the value for this type if it is not initialized. 53 | |- collection Boolean indicating if the type extends collection. 54 | |- initImports List containing the java imports required for using the initialisation values. 55 | 56 | StringConverter 57 | |- lower Lower case all characters. 58 | |- upper Upper case all characters. 59 | |- lowerFirst Lower case the first character. 60 | |- upperFirst Upper case the first character. 61 | |- snakeCase Snake case the characters. 62 | |- lowerSpace Add a space before each uppercase character and then lower case all. 63 | |- lowerDash Add a dash before each uppercase character and then lower case all. 64 | 65 | ``` 66 | -------------------------------------------------------------------------------- /src/main/java/configuration/ClassContainerAdjuster.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package configuration; 19 | 20 | import java.util.function.Consumer; 21 | 22 | import templateInput.ClassContainer; 23 | 24 | /** 25 | * Functional interface to implement a consumer of {@link ClassContainer} so that the input parameters can be changed after parsing. 26 | * 27 | * @author Daan 28 | */ 29 | public interface ClassContainerAdjuster extends Consumer { 30 | // Class is empty because Consumer already defines required methods. This class is mainly needed to ensure type safety. 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/configuration/DefaultAdjusters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package configuration; 19 | 20 | import java.util.List; 21 | import java.util.function.Consumer; 22 | import java.util.function.Function; 23 | 24 | import initialization.InitDefaultValues; 25 | import templateInput.ClassContainer; 26 | import templateInput.TemplateInputParameters; 27 | import templateInput.definition.MethodDefinition; 28 | import templateInput.definition.VariableDefinition; 29 | 30 | /** 31 | * Default adjusters for adding or removing input to/from the {@link TemplateInputParameters} after parsing is done. 32 | * 33 | * @author Daan 34 | */ 35 | public class DefaultAdjusters { 36 | 37 | /** 38 | * @return Returns an {@link ClassContainerAdjuster} to remove all depracated fields 39 | */ 40 | public static ClassContainerAdjuster removeDepracatedFields() { 41 | return p -> removeVariableIf(p, var -> var.getAnnotations().contains("Deprecated")); 42 | } 43 | 44 | /** 45 | * @return Returns an {@link ClassContainerAdjuster} to remove all static fields 46 | */ 47 | public static ClassContainerAdjuster removeStaticFields() { 48 | return p -> removeVariableIf(p, var -> var.getAccessModifiers().contains("static")); 49 | } 50 | 51 | /** 52 | * @return Returns an {@link ClassContainerAdjuster} to replace all primitive types with their object version (e.g. int to Integer). 53 | */ 54 | public static ClassContainerAdjuster replaceFieldPrimitivesWithObjects() { 55 | return p -> changeVariable(p, var -> var.setType(InitDefaultValues.getObjectForPrimitive(var.getType().toString()))); 56 | } 57 | 58 | /** 59 | * @return Returns an {@link ClassContainerAdjuster} to remove all void methods 60 | */ 61 | public static ClassContainerAdjuster removeVoidMethods() { 62 | return p -> removeMethodIf(p, met -> met.getType().toString().equals("void")); 63 | } 64 | 65 | /** 66 | * Changes the fields inside the {@link ClassContainer} using the given parameterChanger. 67 | * 68 | * @param parameters The {@link ClassContainer} in which the fields are changed. 69 | * @param parameterChanger a consumer changing an individual {@link VariableDefinition} inside the parameters. 70 | */ 71 | public static void changeVariable(ClassContainer parameters, Consumer parameterChanger) { 72 | List fields = parameters.getFields(); 73 | for (int i = 0; i < fields.size(); i++) { 74 | parameterChanger.accept(fields.get(i)); 75 | } 76 | } 77 | 78 | /** 79 | * Removes all fields inside the {@link ClassContainer} for which the input function returns true. 80 | * 81 | * @param parameters The {@link ClassContainer} in which the fields are removed. 82 | * @param removeIfTrue Function to determine if a variable should be removed. 83 | */ 84 | public static void removeVariableIf(ClassContainer parameters, Function removeIfTrue) { 85 | List fields = parameters.getFields(); 86 | for (int i = 0; i < fields.size();) { 87 | if (removeIfTrue.apply(fields.get(i))) { 88 | fields.remove(i); 89 | } else { 90 | i++; 91 | } 92 | } 93 | } 94 | 95 | /** 96 | * Removes all methods inside the {@link ClassContainer} for which the input function returns true. 97 | * 98 | * @param parameters The {@link ClassContainer} in which the methods are removed. 99 | * @param removeIfTrue Function to determine if a variable should be removed. 100 | */ 101 | public static void removeMethodIf(ClassContainer parameters, Function removeIfTrue) { 102 | List methods = parameters.getMethods(); 103 | for (int i = 0; i < methods.size();) { 104 | if (removeIfTrue.apply(methods.get(i))) { 105 | methods.remove(i); 106 | } else { 107 | i++; 108 | } 109 | } 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/configuration/DefaultConfigurations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package configuration; 19 | 20 | /** 21 | * Class containing default {@link JavaForgerConfiguration}s for a set of templates. 22 | * 23 | * @author Daan 24 | */ 25 | public class DefaultConfigurations { 26 | 27 | public static JavaForgerConfiguration forEquals() { 28 | return defaultConfig("equals.javat"); 29 | } 30 | 31 | public static JavaForgerConfiguration forEqualsAndTest() { 32 | return defaultConfiguration("equals.javat", "equalsTest.javat"); 33 | } 34 | 35 | public static JavaForgerConfiguration forHashCode() { 36 | return defaultConfig("hashCode.javat"); 37 | } 38 | 39 | public static JavaForgerConfiguration forHashCodeAndTest() { 40 | return defaultConfiguration("hashCode.javat", "hashCodeTest.javat"); 41 | } 42 | 43 | public static JavaForgerConfiguration forBuilder() { 44 | JavaForgerConfiguration config = defaultConfig("innerBuilder.javat"); 45 | config.addParameterAdjusters(DefaultAdjusters.replaceFieldPrimitivesWithObjects()); 46 | return config; 47 | } 48 | 49 | public static JavaForgerConfiguration forBuilderAndTest() { 50 | JavaForgerConfiguration config = defaultConfiguration("innerBuilder.javat", "innerBuilderTest.javat"); 51 | config.addParameterAdjusters(DefaultAdjusters.replaceFieldPrimitivesWithObjects()); 52 | return config; 53 | } 54 | 55 | public static JavaForgerConfiguration forExtendableBuilderAndTest() { 56 | JavaForgerConfiguration config = defaultConfiguration("extendableInnerBuilder.javat", "innerBuilderTest.javat"); 57 | config.addParameterAdjusters(DefaultAdjusters.replaceFieldPrimitivesWithObjects()); 58 | return config; 59 | } 60 | 61 | /** 62 | * @return {@link JavaForgerConfiguration} for creating a toString method in the input class. 63 | */ 64 | public static JavaForgerConfiguration forToString() { 65 | return defaultConfig("toString.javat"); 66 | } 67 | 68 | /** 69 | * This {@link JavaForgerConfiguration} can only be used as {@link JavaForgerConfiguration#getChildConfigs()}. 70 | * 71 | * @return {@link JavaForgerConfiguration} for creating a toString method in the merge class from the parent. 72 | */ 73 | public static JavaForgerConfiguration forChildToString() { 74 | JavaForgerConfiguration conf = forToString(); 75 | conf.setInputClassProvider(ClassProvider.fromParentMergeClass()); 76 | return conf; 77 | } 78 | 79 | /** 80 | * Create a unit test for a class that state. This template is work in progress mainly depending on the JavaDataFlow project. 81 | * 82 | * @return A {@link JavaForgerConfiguration} containing the settings for the state-full class test template. 83 | */ 84 | public static JavaForgerConfiguration forStateFullClassTest() { 85 | return defaultBuilder("test/generic/stateFullClassTest.javat").mergeClassProvider(ClassProvider.forMavenUnitTestFromInput()).build(); 86 | } 87 | 88 | /** 89 | * Create a unit test for a class that has no state. This template is work in progress mainly depending on the JavaDataFlow project. 90 | * 91 | * @return A {@link JavaForgerConfiguration} containing the settings for the state-less class test template. 92 | */ 93 | public static JavaForgerConfiguration forStatelessClassTest() { 94 | return defaultBuilder("test/generic/statelessClassTest.javat").mergeClassProvider(ClassProvider.forMavenUnitTestFromInput()) 95 | .configIfFileDoesNotExist(emptyTestFile()).build(); 96 | } 97 | 98 | protected static JavaForgerConfiguration defaultConfig(String template) { 99 | return defaultBuilder(template).build(); 100 | } 101 | 102 | protected static JavaForgerConfiguration defaultConfiguration(String template, String testTemplate) { 103 | return defaultBuilder(template).childConfig(defaultTestConfiguration(testTemplate)).build(); 104 | } 105 | 106 | private static JavaForgerConfiguration defaultTestConfiguration(String testTemplate) { 107 | return defaultBuilder(testTemplate).mergeClassProvider(ClassProvider.forMavenUnitTestFromInput()).configIfFileDoesNotExist(emptyTestFile()).build(); 108 | } 109 | 110 | private static JavaForgerConfiguration emptyTestFile() { 111 | return JavaForgerConfiguration.builder().template("test/common/emptyTestClass.javat").createFileIfNotExists(true) 112 | .mergeClassProvider(ClassProvider.fromParentMergeClass()).build(); 113 | } 114 | 115 | protected static JavaForgerConfiguration.Builder defaultBuilder(String template) { 116 | return JavaForgerConfiguration.builder().template(template).mergeClassProvider(new ClassProvider()) 117 | .parameterAdjusters(DefaultAdjusters.removeDepracatedFields(), DefaultAdjusters.removeStaticFields()); 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/configuration/FreeMarkerConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package configuration; 19 | 20 | import freemarker.core.PlainTextOutputFormat; 21 | import freemarker.template.Configuration; 22 | import freemarker.template.TemplateExceptionHandler; 23 | import generator.Generator; 24 | 25 | /** 26 | * This class holds the default configurations for Freemarker. 27 | * 28 | * @author Daan 29 | */ 30 | public class FreeMarkerConfiguration { 31 | public static final String TEMPLATE_LOCATION = "/templates/"; 32 | 33 | public static Configuration getDefaultConfig() { 34 | return initConfig(); 35 | } 36 | 37 | private static Configuration initConfig() { 38 | Configuration config; 39 | // TODO maybe put this method in a separate singleton class with a lazy getter for it. 40 | 41 | // Create your Configuration instance, and specify if up to what FreeMarker 42 | // version (here 2.3.27) do you want to apply the fixes that are not 100% 43 | // backward-compatible. See the Configuration JavaDoc for details. 44 | config = new Configuration(Configuration.VERSION_2_3_28); 45 | 46 | // Specify the source where the template files come from. Here I set a 47 | // plain directory for it, but non-file-system sources are possible too: 48 | config.setClassForTemplateLoading(Generator.class, TEMPLATE_LOCATION); 49 | 50 | // Set the preferred charset template files are stored in. UTF-8 is 51 | // a good choice in most applications: 52 | config.setDefaultEncoding("UTF-8"); 53 | 54 | // Sets how errors will appear. 55 | // During web page *development* TemplateExceptionHandler.HTML_DEBUG_HANDLER is better. 56 | config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 57 | 58 | // Don't log exceptions inside FreeMarker that it will thrown at you anyway: 59 | config.setLogTemplateExceptions(false); 60 | 61 | // Wrap unchecked exceptions thrown during template processing into TemplateException-s. 62 | config.setWrapUncheckedExceptions(true); 63 | 64 | // Sets the output format type 65 | config.setOutputFormat(PlainTextOutputFormat.INSTANCE); 66 | 67 | // This prevents special characters (like <>{}& ) from being escaped. 68 | config.setAutoEscapingPolicy(Configuration.DISABLE_AUTO_ESCAPING_POLICY); 69 | 70 | return config; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/configuration/PathConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package configuration; 19 | 20 | /** 21 | * Contains static methods for converting paths. 22 | * 23 | * @author Daan 24 | */ 25 | public class PathConverter { 26 | 27 | public static String toMavenUnitTestPath(String s) { 28 | return s.replace("\\", "/").replace("/main/", "/test/").replace(".java", "Test.java"); 29 | } 30 | 31 | public static String toPackage(String mavenPath) { 32 | String clean = mavenPath.replace("\\", "/"); 33 | String noClass = clean.substring(0, clean.lastIndexOf("/")); 34 | String sourceFolder = "/src/main/java/"; 35 | String testFolder = "/src/test/java/"; 36 | String folder = noClass.contains(sourceFolder) ? sourceFolder : testFolder; 37 | String pack = noClass.substring(noClass.indexOf(folder) + folder.length()); 38 | return pack.replace("/", "."); 39 | } 40 | 41 | /** 42 | * Converts a complete path to only the name of the class. 43 | * 44 | * @param path The path containing the class name 45 | * @return The name of the class 46 | */ 47 | public static String toClassName(String path) { 48 | String safePath = path.replace("\\", "/"); 49 | String className = safePath.substring(safePath.lastIndexOf("/") + 1, safePath.indexOf(".java")); 50 | return className; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/execution/TemplateExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package execution; 19 | 20 | import com.github.javaparser.symbolsolver.JavaSymbolSolver; 21 | import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 22 | import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; 23 | import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; 24 | import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; 25 | 26 | import configuration.DefaultConfigurations; 27 | import configuration.JavaForgerConfiguration; 28 | import configuration.StaticJavaForgerConfiguration; 29 | import generator.JavaForger; 30 | 31 | /** 32 | * Helper class to generate parts of the code. Should never be called from any other class. 33 | * 34 | * @author Daan 35 | */ 36 | public final class TemplateExecutor { 37 | private static final String PATH_PREFIX = "C:/gitrepo"; 38 | 39 | public static void main(String[] args) { 40 | setupSymbolSolver(); 41 | String inputClass = "/JavaForger/src/main/java/dataflow/model/ParameterList.java"; 42 | JavaForgerConfiguration config = DefaultConfigurations.forToString(); 43 | 44 | // config.setMerge(false); 45 | // config.setRecursive(JavaForgerConfiguration::setMerge, false); 46 | // config.setRecursive(JavaForgerConfiguration::setOverride, true); 47 | // config.setOverride(true); 48 | 49 | JavaForger.execute(config, PATH_PREFIX + inputClass).print(); 50 | } 51 | 52 | private static void setupSymbolSolver() { 53 | StaticJavaForgerConfiguration staticConfig = StaticJavaForgerConfiguration.getConfig(); 54 | TypeSolver[] reflTypeSolver = {new ReflectionTypeSolver(), new JavaParserTypeSolver(PATH_PREFIX + "/JavaForger/src/main/java/")}; 55 | TypeSolver typeSolver = new CombinedTypeSolver(reflTypeSolver); 56 | JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver); 57 | staticConfig.setSymbolSolver(symbolSolver); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/generator/CodeSnipit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package generator; 19 | 20 | import java.util.Arrays; 21 | import java.util.List; 22 | import java.util.stream.Collectors; 23 | import java.util.stream.IntStream; 24 | 25 | /** 26 | * Container for a string representing a code block, with methods for printing the code with line numbers. 27 | * 28 | * @author Daan 29 | */ 30 | public class CodeSnipit { 31 | 32 | private String code; 33 | 34 | public CodeSnipit(String codeString) { 35 | code = new String(codeString); 36 | } 37 | 38 | public String getCode() { 39 | return code; 40 | } 41 | 42 | public void add(String string) { 43 | code = code + string; 44 | } 45 | 46 | public void print() { 47 | System.out.println(toString()); 48 | } 49 | 50 | public void printWithLineNumbers() { 51 | System.out.println(toStringWithLineNumbers()); 52 | } 53 | 54 | /** 55 | * @return The code with line numbers. 56 | */ 57 | private String toStringWithLineNumbers() { 58 | String[] split = code.split("\\r?\\n"); 59 | List codeList = Arrays.asList(split); 60 | IntStream.range(0, codeList.size()).mapToObj(i -> (Integer) i).forEach(i -> codeList.set(i, (i + 1) + "\t" + codeList.get(i))); 61 | return codeList.stream().collect(Collectors.joining("\n")); 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return code; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/generator/JavaForger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package generator; 19 | 20 | import java.io.IOException; 21 | 22 | import configuration.JavaForgerConfiguration; 23 | import freemarker.template.TemplateException; 24 | 25 | /** 26 | * Class with static methods for executing code generation and insertion. 27 | * 28 | * @author Daan 29 | */ 30 | public class JavaForger { 31 | 32 | private static final Generator generator = new Generator(); 33 | 34 | /** 35 | * Executes the given {@link JavaForgerConfiguration} that contains the template. The parameters used to fill in the template will also come from the 36 | * configuration. 37 | * 38 | * @param config The Configuration containing the template and settings for how to process the input class to generate code. 39 | * @return The {@link CodeSnipit} containing the generated code. 40 | */ 41 | public static CodeSnipit execute(JavaForgerConfiguration config) { 42 | Exception caught = null; 43 | try { 44 | return generator.execute(config); 45 | } catch (IOException e) { 46 | caught = e; 47 | } catch (TemplateException e) { 48 | caught = e; 49 | } 50 | throw new JavaForgerException(caught); 51 | } 52 | 53 | /** 54 | * Executes the given {@link JavaForgerConfiguration} that contains the template. The input class is used to fill in the given template with fields, methods 55 | * etc. derived from it. 56 | * 57 | * @param config The Configuration containing the template and settings for how to process the input class to generate code. 58 | * @param inputClass The full path to the class to be used as input for the template. 59 | * @return The {@link CodeSnipit} containing the generated code. 60 | */ 61 | public static CodeSnipit execute(JavaForgerConfiguration config, String inputClass) { 62 | Exception caught = null; 63 | try { 64 | return generator.execute(config, inputClass); 65 | } catch (IOException e) { 66 | caught = e; 67 | } catch (TemplateException e) { 68 | caught = e; 69 | } 70 | throw new JavaForgerException(caught); 71 | } 72 | 73 | /** 74 | * Executes the given {@link JavaForgerConfiguration} that contains the template. The input class is used to fill in the given template with fields, methods 75 | * etc. derived from it. The generated code is merged into the output class. 76 | * 77 | * @param config The Configuration containing the template and settings for how to process the input class to generate code. 78 | * @param inputClass The full path to the class to be used as input for the template. 79 | * @param outputClass The class to be used to merge the generated code with. 80 | * @return The {@link CodeSnipit} containing the generated code. 81 | */ 82 | public static CodeSnipit execute(JavaForgerConfiguration config, String inputClass, String outputClass) { 83 | Exception caught = null; 84 | try { 85 | JavaForgerConfiguration copy = JavaForgerConfiguration.builder(config).mergeClass(outputClass).build(); 86 | return generator.execute(copy, inputClass); 87 | } catch (IOException e) { 88 | caught = e; 89 | } catch (TemplateException e) { 90 | caught = e; 91 | } 92 | throw new JavaForgerException(caught); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/generator/JavaForgerException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package generator; 19 | 20 | import com.google.common.util.concurrent.UncheckedExecutionException; 21 | 22 | /** 23 | * Custom unchecked exception that is thrown when execution is not finished. 24 | * 25 | * @author Daan 26 | */ 27 | public class JavaForgerException extends UncheckedExecutionException { 28 | private static final long serialVersionUID = 6709295471984508495L; 29 | 30 | public JavaForgerException(Exception caught) { 31 | super(caught); 32 | } 33 | 34 | public JavaForgerException(String string) { 35 | super(string); 36 | } 37 | 38 | public JavaForgerException(Exception e, String string) { 39 | super(string, e); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/generator/TemplateInputParametersService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package generator; 19 | 20 | import java.io.IOException; 21 | 22 | import configuration.JavaForgerConfiguration; 23 | import configuration.PathConverter; 24 | import configuration.StaticJavaForgerConfiguration; 25 | import initialization.InitializationService; 26 | import reader.ClassContainerReader; 27 | import templateInput.ClassContainer; 28 | import templateInput.TemplateInputDefaults; 29 | import templateInput.TemplateInputParameters; 30 | 31 | /** 32 | * Service for constructing the {@link TemplateInputParameters} required as input for a template. 33 | * 34 | * @author Daan 35 | */ 36 | public class TemplateInputParametersService { 37 | 38 | private ClassContainerReader reader = StaticJavaForgerConfiguration.getReader(); 39 | private InitializationService initializer = StaticJavaForgerConfiguration.getInitializer(); 40 | 41 | /** 42 | * Gets the {@link TemplateInputParameters} from the {@link JavaForgerConfiguration} and inserts all missing input parameters given by 43 | * {@link TemplateInputDefaults}. 44 | * 45 | * @param config The {@link JavaForgerConfiguration} 46 | * @param inputClass The class that will be parsed to construct the input parameters. 47 | * @param mergeClassPath The class to which the template from the config will be merged to. 48 | * @return {@link TemplateInputParameters} 49 | * @throws IOException 50 | */ 51 | public TemplateInputParameters getInputParameters(JavaForgerConfiguration config, String inputClass, String mergeClassPath) throws IOException { 52 | TemplateInputParameters inputParameters = config.getInputParameters(); 53 | 54 | if (inputClass != null && !inputClass.isEmpty()) { 55 | if (!inputParameters.containsKey(TemplateInputDefaults.FIELDS.getName()) || !inputParameters.containsKey(TemplateInputDefaults.CLASS.getName()) 56 | || !inputParameters.containsKey(TemplateInputDefaults.METHODS.getName()) 57 | || !inputParameters.containsKey(TemplateInputDefaults.CONSTRUCTORS.getName())) { 58 | 59 | ClassContainer claz = reader.read(inputClass); 60 | initializer.init(claz); 61 | config.getAdjuster().accept(claz); 62 | if (!inputParameters.containsKey(TemplateInputDefaults.FIELDS.getName())) { 63 | inputParameters.put(TemplateInputDefaults.FIELDS.getName(), claz.getFields()); 64 | } 65 | if (!inputParameters.containsKey(TemplateInputDefaults.CLASS.getName())) { 66 | inputParameters.put(TemplateInputDefaults.CLASS.getName(), claz); 67 | } 68 | if (!inputParameters.containsKey(TemplateInputDefaults.METHODS.getName())) { 69 | inputParameters.put(TemplateInputDefaults.METHODS.getName(), claz.getMethods()); 70 | } 71 | if (!inputParameters.containsKey(TemplateInputDefaults.CONSTRUCTORS.getName())) { 72 | inputParameters.put(TemplateInputDefaults.CONSTRUCTORS.getName(), claz.getConstructors()); 73 | } 74 | } 75 | } 76 | if (mergeClassPath != null) { 77 | if (!inputParameters.containsKey(TemplateInputDefaults.PACKAGE.getName())) { 78 | String pack = PathConverter.toPackage(mergeClassPath); 79 | inputParameters.put(TemplateInputDefaults.PACKAGE.getName(), pack); 80 | } 81 | if (!inputParameters.containsKey(TemplateInputDefaults.MERGE_CLASS_NAME.getName())) { 82 | String a = mergeClassPath.replace("\\", "/"); 83 | String name = a.substring(a.lastIndexOf("/") + 1, a.lastIndexOf(".")); 84 | inputParameters.put(TemplateInputDefaults.MERGE_CLASS_NAME.getName(), name); 85 | } 86 | } 87 | 88 | return inputParameters; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/initialization/InitConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package initialization; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | import generator.JavaForgerException; 24 | 25 | /** 26 | * Converts strings for the initialization of fields in templates from {@link InitDefaultValues} so that numbers or random strings are filled in. 27 | * 28 | * @author Daan 29 | */ 30 | public class InitConverter { 31 | 32 | private InitDefaultValues defaults = new InitDefaultValues(); 33 | 34 | private int i = 1; 35 | private char c = 'a'; 36 | 37 | /** 38 | * Resets the initialization values to the first possible value. This method should be called as a start of any session so that for that session the 39 | * initialization values are predictable. 40 | */ 41 | public void reset() { 42 | i = 1; 43 | c = 'a'; 44 | } 45 | 46 | public String convert(String s) { 47 | return String.format(s, getArgsFor(s)); 48 | } 49 | 50 | private Object[] getArgsFor(String s) { 51 | List parameters = new ArrayList<>(); 52 | 53 | int index = s.indexOf("%"); 54 | String substring = s; 55 | 56 | while (index >= 0) { 57 | String type = substring.substring(index + 1, index + 2); 58 | switch (type) { 59 | case "d": 60 | parameters.add(new Integer(i++)); 61 | break; 62 | case "s": 63 | parameters.add(c); 64 | c = (char) (c + 1); 65 | break; 66 | default: 67 | throw new JavaForgerException("type " + type + "is not supported"); 68 | } 69 | 70 | substring = substring.substring(index + 2); 71 | index = substring.indexOf("%"); 72 | } 73 | return parameters.toArray(); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/initialization/InitValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package initialization; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | /** 26 | * Container class for a value to be assigned to a variable inside a template and the required imports for that value. 27 | * 28 | * @author Daan 29 | */ 30 | public class InitValue { 31 | 32 | private final String value; 33 | private final List imports = new ArrayList<>(); 34 | 35 | /** 36 | * Constructor for {@link InitValue}. 37 | * 38 | * @param value The value to be assigned to a variable. 39 | * @param imports The imports required for that value assignments. 40 | */ 41 | public InitValue(String value, String... imports) { 42 | this.value = value; 43 | this.imports.addAll(Arrays.asList(imports)); 44 | } 45 | 46 | /** 47 | * Constructor for {@link InitValue}. 48 | * 49 | * @param value The value to be assigned to a variable. 50 | */ 51 | public InitValue(String value) { 52 | this.value = value; 53 | } 54 | 55 | public String getValue() { 56 | return value; 57 | } 58 | 59 | public List getImports() { 60 | return Collections.unmodifiableList(imports); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %-5level %d{HH:mm:ss.SSS} %logger{36}:%L - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/merger/CodeSnipitInserter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import java.io.IOException; 21 | import java.nio.charset.StandardCharsets; 22 | import java.nio.file.Files; 23 | import java.nio.file.Paths; 24 | import java.util.Arrays; 25 | import java.util.LinkedHashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import configuration.JavaForgerConfiguration; 30 | 31 | /** 32 | * Class for insterting code into an existing class based on earlier determined insertion locations. 33 | * 34 | * @author Daan 35 | */ 36 | public class CodeSnipitInserter { 37 | 38 | /** 39 | * Inserts the new code into the file given by the mergeClassPath according to the insertLocations. 40 | * 41 | * @param config {@link JavaForgerConfiguration} indicating insert settings, such as if it is allowed to override code or only to insert. 42 | * @param mergeClassPath The path to the class to merge the new code into. 43 | * @param newCode The code to insert. 44 | * @param newCodeInsertionLocations Defines where new code needs to be inserted in the existing code. This map should be ordered on increasing insertLocation. 45 | * @throws IOException If path to existing class is invalid. 46 | */ 47 | public void insert(JavaForgerConfiguration config, String mergeClassPath, String newCode, 48 | LinkedHashMap newCodeInsertionLocations) throws IOException { 49 | List existingLines = Files.readAllLines(Paths.get(mergeClassPath), StandardCharsets.UTF_8); 50 | List newlines = Arrays.asList(newCode.split("\\r?\\n")); 51 | List result = insert(config, existingLines, newlines, newCodeInsertionLocations); 52 | Files.write(Paths.get(mergeClassPath), result, StandardCharsets.UTF_8); 53 | } 54 | 55 | private List insert(JavaForgerConfiguration config, List existingLines, List newlines, 56 | LinkedHashMap newCodeInsertionLocations) { 57 | // Because newCodeInsertionLocations is ordered, we keep track of the already added lines to determine the new insertion location 58 | int addedLines = 0; 59 | 60 | for (Map.Entry locations : newCodeInsertionLocations.entrySet()) { 61 | CodeSnipitLocation codeLocation = locations.getKey(); 62 | CodeSnipitLocation insertLocation = locations.getValue(); 63 | 64 | if (config.isOverride() || !insertLocation.containsLines()) { 65 | // Remove old lines 66 | for (int i = insertLocation.getFirstIndex(); i < insertLocation.getLastIndex(); i++) { 67 | existingLines.remove(addedLines + insertLocation.getFirstIndex()); 68 | } 69 | // write new lines 70 | for (int i = 0; i < codeLocation.size(); i++) { 71 | existingLines.add(addedLines + insertLocation.getFirstIndex() + i, newlines.get(codeLocation.getFirstIndex() + i)); 72 | } 73 | addedLines += codeLocation.size() - insertLocation.size(); 74 | } 75 | } 76 | return existingLines; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/merger/CodeSnipitMerger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import java.io.File; 21 | import java.io.IOException; 22 | 23 | import configuration.JavaForgerConfiguration; 24 | import configuration.StaticJavaForgerConfiguration; 25 | import generator.CodeSnipit; 26 | import generator.JavaForgerException; 27 | 28 | /** 29 | * Responsible for merging {@link CodeSnipit}s into java classes. The current default implementation is {@link LineMerger}. The default can be changed within 30 | * {@link StaticJavaForgerConfiguration}. 31 | * 32 | * @author Daan 33 | */ 34 | public abstract class CodeSnipitMerger { 35 | 36 | public void merge(JavaForgerConfiguration config, CodeSnipit codeSnipit, String mergeClassPath) throws IOException { 37 | if (validate(codeSnipit, mergeClassPath)) { 38 | executeMerge(config, codeSnipit, mergeClassPath); 39 | format(config, mergeClassPath); 40 | } 41 | } 42 | 43 | protected abstract void executeMerge(JavaForgerConfiguration config, CodeSnipit codeSnipit, String mergeClassPath) throws IOException; 44 | 45 | protected boolean validate(CodeSnipit codeSnipit, String mergeClassPath) { 46 | boolean success = true; 47 | if (mergeClassPath == null) { 48 | throw new JavaForgerException("merge class path may not be null"); 49 | } 50 | if (mergeClassPath.isEmpty()) { 51 | throw new JavaForgerException("merge class path may not be empty"); 52 | } 53 | if (!new File(mergeClassPath).exists()) { 54 | throw new JavaForgerException("merge class path does not point to existing file: " + mergeClassPath); 55 | } 56 | if (codeSnipit.getCode().isEmpty()) { 57 | System.err.println("CodeSnipit is empty and cannot be merged to: " + mergeClassPath); 58 | success = false; 59 | } 60 | return success; 61 | } 62 | 63 | protected void format(JavaForgerConfiguration config, String mergeClassPath) { 64 | // TODO implement formatting 65 | System.err.println("formatting is not yet supported and should be done manually for class " + mergeClassPath); 66 | // Probably best to call the formatter via the cmd: 67 | // https://stackoverflow.com/questions/15464111/run-cmd-commands-through-java 68 | // https://www.beyondjava.net/run-eclipse-formatter-command-line 69 | 70 | // Probably we have to let the user set the path to the desired java-formatter in the config 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/merger/LineMerger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import java.io.IOException; 21 | import java.util.LinkedHashMap; 22 | 23 | import com.github.javaparser.ast.CompilationUnit; 24 | 25 | import configuration.JavaForgerConfiguration; 26 | import generator.CodeSnipit; 27 | 28 | /** 29 | * Class to merge new code into an existing class, on line per line basis. 30 | * 31 | * @author Daan 32 | */ 33 | public class LineMerger extends CodeSnipitMerger { 34 | 35 | private CodeSnipitLocater locater = new CodeSnipitLocater(); 36 | private CodeSnipitInserter inserter = new CodeSnipitInserter(); 37 | private CodeSnipitReader reader = new CodeSnipitReader(); 38 | 39 | @Override 40 | protected void executeMerge(JavaForgerConfiguration config, CodeSnipit codeSnipit, String mergeClassPath) throws IOException { 41 | CompilationUnit existingCode = reader.read(mergeClassPath); 42 | CompilationUnit newCode = reader.read(codeSnipit, mergeClassPath); 43 | // TODO Currently there is a bug where the locator does not order the insertLocations if it overrides earlier defined code. 44 | // Solution: let locator except normal unsorted hashmap and sort it inside. 45 | LinkedHashMap newCodeInsertionLocations = locater.locate(existingCode, newCode); 46 | inserter.insert(config, mergeClassPath, codeSnipit.toString(), newCodeInsertionLocations); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/reader/ClassContainerReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package reader; 19 | 20 | import java.io.FileInputStream; 21 | import java.io.FileNotFoundException; 22 | import java.io.IOException; 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | import java.util.Optional; 26 | import java.util.Set; 27 | import java.util.stream.Collectors; 28 | 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | 32 | import com.github.javaparser.StaticJavaParser; 33 | import com.github.javaparser.ast.CompilationUnit; 34 | import com.github.javaparser.ast.Modifier; 35 | import com.github.javaparser.ast.Node; 36 | import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; 37 | import com.github.javaparser.ast.body.ConstructorDeclaration; 38 | import com.github.javaparser.ast.body.FieldDeclaration; 39 | import com.github.javaparser.ast.body.MethodDeclaration; 40 | import com.github.javaparser.ast.body.TypeDeclaration; 41 | import com.github.javaparser.ast.type.ClassOrInterfaceType; 42 | 43 | import dataflow.DataFlowGraphFactory; 44 | import dataflow.NodeCallFactory; 45 | import dataflow.model.DataFlowGraph; 46 | import generator.JavaForgerException; 47 | import templateInput.ClassContainer; 48 | import templateInput.definition.ClassDefinition; 49 | import templateInput.definition.MethodDefinition; 50 | import templateInput.definition.VariableDefinition; 51 | 52 | /** 53 | * Reader for all data within a class. 54 | * 55 | * @author Daan 56 | */ 57 | public class ClassContainerReader { 58 | 59 | private static final Logger LOG = LoggerFactory.getLogger(NodeCallFactory.class); 60 | 61 | private DataFlowGraphFactory dfgFactory = new DataFlowGraphFactory(); 62 | private MethodDefinitionFactory methodFactory = new MethodDefinitionFactory(); 63 | private VariableDefintionFactory fieldFactory = new VariableDefintionFactory(); 64 | 65 | public ClassContainer read(String inputClass) throws IOException { 66 | CompilationUnit cu = getCompilationUnit(inputClass); 67 | DataFlowGraph dfg = null; 68 | try { 69 | dfg = dfgFactory.create(cu); 70 | } catch (Exception e) { 71 | LOG.error("Error creating dataFlowGraph: {}", e); 72 | } 73 | ClassContainer claz = readCompilationUnit(cu, dfg); 74 | return claz; 75 | } 76 | 77 | private CompilationUnit getCompilationUnit(String inputClass) throws IOException { 78 | CompilationUnit cu = null; 79 | try (FileInputStream in = new FileInputStream(inputClass)) { 80 | cu = StaticJavaParser.parse(in); 81 | in.close(); 82 | } catch (FileNotFoundException e) { 83 | throw new JavaForgerException(e, "Could not parse " + inputClass); 84 | } 85 | return cu; 86 | } 87 | 88 | private ClassContainer readCompilationUnit(CompilationUnit cu, DataFlowGraph dfg) { 89 | ClassContainer claz = new ClassContainer(); 90 | List fields = new ArrayList<>(); 91 | List methods = new ArrayList<>(); 92 | List constructors = new ArrayList<>(); 93 | 94 | for (TypeDeclaration type : cu.getTypes()) { 95 | if (type instanceof ClassOrInterfaceDeclaration) { 96 | claz = parseClass(type); 97 | } 98 | 99 | List childNodes = type.getChildNodes(); 100 | for (Node node : childNodes) { 101 | if (node instanceof FieldDeclaration) { 102 | fields.addAll(fieldFactory.create(node)); 103 | } else if (node instanceof MethodDeclaration) { 104 | MethodDefinition newMethod = methodFactory.createMethod(node, dfg); 105 | methods.add(newMethod); 106 | } else if (node instanceof ConstructorDeclaration) { 107 | MethodDefinition constructor = methodFactory.createConstructor(node); 108 | constructors.add(constructor); 109 | } 110 | } 111 | } 112 | 113 | Optional typeImport = cu.getPackageDeclaration().map(pd -> pd.getNameAsString()); 114 | if (typeImport.isPresent()) { 115 | claz.addTypeImport(typeImport.get() + "." + claz.getName()); 116 | constructors.forEach(c -> c.addTypeImport(typeImport.get())); 117 | } 118 | 119 | claz.setFields(fields); 120 | claz.setMethods(methods); 121 | claz.setConstructors(constructors); 122 | return claz; 123 | } 124 | 125 | private ClassContainer parseClass(TypeDeclaration type) { 126 | ClassOrInterfaceDeclaration cd = (ClassOrInterfaceDeclaration) type; 127 | Set annotations = cd.getAnnotations().stream().map(annotation -> annotation.getName().toString()).collect(Collectors.toSet()); 128 | Set accessModifiers = cd.getModifiers().stream().map(Modifier::toString).map(String::trim).collect(Collectors.toSet()); 129 | List interfaces = cd.getImplementedTypes().stream().map(ClassOrInterfaceType::getNameAsString).collect(Collectors.toList()); 130 | String extend = cd.getExtendedTypes().stream().findFirst().map(ClassOrInterfaceType::getNameAsString).orElse(null); 131 | 132 | ClassDefinition def = ClassDefinition.builder().name(cd.getNameAsString()).type(cd.getNameAsString()).lineNumber(cd.getBegin().map(p -> p.line).orElse(-1)) 133 | .column(cd.getBegin().map(p -> p.column).orElse(-1)).annotations(annotations).accessModifiers(accessModifiers).extend(extend).interfaces(interfaces) 134 | .build(); 135 | return new ClassContainer(def); 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/reader/ImportResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package reader; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Collections; 22 | import java.util.List; 23 | import java.util.stream.Collectors; 24 | 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | import com.github.javaparser.JavaParser; 29 | import com.github.javaparser.ast.type.Type; 30 | import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; 31 | import com.github.javaparser.resolution.types.ResolvedReferenceType; 32 | import com.github.javaparser.resolution.types.ResolvedType; 33 | 34 | import configuration.StaticJavaForgerConfiguration; 35 | import templateInput.definition.TypeDefinition; 36 | 37 | /** 38 | * Class for resolving the imports for given {@link JavaParser} Types. 39 | * 40 | * @author Daan 41 | */ 42 | public class ImportResolver { 43 | private static final Logger LOG = LoggerFactory.getLogger(ImportResolver.class); 44 | 45 | private StaticJavaForgerConfiguration staticConfig = StaticJavaForgerConfiguration.getConfig(); 46 | 47 | /** 48 | * @param type 49 | * @param variable 50 | * @deprecated Use resolveImports instead. 51 | */ 52 | @Deprecated 53 | public void resolveAndSetImport(Type type, TypeDefinition variable) { 54 | resolveImport(type).forEach(variable::addTypeImport); 55 | } 56 | 57 | /** 58 | * Resolve the imports for the given type. 59 | * 60 | * @param type The {@link JavaParser} {@link Type}. 61 | * @return A {@link List} of {@link String} representing the imports. 62 | */ 63 | public List resolveImport(Type type) { 64 | List imports = resolve(type); 65 | return !imports.isEmpty() ? imports.stream().filter(s -> !s.contains("?")).collect(Collectors.toList()) : Collections.emptyList(); 66 | } 67 | 68 | private List resolve(Type type) { 69 | List imports = new ArrayList<>(); 70 | if (staticConfig.getSymbolSolver() != null) { 71 | try { 72 | ResolvedType resolve = type.resolve(); 73 | imports.addAll(getImportsFromResolvedType(resolve)); 74 | } catch (Exception e) { 75 | LOG.error("Could not resolve import for {}, check if symbol solver is correctly setup using StaticJavaForgerConfiguration::setProjectPaths. " 76 | + "Received exception with message: {}", type.asString(), e.getMessage()); 77 | } 78 | } 79 | return imports; 80 | } 81 | 82 | private List getImportsFromResolvedType(ResolvedType resolve) { 83 | List imports = new ArrayList<>(); 84 | String imp; 85 | if (resolve.isReferenceType()) { 86 | ResolvedReferenceType refType = resolve.asReferenceType(); 87 | ResolvedReferenceTypeDeclaration type = refType.getTypeDeclaration(); 88 | imp = type.getQualifiedName(); 89 | List innerResolvedTypes = 90 | type.getTypeParameters().stream().map(tp -> refType.typeParametersMap().getValue(tp)).collect(Collectors.toList()); 91 | // This is a recursive call to resolve all imports of parameterized types 92 | List collect = innerResolvedTypes.stream().flatMap(t -> getImportsFromResolvedType(t).stream()).collect(Collectors.toList()); 93 | imports.addAll(collect); 94 | } else { 95 | imp = resolve.describe(); 96 | } 97 | if (!imp.startsWith("java.lang.") && !resolve.isPrimitive()) { 98 | imports.add(imp); 99 | } 100 | return imports; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/reader/Parser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package reader; 19 | 20 | import java.io.BufferedReader; 21 | import java.io.FileInputStream; 22 | import java.io.IOException; 23 | import java.io.InputStreamReader; 24 | 25 | import com.github.javaparser.JavaParser; 26 | import com.github.javaparser.StaticJavaParser; 27 | import com.github.javaparser.ast.CompilationUnit; 28 | 29 | import generator.CodeSnipit; 30 | 31 | /** 32 | * Parser using {@link JavaParser} to parse classes. If an exception is thrown within JavaParser, this class will output the input String so that everything can 33 | * be debugged. 34 | * 35 | * @author Daan 36 | */ 37 | public class Parser { 38 | 39 | /** 40 | * Execute {@link JavaParser} and output the input code if an exception is thrown inside JavaParser so that it becomes debuggable. 41 | * 42 | * @param code The code to be parsed 43 | * @return The {@link CompilationUnit} result after parsing 44 | */ 45 | public static CompilationUnit parse(String code) { 46 | CompilationUnit cu; 47 | try { 48 | cu = StaticJavaParser.parse(code); 49 | } catch (Exception e) { 50 | e.printStackTrace(); 51 | System.out.println("The following could not be parsed:"); 52 | new CodeSnipit(code).printWithLineNumbers(); 53 | throw e; 54 | } 55 | return cu; 56 | } 57 | 58 | public static CompilationUnit parse(FileInputStream in) throws IOException { 59 | return parse(getFileContent(in)); 60 | } 61 | 62 | private static String getFileContent(FileInputStream fis) throws IOException { 63 | try (BufferedReader br = new BufferedReader(new InputStreamReader(fis, "UTF-8"))) { 64 | StringBuilder sb = new StringBuilder(); 65 | String line; 66 | while ((line = br.readLine()) != null) { 67 | sb.append(line); 68 | sb.append('\n'); 69 | } 70 | return sb.toString(); 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/templateInput/ClassContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package templateInput; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Collection; 22 | import java.util.HashSet; 23 | import java.util.List; 24 | import java.util.Set; 25 | import java.util.stream.Collectors; 26 | 27 | import templateInput.definition.ClassDefinition; 28 | import templateInput.definition.MethodDefinition; 29 | import templateInput.definition.TypeDefinition; 30 | import templateInput.definition.VariableDefinition; 31 | 32 | /** 33 | * Container class for everything defined within a class. 34 | * 35 | * @author Daan 36 | */ 37 | public class ClassContainer extends ClassDefinition { 38 | 39 | /** The fields defined within the class */ 40 | private List fields = new ArrayList<>(); 41 | /** The methods defined within the class */ 42 | private List methods = new ArrayList<>(); 43 | /** The constructors defined within the class */ 44 | private List constructors = new ArrayList<>(); 45 | 46 | public ClassContainer(ClassDefinition def) { 47 | super(builder(def)); 48 | } 49 | 50 | public ClassContainer() { 51 | // empty constructor so that everything can be filled in later. 52 | } 53 | 54 | public List getFields() { 55 | return fields; 56 | } 57 | 58 | public void setFields(List fields) { 59 | this.fields = fields; 60 | } 61 | 62 | public List getMethods() { 63 | return methods; 64 | } 65 | 66 | public void setMethods(List methods) { 67 | this.methods = methods; 68 | } 69 | 70 | public List getGetters() { 71 | return methods.stream().filter(this::isGetter).collect(Collectors.toList()); 72 | } 73 | 74 | public List getSetters() { 75 | return methods.stream().filter(this::isSetter).collect(Collectors.toList()); 76 | } 77 | 78 | public List getConstructors() { 79 | return constructors; 80 | } 81 | 82 | public void setConstructors(List constructors) { 83 | this.constructors = constructors; 84 | } 85 | 86 | public List getFieldImports() { 87 | return getTypeImports(fields); 88 | } 89 | 90 | public List getMethodImports() { 91 | return getTypeImports(methods); 92 | } 93 | 94 | public Set getImports() { 95 | Set set = new HashSet<>(); 96 | set.addAll(getMethodImports()); 97 | set.addAll(getFieldImports()); 98 | return set; 99 | } 100 | 101 | private List getTypeImports(final List methods2) { 102 | return methods2.stream().map(TypeDefinition::getTypeImports).flatMap(Collection::stream).distinct().collect(Collectors.toList()); 103 | } 104 | 105 | private boolean isGetter(MethodDefinition m) { 106 | String n = m.getName().toString(); 107 | return n.startsWith("get") || n.startsWith("is"); 108 | } 109 | 110 | private boolean isSetter(MethodDefinition m) { 111 | return m.getName().toString().startsWith("set"); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/templateInput/StringConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package templateInput; 19 | 20 | import org.apache.commons.lang3.builder.EqualsBuilder; 21 | 22 | import templateInput.definition.TypeDefinition; 23 | 24 | /** 25 | * Class for template input, contains frequently used string conversions of the name of {@link TypeDefinition}, like uppercasing the first char, or snake casing 26 | * the whole string. 27 | * 28 | * @author Daan 29 | */ 30 | public class StringConverter { 31 | 32 | private String string; 33 | 34 | public StringConverter(String string) { 35 | this.string = string; 36 | } 37 | 38 | public String getLower() { 39 | return string.toLowerCase(); 40 | } 41 | 42 | public String getUpper() { 43 | return string.toUpperCase(); 44 | } 45 | 46 | public String getLowerFirst() { 47 | char[] c = string.toCharArray(); 48 | c[0] = Character.toLowerCase(c[0]); 49 | return new String(c); 50 | } 51 | 52 | public String getUpperFirst() { 53 | char[] c = string.toCharArray(); 54 | c[0] = Character.toUpperCase(c[0]); 55 | return new String(c); 56 | } 57 | 58 | public String getSnakeCase() { 59 | String regex = "([A-Z])"; 60 | String replacement = "_$1"; 61 | return string.replaceAll(regex, replacement).toUpperCase(); 62 | } 63 | 64 | public String getLowerSpace() { 65 | String regex = "([A-Z])"; 66 | String replacement = " $1"; 67 | return getLowerFirst().replaceAll(regex, replacement).toLowerCase(); 68 | } 69 | 70 | public String getLowerDash() { 71 | String regex = "([A-Z])"; 72 | String replacement = "-$1"; 73 | return getLowerFirst().replaceAll(regex, replacement).toLowerCase(); 74 | } 75 | 76 | @Override 77 | public String toString() { 78 | return string; 79 | } 80 | 81 | @Override 82 | public boolean equals(Object obj) { 83 | boolean equals = false; 84 | if (this == obj) { 85 | equals = true; 86 | } else if (obj != null && getClass() == obj.getClass()) { 87 | StringConverter other = (StringConverter) obj; 88 | equals = new EqualsBuilder().append(string, other.string).isEquals(); 89 | } 90 | return equals; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/templateInput/TemplateInputDefaults.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package templateInput; 19 | 20 | import generator.Generator; 21 | 22 | /** 23 | * Enumeration of all possible custom input variable names that can be used inside a template. Any name, which is defined inside this enum, used inside a 24 | * template as variable will be filled with custom logic depending on other input by the {@link Generator}. 25 | * 26 | * @author Daan 27 | */ 28 | public enum TemplateInputDefaults { 29 | CLASS("class"), 30 | FIELDS("fields"), 31 | CONSTRUCTORS("constructors"), 32 | METHODS("methods"), 33 | PACKAGE("package"), 34 | MERGE_CLASS_NAME("mergeClassName"); 35 | 36 | private final String name; 37 | 38 | private TemplateInputDefaults(String name) { 39 | this.name = name; 40 | } 41 | 42 | public String getName() { 43 | return this.name; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/templateInput/TemplateInputParameters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package templateInput; 19 | 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | 23 | /** 24 | * Class containing the input parameters for a template. 25 | * 26 | * @author Daan 27 | */ 28 | public class TemplateInputParameters extends HashMap { 29 | private static final long serialVersionUID = 7129701603512062051L; 30 | 31 | public TemplateInputParameters(Map collect) { 32 | super(collect); 33 | } 34 | 35 | public TemplateInputParameters() { 36 | // empty constructor 37 | } 38 | 39 | public TemplateInputParameters copy() { 40 | return new TemplateInputParameters(this); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/templateInput/definition/ClassDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package templateInput.definition; 19 | 20 | import java.util.HashSet; 21 | import java.util.List; 22 | import java.util.Set; 23 | 24 | import org.apache.commons.lang3.builder.EqualsBuilder; 25 | import org.apache.commons.lang3.builder.ToStringBuilder; 26 | import org.apache.commons.lang3.builder.ToStringStyle; 27 | 28 | import templateInput.StringConverter; 29 | 30 | /** 31 | * Describes a class. This includes attributes defined ON the class (className, implemented interfaces, annotations ...). It excludes attributes defined INSIDE 32 | * the class (fields, methods ...). 33 | * 34 | * @author Daan 35 | */ 36 | public class ClassDefinition extends TypeDefinition { 37 | 38 | private String extend; 39 | private List interfaces; 40 | 41 | public ClassDefinition() { 42 | // public constructor to make it possible to extend this class. 43 | } 44 | 45 | protected ClassDefinition(Builder builder) { 46 | this.name = builder.name; 47 | this.type = new StringConverter(builder.type); 48 | this.lineNumber = builder.lineNumber; 49 | this.column = builder.column; 50 | this.annotations = builder.annotations; 51 | this.accessModifiers = builder.accessModifiers; 52 | this.extend = builder.extend; 53 | this.interfaces = builder.interfaces; 54 | } 55 | 56 | public String getExtend() { 57 | return extend; 58 | } 59 | 60 | public void setExtend(String extend) { 61 | this.extend = extend; 62 | } 63 | 64 | public List getInterfaces() { 65 | return interfaces; 66 | } 67 | 68 | public void setInterfaces(List interfaces) { 69 | this.interfaces = interfaces; 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).appendSuper(super.toString()).append("extend", extend).append("interfaces", interfaces) 75 | .build(); 76 | } 77 | 78 | @Override 79 | public boolean equals(Object obj) { 80 | boolean equals = false; 81 | if (this == obj) { 82 | equals = true; 83 | } else if (obj != null && getClass() == obj.getClass()) { 84 | ClassDefinition other = (ClassDefinition) obj; 85 | equals = new EqualsBuilder().appendSuper(super.equals(obj)).append(extend, other.extend).append(interfaces, other.interfaces).isEquals(); 86 | } 87 | return equals; 88 | } 89 | 90 | /** 91 | * Creates builder to build {@link VariableDefinition}. 92 | * 93 | * @return created builder 94 | */ 95 | public static Builder builder() { 96 | return new Builder(); 97 | } 98 | 99 | /** 100 | * Creates builder to build {@link VariableDefinition} filled with data from the input {@link ClassDefinition}. 101 | * 102 | * @param copy The {@link ClassDefinition} to copy. 103 | * @return created builder 104 | */ 105 | public static Builder builder(ClassDefinition copy) { 106 | return new Builder(copy); 107 | } 108 | 109 | /** 110 | * Builder to build {@link VariableDefinition}. 111 | */ 112 | public static final class Builder { 113 | private StringConverter name; 114 | private String type; 115 | private int lineNumber; 116 | private int column; 117 | private Set annotations = new HashSet<>(); 118 | private Set accessModifiers = new HashSet<>(); 119 | private String extend; 120 | public List interfaces; 121 | 122 | private Builder() { 123 | } 124 | 125 | private Builder(ClassDefinition copy) { 126 | this.name = copy.name; 127 | this.type = copy.type.toString(); 128 | this.lineNumber = copy.lineNumber; 129 | this.column = copy.column; 130 | this.annotations = copy.annotations; 131 | this.accessModifiers = copy.accessModifiers; 132 | this.extend = copy.extend; 133 | this.interfaces = copy.interfaces; 134 | } 135 | 136 | public Builder name(String name) { 137 | this.name = new StringConverter(name); 138 | return this; 139 | } 140 | 141 | public Builder type(String type) { 142 | this.type = type; 143 | return this; 144 | } 145 | 146 | public Builder lineNumber(int lineNumber) { 147 | this.lineNumber = lineNumber; 148 | return this; 149 | } 150 | 151 | public Builder column(int column) { 152 | this.column = column; 153 | return this; 154 | } 155 | 156 | public Builder annotations(Set annotations) { 157 | this.annotations = annotations; 158 | return this; 159 | } 160 | 161 | public Builder accessModifiers(Set accessModifiers) { 162 | this.accessModifiers = accessModifiers; 163 | return this; 164 | } 165 | 166 | public Builder interfaces(List interfaces) { 167 | this.interfaces = interfaces; 168 | return this; 169 | } 170 | 171 | public Builder extend(String extend) { 172 | this.extend = extend; 173 | return this; 174 | } 175 | 176 | public ClassDefinition build() { 177 | return new ClassDefinition(this); 178 | } 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /src/main/java/templateInput/definition/FlowReceiverDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package templateInput.definition; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | /** 24 | * VariableDefinition receiving a flow 25 | * 26 | * @author Daan 27 | */ 28 | public class FlowReceiverDefinition extends VariableDefinition { 29 | 30 | private List receivedValues = new ArrayList<>(); 31 | 32 | public FlowReceiverDefinition() { 33 | // explicitly make constructor visible 34 | } 35 | 36 | protected FlowReceiverDefinition(Builder builder) { 37 | super(builder); 38 | this.receivedValues = builder.receivedValues; 39 | } 40 | 41 | public List getReceivedValues() { 42 | return receivedValues; 43 | } 44 | 45 | /** 46 | * @return If the list of received values is not empty, get the first received value, otherwise get null as string. 47 | */ 48 | public String getReceivedValue() { 49 | return receivedValues.isEmpty() ? "null" : receivedValues.get(0); 50 | } 51 | 52 | /** 53 | * If we don't have multiple assignments to the given parameter, this will result in a single name. If we have multiple assignments this name will not be 54 | * defined in any other way, and will thus result in a compilation error if we don't define it explicitly. 55 | * 56 | * @return Concatenation of all received Values names. 57 | */ 58 | public String getAllReceivedValues() { 59 | return String.join("_", receivedValues); 60 | } 61 | 62 | public void setReceivedValues(List receivedValues) { 63 | this.receivedValues = receivedValues; 64 | } 65 | 66 | /** 67 | * Creates builder to build {@link VariableDefinition}. 68 | * 69 | * @return created builder 70 | */ 71 | public static Builder builder() { 72 | return new Builder(); 73 | } 74 | 75 | /** 76 | * Builder to build {@link VariableDefinition}. 77 | */ 78 | public static class Builder extends VariableDefinition.Builder { 79 | private List receivedValues; 80 | 81 | protected Builder() { 82 | super(); 83 | } 84 | 85 | public Builder receivedValues(List receivedValues) { 86 | this.receivedValues = receivedValues; 87 | return this; 88 | } 89 | 90 | public Builder copy(FlowReceiverDefinition field) { 91 | super.copy(field); 92 | this.receivedValues = field.getReceivedValues(); 93 | return this; 94 | } 95 | 96 | @Override 97 | public FlowReceiverDefinition build() { 98 | return new FlowReceiverDefinition(this); 99 | } 100 | 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/templateInput/definition/VariableDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package templateInput.definition; 19 | 20 | import org.apache.commons.lang3.builder.EqualsBuilder; 21 | import org.apache.commons.lang3.builder.ToStringBuilder; 22 | import org.apache.commons.lang3.builder.ToStringStyle; 23 | 24 | /** 25 | * This represents the definition of a variable inside a java class. 26 | * 27 | * @author Daan 28 | */ 29 | public class VariableDefinition extends InitializedTypeDefinition { 30 | 31 | /** The original assignment to this variable */ 32 | private String originalInit; 33 | 34 | public VariableDefinition() { 35 | // explicitly make constructor visible 36 | } 37 | 38 | /** 39 | * Copy constructor 40 | * 41 | * @param var 42 | */ 43 | public VariableDefinition(VariableDefinition var) { 44 | super(var); 45 | } 46 | 47 | protected VariableDefinition(Builder builder) { 48 | super(builder); 49 | this.originalInit = builder.originalInit; 50 | } 51 | 52 | /** 53 | * @return {@link VariableDefinition#originalInit} 54 | */ 55 | public String getOriginalInit() { 56 | return originalInit; 57 | } 58 | 59 | /** 60 | * Sets the {@link VariableDefinition#originalInit} 61 | * 62 | * @param originalInit 63 | */ 64 | public void setOriginalInit(String originalInit) { 65 | this.originalInit = originalInit; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).appendSuper(super.toString()).append("originalInit", originalInit).build(); 71 | } 72 | 73 | @Override 74 | public boolean equals(Object obj) { 75 | boolean equals = false; 76 | if (this == obj) { 77 | equals = true; 78 | } else if (obj != null && getClass() == obj.getClass()) { 79 | VariableDefinition other = (VariableDefinition) obj; 80 | equals = new EqualsBuilder().appendSuper(super.equals(obj)).append(originalInit, other.originalInit).isEquals(); 81 | } 82 | return equals; 83 | } 84 | 85 | /** 86 | * Creates builder to build {@link VariableDefinition}. 87 | * 88 | * @return created builder 89 | */ 90 | public static Builder builder() { 91 | return new Builder<>(); 92 | } 93 | 94 | /** 95 | * Builder to build {@link VariableDefinition}. 96 | */ 97 | @SuppressWarnings("unchecked") 98 | public static class Builder> extends InitializedTypeDefinition.Builder { 99 | private String originalInit; 100 | 101 | protected Builder() { 102 | super(); 103 | } 104 | 105 | public T originalInit(String originalInit) { 106 | this.originalInit = originalInit; 107 | return (T) this; 108 | } 109 | 110 | public T copy(VariableDefinition field) { 111 | super.copy(field); 112 | this.originalInit = field.getOriginalInit(); 113 | return (T) this; 114 | } 115 | 116 | public VariableDefinition build() { 117 | return new VariableDefinition(this); 118 | } 119 | 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/classTypeImports.javat: -------------------------------------------------------------------------------- 1 | <#list class.typeImports as import> 2 | import ${import}; 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/header.javat: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ -------------------------------------------------------------------------------- /src/main/resources/templates/common/package.javat: -------------------------------------------------------------------------------- 1 | package ${package}; 2 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/typeImports.javat: -------------------------------------------------------------------------------- 1 | <#list fields as field> 2 | <#list field.typeImports as import> 3 | import ${import}; 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/templates/equals.javat: -------------------------------------------------------------------------------- 1 | import org.apache.commons.lang3.builder.EqualsBuilder; 2 | 3 | @Override 4 | public boolean equals(Object obj) { 5 | boolean equals = false; 6 | if (this == obj) { 7 | equals = true; 8 | } else if (obj != null && getClass() == obj.getClass()) { 9 | ${mergeClassName} other = (${mergeClassName}) obj; 10 | equals = new EqualsBuilder() 11 | <#if class.extend??> 12 | .appendSuper(super.equals(obj)) 13 | 14 | <#list fields as field> 15 | .append(${field.name}, other.${field.name}) 16 | 17 | .isEquals(); 18 | } 19 | return equals; 20 | } -------------------------------------------------------------------------------- /src/main/resources/templates/equalsTest.javat: -------------------------------------------------------------------------------- 1 | import java.util.function.BiFunction; 2 | import org.junit.Assert; 3 | import org.junit.Test; 4 | 5 | <#include "/test/common/imports.javat"> 6 | 7 | <#include "/test/common/staticFieldInit.javat"> 8 | 9 | @Test 10 | public void testEquals_Same() { 11 | ${class.name}.Builder builder = createAndFillBuilder(); 12 | ${class.name} a = builder.build(); 13 | ${class.name} b = builder.build(); 14 | Assert.assertTrue("Expected a and b to be equal", a.equals(b)); 15 | } 16 | 17 | @Test 18 | public void testEquals_Different() { 19 | <#list fields as field> 20 | verifyEqualsDifferent(${class.name}.Builder::${field.name}, ${field.init2}); 21 | 22 | } 23 | 24 | private void verifyEqualsDifferent(BiFunction<${class.name}.Builder, T, ${class.name}.Builder> withMapper, T argument) { 25 | ${class.name}.Builder builder = createAndFillBuilder(); 26 | ${class.name} a = builder.build(); 27 | ${class.name} b = withMapper.apply(builder, argument).build(); 28 | Assert.assertFalse("Expected a and b not to be equal", a.equals(b)); 29 | } 30 | 31 | <#include "/test/common/createAndFillBuilderWithStaticFields.javat"> 32 | -------------------------------------------------------------------------------- /src/main/resources/templates/extendableInnerBuilder.javat: -------------------------------------------------------------------------------- 1 | 2 | <#if !constructors?? | constructors?size < 1> 3 | public ${class.name}() { 4 | // empty constructor which would otherwise be invisible due to the constructor receiving the builder. 5 | } 6 | 7 | 8 | protected ${class.name}(${class.name}.Builder builder) { 9 | <#list fields as field> 10 | this.${field.name} = builder.${field.name} == null ? this.${field.name} : builder.${field.name}; 11 | 12 | } 13 | 14 | /** 15 | * Creates builder to build {@link ${class.name}}. 16 | * @return created builder 17 | */ 18 | public static Builder builder() { 19 | return new Builder(); 20 | } 21 | 22 | /** 23 | * Builder to build {@link ${class.name}}. 24 | */ 25 | @SuppressWarnings("unchecked") 26 | public static class Builder> { 27 | <#list fields as field> 28 | private ${field.type} ${field.name}<#if field.defaultInit??> = ${field.defaultInit}; 29 | 30 | 31 | protected Builder() { 32 | // Builder should only be used via the parent class or extending builder 33 | } 34 | 35 | <#list fields as field> 36 | public T ${field.name}(${field.type} ${field.name}) { 37 | <#if field.collection> 38 | this.${field.name}.clear(); 39 | this.${field.name}.addAll(${field.name}); 40 | <#else> 41 | this.${field.name} = ${field.name}; 42 | 43 | return (T) this; 44 | } 45 | 46 | 47 | 48 | public ${class.name} build() { 49 | return new ${class.name}(this); 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/resources/templates/getterSetter.javat: -------------------------------------------------------------------------------- 1 | <#list fields as field> 2 | /** 3 | * Gets the ${field.name.lowerSpace} of the {@link ${class.name}}. 4 | * 5 | * @return {@link ${field.nonPrimitiveType}} 6 | */ 7 | public ${field.type} ${field.getter}() { 8 | return ${field.name}; 9 | } 10 | 11 | /** 12 | * Sets the ${field.name.lowerSpace} of the {@link ${class.name}}. 13 | * 14 | * @param ${field.name} The input {@link ${field.nonPrimitiveType}}. 15 | */ 16 | public void ${field.setter}(${field.type} ${field.name}) { 17 | this.${field.name} = ${field.name}; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/templates/hashCode.javat: -------------------------------------------------------------------------------- 1 | import java.util.Objects; 2 | 3 | @Override 4 | public int hashCode() { 5 | return Objects.hash( 6 | <#list fields as field> 7 | ${field.name} 8 | <#if !field?is_last>, 9 | ); 10 | } -------------------------------------------------------------------------------- /src/main/resources/templates/hashCodeTest.javat: -------------------------------------------------------------------------------- 1 | import java.util.function.BiFunction; 2 | import org.junit.Assert; 3 | import org.junit.Test; 4 | 5 | <#include "/test/common/imports.javat"> 6 | 7 | <#include "/test/common/staticFieldInit.javat"> 8 | 9 | @Test 10 | public void testHashCode_Same() { 11 | ${class.name}.Builder builder = createAndFillBuilder(); 12 | ${class.name} a = builder.build(); 13 | ${class.name} b = builder.build(); 14 | Assert.assertEquals("Expected hash code to be the same", a.hashCode(), b.hashCode()); 15 | } 16 | 17 | @Test 18 | public void testHashCode_Different() { 19 | <#list fields as field> 20 | verifyHashCode_Different(${class.name}.Builder::${field.name}, ${field.init2}); 21 | 22 | } 23 | 24 | private void verifyHashCode_Different(BiFunction<${class.name}.Builder, T, ${class.name}.Builder> withMapper, T argument) { 25 | ${class.name}.Builder builder = createAndFillBuilder(); 26 | ${class.name} a = builder.build(); 27 | ${class.name} b = withMapper.apply(builder, argument).build(); 28 | Assert.assertNotEquals("Expected hash code to be different", a.hashCode(), b.hashCode()); 29 | } 30 | 31 | <#include "/test/common/createAndFillBuilderWithStaticFields.javat"> 32 | -------------------------------------------------------------------------------- /src/main/resources/templates/innerBuilder.javat: -------------------------------------------------------------------------------- 1 | 2 | <#if !constructors?? | constructors?size < 1> 3 | public ${class.name}() { 4 | // empty constructor which would otherwise be invisible due to the constructor receiving the builder. 5 | } 6 | 7 | 8 | private ${class.name}(Builder builder) { 9 | <#list fields as field> 10 | this.${field.name} = builder.${field.name} == null ? this.${field.name} : builder.${field.name}; 11 | 12 | } 13 | 14 | /** 15 | * Creates builder to build {@link ${class.name}}. 16 | * @return created builder 17 | */ 18 | public static Builder builder() { 19 | return new Builder(); 20 | } 21 | 22 | /** 23 | * Builder to build {@link ${class.name}}. 24 | */ 25 | public static final class Builder { 26 | <#list fields as field> 27 | private ${field.type} ${field.name}<#if field.defaultInit??> = ${field.defaultInit}; 28 | 29 | 30 | private Builder() { 31 | // Builder should only be constructed via the parent class 32 | } 33 | 34 | public Builder copy(${class.name} original) { 35 | <#list fields as field> 36 | <#if field.collection > 37 | this.${field.name}.clear(); 38 | this.${field.name}.addAll(original.get${field.name.upperFirst}()); 39 | <#else> 40 | this.${field.name} = original.get${field.name.upperFirst}(); 41 | 42 | 43 | return this; 44 | } 45 | 46 | <#list fields as field> 47 | public Builder ${field.name}(${field.type} ${field.name}) { 48 | <#if field.collection> 49 | this.${field.name}.clear(); 50 | this.${field.name}.addAll(${field.name}); 51 | <#else> 52 | this.${field.name} = ${field.name}; 53 | 54 | return this; 55 | } 56 | 57 | 58 | 59 | public ${class.name} build() { 60 | return new ${class.name}(this); 61 | } 62 | } -------------------------------------------------------------------------------- /src/main/resources/templates/innerBuilderTest.javat: -------------------------------------------------------------------------------- 1 | import org.junit.Assert; 2 | import org.junit.Test; 3 | 4 | <#include "/test/common/imports.javat"> 5 | 6 | <#include "/test/common/staticFieldInit.javat"> 7 | 8 | @Test 9 | public void test${class.name}_minimum() { 10 | ${class.name} ${class.name.lowerFirst} = ${class.name}.builder().build(); 11 | 12 | <#list fields as field> 13 | <#if field.noInit == "null"> 14 | Assert.assertNull("Unexpected ${field.name}", ${class.name.lowerFirst}.${field.getter}()); 15 | <#elseif field.type == "boolean"> 16 | Assert.assertFalse("Unexpected ${field.name}", ${class.name.lowerFirst}.${field.getter}()); 17 | <#elseif field.collection> 18 | Assert.assertTrue("Unexpected ${field.name}", ${class.name.lowerFirst}.${field.getter}().isEmpty()); 19 | <#else> 20 | Assert.assertEquals("Unexpected ${field.name}", ${field.noInit}, ${class.name.lowerFirst}.${field.getter}()); 21 | 22 | 23 | } 24 | 25 | @Test 26 | public void test${class.name}_maximum() { 27 | ${class.name} ${class.name.lowerFirst} = createAndFillBuilder().build(); 28 | assertMaximum(${class.name.lowerFirst}); 29 | } 30 | 31 | @Test 32 | public void test${class.name}_Copy() { 33 | ${class.name} ${class.name.lowerFirst} = ${class.name}.builder().copy(createAndFillBuilder().build()).build(); 34 | assertMaximum(${class.name.lowerFirst}); 35 | } 36 | 37 | private void assertMaximum(${class.name} ${class.name.lowerFirst}) { 38 | <#list fields as field> 39 | <#if field.type == "boolean"> 40 | Assert.assertTrue("Unexpected ${field.name}", ${class.name.lowerFirst}.${field.getter}()); 41 | <#else> 42 | Assert.assertEquals("Unexpected ${field.name}", ${field.name.snakeCase}, ${class.name.lowerFirst}.${field.getter}()); 43 | 44 | 45 | } 46 | 47 | <#include "/test/common/createAndFillBuilderWithStaticFields.javat"> 48 | -------------------------------------------------------------------------------- /src/main/resources/templates/test/common/createAndFillBuilderWithStaticFields.javat: -------------------------------------------------------------------------------- 1 | private ${class.name}.Builder createAndFillBuilder() { 2 | return ${class.name}.builder() 3 | <#list fields as field> 4 | .${field.name}(${field.name.snakeCase}) 5 | 6 | ; 7 | } -------------------------------------------------------------------------------- /src/main/resources/templates/test/common/emptyTestClass.javat: -------------------------------------------------------------------------------- 1 | <#include "../../common/header.javat"> 2 | <#include "../../common/package.javat"> 3 | 4 | <#include "testClassDefinition.javat">{ 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/templates/test/common/imports.javat: -------------------------------------------------------------------------------- 1 | <#list fields as field> 2 | <#list field.typeImports as import> 3 | import ${import}; 4 | 5 | <#list field.initImports as import> 6 | import ${import}; 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/templates/test/common/staticFieldInit.javat: -------------------------------------------------------------------------------- 1 | <#list fields as field> 2 | private static final ${field.type} ${field.name.snakeCase} = ${field.init1}; 3 | -------------------------------------------------------------------------------- /src/main/resources/templates/test/common/testClassDefinition.javat: -------------------------------------------------------------------------------- 1 | import org.junit.runner.RunWith; 2 | import org.mockito.runners.MockitoJUnitRunner; 3 | 4 | /** 5 | * Unit test for {@link ${class.name}}. 6 | * 7 | * @author Daan 8 | */ 9 | @RunWith(MockitoJUnitRunner.class) 10 | public class ${class.name}Test -------------------------------------------------------------------------------- /src/main/resources/templates/test/generic/stateFullClassTest.javat: -------------------------------------------------------------------------------- 1 | // TODO none of the below shared stuff is under JavaForger 2 | <#-- 3 | <#include "shared/header.javat"> 4 | <#include "shared/package.javat"> 5 | <#include "/test/common/imports.javat"> 6 | --> 7 | 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | 11 | private ${class.type} sut = new ${class.type}(); 12 | 13 | <#list methods as method> 14 | @Test 15 | public void test${method.name.upperFirst}() { 16 | 17 | <#list method.parameters as parameter> 18 | ${parameter.type} ${parameter.name} = ${parameter.init1}; 19 | 20 | 21 | // TODO currently only works for void methods 22 | sut.${method.name}( 23 | <#list method.parameters as parameter> 24 | ${parameter.name}<#sep>, 25 | 26 | ); 27 | 28 | // TODO field has to be a new class FlowReceiverDefnition extends VariableDefinition 29 | <#list method.changedFields as field> 30 | Assert.assertEquals("Unexpected ${field.name}", ${field.receivedValue}, sut.${field.getter}()); 31 | 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/main/resources/templates/test/generic/statelessClassTest.javat: -------------------------------------------------------------------------------- 1 | // TODO none of the below shared stuff is under JavaForger 2 | <#-- 3 | <#include "shared/header.javat"> 4 | <#include "shared/package.javat"> 5 | <#include "/test/common/imports.javat"> 6 | --> 7 | 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | import org.mockito.InjectMocks; 11 | import org.mockito.Mock; 12 | import org.mockito.Mockito; 13 | 14 | <#list fields as field> 15 | @Mock 16 | private ${field.type} ${field.name}; 17 | 18 | 19 | @InjectMocks 20 | private ${class.type} sut; 21 | 22 | <#list methods as method> 23 | @Test 24 | public void test${method.name.upperFirst}() { 25 | 26 | <#list method.parameters as parameter> 27 | ${parameter.type} ${parameter.name} = ${parameter.init1}; 28 | 29 | 30 | <#-- 31 | // TODO these are all the starting nodes inside a method, e.g. "23" is a starting node in "countService.countUntil(23);". 32 | <#list method.definedVariables as var> 33 | ${var.type} ${var.name} = ${var.defaultInit}; 34 | 35 | --> 36 | 37 | <#list method.inputMethods as input> 38 | ${input.type} ${input.returnSignature} = ${input.init1}; 39 | Mockito.when(${input.instance}.${input.callSignature}).thenReturn(${input.returnSignature}); 40 | 41 | 42 | <#if method.expectedReturn??> 43 | ${method.type} return_${method.name} = sut.${method.callSignature}; 44 | 45 | Assert.assertEquals("Unexpected ${method.name}", ${method.expectedReturn}, return_${method.name}); 46 | <#else> 47 | sut.${method.callSignature}; 48 | 49 | 50 | <#list method.outputMethods as output> 51 | Mockito.verify(${output.instance}).${output.callSignature}; 52 | 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/main/resources/templates/toString.javat: -------------------------------------------------------------------------------- 1 | import org.apache.commons.lang3.builder.ToStringBuilder; 2 | import org.apache.commons.lang3.builder.ToStringStyle; 3 | 4 | @Override 5 | public String toString() { 6 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 7 | <#if class.extend??> 8 | .appendSuper(super.toString()) 9 | 10 | <#list fields as field> 11 | .append("${field.name}", ${field.name}) 12 | 13 | .build(); 14 | } -------------------------------------------------------------------------------- /src/test/java/common/SymbolSolverSetup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package common; 19 | 20 | import com.github.javaparser.symbolsolver.JavaSymbolSolver; 21 | import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 22 | import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; 23 | import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; 24 | import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; 25 | 26 | import configuration.StaticJavaForgerConfiguration; 27 | 28 | /** 29 | * Class with common test methods for seting up the symbol solver. 30 | * 31 | * @author Daan 32 | */ 33 | public class SymbolSolverSetup { 34 | 35 | private static JavaSymbolSolver getSymbolSolver() { 36 | JavaParserTypeSolver typeSolver_directory = new JavaParserTypeSolver("src/test/java/"); 37 | ReflectionTypeSolver reflTypeSolver = new ReflectionTypeSolver(); 38 | TypeSolver typeSolver = new CombinedTypeSolver(typeSolver_directory, reflTypeSolver); 39 | JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver); 40 | return symbolSolver; 41 | } 42 | 43 | public static void setup() { 44 | StaticJavaForgerConfiguration.getConfig().setSymbolSolver(getSymbolSolver()); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/generator/CodeSnipitTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package generator; 19 | 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | /** 24 | * Unit test for the {@link CodeSnipit} 25 | * 26 | * @author Daan 27 | */ 28 | public class CodeSnipitTest { 29 | 30 | @Test 31 | public void testCodeSnipitConstructor() { 32 | String codeString = "a\nb\nc"; 33 | CodeSnipit codeSnipit = new CodeSnipit(codeString); 34 | Assert.assertEquals(codeString, codeSnipit.toString()); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/initialization/InitConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package initialization; 19 | 20 | import org.junit.Assert; 21 | import org.junit.Before; 22 | import org.junit.Test; 23 | 24 | /** 25 | * Unit test for {@link InitConverter} 26 | * 27 | * @author Daan 28 | */ 29 | public class InitConverterTest { 30 | 31 | public InitConverter converter = new InitConverter(); 32 | 33 | @Before 34 | public void setup() { 35 | converter.reset(); 36 | } 37 | 38 | @Test 39 | public void testConvert() { 40 | Assert.assertEquals("integer = 1", converter.convert("integer = %d")); 41 | } 42 | 43 | @Test 44 | public void testConvert_() { 45 | Assert.assertEquals("integer = 1 and 2", converter.convert("integer = %d and %d")); 46 | } 47 | 48 | @Test 49 | public void testConvert_String() { 50 | Assert.assertEquals("string = abc", converter.convert("string = %s%s%s")); 51 | } 52 | 53 | @Test 54 | public void testConvert_2Strings() { 55 | Assert.assertEquals("string = abc", converter.convert("string = %s%s%s")); 56 | Assert.assertEquals("string = d", converter.convert("string = %s")); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/initialization/InitializationServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package initialization; 19 | 20 | import org.hamcrest.Matchers; 21 | import org.junit.Assert; 22 | import org.junit.Test; 23 | 24 | import templateInput.definition.VariableDefinition; 25 | 26 | /** 27 | * Unit test for {@link InitializationService}. 28 | * 29 | * @author Daan 30 | */ 31 | public class InitializationServiceTest { 32 | 33 | private InitializationService sut = new InitializationService(); 34 | 35 | @Test 36 | public void testInitialize_parameterized() { 37 | VariableDefinition var = VariableDefinition.builder().type("HashMap").build(); 38 | 39 | sut.init(var); 40 | 41 | Assert.assertEquals( 42 | "Collections.singletonMap(Date.from(ZonedDateTime.of(1, 4, 25, 10, 0, 0, 0, TimeZone.getTimeZone(\"UTC\").toZoneId()).toInstant()), BigDecimal.valueOf(3))", 43 | var.getInit1()); 44 | Assert.assertEquals( 45 | "Collections.singletonMap(Date.from(ZonedDateTime.of(2, 5, 26, 11, 0, 0, 0, TimeZone.getTimeZone(\"UTC\").toZoneId()).toInstant()), BigDecimal.valueOf(4))", 46 | var.getInit2()); 47 | 48 | Assert.assertTrue(var.getTypeImports().isEmpty()); 49 | Assert.assertThat(var.getInitImports(), 50 | Matchers.containsInAnyOrder("java.math.BigDecimal", "java.util.Collections", "java.time.ZonedDateTime", "java.util.TimeZone")); 51 | } 52 | 53 | @Test 54 | public void testInitialize_parameterizedInParameterized() { 55 | VariableDefinition var = VariableDefinition.builder().type("Map, HashMap>").build(); 56 | 57 | sut.init(var); 58 | 59 | Assert.assertEquals("Collections.singletonMap(Collections.singletonMap(1, \"a\"), Collections.singletonMap(new Object(), 3.4))", var.getInit1()); 60 | Assert.assertEquals("Collections.singletonMap(Collections.singletonMap(2, \"b\"), Collections.singletonMap(new Object(), 5.6))", var.getInit2()); 61 | Assert.assertTrue(var.getTypeImports().isEmpty()); 62 | Assert.assertThat(var.getInitImports(), Matchers.containsInAnyOrder("java.util.Collections")); 63 | } 64 | 65 | @Test 66 | public void testInitialize_parameterizedExtends() { 67 | VariableDefinition var = VariableDefinition.builder().type("List").build(); 68 | 69 | sut.init(var); 70 | 71 | Assert.assertEquals("Collections.singletonList(BigDecimal.valueOf(1))", var.getInit1()); 72 | Assert.assertEquals("Collections.singletonList(BigDecimal.valueOf(2))", var.getInit2()); 73 | Assert.assertTrue(var.getTypeImports().isEmpty()); 74 | Assert.assertThat(var.getInitImports(), Matchers.containsInAnyOrder("java.util.Collections", "java.math.BigDecimal")); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/inputClassesForTests/ClassWithEverything.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | private String s; 35 | 36 | public ClassWithEverything(int j) { 37 | this(); 38 | i = j; 39 | } 40 | 41 | private ClassWithEverything() { 42 | // Do nothing 43 | } 44 | 45 | public void method1() { 46 | method2(i, s); 47 | } 48 | 49 | private int method2(int j, String t2) { 50 | s = t2; 51 | return j + 1; 52 | } 53 | 54 | public class InnerClass { 55 | public double d = 0.3; 56 | private float f = 4.8F; 57 | 58 | public void method3() { 59 | method4(d, f); 60 | } 61 | 62 | private int method4(double e, float g) { 63 | d = e; 64 | return Float.floatToIntBits(g); 65 | } 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/inputClassesForTests/ClassWithEverythingTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | /** 21 | * Input class for unit tests. 22 | * 23 | * @author Daan 24 | */ 25 | public class ClassWithEverythingTest { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/inputClassesForTests/ExtendedProduct.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | /** 21 | * Input class for tests. 22 | * 23 | * @author Daan 24 | */ 25 | public class ExtendedProduct extends Product implements TestInterface { 26 | 27 | public ExtendedProduct(String name, String url) { 28 | super(name, url); 29 | } 30 | 31 | @Override 32 | public void someMethod(Object input) { 33 | // do nothing 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/inputClassesForTests/Product.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Objects; 21 | 22 | import org.apache.commons.lang3.builder.EqualsBuilder; 23 | import org.apache.commons.lang3.builder.ToStringBuilder; 24 | import org.apache.commons.lang3.builder.ToStringStyle; 25 | 26 | /** 27 | * Container class for testing purposes. 28 | * 29 | * @author Daan 30 | */ 31 | public class Product { 32 | private String url; 33 | private String name = "interesting"; 34 | public Product prod; 35 | 36 | public Product(String name2, String url) { 37 | this.prod = new Product(); 38 | name = name2; 39 | this.url = url; 40 | } 41 | 42 | public Product() { 43 | // 44 | } 45 | 46 | public String getUrl() { 47 | return url; 48 | } 49 | 50 | public String getName() { 51 | return name; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("url", url).append("name", name).build(); 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | return Objects.hash(url, name); 62 | } 63 | 64 | @Override 65 | public boolean equals(Object obj) { 66 | boolean equals = false; 67 | if (this == obj) { 68 | equals = true; 69 | } else if (obj != null && getClass() == obj.getClass()) { 70 | Product other = (Product) obj; 71 | equals = new EqualsBuilder().append(url, other.url).append(name, other.name).isEquals(); 72 | } 73 | return equals; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/inputClassesForTests/TestInterface.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | /** 21 | * Input interface for testing. 22 | * 23 | * @author Daan 24 | */ 25 | public interface TestInterface { 26 | 27 | void someMethod(Object input); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %-5level %d{HH:mm:ss.SSS} %logger{36}:%L - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/test/java/merger/CodeSnipitInserterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import java.io.IOException; 21 | import java.util.LinkedHashMap; 22 | import java.util.stream.IntStream; 23 | 24 | import org.junit.Assert; 25 | import org.junit.Test; 26 | 27 | import common.AbstractFileChangingTest; 28 | import configuration.JavaForgerConfiguration; 29 | 30 | /** 31 | * Unit test for {@link CodeSnipitInserter}. 32 | * 33 | * @author Daan 34 | */ 35 | public class CodeSnipitInserterTest extends AbstractFileChangingTest { 36 | 37 | /** Path to the file which will be written to create an expected file */ 38 | private static final String EXPECTED_RESULTS_PATH = "src/test/resources/templateTestOutcomes/CodeSnipitInserterTest/"; 39 | 40 | private CodeSnipitInserter inserter = new CodeSnipitInserter(); 41 | 42 | @Test 43 | public void testInsert_addPackageNoOverride() throws IOException { 44 | executeAndVerify("verify-nothingHappend.java", false, CodeSnipitLocation.of(18, 19)); 45 | } 46 | 47 | @Test 48 | public void testInsert_addPackageOverride() throws IOException { 49 | executeAndVerify("verify-overriden.java", true, CodeSnipitLocation.of(18, 19)); 50 | } 51 | 52 | @Test 53 | public void testInsert_addImportNoOverride() throws IOException { 54 | executeAndVerify("verify-inserted.java", false, CodeSnipitLocation.of(19)); 55 | } 56 | 57 | @Test 58 | public void testInsert_addImportOverride() throws IOException { 59 | executeAndVerify("verify-inserted.java", true, CodeSnipitLocation.of(19)); 60 | } 61 | 62 | private void executeAndVerify(String expectedClass, boolean override, CodeSnipitLocation... insertLocation) throws IOException { 63 | LinkedHashMap newCodeInsertionLocations = new LinkedHashMap<>(); 64 | 65 | IntStream.range(0, insertLocation.length).forEach(i -> newCodeInsertionLocations.put(CodeSnipitLocation.of(1 + i, 2 + i), insertLocation[i])); 66 | 67 | executeAndVerify(expectedClass, override, newCodeInsertionLocations); 68 | } 69 | 70 | private void executeAndVerify(String expectedClass, boolean override, LinkedHashMap newCodeInsertionLocations) 71 | throws IOException { 72 | inserter.insert(JavaForgerConfiguration.builder().override(override).build(), INPUT_CLASS, "this is the new Code 1\nthis is the new Code 2\n", 73 | newCodeInsertionLocations); 74 | verifyFileEqual(EXPECTED_RESULTS_PATH + expectedClass, INPUT_CLASS); 75 | } 76 | 77 | /** 78 | * VERY DANGEROUS MAIN METHOD, ONLY USE THIS WHEN YOU KNOW WHAT YOU'RE DOING. 79 | *

80 | * This main method will force the whole test to be green again, by replacing all verify files with the actual result. 81 | * 82 | * @param args 83 | * @throws IOException 84 | */ 85 | public static void main(String[] args) throws IOException { 86 | 87 | // This statement prevents the main method from accidently being executed. 88 | Assert.fail(); 89 | 90 | CodeSnipitInserterTest test = new CodeSnipitInserterTest() { 91 | @Override 92 | protected void verifyFileEqual(String expectedPath, String actualPath) throws IOException { 93 | System.out.println("Copying:\n" + actualPath + " to:\n" + expectedPath); 94 | super.copyClass(actualPath, expectedPath); 95 | } 96 | }; 97 | 98 | test.setup(); 99 | test.testInsert_addPackageNoOverride(); 100 | test.setup(); 101 | test.testInsert_addPackageOverride(); 102 | test.setup(); 103 | test.testInsert_addImportNoOverride(); 104 | test.setup(); 105 | test.testInsert_addImportOverride(); 106 | test.tearDown(); 107 | 108 | Assert.fail(); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/test/java/merger/CodeSnipitLocaterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import java.util.Iterator; 21 | import java.util.LinkedHashMap; 22 | import java.util.Map.Entry; 23 | 24 | import org.junit.Assert; 25 | import org.junit.Test; 26 | 27 | import com.github.javaparser.ast.CompilationUnit; 28 | 29 | import reader.Parser; 30 | 31 | /** 32 | * Unit test for {@link CodeSnipitLocater} 33 | * 34 | * @author Daan 35 | */ 36 | public class CodeSnipitLocaterTest { 37 | 38 | private Parser parser = new Parser(); 39 | 40 | private CodeSnipitLocater locater = new CodeSnipitLocater(); 41 | 42 | @Test 43 | public void testLocate() { 44 | String code = "import my.impord;\n\npublic class ClassToMerge {\n\n}"; 45 | 46 | LinkedHashMap expected = new LinkedHashMap<>(); 47 | expected.put(CodeSnipitLocation.of(1, 2), CodeSnipitLocation.of(2, 2)); 48 | 49 | executeAndVerify(code, code, expected); 50 | } 51 | 52 | @Test 53 | public void testLocate_innerClass() { 54 | String code1 = "public class ClassToMerge {\n\npublic class InnerClass1 {\n\n}\n}"; 55 | String code2 = "public class ClassToMerge {\n\nclass InnerClass2 {\n\n}\n}"; 56 | 57 | LinkedHashMap expected = new LinkedHashMap<>(); 58 | expected.put(CodeSnipitLocation.of(3, 6), CodeSnipitLocation.of(6, 6)); 59 | 60 | executeAndVerify(code1, code2, expected); 61 | } 62 | 63 | @Test 64 | public void testLocate_ordering() { 65 | String code1 = "public class ClassToMerge {\n\n" // 66 | + "public int a; \n" // 67 | + "private int b; \n" // 68 | + "\n}"; 69 | String code2 = "public class ClassToMerge {\n\n" // 70 | + "private int c; \n" // 71 | + "public int a = 5; \n" // 72 | + "\n}"; 73 | 74 | LinkedHashMap expected = new LinkedHashMap<>(); 75 | expected.put(CodeSnipitLocation.of(4, 5), CodeSnipitLocation.of(3, 4)); 76 | expected.put(CodeSnipitLocation.of(3, 4), CodeSnipitLocation.of(5, 5)); 77 | 78 | executeAndVerify(code1, code2, expected); 79 | } 80 | 81 | private void executeAndVerify(String existing, String insert, LinkedHashMap expected) { 82 | CompilationUnit cu1 = parser.parse(existing); 83 | CompilationUnit cu2 = parser.parse(insert); 84 | 85 | LinkedHashMap locations = locater.locate(cu1, cu2); 86 | 87 | Assert.assertEquals("Expected the same size", expected.size(), locations.size()); 88 | 89 | Iterator> res = locations.entrySet().iterator(); 90 | Iterator> exp = expected.entrySet().iterator(); 91 | int i = 0; 92 | while (res.hasNext()) { 93 | Assert.assertEquals("Expected the locations on index " + i++ + " to be equal", exp.next(), res.next()); 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/test/java/merger/CodeSnipitLocationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | import com.github.javaparser.ast.CompilationUnit; 24 | import com.github.javaparser.ast.Node; 25 | 26 | import reader.Parser; 27 | 28 | /** 29 | * Unit test for {@link CodeSnipitLocation} 30 | * 31 | * @author Daan 32 | */ 33 | public class CodeSnipitLocationTest { 34 | 35 | private Parser parser = new Parser(); 36 | 37 | @Test 38 | public void testOf_NodeInput() { 39 | Node node = createNode(); 40 | 41 | CodeSnipitLocation location = CodeSnipitLocation.of(node); 42 | 43 | Assert.assertEquals(CodeSnipitLocation.of(2, 3), location); 44 | } 45 | 46 | @Test 47 | public void testBefore_NodeInput() { 48 | Node node = createNode(); 49 | 50 | CodeSnipitLocation location = CodeSnipitLocation.before(node); 51 | 52 | Assert.assertEquals(CodeSnipitLocation.of(2, 2), location); 53 | } 54 | 55 | @Test 56 | public void testOf_NodeInputWithJavaDoc() { 57 | String field = "/**\n Very nice javadoc.\n * With mulitple lines.\n */\nprivate String someField;\n"; 58 | Node node = wrapInsideCompilationUnit(field); 59 | 60 | CodeSnipitLocation location = CodeSnipitLocation.of(node); 61 | 62 | Assert.assertEquals(CodeSnipitLocation.of(6, 11), location); 63 | } 64 | 65 | @Test 66 | public void testOf_NodeInputAnnotation() { 67 | String field = // 68 | "@Anno1\n" // 69 | + "@Anno2\n" // 70 | + "@Anno3\n" // 71 | + "private String someField;\n"; // 72 | Node node = wrapInsideCompilationUnit(field); 73 | 74 | CodeSnipitLocation location = CodeSnipitLocation.of(node); 75 | 76 | Assert.assertEquals(CodeSnipitLocation.of(6, 10), location); 77 | } 78 | 79 | @Test 80 | public void testOf_NodeInputWithJavaDocAndAnnotation() { 81 | String field = "/**\n Very nice javadoc.\n * With mulitple lines.\n */\n@Anno1\n@Anno2\nprivate String someField;\n"; 82 | Node node = wrapInsideCompilationUnit(field); 83 | 84 | CodeSnipitLocation location = CodeSnipitLocation.of(node); 85 | 86 | Assert.assertEquals(CodeSnipitLocation.of(6, 13), location); 87 | } 88 | 89 | @Test 90 | public void testOf_NodeInputWithAnnotationAndJavaDoc() { 91 | String field = // 92 | "@Anno1\n@Anno2\n" // 93 | + "/**\n " // 94 | + "Very nice javadoc.\n " // 95 | + "* With mulitple lines.\n " // 96 | + "*/\n" // 97 | + "private String someField;\n"; // 98 | Node node = wrapInsideCompilationUnit(field); 99 | 100 | CodeSnipitLocation location = CodeSnipitLocation.of(node); 101 | 102 | Assert.assertEquals(CodeSnipitLocation.of(6, 13), location); 103 | } 104 | 105 | private Node createNode() { 106 | String code = "import my.impord;\nimport my.secondimpord;\n\npublic class ClassToMerge {\n\n}"; 107 | CompilationUnit cu = parser.parse(code); 108 | Node node = cu.getChildNodes().get(1); 109 | return node; 110 | } 111 | 112 | private Node wrapInsideCompilationUnit(String field) { 113 | String code = "import my.impord;\nimport my.secondimpord;\n\npublic class ClassToMerge {\n\n" + field + "\n}"; 114 | CompilationUnit cu = parser.parse(code); 115 | Node node = cu.getChildNodes().get(2).getChildNodes().get(2); 116 | return node; 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/test/java/merger/CodeSnipitReaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | import com.github.javaparser.ast.CompilationUnit; 24 | import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; 25 | import com.github.javaparser.ast.body.FieldDeclaration; 26 | 27 | import generator.CodeSnipit; 28 | 29 | /** 30 | * Unit test for {@link CodeSnipitReader} 31 | * 32 | * @author Daan 33 | */ 34 | public class CodeSnipitReaderTest { 35 | 36 | private CodeSnipitReader sut = new CodeSnipitReader(); 37 | 38 | @Test 39 | public void testRead_withClass() { 40 | String code = "class Claz { \n\n" + "protected String prettyString = \"very pretty\";\n" + "\n}\n"; 41 | 42 | CompilationUnit result = sut.read(new CodeSnipit(code), "/path/to/Claz.java"); 43 | 44 | Assert.assertEquals(1, result.getChildNodes().size()); 45 | Assert.assertTrue(result.getChildNodes().get(0) instanceof ClassOrInterfaceDeclaration); 46 | ClassOrInterfaceDeclaration claz = (ClassOrInterfaceDeclaration) result.getChildNodes().get(0); 47 | Assert.assertEquals("Claz", claz.getNameAsString()); 48 | Assert.assertEquals(2, claz.getChildNodes().size()); 49 | Assert.assertTrue(claz.getChildNodes().get(1) instanceof FieldDeclaration); 50 | } 51 | 52 | @Test 53 | public void testRead_WithoutClass() { 54 | String code = "protected String prettyString = \"very pretty\";"; 55 | 56 | CompilationUnit result = sut.read(new CodeSnipit(code), "/path/to/Claz.java"); 57 | 58 | Assert.assertEquals(1, result.getChildNodes().size()); 59 | Assert.assertTrue(result.getChildNodes().get(0) instanceof ClassOrInterfaceDeclaration); 60 | ClassOrInterfaceDeclaration claz = (ClassOrInterfaceDeclaration) result.getChildNodes().get(0); 61 | Assert.assertEquals("Claz", claz.getNameAsString()); 62 | Assert.assertEquals(3, claz.getChildNodes().size()); 63 | Assert.assertTrue(claz.getChildNodes().get(2) instanceof FieldDeclaration); 64 | } 65 | 66 | @Test 67 | public void testToCompleteClass_onlyImport() { 68 | String code = "import my.impord;"; 69 | 70 | String claz = sut.toCompleteClass(new CodeSnipit(code), "The/Path\\To/MyClass.java"); 71 | 72 | Assert.assertEquals(claz, code, claz); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/merger/JavaParserMergerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import java.io.FileReader; 21 | import java.io.IOException; 22 | import java.io.LineNumberReader; 23 | 24 | import org.junit.After; 25 | import org.junit.Test; 26 | 27 | import common.AbstractFileChangingTest; 28 | import configuration.JavaForgerConfiguration; 29 | import generator.CodeSnipit; 30 | 31 | /** 32 | * Unit test for {@link JavaParserMerger}. 33 | * 34 | * @author Daan 35 | */ 36 | public class JavaParserMergerTest extends AbstractFileChangingTest { 37 | 38 | /** Path to the file which will be written to create an expected file */ 39 | private static final String EXPECTED_CLASS = "src/test/resources/temporaryTestResults/ExpectedClass.java"; 40 | private static final JavaForgerConfiguration CONFIG = JavaForgerConfiguration.builder().build(); 41 | 42 | @Override 43 | @After 44 | public void tearDown() { 45 | super.tearDown(); 46 | removeTestClassIfExists(EXPECTED_CLASS); 47 | } 48 | 49 | @Test 50 | public void testMerge_newPublicMethod() throws IOException { 51 | String newCode = "public void newMethod() {\n// Does this method exist?\n}"; 52 | String expected = genExpected(newCode, 48, 48); 53 | 54 | executeAndVerify(expected, newCode); 55 | } 56 | 57 | private void executeAndVerify(String expected, String merge) throws IOException { 58 | executeAndVerify(CONFIG, expected, merge); 59 | } 60 | 61 | private void executeAndVerify(JavaForgerConfiguration conf, String expected, String merge) throws IOException { 62 | new JavaParserMerger().merge(conf, new CodeSnipit(merge), INPUT_CLASS); 63 | 64 | super.stringToFile(EXPECTED_CLASS, expected); 65 | 66 | verifyFileEqual(EXPECTED_CLASS, INPUT_CLASS); 67 | } 68 | 69 | private String genExpected(String newCode, int startRemoveBlock, int endRemoveBlock) throws IOException { 70 | try (LineNumberReader reader = new LineNumberReader(new FileReader(INPUT_CLASS))) { 71 | StringBuilder sb = new StringBuilder(); 72 | 73 | while (reader.getLineNumber() < startRemoveBlock) { 74 | String readLine = reader.readLine(); 75 | sb.append(readLine + "\r\n"); 76 | } 77 | 78 | reader.setLineNumber(endRemoveBlock); 79 | sb.append(newCode + "\r\n\r\n"); 80 | 81 | String readLine = reader.readLine(); 82 | while (readLine != null) { 83 | sb.append(readLine + "\r\n"); 84 | readLine = reader.readLine(); 85 | } 86 | 87 | reader.close(); 88 | 89 | return sb.toString(); 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/merger/LineMergerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import java.io.IOException; 21 | 22 | import org.junit.Assert; 23 | import org.junit.Test; 24 | 25 | import common.AbstractFileChangingTest; 26 | import configuration.JavaForgerConfiguration; 27 | import generator.CodeSnipit; 28 | 29 | /** 30 | * Unit test for {@link JavaParserMerger}. 31 | * 32 | * @author Daan 33 | */ 34 | public class LineMergerTest extends AbstractFileChangingTest { 35 | 36 | /** Path to the file which will be written to create an expected file */ 37 | private static final String EXPECTED_RESULTS_PATH = "src/test/resources/templateTestOutcomes/LineMergerTest/"; 38 | 39 | private LineMerger merger = new LineMerger(); 40 | 41 | @Test 42 | public void testAddInnerClass() throws IOException { 43 | String code = "public class ClassWithEverything {\n class AddedInnerClass {\n protected newMethod() { \n // Do Nothing \n }\n }\n }\n"; 44 | String expectedClass = "verify-addInnerClass.java"; 45 | executeAndVerify(expectedClass, code); 46 | } 47 | 48 | @Test 49 | public void testMergeInnerClass() throws IOException { 50 | String code = "public class ClassWithEverything {\n class InnerClass {\n protected void methodBetween3and4() { \n // Do Nothing \n }\n }\n }\n"; 51 | String expectedClass = "verify-mergeInnerClass.java"; 52 | executeAndVerify(expectedClass, code); 53 | } 54 | 55 | @Test 56 | public void testReplaceConstructor() throws IOException { 57 | String code = "private ClassWithEverything(int i) {\n this.i = i;\n}\n"; 58 | String expectedClass = "verify-constructor.java"; 59 | executeAndVerify(expectedClass, code); 60 | } 61 | 62 | @Test 63 | public void testField() throws IOException { 64 | String code = "protected String prettyString = \"very pretty\";"; 65 | String expectedClass = "verify-field.java"; 66 | executeAndVerify(expectedClass, code); 67 | } 68 | 69 | @Test 70 | public void testImport() throws IOException { 71 | String code = "import my.impord;"; 72 | String expectedClass = "verify-import.java"; 73 | executeAndVerify(expectedClass, code); 74 | } 75 | 76 | @Test 77 | public void testPackage() throws IOException { 78 | String code = "package my.packingedinges;"; 79 | String expectedClass = "verify-package.java"; 80 | executeAndVerify(expectedClass, code); 81 | } 82 | 83 | private void executeAndVerify(String expectedClass, String code) throws IOException { 84 | merger.merge(JavaForgerConfiguration.builder().override(true).build(), new CodeSnipit(code), INPUT_CLASS); 85 | verifyFileEqual(EXPECTED_RESULTS_PATH + expectedClass, INPUT_CLASS); 86 | } 87 | 88 | /** 89 | * VERY DANGEROUS MAIN METHOD, ONLY USE THIS WHEN YOU KNOW WHAT YOU'RE DOING. 90 | *

91 | * This main method will force the whole test to be green again, by replacing all verify files with the actual result. 92 | * 93 | * @param args 94 | * @throws IOException 95 | */ 96 | public static void main(String[] args) throws IOException { 97 | 98 | // This statement prevents the main method from accidently being executed. 99 | Assert.fail(); 100 | 101 | LineMergerTest test = new LineMergerTest() { 102 | @Override 103 | protected void verifyFileEqual(String expectedPath, String actualPath) throws IOException { 104 | System.out.println("Copying:\n" + actualPath + " to:\n" + expectedPath); 105 | super.copyClass(actualPath, expectedPath); 106 | } 107 | }; 108 | 109 | test.setup(); 110 | test.testPackage(); 111 | test.setup(); 112 | test.testImport(); 113 | test.setup(); 114 | test.testField(); 115 | test.setup(); 116 | test.testReplaceConstructor(); 117 | test.setup(); 118 | test.testAddInnerClass(); 119 | test.setup(); 120 | test.testMergeInnerClass(); 121 | test.tearDown(); 122 | 123 | Assert.fail(); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/test/java/merger/NodeComparatorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package merger; 19 | 20 | import java.util.Arrays; 21 | import java.util.List; 22 | import java.util.stream.Collectors; 23 | 24 | import org.junit.Assert; 25 | import org.junit.Test; 26 | 27 | import com.github.javaparser.ast.ImportDeclaration; 28 | import com.github.javaparser.ast.Modifier.Keyword; 29 | import com.github.javaparser.ast.Node; 30 | import com.github.javaparser.ast.PackageDeclaration; 31 | import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; 32 | import com.github.javaparser.ast.body.ConstructorDeclaration; 33 | import com.github.javaparser.ast.body.FieldDeclaration; 34 | import com.github.javaparser.ast.body.MethodDeclaration; 35 | import com.github.javaparser.ast.body.VariableDeclarator; 36 | import com.github.javaparser.ast.expr.SimpleName; 37 | 38 | /** 39 | * Unit test for {@link NodeComparator}. 40 | * 41 | * @author Daan 42 | */ 43 | public class NodeComparatorTest { 44 | 45 | private static final PackageDeclaration PACKAGE = new PackageDeclaration(); 46 | private static final ImportDeclaration IMPORT = new ImportDeclaration("imp", false, false); 47 | private static final FieldDeclaration FIELD = new FieldDeclaration().addVariable(new VariableDeclarator().setName(new SimpleName("fieldName"))); 48 | private static final ConstructorDeclaration CONSTRUCTOR = new ConstructorDeclaration(); 49 | private static final MethodDeclaration METHOD = new MethodDeclaration().setName("method1"); 50 | private static final MethodDeclaration METHOD2 = new MethodDeclaration().setName("method2"); 51 | private static final ClassOrInterfaceDeclaration CLASS = new ClassOrInterfaceDeclaration().setName("class1"); 52 | private static final ClassOrInterfaceDeclaration CLASS2 = new ClassOrInterfaceDeclaration().setName("class2"); 53 | 54 | private NodeComparator comparator = new NodeComparator(); 55 | 56 | @Test 57 | public void testCompare_sorting() { 58 | List nodes = Arrays.asList(METHOD, FIELD, IMPORT, CLASS, IMPORT, CONSTRUCTOR, PACKAGE); 59 | List expected = Arrays.asList(PACKAGE, IMPORT, IMPORT, FIELD, CONSTRUCTOR, METHOD, CLASS); 60 | 61 | List sortedNodes = nodes.stream().sorted(comparator).collect(Collectors.toList()); 62 | 63 | Assert.assertEquals(expected, sortedNodes); 64 | } 65 | 66 | @Test 67 | public void testCompare_modifiers() { 68 | FieldDeclaration f1 = createField("f1", Keyword.PUBLIC); 69 | FieldDeclaration f2 = createField("f2", null); 70 | FieldDeclaration f3 = createField("f3", Keyword.PROTECTED); 71 | FieldDeclaration f4 = createField("f4", Keyword.PRIVATE); 72 | 73 | List nodes = Arrays.asList(f4, f2, f1, f3); 74 | List expected = Arrays.asList(f1, f2, f3, f4); 75 | 76 | List sortedNodes = nodes.stream().sorted(comparator).collect(Collectors.toList()); 77 | 78 | Assert.assertEquals(expected, sortedNodes); 79 | } 80 | 81 | @Test 82 | public void testCompare_equal() { 83 | Assert.assertEquals(0, comparator.compare(PACKAGE, PACKAGE)); 84 | Assert.assertEquals(-1, comparator.compare(IMPORT, IMPORT)); // TODO not supported yet to find equal imports 85 | Assert.assertEquals(0, comparator.compare(FIELD, FIELD)); 86 | Assert.assertEquals(0, comparator.compare(CONSTRUCTOR, CONSTRUCTOR)); 87 | Assert.assertEquals(0, comparator.compare(METHOD, METHOD)); 88 | Assert.assertEquals(0, comparator.compare(CLASS, CLASS)); 89 | } 90 | 91 | @Test 92 | public void testCompare_smaller() { 93 | Assert.assertEquals(-1, comparator.compare(PACKAGE, IMPORT)); 94 | Assert.assertEquals(-1, comparator.compare(IMPORT, FIELD)); 95 | Assert.assertEquals(-1, comparator.compare(FIELD, CONSTRUCTOR)); 96 | Assert.assertEquals(-1, comparator.compare(CONSTRUCTOR, METHOD)); 97 | Assert.assertEquals(-1, comparator.compare(METHOD, CLASS)); 98 | } 99 | 100 | @Test 101 | public void testCompare_bigger() { 102 | Assert.assertEquals(1, comparator.compare(IMPORT, PACKAGE)); 103 | Assert.assertEquals(1, comparator.compare(FIELD, IMPORT)); 104 | Assert.assertEquals(1, comparator.compare(CONSTRUCTOR, FIELD)); 105 | Assert.assertEquals(1, comparator.compare(METHOD, CONSTRUCTOR)); 106 | Assert.assertEquals(1, comparator.compare(CLASS, METHOD)); 107 | } 108 | 109 | @Test 110 | public void testCompare_sameClass() { 111 | Assert.assertEquals(-1, comparator.compare(METHOD, METHOD2)); 112 | Assert.assertEquals(-1, comparator.compare(METHOD2, METHOD)); 113 | Assert.assertEquals(-1, comparator.compare(CLASS, CLASS2)); 114 | Assert.assertEquals(-1, comparator.compare(CLASS2, CLASS)); 115 | } 116 | 117 | private FieldDeclaration createField(String name, Keyword modifier) { 118 | FieldDeclaration f = new FieldDeclaration().addVariable(new VariableDeclarator().setName(new SimpleName(name))); 119 | if (modifier != null) { 120 | f.setModifier(modifier, true); 121 | } 122 | return f; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/test/java/reader/ClassContainerReaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package reader; 19 | 20 | import static org.junit.Assert.assertEquals; 21 | 22 | import java.io.IOException; 23 | import java.util.Collections; 24 | 25 | import org.junit.Before; 26 | import org.junit.Test; 27 | 28 | import common.SymbolSolverSetup; 29 | import templateInput.ClassContainer; 30 | import templateInput.definition.ClassDefinition; 31 | 32 | /** 33 | * Unit test for the {@link ClassContainerReader}. 34 | * 35 | * @author Daan 36 | */ 37 | public class ClassContainerReaderTest { 38 | 39 | private ClassContainerReader sut = new ClassContainerReader(); 40 | 41 | @Before 42 | public void setup() { 43 | SymbolSolverSetup.setup(); 44 | } 45 | 46 | @Test 47 | public void testRead_Class() throws IOException { 48 | String input = "src/test/java/inputClassesForTests/ExtendedProduct.java"; 49 | ClassContainer cc = sut.read(input); 50 | ClassDefinition result = ClassDefinition.builder(cc).build(); 51 | 52 | ClassDefinition expected = ClassDefinition.builder().name("ExtendedProduct").type("ExtendedProduct").lineNumber(25).column(1) 53 | .accessModifiers(Collections.singleton("public")).extend("Product").interfaces(Collections.singletonList("TestInterface")).build(); 54 | 55 | assertEquals(expected, result); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/reader/MethodDefinitionFactoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package reader; 19 | 20 | import static org.junit.Assert.assertEquals; 21 | 22 | import java.io.IOException; 23 | import java.util.Collections; 24 | import java.util.List; 25 | 26 | import org.hamcrest.Matchers; 27 | import org.junit.Assert; 28 | import org.junit.Before; 29 | import org.junit.Test; 30 | import org.junit.runner.RunWith; 31 | import org.mockito.InjectMocks; 32 | import org.mockito.Mock; 33 | import org.mockito.Mockito; 34 | import org.mockito.runners.MockitoJUnitRunner; 35 | 36 | import com.github.javaparser.ast.Node; 37 | import com.github.javaparser.ast.body.MethodDeclaration; 38 | import com.github.javaparser.ast.body.VariableDeclarator; 39 | 40 | import common.SymbolSolverSetup; 41 | import dataflow.model.DataFlowGraph; 42 | import dataflow.model.DataFlowMethod; 43 | import templateInput.definition.MethodDefinition; 44 | import templateInput.definition.MethodDefinition.Builder; 45 | import templateInput.definition.VariableDefinition; 46 | 47 | /** 48 | * Unit test for {@link MethodDefinitionFactory}. 49 | * 50 | * @author Daan 51 | */ 52 | @RunWith(MockitoJUnitRunner.class) 53 | public class MethodDefinitionFactoryTest { 54 | 55 | @Mock 56 | private VariableDefintionFactory fieldFactory; 57 | @Mock 58 | private DataFlowGraph dfg; 59 | 60 | @InjectMocks 61 | private MethodDefinitionFactory methodFactory = new MethodDefinitionFactory(); 62 | 63 | private ClassContainerReader sut = new ClassContainerReader(); 64 | 65 | @Before 66 | public void setup() { 67 | SymbolSolverSetup.setup(); 68 | } 69 | 70 | @Test 71 | public void testAddChangedFields() { 72 | DataFlowGraph setterDfg = GraphBuilder.withStartingNodes(NodeBuilder.ofParameter("setS", "a").to("setS.s").to(NodeBuilder.ofField("s"))).build(); 73 | Node inputMethod = new MethodDeclaration(); 74 | DataFlowMethod methodDfn = setterDfg.getMethods().iterator().next(); 75 | Mockito.when(dfg.getMethod(inputMethod)).thenReturn(methodDfn); 76 | 77 | VariableDeclarator javaParserNode = new VariableDeclarator(); 78 | setterDfg.getFields().get(0).setRepresentedNode(javaParserNode); 79 | String name = "unique"; 80 | VariableDefinition fieldVariDef = VariableDefinition.builder().name(name).build(); 81 | Mockito.when(fieldFactory.createSingle(javaParserNode)).thenReturn(fieldVariDef); 82 | 83 | MethodDefinition method = methodFactory.createMethod(inputMethod, dfg); 84 | 85 | assertEquals(1, method.getChangedFields().size()); 86 | assertEquals(name, method.getChangedFields().get(0).getName().toString()); 87 | } 88 | 89 | @Test 90 | public void testRead_Methods() throws IOException { 91 | String input = "src/test/java/inputClassesForTests/Product.java"; 92 | List methods = sut.read(input).getMethods(); 93 | 94 | Builder build = MethodDefinition.builder().accessModifiers(Collections.singleton("public")).type("String"); 95 | MethodDefinition m1 = build.name("getUrl").lineNumber(46).column(3).build(); 96 | MethodDefinition m2 = build.name("getName").lineNumber(50).column(3).build(); 97 | MethodDefinition m3 = build.name("toString").lineNumber(54).column(3).annotations(Collections.singleton("Override")).build(); 98 | MethodDefinition m4 = build.name("hashCode").lineNumber(59).column(3).annotations(Collections.singleton("Override")).type("int").build(); 99 | MethodDefinition m5 = build.name("equals").lineNumber(64).column(3).annotations(Collections.singleton("Override")).type("boolean") 100 | .parameters(VariableDefinition.builder().type("Object").name("obj").build()).build(); 101 | 102 | Assert.assertThat(methods, Matchers.contains(m1, m2, m3, m4, m5)); 103 | } 104 | 105 | @Test 106 | public void testRead_Constructors() throws IOException { 107 | String input = "src/test/java/inputClassesForTests/Product.java"; 108 | List constructors = sut.read(input).getConstructors(); 109 | 110 | Builder build = MethodDefinition.builder().accessModifiers(Collections.singleton("public")).type("Product").name("Product").column(3) 111 | .typeImports("inputClassesForTests"); 112 | MethodDefinition m1 = build.lineNumber(36) 113 | .parameters(VariableDefinition.builder().type("String").name("name2").build(), VariableDefinition.builder().type("String").name("url").build()).build(); 114 | MethodDefinition m2 = build.lineNumber(42).parameters().build(); 115 | 116 | Assert.assertThat(constructors, Matchers.contains(m1, m2)); 117 | } 118 | 119 | @Test 120 | public void testAddMethodCallsCalls() { 121 | // TODO implement 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/test/java/reader/NodeBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package reader; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | import com.github.javaparser.ast.expr.SimpleName; 26 | 27 | import dataflow.model.DataFlowNode; 28 | 29 | /** 30 | * Builder for {@link DataFlowNode}, only to be used for test purposes. 31 | * 32 | * @author Daan 33 | * @deprecated This class can only build simple graphs, use the normal setters, constructors and builders of the JavaDataFlow classes. 34 | */ 35 | @Deprecated 36 | public class NodeBuilder { 37 | 38 | protected enum NodeType { 39 | IN_BETWEEN, 40 | METHOD_PARAMETER, 41 | CLASS_FIELD, 42 | RETURN 43 | } 44 | 45 | private String method; 46 | private String name; 47 | private List out = new ArrayList<>(); 48 | private final NodeType type; 49 | private List roots = new ArrayList<>(); 50 | private DataFlowNode build; 51 | 52 | public NodeBuilder(String name, NodeType type) { 53 | this.name = name; 54 | this.type = type; 55 | } 56 | 57 | /** 58 | * Create a {@link NodeBuilder} for given method and parameter. 59 | * 60 | * @param method Name of the method 61 | * @param name Name of the parameter 62 | * @return {@link NodeBuilder} 63 | */ 64 | public static NodeBuilder ofParameter(String method, String name) { 65 | NodeBuilder builder = new NodeBuilder(name, NodeType.METHOD_PARAMETER); 66 | builder.method = method; 67 | return builder; 68 | } 69 | 70 | public static NodeBuilder ofField(String name) { 71 | NodeBuilder builder = new NodeBuilder(name, NodeType.CLASS_FIELD); 72 | return builder; 73 | } 74 | 75 | public static NodeBuilder ofInBetween(String name) { 76 | NodeBuilder builder = new NodeBuilder(name, NodeType.IN_BETWEEN); 77 | return builder; 78 | } 79 | 80 | public static NodeBuilder ofReturn(String methodName, String line, String column) { 81 | NodeBuilder methodReturn = new NodeBuilder(methodName + "_return_" + line + "_" + column, NodeType.RETURN); 82 | methodReturn.method = methodName; 83 | return methodReturn; 84 | } 85 | 86 | public NodeBuilder to(String name) { 87 | NodeBuilder next = new NodeBuilder(name, NodeType.IN_BETWEEN); 88 | next.addRoots(this); 89 | out.add(next); 90 | return next; 91 | } 92 | 93 | public void to(String... names) { 94 | Arrays.stream(names).forEach(this::to); 95 | } 96 | 97 | public NodeBuilder to(NodeBuilder next) { 98 | out.add(next); 99 | // TODO don't think this is correct, it should be next.addRoots(this.roots) 100 | next.addRoots(this); 101 | return next; 102 | } 103 | 104 | public void to(NodeBuilder... names) { 105 | Arrays.stream(names).forEach(this::to); 106 | } 107 | 108 | private void addRoots(NodeBuilder root) { 109 | this.roots.addAll(root.getRoots()); 110 | } 111 | 112 | public List getRoots() { 113 | return this.roots.isEmpty() ? Collections.singletonList(this) : roots; 114 | } 115 | 116 | public NodeBuilder getRoot() { 117 | return this.roots.isEmpty() ? this : roots.get(0); 118 | } 119 | 120 | public String getMethod() { 121 | return method; 122 | } 123 | 124 | public void setMethod(String method) { 125 | this.method = method; 126 | } 127 | 128 | public String getName() { 129 | return name; 130 | } 131 | 132 | public void setName(String name) { 133 | this.name = name; 134 | } 135 | 136 | public List getOut() { 137 | return out; 138 | } 139 | 140 | public void setOut(List out) { 141 | this.out = out; 142 | } 143 | 144 | public NodeType getType() { 145 | return type; 146 | } 147 | 148 | public DataFlowNode build() { 149 | return DataFlowNode.builder().name(name).representedNode(new SimpleName(name)).build(); 150 | } 151 | 152 | public DataFlowNode getOrBuild() { 153 | if (build == null) { 154 | build = build(); 155 | } 156 | return build; 157 | } 158 | 159 | @Override 160 | public String toString() { 161 | return getName(); 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /src/test/java/reader/VariableDefintionFactoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package reader; 19 | 20 | import java.io.IOException; 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | import org.hamcrest.Matchers; 25 | import org.junit.Assert; 26 | import org.junit.Before; 27 | import org.junit.Test; 28 | 29 | import common.SymbolSolverSetup; 30 | import templateInput.definition.VariableDefinition; 31 | 32 | /** 33 | * Unit test for {@link VariableDefintionFactory}. 34 | * 35 | * @author Daan 36 | */ 37 | public class VariableDefintionFactoryTest { 38 | 39 | private ClassContainerReader sut = new ClassContainerReader(); 40 | 41 | @Before 42 | public void setup() { 43 | SymbolSolverSetup.setup(); 44 | } 45 | 46 | @Test 47 | public void testRead_Fields() throws IOException { 48 | String input = "src/test/java/inputClassesForTests/Product.java"; 49 | List variables = sut.read(input).getFields(); 50 | 51 | VariableDefinition v1 = 52 | VariableDefinition.builder().name("url").type("String").lineNumber(32).column(3).accessModifiers(Collections.singleton("private")).build(); 53 | VariableDefinition v2 = VariableDefinition.builder().name("name").type("String").lineNumber(33).column(3).accessModifiers(Collections.singleton("private")) 54 | .originalInit("\"interesting\"").build(); 55 | VariableDefinition v3 = VariableDefinition.builder().name("prod").type("Product").lineNumber(34).column(3).accessModifiers(Collections.singleton("public")) 56 | .typeImport("inputClassesForTests.Product").build(); 57 | 58 | Assert.assertThat(variables, Matchers.contains(v1, v2, v3)); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/templateInput/StringConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 by Eyefreight BV (www.eyefreight.com). All rights reserved. 3 | * 4 | * This software is provided by the copyright holder and contributors "as is" and any express or implied warranties, including, but 5 | * not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall 6 | * Eyefreight BV or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages 7 | * (including, but not limited to, procurement of substitute goods or services; * loss of use, data, or profits; or business 8 | * interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including 9 | * negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. 10 | */ 11 | package templateInput; 12 | 13 | import org.junit.Assert; 14 | import org.junit.Test; 15 | import org.junit.runner.RunWith; 16 | import org.mockito.runners.MockitoJUnitRunner; 17 | 18 | /** 19 | * Unit test for {@link StringConverter}. 20 | * 21 | * @author Daan 22 | */ 23 | @RunWith(MockitoJUnitRunner.class) 24 | public class StringConverterTest { 25 | 26 | @Test 27 | public void testGetLowerDash() { 28 | Assert.assertEquals("ab-cd", new StringConverter("AbCd").getLowerDash()); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/templateInput/definition/MethodDefinitionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */package templateInput.definition; 18 | 19 | import java.util.Collections; 20 | import java.util.List; 21 | 22 | import org.junit.Assert; 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.mockito.runners.MockitoJUnitRunner; 26 | 27 | /** 28 | * Unit test for {@link MethodDefinition}. 29 | * 30 | * @author Daan 31 | */ 32 | @RunWith(MockitoJUnitRunner.class) 33 | public class MethodDefinitionTest { 34 | private static final List PARAMETERS = Collections.singletonList(VariableDefinition.builder().build()); 35 | private static final List CHANGED_FIELDS = Collections.singletonList(FlowReceiverDefinition.builder().build()); 36 | private static final List INPUT_METHODS = Collections.singletonList(MethodDefinition.builder().build()); 37 | private static final List OUTPUT_METHODS = Collections.singletonList(MethodDefinition.builder().build()); 38 | private static final String METHOD_SIGNATURE = "a"; 39 | private static final String RETURN_SIGNATURE = "c"; 40 | 41 | @Test 42 | public void testMethodDefinition_minimum() { 43 | MethodDefinition methodDefinition = MethodDefinition.builder().build(); 44 | 45 | Assert.assertTrue("Unexpected parameters", methodDefinition.getParameters().isEmpty()); 46 | Assert.assertTrue("Unexpected changedFields", methodDefinition.getChangedFields().isEmpty()); 47 | Assert.assertTrue("Unexpected inputMethods", methodDefinition.getInputMethods().isEmpty()); 48 | Assert.assertTrue("Unexpected outputMethods", methodDefinition.getOutputMethods().isEmpty()); 49 | Assert.assertNull("Unexpected methodSignature", methodDefinition.getCallSignature()); 50 | Assert.assertNull("Unexpected returnSignature", methodDefinition.getReturnSignature()); 51 | } 52 | 53 | @Test 54 | public void testMethodDefinition_maximum() { 55 | MethodDefinition methodDefinition = createAndFillBuilder().build(); 56 | 57 | Assert.assertEquals("Unexpected parameters", PARAMETERS, methodDefinition.getParameters()); 58 | Assert.assertEquals("Unexpected changedFields", CHANGED_FIELDS, methodDefinition.getChangedFields()); 59 | Assert.assertEquals("Unexpected inputMethods", INPUT_METHODS, methodDefinition.getInputMethods()); 60 | Assert.assertEquals("Unexpected outputMethods", OUTPUT_METHODS, methodDefinition.getOutputMethods()); 61 | Assert.assertEquals("Unexpected methodSignature", METHOD_SIGNATURE, methodDefinition.getCallSignature()); 62 | Assert.assertEquals("Unexpected returnSignature", RETURN_SIGNATURE, methodDefinition.getReturnSignature()); 63 | } 64 | 65 | private MethodDefinition.Builder createAndFillBuilder() { 66 | return MethodDefinition.builder().parameters(PARAMETERS).changedFields(CHANGED_FIELDS).inputMethods(INPUT_METHODS).outputMethods(OUTPUT_METHODS) 67 | .callSignature(METHOD_SIGNATURE).returnSignature(RETURN_SIGNATURE); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/templateTests/DataFlowGraphTemplateIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package templateTests; 19 | 20 | import java.io.IOException; 21 | 22 | import org.junit.Test; 23 | 24 | import common.AbstractFileChangingTest; 25 | import configuration.DefaultConfigurations; 26 | import configuration.JavaForgerConfiguration; 27 | import dataflow.model.DataFlowGraph; 28 | import generator.JavaForger; 29 | 30 | /** 31 | * Integration test for templates that require a {@link DataFlowGraph} to be constructed, such as stateFullClassTest.javat 32 | * 33 | * @author Daan 34 | */ 35 | public class DataFlowGraphTemplateIntegrationTest extends AbstractFileChangingTest { 36 | 37 | private static final String EXPECTED_RESULTS_PATH = "src/test/resources/stateFullClassTest/"; 38 | 39 | @Test 40 | public void testStateFullClassTest_setter() throws IOException { 41 | String claz = // 42 | "public class Claz {\n" + // 43 | " private String s;\n" + // 44 | " public void setS(String a) {\n" + // 45 | " this.s = a;\n" + // 46 | " }\n" + // 47 | "}"; // 48 | 49 | String expectedClass = "verify-stateFullClassTest.java"; 50 | executeAndVerify(DefaultConfigurations.forStateFullClassTest(), claz, expectedClass); 51 | } 52 | 53 | @Test 54 | public void testStatelessClassTest_facade() throws IOException { 55 | String claz = // 56 | "public class Claz {\n" + // 57 | " StringBuilder sb = new StringBuilder(); \n" + // 58 | " StringBuilder sb1 = new StringBuilder(); \n" + // 59 | " public StringBuilder setS(String a) {\n" + // 60 | " return sb1.append(sb.indexOf(a));\n" + // 61 | " }\n" + // 62 | "}"; // 63 | 64 | String expectedClass = "verify-statelessClassTest-facade.java"; 65 | executeAndVerify(DefaultConfigurations.forStatelessClassTest(), claz, expectedClass); 66 | } 67 | 68 | @Test 69 | public void testStatelessClassTest_outputMethodCall() throws IOException { 70 | String claz = // 71 | "public class Claz {\n" + // 72 | " StringBuilder sb = new StringBuilder(); \n" + // 73 | " public void setS(String a) {\n" + // 74 | " sb.indexOf(a);\n" + // 75 | " }\n" + // 76 | "}"; // 77 | 78 | String expectedClass = "verify-statelessClassTest-outputMethodCall.java"; 79 | executeAndVerify(DefaultConfigurations.forStatelessClassTest(), claz, expectedClass); 80 | } 81 | 82 | private void executeAndVerify(JavaForgerConfiguration config, String claz, String expectedClass) throws IOException { 83 | stringToFile(INPUT_CLASS, claz); 84 | JavaForger.execute(config, INPUT_CLASS); 85 | verifyFileEqual(EXPECTED_RESULTS_PATH + expectedClass, INPUT_TEST_CLASS); 86 | } 87 | 88 | /** 89 | * VERY DANGEROUS MAIN METHOD, ONLY USE THIS WHEN YOU KNOW WHAT YOU'RE DOING. 90 | *

91 | * This main method will force the whole test to be green again, by replacing all verify files with the actual result. 92 | * 93 | * @param args 94 | * @throws IOException 95 | */ 96 | public static void main(String[] args) throws IOException { 97 | DataFlowGraphTemplateIntegrationTest test = new DataFlowGraphTemplateIntegrationTest() { 98 | @Override 99 | protected void verifyFileEqual(String expectedPath, String actualPath) throws IOException { 100 | System.out.println("Copying:\n" + actualPath + " to:\n" + expectedPath); 101 | super.copyClass(actualPath, expectedPath); 102 | } 103 | }; 104 | 105 | test.setup(); 106 | test.testStateFullClassTest_setter(); 107 | test.setup(); 108 | test.testStatelessClassTest_facade(); 109 | test.setup(); 110 | test.testStatelessClassTest_outputMethodCall(); 111 | test.tearDown(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/test/java/templateTests/TemplateIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package templateTests; 19 | 20 | import java.io.IOException; 21 | 22 | import org.junit.Assert; 23 | import org.junit.Test; 24 | 25 | import common.AbstractFileChangingTest; 26 | import configuration.DefaultConfigurations; 27 | import configuration.JavaForgerConfiguration; 28 | import generator.JavaForger; 29 | 30 | /** 31 | * Integration test testing the whole flow of inserting code into a class. If this test fails, comment out deleting the created file in the tearDown method. 32 | * Then go to the TEST_CLASS path to check what the actual result is of executing the failing test. Possibly copy the result to the ORIGINAL_CLASS to check for 33 | * compilation errors. 34 | *

35 | * This class is a bitch to maintain, with small changes in the application every verify file has to be updated. We made maintenance easier with the VERY 36 | * DANGEROUS main method that will make the whole test green again by replacing ALL verify files. USE WITH CARE AND TRIPLE CHECK GIT BEFORE COMMITTING. 37 | * 38 | * @author Daan 39 | */ 40 | public class TemplateIntegrationTest extends AbstractFileChangingTest { 41 | 42 | private static final String EXPECTED_RESULTS_PATH = "src/test/resources/templateTestOutcomes/"; 43 | 44 | @Test 45 | public void testInnerBuilder() throws IOException { 46 | String expectedClass = "verify-innerBuilder.java"; 47 | String expectedTestClass = "verify-innerBuilderTest.java"; 48 | executeAndVerify(DefaultConfigurations.forBuilderAndTest(), expectedClass, expectedTestClass); 49 | } 50 | 51 | @Test 52 | public void testExtendableInnerBuilder() throws IOException { 53 | String expectedClass = "verify-extendableInnerBuilder.java"; 54 | String expectedTestClass = "verify-innerBuilderTest.java"; 55 | executeAndVerify(DefaultConfigurations.forExtendableBuilderAndTest(), expectedClass, expectedTestClass); 56 | } 57 | 58 | @Test 59 | public void testEquals() throws IOException { 60 | String expectedClass = "verify-equals.java"; 61 | String expectedTestClass = "verify-equalsTest.java"; 62 | executeAndVerify(DefaultConfigurations.forEqualsAndTest(), expectedClass, expectedTestClass); 63 | } 64 | 65 | @Test 66 | public void testHashCode() throws IOException { 67 | String expectedClass = "verify-hashCode.java"; 68 | String expectedTestClass = "verify-hashCodeTest.java"; 69 | executeAndVerify(DefaultConfigurations.forHashCodeAndTest(), expectedClass, expectedTestClass); 70 | } 71 | 72 | @Test 73 | public void testToString() throws IOException { 74 | String expectedClass = "verify-toString.java"; 75 | executeAndVerify(DefaultConfigurations.forToString(), expectedClass); 76 | } 77 | 78 | private void executeAndVerify(JavaForgerConfiguration config, String expectedClass, String expectedTestClass) throws IOException { 79 | execute(config); 80 | verifyFileEqual(EXPECTED_RESULTS_PATH + expectedClass, INPUT_CLASS); 81 | verifyFileEqual(EXPECTED_RESULTS_PATH + expectedTestClass, INPUT_TEST_CLASS); 82 | } 83 | 84 | private void executeAndVerify(JavaForgerConfiguration config, String expectedClass) throws IOException { 85 | execute(config); 86 | verifyFileEqual(EXPECTED_RESULTS_PATH + expectedClass, INPUT_CLASS); 87 | } 88 | 89 | private void execute(JavaForgerConfiguration config) { 90 | JavaForger.execute(config, INPUT_CLASS); 91 | } 92 | 93 | /** 94 | * VERY DANGEROUS MAIN METHOD, ONLY USE THIS WHEN YOU KNOW WHAT YOU'RE DOING. 95 | *

96 | * This main method will force the whole test to be green again, by replacing all verify files with the actual result. 97 | * 98 | * @param args 99 | * @throws IOException 100 | */ 101 | public static void main(String[] args) throws IOException { 102 | 103 | // This statement prevents the main method from accidently being executed. 104 | // Assert.fail(); 105 | 106 | TemplateIntegrationTest test = new TemplateIntegrationTest() { 107 | @Override 108 | protected void verifyFileEqual(String expectedPath, String actualPath) throws IOException { 109 | System.out.println("Copying:\n" + actualPath + " to:\n" + expectedPath); 110 | super.copyClass(actualPath, expectedPath); 111 | } 112 | }; 113 | 114 | test.setup(); 115 | test.testEquals(); 116 | test.setup(); 117 | test.testHashCode(); 118 | test.setup(); 119 | test.testInnerBuilder(); 120 | test.setup(); 121 | test.testExtendableInnerBuilder(); 122 | test.setup(); 123 | test.testToString(); 124 | test.tearDown(); 125 | 126 | Assert.fail(); 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/test/resources/stateFullClassTest/verify-stateFullClassTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverythingTest { 28 | private Claz sut = new Claz(); 29 | @Test 30 | public void testSetS() { 31 | 32 | String a = "c"; 33 | 34 | // TODO currently only works for void methods 35 | sut.setS( 36 | a ); 37 | 38 | // TODO field has to be a new class FlowReceiverDefnition extends VariableDefinition 39 | Assert.assertEquals("Unexpected s", a, sut.getS()); 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/test/resources/stateFullClassTest/verify-statelessClassTest-facade.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | import org.mockito.InjectMocks; 22 | import org.mockito.Mock; 23 | import org.mockito.Mockito; 24 | 25 | /** 26 | * Input class for unit tests. 27 | * 28 | * @author Daan 29 | */ 30 | public class ClassWithEverythingTest { 31 | @Mock 32 | private StringBuilder sb; 33 | @Mock 34 | private StringBuilder sb1; 35 | @InjectMocks 36 | private Claz sut; 37 | @Test 38 | public void testSetS() { 39 | 40 | String a = "a"; 41 | 42 | 43 | StringBuilder nodeCall_indexOf_return = StringBuilder.builder().build(); 44 | Mockito.when(nodeCall_indexOf_return.indexOf(a)).thenReturn(nodeCall_indexOf_return); 45 | StringBuilder nodeCall_append_return = StringBuilder.builder().build(); 46 | Mockito.when(nodeCall_append_return.append(nodeCall_indexOf_return)).thenReturn(nodeCall_append_return); 47 | 48 | StringBuilder return_setS = sut.setS(a); 49 | 50 | Assert.assertEquals("Unexpected setS", nodeCall_append_return, return_setS); 51 | 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/test/resources/stateFullClassTest/verify-statelessClassTest-outputMethodCall.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | import org.mockito.InjectMocks; 22 | import org.mockito.Mock; 23 | import org.mockito.Mockito; 24 | 25 | /** 26 | * Input class for unit tests. 27 | * 28 | * @author Daan 29 | */ 30 | public class ClassWithEverythingTest { 31 | @Mock 32 | private StringBuilder sb; 33 | @InjectMocks 34 | private Claz sut; 35 | @Test 36 | public void testSetS() { 37 | 38 | String a = "a"; 39 | 40 | 41 | 42 | sut.setS(a); 43 | 44 | Mockito.verify(nodeCall_indexOf_return).indexOf(a); 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/CodeSnipitInserterTest/verify-inserted.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | this is the new Code 1 20 | 21 | import java.util.Set; 22 | 23 | /** 24 | * Input class for unit tests. 25 | * 26 | * @author Daan 27 | */ 28 | public class ClassWithEverything { 29 | 30 | public static final Boolean PUB_STAT_FIN = false; 31 | 32 | public Set prod; 33 | public int i = 0; 34 | protected ClassWithEverything c; 35 | private String s; 36 | 37 | public ClassWithEverything(int j) { 38 | this(); 39 | i = j; 40 | } 41 | 42 | private ClassWithEverything() { 43 | // Do nothing 44 | } 45 | 46 | public void method1() { 47 | method2(i, s); 48 | } 49 | 50 | private int method2(int j, String t2) { 51 | s = t2; 52 | return j + 1; 53 | } 54 | 55 | public class InnerClass { 56 | public double d = 0.3; 57 | private float f = 4.8F; 58 | 59 | public void method3() { 60 | method4(d, f); 61 | } 62 | 63 | private int method4(double e, float g) { 64 | d = e; 65 | return Float.floatToIntBits(g); 66 | } 67 | 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/CodeSnipitInserterTest/verify-nothingHappend.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | private String s; 35 | 36 | public ClassWithEverything(int j) { 37 | this(); 38 | i = j; 39 | } 40 | 41 | private ClassWithEverything() { 42 | // Do nothing 43 | } 44 | 45 | public void method1() { 46 | method2(i, s); 47 | } 48 | 49 | private int method2(int j, String t2) { 50 | s = t2; 51 | return j + 1; 52 | } 53 | 54 | public class InnerClass { 55 | public double d = 0.3; 56 | private float f = 4.8F; 57 | 58 | public void method3() { 59 | method4(d, f); 60 | } 61 | 62 | private int method4(double e, float g) { 63 | d = e; 64 | return Float.floatToIntBits(g); 65 | } 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/CodeSnipitInserterTest/verify-overriden.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | this is the new Code 1 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | private String s; 35 | 36 | public ClassWithEverything(int j) { 37 | this(); 38 | i = j; 39 | } 40 | 41 | private ClassWithEverything() { 42 | // Do nothing 43 | } 44 | 45 | public void method1() { 46 | method2(i, s); 47 | } 48 | 49 | private int method2(int j, String t2) { 50 | s = t2; 51 | return j + 1; 52 | } 53 | 54 | public class InnerClass { 55 | public double d = 0.3; 56 | private float f = 4.8F; 57 | 58 | public void method3() { 59 | method4(d, f); 60 | } 61 | 62 | private int method4(double e, float g) { 63 | d = e; 64 | return Float.floatToIntBits(g); 65 | } 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/LineMergerTest/verify-addInnerClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | private String s; 35 | 36 | public ClassWithEverything(int j) { 37 | this(); 38 | i = j; 39 | } 40 | 41 | private ClassWithEverything() { 42 | // Do nothing 43 | } 44 | 45 | public void method1() { 46 | method2(i, s); 47 | } 48 | 49 | private int method2(int j, String t2) { 50 | s = t2; 51 | return j + 1; 52 | } 53 | 54 | public class InnerClass { 55 | public double d = 0.3; 56 | private float f = 4.8F; 57 | 58 | public void method3() { 59 | method4(d, f); 60 | } 61 | 62 | private int method4(double e, float g) { 63 | d = e; 64 | return Float.floatToIntBits(g); 65 | } 66 | 67 | } 68 | class AddedInnerClass { 69 | protected newMethod() { 70 | // Do Nothing 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/LineMergerTest/verify-constructor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | private String s; 35 | 36 | private ClassWithEverything(int i) { 37 | this.i = i; 38 | } 39 | 40 | private ClassWithEverything() { 41 | // Do nothing 42 | } 43 | 44 | public void method1() { 45 | method2(i, s); 46 | } 47 | 48 | private int method2(int j, String t2) { 49 | s = t2; 50 | return j + 1; 51 | } 52 | 53 | public class InnerClass { 54 | public double d = 0.3; 55 | private float f = 4.8F; 56 | 57 | public void method3() { 58 | method4(d, f); 59 | } 60 | 61 | private int method4(double e, float g) { 62 | d = e; 63 | return Float.floatToIntBits(g); 64 | } 65 | 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/LineMergerTest/verify-field.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | protected String prettyString = "very pretty"; 35 | private String s; 36 | 37 | public ClassWithEverything(int j) { 38 | this(); 39 | i = j; 40 | } 41 | 42 | private ClassWithEverything() { 43 | // Do nothing 44 | } 45 | 46 | public void method1() { 47 | method2(i, s); 48 | } 49 | 50 | private int method2(int j, String t2) { 51 | s = t2; 52 | return j + 1; 53 | } 54 | 55 | public class InnerClass { 56 | public double d = 0.3; 57 | private float f = 4.8F; 58 | 59 | public void method3() { 60 | method4(d, f); 61 | } 62 | 63 | private int method4(double e, float g) { 64 | d = e; 65 | return Float.floatToIntBits(g); 66 | } 67 | 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/LineMergerTest/verify-import.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | import my.impord; 22 | 23 | /** 24 | * Input class for unit tests. 25 | * 26 | * @author Daan 27 | */ 28 | public class ClassWithEverything { 29 | 30 | public static final Boolean PUB_STAT_FIN = false; 31 | 32 | public Set prod; 33 | public int i = 0; 34 | protected ClassWithEverything c; 35 | private String s; 36 | 37 | public ClassWithEverything(int j) { 38 | this(); 39 | i = j; 40 | } 41 | 42 | private ClassWithEverything() { 43 | // Do nothing 44 | } 45 | 46 | public void method1() { 47 | method2(i, s); 48 | } 49 | 50 | private int method2(int j, String t2) { 51 | s = t2; 52 | return j + 1; 53 | } 54 | 55 | public class InnerClass { 56 | public double d = 0.3; 57 | private float f = 4.8F; 58 | 59 | public void method3() { 60 | method4(d, f); 61 | } 62 | 63 | private int method4(double e, float g) { 64 | d = e; 65 | return Float.floatToIntBits(g); 66 | } 67 | 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/LineMergerTest/verify-mergeInnerClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | private String s; 35 | 36 | public ClassWithEverything(int j) { 37 | this(); 38 | i = j; 39 | } 40 | 41 | private ClassWithEverything() { 42 | // Do nothing 43 | } 44 | 45 | public void method1() { 46 | method2(i, s); 47 | } 48 | 49 | private int method2(int j, String t2) { 50 | s = t2; 51 | return j + 1; 52 | } 53 | 54 | public class InnerClass { 55 | public double d = 0.3; 56 | private float f = 4.8F; 57 | 58 | public void method3() { 59 | method4(d, f); 60 | } 61 | protected void methodBetween3and4() { 62 | // Do Nothing 63 | } 64 | 65 | private int method4(double e, float g) { 66 | d = e; 67 | return Float.floatToIntBits(g); 68 | } 69 | 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/LineMergerTest/verify-package.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package my.packingedinges; 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | private String s; 35 | 36 | public ClassWithEverything(int j) { 37 | this(); 38 | i = j; 39 | } 40 | 41 | private ClassWithEverything() { 42 | // Do nothing 43 | } 44 | 45 | public void method1() { 46 | method2(i, s); 47 | } 48 | 49 | private int method2(int j, String t2) { 50 | s = t2; 51 | return j + 1; 52 | } 53 | 54 | public class InnerClass { 55 | public double d = 0.3; 56 | private float f = 4.8F; 57 | 58 | public void method3() { 59 | method4(d, f); 60 | } 61 | 62 | private int method4(double e, float g) { 63 | d = e; 64 | return Float.floatToIntBits(g); 65 | } 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/verify-equals.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | import org.apache.commons.lang3.builder.EqualsBuilder; 22 | 23 | /** 24 | * Input class for unit tests. 25 | * 26 | * @author Daan 27 | */ 28 | public class ClassWithEverything { 29 | 30 | public static final Boolean PUB_STAT_FIN = false; 31 | 32 | public Set prod; 33 | public int i = 0; 34 | protected ClassWithEverything c; 35 | private String s; 36 | 37 | public ClassWithEverything(int j) { 38 | this(); 39 | i = j; 40 | } 41 | 42 | private ClassWithEverything() { 43 | // Do nothing 44 | } 45 | 46 | public void method1() { 47 | method2(i, s); 48 | } 49 | @Override 50 | public boolean equals(Object obj) { 51 | boolean equals = false; 52 | if (this == obj) { 53 | equals = true; 54 | } else if (obj != null && getClass() == obj.getClass()) { 55 | ClassWithEverything other = (ClassWithEverything) obj; 56 | equals = new EqualsBuilder() 57 | .append(prod, other.prod) 58 | .append(i, other.i) 59 | .append(c, other.c) 60 | .append(s, other.s) 61 | .isEquals(); 62 | } 63 | return equals; 64 | } 65 | 66 | private int method2(int j, String t2) { 67 | s = t2; 68 | return j + 1; 69 | } 70 | 71 | public class InnerClass { 72 | public double d = 0.3; 73 | private float f = 4.8F; 74 | 75 | public void method3() { 76 | method4(d, f); 77 | } 78 | 79 | private int method4(double e, float g) { 80 | d = e; 81 | return Float.floatToIntBits(g); 82 | } 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/verify-equalsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | import java.util.function.BiFunction; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | import inputClassesForTests.Product; 23 | import java.util.Set; 24 | import java.util.Collections; 25 | import inputClassesForTests.ClassWithEverything; 26 | 27 | /** 28 | * Input class for unit tests. 29 | * 30 | * @author Daan 31 | */ 32 | public class ClassWithEverythingTest { 33 | private static final Set PROD = Collections.singleton(Product.builder().build()); 34 | private static final int I = 1; 35 | private static final ClassWithEverything C = ClassWithEverything.builder().build(); 36 | private static final String S = "a"; 37 | @Test 38 | public void testEquals_Same() { 39 | ClassWithEverything.Builder builder = createAndFillBuilder(); 40 | ClassWithEverything a = builder.build(); 41 | ClassWithEverything b = builder.build(); 42 | Assert.assertTrue("Expected a and b to be equal", a.equals(b)); 43 | } 44 | @Test 45 | public void testEquals_Different() { 46 | verifyEqualsDifferent(ClassWithEverything.Builder::prod, Collections.singleton(Product.builder().build())); 47 | verifyEqualsDifferent(ClassWithEverything.Builder::i, 2); 48 | verifyEqualsDifferent(ClassWithEverything.Builder::c, ClassWithEverything.builder().build()); 49 | verifyEqualsDifferent(ClassWithEverything.Builder::s, "b"); 50 | } 51 | private void verifyEqualsDifferent(BiFunction withMapper, T argument) { 52 | ClassWithEverything.Builder builder = createAndFillBuilder(); 53 | ClassWithEverything a = builder.build(); 54 | ClassWithEverything b = withMapper.apply(builder, argument).build(); 55 | Assert.assertFalse("Expected a and b not to be equal", a.equals(b)); 56 | } 57 | private ClassWithEverything.Builder createAndFillBuilder() { 58 | return ClassWithEverything.builder() 59 | .prod(PROD) 60 | .i(I) 61 | .c(C) 62 | .s(S) 63 | ; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/verify-extendableInnerBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | private String s; 35 | 36 | public ClassWithEverything(int j) { 37 | this(); 38 | i = j; 39 | } 40 | protected ClassWithEverything(ClassWithEverything.Builder builder) { 41 | this.prod = builder.prod == null ? this.prod : builder.prod; 42 | this.i = builder.i == null ? this.i : builder.i; 43 | this.c = builder.c == null ? this.c : builder.c; 44 | this.s = builder.s == null ? this.s : builder.s; 45 | } 46 | 47 | private ClassWithEverything() { 48 | // Do nothing 49 | } 50 | 51 | public void method1() { 52 | method2(i, s); 53 | } 54 | 55 | /** 56 | * Creates builder to build {@link ClassWithEverything}. 57 | * @return created builder 58 | */ 59 | public static Builder builder() { 60 | return new Builder(); 61 | } 62 | 63 | private int method2(int j, String t2) { 64 | s = t2; 65 | return j + 1; 66 | } 67 | 68 | public class InnerClass { 69 | public double d = 0.3; 70 | private float f = 4.8F; 71 | 72 | public void method3() { 73 | method4(d, f); 74 | } 75 | 76 | private int method4(double e, float g) { 77 | d = e; 78 | return Float.floatToIntBits(g); 79 | } 80 | 81 | } 82 | /** 83 | * Builder to build {@link ClassWithEverything}. 84 | */ 85 | @SuppressWarnings("unchecked") 86 | public static class Builder> { 87 | private Set prod = new HashSet<>(); 88 | private Integer i; 89 | private ClassWithEverything c; 90 | private String s; 91 | 92 | protected Builder() { 93 | // Builder should only be used via the parent class or extending builder 94 | } 95 | 96 | public T prod(Set prod) { 97 | this.prod.clear(); 98 | this.prod.addAll(prod); 99 | return (T) this; 100 | } 101 | 102 | public T i(Integer i) { 103 | this.i = i; 104 | return (T) this; 105 | } 106 | 107 | public T c(ClassWithEverything c) { 108 | this.c = c; 109 | return (T) this; 110 | } 111 | 112 | public T s(String s) { 113 | this.s = s; 114 | return (T) this; 115 | } 116 | 117 | 118 | public
ClassWithEverything build() { 119 | return new ClassWithEverything(this); 120 | } 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/verify-hashCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | import java.util.Objects; 22 | 23 | /** 24 | * Input class for unit tests. 25 | * 26 | * @author Daan 27 | */ 28 | public class ClassWithEverything { 29 | 30 | public static final Boolean PUB_STAT_FIN = false; 31 | 32 | public Set prod; 33 | public int i = 0; 34 | protected ClassWithEverything c; 35 | private String s; 36 | 37 | public ClassWithEverything(int j) { 38 | this(); 39 | i = j; 40 | } 41 | 42 | private ClassWithEverything() { 43 | // Do nothing 44 | } 45 | 46 | public void method1() { 47 | method2(i, s); 48 | } 49 | @Override 50 | public int hashCode() { 51 | return Objects.hash( 52 | prod 53 | , 54 | i 55 | , 56 | c 57 | , 58 | s 59 | 60 | ); 61 | } 62 | 63 | private int method2(int j, String t2) { 64 | s = t2; 65 | return j + 1; 66 | } 67 | 68 | public class InnerClass { 69 | public double d = 0.3; 70 | private float f = 4.8F; 71 | 72 | public void method3() { 73 | method4(d, f); 74 | } 75 | 76 | private int method4(double e, float g) { 77 | d = e; 78 | return Float.floatToIntBits(g); 79 | } 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/verify-hashCodeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | import java.util.function.BiFunction; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | import inputClassesForTests.Product; 23 | import java.util.Set; 24 | import java.util.Collections; 25 | import inputClassesForTests.ClassWithEverything; 26 | 27 | /** 28 | * Input class for unit tests. 29 | * 30 | * @author Daan 31 | */ 32 | public class ClassWithEverythingTest { 33 | private static final Set PROD = Collections.singleton(Product.builder().build()); 34 | private static final int I = 1; 35 | private static final ClassWithEverything C = ClassWithEverything.builder().build(); 36 | private static final String S = "a"; 37 | @Test 38 | public void testHashCode_Same() { 39 | ClassWithEverything.Builder builder = createAndFillBuilder(); 40 | ClassWithEverything a = builder.build(); 41 | ClassWithEverything b = builder.build(); 42 | Assert.assertEquals("Expected hash code to be the same", a.hashCode(), b.hashCode()); 43 | } 44 | @Test 45 | public void testHashCode_Different() { 46 | verifyHashCode_Different(ClassWithEverything.Builder::prod, Collections.singleton(Product.builder().build())); 47 | verifyHashCode_Different(ClassWithEverything.Builder::i, 2); 48 | verifyHashCode_Different(ClassWithEverything.Builder::c, ClassWithEverything.builder().build()); 49 | verifyHashCode_Different(ClassWithEverything.Builder::s, "b"); 50 | } 51 | private void verifyHashCode_Different(BiFunction withMapper, T argument) { 52 | ClassWithEverything.Builder builder = createAndFillBuilder(); 53 | ClassWithEverything a = builder.build(); 54 | ClassWithEverything b = withMapper.apply(builder, argument).build(); 55 | Assert.assertNotEquals("Expected hash code to be different", a.hashCode(), b.hashCode()); 56 | } 57 | private ClassWithEverything.Builder createAndFillBuilder() { 58 | return ClassWithEverything.builder() 59 | .prod(PROD) 60 | .i(I) 61 | .c(C) 62 | .s(S) 63 | ; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/verify-innerBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | 22 | /** 23 | * Input class for unit tests. 24 | * 25 | * @author Daan 26 | */ 27 | public class ClassWithEverything { 28 | 29 | public static final Boolean PUB_STAT_FIN = false; 30 | 31 | public Set prod; 32 | public int i = 0; 33 | protected ClassWithEverything c; 34 | private String s; 35 | 36 | public ClassWithEverything(int j) { 37 | this(); 38 | i = j; 39 | } 40 | 41 | private ClassWithEverything() { 42 | // Do nothing 43 | } 44 | private ClassWithEverything(Builder builder) { 45 | this.prod = builder.prod == null ? this.prod : builder.prod; 46 | this.i = builder.i == null ? this.i : builder.i; 47 | this.c = builder.c == null ? this.c : builder.c; 48 | this.s = builder.s == null ? this.s : builder.s; 49 | } 50 | 51 | public void method1() { 52 | method2(i, s); 53 | } 54 | 55 | /** 56 | * Creates builder to build {@link ClassWithEverything}. 57 | * @return created builder 58 | */ 59 | public static Builder builder() { 60 | return new Builder(); 61 | } 62 | 63 | private int method2(int j, String t2) { 64 | s = t2; 65 | return j + 1; 66 | } 67 | 68 | public class InnerClass { 69 | public double d = 0.3; 70 | private float f = 4.8F; 71 | 72 | public void method3() { 73 | method4(d, f); 74 | } 75 | 76 | private int method4(double e, float g) { 77 | d = e; 78 | return Float.floatToIntBits(g); 79 | } 80 | 81 | } 82 | /** 83 | * Builder to build {@link ClassWithEverything}. 84 | */ 85 | public static final class Builder { 86 | private Set prod = new HashSet<>(); 87 | private Integer i; 88 | private ClassWithEverything c; 89 | private String s; 90 | 91 | private Builder() { 92 | // Builder should only be constructed via the parent class 93 | } 94 | 95 | public Builder copy(ClassWithEverything original) { 96 | this.prod.clear(); 97 | this.prod.addAll(original.getProd()); 98 | this.i = original.getI(); 99 | this.c = original.getC(); 100 | this.s = original.getS(); 101 | return this; 102 | } 103 | 104 | public Builder prod(Set prod) { 105 | this.prod.clear(); 106 | this.prod.addAll(prod); 107 | return this; 108 | } 109 | 110 | public Builder i(Integer i) { 111 | this.i = i; 112 | return this; 113 | } 114 | 115 | public Builder c(ClassWithEverything c) { 116 | this.c = c; 117 | return this; 118 | } 119 | 120 | public Builder s(String s) { 121 | this.s = s; 122 | return this; 123 | } 124 | 125 | 126 | public ClassWithEverything build() { 127 | return new ClassWithEverything(this); 128 | } 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/verify-innerBuilderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | import inputClassesForTests.Product; 22 | import java.util.Set; 23 | import java.util.Collections; 24 | import inputClassesForTests.ClassWithEverything; 25 | 26 | /** 27 | * Input class for unit tests. 28 | * 29 | * @author Daan 30 | */ 31 | public class ClassWithEverythingTest { 32 | private static final Set PROD = Collections.singleton(Product.builder().build()); 33 | private static final int I = 1; 34 | private static final ClassWithEverything C = ClassWithEverything.builder().build(); 35 | private static final String S = "a"; 36 | @Test 37 | public void testClassWithEverything_minimum() { 38 | ClassWithEverything classWithEverything = ClassWithEverything.builder().build(); 39 | 40 | Assert.assertTrue("Unexpected prod", classWithEverything.getProd().isEmpty()); 41 | Assert.assertEquals("Unexpected i", 0, classWithEverything.getI()); 42 | Assert.assertNull("Unexpected c", classWithEverything.getC()); 43 | Assert.assertNull("Unexpected s", classWithEverything.getS()); 44 | } 45 | @Test 46 | public void testClassWithEverything_maximum() { 47 | ClassWithEverything classWithEverything = createAndFillBuilder().build(); 48 | assertMaximum(classWithEverything); 49 | } 50 | @Test 51 | public void testClassWithEverything_Copy() { 52 | ClassWithEverything classWithEverything = ClassWithEverything.builder().copy(createAndFillBuilder().build()).build(); 53 | assertMaximum(classWithEverything); 54 | } 55 | private void assertMaximum(ClassWithEverything classWithEverything) { 56 | Assert.assertEquals("Unexpected prod", PROD, classWithEverything.getProd()); 57 | Assert.assertEquals("Unexpected i", I, classWithEverything.getI()); 58 | Assert.assertEquals("Unexpected c", C, classWithEverything.getC()); 59 | Assert.assertEquals("Unexpected s", S, classWithEverything.getS()); 60 | } 61 | private ClassWithEverything.Builder createAndFillBuilder() { 62 | return ClassWithEverything.builder() 63 | .prod(PROD) 64 | .i(I) 65 | .c(C) 66 | .s(S) 67 | ; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/test/resources/templateTestOutcomes/verify-toString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Daan van den Heuvel. 3 | * 4 | * This file is part of JavaForger. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package inputClassesForTests; 19 | 20 | import java.util.Set; 21 | import org.apache.commons.lang3.builder.ToStringBuilder; 22 | import org.apache.commons.lang3.builder.ToStringStyle; 23 | 24 | /** 25 | * Input class for unit tests. 26 | * 27 | * @author Daan 28 | */ 29 | public class ClassWithEverything { 30 | 31 | public static final Boolean PUB_STAT_FIN = false; 32 | 33 | public Set prod; 34 | public int i = 0; 35 | protected ClassWithEverything c; 36 | private String s; 37 | 38 | public ClassWithEverything(int j) { 39 | this(); 40 | i = j; 41 | } 42 | 43 | private ClassWithEverything() { 44 | // Do nothing 45 | } 46 | 47 | public void method1() { 48 | method2(i, s); 49 | } 50 | @Override 51 | public String toString() { 52 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 53 | .append("prod", prod) 54 | .append("i", i) 55 | .append("c", c) 56 | .append("s", s) 57 | .build(); 58 | } 59 | 60 | private int method2(int j, String t2) { 61 | s = t2; 62 | return j + 1; 63 | } 64 | 65 | public class InnerClass { 66 | public double d = 0.3; 67 | private float f = 4.8F; 68 | 69 | public void method3() { 70 | method4(d, f); 71 | } 72 | 73 | private int method4(double e, float g) { 74 | d = e; 75 | return Float.floatToIntBits(g); 76 | } 77 | 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/test/resources/templates/classFields.ftlh: -------------------------------------------------------------------------------- 1 | The input class has the following fields: 2 | <#list fields as field> 3 | ${field.type} ${field.name} 4 | -------------------------------------------------------------------------------- /src/test/resources/templates/condition.ftlh: -------------------------------------------------------------------------------- 1 | Welcome ${user}, <#if user == "Big Joe">our beloved leader<#else>minion of Big Joe! -------------------------------------------------------------------------------- /src/test/resources/templates/include.ftlh: -------------------------------------------------------------------------------- 1 | We can also include stuff: 2 | <#include "/object.ftlh"> -------------------------------------------------------------------------------- /src/test/resources/templates/object.ftlh: -------------------------------------------------------------------------------- 1 | The product with 2 properties: name=${prod.name}, url=${prod.url} -------------------------------------------------------------------------------- /src/test/resources/templates/sequence.ftlh: -------------------------------------------------------------------------------- 1 | We hebben deze dieren: 2 | <#list products as prod> 3 | Een ${prod.name} kan ${prod.url}. 4 | -------------------------------------------------------------------------------- /src/test/resources/templates/simple.ftlh: -------------------------------------------------------------------------------- 1 | <#-- This is a comment and will not be shown --> 2 | This is a simple test template. --------------------------------------------------------------------------------