├── project ├── build.properties └── assembly.sbt ├── screenshots ├── Capture.PNG ├── DePaCoG.png ├── Capture2.PNG ├── Capture3.PNG ├── Capture4.PNG └── laptopFactory.png ├── target └── scala-2.13 │ └── hw1-assembly-0.1.jar ├── outputs └── com │ ├── laptopAbstractFactory │ ├── AMD.java │ ├── Intel.java │ ├── OS.java │ ├── Processor.java │ ├── OperatingSystem.java │ ├── ChromeOS.java │ ├── Ubuntu.java │ ├── LaptopFactory.java │ └── ChromeBookFactory.java │ ├── usbAdapter │ ├── TypeC.java │ ├── MicroUSB.java │ └── USBDongle.java │ ├── coffeeDecorator │ ├── Beverage.java │ ├── Coffee.java │ ├── CondimentDecorator.java │ ├── Milk.java │ └── WhipCream.java │ └── weatherObserver │ ├── SmartPhone.java │ ├── DarkSkyServer.java │ ├── AndroidPhone.java │ └── WeatherServiceServer.java ├── src ├── main │ ├── resources │ │ ├── logback.xml │ │ └── default.conf │ └── java │ │ └── com │ │ ├── DesignPatternGenerator.java │ │ ├── DePaCoG.java │ │ ├── creational │ │ ├── Singleton.java │ │ ├── Prototype.java │ │ ├── FactoryMethod.java │ │ ├── AbstractFactory.java │ │ └── Builder.java │ │ ├── structural │ │ ├── Adapter.java │ │ ├── Proxy.java │ │ ├── Composite.java │ │ ├── Bridge.java │ │ ├── Decorator.java │ │ └── Flyweight.java │ │ ├── behavioral │ │ ├── TemplateMethod.java │ │ ├── State.java │ │ ├── ChainOfResponsibility.java │ │ ├── Memento.java │ │ ├── Command.java │ │ ├── Strategy.java │ │ ├── Observer.java │ │ ├── Iterator.java │ │ ├── Mediator.java │ │ ├── Interpreter.java │ │ └── Visitor.java │ │ ├── Hw1DesignPatternGenerator.java │ │ └── DesignPattern.java └── test │ └── java │ └── com │ ├── DesignPatternTest.java │ └── Hw1DesignPatternGeneratorTest.java ├── LICENSE ├── .gitignore └── README.md /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version = 1.3.8 -------------------------------------------------------------------------------- /project/assembly.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10") -------------------------------------------------------------------------------- /screenshots/Capture.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samujjwaal/Design-Pattern-Code-Generator/HEAD/screenshots/Capture.PNG -------------------------------------------------------------------------------- /screenshots/DePaCoG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samujjwaal/Design-Pattern-Code-Generator/HEAD/screenshots/DePaCoG.png -------------------------------------------------------------------------------- /screenshots/Capture2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samujjwaal/Design-Pattern-Code-Generator/HEAD/screenshots/Capture2.PNG -------------------------------------------------------------------------------- /screenshots/Capture3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samujjwaal/Design-Pattern-Code-Generator/HEAD/screenshots/Capture3.PNG -------------------------------------------------------------------------------- /screenshots/Capture4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samujjwaal/Design-Pattern-Code-Generator/HEAD/screenshots/Capture4.PNG -------------------------------------------------------------------------------- /screenshots/laptopFactory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samujjwaal/Design-Pattern-Code-Generator/HEAD/screenshots/laptopFactory.png -------------------------------------------------------------------------------- /target/scala-2.13/hw1-assembly-0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samujjwaal/Design-Pattern-Code-Generator/HEAD/target/scala-2.13/hw1-assembly-0.1.jar -------------------------------------------------------------------------------- /outputs/com/laptopAbstractFactory/AMD.java: -------------------------------------------------------------------------------- 1 | package com.laptopAbstractFactory; 2 | 3 | /** 4 | * ProductA2, implements AbstractProductA interface 5 | */ 6 | public class AMD implements Processor { 7 | } 8 | -------------------------------------------------------------------------------- /outputs/com/laptopAbstractFactory/Intel.java: -------------------------------------------------------------------------------- 1 | package com.laptopAbstractFactory; 2 | 3 | /** 4 | * ProductA1, implements AbstractProductA interface 5 | */ 6 | public class Intel implements Processor { 7 | } 8 | -------------------------------------------------------------------------------- /outputs/com/laptopAbstractFactory/OS.java: -------------------------------------------------------------------------------- 1 | package com.laptopAbstractFactory; 2 | 3 | /** 4 | * ProductB1, implements AbstractProductB interface 5 | */ 6 | public class OS implements OperatingSystem { 7 | } 8 | -------------------------------------------------------------------------------- /outputs/com/laptopAbstractFactory/Processor.java: -------------------------------------------------------------------------------- 1 | package com.laptopAbstractFactory; 2 | 3 | /** 4 | * AbstractProductA defines interface for ProductA objects 5 | */ 6 | public interface Processor { 7 | } 8 | -------------------------------------------------------------------------------- /outputs/com/laptopAbstractFactory/OperatingSystem.java: -------------------------------------------------------------------------------- 1 | package com.laptopAbstractFactory; 2 | 3 | /** 4 | * AbstractProductB defines interface for ProductB objects 5 | */ 6 | public interface OperatingSystem { 7 | } 8 | -------------------------------------------------------------------------------- /outputs/com/laptopAbstractFactory/ChromeOS.java: -------------------------------------------------------------------------------- 1 | package com.laptopAbstractFactory; 2 | 3 | /** 4 | * ProductB1, implements AbstractProductB interface 5 | */ 6 | public class ChromeOS implements OperatingSystem { 7 | } 8 | -------------------------------------------------------------------------------- /outputs/com/usbAdapter/TypeC.java: -------------------------------------------------------------------------------- 1 | package com.usbAdapter; 2 | 3 | /** 4 | * Target interface, defines domain-specific interface to which Adaptee will be adapted 5 | */ 6 | public interface TypeC { 7 | String request(); 8 | } 9 | -------------------------------------------------------------------------------- /outputs/com/coffeeDecorator/Beverage.java: -------------------------------------------------------------------------------- 1 | package com.coffeeDecorator; 2 | 3 | /** 4 | * Component, defines interface for new features which will be added dynamically 5 | */ 6 | public interface Beverage { 7 | void operation(); 8 | } 9 | -------------------------------------------------------------------------------- /outputs/com/coffeeDecorator/Coffee.java: -------------------------------------------------------------------------------- 1 | package com.coffeeDecorator; 2 | 3 | /** 4 | * ConcreteComponent, define object where new features can be added 5 | */ 6 | public class Coffee implements Beverage { 7 | public void operation() { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /outputs/com/usbAdapter/MicroUSB.java: -------------------------------------------------------------------------------- 1 | package com.usbAdapter; 2 | 3 | /** 4 | * Adaptee class, interface which will be adapted 5 | */ 6 | public class MicroUSB { 7 | public String specialRequest() { 8 | return "specialRequest"; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /outputs/com/weatherObserver/SmartPhone.java: -------------------------------------------------------------------------------- 1 | package com.weatherObserver; 2 | 3 | /** 4 | * Observer defines an updating interface for objects that should be notified of changes in a subject. 5 | */ 6 | public interface SmartPhone { 7 | void update(); 8 | } 9 | -------------------------------------------------------------------------------- /outputs/com/laptopAbstractFactory/Ubuntu.java: -------------------------------------------------------------------------------- 1 | package com.laptopAbstractFactory; 2 | 3 | /** 4 | * Abstract Factory, defines interface for creation of the abstract product objects 5 | */ 6 | public interface Ubuntu { 7 | Processor createProcessor(); 8 | 9 | OperatingSystem createOperatingSystem(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /outputs/com/coffeeDecorator/CondimentDecorator.java: -------------------------------------------------------------------------------- 1 | package com.coffeeDecorator; 2 | 3 | /** 4 | * Decorator, keep reference to Component object 5 | */ 6 | abstract class CondimentDecorator implements Beverage { 7 | protected Beverage component; 8 | 9 | public abstract void operation(); 10 | 11 | public void setComponent(Beverage component) { 12 | this.component = component; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /outputs/com/coffeeDecorator/Milk.java: -------------------------------------------------------------------------------- 1 | package com.coffeeDecorator; 2 | 3 | /** 4 | * ConcreteDecoratorA, add features to component 5 | */ 6 | public class Milk extends CondimentDecorator { 7 | private boolean state; 8 | 9 | public void operation() { 10 | state = true; 11 | this.component.operation(); 12 | } 13 | 14 | public boolean isState() { 15 | return state; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /outputs/com/usbAdapter/USBDongle.java: -------------------------------------------------------------------------------- 1 | package com.usbAdapter; 2 | 3 | /** 4 | * Adapter class, adapts Adaptee to the Target interface 5 | */ 6 | public class USBDongle implements TypeC { 7 | private MicroUSB adaptee; 8 | 9 | public USBDongle(MicroUSB adaptee) { 10 | this.adaptee = adaptee; 11 | } 12 | 13 | public String request() { 14 | return adaptee.specialRequest(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /outputs/com/laptopAbstractFactory/LaptopFactory.java: -------------------------------------------------------------------------------- 1 | package com.laptopAbstractFactory; 2 | 3 | /** 4 | * ConcreteFactory1, implements creation of the concrete Product1 objects 5 | */ 6 | public class LaptopFactory implements Ubuntu { 7 | public Processor createProcessor() { 8 | return new Intel(); 9 | } 10 | 11 | public OperatingSystem createOperatingSystem() { 12 | return new OS(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /outputs/com/laptopAbstractFactory/ChromeBookFactory.java: -------------------------------------------------------------------------------- 1 | package com.laptopAbstractFactory; 2 | 3 | /** 4 | * ConcreteFactory2, implements creation of the concrete Product2 objects 5 | */ 6 | public class ChromeBookFactory implements Ubuntu { 7 | public Processor createProcessor() { 8 | return new AMD(); 9 | } 10 | 11 | public OperatingSystem createOperatingSystem() { 12 | return new ChromeOS(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /outputs/com/weatherObserver/DarkSkyServer.java: -------------------------------------------------------------------------------- 1 | package com.weatherObserver; 2 | 3 | /** 4 | * ConcreteSubject stores state of interest to ConcreteObserver objects, sends a notification to its observers 5 | * when its state changes. 6 | */ 7 | public class DarkSkyServer extends WeatherServiceServer { 8 | private int state; 9 | 10 | public int getState() { 11 | return state; 12 | } 13 | 14 | public void setState(int state) { 15 | this.state = state; 16 | this.notifyObservers(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /outputs/com/coffeeDecorator/WhipCream.java: -------------------------------------------------------------------------------- 1 | package com.coffeeDecorator; 2 | 3 | /** 4 | * ConcreteDecoratorB, add features to component 5 | */ 6 | public class WhipCream extends CondimentDecorator { 7 | private boolean behaviorMethodInvoked = false; 8 | 9 | public void operation() { 10 | this.component.operation(); 11 | addedBehavior(); 12 | } 13 | 14 | private void addedBehavior() { 15 | behaviorMethodInvoked = true; 16 | } 17 | 18 | protected boolean isBehaviorMethodInvoked() { 19 | return behaviorMethodInvoked; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/DesignPatternGenerator.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import java.io.IOException; 4 | 5 | abstract class DesignPatternGenerator { 6 | 7 | protected String[] designPatterns = {"Singleton","Abstract Factory","Builder","Factory Method","Prototype", 8 | "Adapter","Bridge","Composite","Decorator","Facade","Flyweight","Proxy", 9 | "Chain of Responsibility","Command","Interpreter","Iterator","Mediator","Memento","Observer","State","Strategy","Visitor","Template Method"}; 10 | 11 | abstract void displayDesignPatterns(); 12 | 13 | abstract void generateDesignPattern() throws IOException; 14 | 15 | abstract void designPatternFactory() throws IOException; 16 | } 17 | -------------------------------------------------------------------------------- /outputs/com/weatherObserver/AndroidPhone.java: -------------------------------------------------------------------------------- 1 | package com.weatherObserver; 2 | 3 | /** 4 | * ConcreteObserver maintains a reference to a ConcreteSubject object, stores 5 | * state that should stay consistent with the subject's, implements the Observer 6 | * updating interface to keep its state consistent with the subject's. 7 | */ 8 | public class AndroidPhone implements SmartPhone { 9 | private int observerState; 10 | 11 | private DarkSkyServer subject; 12 | 13 | public AndroidPhone(DarkSkyServer subject) { 14 | this.subject = subject; 15 | } 16 | 17 | public void update() { 18 | observerState = subject.getState(); 19 | } 20 | 21 | protected int getObserverState() { 22 | return observerState; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /outputs/com/weatherObserver/WeatherServiceServer.java: -------------------------------------------------------------------------------- 1 | package com.weatherObserver; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | /** 8 | * Subject knows its observers. Any number of Observer objects may observe a subject. 9 | */ 10 | abstract class WeatherServiceServer { 11 | private List observers = new ArrayList(); 12 | 13 | public void attach(SmartPhone observer) { 14 | observers.add(observer); 15 | } 16 | 17 | public void detach(SmartPhone observer) { 18 | observers.remove(observer); 19 | } 20 | 21 | public void notifyObservers() { 22 | (Iterator iterator = observers.iterator(); iterator.hasNext();) { 23 | SmartPhone observer = (SmartPhone) iterator.next(); 24 | observer.update(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/resources/default.conf: -------------------------------------------------------------------------------- 1 | { 2 | iterations = [ 3 | { 4 | designPatternChoice = "2" 5 | classes = ["Processor", "Intel", "AMD", 6 | "OperatingSystem", "OS", "ChromeOS", "Ubuntu", 7 | "LaptopFactory", "ChromeBookFactory","LinuxLaptopFactory"] 8 | packageName = "com.laptopAbstractFactory" 9 | }, 10 | { 11 | designPatternChoice = "9" 12 | classes = ["Beverage","Coffee","CondimentDecorator","Milk","WhipCream"] 13 | packageName = "com.coffeeDecorator" 14 | }, 15 | { 16 | designPatternChoice = "6" 17 | classes = ["TypeC", "MicroUSB","USBDongle"] 18 | packageName = "com.usbAdapter" 19 | }, 20 | { 21 | designPatternChoice = "19" 22 | classes = ["SmartPhone", "WeatherServiceServer","DarkSkyServer","AndroidPhone"] 23 | packageName = "com.weatherObserver" 24 | }] 25 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Samujjwaal Dey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/test/java/com/DesignPatternTest.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import com.squareup.javapoet.JavaFile; 4 | import com.structural.Flyweight; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | import java.nio.file.Paths; 12 | 13 | import static org.junit.jupiter.api.Assertions.*; 14 | 15 | class DesignPatternTest { 16 | String[] classNames = {"Flyweight", "ConcreteFlyweight","UnsharedConcreteFlyweight","FlyweightFactory"}; 17 | String packageName = "com.test_generateCode.flyweight"; 18 | 19 | @Test 20 | void test_generateCode() throws IOException { 21 | 22 | // Test Case to verify generateCode() returns JavaFile[] object 23 | 24 | assertEquals(JavaFile[].class,new Flyweight(0).generateCode(classNames, packageName).getClass()); 25 | } 26 | 27 | @Test 28 | void test_writeJavaFiles() throws IOException { 29 | 30 | // Test Case to verify the generated java files are written successfully in the output folder 31 | int mode = 0; 32 | Flyweight test = new Flyweight(mode); 33 | JavaFile[] test_files = test.generateCode(classNames, packageName); 34 | test.writeJavaFiles(test_files); 35 | Path path = Paths.get("outputs/com/test_generateCode/flyweight"); 36 | assertTrue(Files.exists(path)); 37 | 38 | 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/test/java/com/Hw1DesignPatternGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import com.structural.Flyweight; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | 8 | 9 | import static org.junit.jupiter.api.Assertions.*; 10 | 11 | class Hw1DesignPatternGeneratorTest { 12 | 13 | 14 | @Test 15 | void test_getInstance() { 16 | 17 | // Test Case to verify only 1 instance of Hw1DesignPatternGenerator is created each time 18 | 19 | Hw1DesignPatternGenerator firstInstance = Hw1DesignPatternGenerator.getInstance(); 20 | Hw1DesignPatternGenerator secondInstance = Hw1DesignPatternGenerator.getInstance(); 21 | 22 | assertEquals(firstInstance,secondInstance); 23 | } 24 | 25 | 26 | @Test 27 | void chooseDesignPattern() throws IOException { 28 | 29 | //Test Case to verify correct design pattern file is executed when user inputs the choice of design pattern 30 | // Here Flyweight( 11 ) is selected. 31 | 32 | DesignPattern design_pattern2 = Hw1DesignPatternGenerator.getInstance().chooseDesignPattern(11,0); 33 | assertEquals(Flyweight.class,design_pattern2.getClass()); 34 | 35 | // Test Case to check null is returned on selecting incorrect design pattern choice 36 | int choice = 75; 37 | DesignPattern design_pattern = Hw1DesignPatternGenerator.getInstance().chooseDesignPattern(choice,0); 38 | assertNull(design_pattern); 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/java/com/DePaCoG.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import com.squareup.javapoet.JavaFile; 4 | import com.typesafe.config.Config; 5 | import com.typesafe.config.ConfigFactory; 6 | import ch.qos.logback.classic.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import java.io.IOException; 9 | import java.util.Arrays; 10 | 11 | public class DePaCoG { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(DePaCoG.class); 15 | 16 | public static void main(String[] args) throws IOException { 17 | logger.info("Started execution of main()"); 18 | 19 | Hw1DesignPatternGenerator hw1 = Hw1DesignPatternGenerator.getInstance(); 20 | // hw1.displayDesignPatterns(); 21 | 22 | if(args[0].equals("0")){ 23 | 24 | logger.info("Parsing input from default config file "); 25 | 26 | // parse the config file 27 | Config paramsConfig = ConfigFactory.load("default.conf"); 28 | 29 | //mode for taking input from config file 30 | int mode = 0; 31 | // create array of Config objects to obtain inputs for every iterations of run 32 | Config[] iterations = paramsConfig.getConfigList("iterations").toArray(new Config[0]); 33 | 34 | for (Config iteration: iterations) { 35 | // get the choice of design pattern to be generated 36 | int choice = iteration.getInt("designPatternChoice"); 37 | // get class names for output files 38 | Object[] classes = iteration.getStringList("classes").toArray(); 39 | String[] classNames = Arrays.copyOf(classes,classes.length,String[].class); 40 | // get package name to set for output files 41 | String packageName = iteration.getString("packageName"); 42 | // pass design pattern choice and mode 43 | DesignPattern outputDesignPattern = hw1.chooseDesignPattern(choice,mode); 44 | // get outputs files as JavaFile[] 45 | JavaFile[] files = outputDesignPattern.generateCode(classNames,packageName); 46 | // write generated design patterns into files 47 | outputDesignPattern.writeJavaFiles(files); 48 | } 49 | } 50 | if (args[0].equals("1")){ 51 | logger.info("Displaying interactive menu"); 52 | // to execute using custom inputs 53 | hw1.generateDesignPattern(); 54 | } 55 | logger.info("End of execution"); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/creational/Singleton.java: -------------------------------------------------------------------------------- 1 | package com.creational; 2 | 3 | import com.squareup.javapoet.*; 4 | import javax.lang.model.element.Modifier; 5 | import java.io.IOException; 6 | import com.DesignPattern; 7 | import ch.qos.logback.classic.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class Singleton implements DesignPattern { 11 | 12 | //Define a static logger variable so that it references the Logger instance 13 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Singleton.class); 14 | 15 | String[] defaultClasses = {"Singleton"}; 16 | String packageName = "com.CreationalDP.singleton"; 17 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 18 | 19 | public Singleton(int flag)throws IOException{ 20 | logger.info("Executing Singleton()"); 21 | if (flag == 1){ 22 | createDesignPattern(defaultClasses, packageName); 23 | } 24 | // else{ 25 | // System.out.println("Exit"); 26 | // } 27 | } 28 | 29 | 30 | @Override 31 | public JavaFile[] generateCode(String[] classes, String packageName){ 32 | logger.info("Executing generateCode()"); 33 | int i = 0; 34 | ClassName Singleton = ClassName.get("", classes[i]); 35 | 36 | MethodSpec constructor = MethodSpec.constructorBuilder() 37 | .addModifiers(Modifier.PRIVATE) 38 | .build(); 39 | 40 | FieldSpec instance = FieldSpec.builder(Singleton, "INSTANCE") 41 | .addModifiers(Modifier.PRIVATE, Modifier.STATIC) 42 | .build(); 43 | 44 | MethodSpec getInstance = MethodSpec.methodBuilder("getInstance") 45 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC) 46 | .returns(Singleton) 47 | .beginControlFlow("if ($N == null)", instance.name) 48 | .addStatement("$N = new $T()",instance.name, Singleton) 49 | .endControlFlow() 50 | .addStatement("return $N", instance.name) 51 | .build(); 52 | 53 | TypeSpec singleton = TypeSpec.classBuilder(Singleton) 54 | .addModifiers(Modifier.PUBLIC) 55 | .addField(instance) 56 | .addMethod(constructor) 57 | .addMethod(getInstance) 58 | .build(); 59 | 60 | generatedCode[i] = JavaFile.builder(packageName, singleton) 61 | .skipJavaLangImports(true) 62 | .build(); 63 | i += 1; 64 | 65 | logger.info("Returning generated java code to be written in files"); 66 | 67 | // javaFile.writeTo(new File("C:\\Users\\Samujjwaal Dey\\Desktop\\CS 474 OOLE\\outputs/singleton.java")); 68 | return generatedCode; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/sbt,java,intellij 3 | # Edit at https://www.gitignore.io/?templates=sbt,java,intellij 4 | 5 | ### Intellij ### 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 8 | 9 | # User-specific stuff 10 | .idea/**/workspace.xml 11 | .idea/**/tasks.xml 12 | .idea/**/usage.statistics.xml 13 | .idea/**/dictionaries 14 | .idea/**/shelf 15 | 16 | # Generated files 17 | .idea/**/contentModel.xml 18 | 19 | # Sensitive or high-churn files 20 | .idea/**/dataSources/ 21 | .idea/**/dataSources.ids 22 | .idea/**/dataSources.local.xml 23 | .idea/**/sqlDataSources.xml 24 | .idea/**/dynamic.xml 25 | .idea/**/uiDesigner.xml 26 | .idea/**/dbnavigator.xml 27 | 28 | # Gradle 29 | .idea/**/gradle.xml 30 | .idea/**/libraries 31 | 32 | # Gradle and Maven with auto-import 33 | # When using Gradle or Maven with auto-import, you should exclude module files, 34 | # since they will be recreated, and may cause churn. Uncomment if using 35 | # auto-import. 36 | # .idea/modules.xml 37 | # .idea/*.iml 38 | # .idea/modules 39 | # *.iml 40 | # *.ipr 41 | 42 | # CMake 43 | cmake-build-*/ 44 | 45 | # Mongo Explorer plugin 46 | .idea/**/mongoSettings.xml 47 | 48 | # File-based project format 49 | *.iws 50 | 51 | # IntelliJ 52 | out/ 53 | 54 | # mpeltonen/sbt-idea plugin 55 | .idea_modules/ 56 | 57 | # JIRA plugin 58 | atlassian-ide-plugin.xml 59 | 60 | # Cursive Clojure plugin 61 | .idea/replstate.xml 62 | 63 | # Crashlytics plugin (for Android Studio and IntelliJ) 64 | com_crashlytics_export_strings.xml 65 | crashlytics.properties 66 | crashlytics-build.properties 67 | fabric.properties 68 | 69 | # Editor-based Rest Client 70 | .idea/httpRequests 71 | 72 | # Android studio 3.1+ serialized cache file 73 | .idea/caches/build_file_checksums.ser 74 | 75 | ### Intellij Patch ### 76 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 77 | 78 | # *.iml 79 | # modules.xml 80 | # .idea/misc.xml 81 | # *.ipr 82 | 83 | # Sonarlint plugin 84 | .idea/**/sonarlint/ 85 | 86 | # SonarQube Plugin 87 | .idea/**/sonarIssues.xml 88 | 89 | # Markdown Navigator plugin 90 | .idea/**/markdown-navigator.xml 91 | .idea/**/markdown-navigator/ 92 | 93 | ### Java ### 94 | # Compiled class file 95 | *.class 96 | 97 | # Log file 98 | *.log 99 | 100 | # BlueJ files 101 | *.ctxt 102 | 103 | # Mobile Tools for Java (J2ME) 104 | .mtj.tmp/ 105 | 106 | # Package Files # 107 | *.jar 108 | *.war 109 | *.nar 110 | *.ear 111 | *.zip 112 | *.tar.gz 113 | *.rar 114 | 115 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 116 | hs_err_pid* 117 | 118 | ### SBT ### 119 | # Simple Build Tool 120 | # http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control 121 | 122 | dist/* 123 | target/ 124 | lib_managed/ 125 | src_managed/ 126 | project/boot/ 127 | project/plugins/project/ 128 | .history 129 | .cache 130 | .lib/ 131 | 132 | # End of https://www.gitignore.io/api/sbt,java,intellij 133 | 134 | outputs/ 135 | .idea 136 | target/streams 137 | project/project 138 | project/target 139 | !target/scala-2.13/hw1-assembly-0.1.jar -------------------------------------------------------------------------------- /src/main/java/com/structural/Adapter.java: -------------------------------------------------------------------------------- 1 | package com.structural; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class Adapter implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Adapter.class); 15 | 16 | 17 | String[] defaultClasses = {"Target", "Adaptee","Adapter"}; 18 | String packageName = "com.StructuralDP.adapter"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | 22 | public Adapter(int flag)throws IOException{ 23 | logger.info("Executing Adapter()"); 24 | if(flag == 1) { 25 | createDesignPattern(defaultClasses, packageName); 26 | } 27 | } 28 | 29 | public JavaFile[] generateCode(String[] classes, String packageName){ 30 | 31 | int i = 0; 32 | logger.info("Executing generateCode()"); 33 | 34 | 35 | // Target interface declaration 36 | ClassName Target = ClassName.get("",classes[i]); 37 | TypeSpec target = TypeSpec.interfaceBuilder(Target) 38 | .addModifiers(Modifier.PUBLIC) 39 | .addJavadoc("Target interface, defines domain-specific interface to which Adaptee will be adapted") 40 | .addMethod(MethodSpec.methodBuilder("request") 41 | .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC) 42 | .returns(String.class) 43 | .build()) 44 | .build(); 45 | generatedCode[i] = JavaFile.builder(packageName,target) 46 | .skipJavaLangImports(true) 47 | .build(); 48 | i += 1; 49 | // Adaptee class declaration 50 | ClassName Adaptee = ClassName.get("",classes[i]); 51 | TypeSpec adaptee = TypeSpec.classBuilder(Adaptee) 52 | .addModifiers(Modifier.PUBLIC) 53 | .addJavadoc("Adaptee class, interface which will be adapted") 54 | .addMethod(MethodSpec.methodBuilder("specialRequest") 55 | .addModifiers(Modifier.PUBLIC) 56 | .returns(String.class) 57 | .addStatement("return $S","specialRequest") 58 | .build()) 59 | .build(); 60 | generatedCode[i] = JavaFile.builder(packageName,adaptee) 61 | .skipJavaLangImports(true) 62 | .build(); 63 | i += 1; 64 | // Adapter class declaration 65 | ClassName Adapter =ClassName.get("",classes[i]); 66 | TypeSpec adapter = TypeSpec.classBuilder(Adapter) 67 | .addSuperinterface(Target) 68 | .addJavadoc("Adapter class, adapts Adaptee to the Target interface") 69 | .addModifiers(Modifier.PUBLIC) 70 | .addField(Adaptee, "adaptee",Modifier.PRIVATE) 71 | .addMethod(MethodSpec.constructorBuilder() 72 | .addModifiers(Modifier.PUBLIC) 73 | .addParameter(Adaptee, "adaptee") 74 | .addStatement("this.adaptee = adaptee") 75 | .build()) 76 | .addMethod(MethodSpec.methodBuilder("request") 77 | .addModifiers(Modifier.PUBLIC) 78 | .returns(String.class) 79 | .addStatement("return adaptee.specialRequest()") 80 | .build()) 81 | .build(); 82 | generatedCode[i] = JavaFile.builder(packageName,adapter) 83 | .skipJavaLangImports(true) 84 | .build(); 85 | 86 | logger.info("Returning generated java code to be written in files"); 87 | 88 | return generatedCode; 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/TemplateMethod.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class TemplateMethod implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(TemplateMethod.class); 15 | 16 | 17 | String[] defaultClasses = {"AbstractClass", "ConcreteClass"}; 18 | String packageName = "com.BehavioralDP.templateMethod"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public TemplateMethod(int flag)throws IOException{ 22 | logger.info("Executing TemplateMethod()"); 23 | if(flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | public JavaFile[] generateCode(String[] classes, String packageName){ 29 | logger.info("Executing generateCode()"); 30 | 31 | int i = 0; 32 | 33 | ClassName abstractclass = ClassName.get("",classes[i]); 34 | 35 | // AbstractClass declaration 36 | MethodSpec primOp1 = MethodSpec.methodBuilder("primitiveOperation1") 37 | .addModifiers(Modifier.ABSTRACT) 38 | .returns(String.class) 39 | .build(); 40 | MethodSpec primOp2 = MethodSpec.methodBuilder("primitiveOperation2") 41 | .addModifiers(Modifier.ABSTRACT) 42 | .returns(String.class) 43 | .build(); 44 | 45 | TypeSpec abstractC = TypeSpec.classBuilder(abstractclass) 46 | .addModifiers(Modifier.ABSTRACT) 47 | .addJavadoc("Defines interfaces for primitive operations. Implements algorithm.") 48 | .addMethod(MethodSpec.methodBuilder("templateMethod") 49 | .addModifiers(Modifier.PUBLIC) 50 | .returns(String.class) 51 | .addJavadoc("Template method, implementation of algorithm which consists of\n" + 52 | "primitiveOperations\n" + 53 | "\n" + 54 | "@return result of the primitive operations") 55 | .addStatement("return this.$N() + this.$N()",primOp1.name,primOp2.name) 56 | .build()) 57 | .addMethod(primOp1) 58 | .addMethod(primOp2) 59 | .build(); 60 | generatedCode[i] = JavaFile.builder(packageName,abstractC) 61 | .skipJavaLangImports(true) 62 | .build(); 63 | i += 1; 64 | 65 | // ConcreteClass declaration 66 | ClassName concreteclass = ClassName.get("",classes[i]); 67 | TypeSpec concreteC = TypeSpec.classBuilder(concreteclass) 68 | .superclass(abstractclass) 69 | .addJavadoc("Implements the primitive operations to carry out subclass-specific steps of\n" + 70 | "the algorithm.") 71 | .addModifiers(Modifier.PUBLIC) 72 | .addMethod(MethodSpec.methodBuilder(primOp1.name) 73 | .addModifiers(Modifier.PUBLIC) 74 | .returns(String.class) 75 | .addStatement("return $S","Template") 76 | .build()) 77 | .addMethod(MethodSpec.methodBuilder(primOp2.name) 78 | .addModifiers(Modifier.PUBLIC) 79 | .returns(String.class) 80 | .addStatement("return $S","Method") 81 | .build()) 82 | .build(); 83 | generatedCode[i] = JavaFile.builder(packageName,concreteC) 84 | .skipJavaLangImports(true) 85 | .build(); 86 | 87 | logger.info("Returning generated java code to be written in files"); 88 | 89 | return generatedCode; 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/structural/Proxy.java: -------------------------------------------------------------------------------- 1 | package com.structural; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class Proxy implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Proxy.class); 15 | 16 | String[] defaultClasses = {"Subject", "RealSubject","Proxy"}; 17 | String packageName = "com.StructuralDP.proxy"; 18 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 19 | 20 | public Proxy(int flag)throws IOException{ 21 | logger.info("Executing Proxy()"); 22 | if(flag == 1) { 23 | createDesignPattern(defaultClasses, packageName); 24 | } 25 | } 26 | 27 | public JavaFile[] generateCode(String[] classes, String packageName){ 28 | logger.info("Executing generateCode()"); 29 | 30 | int i = 0; 31 | 32 | // Proxy interface declaration 33 | MethodSpec doOp = MethodSpec.methodBuilder("doOperation") 34 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT) 35 | .returns(TypeName.VOID) 36 | .build(); 37 | ClassName Subject = ClassName.get("",classes[i]); 38 | TypeSpec subject = TypeSpec.interfaceBuilder(Subject) 39 | .addModifiers(Modifier.PUBLIC) 40 | .addJavadoc("Subject interface defines common interface for RealSubject and Proxy") 41 | .addMethod(doOp) 42 | .build(); 43 | generatedCode[i] = JavaFile.builder(packageName,subject) 44 | .skipJavaLangImports(true) 45 | .build(); 46 | i += 1; 47 | 48 | // RealSubject class declaration 49 | ClassName RealSubject = ClassName.get("",classes[i]); 50 | TypeSpec realSubject = TypeSpec.classBuilder(RealSubject) 51 | .addSuperinterface(Subject) 52 | .addJavadoc("RealSubject class is a real object which is represented by Proxy") 53 | .addModifiers(Modifier.PUBLIC) 54 | .addMethod(MethodSpec.methodBuilder(doOp.name) 55 | .addModifiers(Modifier.PUBLIC) 56 | .build()) 57 | .build(); 58 | generatedCode[i] = JavaFile.builder(packageName,realSubject) 59 | .skipJavaLangImports(true) 60 | .build(); 61 | i += 1; 62 | 63 | // Proxy class declaration 64 | ClassName Proxy = ClassName.get("",classes[i]); 65 | TypeSpec proxy = TypeSpec.classBuilder(Proxy) 66 | .addModifiers(Modifier.PUBLIC) 67 | .addSuperinterface(Subject) 68 | .addJavadoc("Proxy class keep reference on a real subject, define interface which\n" + 69 | "represents Subject, so he can: - act as a surrogate - control access to real\n" + 70 | "subject - can be responsible for creation and maintenance of the real\n" + 71 | "subject\n") 72 | .addField(RealSubject, "realSubject",Modifier.PRIVATE) 73 | .addMethod(MethodSpec.methodBuilder(doOp.name) 74 | .addModifiers(Modifier.PUBLIC) 75 | .addStatement("this.$N = new $T()","realSubject",RealSubject) 76 | .addStatement("this.$N.$N()","realSubject",doOp.name) 77 | .build()) 78 | .addMethod(MethodSpec.methodBuilder("getRealSubject") 79 | .addModifiers(Modifier.PUBLIC) 80 | .returns(RealSubject) 81 | .addStatement("return $N","realSubject") 82 | .build()) 83 | .build(); 84 | generatedCode[i] = JavaFile.builder(packageName,proxy) 85 | .skipJavaLangImports(true) 86 | .build(); 87 | 88 | logger.info("Returning generated java code to be written in files"); 89 | 90 | return generatedCode; 91 | 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/structural/Composite.java: -------------------------------------------------------------------------------- 1 | package com.structural; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class Composite implements DesignPattern { 12 | //Define a static logger variable so that it references the Logger instance 13 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Composite.class); 14 | 15 | 16 | String[] defaultClasses = {"Component", "Composite"}; 17 | String packageName = "com.StructuralDP.composite"; 18 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 19 | 20 | public Composite(int flag)throws IOException{ 21 | logger.info("Executing Composite()"); 22 | if(flag == 1) { 23 | createDesignPattern(defaultClasses, packageName); 24 | } 25 | } 26 | 27 | public JavaFile[] generateCode(String[] classes, String packageName){ 28 | 29 | logger.info("Executing generateCode()"); 30 | int i = 0; 31 | 32 | // Component interface declaration 33 | ClassName Component = ClassName.get("",classes[i]); 34 | MethodSpec oper = MethodSpec.methodBuilder("operation") 35 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT) 36 | .returns(TypeName.VOID) 37 | .build(); 38 | TypeSpec component = TypeSpec.interfaceBuilder(Component) 39 | .addModifiers(Modifier.PUBLIC) 40 | .addJavadoc("Component declares the interface for objects in the composition") 41 | .addMethod(oper) 42 | .build(); 43 | generatedCode[i] = JavaFile.builder(packageName,component) 44 | .skipJavaLangImports(true) 45 | .build(); 46 | i += 1; 47 | 48 | // Composite class declaration 49 | ClassName Composite = ClassName.get("",classes[i]); 50 | ClassName list = ClassName.get("java.util", "List"); 51 | ClassName arrayList = ClassName.get("java.util", "ArrayList"); 52 | TypeName listOfComponents = ParameterizedTypeName.get(list,Component); 53 | 54 | FieldSpec child = FieldSpec.builder(listOfComponents,"children") 55 | .addModifiers(Modifier.PRIVATE) 56 | .initializer("new $T<$T>()",arrayList,Component) 57 | .build(); 58 | TypeSpec composite = TypeSpec.classBuilder(Composite) 59 | .superclass(Component) 60 | .addModifiers(Modifier.PUBLIC) 61 | .addJavadoc("Composite class defines behavior for components having children, stores child\n" + 62 | "components, implements child-related operations in the Component interface") 63 | .addField(child) 64 | .addMethod(MethodSpec.methodBuilder(oper.name) 65 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 66 | .beginControlFlow("for($T component : $N)",Component,child.name) 67 | .addStatement("component.$N()",oper.name) 68 | .endControlFlow() 69 | .build()) 70 | .addMethod(MethodSpec.methodBuilder("add") 71 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 72 | .addParameter(Component,"component") 73 | .addStatement("$N.add(component)",child.name) 74 | .build()) 75 | .addMethod(MethodSpec.methodBuilder("remove") 76 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 77 | .addParameter(Component,"component") 78 | .addStatement("$N.remove(component)",child.name) 79 | .build()) 80 | .addMethod(MethodSpec.methodBuilder("getChild") 81 | .addModifiers(Modifier.PUBLIC).returns(Component) 82 | .addParameter(int.class,"index") 83 | .addStatement("return $N.get(index)",child.name) 84 | .build()) 85 | .build(); 86 | generatedCode[i] = JavaFile.builder(packageName,composite) 87 | .skipJavaLangImports(true) 88 | .build(); 89 | 90 | logger.info("Returning generated java code to be written in files"); 91 | 92 | return generatedCode; 93 | 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/creational/Prototype.java: -------------------------------------------------------------------------------- 1 | package com.creational; 2 | 3 | import com.squareup.javapoet.*; 4 | import javax.lang.model.element.Modifier; 5 | import java.io.IOException; 6 | import com.DesignPattern; 7 | import ch.qos.logback.classic.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class Prototype implements DesignPattern { 11 | 12 | //Define a static logger variable so that it references the Logger instance 13 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Prototype.class); 14 | 15 | String[] defaultClasses = {"Prototype","ConcretePrototype","Client"}; 16 | String packageName = "com.CreationalDP.prototype"; 17 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 18 | 19 | public Prototype(int flag)throws IOException { 20 | logger.info("Executing Prototype()"); 21 | 22 | if (flag == 1) { 23 | createDesignPattern(defaultClasses, packageName); 24 | } 25 | } 26 | 27 | @Override 28 | public JavaFile[] generateCode(String[] classes, String packageName){ 29 | logger.info("Executing generateCode()"); 30 | int i = 0; 31 | 32 | // Prototype abstract class declaration 33 | ClassName Prototype = ClassName.get("",classes[i]); 34 | MethodSpec copyMe = MethodSpec.methodBuilder("copyMe") 35 | .addModifiers(Modifier.ABSTRACT) 36 | .addException(CloneNotSupportedException.class) 37 | .addJavadoc("Copy method.\n" + 38 | "@return copy of the object\n" + 39 | "@throws CloneNotSupportedException exception") 40 | .returns(Prototype) 41 | .build(); 42 | TypeSpec prototype = TypeSpec.classBuilder(Prototype) 43 | .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC) 44 | .addSuperinterface(Cloneable.class) 45 | .addJavadoc("Declares interface to copy it self.") 46 | .addMethod(copyMe) 47 | .build(); 48 | generatedCode[i] = JavaFile.builder(packageName,prototype) 49 | .skipJavaLangImports(true) 50 | .build(); 51 | i += 1; 52 | 53 | // ConcretePrototype class declaration 54 | ClassName ConcretePrototype = ClassName.get("",classes[i]); 55 | TypeSpec concPrototype = TypeSpec.classBuilder(ConcretePrototype) 56 | .addModifiers(Modifier.PUBLIC) 57 | .superclass(Prototype) 58 | .addJavadoc("Declares interface to copy it self.") 59 | .addMethod(MethodSpec.methodBuilder(copyMe.name) 60 | .addModifiers(Modifier.PUBLIC) 61 | .addException(CloneNotSupportedException.class) 62 | .returns(Prototype) 63 | .addStatement("return ($T) this.clone()",Prototype) 64 | .build()) 65 | .build(); 66 | generatedCode[i] = JavaFile.builder(packageName,concPrototype) 67 | .skipJavaLangImports(true) 68 | .build(); 69 | i += 1; 70 | 71 | // Client class declaration 72 | ClassName Client = ClassName.get("",classes[i]); 73 | FieldSpec proto = FieldSpec.builder(Prototype, "prototype",Modifier.PRIVATE).build(); 74 | TypeSpec client = TypeSpec.classBuilder(Client) 75 | .addModifiers(Modifier.PUBLIC) 76 | .addJavadoc("Creates a new object by asking a Prototype to clone itself") 77 | .addField(proto) 78 | .addMethod(MethodSpec.constructorBuilder() 79 | .addModifiers(Modifier.PUBLIC) 80 | .addParameter(Prototype,"prototype") 81 | .addStatement("this.$N = prototype",proto.name) 82 | .build()) 83 | .addMethod(MethodSpec.methodBuilder("operation") 84 | .addModifiers(Modifier.PUBLIC) 85 | .addException(CloneNotSupportedException.class) 86 | .returns(Prototype) 87 | .addStatement("return $N.$N()",proto.name,copyMe.name) 88 | .build()) 89 | .build(); 90 | generatedCode[i] = JavaFile.builder(packageName,client) 91 | .skipJavaLangImports(true) 92 | .build(); 93 | 94 | logger.info("Returning generated java code to be written in files"); 95 | 96 | return generatedCode; 97 | 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/State.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class State implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(State.class); 15 | 16 | 17 | String[] defaultClasses = {"State", "ConcreteState","Context"}; 18 | String packageName = "com.BehavioralDP.state"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public State(int flag)throws IOException{ 22 | logger.info("Executing State()"); 23 | if(flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | public JavaFile[] generateCode(String[] classes, String packageName){ 29 | logger.info("Executing generateCode()"); 30 | 31 | int i = 0; 32 | 33 | // State interface declaration 34 | ClassName State = ClassName.get("",classes[i]); 35 | MethodSpec handle = MethodSpec.methodBuilder("handle") 36 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT) 37 | .returns(TypeName.VOID) 38 | .build(); 39 | TypeSpec state = TypeSpec.interfaceBuilder(State) 40 | .addModifiers(Modifier.PUBLIC) 41 | .addJavadoc("The interface for encapsulating the behavior associated with a particular\n" + 42 | "state of the Context.") 43 | .addMethod(handle) 44 | .build(); 45 | generatedCode[i] = JavaFile.builder(packageName,state) 46 | .skipJavaLangImports(true) 47 | .build(); 48 | i += 1; 49 | 50 | // ConcreteState class declaration 51 | ClassName ConcreteState = ClassName.get("",classes[i]); 52 | FieldSpec handleInv = FieldSpec.builder(TypeName.BOOLEAN,"handleInvoked") 53 | .addModifiers(Modifier.PRIVATE) 54 | .initializer("false") 55 | .build(); 56 | TypeSpec concreteState = TypeSpec.classBuilder(ConcreteState) 57 | .addSuperinterface(State) 58 | .addModifiers(Modifier.PUBLIC) 59 | .addJavadoc("ConcreteState implements a behavior associated with a state of the Context.") 60 | .addField(handleInv) 61 | .addMethod(MethodSpec.methodBuilder(handle.name) 62 | .addModifiers(Modifier.PUBLIC) 63 | .returns(TypeName.VOID) 64 | .addStatement("this.$N = true",handleInv.name) 65 | .build()) 66 | .addMethod(MethodSpec.methodBuilder("isHandleInvoked") 67 | .addModifiers(Modifier.PROTECTED) 68 | .returns(TypeName.BOOLEAN) 69 | .addStatement("return $N", handleInv) 70 | .build()) 71 | .build(); 72 | generatedCode[i] = JavaFile.builder(packageName,concreteState) 73 | .skipJavaLangImports(true) 74 | .build(); 75 | i += 1; 76 | 77 | // Context class declaration 78 | ClassName Context = ClassName.get("",classes[i]); 79 | TypeSpec context = TypeSpec.classBuilder(Context) 80 | .addModifiers(Modifier.PUBLIC) 81 | .addJavadoc("Context maintains an instance of a ConcreteState subclass that defines the\n" + 82 | "current state.") 83 | .addField(ConcreteState, "state",Modifier.PRIVATE) 84 | .addMethod(MethodSpec.methodBuilder("request") 85 | .addModifiers(Modifier.PUBLIC) 86 | .addStatement("$N.$N()","state",handle.name) 87 | .build()) 88 | .addMethod(MethodSpec.methodBuilder("setState") 89 | .addModifiers(Modifier.PUBLIC) 90 | .returns(TypeName.VOID) 91 | .addParameter(State, "state") 92 | .addStatement("this.$N = state", "state") 93 | .build()) 94 | .build(); 95 | generatedCode[i] = JavaFile.builder(packageName,context) 96 | .skipJavaLangImports(true) 97 | .build(); 98 | 99 | logger.info("Returning generated java code to be written in files"); 100 | 101 | return generatedCode; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/creational/FactoryMethod.java: -------------------------------------------------------------------------------- 1 | package com.creational; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class FactoryMethod implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(FactoryMethod.class); 15 | 16 | String[] defaultClasses = {"Product","Factory","ConcreteProductA","ConcreteProductB","ConcreteFactory"}; 17 | String packageName = "com.CreationalDP.factoryMethod"; 18 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 19 | 20 | public FactoryMethod(int flag)throws IOException { 21 | logger.info("Executing FactoryMethod()"); 22 | 23 | if (flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | @Override 29 | public JavaFile[] generateCode(String[] classes, String packageName){ 30 | logger.info("Executing generateCode()"); 31 | 32 | int i = 0; 33 | // Product interface declaration 34 | ClassName Product = ClassName.get("",classes[i]); 35 | TypeSpec product = TypeSpec.interfaceBuilder(Product) 36 | .addModifiers(Modifier.PUBLIC) 37 | .addJavadoc("Product interface, defines the interface of the objects which factory method creates.") 38 | .build(); 39 | generatedCode[i] = JavaFile.builder(packageName,product) 40 | .skipJavaLangImports(true) 41 | .build(); 42 | i += 1; 43 | // Factory abstract class declaration 44 | ClassName Factory = ClassName.get("",classes[i]); 45 | MethodSpec factoryMethod = MethodSpec.methodBuilder("factoryMethod") 46 | .addModifiers(Modifier.ABSTRACT) 47 | .returns(Product) 48 | .addParameter(String.class,"type") 49 | .build(); 50 | TypeSpec factory = TypeSpec.classBuilder(Factory) 51 | .addModifiers(Modifier.ABSTRACT) 52 | .addJavadoc("Factory class declares factory method") 53 | .addMethod(factoryMethod) 54 | .build(); 55 | generatedCode[i] = JavaFile.builder(packageName,factory) 56 | .skipJavaLangImports(true) 57 | .build(); 58 | i += 1; 59 | // ConcreteProductA class declaration 60 | ClassName ConcreteProductA = ClassName.get("",classes[i]); 61 | TypeSpec concProdA = TypeSpec.classBuilder(ConcreteProductA) 62 | .addModifiers(Modifier.PUBLIC) 63 | .addSuperinterface(Product) 64 | .addJavadoc("ConcreteProductA class implements Product interface") 65 | .build(); 66 | generatedCode[i] = JavaFile.builder(packageName,concProdA) 67 | .skipJavaLangImports(true) 68 | .build(); 69 | i += 1; 70 | // ConcreteProductB class declaration 71 | ClassName ConcreteProductB = ClassName.get("",classes[i]); 72 | TypeSpec concProdB = TypeSpec.classBuilder(ConcreteProductB) 73 | .addModifiers(Modifier.PUBLIC) 74 | .addSuperinterface(Product) 75 | .addJavadoc("ConcreteProductB class implements Product interface") 76 | .build(); 77 | generatedCode[i] = JavaFile.builder(packageName,concProdB) 78 | .skipJavaLangImports(true) 79 | .build(); 80 | i += 1; 81 | // ProductFactory class declaration 82 | ClassName ConcreteFactory = ClassName.get("",classes[i]); 83 | TypeSpec concFactory = TypeSpec.classBuilder(ConcreteFactory) 84 | .superclass(Factory) 85 | .addModifiers(Modifier.PUBLIC) 86 | .addMethod(MethodSpec.methodBuilder("productFactory") 87 | .addModifiers(Modifier.PUBLIC).returns(Product) 88 | .addParameter(String.class,"type") 89 | .beginControlFlow("if (type.equals(\"A\"))") 90 | .addStatement("return new $T()",ConcreteProductA) 91 | .nextControlFlow("else if (type.equals(\"B\"))") 92 | .addStatement("return new $T()",ConcreteProductB) 93 | .endControlFlow() 94 | .addStatement("return null") 95 | .build()) 96 | .build(); 97 | generatedCode[i] = JavaFile.builder(packageName,concFactory) 98 | .skipJavaLangImports(true) 99 | .build(); 100 | 101 | logger.info("Returning generated java code to be written in files"); 102 | 103 | return generatedCode; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/ChainOfResponsibility.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | import javax.lang.model.element.Modifier; 5 | import java.io.IOException; 6 | import com.DesignPattern; 7 | 8 | public class ChainOfResponsibility implements DesignPattern { 9 | 10 | String[] defaultClasses = {"Handler", "ConcreteHandler1","ConcreteHandler2"}; 11 | String packageName = "com.BehavioralDP.chainOfResponsibility"; 12 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 13 | 14 | public ChainOfResponsibility(int flag)throws IOException{ 15 | logger.info("Executing ChainOfResponsibility()"); 16 | if(flag == 1) { 17 | createDesignPattern(defaultClasses, packageName); 18 | } 19 | } 20 | 21 | public JavaFile[] generateCode(String[] classes, String packageName){ 22 | 23 | int i = 0; 24 | 25 | // Handler class declaration 26 | ClassName Handler = ClassName.get("",classes[i]); 27 | MethodSpec handleReq = MethodSpec.methodBuilder("handleRequest") 28 | .addModifiers(Modifier.ABSTRACT) 29 | .returns(TypeName.VOID) 30 | .build(); 31 | TypeSpec handler = TypeSpec.classBuilder(Handler) 32 | .addModifiers(Modifier.ABSTRACT) 33 | .addJavadoc("Handler interface, declares an interface for request handling") 34 | .addField(Handler,"successor",Modifier.PROTECTED) 35 | .addMethod(handleReq) 36 | .addMethod(MethodSpec.methodBuilder("setSuccessor") 37 | .addModifiers(Modifier.PUBLIC) 38 | .returns(TypeName.VOID) 39 | .addParameter(Handler,"successor") 40 | .addStatement("this.$N = $N","successor","successor") 41 | .build()) 42 | .build(); 43 | generatedCode[i] = JavaFile.builder(packageName,handler) 44 | .skipJavaLangImports(true) 45 | .build(); 46 | i += 1; 47 | 48 | // ConcreteHandler1 class declaration 49 | ClassName ConcreteHandler1 = ClassName.get("",classes[i]); 50 | FieldSpec handleReqInv = FieldSpec.builder(Boolean.TYPE,"handleRequestInvoked") 51 | .addModifiers(Modifier.PRIVATE) 52 | .initializer("false") 53 | .build(); 54 | MethodSpec isHandleReqInv = MethodSpec.methodBuilder("isHandleRequestInvoked") 55 | .addModifiers(Modifier.PROTECTED) 56 | .returns(Boolean.TYPE) 57 | .addStatement("return $N",handleReqInv.name) 58 | .build(); 59 | TypeSpec concHandler1 = TypeSpec.classBuilder(ConcreteHandler1) 60 | .superclass(Handler) 61 | .addModifiers(Modifier.PUBLIC) 62 | .addJavadoc("ConcreteHandler1 class, handles the request, can access to the next object in " + 63 | "a chain and forward the request if necessary.") 64 | .addField(handleReqInv) 65 | .addMethod(MethodSpec.methodBuilder(handleReq.name) 66 | .returns(TypeName.VOID) 67 | .addStatement("$N = true",handleReqInv.name) 68 | .addCode("\n") 69 | .addComment("if some condition call handleRequest on successor") 70 | .beginControlFlow("if ($N)",handleReqInv.name) 71 | .addStatement("$N.$N()","successor",handleReq.name) 72 | .endControlFlow() 73 | .build()) 74 | .addMethod(isHandleReqInv) 75 | .build(); 76 | generatedCode[i] = JavaFile.builder(packageName,concHandler1) 77 | .skipJavaLangImports(true) 78 | .build(); 79 | i += 1; 80 | 81 | // ConcreteHandler2 class declaration 82 | ClassName ConcreteHandler2 = ClassName.get("",classes[i]); 83 | TypeSpec concHandler2 = TypeSpec.classBuilder(ConcreteHandler2) 84 | .superclass(Handler) 85 | .addModifiers(Modifier.PUBLIC) 86 | .addJavadoc("ConcreteHandler2 class, handles the request, can access to the " + 87 | "next object in a chain" + 88 | " and forward the request if necessary.") 89 | .addField(handleReqInv) 90 | .addMethod(MethodSpec.methodBuilder(handleReq.name) 91 | .returns(TypeName.VOID) 92 | .addStatement("$N = true",handleReqInv.name) 93 | .build()) 94 | .addMethod(isHandleReqInv) 95 | .build(); 96 | generatedCode[i] = JavaFile.builder(packageName,concHandler2) 97 | .skipJavaLangImports(true) 98 | .build(); 99 | 100 | return generatedCode; 101 | 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/Hw1DesignPatternGenerator.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import com.behavioral.*; 4 | import com.creational.*; 5 | import com.structural.*; 6 | import ch.qos.logback.classic.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.io.IOException; 10 | import java.util.InputMismatchException; 11 | import java.util.Scanner; 12 | 13 | public class Hw1DesignPatternGenerator extends DesignPatternGenerator { 14 | 15 | //Define a static logger variable so that it references the Logger instance 16 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Hw1DesignPatternGenerator.class); 17 | 18 | private static Hw1DesignPatternGenerator instance; 19 | 20 | private Hw1DesignPatternGenerator(){ 21 | logger.info("Executing constructor Hw1DesignPatternGenerator()"); 22 | } 23 | 24 | public static Hw1DesignPatternGenerator getInstance(){ 25 | logger.info("Creating instance of {}",Hw1DesignPatternGenerator.class.getSimpleName()); 26 | 27 | if (instance == null) { 28 | instance = new Hw1DesignPatternGenerator(); 29 | } 30 | return instance; 31 | } 32 | 33 | @Override 34 | protected void generateDesignPattern() throws IOException { 35 | logger.info("Entering generateDesignPattern()"); 36 | Scanner sc = new Scanner(System.in); 37 | char c; 38 | do { 39 | displayDesignPatterns(); 40 | designPatternFactory(); 41 | 42 | System.out.print("\nDo you want to try again ? "); 43 | c = sc.next().toLowerCase().charAt(0); 44 | if(c != 'y') { 45 | System.out.println("\nExiting . . ."); 46 | } 47 | }while(c == 'y'); 48 | } 49 | 50 | @Override 51 | protected void designPatternFactory() throws IOException { 52 | logger.info("Executing designPatternFactory()"); 53 | int mode = 1; 54 | 55 | Scanner sc = new Scanner(System.in); 56 | int choice = 0 ; 57 | try { 58 | System.out.print("\nEnter your choice of design pattern(1 to 23): "); 59 | choice = sc.nextInt(); 60 | } 61 | catch (InputMismatchException e){ 62 | logger.error("Exception {} encountered ", InputMismatchException.class.getSimpleName()); 63 | // System.out.println(e); 64 | System.out.println("\nInvalid choice! Enter a valid numeric value. Try Again! \n"); 65 | } 66 | logger.info("Passing {} to chooseDesignPattern()",choice); 67 | 68 | chooseDesignPattern(choice, mode); 69 | } 70 | 71 | @Override 72 | protected void displayDesignPatterns(){ 73 | logger.info("Entering displayDesignPatterns()"); 74 | 75 | System.out.println("\nThe design patterns available are: "); 76 | 77 | for (int i = 0; i < 7; i++) { 78 | System.out.print((i+1)+"-" + designPatterns[i] + "\t "); 79 | } 80 | System.out.println("\n"); 81 | for (int i = 7; i < 14; i++) { 82 | System.out.print((i+1)+"-" + designPatterns[i] + "\t "); 83 | } 84 | System.out.println("\n"); 85 | for (int i = 15; i < 23; i++) { 86 | System.out.print((i+1)+"-" + designPatterns[i] + "\t "); 87 | } 88 | System.out.println("\n"); 89 | } 90 | 91 | protected DesignPattern chooseDesignPattern(int choice, int mode) throws IOException { 92 | logger.info("Entering chooseDesignPattern()"); 93 | DesignPattern dp = null; 94 | switch (choice) { 95 | case 1 : dp = new Singleton(mode); break; 96 | case 2 : dp = new AbstractFactory(mode); break; 97 | case 3 : dp = new Builder(mode); break; 98 | case 4 : dp = new FactoryMethod(mode); break; 99 | case 5 : dp = new Prototype(mode); break; 100 | case 6 : dp = new Adapter(mode); break; 101 | case 7 : dp = new Bridge(mode); break; 102 | case 8 : dp = new Composite(mode); break; 103 | case 9 : dp = new Decorator(mode); break; 104 | case 10 : System.out.println("Facade"); break; 105 | case 11 : dp = new Flyweight(mode); break; 106 | case 12 : dp = new Proxy(mode); break; 107 | case 13 : dp = new ChainOfResponsibility(mode); break; 108 | case 14 : dp = new Command(mode); break; 109 | case 15 : dp = new Interpreter(mode); break; 110 | case 16 : dp = new Iterator(mode); break; 111 | case 17 : dp = new Mediator(mode); break; 112 | case 18 : dp = new Memento(mode); break; 113 | case 19 : dp = new Observer(mode); break; 114 | case 20 : dp = new State(mode); break; 115 | case 21 : dp = new Strategy(mode); break; 116 | case 22 : dp = new Visitor(mode); break; 117 | case 23 : dp = new TemplateMethod(mode); break; 118 | default : System.out.println("\nInvalid Choice! Input a choice from 1 to 23. Try again! \n"); 119 | 120 | logger.info("Exiting chooseDesignPattern()"); 121 | } 122 | return dp; 123 | 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/com/DesignPattern.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import com.squareup.javapoet.JavaFile; 4 | import ch.qos.logback.classic.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.util.Scanner; 9 | 10 | public interface DesignPattern { 11 | 12 | //Define a static logger variable so that it references the Logger instance 13 | Logger logger = (Logger) LoggerFactory.getLogger(DesignPattern.class); 14 | 15 | // to display all available design pattern that can be generated 16 | default void displayClassNames(String[] classes){ 17 | 18 | for (String name: classes) { 19 | System.out.print(name + " \t "); 20 | } 21 | } 22 | 23 | // to set custom class names from user input 24 | default String[] setClassNames(String[] oldClasses){ 25 | 26 | Scanner sc = new Scanner(System.in); 27 | int n = oldClasses.length; 28 | String[] newClasses = new String[n]; 29 | System.out.print("\n\nDo you want custom class names(y/n) ? "); 30 | char c ; 31 | // do-while loop to make user inputs y or n 32 | do { 33 | c = sc.next().toLowerCase().charAt(0); 34 | if (c == 'y'){ 35 | for (int i = 0; i< n; i++) { 36 | boolean check; 37 | // do-while loop to ask for input again if user inputs invalid class name 38 | do { 39 | System.out.print("\nEnter class name for "+ oldClasses[i]+" : "); 40 | // get class names from user 41 | newClasses[i] = sc.next(); 42 | // checking if classname starts with a letter or not 43 | check = Character.isAlphabetic(newClasses[i].toLowerCase().charAt(0)); 44 | logger.info("Checking if classname entered is valid"); 45 | if(!check){ 46 | logger.error("Invalid classname"); 47 | System.out.println("\nInvalid class name! Class name must start with a letter."); 48 | System.out.print("Enter the class name again: \n"); 49 | } 50 | }while (!check); 51 | } 52 | }else if (c == 'n'){ 53 | // default class names set as new class names 54 | newClasses = oldClasses; 55 | } 56 | else { 57 | logger.error("Invalid input"); 58 | System.out.print("\nInvalid choice! Enter only y/n. Please try again: "); 59 | } 60 | 61 | }while(c != 'y'&& c!='n'); 62 | logger.info("Returning class names to createDesignPattern()"); 63 | return newClasses; 64 | } 65 | 66 | // to set custom package name from user input 67 | default String setPackageName(String defaultPckgName){ 68 | 69 | Scanner sc = new Scanner(System.in); 70 | String pckgName = null; 71 | System.out.print("\nDo you want custom package name for generated design pattern java files(y/n) ? "); 72 | char c ; 73 | // do-while loop to make user inputs y or n 74 | do { 75 | c = sc.next().toLowerCase().charAt(0); 76 | if (c == 'y'){ 77 | System.out.print("\nPlease enter the package name: "); 78 | // get package name from user 79 | pckgName = sc.next(); 80 | System.out.println("\n"); 81 | } else if (c == 'n'){ 82 | pckgName = defaultPckgName; 83 | } 84 | else { 85 | logger.error("Invalid input"); 86 | System.out.print("\nInvalid choice! Enter only y/n. Please try again: "); 87 | } 88 | 89 | }while(c != 'y'&& c!='n'); 90 | logger.info("Returning package name to createDesignPattern()"); 91 | return pckgName; 92 | } 93 | 94 | // method implementation in child class which implements this interface 95 | JavaFile[] generateCode(String[] classes, String packageName); 96 | 97 | //method to write generated code as .java file 98 | default void writeJavaFiles(JavaFile[] files) throws IOException { 99 | for(JavaFile file : files){ 100 | // System.out.println(file); 101 | file.writeTo(new File("outputs")); 102 | } 103 | logger.info("Written java code into output files "); 104 | } 105 | 106 | default void createDesignPattern(String[] oldClasses, String oldPackageName) throws IOException { 107 | logger.info("Entering createDesignPattern()"); 108 | 109 | System.out.println("\nThe Design pattern will contain following classes: "); 110 | displayClassNames(oldClasses); 111 | String[] newClasses = setClassNames(oldClasses); 112 | String pckgName = setPackageName(oldPackageName); 113 | 114 | logger.info("Generating java code using JavaPoet"); 115 | JavaFile[] code = generateCode(newClasses,pckgName); 116 | 117 | logger.info("Writing java code into output files"); 118 | writeJavaFiles(code); 119 | System.out.println("\nThe following java files have been created: "); 120 | displayClassNames(newClasses); 121 | System.out.println("\n\nAt package name: " + pckgName); 122 | System.out.println("\n"); 123 | 124 | logger.info("Exiting createDesignPattern()"); 125 | 126 | } 127 | 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/Memento.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class Memento implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Memento.class); 15 | 16 | 17 | String[] defaultClasses = {"Memento", "Caretaker","Originator"}; 18 | String packageName = "com.BehavioralDP.memento"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public Memento(int flag)throws IOException{ 22 | logger.info("Executing Memento()"); 23 | if(flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | public JavaFile[] generateCode(String[] classes, String packageName){ 29 | logger.info("Executing generateCode()"); 30 | 31 | int i = 0; 32 | 33 | // Memento class declaration 34 | ClassName Memento = ClassName.get("",classes[i]); 35 | FieldSpec state = FieldSpec.builder(int.class,"state") 36 | .addModifiers(Modifier.PRIVATE) 37 | .build(); 38 | MethodSpec getstate = MethodSpec.methodBuilder("getState") 39 | .addModifiers(Modifier.PUBLIC) 40 | .returns(int.class) 41 | .addStatement("return $N", "state") 42 | .build(); 43 | TypeSpec memento = TypeSpec.classBuilder(Memento) 44 | .addModifiers(Modifier.PUBLIC) 45 | .addJavadoc("Memento stores internal state of the Originator object, protects against\n" + 46 | "access by objects other than the Originator.") 47 | .addField(state) 48 | .addMethod(MethodSpec.constructorBuilder() 49 | .addModifiers(Modifier.PUBLIC) 50 | .addParameter(int.class,"state") 51 | .addStatement("this.$N = $N",state.name,"state") 52 | .build()) 53 | .addMethod(getstate) 54 | .build(); 55 | generatedCode[i] = JavaFile.builder(packageName, memento) 56 | .skipJavaLangImports(true) 57 | .build(); 58 | i += 1; 59 | 60 | // Caretaker class declaration 61 | ClassName Caretaker = ClassName.get("",classes[i]); 62 | TypeSpec caretaker = TypeSpec.classBuilder(Caretaker) 63 | .addModifiers(Modifier.PUBLIC) 64 | .addJavadoc("Caretaker responsible for the Memento's safekeeping.") 65 | .addField(Memento, "memento",Modifier.PRIVATE) 66 | .addMethod(MethodSpec.methodBuilder("getMemento") 67 | .addModifiers(Modifier.PUBLIC) 68 | .returns(Memento) 69 | .addStatement("return $N","memento") 70 | .build()) 71 | .addMethod(MethodSpec.methodBuilder("setMemento") 72 | .addModifiers(Modifier.PUBLIC) 73 | .returns(TypeName.VOID) 74 | .addParameter(Memento, "memento") 75 | .addStatement("this.$N = memento","memento") 76 | .build()) 77 | .build(); 78 | generatedCode[i] = JavaFile.builder(packageName,caretaker) 79 | .skipJavaLangImports(true) 80 | .build(); 81 | i += 1; 82 | 83 | // Originator class declaration 84 | ClassName Originator = ClassName.get("",classes[i]); 85 | TypeSpec originator = TypeSpec.classBuilder(Originator) 86 | .addModifiers(Modifier.PUBLIC) 87 | .addJavadoc("Originator creates a Memento containing a snapshot of its current internal\n" + 88 | "state. Originator use Memento to restore its internal state.") 89 | .addField(state) 90 | .addMethod(MethodSpec.methodBuilder("setMemento") 91 | .addModifiers(Modifier.PUBLIC) 92 | .returns(TypeName.VOID) 93 | .addParameter(Memento, "memento") 94 | .addStatement("this.$N = $N.$N()",state.name,"memento",getstate.name) 95 | .build()) 96 | .addMethod(MethodSpec.methodBuilder("createMemento") 97 | .addModifiers(Modifier.PUBLIC) 98 | .returns(Memento) 99 | .addStatement("return new $T(this.$N)",Memento,state.name) 100 | .build()) 101 | .addMethod(getstate) 102 | .addMethod(MethodSpec.methodBuilder("setState") 103 | .addModifiers(Modifier.PUBLIC) 104 | .returns(TypeName.VOID) 105 | .addParameter(int.class, "state") 106 | .addStatement("this.$N = $N",state.name,"state") 107 | .build()) 108 | .build(); 109 | generatedCode[i] = JavaFile.builder(packageName,originator) 110 | .skipJavaLangImports(true) 111 | .build(); 112 | 113 | logger.info("Returning generated java code to be written in files"); 114 | 115 | return generatedCode; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/Command.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | import java.io.IOException; 5 | import com.DesignPattern; 6 | import ch.qos.logback.classic.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import javax.lang.model.element.Modifier; 10 | 11 | public class Command implements DesignPattern { 12 | //Define a static logger variable so that it references the Logger instance 13 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Command.class); 14 | 15 | 16 | String[] defaultClasses = {"Command", "Invoker","Receiver","ConcreteCommand"}; 17 | String packageName = "com.BehavioralDP.command"; 18 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 19 | 20 | public Command(int flag)throws IOException{ 21 | logger.info("Executing Command()"); 22 | if(flag == 1) { 23 | createDesignPattern(defaultClasses, packageName); 24 | } } 25 | 26 | public JavaFile[] generateCode(String[] classes, String packageName){ 27 | logger.info("Executing generateCode()"); 28 | 29 | int i = 0; 30 | 31 | // Command interface declaration 32 | ClassName Command = ClassName.get("",classes[i]); 33 | MethodSpec execute = MethodSpec.methodBuilder("execute") 34 | .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC) 35 | .returns(TypeName.VOID) 36 | .build(); 37 | TypeSpec command = TypeSpec.interfaceBuilder(Command) 38 | .addModifiers(Modifier.PUBLIC) 39 | .addJavadoc("Command interface, declares an interface for executing an operation") 40 | .addMethod(execute) 41 | .build(); 42 | generatedCode[i] = JavaFile.builder(packageName,command) 43 | .skipJavaLangImports(true) 44 | .build(); 45 | i += 1; 46 | 47 | // Invoker class declaration 48 | ClassName Invoker = ClassName.get("",classes[i]); 49 | TypeSpec invoker = TypeSpec.classBuilder(Invoker) 50 | .addModifiers(Modifier.PUBLIC) 51 | .addJavadoc("Invoker class, asks the command to carry out the request") 52 | .addField(Command, "command", Modifier.PRIVATE) 53 | .addMethod(MethodSpec.constructorBuilder() 54 | .addModifiers(Modifier.PUBLIC) 55 | .addParameter(Command,"command") 56 | .addStatement("this.$N = command", "command") 57 | .build()) 58 | .addMethod(MethodSpec.methodBuilder(execute.name) 59 | .addModifiers(Modifier.PUBLIC) 60 | .returns(TypeName.VOID) 61 | .addStatement("$N.$N()","command", execute.name) 62 | .build()) 63 | .build(); 64 | generatedCode[i] = JavaFile.builder(packageName,invoker) 65 | .skipJavaLangImports(true) 66 | .build(); 67 | i += 1; 68 | 69 | // Receiver class declaration 70 | ClassName Receiver = ClassName.get("",classes[i]); 71 | FieldSpec opPerf = FieldSpec.builder(Boolean.TYPE,"operationPerfomed") 72 | .addModifiers(Modifier.PRIVATE) 73 | .initializer("false") 74 | .build(); 75 | TypeSpec receiver = TypeSpec.classBuilder(Receiver) 76 | .addModifiers(Modifier.PUBLIC) 77 | .addJavadoc("Receiver class, knows how to perform the operations associated with carrying\n" + 78 | "out a request") 79 | .addField(opPerf) 80 | .addMethod(MethodSpec.methodBuilder("action") 81 | .addModifiers(Modifier.PUBLIC) 82 | .returns(TypeName.VOID) 83 | .addStatement("$N = true",opPerf.name) 84 | .build()) 85 | .addMethod(MethodSpec.methodBuilder("isOperationPerfomed") 86 | .addModifiers(Modifier.PROTECTED) 87 | .returns(TypeName.BOOLEAN) 88 | .addStatement("return $N",opPerf.name) 89 | .build()) 90 | .build(); 91 | generatedCode[i] = JavaFile.builder(packageName,receiver) 92 | .skipJavaLangImports(true) 93 | .build(); 94 | i += 1; 95 | 96 | // ConcreteCommand class declaration 97 | ClassName ConcreteCommand = ClassName.get("",classes[i]); 98 | TypeSpec concreteCommand = TypeSpec.classBuilder(ConcreteCommand) 99 | .addSuperinterface(Command) 100 | .addModifiers(Modifier.PUBLIC) 101 | .addJavadoc("ConcreteCommand class, defines a binding between a Receiver object and an\n" + 102 | "operation") 103 | .addField(Receiver, "receiver",Modifier.PRIVATE) 104 | .addMethod(MethodSpec.constructorBuilder() 105 | .addModifiers(Modifier.PUBLIC) 106 | .addParameter(Receiver, "receiver") 107 | .addStatement("this.$N = receiver","receiver") 108 | .build()) 109 | .addMethod(MethodSpec.methodBuilder(execute.name) 110 | .addModifiers(Modifier.PUBLIC) 111 | .returns(TypeName.VOID) 112 | .addStatement("this.$N.$N()","receiver","action") 113 | .build()) 114 | .build(); 115 | generatedCode[i] = JavaFile.builder(packageName,concreteCommand) 116 | .skipJavaLangImports(true) 117 | .build(); 118 | 119 | logger.info("Returning generated java code to be written in files"); 120 | 121 | return generatedCode; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/structural/Bridge.java: -------------------------------------------------------------------------------- 1 | package com.structural; 2 | 3 | import com.squareup.javapoet.*; 4 | import javax.lang.model.element.Modifier; 5 | import java.io.IOException; 6 | import com.DesignPattern; 7 | import ch.qos.logback.classic.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class Bridge implements DesignPattern { 11 | 12 | //Define a static logger variable so that it references the Logger instance 13 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Bridge.class); 14 | 15 | 16 | String[] defaultClasses = {"Implementor", "ConcreteImplementorA","ConcreteImplementorB","Abstraction","RefinedAbstraction"}; 17 | String packageName = "com.StructuralDP.bridge"; 18 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 19 | 20 | public Bridge(int flag)throws IOException{ 21 | logger.info("Executing Bridge()"); 22 | if(flag == 1) { 23 | createDesignPattern(defaultClasses, packageName); 24 | } 25 | } 26 | 27 | public JavaFile[] generateCode(String[] classes, String packageName){ 28 | int i = 0 ; 29 | logger.info("Executing generateCode()"); 30 | 31 | 32 | // Implementor interface declaration 33 | ClassName Implementor = ClassName.get("",classes[i]); 34 | MethodSpec implementation = MethodSpec.methodBuilder("implementation") 35 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(String.class) 36 | .build(); 37 | TypeSpec implementor = TypeSpec.interfaceBuilder(Implementor) 38 | .addModifiers(Modifier.PUBLIC) 39 | .addJavadoc("Implementor, defines interface for implementation") 40 | .addMethod(implementation) 41 | .build(); 42 | generatedCode[i] = JavaFile.builder(packageName,implementor).skipJavaLangImports(true).build(); 43 | i += 1; 44 | 45 | // ConcreteImplementorA class declaration 46 | ClassName ConcreteImplementorA = ClassName.get("",classes[i]); 47 | TypeSpec concImplementorA = TypeSpec.classBuilder(ConcreteImplementorA) 48 | .addModifiers(Modifier.PUBLIC) 49 | .addSuperinterface(Implementor) 50 | .addJavadoc("ConcreteImplementorA, implements Implementor interface") 51 | .addMethod(MethodSpec.methodBuilder(implementation.name) 52 | .addModifiers(Modifier.PUBLIC).returns(String.class) 53 | .addStatement("return this.getClass().getName()") 54 | .build()) 55 | .build(); 56 | generatedCode[i] = JavaFile.builder(packageName,concImplementorA).skipJavaLangImports(true).build(); 57 | i += 1; 58 | 59 | // ConcreteImplementorB class declaration 60 | ClassName ConcreteImplementorB = ClassName.get("",classes[i]); 61 | TypeSpec concImplementorB = TypeSpec.classBuilder(ConcreteImplementorB) 62 | .addModifiers(Modifier.PUBLIC) 63 | .addSuperinterface(Implementor) 64 | .addJavadoc("ConcreteImplementorB, implements Implementor interface") 65 | .addMethod(MethodSpec.methodBuilder(implementation.name) 66 | .addModifiers(Modifier.PUBLIC).returns(String.class) 67 | .addStatement("return this.getClass().getName()") 68 | .build()) 69 | .build(); 70 | generatedCode[i] = JavaFile.builder(packageName,concImplementorB).skipJavaLangImports(true).build(); 71 | i += 1; 72 | 73 | // Abstraction abstract class declaration 74 | ClassName Abstraction = ClassName.get("",classes[i]); 75 | FieldSpec implement = FieldSpec.builder(Implementor,"implementor",Modifier.PROTECTED).build(); 76 | MethodSpec oper = MethodSpec.methodBuilder("operation") 77 | .addModifiers(Modifier.ABSTRACT).returns(String.class) 78 | .build(); 79 | TypeSpec abstraction = TypeSpec.classBuilder(Abstraction) 80 | .addModifiers(Modifier.ABSTRACT) 81 | .addJavadoc("Abstraction, defines abstraction interface, maintains a reference to object of type Implementor") 82 | .addField(implement) 83 | .addMethod(MethodSpec.constructorBuilder() 84 | .addModifiers(Modifier.PUBLIC) 85 | .addParameter(Implementor,"implementor") 86 | .addStatement("this.$N = implementor",implement.name) 87 | .build()) 88 | .addMethod(oper) 89 | .build(); 90 | generatedCode[i] = JavaFile.builder(packageName,abstraction).skipJavaLangImports(true).build(); 91 | i += 1; 92 | 93 | // RefinedAbstraction class declaration 94 | ClassName RefinedAbstraction = ClassName.get("",classes[i]); 95 | TypeSpec refAbstraction = TypeSpec.classBuilder(RefinedAbstraction) 96 | .addModifiers(Modifier.PUBLIC) 97 | .superclass(Abstraction) 98 | .addJavadoc("Refined Abstraction, extends the interface defined by Abstraction") 99 | .addMethod(MethodSpec.constructorBuilder() 100 | .addModifiers(Modifier.PUBLIC) 101 | .addParameter(Implementor,"implementor") 102 | .addStatement("super(implementor)",implement.name) 103 | .build()) 104 | .addMethod(MethodSpec.methodBuilder("operation") 105 | .addModifiers(Modifier.PUBLIC).returns(String.class) 106 | .addStatement("return this.$N.$N()",implement.name,implementation.name) 107 | .build()) 108 | .build(); 109 | generatedCode[i] = JavaFile.builder(packageName,refAbstraction).skipJavaLangImports(true).build(); 110 | 111 | logger.info("Returning generated java code to be written in files"); 112 | 113 | return generatedCode; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/Strategy.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class Strategy implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Strategy.class); 15 | 16 | 17 | String[] defaultClasses = {"Strategy", "Context","ConcreteStrategyA","ConcreteStrategyB","ConcreteStrategyC"}; 18 | String packageName = "com.BehavioralDP.strategy"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public Strategy(int flag)throws IOException{ 22 | logger.info("Executing Strategy()"); 23 | if(flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | public JavaFile[] generateCode(String[] classes, String packageName){ 29 | logger.info("Executing generateCode()"); 30 | 31 | int i = 0; 32 | 33 | // Strategy interface declaration 34 | ClassName Strategy = ClassName.get("",classes[i]); 35 | MethodSpec algoInterface = MethodSpec.methodBuilder("algorithmInterface") 36 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT) 37 | .returns(String.class) 38 | .build(); 39 | TypeSpec strategy = TypeSpec.interfaceBuilder(Strategy) 40 | .addModifiers(Modifier.PUBLIC) 41 | .addJavadoc("Declares an interface common to all supported algorithms. Context uses this interface to call the algorithm\n" + 42 | "defined by a ConcreteStrategy.") 43 | .addMethod(algoInterface) 44 | .build(); 45 | generatedCode[i] = JavaFile.builder(packageName,strategy) 46 | .skipJavaLangImports(true) 47 | .build(); 48 | i += 1; 49 | 50 | // Context class declaration 51 | ClassName Context = ClassName.get("",classes[i]); 52 | FieldSpec strategyField = FieldSpec.builder(Strategy,"strategy",Modifier.PRIVATE).build(); 53 | TypeSpec context = TypeSpec.classBuilder(Context) 54 | .addModifiers(Modifier.PUBLIC) 55 | .addJavadoc(" Maintains a reference to a Strategy object. Invokes algorithm implemented in ConcreteStrategy.") 56 | .addField(strategyField) 57 | .addMethod(MethodSpec.constructorBuilder() 58 | .addModifiers(Modifier.PUBLIC) 59 | .addParameter(Strategy, "strategy") 60 | .addStatement("this.$N = strategy",strategyField.name) 61 | .build()) 62 | .addMethod(MethodSpec.methodBuilder("contextInterface") 63 | .addModifiers(Modifier.PROTECTED).returns(String.class) 64 | .addStatement("return this.$N.$N()",strategyField.name,algoInterface.name) 65 | .build()) 66 | .build(); 67 | generatedCode[i] = JavaFile.builder(packageName,context) 68 | .skipJavaLangImports(true) 69 | .build(); 70 | i += 1; 71 | 72 | // ConcreteStrategyA class declaration 73 | ClassName ConcreteStrategyA = ClassName.get("",classes[i]); 74 | TypeSpec concStratA = TypeSpec.classBuilder(ConcreteStrategyA) 75 | .addSuperinterface(Strategy) 76 | .addModifiers(Modifier.PUBLIC) 77 | .addJavadoc("Implements the algorithm defined in Strategy interface.") 78 | .addMethod(MethodSpec.methodBuilder(algoInterface.name) 79 | .addModifiers(Modifier.PUBLIC) 80 | .returns(String.class) 81 | .addStatement("return $S","Inside ConcreteStrategyA to invoke Algorithm A") 82 | .build()) 83 | .build(); 84 | generatedCode[i] = JavaFile.builder(packageName,concStratA) 85 | .skipJavaLangImports(true) 86 | .build(); 87 | i += 1; 88 | 89 | // ConcreteStrategyB class declaration 90 | ClassName ConcreteStrategyB = ClassName.get("",classes[i]); 91 | TypeSpec concStratB = TypeSpec.classBuilder(ConcreteStrategyB) 92 | .addSuperinterface(Strategy) 93 | .addModifiers(Modifier.PUBLIC) 94 | .addJavadoc("Implements the algorithm defined in Strategy interface.") 95 | .addMethod(MethodSpec.methodBuilder(algoInterface.name) 96 | .addModifiers(Modifier.PUBLIC) 97 | .returns(String.class) 98 | .addStatement("return $S","Inside ConcreteStrategyB to invoke Algorithm B") 99 | .build()) 100 | .build(); 101 | generatedCode[i] = JavaFile.builder(packageName,concStratB) 102 | .skipJavaLangImports(true) 103 | .build(); 104 | i += 1; 105 | 106 | // ConcreteStrategyC class declaration 107 | ClassName ConcreteStrategyC = ClassName.get("",classes[i]); 108 | TypeSpec concStratC = TypeSpec.classBuilder(ConcreteStrategyC) 109 | .addSuperinterface(Strategy) 110 | .addModifiers(Modifier.PUBLIC) 111 | .addJavadoc("Implements the algorithm defined in Strategy interface.") 112 | .addMethod(MethodSpec.methodBuilder(algoInterface.name) 113 | .addModifiers(Modifier.PUBLIC) 114 | .returns(String.class) 115 | .addStatement("return $S","Inside ConcreteStrategyC to invoke Algorithm C") 116 | .build()) 117 | .build(); 118 | generatedCode[i] = JavaFile.builder(packageName,concStratC) 119 | .skipJavaLangImports(true) 120 | .build(); 121 | 122 | logger.info("Returning generated java code to be written in files"); 123 | 124 | return generatedCode; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/structural/Decorator.java: -------------------------------------------------------------------------------- 1 | package com.structural; 2 | 3 | import com.squareup.javapoet.*; 4 | import javax.lang.model.element.Modifier; 5 | import java.io.IOException; 6 | import com.DesignPattern; 7 | import ch.qos.logback.classic.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class Decorator implements DesignPattern { 11 | //Define a static logger variable so that it references the Logger instance 12 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Decorator.class); 13 | 14 | String[] defaultClasses = {"Component","ConcreteComponent","Decorator","ConcreteDecoratorA","ConcreteDecoratorB"}; 15 | String packageName = "com.StructuralDP.decorator"; 16 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 17 | 18 | public Decorator(int flag)throws IOException{ 19 | logger.info("Executing Decorator()"); 20 | if(flag == 1) { 21 | createDesignPattern(defaultClasses, packageName); 22 | } 23 | } 24 | 25 | public JavaFile[] generateCode(String[] classes, String packageName){ 26 | int i = 0; 27 | logger.info("Executing generateCode()"); 28 | 29 | // Component interface declaration 30 | ClassName Component = ClassName.get("",classes[i]); 31 | MethodSpec oper = MethodSpec.methodBuilder("operation") 32 | .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC).returns(TypeName.VOID) 33 | .build(); 34 | TypeSpec component = TypeSpec.interfaceBuilder(Component) 35 | .addModifiers(Modifier.PUBLIC) 36 | .addJavadoc("Component, defines interface for new features which will be added dynamically") 37 | .addMethod(oper) 38 | .build(); 39 | generatedCode[i] = JavaFile.builder(packageName,component) 40 | .skipJavaLangImports(true) 41 | .build(); 42 | i += 1; 43 | 44 | // ConcreteComponent class declaration 45 | ClassName ConcreteComponent = ClassName.get("",classes[i]); 46 | TypeSpec concComponent = TypeSpec.classBuilder(ConcreteComponent) 47 | .addModifiers(Modifier.PUBLIC) 48 | .addSuperinterface(Component) 49 | .addJavadoc("ConcreteComponent, define object where new features can be added") 50 | .addMethod(MethodSpec.methodBuilder(oper.name) 51 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 52 | .build()) 53 | .build(); 54 | generatedCode[i] = JavaFile.builder(packageName,concComponent) 55 | .skipJavaLangImports(true) 56 | .build(); 57 | i += 1; 58 | 59 | // Decorator abstract class declaration 60 | ClassName Decorator = ClassName.get("",classes[i]); 61 | FieldSpec compo = FieldSpec.builder(Component, "component",Modifier.PROTECTED).build(); 62 | TypeSpec decorator = TypeSpec.classBuilder(Decorator) 63 | .addModifiers(Modifier.ABSTRACT) 64 | .addSuperinterface(Component) 65 | .addJavadoc("Decorator, keep reference to Component object") 66 | .addField(compo) 67 | .addMethod(MethodSpec.methodBuilder(oper.name) 68 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.VOID) 69 | .build()) 70 | .addMethod(MethodSpec.methodBuilder("setComponent") 71 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 72 | .addParameter(Component, "component") 73 | .addStatement("this.$N = component",compo.name) 74 | .build()) 75 | .build(); 76 | generatedCode[i] = JavaFile.builder(packageName,decorator) 77 | .skipJavaLangImports(true) 78 | .build(); 79 | i += 1; 80 | 81 | // ConcreteDecoratorA class declaration 82 | ClassName ConcreteDecoratorA = ClassName.get("",classes[i]); 83 | FieldSpec state = FieldSpec.builder(Boolean.TYPE, "state",Modifier.PRIVATE).build(); 84 | TypeSpec concDecoA = TypeSpec.classBuilder(ConcreteDecoratorA) 85 | .addModifiers(Modifier.PUBLIC) 86 | .superclass(Decorator) 87 | .addJavadoc("ConcreteDecoratorA, add features to component") 88 | .addField(state) 89 | .addMethod(MethodSpec.methodBuilder(oper.name) 90 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 91 | .addStatement("$N = true",state.name) 92 | .addStatement("this.$N.$N()",compo.name,oper.name) 93 | .build()) 94 | .addMethod(MethodSpec.methodBuilder("isState") 95 | .addModifiers(Modifier.PUBLIC).returns(TypeName.BOOLEAN) 96 | .addStatement("return $N",state.name) 97 | .build()) 98 | .build(); 99 | generatedCode[i] = JavaFile.builder(packageName,concDecoA) 100 | .skipJavaLangImports(true) 101 | .build(); 102 | i += 1; 103 | 104 | // ConcreteDecoratorB class declaration 105 | ClassName ConcreteDecoratorB = ClassName.get("",classes[i]); 106 | FieldSpec behMethInvok = FieldSpec.builder(Boolean.TYPE, "behaviorMethodInvoked",Modifier.PRIVATE) 107 | .initializer("false").build(); 108 | MethodSpec addBehav = MethodSpec.methodBuilder("addedBehavior") 109 | .addModifiers(Modifier.PRIVATE).returns(TypeName.VOID) 110 | .addStatement("$N = true", behMethInvok.name) 111 | .build(); 112 | TypeSpec concDecoB = TypeSpec.classBuilder(ConcreteDecoratorB) 113 | .addModifiers(Modifier.PUBLIC) 114 | .superclass(Decorator) 115 | .addJavadoc("ConcreteDecoratorB, add features to component") 116 | .addField(behMethInvok) 117 | .addMethod(MethodSpec.methodBuilder(oper.name) 118 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 119 | .addStatement("this.$N.$N()",compo.name,oper.name) 120 | .addStatement("$N()",addBehav.name) 121 | .build()) 122 | .addMethod(addBehav) 123 | .addMethod(MethodSpec.methodBuilder("isBehaviorMethodInvoked") 124 | .addModifiers(Modifier.PROTECTED).returns(TypeName.BOOLEAN) 125 | .addStatement("return $N", behMethInvok.name) 126 | .build()) 127 | .build(); 128 | generatedCode[i] = JavaFile.builder(packageName,concDecoB) 129 | .skipJavaLangImports(true) 130 | .build(); 131 | 132 | logger.info("Returning generated java code to be written in files"); 133 | 134 | return generatedCode; 135 | 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/Observer.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class Observer implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Observer.class); 15 | 16 | 17 | String[] defaultClasses = {"Observer", "Subject","ConcreteSubject","ConcreteObserver"}; 18 | String packageName = "com.BehavioralDP.observer"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public Observer(int flag)throws IOException{ 22 | logger.info("Executing Observer()"); 23 | if(flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | public JavaFile[] generateCode(String[] classes, String packageName){ 29 | logger.info("Executing generateCode()"); 30 | 31 | int i = 0; 32 | 33 | // Observer interface declaration 34 | ClassName Observer = ClassName.get("",classes[i]); 35 | MethodSpec update = MethodSpec.methodBuilder("update") 36 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.VOID) 37 | .build(); 38 | TypeSpec component = TypeSpec.interfaceBuilder(Observer) 39 | .addModifiers(Modifier.PUBLIC) 40 | .addJavadoc("Observer defines an updating interface for objects that should be notified of changes in a subject.") 41 | .addMethod(update) 42 | .build(); 43 | generatedCode[i] = JavaFile.builder(packageName,component) 44 | .skipJavaLangImports(true) 45 | .build(); 46 | i += 1; 47 | 48 | // Subject class declaration 49 | ClassName Subject = ClassName.get("",classes[i]); 50 | ClassName list = ClassName.get("java.util", "List"); 51 | ClassName arrayList = ClassName.get("java.util", "ArrayList"); 52 | ClassName Iterator = ClassName.get("java.util","Iterator"); 53 | TypeName listOfObservers = ParameterizedTypeName.get(list,Observer); 54 | 55 | FieldSpec obs = FieldSpec.builder(listOfObservers,"observers",Modifier.PRIVATE) 56 | .initializer("new $T<$T>()",arrayList,Observer) 57 | .build(); 58 | MethodSpec notifyObs = MethodSpec.methodBuilder("notifyObservers") 59 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 60 | .beginControlFlow("($T iterator = $N.iterator(); iterator.hasNext();)",Iterator,obs.name) 61 | .addStatement("$T observer = ($T) iterator.next()",Observer,Observer) 62 | .addStatement("observer.$N()",update.name) 63 | .endControlFlow() 64 | .build(); 65 | TypeSpec subject = TypeSpec.classBuilder(Subject) 66 | .addModifiers(Modifier.ABSTRACT) 67 | .addJavadoc("Subject knows its observers. Any number of Observer objects may observe a subject.") 68 | .addField(obs) 69 | .addMethod(MethodSpec.methodBuilder("attach") 70 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 71 | .addParameter(Observer,"observer") 72 | .addStatement("$N.add(observer)",obs.name) 73 | .build()) 74 | .addMethod(MethodSpec.methodBuilder("detach") 75 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 76 | .addParameter(Observer,"observer") 77 | .addStatement("$N.remove(observer)",obs.name) 78 | .build()) 79 | .addMethod(notifyObs) 80 | .build(); 81 | generatedCode[i] = JavaFile.builder(packageName,subject) 82 | .skipJavaLangImports(true).build(); 83 | i += 1; 84 | 85 | // ConcreteSubject class declaration 86 | ClassName ConcreteSubject = ClassName.get("",classes[i]); 87 | FieldSpec state = FieldSpec.builder(int.class,"state",Modifier.PRIVATE).build(); 88 | MethodSpec getstate = MethodSpec.methodBuilder("getState") 89 | .addModifiers(Modifier.PUBLIC).returns(int.class) 90 | .addStatement("return $N", state.name) 91 | .build(); 92 | TypeSpec concSub = TypeSpec.classBuilder(ConcreteSubject) 93 | .superclass(Subject) 94 | .addModifiers(Modifier.PUBLIC) 95 | .addJavadoc("ConcreteSubject stores state of interest to ConcreteObserver objects, sends a notification to its observers\n" + 96 | "when its state changes.") 97 | .addField(state) 98 | .addMethod(getstate) 99 | .addMethod(MethodSpec.methodBuilder("setState") 100 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 101 | .addParameter(int.class, "state") 102 | .addStatement("this.$N = state",state.name) 103 | .addStatement("this.$N()",notifyObs.name) 104 | .build()) 105 | .build(); 106 | generatedCode[i] = JavaFile.builder(packageName,concSub) 107 | .skipJavaLangImports(true).build(); 108 | i += 1; 109 | 110 | // ConcreteObserver class declaration 111 | ClassName ConcreteObserver = ClassName.get("",classes[i]); 112 | FieldSpec obsState = FieldSpec.builder(int.class, "observerState",Modifier.PRIVATE).build(); 113 | FieldSpec subjectField = FieldSpec.builder(ConcreteSubject, "subject",Modifier.PRIVATE).build(); 114 | TypeSpec concObs = TypeSpec.classBuilder(ConcreteObserver) 115 | .addModifiers(Modifier.PUBLIC) 116 | .addSuperinterface(Observer) 117 | .addJavadoc("ConcreteObserver maintains a reference to a ConcreteSubject object, stores\n" + 118 | "state that should stay consistent with the subject's, implements the Observer\n" + 119 | "updating interface to keep its state consistent with the subject's.") 120 | .addField(obsState) 121 | .addField(subjectField) 122 | .addMethod(MethodSpec.constructorBuilder() 123 | .addModifiers(Modifier.PUBLIC) 124 | .addParameter(ConcreteSubject, "subject") 125 | .addStatement("this.$N = subject",subjectField.name) 126 | .build()) 127 | .addMethod(MethodSpec.methodBuilder("update") 128 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 129 | .addStatement("$N = subject.$N()",obsState.name,getstate.name) 130 | .build()) 131 | .addMethod(MethodSpec.methodBuilder("getObserverState") 132 | .addModifiers(Modifier.PROTECTED).returns(int.class) 133 | .addStatement("return $N",obsState.name) 134 | .build()) 135 | .build(); 136 | generatedCode[i] = JavaFile.builder(packageName,concObs) 137 | .skipJavaLangImports(true).build(); 138 | 139 | logger.info("Returning generated java code to be written in files"); 140 | 141 | return generatedCode; 142 | 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/Iterator.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | 12 | public class Iterator implements DesignPattern { 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Iterator.class); 15 | 16 | 17 | String[] defaultClasses = {"Iterator", "Aggregate","ConcreteAggregate","ConcreteIterator"}; 18 | String packageName = "com.BehavioralDP.iterator"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public Iterator(int flag)throws IOException{ 22 | logger.info("Executing Iterator()"); 23 | if(flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | public JavaFile[] generateCode(String[] classes, String packageName){ 29 | logger.info("Executing generateCode()"); 30 | 31 | // Observer interface declaration 32 | ClassName Iterator = ClassName.get("",classes[0]); 33 | ClassName ConcreteIterator = ClassName.get("",classes[3]); 34 | MethodSpec first = MethodSpec.methodBuilder("first") 35 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.OBJECT) 36 | .build(); 37 | MethodSpec next = MethodSpec.methodBuilder("next") 38 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.OBJECT) 39 | .build(); 40 | MethodSpec isDone = MethodSpec.methodBuilder("isDone") 41 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.BOOLEAN) 42 | .build(); 43 | MethodSpec currentItem = MethodSpec.methodBuilder("currentItem") 44 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.OBJECT) 45 | .build(); 46 | TypeSpec iterator = TypeSpec.interfaceBuilder(Iterator) 47 | .addModifiers(Modifier.PUBLIC) 48 | .addJavadoc("Iterator defines an interface for accessing and traversing elements.") 49 | .addMethod(first) 50 | .addMethod(next) 51 | .addMethod(isDone) 52 | .addMethod(currentItem) 53 | .build(); 54 | generatedCode[0] = JavaFile.builder(packageName,iterator) 55 | .skipJavaLangImports(true) 56 | .build(); 57 | 58 | // Aggregate interface declaration 59 | ClassName Aggregate = ClassName.get("",classes[1]); 60 | MethodSpec createIterator = MethodSpec.methodBuilder("createIterator") 61 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(Iterator) 62 | .build(); 63 | TypeSpec aggregate = TypeSpec.interfaceBuilder(Aggregate) 64 | .addModifiers(Modifier.PUBLIC) 65 | .addJavadoc("Aggregate defines an interface for creating an Iterator object.") 66 | .addMethod(createIterator) 67 | .build(); 68 | generatedCode[1] = JavaFile.builder(packageName,aggregate) 69 | .skipJavaLangImports(true) 70 | .build(); 71 | 72 | // ConcreteAggregate class declaration 73 | ClassName ConcreteAggregate = ClassName.get("",classes[2]); 74 | // String[] stringRecords = { "first", "second", "third", "fourth" }; 75 | FieldSpec records = FieldSpec.builder(String[].class,"records",Modifier.FINAL,Modifier.PRIVATE) 76 | .initializer(" { \"first\", \"second\", \"third\", \"fourth\" }") 77 | .build(); 78 | MethodSpec getRecords= MethodSpec.methodBuilder("getRecords") 79 | .addModifiers(Modifier.PROTECTED).returns(String[].class) 80 | .addStatement("return $N", records.name) 81 | .build(); 82 | TypeSpec concreteAggregate = TypeSpec.classBuilder(ConcreteAggregate) 83 | .addSuperinterface(Aggregate) 84 | .addModifiers(Modifier.PUBLIC) 85 | .addJavadoc("ConcreteAggregate implements the Iterator creation interface to return an instance of the proper ConcreteIterator.") 86 | .addField(records) 87 | .addMethod(MethodSpec.methodBuilder(createIterator.name) 88 | .addModifiers(Modifier.PUBLIC).returns(Iterator) 89 | .addStatement("return new $T(this)", ConcreteIterator) 90 | .build()) 91 | .addMethod(getRecords) 92 | .build(); 93 | generatedCode[2] = JavaFile.builder(packageName,concreteAggregate) 94 | .skipJavaLangImports(true).build(); 95 | 96 | 97 | // ConcreteIterator class declaration 98 | FieldSpec concAgg = FieldSpec.builder(ConcreteAggregate,"concreteAggregate",Modifier.PRIVATE) 99 | .build(); 100 | FieldSpec index = FieldSpec.builder(int.class,"index",Modifier.PRIVATE) 101 | .initializer("-1") 102 | .build(); 103 | TypeSpec concreteIterator = TypeSpec.classBuilder(ConcreteIterator) 104 | .addSuperinterface(Iterator) 105 | .addModifiers(Modifier.PUBLIC) 106 | .addJavadoc("ConcreteIterator implements the Iterator interface. Keeps track of the current position in the traversal of the aggregate.") 107 | .addField(concAgg) 108 | .addField(index) 109 | .addMethod(MethodSpec.constructorBuilder() 110 | .addModifiers(Modifier.PUBLIC) 111 | .addParameter(ConcreteAggregate, "concreteAggregate") 112 | .addStatement("this.$N = concreteAggregate",concAgg.name) 113 | .build()) 114 | .addMethod(MethodSpec.methodBuilder(first.name) 115 | .addModifiers(Modifier.PUBLIC).returns(TypeName.OBJECT) 116 | .addStatement("$N = 0",index.name) 117 | .addStatement("return $N.$N()[$N]",concAgg.name,getRecords.name,index.name) 118 | .build()) 119 | .addMethod(MethodSpec.methodBuilder(next.name) 120 | .addModifiers(Modifier.PUBLIC).returns(TypeName.OBJECT) 121 | .addStatement("$N++",index.name) 122 | .addStatement("return $N.$N()[$N]",concAgg.name,getRecords.name,index.name) 123 | .build()) 124 | .addMethod(MethodSpec.methodBuilder(isDone.name) 125 | .addModifiers(Modifier.PUBLIC).returns(TypeName.BOOLEAN) 126 | .beginControlFlow("if ($N.$N().length == ($N + 1))",concAgg.name,getRecords.name,index.name) 127 | .addStatement("return true") 128 | .endControlFlow() 129 | .addStatement("return false") 130 | .build()) 131 | .addMethod(MethodSpec.methodBuilder(currentItem.name) 132 | .addModifiers(Modifier.PUBLIC).returns(TypeName.OBJECT) 133 | .addStatement("return $N.$N()[$N]",concAgg.name,getRecords.name,index.name) 134 | .build()) 135 | .build(); 136 | generatedCode[3] = JavaFile.builder(packageName,concreteIterator) 137 | .skipJavaLangImports(true).build(); 138 | 139 | logger.info("Returning generated java code to be written in files"); 140 | 141 | return generatedCode; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/creational/AbstractFactory.java: -------------------------------------------------------------------------------- 1 | package com.creational; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class AbstractFactory implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(AbstractFactory.class); 15 | 16 | String[] defaultClasses = {"AbstractProductA","ProductA1","ProductA2","AbstractProductB","ProductB1","ProductB2", 17 | "AbstractFactory","ConcreteFactory1","ConcreteFactory2"}; 18 | String packageName = "com.CreationalDP.abstractFactory"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public AbstractFactory(int flag)throws IOException { 22 | logger.info("Executing AbstractFactory()"); 23 | if (flag == 1){ 24 | createDesignPattern(defaultClasses,packageName); 25 | } 26 | } 27 | 28 | @Override 29 | public JavaFile[] generateCode(String[] classes, String packageName){ 30 | logger.info("Executing generateCode()"); 31 | 32 | int i = 0; 33 | // AbstractProductA interface declaration 34 | ClassName AbstractProductA = ClassName.get("",classes[i]); 35 | TypeSpec abstProductA = TypeSpec.interfaceBuilder(AbstractProductA) 36 | .addModifiers(Modifier.PUBLIC) 37 | .addJavadoc("AbstractProductA defines interface for ProductA objects") 38 | .build(); 39 | generatedCode[i] = JavaFile.builder(packageName,abstProductA) 40 | .skipJavaLangImports(true) 41 | .build(); 42 | i += 1; 43 | 44 | // ProductA1 class declaration 45 | ClassName ProductA1 = ClassName.get("",classes[i]); 46 | TypeSpec prodA1 = TypeSpec.classBuilder(ProductA1) 47 | .addModifiers(Modifier.PUBLIC) 48 | .addSuperinterface(AbstractProductA) 49 | .addJavadoc("ProductA1, implements AbstractProductA interface") 50 | .build(); 51 | generatedCode[i] = JavaFile.builder(packageName,prodA1) 52 | .skipJavaLangImports(true) 53 | .build(); 54 | i += 1; 55 | 56 | // ProductA2 class declaration 57 | ClassName ProductA2 = ClassName.get("",classes[i]); 58 | TypeSpec prodA2 = TypeSpec.classBuilder(ProductA2) 59 | .addModifiers(Modifier.PUBLIC) 60 | .addSuperinterface(AbstractProductA) 61 | .addJavadoc("ProductA2, implements AbstractProductA interface") 62 | .build(); 63 | generatedCode[i] = JavaFile.builder(packageName,prodA2) 64 | .skipJavaLangImports(true) 65 | .build(); 66 | i += 1; 67 | 68 | // AbstractProductB interface declaration 69 | ClassName AbstractProductB = ClassName.get("",classes[i]); 70 | TypeSpec abstProductB = TypeSpec.interfaceBuilder(AbstractProductB) 71 | .addModifiers(Modifier.PUBLIC) 72 | .addJavadoc("AbstractProductB defines interface for ProductB objects") 73 | .build(); 74 | generatedCode[i] = JavaFile.builder(packageName,abstProductB) 75 | .skipJavaLangImports(true) 76 | .build(); 77 | i += 1; 78 | 79 | // ProductB1 class declaration 80 | ClassName ProductB1 = ClassName.get("",classes[i]); 81 | TypeSpec prodB1 = TypeSpec.classBuilder(ProductB1) 82 | .addModifiers(Modifier.PUBLIC) 83 | .addSuperinterface(AbstractProductB) 84 | .addJavadoc("ProductB1, implements AbstractProductB interface") 85 | .build(); 86 | generatedCode[i] = JavaFile.builder(packageName,prodB1) 87 | .skipJavaLangImports(true) 88 | .build(); 89 | i += 1; 90 | 91 | // ProductB2 class declaration 92 | ClassName ProductB2 = ClassName.get("",classes[i]); 93 | TypeSpec prodB2 = TypeSpec.classBuilder(ProductB2) 94 | .addModifiers(Modifier.PUBLIC) 95 | .addSuperinterface(AbstractProductB) 96 | .addJavadoc("ProductB1, implements AbstractProductB interface") 97 | .build(); 98 | generatedCode[i] = JavaFile.builder(packageName,prodB2) 99 | .skipJavaLangImports(true) 100 | .build(); 101 | i += 1; 102 | 103 | // AbstractFactory interface declaration 104 | ClassName AbstractFactory = ClassName.get("",classes[i]); 105 | MethodSpec createProdA = MethodSpec.methodBuilder("create" + classes[0]) 106 | .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC) 107 | .returns(AbstractProductA) 108 | .build(); 109 | MethodSpec createProdB = MethodSpec.methodBuilder("create" + classes[3] ) 110 | .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC) 111 | .returns(AbstractProductB) 112 | .build(); 113 | TypeSpec abstractFactory = TypeSpec.interfaceBuilder(AbstractFactory) 114 | .addModifiers(Modifier.PUBLIC) 115 | .addJavadoc("Abstract Factory, defines interface for creation of the abstract product objects") 116 | .addMethod(createProdA) 117 | .addMethod(createProdB) 118 | .build(); 119 | generatedCode[i] = JavaFile.builder(packageName,abstractFactory) 120 | .skipJavaLangImports(true) 121 | .build(); 122 | i += 1; 123 | 124 | // ConcreteFactory1 interface declaration 125 | ClassName ConcreteFactory1 = ClassName.get("",classes[i]); 126 | TypeSpec concFactory1 = TypeSpec.classBuilder(ConcreteFactory1) 127 | .addModifiers(Modifier.PUBLIC) 128 | .addSuperinterface(AbstractFactory) 129 | .addJavadoc("ConcreteFactory1, implements creation of the concrete Product1 objects") 130 | .addMethod(MethodSpec.methodBuilder(createProdA.name) 131 | .addModifiers(Modifier.PUBLIC) 132 | .returns(AbstractProductA) 133 | .addStatement("return new $N()", prodA1.name) 134 | .build()) 135 | .addMethod(MethodSpec.methodBuilder(createProdB.name) 136 | .addModifiers(Modifier.PUBLIC) 137 | .returns(AbstractProductB) 138 | .addStatement("return new $N()", prodB1.name) 139 | .build()) 140 | .build(); 141 | generatedCode[i] = JavaFile.builder(packageName,concFactory1) 142 | .skipJavaLangImports(true) 143 | .build(); 144 | i += 1; 145 | 146 | // ConcreteFactory2 interface declaration 147 | ClassName ConcreteFactory2 = ClassName.get("",classes[i]); 148 | TypeSpec concFactory2 = TypeSpec.classBuilder(ConcreteFactory2) 149 | .addModifiers(Modifier.PUBLIC) 150 | .addSuperinterface(AbstractFactory) 151 | .addJavadoc("ConcreteFactory2, implements creation of the concrete Product2 objects") 152 | .addMethod(MethodSpec.methodBuilder(createProdA.name) 153 | .addModifiers(Modifier.PUBLIC) 154 | .returns(AbstractProductA) 155 | .addStatement("return new $N()", prodA2.name) 156 | .build()) 157 | .addMethod(MethodSpec.methodBuilder(createProdB.name) 158 | .addModifiers(Modifier.PUBLIC) 159 | .returns(AbstractProductB) 160 | .addStatement("return new $N()", prodB2.name) 161 | .build()) 162 | .build(); 163 | generatedCode[i] = JavaFile.builder(packageName,concFactory2) 164 | .skipJavaLangImports(true) 165 | .build(); 166 | 167 | logger.info("Returning generated java code to be written in files"); 168 | 169 | return generatedCode; 170 | } 171 | 172 | } 173 | -------------------------------------------------------------------------------- /src/main/java/com/creational/Builder.java: -------------------------------------------------------------------------------- 1 | package com.creational; 2 | 3 | import com.squareup.javapoet.*; 4 | import javax.lang.model.element.Modifier; 5 | import java.io.IOException; 6 | import com.DesignPattern; 7 | import ch.qos.logback.classic.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | 11 | public class Builder implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Builder.class); 15 | 16 | String[] defaultClasses = {"Builder", "Director","Product","concreteBuilder"}; 17 | String packageName = "com.CreationalDP.builder"; 18 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 19 | 20 | public Builder(int flag)throws IOException{ 21 | logger.info("Executing Builder()"); 22 | 23 | if (flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | @Override 29 | public JavaFile[] generateCode(String[] classes, String packageName){ 30 | 31 | logger.info("Executing generateCode()"); 32 | 33 | int i = 0; 34 | 35 | // Abstract Builder class declaration 36 | ClassName Builder = ClassName.get("",classes[i]); 37 | 38 | MethodSpec createProduct = MethodSpec.methodBuilder("createProduct") 39 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT) 40 | .returns(Builder) 41 | .build(); 42 | 43 | MethodSpec buildPart1 = MethodSpec.methodBuilder("buildPart1") 44 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT) 45 | .returns(Builder) 46 | .addParameter(String.class, "part") 47 | .build(); 48 | 49 | MethodSpec buildPart2 = MethodSpec.methodBuilder("buildPart2") 50 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT) 51 | .returns(Builder) 52 | .addParameter(String.class, "part") 53 | .build(); 54 | 55 | TypeSpec builder = TypeSpec.classBuilder(Builder) 56 | .addModifiers(Modifier.ABSTRACT) 57 | .addJavadoc("Builder, declares interface for creating parts of a Product object") 58 | .addMethod(createProduct) 59 | .addMethod(buildPart1) 60 | .addMethod(buildPart2) 61 | .build(); 62 | 63 | generatedCode[i] = JavaFile.builder(packageName,builder) 64 | .addFileComment("Builder, declares interface for creating parts of a Product object") 65 | .skipJavaLangImports(true) 66 | .build(); 67 | 68 | i += 1; 69 | // Director class declaration 70 | 71 | ClassName Director = ClassName.get("",classes[i]); 72 | 73 | MethodSpec constructorDirector = MethodSpec.constructorBuilder() 74 | .addModifiers(Modifier.PUBLIC) 75 | .addParameter(Builder,"builder") 76 | .addStatement("this.builder = builder") 77 | .build(); 78 | 79 | MethodSpec construct = MethodSpec.methodBuilder("construct") 80 | .addModifiers(Modifier.PUBLIC) 81 | .returns(TypeName.VOID) 82 | .addStatement("builder.$N().$N($S).$N($S)",createProduct.name,buildPart1.name,"part1",buildPart2.name,"part2") 83 | .build(); 84 | 85 | TypeSpec director = TypeSpec.classBuilder(Director) 86 | .addModifiers(Modifier.PUBLIC) 87 | .addJavadoc("Director class, constructs an object using the Builder interface") 88 | .addField(Builder,"builder",Modifier.PRIVATE) 89 | .addMethod(constructorDirector) 90 | .addMethod(construct) 91 | .build(); 92 | 93 | generatedCode[i] = JavaFile.builder(packageName,director) 94 | .skipJavaLangImports(true) 95 | .build(); 96 | 97 | i += 1; 98 | // Product class declaration 99 | 100 | ClassName Product = ClassName.get("",classes[i]); 101 | 102 | MethodSpec set1 = MethodSpec.methodBuilder("setPart1") 103 | .addModifiers(Modifier.PUBLIC) 104 | .returns(TypeName.VOID) 105 | .addParameter(String.class,"part1") 106 | .addStatement("this.$N() = $N","part1","part1") 107 | .build(); 108 | 109 | MethodSpec set2 = MethodSpec.methodBuilder("setPart2") 110 | .addModifiers(Modifier.PUBLIC) 111 | .returns(TypeName.VOID) 112 | .addParameter(String.class,"part2") 113 | .addStatement("this.$N() = $N","part2","part2") 114 | .build(); 115 | 116 | MethodSpec get1 = MethodSpec.methodBuilder("getPart1") 117 | .addModifiers(Modifier.PUBLIC) 118 | .returns(String.class) 119 | .addStatement("return $N","part1") 120 | .build(); 121 | 122 | MethodSpec get2 = MethodSpec.methodBuilder("getPart2") 123 | .addModifiers(Modifier.PUBLIC) 124 | .returns(String.class) 125 | .addStatement("return $N","part2") 126 | .build(); 127 | 128 | TypeSpec product = TypeSpec.classBuilder(Product) 129 | .addModifiers(Modifier.PUBLIC) 130 | .addJavadoc("Product class, represents complex object") 131 | .addField(String.class, "part1", Modifier.PRIVATE) 132 | .addField(String.class, "part2", Modifier.PRIVATE) 133 | .addMethod(set1) 134 | .addMethod(set2) 135 | .addMethod(get1) 136 | .addMethod(get2) 137 | .build(); 138 | 139 | generatedCode[i] = JavaFile.builder(packageName,product) 140 | .skipJavaLangImports(true) 141 | .build(); 142 | 143 | i += 1; 144 | // Concrete Builder class declaration 145 | 146 | ClassName concreteBuilder = ClassName.get("",classes[i]); 147 | 148 | MethodSpec createproduct = MethodSpec.methodBuilder("createProduct") 149 | .addModifiers(Modifier.PUBLIC) 150 | .returns(Builder) 151 | .addStatement("this.product = new $T()",Product) 152 | .addStatement("return this") 153 | .build(); 154 | 155 | MethodSpec buildpart1 = MethodSpec.methodBuilder("buildPart1") 156 | .addModifiers(Modifier.PUBLIC) 157 | .returns(Builder) 158 | .addParameter(String.class,"part" ) 159 | .addStatement("product.$N($N)",set1.name,"part") 160 | .addStatement("return this") 161 | .build(); 162 | 163 | MethodSpec buildpart2 = MethodSpec.methodBuilder("buildPart2") 164 | .addModifiers(Modifier.PUBLIC) 165 | .returns(Builder) 166 | .addParameter(String.class,"part" ) 167 | .addStatement("product.$N($N)",set2.name,"part") 168 | .addStatement("return this") 169 | .build(); 170 | 171 | MethodSpec getresult = MethodSpec.methodBuilder("getResult") 172 | .addModifiers(Modifier.PUBLIC) 173 | .returns(Product) 174 | .addStatement("return product") 175 | .build(); 176 | 177 | TypeSpec concretebuilder = TypeSpec.classBuilder(concreteBuilder) 178 | .superclass(Builder) 179 | .addModifiers(Modifier.PUBLIC) 180 | .addJavadoc("ConcreteBuilder class, constructs and assembles parts of the Product by\n" + 181 | "implementing the Builder interface") 182 | .addField(Product, "product", Modifier.PRIVATE) 183 | .addMethod(createproduct) 184 | .addMethod(buildpart1) 185 | .addMethod(buildpart2) 186 | .addMethod(getresult) 187 | .build(); 188 | 189 | generatedCode[i] = JavaFile.builder(packageName,concretebuilder) 190 | .skipJavaLangImports(true) 191 | .build(); 192 | 193 | logger.info("Returning generated java code to be written in files"); 194 | 195 | return generatedCode; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/main/java/com/structural/Flyweight.java: -------------------------------------------------------------------------------- 1 | package com.structural; 2 | 3 | 4 | import com.squareup.javapoet.*; 5 | 6 | import javax.lang.model.element.Modifier; 7 | import java.io.IOException; 8 | import com.DesignPattern; 9 | import ch.qos.logback.classic.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class Flyweight implements DesignPattern { 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Flyweight.class); 15 | 16 | 17 | String[] defaultClasses = {"Flyweight", "ConcreteFlyweight","UnsharedConcreteFlyweight","FlyweightFactory"}; 18 | String packageName = "com.StructuralDP.flyweight"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public Flyweight(int flag) throws IOException { 22 | logger.info("Executing Flyweight()"); 23 | if(flag == 1) { 24 | createDesignPattern(defaultClasses,packageName); 25 | } 26 | 27 | } 28 | 29 | public void create() throws IOException { 30 | createDesignPattern(defaultClasses,packageName); 31 | } 32 | public JavaFile[] generateCode(String[] classes, String packageName){ 33 | logger.info("Executing generateCode()"); 34 | 35 | int i = 0; 36 | 37 | // Flyweight interface declaration 38 | ClassName Flyweight = ClassName.get("",classes[i]); 39 | MethodSpec oper = MethodSpec.methodBuilder("operation") 40 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT) 41 | .returns(TypeName.VOID) 42 | .addParameter(TypeName.OBJECT, "extrinsicState") 43 | .build(); 44 | TypeSpec flyweight = TypeSpec.interfaceBuilder(Flyweight) 45 | .addModifiers(Modifier.PUBLIC) 46 | .addJavadoc("Flyweight, interface through flyweight can receive and act on extrinsic state.") 47 | .addMethod(oper) 48 | .build(); 49 | generatedCode[i] = JavaFile.builder(packageName,flyweight) 50 | .skipJavaLangImports(true) 51 | .build(); 52 | i += 1; 53 | 54 | // ConcreteFlyweight class declaration 55 | ClassName ConcreteFlyweight = ClassName.get("",classes[i]); 56 | FieldSpec intrinsicState = FieldSpec.builder(TypeName.OBJECT,"intrinsicState",Modifier.PRIVATE).build(); 57 | TypeSpec concreteFlyweight = TypeSpec.classBuilder(ConcreteFlyweight) 58 | .addModifiers(Modifier.PUBLIC) 59 | .addSuperinterface(Flyweight) 60 | .addJavadoc("ConcreteFlyweight,implements Flyweight, and add storage for intrinsic state.") 61 | .addField(intrinsicState) 62 | .addMethod(MethodSpec.constructorBuilder() 63 | .addModifiers(Modifier.PUBLIC) 64 | .addParameter(TypeName.OBJECT, "intrinsicState") 65 | .addStatement("this.$N = intrinsicState", intrinsicState.name) 66 | .build()) 67 | .addMethod(MethodSpec.methodBuilder(oper.name) 68 | .addComment("Using extrinsicState as context and does NOT modify intrinsic state") 69 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 70 | .addParameter(TypeName.OBJECT, "extrinsicState") 71 | .build()) 72 | .addMethod(MethodSpec.methodBuilder("getIntrinsicState") 73 | .addJavadoc("@return intrinsic state") 74 | .addModifiers(Modifier.PUBLIC).returns(TypeName.OBJECT) 75 | .addStatement("return $N", intrinsicState.name) 76 | .build()) 77 | .build(); 78 | generatedCode[i] = JavaFile.builder(packageName,concreteFlyweight) 79 | .skipJavaLangImports(true) 80 | .build(); 81 | i += 1; 82 | 83 | // UnsharedConcreteFlyweight class declaration 84 | ClassName UnsharedConcreteFlyweight = ClassName.get("",classes[i]); 85 | FieldSpec state = FieldSpec.builder(TypeName.OBJECT,"state",Modifier.PRIVATE).build(); 86 | TypeSpec unsharedConcreteFlyweight = TypeSpec.classBuilder(UnsharedConcreteFlyweight) 87 | .addModifiers(Modifier.PUBLIC) 88 | .addSuperinterface(Flyweight) 89 | .addJavadoc("UnsharedConcreteFlyweight, defines objects which are not shared.") 90 | .addField(state) 91 | .addMethod(MethodSpec.constructorBuilder() 92 | .addModifiers(Modifier.PUBLIC) 93 | .addParameter(TypeName.OBJECT, "state") 94 | .addStatement("this.$N = state", state.name) 95 | .build()) 96 | .addMethod(MethodSpec.methodBuilder(oper.name) 97 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 98 | .addParameter(TypeName.OBJECT, "extrinsicState") 99 | .build()) 100 | .addMethod(MethodSpec.methodBuilder("getState") 101 | .addModifiers(Modifier.PUBLIC).returns(TypeName.OBJECT) 102 | .addStatement("return $N", state.name) 103 | .build()) 104 | .build(); 105 | generatedCode[i] = JavaFile.builder(packageName,unsharedConcreteFlyweight) 106 | .skipJavaLangImports(true) 107 | .build(); 108 | i += 1; 109 | 110 | // FlyweightFactory class declaration 111 | ClassName FlyweightFactory = ClassName.get("",classes[i]); 112 | ClassName hashMap = ClassName.get("java.util", "HashMap"); 113 | ClassName map = ClassName.get("java.util", "Map"); 114 | TypeName listOfFlyweights = ParameterizedTypeName.get(map,Flyweight); 115 | // TypeName listOfFlyweights = ParameterizedTypeName.get(map,TypeName.get(String.class.getComponentType())); 116 | // TypeName f = ParameterizedTypeName.get(String.class,listOfFlyweights ); 117 | 118 | FieldSpec flyweights = FieldSpec.builder(listOfFlyweights,"flyweights") 119 | .addModifiers(Modifier.PRIVATE,Modifier.STATIC) 120 | .initializer("new $T<$T, $T>()",hashMap,String.class,Flyweight) 121 | .build(); 122 | TypeSpec flyweightFact = TypeSpec.classBuilder(FlyweightFactory) 123 | .addModifiers(Modifier.PUBLIC) 124 | .addJavadoc("FlyweightFactory, creates and manages the flyweight objects.") 125 | .addField(flyweights) 126 | .addMethod(MethodSpec.methodBuilder("getFlyweight") 127 | .addModifiers(Modifier.PUBLIC,Modifier.STATIC).returns(Flyweight) 128 | .addParameter(String.class,"key") 129 | .addParameter(String.class,"value") 130 | .addJavadoc("Returns Flyweight object. Just for sake of example following logic is\n" + 131 | "applied, if key starts with phrase:unshared than UnsharedConcreteFlyweight\n" + 132 | "object is created. Otherwise ConcreteFlyweight object is created.\n" + 133 | "@param key\n" + 134 | "@return Flyweight") 135 | .beginControlFlow("if (key.startsWith(\"unshared\"))") 136 | .addStatement("$N.put(key, new $T(value))",flyweights.name,UnsharedConcreteFlyweight) 137 | .nextControlFlow("else { \n" + 138 | "if (!$N.containsKey(key))",flyweights.name) 139 | .addStatement("$N.put(key, new $T(value))",flyweights.name,ConcreteFlyweight) 140 | .addCode("}\n") 141 | .endControlFlow() 142 | .addStatement("return ($T) $N.get(key)",Flyweight,flyweights.name) 143 | .build()) 144 | .build(); 145 | generatedCode[i] = JavaFile.builder(packageName,flyweightFact) 146 | .skipJavaLangImports(true) 147 | .build(); 148 | 149 | logger.info("Returning generated java code to be written in files"); 150 | 151 | return generatedCode; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/Mediator.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | import javax.lang.model.element.Modifier; 5 | import java.io.IOException; 6 | 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class Mediator implements DesignPattern { 12 | 13 | //Define a static logger variable so that it references the Logger instance 14 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Mediator.class); 15 | 16 | 17 | String[] defaultClasses = {"Colleague","ConcreteColleague1","ConcreteColleague2","Mediator","ConcreteMediator"}; 18 | String packageName = "com.BehavioralDP.mediator"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public Mediator(int flag)throws IOException{ 22 | logger.info("Executing Mediator()"); 23 | if(flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | public JavaFile[] generateCode(String[] classes, String packageName){ 29 | logger.info("Executing generateCode()"); 30 | int i = 0; 31 | ClassName Colleague = ClassName.get("",classes[0]); 32 | ClassName ConcreteColleague1 = ClassName.get("",classes[1]); 33 | ClassName ConcreteColleague2 = ClassName.get("",classes[2]); 34 | ClassName Mediator = ClassName.get("",classes[3]); 35 | ClassName ConcreteMediator = ClassName.get("",classes[4]); 36 | 37 | // Colleague abstract class declaration 38 | FieldSpec mediatorField = FieldSpec.builder(Mediator,"mediator",Modifier.PROTECTED).build(); 39 | FieldSpec recMsg = FieldSpec.builder(String.class,"receivedMessage",Modifier.PRIVATE).build(); 40 | MethodSpec notifyCol = MethodSpec.methodBuilder("notifyColleague") 41 | .addModifiers(Modifier.ABSTRACT).returns(TypeName.VOID) 42 | .addParameter(String.class,"message") 43 | .build(); 44 | MethodSpec receive = MethodSpec.methodBuilder("receive") 45 | .addModifiers(Modifier.ABSTRACT).returns(TypeName.VOID) 46 | .addParameter(String.class,"message") 47 | .build(); 48 | MethodSpec getRecMsg = MethodSpec.methodBuilder("getReceivedMessage") 49 | .addModifiers(Modifier.PROTECTED).returns(String.class) 50 | .addStatement("return this.$N",recMsg.name) 51 | .build(); 52 | MethodSpec setRecMsg = MethodSpec.methodBuilder("setReceivedMessage") 53 | .addModifiers(Modifier.PROTECTED).returns(TypeName.VOID) 54 | .addParameter(String.class,"receivedMessage") 55 | .addStatement("this.$N = receivedMessage",recMsg.name) 56 | .build(); 57 | TypeSpec colleague = TypeSpec.classBuilder(Colleague) 58 | .addModifiers(Modifier.ABSTRACT) 59 | .addJavadoc("Colleague defines an interface for communication with another Colleague via mediator.") 60 | .addField(mediatorField) 61 | .addField(recMsg) 62 | .addMethod(MethodSpec.constructorBuilder() 63 | .addModifiers(Modifier.PUBLIC) 64 | .addParameter(Mediator,"mediator") 65 | .addStatement("this.$N = mediator",mediatorField.name) 66 | .build()) 67 | .addMethod(notifyCol) 68 | .addMethod(receive) 69 | .addMethod(getRecMsg) 70 | .addMethod(setRecMsg) 71 | .build(); 72 | generatedCode[i] = JavaFile.builder(packageName,colleague) 73 | .skipJavaLangImports(true) 74 | .build(); 75 | i += 1; 76 | 77 | // ConcreteColleague1 class declaration 78 | TypeSpec concCol1 = TypeSpec.classBuilder(ConcreteColleague1) 79 | .addModifiers(Modifier.PUBLIC).superclass(Colleague) 80 | .addJavadoc("ConcreteColleague1 implements Colleague interface.") 81 | .addMethod(MethodSpec.constructorBuilder() 82 | .addModifiers(Modifier.PUBLIC) 83 | .addParameter(Mediator, "mediator") 84 | .addStatement("super(mediator)") 85 | .build()) 86 | .addMethod(MethodSpec.methodBuilder(notifyCol.name) 87 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 88 | .addParameter(String.class,"message") 89 | .addStatement("this.$N.$N(this, message)",mediatorField.name,notifyCol.name) 90 | .build()) 91 | .addMethod(MethodSpec.methodBuilder(receive.name) 92 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 93 | .addParameter(String.class,"message") 94 | .addStatement("this.$N(message)",setRecMsg.name) 95 | .build()) 96 | .build(); 97 | generatedCode[i] = JavaFile.builder(packageName,concCol1) 98 | .skipJavaLangImports(true) 99 | .build(); 100 | i += 1; 101 | 102 | // ConcreteColleague1 class declaration 103 | TypeSpec concCol2 = TypeSpec.classBuilder(ConcreteColleague2) 104 | .addModifiers(Modifier.PUBLIC).superclass(Colleague) 105 | .addJavadoc("ConcreteColleague2 implements Colleague interface.") 106 | .addMethod(MethodSpec.constructorBuilder() 107 | .addModifiers(Modifier.PUBLIC) 108 | .addParameter(Mediator, "mediator") 109 | .addStatement("super(mediator)") 110 | .build()) 111 | .addMethod(MethodSpec.methodBuilder(notifyCol.name) 112 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 113 | .addParameter(String.class,"message") 114 | .addStatement("this.$N.$N(this, message)",mediatorField.name,notifyCol.name) 115 | .build()) 116 | .addMethod(MethodSpec.methodBuilder(receive.name) 117 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 118 | .addParameter(String.class,"message") 119 | .addStatement("this.$N(message)",setRecMsg.name) 120 | .build()) 121 | .build(); 122 | generatedCode[i] = JavaFile.builder(packageName,concCol2) 123 | .skipJavaLangImports(true) 124 | .build(); 125 | i += 1; 126 | 127 | // Mediator interface declaration 128 | TypeSpec mediator = TypeSpec.interfaceBuilder(Mediator) 129 | .addModifiers(Modifier.PUBLIC) 130 | .addMethod(MethodSpec.methodBuilder(notifyCol.name) 131 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.VOID) 132 | .addParameter(Colleague, "colleague") 133 | .addParameter(String.class,"message") 134 | .build()) 135 | .build(); 136 | generatedCode[i] = JavaFile.builder(packageName,mediator) 137 | .skipJavaLangImports(true) 138 | .build(); 139 | i += 1; 140 | 141 | // ConcreteMediator class declaration 142 | ClassName list = ClassName.get("java.util", "List"); 143 | ClassName arrayList = ClassName.get("java.util", "ArrayList"); 144 | ClassName Iterator = ClassName.get("java.util","Iterator"); 145 | TypeName listOfColleagues = ParameterizedTypeName.get(list,Colleague); 146 | 147 | FieldSpec cols = FieldSpec.builder(listOfColleagues,"colleagues",Modifier.PRIVATE) 148 | .build(); 149 | TypeSpec concreteMediator = TypeSpec.classBuilder(ConcreteMediator) 150 | .addModifiers(Modifier.PUBLIC) 151 | .addSuperinterface(Mediator) 152 | .addJavadoc("ConcreteMediator implements Mediator, coordinates between Colleague objects.") 153 | .addField(cols) 154 | .addMethod(MethodSpec.constructorBuilder() 155 | .addModifiers(Modifier.PUBLIC) 156 | .addStatement("$N = new $T<$T>()", cols.name,arrayList,Colleague) 157 | .build()) 158 | .addMethod(MethodSpec.methodBuilder("addColleague") 159 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 160 | .addParameter(Colleague,"colleague") 161 | .addStatement("$N.add(colleague)",cols.name) 162 | .build()) 163 | .addMethod(MethodSpec.methodBuilder(notifyCol.name) 164 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 165 | .addParameter(Colleague, "colleague") 166 | .addParameter(String.class,"message") 167 | .addCode("\n") 168 | .beginControlFlow("for ($T iterator = $N.iterator(); iterator.hasNext();)",Iterator,cols.name) 169 | .addStatement("$T receiverColleague = ($T) iterator.next()",Colleague,Colleague) 170 | .addCode("\n") 171 | .beginControlFlow("if (colleague != receiverColleague)") 172 | .addStatement("receiverColleague.$N(message)",receive.name) 173 | .endControlFlow() 174 | .endControlFlow() 175 | .build()) 176 | .build(); 177 | generatedCode[i] = JavaFile.builder(packageName,concreteMediator) 178 | .skipJavaLangImports(true) 179 | .build(); 180 | 181 | logger.info("Returning generated java code to be written in files"); 182 | 183 | return generatedCode; 184 | 185 | 186 | } 187 | 188 | } 189 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/Interpreter.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | 5 | import javax.lang.model.element.Modifier; 6 | import java.io.IOException; 7 | import com.DesignPattern; 8 | import ch.qos.logback.classic.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class Interpreter implements DesignPattern { 12 | //Define a static logger variable so that it references the Logger instance 13 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Interpreter.class); 14 | 15 | 16 | String[] defaultClasses = {"Context", "AbstractExpression","OrExpression","AndExpression","TerminalExpression"}; 17 | String packageName = "com.BehavioralDP.interpreter"; 18 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 19 | 20 | public Interpreter(int flag)throws IOException{ 21 | logger.info("Executing Interpreter()"); 22 | if(flag == 1) { 23 | createDesignPattern(defaultClasses, packageName); 24 | } 25 | } 26 | 27 | public JavaFile[] generateCode(String[] classes, String packageName){ 28 | logger.info("Executing generateCode()"); 29 | 30 | int i = 0; 31 | 32 | // Context class declaration 33 | ClassName Context = ClassName.get("",classes[i]); 34 | ClassName list = ClassName.get("java.util", "List"); 35 | ClassName arrayList = ClassName.get("java.util", "ArrayList"); 36 | ClassName Boolean = ClassName.get("java.lang","Boolean"); 37 | TypeName listOfBoolean = ParameterizedTypeName.get(list,Boolean); 38 | 39 | FieldSpec operands = FieldSpec.builder(listOfBoolean,"operands",Modifier.PRIVATE) 40 | .initializer("new $T<$T>()",arrayList,Boolean.class) 41 | .build(); 42 | FieldSpec result = FieldSpec.builder(Boolean.class, "result",Modifier.PRIVATE) 43 | .initializer("null").build(); 44 | 45 | MethodSpec getOperands = MethodSpec.methodBuilder("getOperands") 46 | .addModifiers(Modifier.PUBLIC).returns(listOfBoolean) 47 | .addStatement("return $N",operands.name).build(); 48 | MethodSpec addOperand = MethodSpec.methodBuilder("addOperand") 49 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 50 | .addParameter(Boolean.class, "operand") 51 | .addStatement("$N.add(operand)",operands.name).build(); 52 | 53 | TypeSpec context = TypeSpec.classBuilder(Context) 54 | .addModifiers(Modifier.PUBLIC) 55 | .addJavadoc("Context contains global information for Interpreter.") 56 | .addField(operands) 57 | .addField(result) 58 | .addMethod(getOperands) 59 | .addMethod(addOperand) 60 | .addMethod(MethodSpec.methodBuilder("isResult") 61 | .addModifiers(Modifier.PUBLIC).returns(TypeName.BOOLEAN) 62 | .addStatement("return $N",result.name).build()) 63 | .addMethod(MethodSpec.methodBuilder("setResult") 64 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 65 | .addParameter(TypeName.BOOLEAN, "result") 66 | .addStatement("this.$N = result",result.name).build()) 67 | .build(); 68 | generatedCode[i] = JavaFile.builder(packageName,context).skipJavaLangImports(true).build(); 69 | i += 1; 70 | 71 | // AbstractExpression class declaration 72 | ClassName AbstractExpression = ClassName.get("",classes[i]); 73 | MethodSpec interpret = MethodSpec.methodBuilder("interpret") 74 | .addModifiers(Modifier.ABSTRACT).returns(TypeName.VOID) 75 | .addParameter(Context, "context") 76 | .build(); 77 | 78 | TypeSpec abstractExp = TypeSpec.classBuilder(AbstractExpression) 79 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT) 80 | .addJavadoc("AbstractExpresion defines interface for interpretation. Interface must be used by" + 81 | " TerminalExpression and NonTerminalExpression.") 82 | .addMethod(interpret).build(); 83 | generatedCode[i] = JavaFile.builder(packageName,abstractExp).skipJavaLangImports(true).build(); 84 | i += 1; 85 | 86 | // OrExpression class declaration 87 | ClassName OrExpression = ClassName.get("",classes[i]); 88 | FieldSpec firstAbsExp = FieldSpec.builder(AbstractExpression, "firstAbstractExpression",Modifier.PRIVATE).build(); 89 | FieldSpec secondAbsExp = FieldSpec.builder(AbstractExpression, "secondAbstractExpression",Modifier.PRIVATE).build(); 90 | TypeSpec orExp = TypeSpec.classBuilder(OrExpression) 91 | .superclass(AbstractExpression) 92 | .addModifiers(Modifier.PUBLIC) 93 | .addJavadoc("OrExpression implements AbstractExpression for logical OR grammar expression") 94 | .addField(firstAbsExp) 95 | .addField(secondAbsExp) 96 | .addMethod(MethodSpec.constructorBuilder() 97 | .addModifiers(Modifier.PUBLIC) 98 | .addParameter(AbstractExpression, "firstAbstractExpression") 99 | .addParameter(AbstractExpression, "secondAbstractExpression") 100 | .addStatement("this.$N = firstAbstractExpression",firstAbsExp) 101 | .addStatement("this.$N = secondAbstractExpression",secondAbsExp) 102 | .build()) 103 | .addMethod(MethodSpec.methodBuilder(interpret.name) 104 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 105 | .addParameter(Context, "context") 106 | .addStatement("$N.$N(context)",firstAbsExp.name,interpret.name) 107 | .addStatement("$N.$N(context)",secondAbsExp.name,interpret.name) 108 | .addCode("\n") 109 | .addStatement("$T $N = context.$N()",listOfBoolean,operands.name,getOperands.name) 110 | .addCode("\n") 111 | .addStatement("Boolean firstOperand = operands.get(0)") 112 | .addStatement("Boolean secondOperand = operands.get(1)") 113 | .addCode("\n") 114 | .addStatement("$T $N = firstOperand || secondOperand",Boolean,result.name) 115 | .addStatement("$N.setResult($N)",context.name,result.name) 116 | .build()) 117 | .build(); 118 | generatedCode[i] = JavaFile.builder(packageName,orExp).skipJavaLangImports(true).build(); 119 | i += 1; 120 | 121 | // OrExpression class declaration 122 | ClassName AndExpression = ClassName.get("",classes[i]); 123 | TypeSpec andExp = TypeSpec.classBuilder(AndExpression) 124 | .superclass(AbstractExpression) 125 | .addModifiers(Modifier.PUBLIC) 126 | .addJavadoc("AndExpression implements AbstractExpression for logical AND grammar expression") 127 | .addField(firstAbsExp) 128 | .addField(secondAbsExp) 129 | .addMethod(MethodSpec.constructorBuilder() 130 | .addModifiers(Modifier.PUBLIC) 131 | .addParameter(AbstractExpression, "firstAbstractExpression") 132 | .addParameter(AbstractExpression, "secondAbstractExpression") 133 | .addStatement("this.$N = firstAbstractExpression",firstAbsExp) 134 | .addStatement("this.$N = secondAbstractExpression",secondAbsExp) 135 | .build()) 136 | .addMethod(MethodSpec.methodBuilder(interpret.name) 137 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 138 | .addParameter(Context, "context") 139 | .addStatement("$N.$N(context)",firstAbsExp.name,interpret.name) 140 | .addStatement("$N.$N(context)",secondAbsExp.name,interpret.name) 141 | .addCode("\n") 142 | .addStatement("$T $N = context.$N()",listOfBoolean,operands.name,getOperands.name) 143 | .addCode("\n") 144 | .addStatement("Boolean firstOperand = operands.get(0)") 145 | .addStatement("Boolean secondOperand = operands.get(1)") 146 | .addCode("\n") 147 | .addStatement("$T $N = firstOperand && secondOperand",Boolean,result.name) 148 | .addStatement("$N.setResult($N)",context.name,result.name) 149 | .build()) 150 | .build(); 151 | generatedCode[i] = JavaFile.builder(packageName,andExp).skipJavaLangImports(true).build(); 152 | i += 1; 153 | 154 | // TerminalExpression class declaration 155 | ClassName TerminalExpression = ClassName.get("",classes[i]); 156 | FieldSpec data = FieldSpec.builder(boolean.class,"data",Modifier.PRIVATE).build(); 157 | TypeSpec termExp = TypeSpec.classBuilder(TerminalExpression) 158 | .superclass(AbstractExpression) 159 | .addModifiers(Modifier.PUBLIC) 160 | .addJavadoc("TerminalExpresion implements AbstractExpression for literal symbol in grammar.") 161 | .addField(data) 162 | .addMethod(MethodSpec.constructorBuilder() 163 | .addModifiers(Modifier.PUBLIC) 164 | .addParameter(boolean.class,"data") 165 | .addStatement("this.$N = data",data.name) 166 | .build()) 167 | .addMethod(MethodSpec.methodBuilder(interpret.name) 168 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 169 | .addParameter(Context,"context") 170 | .addStatement("context.$N(this.$N)",addOperand.name,data.name) 171 | .build()) 172 | .build(); 173 | generatedCode[i] = JavaFile.builder(packageName,termExp).skipJavaLangImports(true).build(); 174 | 175 | logger.info("Returning generated java code to be written in files"); 176 | 177 | return generatedCode; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/main/java/com/behavioral/Visitor.java: -------------------------------------------------------------------------------- 1 | package com.behavioral; 2 | 3 | import com.squareup.javapoet.*; 4 | import javax.lang.model.element.Modifier; 5 | import java.io.IOException; 6 | import com.DesignPattern; 7 | import ch.qos.logback.classic.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class Visitor implements DesignPattern { 11 | 12 | //Define a static logger variable so that it references the Logger instance 13 | private static final Logger logger = (Logger) LoggerFactory.getLogger(Visitor.class); 14 | 15 | 16 | String[] defaultClasses = {"Element","ConcreteElementA","ConcreteElementB","Visitor","ConcreteVisitor1", 17 | "ConcreteVisitor2", "ObjectStructure"}; 18 | String packageName = "com.BehavioralDP.visitor"; 19 | JavaFile[] generatedCode = new JavaFile[defaultClasses.length]; 20 | 21 | public Visitor(int flag)throws IOException{ 22 | logger.info("Executing Visitor()"); 23 | if(flag == 1) { 24 | createDesignPattern(defaultClasses, packageName); 25 | } 26 | } 27 | 28 | public JavaFile[] generateCode(String[] classes, String packageName){ 29 | logger.info("Executing generateCode()"); 30 | 31 | ClassName Element = ClassName.get("",classes[0]); 32 | ClassName ConcreteElementA = ClassName.get("",classes[1]); 33 | ClassName ConcreteElementB = ClassName.get("",classes[2]); 34 | ClassName Visitor = ClassName.get("",classes[3]); 35 | ClassName ConcreteVisitor1 = ClassName.get("",classes[4]); 36 | ClassName ConcreteVisitor2 = ClassName.get("",classes[5]); 37 | ClassName ObjectStructure = ClassName.get("",classes[6]); 38 | 39 | int i = 0; 40 | // Element interface declaration 41 | MethodSpec accept = MethodSpec.methodBuilder("accept") 42 | .addJavadoc("Defines an Accept operation that takes a visitor as an argument.") 43 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.VOID) 44 | .addParameter(Visitor, "visitor").build(); 45 | TypeSpec element = TypeSpec.interfaceBuilder(Element) 46 | .addModifiers(Modifier.PUBLIC) 47 | .addMethod(accept).build(); 48 | generatedCode[i] = JavaFile.builder(packageName,element) 49 | .skipJavaLangImports(true).build(); 50 | i += 1; 51 | 52 | 53 | MethodSpec visitConcElementA = MethodSpec.methodBuilder("visitConcreteElementA") 54 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.VOID) 55 | .addParameter(ConcreteElementA,"concreteElementA").build(); 56 | 57 | MethodSpec visitConcElementB = MethodSpec.methodBuilder("visitConcreteElementB") 58 | .addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT).returns(TypeName.VOID) 59 | .addParameter(ConcreteElementB,"concreteElementB").build(); 60 | 61 | 62 | // ConcreteElementA class decalaration 63 | FieldSpec counter = FieldSpec.builder(int.class,"counter",Modifier.PRIVATE) 64 | .initializer("0").build(); 65 | 66 | MethodSpec operA = MethodSpec.methodBuilder("operationA") 67 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 68 | .addStatement("$N++",counter.name).build(); 69 | MethodSpec getCounter = MethodSpec.methodBuilder("getCounter") 70 | .addModifiers(Modifier.PROTECTED).returns(TypeName.INT) 71 | .addStatement("return $N",counter.name).build(); 72 | 73 | TypeSpec concElementA = TypeSpec.classBuilder(ConcreteElementA) 74 | .addModifiers(Modifier.PUBLIC) 75 | .addSuperinterface(Element) 76 | .addJavadoc("Implements accept operation.") 77 | .addField(counter) 78 | .addMethod(MethodSpec.methodBuilder(accept.name) 79 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 80 | .addParameter(Visitor,"visitor") 81 | .addStatement("visitor.$N(this)",visitConcElementA.name) 82 | .build()) 83 | .addMethod(operA) 84 | .addMethod(getCounter) 85 | .build(); 86 | generatedCode[i] = JavaFile.builder(packageName,concElementA) 87 | .skipJavaLangImports(true) 88 | .build(); 89 | i += 1; 90 | 91 | // ConcreteElementB class decalaration 92 | MethodSpec operB = MethodSpec.methodBuilder("operationB") 93 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 94 | .addStatement("$N++",counter.name).build(); 95 | 96 | TypeSpec concElementB = TypeSpec.classBuilder(ConcreteElementB) 97 | .addModifiers(Modifier.PUBLIC) 98 | .addSuperinterface(Element) 99 | .addJavadoc("Implements accept operation.") 100 | .addField(counter) 101 | .addMethod(MethodSpec.methodBuilder(accept.name) 102 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 103 | .addParameter(Visitor,"visitor") 104 | .addStatement("visitor.$N(this)",visitConcElementB.name) 105 | .build()) 106 | .addMethod(operB) 107 | .addMethod(getCounter) 108 | .build(); 109 | generatedCode[i] = JavaFile.builder(packageName,concElementB) 110 | .skipJavaLangImports(true) 111 | .build(); 112 | i += 1; 113 | 114 | // Visitor interface declaration 115 | TypeSpec visitor = TypeSpec.interfaceBuilder(Visitor) 116 | .addModifiers(Modifier.PUBLIC) 117 | .addJavadoc("Declares a Visit operation for each class of ConcreteElement in the object structure") 118 | .addMethod(visitConcElementA) 119 | .addMethod(visitConcElementB).build(); 120 | generatedCode[i] = JavaFile.builder(packageName,visitor) 121 | .skipJavaLangImports(true).build(); 122 | i += 1; 123 | 124 | // ConcreteVisitor1 class declaration 125 | TypeSpec concVisitor1 = TypeSpec.classBuilder(ConcreteVisitor1) 126 | .addSuperinterface(Visitor) 127 | .addModifiers(Modifier.PUBLIC) 128 | .addMethod(MethodSpec.methodBuilder(visitConcElementA.name) 129 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 130 | .addParameter(ConcreteElementA,"concreteElementA") 131 | .addStatement("concreteElementA.$N()",operA.name) 132 | .build()) 133 | .addMethod(MethodSpec.methodBuilder(visitConcElementB.name) 134 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 135 | .addParameter(ConcreteElementB,"concreteElementB") 136 | .addStatement("concreteElementB.$N()",operB.name) 137 | .build()) 138 | .build(); 139 | generatedCode[i] = JavaFile.builder(packageName,concVisitor1) 140 | .skipJavaLangImports(true).build(); 141 | i += 1; 142 | 143 | // ConcreteVisitor2 class declaration 144 | TypeSpec concVisitor2 = TypeSpec.classBuilder(ConcreteVisitor2) 145 | .addSuperinterface(Visitor) 146 | .addModifiers(Modifier.PUBLIC) 147 | .addMethod(MethodSpec.methodBuilder(visitConcElementA.name) 148 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 149 | .addParameter(ConcreteElementA,"concreteElementA") 150 | .addStatement("concreteElementA.$N()",operA.name) 151 | .build()) 152 | .addMethod(MethodSpec.methodBuilder(visitConcElementB.name) 153 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 154 | .addParameter(ConcreteElementB,"concreteElementB") 155 | .addStatement("concreteElementB.$N()",operB.name) 156 | .build()) 157 | .build(); 158 | generatedCode[i] = JavaFile.builder(packageName,concVisitor2) 159 | .skipJavaLangImports(true).build(); 160 | i += 1; 161 | 162 | // ObjectStructure class declaration 163 | ClassName list = ClassName.get("java.util", "List"); 164 | ClassName arrayList = ClassName.get("java.util", "ArrayList"); 165 | ClassName Iterator = ClassName.get("java.util","Iterator"); 166 | TypeName listOfElements = ParameterizedTypeName.get(list,Element); 167 | 168 | FieldSpec children = FieldSpec.builder(listOfElements,"children",Modifier.PRIVATE) 169 | .initializer("new $T<$T>()",arrayList,Element) 170 | .build(); 171 | 172 | TypeSpec objStruct = TypeSpec.classBuilder(ObjectStructure) 173 | .addModifiers(Modifier.PUBLIC) 174 | .addJavadoc("Holds objects in structure. Provides interface to allow visitors to visit its elements.") 175 | .addField(children) 176 | .addMethod(MethodSpec.methodBuilder("add") 177 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 178 | .addParameter(Element,"element") 179 | .addStatement("$N.add(element)",children.name) 180 | .build()) 181 | .addMethod(MethodSpec.methodBuilder("remove") 182 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 183 | .addParameter(Element,"element") 184 | .addStatement("$N.remove(element)",children.name) 185 | .build()) 186 | .addMethod(MethodSpec.methodBuilder("getChild") 187 | .addModifiers(Modifier.PUBLIC).returns(Element) 188 | .addParameter(int.class,"index") 189 | .addStatement("return $N.get(index)",children.name) 190 | .build()) 191 | .addMethod(MethodSpec.methodBuilder("acceptAll") 192 | .addModifiers(Modifier.PUBLIC).returns(TypeName.VOID) 193 | .addParameter(Visitor,"visitor") 194 | .beginControlFlow("($T iterator = $N.iterator(); iterator.hasNext();)",Iterator,children.name) 195 | .addStatement("$T element = ($T) iterator.next()",Element,Element) 196 | .addStatement("element.$N(visitor)",accept.name) 197 | .endControlFlow() 198 | .build()) 199 | .build(); 200 | generatedCode[i] = JavaFile.builder(packageName,objStruct) 201 | .skipJavaLangImports(true).build(); 202 | 203 | logger.info("Returning generated java code to be written in files"); 204 | 205 | return generatedCode; 206 | 207 | } 208 | 209 | 210 | } 211 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Design Pattern Code Generator 2 | This project is to generate the implementation code of the 23 Gang of Four(GoF) design patterns, as presented in the book “Design Patterns: Elements of Reusable Object-Oriented Software”. 3 | 4 | An [Intellij Plugin](https://github.com/samujjwaal/IntelliJ-DP-Generator-Plugin) to generate design pattern code based on this implementation. 5 | 6 | 7 | ## Index 8 | 9 | 1. [About Design Patterns](#1-about-design-patterns) 10 | 2. [About JavaPoet](#2-about-javapoet) 11 | 3. [Application Design](#3-application-design) 12 | 4. [Test Cases](#4-test-cases) 13 | 5. I[nstructions to Execute](#5-instructions-to-execute) 14 | 6. [Results of Execution](#6-results-of-execution) 15 | 16 | ------ 17 | 18 | ### 1. About Design Patterns 19 | 20 | Design patterns are the best practices that a programmer can employ to solve trivial problems while designing an application. Design patterns help in speeding up the development process as they provide a set of time tested, proven development paradigms. They provide an industry standard approach to solve a recurring problem. Using design patterns promotes reusability that leads to more robust and highly maintainable code. 21 | 22 | The 23 Design Patterns are classified into 3 main categories: 23 | 24 | * Creational Design Patterns 25 | * Singleton 26 | * Abstract Factory 27 | * Builder 28 | * Factory Method 29 | 30 | * Structural Design Patterns 31 | * Adapter 32 | * Bridge 33 | * Composite 34 | * Decorator 35 | * Facade 36 | * Flyweight 37 | * Proxy 38 | * Behavioral Design Patterns 39 | * Chain of Responsibility 40 | * Command 41 | * Interpreter 42 | * Iterator 43 | * Mediator 44 | * Memento 45 | * Observer 46 | * State 47 | * Strategy 48 | * Template 49 | * Visitor 50 | 51 | ------ 52 | 53 | ### 2. About JavaPoet 54 | 55 | [JavaPoet](https://github.com/square/javapoet), a successor to [JavaWriter](https://github.com/square/javapoet/tree/javawriter_2), is a Java API for generating .java source files. It can generate primitive types, reference types (like classes, interfaces, enumerated types, anonymous inner classes), fields, methods, parameters, annotations, and Javadocs. 56 | 57 | JavaPoet manages the import of the dependent classes automatically. It uses the ***Builder*** design pattern to specify the logic to generate Java code. 58 | 59 | A HelloWorld program like the one here: 60 | 61 | ```java 62 | package com.example.helloworld; 63 | 64 | public final class HelloWorld { 65 | public static void main(String[] args) { 66 | System.out.println("Hello, JavaPoet!"); 67 | } 68 | } 69 | ``` 70 | 71 | can be generated using JavaPoet as follows: 72 | 73 | ```java 74 | MethodSpec main = MethodSpec.methodBuilder("main") 75 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC) 76 | .returns(void.class) 77 | .addParameter(String[].class, "args") 78 | .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") 79 | .build(); 80 | 81 | TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") 82 | .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 83 | .addMethod(main) 84 | .build(); 85 | 86 | JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld) 87 | .build(); 88 | 89 | javaFile.writeTo(System.out); 90 | ``` 91 | 92 | `MethodSpec` "main" is configured with modifiers, return type, parameters and code statements to declare the main method. The main method is added to a `HelloWorld` class and then the class is added to a `HelloWorld.java` file. 93 | 94 | JavaPoet offers models for classes & interfaces (`TypeSpec`), fields (`FieldSpec`), methods & constructors (`MethodSpec`), parameters (`ParameterSpec`) and annotations (`AnnotationSpec`). It also generates the package folder structure for the output java source files. 95 | 96 | The most recent version of JavaPoet available as of now is 1.12.1. 97 | 98 | ------ 99 | 100 | ### 3. Application Design 101 | 102 | To implement Design Pattern Code Generator(DePaCoG), I have employed the **Factory Method**, **Template Method** and **Singleton** design patterns. 103 | 104 | ------ 105 | 106 | The **Factory Method**, a creational design pattern, creates two basic abstractions: the Product and Creator classes. Both these classes are abstract and clients need to extend them to realize their specific implementations. This pattern is used when there is a super class with multiple sub-classes and based on user input a particular sub-class needs to be instantiated. The responsibility of instantiation of a class is taken from the user to the factory class. 107 | 108 | In the case of DePaCoG, the `DesignPattern` and `DesignPatternGenerator` are the two abstractions I have chosen. 109 | 110 | * `DesignPattern` is an `interface` which declares methods for accepting and displaying the class names & package names from the user, generating java source code of the design patterns using JavaPoet and writing the java code into java files as output. 111 | 112 | ```java 113 | public interface DesignPattern { 114 | 115 | void displayClassNames(String[] classes); 116 | 117 | String[] setClassNames(String[] oldClasses); 118 | 119 | String setPackageName(String defaultPckgName); 120 | 121 | void createDesignPattern(String[] oldClasses, String oldPackageName); 122 | 123 | JavaFile[] generateCode(String[] classes, String packageName); 124 | 125 | void writeJavaFiles(JavaFile[] files); 126 | } 127 | ``` 128 | 129 | There are 23 separate concrete classes(java files) to generate the java source code for each design pattern. Each concrete class `implements DesignPattern`. Interface `DesignPattern` provides the `default` method definition of all methods except the method `generateCode()` as the implementation of all other methods do not change according to the design patterns. Each concrete class of `DesignPattern` overrides `generateCode()`. 130 | 131 | * `DesignPatternGenerator` is an `abstract class` which declares methods to display a menu of all available design patterns and invoking appropriate classes to generate a user selected design pattern. 132 | 133 | ```java 134 | abstract class DesignPatternGenerator { 135 | 136 | protected String[] designPatterns; 137 | 138 | abstract void displayDesignPatterns(); 139 | 140 | abstract void generateDesignPattern(); 141 | 142 | abstract void designPatternFactory(); 143 | } 144 | ``` 145 | 146 | The field `designPatterns` declares all the design patterns available for creation. All the methods are abstract and are provided with the implementation in the concrete class `Hw1DesignPatternGenerator` which `extends DesignPatternGenerator.` The class `Hw1DesignPatternGenerator` also defines an additional method `chooseDesignPattern(int choice)` which takes in user’s choice of design pattern as input and instantiates an anonymous object of the appropriate design pattern class. 147 | 148 | * Advantages of using Factory Method pattern: 149 | * It provides an approach to “program to an interface, not an implementation”. 150 | * Through inheritance it provides an abstraction between implementation and client classes. It removes the instantiation of objects of implementation classes from the user/client code 151 | * It makes the code more robust, easy to extend and less coupled 152 | * New types of concrete products can be introduced without any modifications to the existing client code 153 | * Disadvantages of using Factory Method pattern: 154 | * For just creating a single instance of a particular concrete object the user might have to sub-class the creator, which complicates the hierarchy of creator classes 155 | * Makes the code difficult to interpret as all code is behind an abstraction that may also be hiding another set of abstractions 156 | 157 | ------ 158 | 159 | The **Template Method**, a behavioral design pattern, is used to create method stub and defer the steps of implementation to the subclasses. 160 | 161 | The algorithm for generating design patterns has the following steps: display list of all design patterns, ask user which design pattern code is to be generated, ask for and set custom (or default) class names & package name, generate source file using JavaPoet and finally write into output files. The order of execution of these steps cannot be altered as the sequence is critical for the execution of the program. So here different methods are used to achieve the goal of generating the design pattern code. Steps like asking class names& package name and writing generated code into file are common for any design pattern whether it is a creational or structural design pattern. 162 | 163 | This is where Template Method design pattern is useful. It helps define the basic steps to execute an algorithm and can provide default implementation of the methods that might be common for all or a majority of the sub-classes implementing the design pattern. The method is which defines an exclusive property of a design pattern can be overridden by the sub-class. 164 | 165 | Template Method is implemented in the `interface DesignPattern` and its sub-classes. Interface `DesignPattern` provides the `default` method definition of all methods except the method `generateCode()` as the implementation of all other methods do not change according to the design patterns. Each concrete class of `DesignPattern` overrides `generateCode()`. 166 | 167 | Inside the `interface DesignPattern`: 168 | 169 | ```java 170 | JavaFile[] generateCode(String[] classes, String packageName); 171 | ``` 172 | 173 | Inside `class Singleton` which implements `DesignPattern`: 174 | 175 | ```java 176 | public JavaFile[] generateCode(String[] classes, String packageName){ 177 | int i = 0; 178 | ClassName Singleton = ClassName.get("", classes[i]); 179 | MethodSpec constructor = MethodSpec.constructorBuilder() 180 | .addModifiers(Modifier.PRIVATE) 181 | .build(); 182 | FieldSpec instance = FieldSpec.builder(Singleton, "INSTANCE") 183 | .addModifiers(Modifier.PRIVATE, Modifier.STATIC) 184 | .build(); 185 | MethodSpec getInstance = MethodSpec.methodBuilder("getInstance") 186 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC) 187 | .returns(Singleton) 188 | .beginControlFlow("if ($N == null)", instance.name) 189 | .addStatement("$N = new $T()",instance.name, Singleton) 190 | .endControlFlow() 191 | .addStatement("return $N", instance.name) 192 | .build(); 193 | TypeSpec singleton = TypeSpec.classBuilder(Singleton) 194 | .addModifiers(Modifier.PUBLIC) 195 | .addField(instance) 196 | .addMethod(constructor) 197 | .addMethod(getInstance) 198 | .build(); 199 | generatedCode[i] = JavaFile.builder(packageName, singleton) 200 | .skipJavaLangImports(true) 201 | .build(); 202 | return generatedCode; 203 | } 204 | ``` 205 | 206 | * Advantages of using Template Method pattern: 207 | * All the duplicate code/methods of sub-classes can be put together in the super-class 208 | * Client can override only certain methods of a large algorithm, so that the other components of the algorithm are not affected 209 | * Disadvantages of using Template Method pattern: 210 | * Sometimes client might have to change certain fundamental aspects of the algorithm and changing only certain fixed components of the algorithm might not suffice 211 | * If the number of components in the algorithm being modelled is large, it is harder to maintain the code 212 | 213 | ------ 214 | 215 | The **Singleton**, a creational design pattern, that helps in ensuring that a class has only one instance in a program while also providing a global access point to the instance. I have used Singleton to instantiate only one instance of the class `Hw1DesignPatternGenerator` so that in the client class `DePaCoG` the design pattern generating method is only called once at a time. The `instance` field in `Hw1DesignPatternGenerator` is lazy initialized. 216 | 217 | Inside class `Hw1DesignPatternGenerator`: 218 | 219 | ```java 220 | private static Hw1DesignPatternGenerator instance; 221 | 222 | private Hw1DesignPatternGenerator(){ 223 | logger.info("Executing constructor Hw1DesignPatternGenerator()"); 224 | generateDesignPattern(); 225 | } 226 | 227 | public static Hw1DesignPatternGenerator getInstance(){ 228 | if (instance == null) { 229 | instance = new Hw1DesignPatternGenerator(); 230 | } 231 | return instance; 232 | } 233 | ``` 234 | 235 | Creating instance inside `DePaCoG` class: 236 | 237 | ```java 238 | public class DePaCoG { 239 | public static void main(String[] args){ 240 | 241 | Hw1DesignPatternGenerator.getInstance(); 242 | } 243 | } 244 | ``` 245 | 246 | * Advantages of using Singleton pattern: 247 | * It makes sure that a single instance is instantiated for a class 248 | * Helps to get a global access point to the instance 249 | * The object is only initialized when initially requested 250 | * Disadvantages of using Singleton pattern: 251 | * Sometimes singleton pattern can hide bad code design 252 | * It requires modifications to be used in a multi threaded environment to make sure multiple instances are not created by multiple threads 253 | 254 | ------ 255 | 256 | The image below shows a class diagram for the complete application. For simplicity I have selected only 3 design pattern classes (each representing its category of design patterns) out of the 23. 257 | 258 | ![](screenshots/DePaCoG.png) 259 | 260 | The class `DePaCoG` has the main() method in it. It creates an instance of class `Hw1DesignPatternGenerator` (concrete implementation of `DesignPatternGenerator` ). Methods here are for displaying menu of design patterns and getting choice of design pattern from user. Depending on user’s choice the corresponding design pattern generating class (implementation of `DesignPattern`) is instantiated to generate the design pattern source code. 261 | 262 | ------ 263 | 264 | ### 4. Test Cases 265 | 266 | There are 2 test classes `DesignPatternTest` and `Hw1DesignPatternGeneratorTest`, with a total of 5 test cases. 267 | 268 | * Test Case to verify only 1 instance of `Hw1DesignPatternGenerator` is created each time. 269 | * Test Case to verify correct design pattern file is executed when user inputs the choice of design pattern. 270 | * Test Case to check null is returned on selecting incorrect design pattern choice. 271 | * Test Case to verify `generateCode()` returns `JavaFile[]` object 272 | * Test Case to verify the generated java files are written successfully in the output folder. 273 | 274 | ------ 275 | 276 | ### 5. Instructions to Execute 277 | 278 | First clone the repository from GitHub. 279 | 280 | Execution can be in two modes, using default config file or using interactive environment/menu to get custom inputs from user. 281 | 282 | The `default.conf` configuration file is present at `src/main/resources`. 283 | 284 | For command line execution, locate `hw1-assembly-0.1.jar` at `target\scala-2.13`. 285 | 286 | On Windows, the command to run the jar file: `java -jar hw1-assembly-0.1.jar mode` 287 | 288 | * Executing using default config file, then `mode = 0`: 289 | 290 | * run `java -jar hw1-assembly-0.1.jar 0` 291 | 292 | ![](screenshots/Capture4.PNG) 293 | 294 | * Executing using custom inputs from user, then `mode = 1`: 295 | 296 | * run `java -jar hw1-assembly-0.1.jar 1` 297 | 298 | ![](screenshots/Capture2.PNG) 299 | 300 | For execution in IntelliJ, use `run 0` or `run 1` for the preferred way of execution (argument passed has similar purpose like in the command line method) 301 | 302 | The output java files are saved under the package name provided in the config file (or as custom input) in a folder named `outputs`. The `outputs` folder is created in the current working directory during execution. 303 | 304 | ------ 305 | 306 | ### 6. Results of Execution 307 | 308 | While executing the Design Pattern Code Generator, the main() method in class `DePaCoG` is executed along with a command line argument (`0` or `1`). The command line argument is to select whether inputs will be entered via a configuration file or via inputs through the interactive environment. 309 | 310 | Here is an example of config values to create Abstract Factory design pattern. 311 | 312 | ``` 313 | { 314 | designPatternChoice = "2" 315 | classes = ["Processor", "Intel", "AMD", 316 | "OperatingSystem", "OS", "ChromeOS", "Ubuntu", 317 | "LaptopFactory", "ChromeBookFactory","LinuxLaptopFactory"] 318 | packageName = "com.laptopAbstractFacty" 319 | } 320 | ``` 321 | 322 | For above config input, the output files will be saved at `outputs/com/laptopAbstractFactory`. 323 | 324 | The classes created are : `Processor.java, Intel.java, AMD.java, OperatingSystem.java, OS.java, ChromeOS.java, Ubuntu.java, LaptopFactory.java, ChromeBookFactory.java,LinuxLaptopFactory.java` 325 | 326 | The image below shows the class diagram of the classes generated after executing the config input values. 327 | 328 | ![](screenshots/laptopFactory.png) 329 | 330 | In addition to Abstract Factory, the `default.conf` configuration file also contains inputs for Decorator, Adapter and Observer design patterns. 331 | 332 | The `outputs` folder is created in the current working directory during execution. 333 | 334 | 335 | 336 | --------------------------------------------------------------------------------