├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── pom.xml └── src └── main └── java └── com └── cmeza └── sdgenerator ├── SDGeneratorManager.java ├── annotation ├── SDGenerate.java ├── SDGenerator.java └── SDNoGenerate.java ├── plugin ├── CommonsMojo.java ├── SDAllMojo.java ├── SDManagerMojo.java └── SDRepositoryMojo.java ├── provider ├── AbstractTemplateProvider.java └── ClassPathScanningProvider.java ├── support ├── ManagerTemplateSupport.java ├── RepositoryTemplateSupport.java ├── ScanningConfigurationSupport.java └── maker │ ├── ManagerStructure.java │ ├── RepositoryStructure.java │ ├── builder │ ├── ObjectBuilder.java │ └── ObjectStructure.java │ └── values │ ├── AccessValues.java │ ├── CommonValues.java │ ├── ExpressionValues.java │ ├── ObjectTypeValues.java │ ├── ObjectValues.java │ └── ScopeValues.java └── util ├── BuildUtils.java ├── Constants.java ├── CustomResourceLoader.java ├── GeneratorException.java ├── GeneratorProperties.java ├── GeneratorUtils.java ├── SDLogger.java ├── SDMojoException.java └── Tuple.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | pom.xml 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | ### IntelliJ IDEA ### 12 | .idea 13 | *.iws 14 | *.iml 15 | *.ipr 16 | ### NetBeans ### 17 | nbproject/private/ 18 | build/ 19 | nbbuild/ 20 | dist/ 21 | nbdist/ 22 | .nb-gradle/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - oraclejdk8 5 | 6 | script: mvn clean verify 7 | 8 | before_install: 9 | - sudo add-apt-repository -y ppa:webupd8team/java 10 | - sudo apt-get update 11 | - sudo apt-get install -y oracle-java8-installer || true 12 | #todo remove this kludge and the above || true when the ppa is fixed 13 | - cd /var/lib/dpkg/info 14 | - sudo sed -i 's|JAVA_VERSION=8u171|JAVA_VERSION=8u181|' oracle-java8-installer.* 15 | - sudo sed -i 's|PARTNER_URL=http://download.oracle.com/otn-pub/java/jdk/8u171-b11/512cd62ec5174c3487ac17c61aaa89e8/|PARTNER_URL=http://download.oracle.com/otn-pub/java/jdk/8u181-b13/96a7b8442fe848ef90c96a2fad6ed6d1/|' oracle-java8-installer.* 16 | - sudo sed -i 's|SHA256SUM_TGZ="b6dd2837efaaec4109b36cfbb94a774db100029f98b0d78be68c27bec0275982"|SHA256SUM_TGZ="1845567095bfbfebd42ed0d09397939796d05456290fb20a83c476ba09f991d3"|' oracle-java8-installer.* 17 | - sudo sed -i 's|J_DIR=jdk1.8.0_171|J_DIR=jdk1.8.0_181|' oracle-java8-installer.* 18 | - sudo apt-get update 19 | - sudo apt-get install -y oracle-java8-installer 20 | - cd $TRAVIS_BUILD_DIR -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [2.0.1] - 2023-11-29 4 | ### Added 5 | - [Issue:33]: Enable/Disable JpaSpecificationExecutor 6 | 7 | ## [2.0.0] - 2023-02-09 8 | ### Added 9 | - Jakarta persistence support 10 | 11 | ## [1.1.9] - 2022-04-27 12 | ### Added 13 | - [Issue:25]: Hide class comments 14 | - Lombok configuration 15 | - Access "final" to manager attribute 16 | 17 | ## [1.1.8] - 2018-08-13 18 | ### Added 19 | - [Issue:20]: Missing class while generating managers with Maven plugin 20 | 21 | ## [1.1.7] - 2018-05-30 22 | ### Added 23 | - Package structure support 24 | 25 | ## [1.1.6] - 2018-04-09 26 | ### Added 27 | - @Id or @EmbeddedId primitive support 28 | 29 | ## [1.1.5] - 2017-12-21 30 | ### Fix 31 | - Fix @Id or @EmbeddedId inherited from a superclass 32 | - Fix table info 33 | 34 | ## [1.1.4] - 2017-11-29 35 | ### Added 36 | - Support JpaSpecificationExcecutor in generated JpaRepository 37 | 38 | ## [1.1.3] - 2017-07-17 39 | ### Added 40 | - Getter method annotated with @Id 41 | - Support @EmbeddedId annotation 42 | 43 | ## [1.1.2] - 2017-05-23 44 | ### Optimization 45 | - Code optimization with Sonar 46 | 47 | ## [1.1.1] - 2017-05-10 48 | ### Added 49 | - @Repository annotation in repositories 50 | - Overwrite option 51 | 52 | ## [1.1.0] - 2017-05-01 53 | ### Added 54 | - Optional Scan Annotations 55 | - Generate by plugin 56 | 57 | ## [1.0.0] - 2017-04-09 58 | ### Added 59 | - Generate in Runtime 60 | 61 | [2.0.1]: https://github.com/cmeza20/spring-data-generator/compare/2.0.0...2.0.1 62 | [2.0.0]: https://github.com/cmeza20/spring-data-generator/compare/1.1.9...2.0.0 63 | [1.1.9]: https://github.com/cmeza20/spring-data-generator/compare/1.1.8...1.1.9 64 | [1.1.8]: https://github.com/cmeza20/spring-data-generator/compare/1.1.7...1.1.8 65 | [1.1.7]: https://github.com/cmeza20/spring-data-generator/compare/1.1.6...1.1.7 66 | [1.1.6]: https://github.com/cmeza20/spring-data-generator/compare/1.1.5...1.1.6 67 | [1.1.5]: https://github.com/cmeza20/spring-data-generator/compare/1.1.4...1.1.5 68 | [1.1.4]: https://github.com/cmeza20/spring-data-generator/compare/1.1.3...1.1.4 69 | [1.1.3]: https://github.com/cmeza20/spring-data-generator/compare/1.1.2...1.1.3 70 | [1.1.2]: https://github.com/cmeza20/spring-data-generator/compare/1.1.1...1.1.2 71 | [1.1.1]: https://github.com/cmeza20/spring-data-generator/compare/1.1.0...1.1.1 72 | [1.1.0]: https://github.com/cmeza20/spring-data-generator/compare/1.0.0...1.1.0 73 | [1.0.0]: https://github.com/cmeza20/spring-data-generator/tree/1.0.0 74 | 75 | 76 | [Issue:20]: https://github.com/cmeza20/spring-data-generator/issues/20 77 | [Issue:25]: https://github.com/cmeza20/spring-data-generator/issues/25 78 | [Issue:33]: https://github.com/cmeza20/spring-data-generator/issues/33 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Carlos Meza Yana 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring Data Generator [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.cmeza/spring-data-generator/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.cmeza/spring-data-generator) 2 | 3 | Spring Data Generator for JPA repositories and managers. 4 | 5 | ## Features ## 6 | * Generate in Runtime 7 | * Generate by Plugin 8 | * Generate repositories for JPA Entities 9 | * Generate managers for JPA Entities 10 | * EntityScan wrapped annotation 11 | * Overwrite option 12 | * Support JpaSpecificationExcecutor 13 | * Support @EmbeddedId annotation 14 | * @Id or @EmbeddedId primitive support 15 | * Package structure support 16 | * Additional extends support 17 | * Lombok support 18 | * Jakarta support 19 | 20 | ## Dependencies ## 21 | 22 | * **Java 11** 23 | * **Spring data JPA** 24 | 25 | ## Generate in Runtime ## 26 | Download the jar through Maven: 27 | 28 | ```xml 29 | 30 | com.cmeza 31 | spring-data-generator 32 | 2.0.1 33 | 34 | ``` 35 | 36 | The simple Spring Data JPA configuration with Java-Config looks like this: 37 | ```java 38 | @SDGenerator( 39 | entityPackage = "com.acme.model", 40 | repositoryPackage = "com.acme.repositories", 41 | managerPackage = "com.acme.managers", 42 | repositoryPostfix = "Repository", 43 | managerPostfix = "Manager", 44 | onlyAnnotations = false, 45 | debug = false, 46 | overwrite = false, 47 | additionalExtends = { 48 | QuerydslPredicateExecutor.class 49 | }, 50 | lombokAnnotations = false, 51 | withComments = true, 52 | withJpaSpecificationExecutor = true 53 | ) 54 | @SpringBootApplication 55 | public class AppConfig { 56 | 57 | public static void main(String[] args) { 58 | SpringApplication.run(WebApplication.class, args); 59 | } 60 | 61 | } 62 | ``` 63 | 64 | | Attribute | Required | Default | Description | 65 | |----------|:-------------:|:------:|------------| 66 | | entityPackage | No | [] | Entity scan package | 67 | | repositoryPackage | No | "" | Package where the repositories will be generated | 68 | | managerPackage | No | "" | Package where the managers will be generated | 69 | | repositoryPostfix | No | "Repository" | Postfix for repositories. example: Account**Repository** | 70 | | managerPostfix | No | "Manager" | Postfix for managers. example: Account**Manager** | 71 | | onlyAnnotations | No | false | Scan only classes annotated with @SDGenerate or @SDNoGenerate | 72 | | debug | No | false | Enable debug log | 73 | | overwrite | No | false | Overwrite existing files | 74 | | additionalExtends | No | [] | Extension of additional interfaces | 75 | | lombokAnnotations | No | false | Support Lombok annotations | 76 | | withComments | No | true | Class comments activation | 77 | | withJpaSpecificationExecutor | No | true | JpaSpecificationExecutor activation | 78 | 79 | ## Generate by Plugin ## 80 | Download the jar through Maven: 81 | ```xml 82 | 83 | 84 | 85 | com.cmeza 86 | spring-data-generator 87 | 2.0.1 88 | 89 | 90 | com.acme.model 91 | 92 | com.acme.repository 93 | Repository 94 | com.acme.managers 95 | Manager 96 | false 97 | false 98 | 99 | org.springframework.data.querydsl.QuerydslPredicateExecutor 100 | 101 | false 102 | true 103 | true 104 | 105 | 106 | 107 | 108 | ``` 109 | 110 | | Attribute | Required | Default | Description | 111 | |----------|:-------------:|:------:|------------| 112 | | entity-package | Yes | [] | Entity scan package | 113 | | repository-package | Yes | "" | Package where the repositories will be generated | 114 | | manager-package | Yes | "" | Package where the managers will be generated | 115 | | repository-postfix | No | "Repository" | Postfix for repositories. example: Account**Repository** | 116 | | manager-postfix | No | "Manager" | Postfix for managers. example: Account**Manager** | 117 | | onlyAnnotations | No | false | Scan only classes annotated with @SDGenerate or @SDNoGenerate | 118 | | overwrite | No | false | Overwrite existing files | 119 | | additional-extends | No | [] | Extension of additional interfaces | 120 | | lombok-annotations | No | false | Support Lombok annotations | 121 | | with-comments | No | true | Class comments activation | 122 | | with-JpaSpecificationExecutor | No | true | JpaSpecificationExecutor activation | 123 | 124 | #### Generate repositories (terminal) 125 | ``` 126 | $ mvn spring-data-generator:repositories 127 | ``` 128 | #### Generate managers (terminal) 129 | ``` 130 | $ mvn spring-data-generator:managers 131 | ``` 132 | 133 | ## Example ## 134 | 135 | Sample entity in `com.acme.model` 136 | 137 | ```java 138 | 139 | //import javax.persistence.Entity; //javax persistence support 140 | //import javax.persistence.Id; //javax persistence support 141 | import jakarta.persistence.Entity; //jakarta persistence support 142 | import jakarta.persistence.Id; //jakarta persistence support 143 | 144 | @Entity 145 | //@SDGenerate -> Optional: Include to classes scan 146 | //@SDNoGenerate -> Optional: Exclude to classes scan 147 | public class Account { 148 | 149 | @Id 150 | @GeneratedValue 151 | private Long id; 152 | private String firstname; 153 | private String lastname; 154 | 155 | // Getters and setters 156 | // (Firstname, Lastname)-constructor and noargs-constructor 157 | // equals / hashcode 158 | } 159 | ``` 160 | 161 | Generate a repository interface example in `com.acme.repositories`: 162 | 163 | ```java 164 | // With JpaSpecificationExecutor interface 165 | @Repository 166 | public interface AccountRepository extends JpaRepository, JpaSpecificationExecutor { 167 | } 168 | ``` 169 | 170 | ```java 171 | // Without JpaSpecificationExecutor interface 172 | @Repository 173 | public interface AccountRepository extends JpaRepository { 174 | } 175 | ``` 176 | 177 | Generate a manager class example in `com.acme.managers`: 178 | 179 | Without Lombok 180 | ```java 181 | @Component 182 | public class AccountManager { 183 | 184 | private final AccountRepository accountRepository; 185 | 186 | @Autowired 187 | public AccountManager(AccountRepository accountRepository) { 188 | this.accountRepository = accountRepository; 189 | } 190 | } 191 | ``` 192 | With Lombok 193 | 194 | ```java 195 | @Component 196 | @RequiredArgsConstructor 197 | public class AccountManager { 198 | 199 | private final AccountRepository accountRepository; 200 | 201 | } 202 | ``` 203 | 204 | ## Notes ## 205 | 206 | * The overwrite option delete the existing file to regenerate 207 | * The generation of repositories and managers inherits the entity package. Example: 208 | 209 | ![alt tag](https://user-images.githubusercontent.com/9298942/39490821-bf4b53b6-4d4f-11e8-9853-fb4ece43346e.png "Package structure support") 210 | 211 | License 212 | ---- 213 | 214 | MIT 215 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cmeza 8 | spring-data-generator 9 | maven-plugin 10 | 2.0.1 11 | 12 | ${project.groupId}:${project.artifactId} 13 | Spring Data Generator for JPA repositories and managers. 14 | https://github.com/cmeza20/spring-data-generator 15 | 16 | 17 | 18 | MIT License 19 | http://www.opensource.org/licenses/mit-license.php 20 | 21 | 22 | 23 | 24 | 25 | Carlos Meza Yana 26 | cmeza.20@gmail.com 27 | CMeza 28 | http://www.cmeza.com 29 | 30 | 31 | 32 | 33 | scm:git:git://github.com/cmeza20/spring-data-generator.git 34 | scm:git:ssh://github.com:cmeza20/spring-data-generator.git 35 | https://github.com/cmeza20/spring-data-generator/tree/master 36 | 37 | 38 | 39 | 2.7.12 40 | 1.0.2 41 | 3.1.0 42 | 3.9.0 43 | 3.4 44 | 0.3.2 45 | 1.18.24 46 | UTF-8 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-autoconfigure 53 | ${spring-version} 54 | 55 | 56 | javax.persistence 57 | persistence-api 58 | ${javax-persistance-api-version} 59 | 60 | 61 | org.apache.maven 62 | maven-core 63 | ${maven-core-version} 64 | 65 | 66 | org.apache.maven.plugin-tools 67 | maven-plugin-annotations 68 | ${maven-plugin-annotation-version} 69 | provided 70 | 71 | 72 | de.vandermeer 73 | asciitable 74 | ${asciitable-version} 75 | 76 | 77 | org.projectlombok 78 | lombok 79 | ${lombok-version} 80 | 81 | 82 | jakarta.persistence 83 | jakarta.persistence-api 84 | ${jakarta-persistance-api-version} 85 | 86 | 87 | 88 | 89 | 90 | 91 | ossrh 92 | https://oss.sonatype.org/content/repositories/snapshots 93 | 94 | 95 | ossrh 96 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 97 | 98 | 99 | 100 | 101 | spring-data-generator 102 | 103 | 104 | maven-compiler-plugin 105 | 3.3 106 | 107 | 11 108 | 11 109 | 110 | 111 | 112 | org.apache.maven.plugins 113 | maven-source-plugin 114 | 2.2.1 115 | 116 | 117 | attach-sources 118 | 119 | jar-no-fork 120 | 121 | 122 | 123 | 124 | 125 | org.apache.maven.plugins 126 | maven-javadoc-plugin 127 | 2.9.1 128 | 129 | 130 | attach-javadocs 131 | 132 | jar 133 | 134 | 135 | 136 | 137 | 138 | org.apache.maven.plugins 139 | maven-plugin-plugin 140 | 3.6.4 141 | 142 | 143 | org.sonarsource.scanner.maven 144 | sonar-maven-plugin 145 | 3.2 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/SDGeneratorManager.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator; 2 | 3 | import com.cmeza.sdgenerator.annotation.SDGenerator; 4 | import com.cmeza.sdgenerator.support.ManagerTemplateSupport; 5 | import com.cmeza.sdgenerator.support.RepositoryTemplateSupport; 6 | import com.cmeza.sdgenerator.support.ScanningConfigurationSupport; 7 | import com.cmeza.sdgenerator.util.GeneratorUtils; 8 | import com.cmeza.sdgenerator.util.SDLogger; 9 | import com.google.common.collect.Iterables; 10 | import org.springframework.beans.factory.config.BeanDefinition; 11 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 12 | import org.springframework.context.EnvironmentAware; 13 | import org.springframework.context.ResourceLoaderAware; 14 | import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; 15 | import org.springframework.core.annotation.AnnotationAttributes; 16 | import org.springframework.core.env.Environment; 17 | import org.springframework.core.io.ResourceLoader; 18 | import org.springframework.core.type.AnnotationMetadata; 19 | import org.springframework.util.Assert; 20 | 21 | import java.util.*; 22 | 23 | /** 24 | * Created by carlos on 08/04/17. 25 | */ 26 | public class SDGeneratorManager implements ImportBeanDefinitionRegistrar, EnvironmentAware, ResourceLoaderAware { 27 | 28 | private Environment environment; 29 | private ResourceLoader resourceLoader; 30 | 31 | @Override 32 | public void setEnvironment(Environment environment) { 33 | this.environment = environment; 34 | } 35 | 36 | @Override 37 | public void setResourceLoader(ResourceLoader resourceLoader) { 38 | this.resourceLoader = resourceLoader; 39 | } 40 | 41 | @Override 42 | public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { 43 | Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null!"); 44 | Assert.notNull(beanDefinitionRegistry, "BeanDefinitionRegistry must not be null!"); 45 | 46 | if (annotationMetadata.getAnnotationAttributes(SDGenerator.class.getName()) != null) { 47 | 48 | AnnotationAttributes attributes = new AnnotationAttributes(annotationMetadata.getAnnotationAttributes(SDGenerator.class.getName())); 49 | 50 | String repositoryPackage = attributes.getString("repositoryPackage"); 51 | String managerPackage = attributes.getString("managerPackage"); 52 | boolean lombokAnnotations = attributes.getBoolean("lombokAnnotations"); 53 | boolean withComments = attributes.getBoolean("withComments"); 54 | boolean withJpaSpecificationExecutor = attributes.getBoolean("withJpaSpecificationExecutor"); 55 | 56 | if (!managerPackage.isEmpty() && repositoryPackage.isEmpty()) { 57 | SDLogger.error("Repositories must be generated before generating managers"); 58 | return; 59 | } 60 | 61 | if (!repositoryPackage.isEmpty() || !managerPackage.isEmpty()) { 62 | ScanningConfigurationSupport configurationSource = new ScanningConfigurationSupport(annotationMetadata, attributes, this.environment); 63 | 64 | Collection candidates = configurationSource.getCandidates(resourceLoader); 65 | 66 | String absolutePath = GeneratorUtils.getAbsolutePath(); 67 | if (absolutePath == null) { 68 | SDLogger.addError("Could not define the absolute path!"); 69 | return; 70 | } 71 | 72 | if (!repositoryPackage.isEmpty()) { 73 | 74 | String repositoriesPath = absolutePath + repositoryPackage.replace(".", "/"); 75 | Set additionalExtends = this.validateExtends(attributes.getClassArray("additionalExtends")); 76 | if (Objects.nonNull(additionalExtends)) { 77 | RepositoryTemplateSupport repositoryTemplateSupport = new RepositoryTemplateSupport(attributes, additionalExtends, withComments, withJpaSpecificationExecutor); 78 | repositoryTemplateSupport.initializeCreation(repositoriesPath, repositoryPackage, candidates, Iterables.toArray(configurationSource.getBasePackages(), String.class)); 79 | } 80 | } 81 | 82 | if (!repositoryPackage.isEmpty() && !managerPackage.isEmpty()) { 83 | 84 | String managerPath = absolutePath + managerPackage.replace(".", "/"); 85 | 86 | String repositoryPostfix = attributes.getString("repositoryPostfix"); 87 | 88 | ManagerTemplateSupport managerTemplateSupport = new ManagerTemplateSupport(attributes, repositoryPackage, repositoryPostfix, lombokAnnotations, withComments); 89 | managerTemplateSupport.initializeCreation(managerPath, managerPackage, candidates, Iterables.toArray(configurationSource.getBasePackages(), String.class)); 90 | } 91 | 92 | SDLogger.printGeneratedTables(attributes.getBoolean("debug")); 93 | } 94 | 95 | } 96 | } 97 | 98 | private Set validateExtends(Class[] additionalExtends) { 99 | boolean errorValidate = Boolean.FALSE; 100 | Set additionalExtendsList = new LinkedHashSet<>(); 101 | for (Class extendTemporal : additionalExtends) { 102 | SDLogger.addAdditionalExtend(extendTemporal.getName()); 103 | 104 | if (!extendTemporal.isInterface()) { 105 | SDLogger.addError(String.format("'%s' is not a interface!", extendTemporal.getName())); 106 | errorValidate = Boolean.TRUE; 107 | } else { 108 | additionalExtendsList.add(extendTemporal.getName()); 109 | } 110 | } 111 | 112 | if (errorValidate) { 113 | return null; 114 | } 115 | 116 | return additionalExtendsList; 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/annotation/SDGenerate.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by carlos on 22/04/17. 7 | */ 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface SDGenerate { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/annotation/SDGenerator.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.annotation; 2 | 3 | import com.cmeza.sdgenerator.SDGeneratorManager; 4 | import org.springframework.boot.autoconfigure.domain.EntityScan; 5 | import org.springframework.context.annotation.Import; 6 | import org.springframework.core.annotation.AliasFor; 7 | 8 | import java.lang.annotation.*; 9 | 10 | /** 11 | * Created by carlos on 08/04/17. 12 | */ 13 | @Target(ElementType.TYPE) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Documented 16 | @Inherited 17 | @EntityScan 18 | @Import(SDGeneratorManager.class) 19 | public @interface SDGenerator { 20 | 21 | String repositoryPackage() default ""; 22 | String repositoryPostfix() default "Repository"; 23 | Class[] excludeRepositoriesClasses() default {}; 24 | 25 | String managerPackage() default ""; 26 | String managerPostfix() default "Manager"; 27 | Class[] excludeManagerClasses() default {}; 28 | 29 | @AliasFor(annotation = EntityScan.class, attribute = "basePackages") 30 | String[] entityPackage() default {}; 31 | 32 | boolean debug() default false; 33 | 34 | boolean onlyAnnotations() default false; 35 | 36 | boolean overwrite() default false; 37 | 38 | boolean lombokAnnotations() default false; 39 | 40 | boolean withComments() default true; 41 | 42 | boolean withJpaSpecificationExecutor() default true; 43 | 44 | Class[] additionalExtends() default {}; 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/annotation/SDNoGenerate.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by carlos on 22/04/17. 7 | */ 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface SDNoGenerate { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/plugin/CommonsMojo.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.plugin; 2 | 3 | import com.cmeza.sdgenerator.util.*; 4 | import org.apache.maven.plugin.AbstractMojo; 5 | import org.apache.maven.plugins.annotations.Component; 6 | import org.apache.maven.plugins.annotations.Parameter; 7 | import org.apache.maven.project.MavenProject; 8 | 9 | import java.util.LinkedHashSet; 10 | import java.util.Set; 11 | 12 | /** 13 | * Created by carlos on 01/05/17. 14 | */ 15 | public abstract class CommonsMojo extends AbstractMojo { 16 | 17 | @Parameter(name = Constants.ENTITY_PACKAGE) 18 | protected String[] entityPackage; 19 | 20 | @Parameter(name = Constants.REPOSITORY_PACKAGE) 21 | protected String repositoryPackage; 22 | 23 | @Parameter(name = Constants.REPOSITORY_POSTFIX, defaultValue = "Repository") 24 | protected String repositoryPostfix; 25 | 26 | @Parameter(name = Constants.MAGANER_PACKAGE) 27 | protected String managerPackage; 28 | 29 | @Parameter(name = Constants.MANAGER_POSTFIX, defaultValue = "Manager") 30 | protected String managerPostfix; 31 | 32 | @Parameter(name = Constants.ONLY_ANNOTATIONS, defaultValue = "false") 33 | protected Boolean onlyAnnotations; 34 | 35 | @Parameter(name = Constants.OVERWRITE, defaultValue = "false") 36 | protected Boolean overwrite; 37 | 38 | @Parameter(name = Constants.LOMBOK_ANOTATIONS, defaultValue = "false") 39 | protected Boolean lombokAnnotations; 40 | 41 | @Parameter(name = Constants.WITH_COMMENTS, defaultValue = "true") 42 | protected Boolean withComments; 43 | 44 | @Parameter(name = Constants.WITH_JPASPECIFICATIONEXECUTOR, defaultValue = "true") 45 | protected Boolean withJpaSpecificationExecutor; 46 | 47 | @Parameter(name = Constants.EXTENDS) 48 | protected String[] additionalExtends; 49 | 50 | @Component 51 | protected MavenProject project; 52 | 53 | protected Set additionalExtendsList = new LinkedHashSet<>(); 54 | 55 | public void validateField(String parameter) throws SDMojoException { 56 | 57 | boolean errorFound = Boolean.FALSE; 58 | 59 | switch (parameter) { 60 | case Constants.ENTITY_PACKAGE: 61 | if (entityPackage == null) { 62 | errorFound = Boolean.TRUE; 63 | } 64 | break; 65 | case Constants.REPOSITORY_PACKAGE: 66 | if (repositoryPackage == null) { 67 | errorFound = Boolean.TRUE; 68 | } 69 | break; 70 | case Constants.REPOSITORY_POSTFIX: 71 | if (repositoryPostfix == null) { 72 | errorFound = Boolean.TRUE; 73 | } 74 | break; 75 | case Constants.MAGANER_PACKAGE: 76 | if (managerPackage == null) { 77 | errorFound = Boolean.TRUE; 78 | } 79 | break; 80 | case Constants.MANAGER_POSTFIX: 81 | if (managerPostfix == null) { 82 | errorFound = Boolean.TRUE; 83 | } 84 | break; 85 | case Constants.EXTENDS: 86 | if (additionalExtends != null) { 87 | this.validateExtends(); 88 | } 89 | break; 90 | default: 91 | SDLogger.addError( String.format("%s configuration parameter not found!", parameter)); 92 | throw new SDMojoException(); 93 | } 94 | 95 | if (errorFound) { 96 | SDLogger.addError( String.format("%s configuration not found!", parameter)); 97 | throw new SDMojoException(); 98 | } 99 | } 100 | 101 | private void validateExtends() throws SDMojoException { 102 | String extendTemporal; 103 | boolean errorValidate = Boolean.FALSE; 104 | for (int i = 0; i < additionalExtends.length; i++) { 105 | extendTemporal = additionalExtends[i]; 106 | SDLogger.addAdditionalExtend(extendTemporal); 107 | if (extendTemporal.contains(".")){ 108 | additionalExtendsList.add(extendTemporal); 109 | } else { 110 | errorValidate = Boolean.TRUE; 111 | SDLogger.addError( String.format("'%s' is not a valid object!", extendTemporal)); 112 | } 113 | } 114 | 115 | if (errorValidate) { 116 | throw new SDMojoException(); 117 | } 118 | } 119 | 120 | protected GeneratorProperties buildProperties() { 121 | return GeneratorProperties.builder() 122 | .entityPackage(entityPackage) 123 | .repositoryPackage(repositoryPackage) 124 | .repositoryPostfix(repositoryPostfix) 125 | .managerPackage(managerPackage) 126 | .managerPostfix(managerPostfix) 127 | .onlyAnnotations(onlyAnnotations) 128 | .overwrite(overwrite) 129 | .lombokAnnotations(lombokAnnotations) 130 | .withComments(withComments) 131 | .withJpaSpecificationExecutor(withJpaSpecificationExecutor) 132 | .additionalExtendsList(additionalExtendsList) 133 | .project(project) 134 | .build(); 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/plugin/SDAllMojo.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.plugin; 2 | 3 | import com.cmeza.sdgenerator.util.Constants; 4 | import com.cmeza.sdgenerator.util.GeneratorProperties; 5 | import com.cmeza.sdgenerator.util.SDLogger; 6 | import com.cmeza.sdgenerator.util.SDMojoException; 7 | import org.apache.maven.plugin.MojoExecutionException; 8 | import org.apache.maven.plugin.MojoFailureException; 9 | import org.apache.maven.plugins.annotations.Execute; 10 | import org.apache.maven.plugins.annotations.LifecyclePhase; 11 | import org.apache.maven.plugins.annotations.Mojo; 12 | 13 | /** 14 | * Created by carlos on 25/04/22. 15 | */ 16 | @Mojo(name = "all") 17 | @Execute(phase = LifecyclePhase.COMPILE) 18 | @SuppressWarnings("unused") 19 | public class SDAllMojo extends CommonsMojo { 20 | 21 | @Override 22 | public void execute() throws MojoExecutionException, MojoFailureException { 23 | 24 | SDLogger.configure(getLog()); 25 | 26 | this.validateField(Constants.ENTITY_PACKAGE); 27 | this.validateField(Constants.REPOSITORY_PACKAGE); 28 | this.validateField(Constants.EXTENDS); 29 | 30 | try { 31 | GeneratorProperties generatorProperties = this.buildProperties(); 32 | 33 | SDRepositoryMojo sdRepositoryMojo = new SDRepositoryMojo(); 34 | sdRepositoryMojo.executeInternalMojo(generatorProperties); 35 | 36 | SDManagerMojo sdManagerMojo = new SDManagerMojo(); 37 | sdManagerMojo.executeInternalMojo(generatorProperties); 38 | 39 | SDLogger.printGeneratedTables(true); 40 | } catch (Exception e) { 41 | SDLogger.addError(e.getMessage()); 42 | throw new SDMojoException(e.getMessage(), e); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/plugin/SDManagerMojo.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.plugin; 2 | 3 | import com.cmeza.sdgenerator.support.ManagerTemplateSupport; 4 | import com.cmeza.sdgenerator.support.ScanningConfigurationSupport; 5 | import com.cmeza.sdgenerator.util.*; 6 | import org.apache.maven.plugin.MojoExecutionException; 7 | import org.apache.maven.plugin.MojoFailureException; 8 | import org.apache.maven.plugins.annotations.Execute; 9 | import org.apache.maven.plugins.annotations.LifecyclePhase; 10 | import org.apache.maven.plugins.annotations.Mojo; 11 | 12 | /** 13 | * Created by carlos on 22/04/17. 14 | */ 15 | @Mojo(name = "managers") 16 | @Execute(phase = LifecyclePhase.COMPILE) 17 | @SuppressWarnings("unused") 18 | public class SDManagerMojo extends CommonsMojo { 19 | 20 | @Override 21 | public void execute() throws MojoExecutionException, MojoFailureException { 22 | 23 | SDLogger.configure(getLog()); 24 | 25 | this.validateField(Constants.ENTITY_PACKAGE); 26 | this.validateField(Constants.MAGANER_PACKAGE); 27 | this.validateField(Constants.REPOSITORY_PACKAGE); 28 | 29 | try { 30 | GeneratorProperties generatorProperties = this.buildProperties(); 31 | this.executeInternalMojo(generatorProperties); 32 | 33 | SDLogger.printGeneratedTables(true); 34 | 35 | } catch (Exception e) { 36 | SDLogger.addError(e.getMessage()); 37 | throw new SDMojoException(e.getMessage(), e); 38 | } 39 | } 40 | 41 | public void executeInternalMojo(GeneratorProperties generatorProperties) throws MojoExecutionException { 42 | CustomResourceLoader resourceLoader = new CustomResourceLoader(generatorProperties.getProject()); 43 | resourceLoader.setPostfix(generatorProperties.getManagerPostfix()); 44 | resourceLoader.setRepositoryPackage(generatorProperties.getRepositoryPackage()); 45 | resourceLoader.setRepositoryPostfix(generatorProperties.getRepositoryPostfix()); 46 | resourceLoader.setOverwrite(generatorProperties.isOverwrite()); 47 | 48 | String absolutePath = GeneratorUtils.getAbsolutePath(generatorProperties.getManagerPackage()); 49 | if (absolutePath == null) { 50 | SDLogger.addError("Could not define the absolute path of the managers"); 51 | throw new SDMojoException(); 52 | } 53 | 54 | ScanningConfigurationSupport scanningConfigurationSupport = new ScanningConfigurationSupport(generatorProperties.getEntityPackage(), generatorProperties.isOnlyAnnotations()); 55 | 56 | ManagerTemplateSupport managerTemplateSupport = new ManagerTemplateSupport(resourceLoader, generatorProperties.isLombokAnnotations(), generatorProperties.isWithComments()); 57 | managerTemplateSupport.initializeCreation(absolutePath, generatorProperties.getManagerPackage(), scanningConfigurationSupport.getCandidates(resourceLoader), generatorProperties.getEntityPackage()); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/plugin/SDRepositoryMojo.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.plugin; 2 | 3 | import com.cmeza.sdgenerator.support.RepositoryTemplateSupport; 4 | import com.cmeza.sdgenerator.support.ScanningConfigurationSupport; 5 | import com.cmeza.sdgenerator.util.*; 6 | import org.apache.maven.plugin.MojoExecutionException; 7 | import org.apache.maven.plugin.MojoFailureException; 8 | import org.apache.maven.plugins.annotations.Execute; 9 | import org.apache.maven.plugins.annotations.LifecyclePhase; 10 | import org.apache.maven.plugins.annotations.Mojo; 11 | 12 | /** 13 | * Created by carlos on 22/04/17. 14 | */ 15 | @Mojo(name = "repositories", requiresDependencyResolution = ResolutionScope.RUNTIME) 16 | @Execute(phase = LifecyclePhase.COMPILE) 17 | @SuppressWarnings("unused") 18 | public class SDRepositoryMojo extends CommonsMojo { 19 | 20 | @Override 21 | public void execute() throws MojoExecutionException, MojoFailureException { 22 | 23 | SDLogger.configure(getLog()); 24 | 25 | this.validateField(Constants.ENTITY_PACKAGE); 26 | this.validateField(Constants.REPOSITORY_PACKAGE); 27 | this.validateField(Constants.MAGANER_PACKAGE); 28 | this.validateField(Constants.EXTENDS); 29 | 30 | try { 31 | GeneratorProperties generatorProperties = this.buildProperties(); 32 | this.executeInternalMojo(generatorProperties); 33 | SDLogger.printGeneratedTables(true); 34 | } catch (Exception e) { 35 | SDLogger.addError(e.getMessage()); 36 | throw new SDMojoException(e.getMessage(), e); 37 | } 38 | } 39 | 40 | public void executeInternalMojo(GeneratorProperties generatorProperties) throws MojoExecutionException { 41 | CustomResourceLoader resourceLoader = new CustomResourceLoader(generatorProperties.getProject()); 42 | resourceLoader.setPostfix(generatorProperties.getRepositoryPostfix()); 43 | resourceLoader.setOverwrite(generatorProperties.isOverwrite()); 44 | 45 | String absolutePath = GeneratorUtils.getAbsolutePath(generatorProperties.getRepositoryPackage()); 46 | if (absolutePath == null) { 47 | SDLogger.addError("Could not define the absolute path of the repositories"); 48 | throw new SDMojoException(); 49 | } 50 | 51 | ScanningConfigurationSupport scanningConfigurationSupport = new ScanningConfigurationSupport(generatorProperties.getEntityPackage(), generatorProperties.isOnlyAnnotations()); 52 | 53 | RepositoryTemplateSupport repositoryTemplateSupport = new RepositoryTemplateSupport(resourceLoader, generatorProperties.getAdditionalExtendsList(), generatorProperties.isWithComments(), generatorProperties.isWithJpaSpecificationExecutor()); 54 | repositoryTemplateSupport.initializeCreation(absolutePath, generatorProperties.getRepositoryPackage(), scanningConfigurationSupport.getCandidates(resourceLoader), generatorProperties.getEntityPackage()); 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/provider/AbstractTemplateProvider.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.provider; 2 | 3 | import com.cmeza.sdgenerator.util.CustomResourceLoader; 4 | import com.cmeza.sdgenerator.util.GeneratorUtils; 5 | import com.cmeza.sdgenerator.util.SDLogger; 6 | import com.cmeza.sdgenerator.util.Tuple; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.beans.factory.config.BeanDefinition; 9 | import org.springframework.core.annotation.AnnotationAttributes; 10 | import org.springframework.util.Assert; 11 | 12 | import java.io.BufferedWriter; 13 | import java.io.File; 14 | import java.io.FileWriter; 15 | import java.io.IOException; 16 | import java.util.*; 17 | 18 | /** 19 | * Created by carlos on 08/04/17. 20 | */ 21 | public abstract class AbstractTemplateProvider { 22 | 23 | private final Class[] excludeClasses; 24 | private final String postfix; 25 | private final boolean debug; 26 | private Collection includeFilter; 27 | private String includeFilterPostfix = ""; 28 | private final boolean overwrite; 29 | 30 | protected AbstractTemplateProvider(AnnotationAttributes attributes) { 31 | Assert.notNull(attributes, "AnnotationAttributes must not be null!"); 32 | this.excludeClasses = attributes.getClassArray(getExcludeClasses()); 33 | this.postfix = attributes.getString(getPostfix()); 34 | this.debug = attributes.getBoolean("debug"); 35 | this.overwrite = attributes.getBoolean("overwrite"); 36 | if (excludeClasses.length > 0 && debug) { 37 | SDLogger.debug(String.format("Exclude %s %s in the %s generator", excludeClasses.length, excludeClasses.length == 1 ? "entity" : "entities", postfix)); 38 | } 39 | } 40 | 41 | protected AbstractTemplateProvider(CustomResourceLoader customResourceLoader) { 42 | Assert.notNull(customResourceLoader, "CustomResourceLoader must not be null!"); 43 | this.postfix = customResourceLoader.getPostfix(); 44 | this.debug = true; 45 | this.excludeClasses = new Class[]{}; 46 | this.overwrite = customResourceLoader.isOverwrite(); 47 | } 48 | 49 | public void initializeCreation(String path, String ePackage, Collection candidates, String[] entityPackage) { 50 | int generatedCount = 0; 51 | 52 | if (!GeneratorUtils.verifyPackage(path)) { 53 | return; 54 | } 55 | 56 | Arrays.sort(entityPackage, Comparator.comparingInt(String::length)); 57 | 58 | for (BeanDefinition beanDefinition : candidates) { 59 | 60 | if (verifyEntityNonExclude(beanDefinition.getBeanClassName())) { 61 | continue; 62 | } 63 | 64 | if (createHelper(path, beanDefinition, postfix, ePackage, entityPackage)) { 65 | generatedCount++; 66 | } 67 | } 68 | 69 | SDLogger.plusGenerated(generatedCount); 70 | } 71 | 72 | protected void setIncludeFilter(Collection includeFilter) { 73 | this.includeFilter = includeFilter; 74 | } 75 | 76 | protected void setIncludeFilterPostfix(String includeFilterPostfix) { 77 | this.includeFilterPostfix = includeFilterPostfix; 78 | } 79 | 80 | private Tuple verifyIncludeFilter(String beanDefinitionName) { 81 | int warnPosition = 0; 82 | 83 | if (includeFilter == null) { 84 | return new Tuple<>(Boolean.TRUE, warnPosition); 85 | } 86 | 87 | boolean result = includeFilter.stream().anyMatch(i -> 88 | i.getName().replace(".java", "") 89 | .equals(beanDefinitionName + includeFilterPostfix) 90 | ); 91 | 92 | if (!result) { 93 | warnPosition = SDLogger.addWarn(String.format("%s ignored: Repository not found for %s entity class", postfix, beanDefinitionName)); 94 | } 95 | return new Tuple<>(result, warnPosition); 96 | } 97 | 98 | private boolean verifyEntityNonExclude(String beanClassName) { 99 | return Arrays.stream(excludeClasses).anyMatch(b -> b.getName().equals(beanClassName)); 100 | } 101 | 102 | private boolean createHelper(String path, BeanDefinition beanDefinition, String postfix, String repositoryPackage, String[] entityPackage) { 103 | Assert.notNull(beanDefinition, "BeanDefinition is null"); 104 | String simpleClassName = GeneratorUtils.getSimpleClassName(beanDefinition.getBeanClassName()); 105 | Tuple result = null; 106 | if (simpleClassName != null) { 107 | 108 | String fileHelper = simpleClassName + postfix + ".java"; 109 | 110 | String additionalPath = this.getAdditionalPath(entityPackage, beanDefinition, simpleClassName, path); 111 | String additionalPackage = ""; 112 | if (!StringUtils.isEmpty(additionalPath)) { 113 | repositoryPackage += "." + additionalPath; 114 | additionalPackage = additionalPath; 115 | additionalPath = additionalPath.replace(".", File.separator) + File.separator; 116 | } 117 | String filePath = path + File.separator + additionalPath + fileHelper; 118 | 119 | Tuple verifyInclude = verifyIncludeFilter(simpleClassName); 120 | if (!verifyInclude.left()) { 121 | SDLogger.addRowGeneratedTable(postfix, fileHelper, "Warn #" + verifyInclude.right()); 122 | return false; 123 | } 124 | 125 | File file = new File(filePath); 126 | 127 | String fileCondition = "Created"; 128 | if (overwrite && file.exists()) { 129 | GeneratorUtils.deleteQuietly(file); 130 | fileCondition = "Overwritten"; 131 | } 132 | 133 | if (!file.exists()) { 134 | result = createFileFromTemplate(filePath, repositoryPackage, simpleClassName, postfix, beanDefinition, additionalPackage); 135 | if (debug) { 136 | SDLogger.addRowGeneratedTable(postfix, fileHelper, result.left() ? fileCondition : "Error #" + result.right()); 137 | } 138 | } 139 | } else { 140 | SDLogger.addError(String.format("Could not get SimpleName from: %s", beanDefinition.getBeanClassName())); 141 | } 142 | 143 | return result != null && result.left(); 144 | } 145 | 146 | protected abstract Tuple getContentFromTemplate(String mPackage, String simpleClassName, String postfix, BeanDefinition beanDefinition, String additionalPackage); 147 | 148 | private Tuple createFileFromTemplate(String path, String repositoryPackage, String simpleClassName, String postfix, BeanDefinition beanDefinition, String additionalPackage) { 149 | Tuple content = getContentFromTemplate(repositoryPackage, simpleClassName, postfix, beanDefinition, additionalPackage); 150 | if (content.left() == null) { 151 | return new Tuple<>(false, content.right()); 152 | } 153 | 154 | try (BufferedWriter bw = new BufferedWriter(new FileWriter(path))) { 155 | bw.write(content.left()); 156 | return new Tuple<>(true, 0); 157 | } catch (IOException e) { 158 | return new Tuple<>(false, SDLogger.addError("Error occurred while persisting file: " + e.getMessage())); 159 | } 160 | } 161 | 162 | protected abstract String getExcludeClasses(); 163 | 164 | protected abstract String getPostfix(); 165 | 166 | private String getAdditionalPath(String[] entityPackages, BeanDefinition beanDefinition, String filename, String path) { 167 | List additionalFolders = new ArrayList<>(); 168 | for (String entityPackage : entityPackages) { 169 | if (beanDefinition.getBeanClassName().startsWith(entityPackage)) { 170 | String stack = beanDefinition.getBeanClassName().replace(entityPackage, "").replace(filename, ""); 171 | if (stack.length() > 1) { 172 | if (stack.startsWith(".")) { 173 | stack = stack.substring(1); 174 | } 175 | if (stack.endsWith(".")) { 176 | stack = stack.substring(0, stack.length() - 1); 177 | } 178 | additionalFolders.add(stack); 179 | } 180 | } 181 | } 182 | 183 | if (!additionalFolders.isEmpty()) { 184 | additionalFolders.sort((a, b) -> Integer.compare(b.length(), a.length())); 185 | String additional = path + "/" + additionalFolders.get(0); 186 | String pathAdditional = additional.replace(".", "/"); 187 | GeneratorUtils.verifyPackage(pathAdditional); 188 | return additionalFolders.get(0); 189 | } 190 | return ""; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/provider/ClassPathScanningProvider.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.provider; 2 | 3 | import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; 4 | import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; 5 | import org.springframework.core.type.filter.AnnotationTypeFilter; 6 | 7 | import java.lang.annotation.Annotation; 8 | 9 | /** 10 | * Created by carlos on 08/04/17. 11 | */ 12 | public class ClassPathScanningProvider extends ClassPathScanningCandidateComponentProvider { 13 | 14 | private Class classComparator; 15 | 16 | public ClassPathScanningProvider() { 17 | super(false); 18 | } 19 | 20 | public void setIncludeAnnotation(Class annotation) { 21 | this.classComparator = annotation; 22 | super.addIncludeFilter(new AnnotationTypeFilter(annotation)); 23 | } 24 | 25 | public void setExcludeAnnotation(Class annotation) { 26 | super.addExcludeFilter(new AnnotationTypeFilter(annotation)); 27 | } 28 | 29 | @Override 30 | protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { 31 | if (classComparator == null) { 32 | return false; 33 | } 34 | 35 | boolean isNonRepositoryInterface = !classComparator.getName().equals(beanDefinition.getBeanClassName()); 36 | boolean isTopLevelType = !beanDefinition.getMetadata().hasEnclosingClass(); 37 | return isNonRepositoryInterface && isTopLevelType; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/ManagerTemplateSupport.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support; 2 | 3 | import com.cmeza.sdgenerator.provider.AbstractTemplateProvider; 4 | import com.cmeza.sdgenerator.support.maker.ManagerStructure; 5 | import com.cmeza.sdgenerator.util.CustomResourceLoader; 6 | import com.cmeza.sdgenerator.util.GeneratorUtils; 7 | import com.cmeza.sdgenerator.util.Tuple; 8 | import org.springframework.beans.factory.config.BeanDefinition; 9 | import org.springframework.core.annotation.AnnotationAttributes; 10 | 11 | import java.io.File; 12 | import java.util.Arrays; 13 | 14 | /** 15 | * Created by carlos on 08/04/17. 16 | */ 17 | public class ManagerTemplateSupport extends AbstractTemplateProvider { 18 | 19 | private final String repositoryPackage; 20 | private final String repositoryPostfix; 21 | private final boolean lombokAnnotations; 22 | private final boolean withComments; 23 | 24 | public ManagerTemplateSupport(AnnotationAttributes attributes, String repositoryPackage, String repositoryPostfix, boolean lombokAnnotations, boolean withComments) { 25 | super(attributes); 26 | this.repositoryPackage = repositoryPackage; 27 | this.repositoryPostfix = repositoryPostfix; 28 | this.lombokAnnotations = lombokAnnotations; 29 | this.withComments = withComments; 30 | this.findFilterRepositories(); 31 | } 32 | 33 | public ManagerTemplateSupport(CustomResourceLoader customResourceLoader, boolean lombokAnnotations, boolean withComments) { 34 | super(customResourceLoader); 35 | this.repositoryPackage = customResourceLoader.getRepositoryPackage(); 36 | this.repositoryPostfix = customResourceLoader.getRepositoryPostfix(); 37 | this.lombokAnnotations = lombokAnnotations; 38 | this.withComments = withComments; 39 | this.findFilterRepositories(); 40 | } 41 | 42 | private void findFilterRepositories() { 43 | String repositoryPath = GeneratorUtils.getAbsolutePath() + repositoryPackage.replace(".", "/"); 44 | File[] repositoryFiles = GeneratorUtils.getFileList(repositoryPath, repositoryPostfix); 45 | this.setIncludeFilter(Arrays.asList(repositoryFiles)); 46 | this.setIncludeFilterPostfix(repositoryPostfix); 47 | } 48 | 49 | @Override 50 | protected Tuple getContentFromTemplate(String mPackage, String simpleClassName, String postfix, BeanDefinition beanDefinition, String additionalPackage) { 51 | return new ManagerStructure(mPackage, simpleClassName, beanDefinition.getBeanClassName(), postfix, repositoryPackage, repositoryPostfix, additionalPackage, lombokAnnotations, withComments).build(); 52 | } 53 | 54 | @Override 55 | protected String getExcludeClasses() { 56 | return "excludeManagerClasses"; 57 | } 58 | 59 | @Override 60 | protected String getPostfix() { 61 | return "managerPostfix"; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/RepositoryTemplateSupport.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support; 2 | 3 | import com.cmeza.sdgenerator.provider.AbstractTemplateProvider; 4 | import com.cmeza.sdgenerator.support.maker.RepositoryStructure; 5 | import com.cmeza.sdgenerator.util.CustomResourceLoader; 6 | import com.cmeza.sdgenerator.util.Tuple; 7 | import org.springframework.beans.factory.config.BeanDefinition; 8 | import org.springframework.core.annotation.AnnotationAttributes; 9 | 10 | import java.util.Set; 11 | 12 | /** 13 | * Created by carlos on 08/04/17. 14 | */ 15 | public class RepositoryTemplateSupport extends AbstractTemplateProvider { 16 | 17 | private CustomResourceLoader loader; 18 | private final Set additionalExtends; 19 | private final boolean withComments; 20 | private final boolean withJpaSpecificationExecutor; 21 | 22 | public RepositoryTemplateSupport(AnnotationAttributes attributes, Set additionalExtends, boolean withComments, boolean withJpaSpecificationExecutor) { 23 | super(attributes); 24 | this.additionalExtends = additionalExtends; 25 | this.withComments = withComments; 26 | this.withJpaSpecificationExecutor = withJpaSpecificationExecutor; 27 | } 28 | 29 | public RepositoryTemplateSupport(CustomResourceLoader loader, Set additionalExtends, boolean withComments, boolean withJpaSpecificationExecutor) { 30 | super(loader); 31 | this.loader = loader; 32 | this.additionalExtends = additionalExtends; 33 | this.withComments = withComments; 34 | this.withJpaSpecificationExecutor = withJpaSpecificationExecutor; 35 | } 36 | 37 | @Override 38 | protected Tuple getContentFromTemplate(String repositoryPackage, String simpleClassName, String postfix, BeanDefinition beanDefinition, String additionalPackage) { 39 | return new RepositoryStructure(repositoryPackage, simpleClassName, beanDefinition.getBeanClassName(), postfix, loader, additionalExtends, withComments, withJpaSpecificationExecutor).build(); 40 | } 41 | 42 | @Override 43 | protected String getExcludeClasses() { 44 | return "excludeRepositoriesClasses"; 45 | } 46 | 47 | @Override 48 | protected String getPostfix() { 49 | return "repositoryPostfix"; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/ScanningConfigurationSupport.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support; 2 | 3 | import com.cmeza.sdgenerator.annotation.SDGenerate; 4 | import com.cmeza.sdgenerator.annotation.SDNoGenerate; 5 | import com.cmeza.sdgenerator.provider.ClassPathScanningProvider; 6 | import org.springframework.beans.factory.config.BeanDefinition; 7 | import org.springframework.core.annotation.AnnotationAttributes; 8 | import org.springframework.core.env.Environment; 9 | import org.springframework.core.io.ResourceLoader; 10 | import org.springframework.core.type.AnnotationMetadata; 11 | import org.springframework.util.Assert; 12 | import org.springframework.util.ClassUtils; 13 | 14 | import javax.persistence.Entity; 15 | import java.util.*; 16 | 17 | /** 18 | * Created by carlos on 08/04/17. 19 | */ 20 | public class ScanningConfigurationSupport { 21 | 22 | private final Environment environment; 23 | private final AnnotationAttributes attributes; 24 | private final AnnotationMetadata annotationMetadata; 25 | private final String[] entityPackage; 26 | private final boolean onlyAnnotations; 27 | 28 | public ScanningConfigurationSupport(AnnotationMetadata annotationMetadata, AnnotationAttributes attributes, Environment environment){ 29 | Assert.notNull(environment, "Environment must not be null!"); 30 | Assert.notNull(environment, "AnnotationMetadata must not be null!"); 31 | this.environment = environment; 32 | this.attributes = attributes; 33 | this.annotationMetadata = annotationMetadata; 34 | this.entityPackage = this.attributes.getStringArray("entityPackage"); 35 | this.onlyAnnotations = this.attributes.getBoolean("onlyAnnotations"); 36 | } 37 | 38 | public ScanningConfigurationSupport(String[] entityPackage, boolean onlyAnnotations) { 39 | this.entityPackage = entityPackage; 40 | this.onlyAnnotations = onlyAnnotations; 41 | this.environment = null; 42 | this.annotationMetadata = null; 43 | this.attributes = null; 44 | } 45 | 46 | public Iterable getBasePackages() { 47 | 48 | if (entityPackage.length == 0) { 49 | String className = this.annotationMetadata.getClassName(); 50 | return Collections.singleton(ClassUtils.getPackageName(className)); 51 | } else { 52 | return new HashSet<>(Arrays.asList(entityPackage)); 53 | } 54 | } 55 | 56 | public Collection getCandidates(ResourceLoader resourceLoader) { 57 | if(this.getBasePackages() == null){ 58 | return Collections.emptyList(); 59 | } 60 | 61 | ClassPathScanningProvider scanner = new ClassPathScanningProvider(); 62 | scanner.setResourceLoader(resourceLoader); 63 | if (environment != null) { 64 | scanner.setEnvironment(this.environment); 65 | } 66 | 67 | scanner.setIncludeAnnotation(SDGenerate.class); 68 | scanner.setExcludeAnnotation(SDNoGenerate.class); 69 | if (!onlyAnnotations) { 70 | scanner.setIncludeAnnotation(Entity.class); 71 | scanner.setIncludeAnnotation(jakarta.persistence.Entity.class); 72 | } 73 | 74 | Iterator filterPackages = this.getBasePackages().iterator(); 75 | 76 | HashSet candidates = new HashSet<>(); 77 | 78 | while(filterPackages.hasNext()) { 79 | String basePackage = filterPackages.next(); 80 | Set candidate = scanner.findCandidateComponents(basePackage); 81 | candidates.addAll(candidate); 82 | } 83 | 84 | return candidates; 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/ManagerStructure.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker; 2 | 3 | import com.cmeza.sdgenerator.support.maker.builder.ObjectBuilder; 4 | import com.cmeza.sdgenerator.support.maker.builder.ObjectStructure; 5 | import com.cmeza.sdgenerator.support.maker.values.ExpressionValues; 6 | import com.cmeza.sdgenerator.support.maker.values.ObjectTypeValues; 7 | import com.cmeza.sdgenerator.support.maker.values.ObjectValues; 8 | import com.cmeza.sdgenerator.support.maker.values.ScopeValues; 9 | import com.cmeza.sdgenerator.util.GeneratorUtils; 10 | import com.cmeza.sdgenerator.util.Tuple; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Component; 13 | 14 | /** 15 | * Created by carlos on 08/04/17. 16 | */ 17 | public class ManagerStructure { 18 | 19 | private final ObjectBuilder objectBuilder; 20 | 21 | public ManagerStructure(String managerPackage, String entityName, String entityClass, String postfix, String repositoryPackage, String repositoryPostfix, String additionalPackage, boolean lombokAnnotations, boolean withComments) { 22 | 23 | String managerName = entityName + postfix; 24 | String repositoryName = entityName + repositoryPostfix; 25 | String repositoryNameAttribute = GeneratorUtils.decapitalize(repositoryName); 26 | 27 | this.objectBuilder = new ObjectBuilder(new ObjectStructure(managerPackage, ScopeValues.PUBLIC, ObjectTypeValues.CLASS, managerName) 28 | .setLombokAnnotations(lombokAnnotations) 29 | .addImport(repositoryPackage + "." + (additionalPackage.isEmpty() ? "" : (additionalPackage + ".")) + repositoryName) 30 | .addImport(entityClass) 31 | .addImport(Autowired.class) 32 | .addImport(Component.class) 33 | .addAnnotation(Component.class) 34 | .addFinalAttribute(repositoryName, repositoryNameAttribute) 35 | .addConstructor(new ObjectStructure.ObjectConstructor(ScopeValues.PUBLIC, managerName) 36 | .addAnnotation(Autowired.class) 37 | .addArgument(repositoryName, repositoryNameAttribute) 38 | .addBodyLine(ObjectValues.THIS.getValue() + repositoryNameAttribute + ExpressionValues.EQUAL.getValue() + repositoryNameAttribute) 39 | ) 40 | ) 41 | .setAttributeBottom(false) 42 | .setWithComments(withComments); 43 | 44 | } 45 | 46 | public Tuple build() { 47 | return new Tuple<>(objectBuilder == null ? null : objectBuilder.build(), 0); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/RepositoryStructure.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker; 2 | 3 | import com.cmeza.sdgenerator.support.maker.builder.ObjectBuilder; 4 | import com.cmeza.sdgenerator.support.maker.builder.ObjectStructure; 5 | import com.cmeza.sdgenerator.support.maker.values.ObjectTypeValues; 6 | import com.cmeza.sdgenerator.support.maker.values.ScopeValues; 7 | import com.cmeza.sdgenerator.util.*; 8 | 9 | import javax.persistence.EmbeddedId; 10 | import javax.persistence.Id; 11 | import java.lang.reflect.Field; 12 | import java.lang.reflect.Method; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | import java.util.Set; 16 | 17 | /** 18 | * Created by carlos on 08/04/17. 19 | */ 20 | public class RepositoryStructure { 21 | 22 | private static final Map, Class> mapConvert = new HashMap<>(); 23 | 24 | static { 25 | mapConvert.put(boolean.class, Boolean.class); 26 | mapConvert.put(byte.class, Byte.class); 27 | mapConvert.put(short.class, Short.class); 28 | mapConvert.put(char.class, Character.class); 29 | mapConvert.put(int.class, Integer.class); 30 | mapConvert.put(long.class, Long.class); 31 | mapConvert.put(float.class, Float.class); 32 | mapConvert.put(double.class, Double.class); 33 | } 34 | 35 | private final CustomResourceLoader loader; 36 | private ObjectBuilder objectBuilder; 37 | private Integer error = 0; 38 | 39 | public RepositoryStructure(String repositoryPackage, String entityName, String entityClass, String postfix, CustomResourceLoader loader, Set additionalExtends, boolean withComments, boolean withJpaSpecificationExecutor) { 40 | this.loader = loader; 41 | String repositoryName = entityName + postfix; 42 | Tuple entityId = getEntityId(entityClass); 43 | if (entityId != null) { 44 | 45 | ObjectStructure objectStructure = new ObjectStructure(repositoryPackage, ScopeValues.PUBLIC, ObjectTypeValues.INTERFACE, repositoryName) 46 | .addImport(entityClass) 47 | .addImport("org.springframework.data.jpa.repository.JpaRepository") 48 | .addImport("org.springframework.stereotype.Repository") 49 | .addImport(entityId.right() ? entityId.left() : "") 50 | .addAnnotation("Repository") 51 | .addExtend("JpaRepository", entityName, GeneratorUtils.getSimpleClassName(entityId.left())); 52 | 53 | if (withJpaSpecificationExecutor) { 54 | objectStructure.addImport("org.springframework.data.jpa.repository.JpaSpecificationExecutor"); 55 | objectStructure.addExtend("JpaSpecificationExecutor", entityName); 56 | } 57 | 58 | if (additionalExtends != null) { 59 | for (String additionalExtend : additionalExtends) { 60 | objectStructure.addImport(additionalExtend); 61 | objectStructure.addExtend(GeneratorUtils.getSimpleClassName(additionalExtend), entityName); 62 | } 63 | } 64 | this.objectBuilder = new ObjectBuilder(objectStructure).setWithComments(withComments); 65 | } 66 | } 67 | 68 | private Tuple getEntityId(String entityClass) { 69 | try { 70 | Class entity; 71 | if (loader == null) { 72 | entity = Class.forName(entityClass); 73 | } else { 74 | entity = loader.getUrlClassLoader().loadClass(entityClass); 75 | } 76 | 77 | while (entity != null) { 78 | for (Field field : entity.getDeclaredFields()) { 79 | if (field.isAnnotationPresent(Id.class) || field.isAnnotationPresent(EmbeddedId.class) || 80 | field.isAnnotationPresent(jakarta.persistence.Id.class) || field.isAnnotationPresent(jakarta.persistence.EmbeddedId.class)) { 81 | Class dataType = field.getType(); 82 | if (field.getType().isPrimitive()) { 83 | dataType = this.primitiveToObject(field.getType()); 84 | } 85 | return new Tuple<>(dataType.getName(), this.isCustomType(dataType)); 86 | } 87 | } 88 | 89 | for (Method method : entity.getDeclaredMethods()) { 90 | if (!method.getReturnType().equals(Void.TYPE) && 91 | (method.isAnnotationPresent(Id.class) || method.isAnnotationPresent(EmbeddedId.class)) || 92 | (method.isAnnotationPresent(jakarta.persistence.Id.class) || method.isAnnotationPresent(jakarta.persistence.EmbeddedId.class)) 93 | ) { 94 | Class dataType = method.getReturnType(); 95 | if (method.getReturnType().isPrimitive()) { 96 | dataType = this.primitiveToObject(method.getReturnType()); 97 | } 98 | return new Tuple<>(dataType.getName(), this.isCustomType(dataType)); 99 | } 100 | } 101 | entity = entity.getSuperclass(); 102 | } 103 | 104 | error = SDLogger.addError("Repository Error: Primary key not found in " + GeneratorUtils.getSimpleClassName(entityClass) + ".java"); 105 | return null; 106 | } catch (GeneratorException ex) { 107 | error = SDLogger.addError(ex.getMessage()); 108 | return null; 109 | } catch (Exception e) { 110 | error = SDLogger.addError("Repository Error: Failed to access entity " + GeneratorUtils.getSimpleClassName(entityClass) + ".java"); 111 | return null; 112 | } 113 | } 114 | 115 | public Tuple build() { 116 | return new Tuple<>(objectBuilder == null ? null : objectBuilder.build(), error); 117 | } 118 | 119 | private boolean isCustomType(Class clazz) { 120 | return !clazz.isAssignableFrom(Boolean.class) && 121 | !clazz.isAssignableFrom(Byte.class) && 122 | !clazz.isAssignableFrom(String.class) && 123 | !clazz.isAssignableFrom(Integer.class) && 124 | !clazz.isAssignableFrom(Long.class) && 125 | !clazz.isAssignableFrom(Float.class) && 126 | !clazz.isAssignableFrom(Double.class); 127 | } 128 | 129 | private Class primitiveToObject(Class clazz) { 130 | Class convertResult = mapConvert.get(clazz); 131 | if (convertResult == null) { 132 | throw new GeneratorException("Type parameter '" + clazz.getName() + "' is incorrect"); 133 | } 134 | return convertResult; 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/builder/ObjectBuilder.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker.builder; 2 | 3 | import com.cmeza.sdgenerator.support.maker.values.CommonValues; 4 | import com.cmeza.sdgenerator.util.Constants; 5 | 6 | import java.text.SimpleDateFormat; 7 | import java.util.Date; 8 | 9 | /** 10 | * Created by carlos on 08/04/17. 11 | */ 12 | public class ObjectBuilder { 13 | 14 | private ObjectStructure objectStructure; 15 | private boolean attributeBottom; 16 | private boolean withComments; 17 | 18 | public ObjectBuilder(ObjectStructure objectStructure) { 19 | this.objectStructure = objectStructure; 20 | } 21 | 22 | public ObjectBuilder(ObjectStructure objectStructure, boolean attributeBottom) { 23 | this.objectStructure = objectStructure; 24 | this.attributeBottom = attributeBottom; 25 | } 26 | 27 | public ObjectBuilder setAttributeBottom(boolean attributeBottom) { 28 | this.attributeBottom = attributeBottom; 29 | return this; 30 | } 31 | 32 | public ObjectBuilder setWithComments(boolean withComments) { 33 | this.withComments = withComments; 34 | return this; 35 | } 36 | 37 | private String buildComments() { 38 | if (withComments) { 39 | SimpleDateFormat smf = new SimpleDateFormat("dd/MM/yyy"); 40 | return new StringBuilder() 41 | .append(CommonValues.COMMENT_START.getValue()) 42 | .append(CommonValues.COMMENT_BODY.getValue()) 43 | .append(String.format("Generated by %s on ", Constants.PROJECT_NAME)) 44 | .append(smf.format(new Date())) 45 | .append(CommonValues.NEWLINE.getValue()) 46 | .append(CommonValues.COMMENT_END.getValue()) 47 | .toString(); 48 | } 49 | return CommonValues.NONE.getValue(); 50 | } 51 | 52 | public String build() { 53 | return new StringBuilder() 54 | .append(this.objectStructure.getObjectPackage()) 55 | .append(CommonValues.NEWLINE.getValue()) 56 | .append(this.objectStructure.getObjectImports()) 57 | .append(this.buildComments()) 58 | .append(this.objectStructure.getObjectAnnotations()) 59 | .append(this.objectStructure.getObjectScope()).append(this.objectStructure.getObjectType()).append(this.objectStructure.getObjectName()) 60 | .append(this.objectStructure.getObjectExtend()) 61 | .append(this.objectStructure.getObjectImplements()) 62 | .append(CommonValues.KEY_START.getValue()) 63 | .append(!this.attributeBottom ? objectStructure.getObjectAttributes() : "") 64 | .append(!this.attributeBottom ? objectStructure.getObjectFinalAttributes() : "") 65 | .append(this.objectStructure.getObjectConstructors()) 66 | .append(this.objectStructure.getObjectMethods()) 67 | .append(this.objectStructure.getObjectFunctions()) 68 | .append(this.objectStructure.getObjectRawBody()) 69 | .append(this.attributeBottom ? objectStructure.getObjectAttributes() : "") 70 | .append(this.attributeBottom ? objectStructure.getObjectFinalAttributes() : "") 71 | .append(CommonValues.NEWLINE.getValue()) 72 | .append(CommonValues.KEY_END.getValue()) 73 | .toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/builder/ObjectStructure.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker.builder; 2 | 3 | import com.cmeza.sdgenerator.support.maker.values.CommonValues; 4 | import com.cmeza.sdgenerator.support.maker.values.ObjectTypeValues; 5 | import com.cmeza.sdgenerator.support.maker.values.ObjectValues; 6 | import com.cmeza.sdgenerator.support.maker.values.ScopeValues; 7 | import com.cmeza.sdgenerator.util.BuildUtils; 8 | import lombok.RequiredArgsConstructor; 9 | import org.apache.commons.lang3.tuple.Pair; 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | 13 | import java.util.*; 14 | 15 | /** 16 | * Created by carlos on 08/04/17. 17 | */ 18 | public class ObjectStructure { 19 | 20 | private final ObjectTypeValues objectType; 21 | private final ScopeValues objectScope; 22 | 23 | private String objectPackage; 24 | private final Set objectImports = new LinkedHashSet<>(); 25 | private final Set objectAnnotations = new LinkedHashSet<>(); 26 | private final Set objectImplements = new LinkedHashSet<>(); 27 | private final Set objectAttributes = new LinkedHashSet<>(); 28 | private final Set objectFinalAttributes = new LinkedHashSet<>(); 29 | private final Set objectMethods = new LinkedHashSet<>(); 30 | private final Set objectFunctions = new LinkedHashSet<>(); 31 | private final Set objectConstructors = new LinkedHashSet<>(); 32 | private final Set objectExtends = new LinkedHashSet<>(); 33 | private final String objectName; 34 | private boolean lombokAnnotations; 35 | private String objectRawBody; 36 | 37 | public ObjectStructure(String objectPackage, ScopeValues objectScope, ObjectTypeValues objectType, String objectName) { 38 | this.objectPackage = BuildUtils.buildPackage(objectPackage); 39 | this.objectScope = objectScope; 40 | this.objectType = objectType; 41 | this.objectName = BuildUtils.cleanSpaces(objectName); 42 | this.objectRawBody = ""; 43 | } 44 | 45 | public ObjectStructure setPackage(String objectPackage) { 46 | if (!objectPackage.isEmpty()) { 47 | this.objectPackage = BuildUtils.buildPackage(objectPackage); 48 | } 49 | return this; 50 | } 51 | 52 | public ObjectStructure addImport(String objectImport) { 53 | if (!objectImport.isEmpty()) { 54 | this.objectImports.add(BuildUtils.buildImport(objectImport)); 55 | } 56 | return this; 57 | } 58 | 59 | public ObjectStructure addImport(Class clazz) { 60 | if (clazz != null) { 61 | this.objectImports.add(BuildUtils.buildImport(clazz.getName())); 62 | } 63 | return this; 64 | } 65 | 66 | public ObjectStructure addAnnotation(String annotation) { 67 | if (!annotation.isEmpty()) { 68 | this.objectAnnotations.add(BuildUtils.buildAnnotation(annotation)); 69 | } 70 | return this; 71 | } 72 | 73 | public ObjectStructure addAnnotation(Class clazz) { 74 | if (clazz != null) { 75 | this.objectAnnotations.add(BuildUtils.buildAnnotation(clazz.getSimpleName())); 76 | } 77 | return this; 78 | } 79 | 80 | public ObjectStructure addImplement(String objectImplement, Object... objects) { 81 | this.objectImplements.add(BuildUtils.builDiamond(objectImplement, objects)); 82 | return this; 83 | } 84 | 85 | public ObjectStructure addImplement(Class clazz, Object... objects) { 86 | if (clazz != null) { 87 | this.objectImplements.add(BuildUtils.builDiamond(clazz.getSimpleName(), objects)); 88 | } 89 | return this; 90 | } 91 | 92 | public ObjectStructure addExtend(String objectExtend, Object... objects) { 93 | this.objectExtends.add(BuildUtils.builDiamond(objectExtend, objects)); 94 | return this; 95 | } 96 | 97 | public ObjectStructure addExtend(Class clazz, Object... objects) { 98 | this.objectExtends.add(BuildUtils.builDiamond(clazz.getSimpleName(), objects)); 99 | return this; 100 | } 101 | 102 | public ObjectStructure setObjectRawBody(String objectRawBody) { 103 | this.objectRawBody = objectRawBody; 104 | return this; 105 | } 106 | 107 | public ObjectStructure addConstructor(ObjectConstructor objectConstructor) { 108 | if (objectConstructor != null) { 109 | this.objectConstructors.add(objectConstructor); 110 | } 111 | return this; 112 | } 113 | 114 | public ObjectStructure addAttribute(String attributeClass, String attribute) { 115 | this.objectAttributes.add(BuildUtils.buildAttribute(attributeClass, attribute, false)); 116 | return this; 117 | } 118 | 119 | public ObjectStructure addFinalAttribute(String attributeClass, String attribute) { 120 | this.objectFinalAttributes.add(BuildUtils.buildAttribute(attributeClass, attribute, true)); 121 | return this; 122 | } 123 | 124 | public ObjectStructure addMethod(ObjectMethod objectMethod) { 125 | this.objectMethods.add(objectMethod); 126 | return this; 127 | } 128 | 129 | public ObjectStructure addFunction(ObjectFunction objectFunction) { 130 | this.objectFunctions.add(objectFunction); 131 | return this; 132 | } 133 | 134 | public ObjectStructure setLombokAnnotations(boolean lombokAnnotations) { 135 | this.lombokAnnotations = lombokAnnotations; 136 | return this; 137 | } 138 | 139 | public ObjectTypeValues getObjectType() { 140 | return objectType; 141 | } 142 | 143 | public ScopeValues getObjectScope() { 144 | return objectScope; 145 | } 146 | 147 | public String getObjectPackage() { 148 | return objectPackage; 149 | } 150 | 151 | public String getObjectImports() { 152 | List objectImportsOrder = new LinkedList<>(objectImports); 153 | if (lombokAnnotations) { 154 | objectImportsOrder.add(BuildUtils.buildImport("lombok.RequiredArgsConstructor")); 155 | BuildUtils.removeImport(objectImportsOrder, Autowired.class.getName()); 156 | } 157 | objectImportsOrder.sort(Comparator.comparing(String::toString)); 158 | StringBuilder concat = new StringBuilder(""); 159 | for (String str : objectImportsOrder) { 160 | concat.append(str); 161 | } 162 | if (!objectImportsOrder.isEmpty()) { 163 | concat.append(CommonValues.NEWLINE); 164 | } 165 | return concat.toString(); 166 | } 167 | 168 | public String getObjectAnnotations() { 169 | StringBuilder concat = new StringBuilder(""); 170 | if (lombokAnnotations) { 171 | objectAnnotations.add(BuildUtils.buildAnnotation(RequiredArgsConstructor.class.getSimpleName())); 172 | } 173 | for (String str : objectAnnotations) { 174 | concat.append(str); 175 | } 176 | return concat.toString(); 177 | } 178 | 179 | public String getObjectImplements() { 180 | StringBuilder concat = new StringBuilder(""); 181 | int position = 0; 182 | for (String str : objectImplements) { 183 | concat.append(str); 184 | if (position != (objectImplements.size() -1)){ 185 | concat.append(CommonValues.COMA); 186 | } 187 | position++; 188 | } 189 | return objectImplements.isEmpty() ? "" : CommonValues.SPACE.getValue() + ObjectValues.IMPLEMENTS.getValue() + concat; 190 | } 191 | 192 | public String getObjectAttributes() { 193 | StringBuilder concat = new StringBuilder(""); 194 | for (String str : objectAttributes) { 195 | concat.append(str); 196 | } 197 | return !objectAttributes.isEmpty() ? CommonValues.NEWLINE.getValue() + concat : ""; 198 | } 199 | 200 | public String getObjectFinalAttributes() { 201 | StringBuilder concat = new StringBuilder(""); 202 | for (String str : objectFinalAttributes) { 203 | concat.append(str); 204 | } 205 | return !objectFinalAttributes.isEmpty() ? CommonValues.NEWLINE.getValue() + concat : ""; 206 | } 207 | 208 | public int getObjectAttributesSize() { 209 | return objectAttributes.size(); 210 | } 211 | 212 | public String getObjectMethods() { 213 | StringBuilder concat = new StringBuilder(""); 214 | int position = 0; 215 | for (ObjectMethod method : objectMethods) { 216 | concat.append(method); 217 | if (position != (objectMethods.size() -1)){ 218 | concat.append(CommonValues.NEWLINE); 219 | } 220 | position++; 221 | } 222 | return !objectMethods.isEmpty() ? CommonValues.NEWLINE.getValue() + concat : ""; 223 | } 224 | 225 | public String getObjectFunctions() { 226 | StringBuilder concat = new StringBuilder(""); 227 | int position = 0; 228 | for (ObjectFunction function : objectFunctions) { 229 | concat.append(function); 230 | if (position != (objectFunctions.size() -1)){ 231 | concat.append(CommonValues.NEWLINE); 232 | } 233 | position++; 234 | } 235 | return !objectFunctions.isEmpty() ? CommonValues.NEWLINE.getValue() + concat : ""; 236 | } 237 | 238 | public String getObjectConstructors() { 239 | if (!lombokAnnotations) { 240 | StringBuilder concat = new StringBuilder(""); 241 | int position = 0; 242 | for (ObjectConstructor constructor : objectConstructors) { 243 | concat.append(constructor); 244 | if (position != (objectConstructors.size() -1)){ 245 | concat.append(CommonValues.NEWLINE); 246 | } 247 | position++; 248 | } 249 | return !objectConstructors.isEmpty() ? CommonValues.NEWLINE.getValue() + concat : ""; 250 | } 251 | return CommonValues.NONE.getValue(); 252 | } 253 | 254 | public String getObjectName() { 255 | return objectName; 256 | } 257 | 258 | public String getObjectExtend() { 259 | return objectExtends.isEmpty() ? "" : CommonValues.SPACE.getValue() + ObjectValues.EXTENDS.getValue() + StringUtils.join(objectExtends, ", "); 260 | } 261 | 262 | public String getObjectRawBody() { 263 | return objectRawBody.isEmpty() ? "" : CommonValues.NEWLINE.getValue() + objectRawBody; 264 | } 265 | 266 | public static class ObjectConstructor { 267 | private final ScopeValues constructorScope; 268 | private final String constructorName; 269 | private final Set> constructorArguments = new LinkedHashSet<>(); 270 | private String constructorBody; 271 | private String constructorAnnotations; 272 | 273 | public ObjectConstructor(ScopeValues constructorScope, String constructorName) { 274 | this.constructorScope = constructorScope; 275 | this.constructorName = BuildUtils.cleanSpaces(constructorName); 276 | this.constructorAnnotations = ""; 277 | this.constructorBody = ""; 278 | } 279 | 280 | public ObjectConstructor addArgument(String argumentClass, String argumentName) { 281 | constructorArguments.add(Pair.of(BuildUtils.cleanSpaces(argumentClass), BuildUtils.cleanSpaces(argumentName))); 282 | return this; 283 | } 284 | 285 | public ObjectConstructor setBody(String constructorBody) { 286 | this.constructorBody = constructorBody; 287 | return this; 288 | } 289 | 290 | public ObjectConstructor addBodyLine(String constructorBody) { 291 | this.constructorBody += BuildUtils.buildBodyLine(constructorBody); 292 | return this; 293 | } 294 | 295 | public ObjectConstructor addAnnotation(String constructorAnnotation) { 296 | constructorAnnotations += BuildUtils.buildAnnotation(constructorAnnotation); 297 | return this; 298 | } 299 | 300 | public ObjectConstructor addAnnotation(Class clazz) { 301 | if (clazz != null) { 302 | this.constructorAnnotations += BuildUtils.buildAnnotation(clazz.getSimpleName()); 303 | } 304 | return this; 305 | } 306 | 307 | @Override 308 | public String toString() { 309 | return BuildUtils.buildConstructor(constructorAnnotations, constructorScope, constructorName, constructorArguments, constructorBody); 310 | } 311 | 312 | @Override 313 | public boolean equals(Object o) { 314 | if (this == o) return true; 315 | if (o == null || getClass() != o.getClass()) return false; 316 | 317 | ObjectConstructor that = (ObjectConstructor) o; 318 | 319 | if (constructorScope != that.constructorScope) return false; 320 | if (constructorName != null ? !constructorName.equals(that.constructorName) : that.constructorName != null) 321 | return false; 322 | if (constructorArguments != null ? !constructorArguments.equals(that.constructorArguments) : that.constructorArguments != null) 323 | return false; 324 | if (constructorBody != null ? !constructorBody.equals(that.constructorBody) : that.constructorBody != null) 325 | return false; 326 | return constructorAnnotations != null ? constructorAnnotations.equals(that.constructorAnnotations) : that.constructorAnnotations == null; 327 | } 328 | 329 | @Override 330 | public int hashCode() { 331 | int result = constructorScope != null ? constructorScope.hashCode() : 0; 332 | result = 31 * result + (constructorName != null ? constructorName.hashCode() : 0); 333 | result = 31 * result + (constructorArguments != null ? constructorArguments.hashCode() : 0); 334 | result = 31 * result + (constructorBody != null ? constructorBody.hashCode() : 0); 335 | result = 31 * result + (constructorAnnotations != null ? constructorAnnotations.hashCode() : 0); 336 | return result; 337 | } 338 | } 339 | 340 | public static class ObjectFunction { 341 | private final ScopeValues functionScope; 342 | private final String functionName; 343 | private final String functionReturnType; 344 | private final Set> functionArguments = new LinkedHashSet<>(); 345 | private String functionBody; 346 | private String functionAnnotations; 347 | private String functionReturn; 348 | 349 | public ObjectFunction(ScopeValues functionScope, String functionName, String functionReturnType) { 350 | this.functionScope = functionScope; 351 | this.functionName = BuildUtils.cleanSpaces(functionName); 352 | this.functionReturnType = BuildUtils.cleanSpaces(functionReturnType); 353 | this.functionBody = ""; 354 | this.functionAnnotations = ""; 355 | this.functionReturn = ""; 356 | } 357 | 358 | public ObjectFunction addArgument(String argumentClass, String argumentName) { 359 | functionArguments.add(Pair.of(BuildUtils.cleanSpaces(argumentClass), BuildUtils.cleanSpaces(argumentName))); 360 | return this; 361 | } 362 | 363 | public ObjectFunction setBody(String functionBody) { 364 | this.functionBody = functionBody; 365 | return this; 366 | } 367 | 368 | public ObjectFunction addBodyLine(String functionBody) { 369 | this.functionBody += BuildUtils.buildBodyLine(functionBody); 370 | return this; 371 | } 372 | 373 | public ObjectFunction addAnnotation(String functionAnnotation) { 374 | this.functionAnnotations += BuildUtils.buildAnnotation(functionAnnotation); 375 | return this; 376 | } 377 | 378 | public ObjectFunction addAnnotation(Class clazz) { 379 | if (clazz != null) { 380 | this.functionAnnotations += BuildUtils.buildAnnotation(clazz.getSimpleName()); 381 | } 382 | return this; 383 | } 384 | 385 | public ObjectFunction setFunctionReturn(String functionReturn) { 386 | this.functionReturn = BuildUtils.cleanSpaces(functionReturn); 387 | return this; 388 | } 389 | 390 | @Override 391 | public String toString() { 392 | return BuildUtils.buildFunction(functionAnnotations, functionScope, functionReturnType, functionName, functionArguments, functionBody, functionReturn); 393 | } 394 | 395 | @Override 396 | public boolean equals(Object o) { 397 | if (this == o) return true; 398 | if (o == null || getClass() != o.getClass()) return false; 399 | 400 | ObjectFunction that = (ObjectFunction) o; 401 | 402 | if (functionScope != that.functionScope) return false; 403 | if (functionName != null ? !functionName.equals(that.functionName) : that.functionName != null) 404 | return false; 405 | if (functionReturnType != null ? !functionReturnType.equals(that.functionReturnType) : that.functionReturnType != null) 406 | return false; 407 | if (functionArguments != null ? !functionArguments.equals(that.functionArguments) : that.functionArguments != null) 408 | return false; 409 | if (functionBody != null ? !functionBody.equals(that.functionBody) : that.functionBody != null) 410 | return false; 411 | if (functionAnnotations != null ? !functionAnnotations.equals(that.functionAnnotations) : that.functionAnnotations != null) 412 | return false; 413 | return functionReturn != null ? functionReturn.equals(that.functionReturn) : that.functionReturn == null; 414 | } 415 | 416 | @Override 417 | public int hashCode() { 418 | int result = functionScope != null ? functionScope.hashCode() : 0; 419 | result = 31 * result + (functionName != null ? functionName.hashCode() : 0); 420 | result = 31 * result + (functionReturnType != null ? functionReturnType.hashCode() : 0); 421 | result = 31 * result + (functionArguments != null ? functionArguments.hashCode() : 0); 422 | result = 31 * result + (functionBody != null ? functionBody.hashCode() : 0); 423 | result = 31 * result + (functionAnnotations != null ? functionAnnotations.hashCode() : 0); 424 | result = 31 * result + (functionReturn != null ? functionReturn.hashCode() : 0); 425 | return result; 426 | } 427 | } 428 | 429 | public static class ObjectMethod { 430 | private final ScopeValues methodScope; 431 | private final String methodName; 432 | private final Set> methodArguments = new LinkedHashSet<>(); 433 | private String methodBody; 434 | private String methodAnnotations; 435 | 436 | public ObjectMethod(ScopeValues methodScope, String methodName) { 437 | this.methodScope = methodScope; 438 | this.methodName = BuildUtils.cleanSpaces(methodName); 439 | this.methodBody = ""; 440 | this.methodAnnotations = ""; 441 | } 442 | 443 | public ObjectMethod addArgument(String argumentClass, String argumentName) { 444 | methodArguments.add(Pair.of(BuildUtils.cleanSpaces(argumentClass), BuildUtils.cleanSpaces(argumentName))); 445 | return this; 446 | } 447 | 448 | public ObjectMethod setBody(String methodBody) { 449 | this.methodBody = methodBody; 450 | return this; 451 | } 452 | 453 | public ObjectMethod addBodyLine(String methodBody) { 454 | this.methodBody += BuildUtils.buildBodyLine(methodBody); 455 | return this; 456 | } 457 | 458 | public ObjectMethod addAnnotation(String methodAnnotation) { 459 | this.methodAnnotations += BuildUtils.buildAnnotation(methodAnnotation); 460 | return this; 461 | } 462 | 463 | public ObjectMethod addAnnotation(Class clazz) { 464 | if (clazz != null) { 465 | this.methodAnnotations += BuildUtils.buildAnnotation(clazz.getSimpleName()); 466 | } 467 | return this; 468 | } 469 | 470 | @Override 471 | public String toString() { 472 | return BuildUtils.buildMethod(methodAnnotations, methodScope, methodName, methodArguments, methodBody); 473 | } 474 | 475 | @Override 476 | public boolean equals(Object o) { 477 | if (this == o) return true; 478 | if (o == null || getClass() != o.getClass()) return false; 479 | 480 | ObjectMethod that = (ObjectMethod) o; 481 | 482 | if (methodScope != that.methodScope) return false; 483 | if (methodName != null ? !methodName.equals(that.methodName) : that.methodName != null) return false; 484 | if (methodArguments != null ? !methodArguments.equals(that.methodArguments) : that.methodArguments != null) 485 | return false; 486 | if (methodBody != null ? !methodBody.equals(that.methodBody) : that.methodBody != null) return false; 487 | return methodAnnotations != null ? methodAnnotations.equals(that.methodAnnotations) : that.methodAnnotations == null; 488 | } 489 | 490 | @Override 491 | public int hashCode() { 492 | int result = methodScope != null ? methodScope.hashCode() : 0; 493 | result = 31 * result + (methodName != null ? methodName.hashCode() : 0); 494 | result = 31 * result + (methodArguments != null ? methodArguments.hashCode() : 0); 495 | result = 31 * result + (methodBody != null ? methodBody.hashCode() : 0); 496 | result = 31 * result + (methodAnnotations != null ? methodAnnotations.hashCode() : 0); 497 | return result; 498 | } 499 | } 500 | 501 | } 502 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/values/AccessValues.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker.values; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | import static com.cmeza.sdgenerator.support.maker.values.CommonValues.SPACE; 7 | 8 | /** 9 | * Created by carlos on 25/04/22. 10 | */ 11 | 12 | @AllArgsConstructor 13 | public enum AccessValues { 14 | FINAL("final" + SPACE), 15 | STATIC("static" + SPACE); 16 | 17 | @Getter 18 | private final String value; 19 | 20 | @Override 21 | public String toString() { 22 | return this.value; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/values/CommonValues.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker.values; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * Created by carlos on 08/04/17. 8 | */ 9 | @AllArgsConstructor 10 | public enum CommonValues { 11 | NONE(""), 12 | SPACE(" "), 13 | NEWLINE("\r\n"), 14 | TAB("\t"), 15 | COMA("," + SPACE), 16 | SEMICOLON(";" + NEWLINE), 17 | KEY_START(SPACE + "{" + NEWLINE), 18 | KEY_END("}" + NEWLINE), 19 | PARENTHESIS("("), 20 | PARENTHESIS_END(")"), 21 | COMMENT_START("/**" + NEWLINE), 22 | COMMENT_BODY("*" + SPACE), 23 | COMMENT_END("*/" + NEWLINE), 24 | COMMENT_SINGLE("//" + SPACE), 25 | DIAMOND_START("<"), 26 | DIAMOND_END(">"); 27 | 28 | @Getter 29 | private final String value; 30 | 31 | @Override 32 | public String toString() { 33 | return this.value; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/values/ExpressionValues.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker.values; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | import static com.cmeza.sdgenerator.support.maker.values.CommonValues.SPACE; 7 | 8 | /** 9 | * Created by carlos on 08/04/17. 10 | */ 11 | @AllArgsConstructor 12 | public enum ExpressionValues { 13 | 14 | EQUAL(SPACE + "=" + SPACE), 15 | AT("@"); 16 | 17 | @Getter 18 | private final String value; 19 | 20 | @Override 21 | public String toString() { 22 | return this.value; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/values/ObjectTypeValues.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker.values; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | import static com.cmeza.sdgenerator.support.maker.values.CommonValues.SPACE; 7 | 8 | /** 9 | * Created by carlos on 08/04/17. 10 | */ 11 | @AllArgsConstructor 12 | public enum ObjectTypeValues { 13 | 14 | CLASS("class" + SPACE), 15 | INTERFACE("interface" + SPACE); 16 | 17 | @Getter 18 | private final String value; 19 | 20 | @Override 21 | public String toString() { 22 | return this.value; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/values/ObjectValues.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker.values; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | import static com.cmeza.sdgenerator.support.maker.values.CommonValues.SPACE; 7 | 8 | /** 9 | * Created by carlos on 08/04/17. 10 | */ 11 | @AllArgsConstructor 12 | public enum ObjectValues { 13 | PACKAGE("package" + SPACE), 14 | IMPORT("import" + SPACE), 15 | IMPLEMENTS("implements" + SPACE), 16 | THIS("this."), 17 | EXTENDS("extends" + SPACE), 18 | RETURN("return" + SPACE); 19 | 20 | @Getter 21 | private final String value; 22 | 23 | @Override 24 | public String toString() { 25 | return this.value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/support/maker/values/ScopeValues.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.support.maker.values; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | import static com.cmeza.sdgenerator.support.maker.values.CommonValues.SPACE; 7 | 8 | /** 9 | * Created by carlos on 08/04/17. 10 | */ 11 | @AllArgsConstructor 12 | public enum ScopeValues { 13 | 14 | PUBLIC("public" + SPACE), 15 | PRIVATE("private" + SPACE); 16 | 17 | @Getter 18 | private final String value; 19 | 20 | @Override 21 | public String toString() { 22 | return this.value; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/util/BuildUtils.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.util; 2 | 3 | import com.cmeza.sdgenerator.support.maker.values.*; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.apache.commons.lang3.tuple.Pair; 6 | 7 | import java.util.List; 8 | import java.util.Objects; 9 | import java.util.Set; 10 | 11 | /** 12 | * Created by carlos on 08/04/17. 13 | */ 14 | public class BuildUtils { 15 | 16 | private BuildUtils() { 17 | } 18 | 19 | public static String cleanSpaces(String str) { 20 | return str.replace(" ", ""); 21 | } 22 | 23 | public static String buildPackage(String objectPackage) { 24 | return ObjectValues.PACKAGE + cleanSpaces(objectPackage) + CommonValues.SEMICOLON; 25 | } 26 | 27 | public static String buildImport(String objectImport) { 28 | return ObjectValues.IMPORT + cleanSpaces(objectImport) + CommonValues.SEMICOLON; 29 | } 30 | 31 | public static void removeImport(List objectsImport, String importTag) { 32 | objectsImport.removeIf(e -> e.equalsIgnoreCase(ObjectValues.IMPORT + cleanSpaces(importTag) + CommonValues.SEMICOLON)); 33 | } 34 | 35 | public static String buildAttribute(String attributeClass, String attributeName, boolean hasFinal) { 36 | return CommonValues.TAB + ScopeValues.PRIVATE.getValue() + (hasFinal ? AccessValues.FINAL.getValue() : "") + cleanSpaces(attributeClass) + CommonValues.SPACE + cleanSpaces(attributeName) + CommonValues.SEMICOLON; 37 | } 38 | 39 | public static String builDiamond(String objectClass, Object... objects) { 40 | 41 | if (objects != null && objects.length > 0) { 42 | StringBuilder diamondString = new StringBuilder(); 43 | diamondString.append(cleanSpaces(objectClass)); 44 | diamondString.append(CommonValues.DIAMOND_START); 45 | for(Object obj: objects) { 46 | diamondString.append(cleanSpaces(String.valueOf(obj))); 47 | if (!String.valueOf(objects[objects.length - 1]).equals(String.valueOf(obj))) { 48 | diamondString.append(CommonValues.COMA); 49 | } 50 | } 51 | diamondString.append(CommonValues.DIAMOND_END); 52 | return diamondString.toString(); 53 | } 54 | 55 | return cleanSpaces(objectClass); 56 | } 57 | 58 | public static String buildAnnotation(String annotation) { 59 | return (annotation.startsWith(ExpressionValues.AT.getValue()) ? cleanSpaces(annotation) : ExpressionValues.AT + cleanSpaces(annotation)) + CommonValues.NEWLINE; 60 | } 61 | 62 | public static String buildBodyLine(String bodyLine) { 63 | return CommonValues.TAB.getValue() + CommonValues.TAB.getValue() + bodyLine + CommonValues.SEMICOLON.getValue(); 64 | } 65 | 66 | public static String buildReturn(String returnString) { 67 | return CommonValues.TAB.getValue() + CommonValues.TAB.getValue() + ObjectValues.RETURN.getValue() + returnString + CommonValues.SEMICOLON.getValue(); 68 | } 69 | 70 | public static String buildConstructor(String annotations, ScopeValues scope, String objectName, Set> arguments, String body) { 71 | return buildStructure(annotations, scope, null, objectName, arguments, body, null); 72 | } 73 | 74 | public static String buildFunction(String annotations, ScopeValues scope, String returnStructure, String objectName, Set> arguments, String body, String returnString) { 75 | return buildStructure(annotations, scope, returnStructure, objectName, arguments, body, returnString); 76 | } 77 | 78 | public static String buildMethod(String annotations, ScopeValues scope, String objectName, Set> arguments, String body) { 79 | return buildStructure(annotations, scope, "void", objectName, arguments, body, null); 80 | } 81 | 82 | public static String buildStructure(String annotations, ScopeValues scope, String returnStructure, String objectName, Set> arguments, String body, String returnString) { 83 | StringBuilder constructor = new StringBuilder(); 84 | if (annotations != null && !annotations.isEmpty()) { 85 | constructor.append(CommonValues.TAB.getValue()); 86 | constructor.append(annotations); 87 | } 88 | 89 | constructor.append(CommonValues.TAB) 90 | .append(scope) 91 | .append(returnStructure == null ? "" : returnStructure + CommonValues.SPACE) 92 | .append(objectName) 93 | .append(CommonValues.PARENTHESIS); 94 | 95 | 96 | if (arguments != null && !arguments.isEmpty()) { 97 | int position = 0; 98 | for (Pair obj : arguments) { 99 | constructor.append(obj.getKey()) 100 | .append(CommonValues.SPACE) 101 | .append(obj.getValue()); 102 | if (position != (arguments.size() -1)) { 103 | constructor.append(CommonValues.COMA); 104 | } 105 | position++; 106 | } 107 | 108 | } 109 | 110 | constructor.append(CommonValues.PARENTHESIS_END) 111 | .append(CommonValues.KEY_START) 112 | .append(body.isEmpty() ? CommonValues.NEWLINE : body) 113 | .append(Objects.isNull(returnString) ? StringUtils.EMPTY : (returnString.isEmpty() ? StringUtils.EMPTY : buildReturn(returnString))) 114 | .append(CommonValues.TAB) 115 | .append(CommonValues.KEY_END); 116 | 117 | return constructor.toString(); 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/util/Constants.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.util; 2 | 3 | /** 4 | * Created by carlos on 01/05/17. 5 | */ 6 | public class Constants { 7 | 8 | public static final String ENTITY_PACKAGE = "entity-package"; 9 | public static final String REPOSITORY_PACKAGE = "repository-package"; 10 | public static final String REPOSITORY_POSTFIX = "repository-postfix"; 11 | public static final String MAGANER_PACKAGE = "manager-package"; 12 | public static final String MANAGER_POSTFIX = "manager-postfix"; 13 | public static final String ONLY_ANNOTATIONS = "only-annotations"; 14 | public static final String OVERWRITE = "overwrite"; 15 | public static final String EXTENDS = "additional-extends"; 16 | public static final String LOMBOK_ANOTATIONS = "lombok-annotations"; 17 | public static final String WITH_COMMENTS = "with-comments"; 18 | public static final String WITH_JPASPECIFICATIONEXECUTOR = "with-JpaSpecificationExecutor"; 19 | 20 | public static final String PROJECT_NAME = "Spring Data Generator"; 21 | 22 | public static final String VERSION = "(v2.0.1)"; 23 | 24 | public static final String TABLE_POSTFIX_COLUMN = "Postfix"; 25 | 26 | public static final String TABLE_FILE_COLUMN = "File Name"; 27 | public static final String TABLE_RESULT_COLUMN = "Result"; 28 | private Constants(){} 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/util/CustomResourceLoader.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.util; 2 | 3 | import org.apache.maven.artifact.DependencyResolutionRequiredException; 4 | import org.apache.maven.project.MavenProject; 5 | import org.springframework.core.io.Resource; 6 | import org.springframework.core.io.ResourceLoader; 7 | 8 | import java.io.File; 9 | import java.net.MalformedURLException; 10 | import java.net.URL; 11 | import java.net.URLClassLoader; 12 | import java.util.List; 13 | 14 | /** 15 | * Created by carlos on 22/04/17. 16 | */ 17 | public class CustomResourceLoader implements ResourceLoader { 18 | 19 | private URLClassLoader urlClassLoader; 20 | private String postfix; 21 | private boolean overwrite; 22 | private String repositoryPackage; 23 | private String repositoryPostfix; 24 | 25 | public CustomResourceLoader(MavenProject project){ 26 | 27 | try { 28 | List runtimeClasspathElements = project.getRuntimeClasspathElements(); 29 | URL[] runtimeUrls = new URL[runtimeClasspathElements.size()]; 30 | for (int i = 0; i < runtimeClasspathElements.size(); i++) { 31 | String element = runtimeClasspathElements.get(i); 32 | runtimeUrls[i] = new File(element).toURI().toURL(); 33 | } 34 | urlClassLoader = new URLClassLoader(runtimeUrls, Thread.currentThread().getContextClassLoader()); 35 | } catch (DependencyResolutionRequiredException | MalformedURLException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | 40 | @Override 41 | public Resource getResource(String s) { 42 | return null; 43 | } 44 | 45 | @Override 46 | public ClassLoader getClassLoader() { 47 | return this.urlClassLoader; 48 | } 49 | 50 | public URLClassLoader getUrlClassLoader(){ 51 | return this.urlClassLoader; 52 | } 53 | 54 | public String getPostfix() { 55 | return postfix; 56 | } 57 | 58 | public CustomResourceLoader setPostfix(String postfix) { 59 | this.postfix = postfix; 60 | return this; 61 | } 62 | 63 | public boolean isOverwrite() { 64 | return overwrite; 65 | } 66 | 67 | public CustomResourceLoader setOverwrite(boolean overwrite) { 68 | this.overwrite = overwrite; 69 | return this; 70 | } 71 | 72 | public String getRepositoryPackage() { 73 | return repositoryPackage; 74 | } 75 | 76 | public CustomResourceLoader setRepositoryPackage(String repositoryPackage) { 77 | this.repositoryPackage = repositoryPackage; 78 | return this; 79 | } 80 | 81 | public String getRepositoryPostfix() { 82 | return repositoryPostfix; 83 | } 84 | 85 | public CustomResourceLoader setRepositoryPostfix(String repositoryPostfix) { 86 | this.repositoryPostfix = repositoryPostfix; 87 | return this; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/util/GeneratorException.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.util; 2 | 3 | /** 4 | * Created by carlos on 17/07/17. 5 | */ 6 | public class GeneratorException extends RuntimeException{ 7 | 8 | public GeneratorException() { 9 | super(); 10 | } 11 | 12 | public GeneratorException(String message) { 13 | super(message); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/util/GeneratorProperties.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.util; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import org.apache.maven.project.MavenProject; 6 | 7 | import java.util.Set; 8 | 9 | /** 10 | * Created by carlos on 29/11/23. 11 | */ 12 | 13 | @Data 14 | @Builder 15 | public class GeneratorProperties { 16 | private String[] entityPackage; 17 | private String repositoryPackage; 18 | private String repositoryPostfix; 19 | private String managerPackage; 20 | private String managerPostfix; 21 | private boolean onlyAnnotations; 22 | private boolean overwrite; 23 | private boolean lombokAnnotations; 24 | private boolean withComments; 25 | private boolean withJpaSpecificationExecutor; 26 | private Set additionalExtendsList; 27 | private MavenProject project; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/util/GeneratorUtils.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.util; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | import java.nio.file.Paths; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * Created by carlos on 08/04/17. 13 | */ 14 | public class GeneratorUtils { 15 | 16 | private GeneratorUtils() { 17 | } 18 | 19 | public static String getAbsolutePath(){ 20 | try { 21 | return new File(".").getCanonicalPath() + "/src/main/java/"; 22 | } catch (IOException e) { 23 | return null; 24 | } 25 | } 26 | 27 | public static String getAbsolutePath(String strPackage){ 28 | String absolute = getAbsolutePath(); 29 | if (absolute == null) { 30 | return null; 31 | } 32 | return absolute + strPackage.replace(".", "/"); 33 | } 34 | 35 | public static boolean verifyPackage(String stringPath){ 36 | Path path = Paths.get(stringPath); 37 | if (!path.toFile().exists()) { 38 | try { 39 | Files.createDirectories(path); 40 | return true; 41 | } catch (IOException e) { 42 | SDLogger.addError(String.format("Could not create directory: %s ", stringPath) + e.getMessage()); 43 | return false; 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | public static String getSimpleClassName(String beanClassName) { 50 | int index = -1; 51 | for (int i = (beanClassName.length() - 1); i >= 0; i--) { 52 | if(beanClassName.charAt(i) == '.'){ 53 | index = i; 54 | break; 55 | } 56 | } 57 | return index == -1 ? null : beanClassName.substring(index + 1); 58 | } 59 | 60 | public static String decapitalize(String cad) { 61 | char[] c = cad.toCharArray(); 62 | c[0] = Character.toLowerCase(c[0]); 63 | return new String(c); 64 | } 65 | 66 | public static File[] getFileList(String dirPath, String prefix) { 67 | List returnFiles = new ArrayList<>(); 68 | findFiles(dirPath, returnFiles, prefix); 69 | return returnFiles.toArray(new File[returnFiles.size()]); 70 | } 71 | 72 | private static void findFiles(String directoryName, List files, String prefix) { 73 | File directory = new File(directoryName); 74 | File[] filedDirectory = directory.listFiles(); 75 | if (filedDirectory != null) { 76 | for (File file : filedDirectory) { 77 | if (file.isFile()) { 78 | files.add(file); 79 | } else if (file.isDirectory()) { 80 | findFiles(file.getAbsolutePath(), files, prefix); 81 | } 82 | } 83 | } 84 | } 85 | public static boolean deleteQuietly(File file) { 86 | if (file == null) { 87 | return false; 88 | } else { 89 | try { 90 | return file.delete(); 91 | } catch (Exception var2) { 92 | return false; 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/util/SDLogger.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.util; 2 | 3 | import com.cmeza.sdgenerator.annotation.SDGenerator; 4 | import de.vandermeer.asciitable.AT_Row; 5 | import de.vandermeer.asciitable.AsciiTable; 6 | import de.vandermeer.asciitable.CWC_LongestWordMin; 7 | import de.vandermeer.asciithemes.a7.A7_Grids; 8 | import de.vandermeer.skb.interfaces.transformers.textformat.TextAlignment; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.apache.commons.logging.Log; 11 | import org.apache.commons.logging.LogFactory; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.stream.IntStream; 16 | 17 | /** 18 | * Created by carlos on 23/04/17. 19 | */ 20 | public class SDLogger { 21 | private static final Log commonsLogger = LogFactory.getLog(SDGenerator.class); 22 | private static org.apache.maven.plugin.logging.Log mavenLogger; 23 | private static int generated = 0; 24 | private static final List errors = new ArrayList<>(); 25 | private static final List warns = new ArrayList<>(); 26 | private static final List additionalExtend = new ArrayList<>(); 27 | private static AsciiTable generatedTable; 28 | 29 | private SDLogger() { 30 | } 31 | 32 | public static void configure(org.apache.maven.plugin.logging.Log log) { 33 | mavenLogger = log; 34 | } 35 | 36 | public static void info(String message) { 37 | if (mavenLogger == null) { 38 | commonsLogger.info(message); 39 | return; 40 | } 41 | mavenLogger.info(message); 42 | } 43 | 44 | public static void debug(String message) { 45 | if (mavenLogger == null) { 46 | commonsLogger.debug(message); 47 | return; 48 | } 49 | mavenLogger.debug(message); 50 | } 51 | 52 | public static void error(String message) { 53 | if (mavenLogger == null) { 54 | commonsLogger.error(message); 55 | return; 56 | } 57 | mavenLogger.error(message); 58 | } 59 | 60 | public static Integer addError(String message) { 61 | errors.add(message); 62 | return errors.size(); 63 | } 64 | 65 | public static Integer addWarn(String warn) { 66 | warns.add(warn); 67 | return warns.size(); 68 | } 69 | 70 | public static Integer addAdditionalExtend(String ext) { 71 | additionalExtend.add(ext); 72 | return additionalExtend.size(); 73 | } 74 | 75 | private static void printErrors() { 76 | printGenericTable("Errors", errors); 77 | } 78 | 79 | private static void printWarns() { 80 | printGenericTable("Warnings", warns); 81 | } 82 | 83 | private static void printAdditionalExtends() { 84 | printGenericTable("Additional Extends", additionalExtend); 85 | } 86 | 87 | private static void br() { 88 | br(1); 89 | } 90 | 91 | private static void br(int iterate) { 92 | IntStream.iterate(0, i -> i++).limit(iterate).forEach(j ->{ 93 | if (mavenLogger == null) { 94 | commonsLogger.info(StringUtils.EMPTY); 95 | return; 96 | } 97 | mavenLogger.info(StringUtils.EMPTY); 98 | }); 99 | } 100 | 101 | private static void printGenericTable(String title, List messages) { 102 | AsciiTable table = new AsciiTable(); 103 | table.addRule(); 104 | table.addRow(null, title + ": " + messages.size()).getCells().get(1).getContext().setTextAlignment(TextAlignment.CENTER); 105 | table.addRule(); 106 | 107 | int count = 1; 108 | for (String mess : messages) { 109 | table.addRow("#" + count, mess).getCells().get(0).getContext().setTextAlignment(TextAlignment.CENTER); 110 | table.addRule(); 111 | count ++; 112 | } 113 | 114 | table.getContext().setGrid(A7_Grids.minusBarPlusEquals()); 115 | table.getRenderer().setCWC(new CWC_LongestWordMin(new int[]{5, 101})); 116 | table.renderAsCollection().forEach(SDLogger::info); 117 | } 118 | 119 | public static void addRowGeneratedTable(Object... columns) { 120 | if (generatedTable == null) { 121 | initializeTable(); 122 | } 123 | generatedTable.addRule(); 124 | AT_Row row = generatedTable.addRow(columns); 125 | 126 | if (columns[0] != null) { 127 | row.getCells().get(0).getContext().setTextAlignment(TextAlignment.CENTER); 128 | } 129 | 130 | 131 | if (columns[2] != null) { 132 | row.getCells().get(2).getContext().setTextAlignment(TextAlignment.CENTER); 133 | } 134 | } 135 | 136 | public static void printGeneratedTables(boolean debug) { 137 | if (debug && generatedTable == null) { 138 | initializeTable(); 139 | } 140 | 141 | if (generatedTable != null) { 142 | br(); 143 | printBanner(); 144 | br(); 145 | 146 | if (!additionalExtend.isEmpty()) { 147 | br(); 148 | printAdditionalExtends(); 149 | br(2); 150 | } 151 | 152 | if (generated > 0) { 153 | addRowGeneratedTable( null, null, generated + " files generated"); 154 | } else { 155 | addRowGeneratedTable( null, null, "No files generated"); 156 | } 157 | generatedTable.addRule(); 158 | generatedTable.getContext().setGrid(A7_Grids.minusBarPlusEquals()); 159 | generatedTable.getRenderer().setCWC(new CWC_LongestWordMin(new int[]{20, 68, 17})); 160 | generatedTable.renderAsCollection().forEach(SDLogger::info); 161 | 162 | br(); 163 | 164 | if (!warns.isEmpty()) { 165 | printWarns(); 166 | br(2); 167 | } 168 | 169 | }else { 170 | info(String.format("\u001B[1m\u001B[43m %s:\u001B[0m\u001B[43m %s files generated \u001B[0m", Constants.PROJECT_NAME, generated)); 171 | } 172 | 173 | if (!errors.isEmpty()) { 174 | br(); 175 | printErrors(); 176 | br(2); 177 | } 178 | } 179 | 180 | private static void initializeTable() { 181 | generatedTable = new AsciiTable(); 182 | generatedTable.addRule(); 183 | AT_Row header = generatedTable.addRow(Constants.TABLE_POSTFIX_COLUMN, Constants.TABLE_FILE_COLUMN, Constants.TABLE_RESULT_COLUMN); 184 | header.getCells().forEach(c -> c.getContext().setTextAlignment(TextAlignment.CENTER)); 185 | } 186 | 187 | public static void plusGenerated(int plus) { 188 | generated += plus; 189 | } 190 | 191 | private static void printBanner() { 192 | List banner = new ArrayList<>(); 193 | banner.add(" _____ _ ____ __ ______ __ "); 194 | banner.add(" / ___/____ _____(_)___ ____ _ / __ \\____ _/ /_____ _ / ____/__ ____ ___ _________ _/ /_____ _____"); 195 | banner.add(" \\__ \\/ __ \\/ ___/ / __ \\/ __ `/ / / / / __ `/ __/ __ `/ / / __/ _ \\/ __ \\/ _ \\/ ___/ __ `/ __/ __ \\/ ___/"); 196 | banner.add(" ___/ / /_/ / / / / / / / /_/ / / /_/ / /_/ / /_/ /_/ / / /_/ / __/ / / / __/ / / /_/ / /_/ /_/ / / "); 197 | banner.add("/____/ .___/_/ /_/_/ /_/\\__, / /_____/\\__,_/\\__/\\__,_/ \\____/\\___/_/ /_/\\___/_/ \\__,_/\\__/\\____/_/ "); 198 | banner.add("====/_/=================/____/======================================================================" + Constants.VERSION); 199 | banner.forEach(SDLogger::info); 200 | } 201 | 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/util/SDMojoException.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.util; 2 | 3 | import org.apache.maven.plugin.MojoExecutionException; 4 | 5 | /** 6 | * Created by carlos on 23/04/17. 7 | */ 8 | public class SDMojoException extends MojoExecutionException { 9 | 10 | public SDMojoException() { 11 | super(""); 12 | SDLogger.printGeneratedTables(true); 13 | } 14 | 15 | public SDMojoException(String message) { 16 | super(message); 17 | SDLogger.printGeneratedTables(true); 18 | } 19 | 20 | public SDMojoException(String message, Throwable cause) { 21 | super(message, cause); 22 | SDLogger.printGeneratedTables(true); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/cmeza/sdgenerator/util/Tuple.java: -------------------------------------------------------------------------------- 1 | package com.cmeza.sdgenerator.util; 2 | 3 | /** 4 | * Created by carlos on 23/04/17. 5 | */ 6 | public class Tuple, Y extends Comparable> implements Comparable>{ 7 | public final X x; 8 | public final Y y; 9 | public Tuple(X x, Y y) { 10 | this.x = x; 11 | this.y = y; 12 | } 13 | 14 | public X left(){ 15 | return this.x; 16 | } 17 | 18 | public Y right(){ 19 | return this.y; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "(" + x + "," + y + ")"; 25 | } 26 | 27 | @Override 28 | public int compareTo(Tuple o) { 29 | int d = this.x.compareTo(o.x); 30 | if (d == 0) 31 | return this.y.compareTo(o.y); 32 | return d; 33 | } 34 | 35 | @Override 36 | public boolean equals(Object obj) { 37 | return super.equals(obj); 38 | } 39 | 40 | @Override 41 | public int hashCode() { 42 | return super.hashCode(); 43 | } 44 | } --------------------------------------------------------------------------------