From 31901374fc15460a4697e1ae2fa4cec113774b3d Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Tue, 7 Jul 2009 09:04:46 +0000 Subject: [PATCH] METAGEN Start of JPA metamodel processor project --- tooling/metamodel-generator/issues.txt | 19 + tooling/metamodel-generator/license.txt | 202 +++ tooling/metamodel-generator/pom.xml | 323 ++++ tooling/metamodel-generator/readme.txt | 65 + .../src/main/assembly/dist.xml | 81 + .../hibernate/jpamodelgen/ClassWriter.java | 140 ++ .../org/hibernate/jpamodelgen/Context.java | 104 ++ .../hibernate/jpamodelgen/IMetaAttribute.java | 31 + .../jpamodelgen/IMetaCollection.java | 26 + .../hibernate/jpamodelgen/IMetaEntity.java | 45 + .../jpamodelgen/IMetaSingleAttribute.java | 24 + .../hibernate/jpamodelgen/ImportContext.java | 46 + .../jpamodelgen/ImportContextImpl.java | 184 ++ .../JPAMetaModelEntityProcessor.java | 443 +++++ .../org/hibernate/jpamodelgen/TypeUtils.java | 75 + .../jpamodelgen/annotation/MetaAttribute.java | 74 + .../annotation/MetaCollection.java | 46 + .../jpamodelgen/annotation/MetaEntity.java | 433 +++++ .../jpamodelgen/annotation/MetaMap.java | 42 + .../annotation/MetaSingleAttribute.java | 41 + .../jpamodelgen/xml/XmlMetaAttribute.java | 56 + .../jpamodelgen/xml/XmlMetaCollection.java | 38 + .../jpamodelgen/xml/XmlMetaEntity.java | 255 +++ .../xml/XmlMetaSingleAttribute.java | 35 + .../javax.annotation.processing.Processor | 1 + .../src/main/xsd/orm_2_0.xsd | 1504 +++++++++++++++++ .../src/main/xsd/persistence_2_0.xsd | 247 +++ .../src/test/java/model/Address.java | 71 + .../src/test/java/model/Area.java | 59 + .../src/test/java/model/Building.java | 36 + .../src/test/java/model/Country.java | 46 + .../src/test/java/model/Customer.java | 45 + .../src/test/java/model/Detail.java | 55 + .../src/test/java/model/Hominidae.java | 43 + .../src/test/java/model/House.java | 38 + .../src/test/java/model/Human.java | 37 + .../src/test/java/model/Inhabitant.java | 43 + .../src/test/java/model/Item.java | 94 ++ .../src/test/java/model/LivingBeing.java | 43 + .../src/test/java/model/Mammals.java | 47 + .../src/test/java/model/Order.java | 47 + .../src/test/java/model/Pet.java | 40 + .../src/test/java/model/Product.java | 53 + .../src/test/java/model/Shop.java | 35 + .../src/test/java/model/User.java | 58 + .../test/java/model/xmlmapped/Address.java | 51 + .../test/java/model/xmlmapped/Building.java | 36 + .../java/model/xmlmapped/LivingBeing.java | 37 + .../src/test/java/model/xmlmapped/Mammal.java | 42 + .../src/test/java/test/AccessTypeTest.java | 94 ++ .../src/test/java/test/InheritanceTest.java | 46 + .../src/test/java/test/QueryTest.java | 166 ++ .../src/test/java/test/XmlMappingTest.java | 55 + .../src/test/resources/META-INF/dummy.xml | 14 + .../src/test/resources/META-INF/jpa1-orm.xml | 14 + .../META-INF/malformed-mapping-xml.xml | 13 + .../src/test/resources/META-INF/orm.xml | 29 + .../test/resources/META-INF/persistence.xml | 14 + .../resources/model/xmlmapped/address.xml | 17 + .../resources/model/xmlmapped/building.xml | 15 + .../test/resources/model/xmlmapped/mammal.xml | 20 + .../src/test/suite/unit-tests.xml | 9 + 62 files changed, 6142 insertions(+) create mode 100644 tooling/metamodel-generator/issues.txt create mode 100644 tooling/metamodel-generator/license.txt create mode 100644 tooling/metamodel-generator/pom.xml create mode 100644 tooling/metamodel-generator/readme.txt create mode 100644 tooling/metamodel-generator/src/main/assembly/dist.xml create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaAttribute.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaCollection.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaEntity.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaSingleAttribute.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContext.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContextImpl.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/TypeUtils.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttribute.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaCollection.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaEntity.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaMap.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaSingleAttribute.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaAttribute.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaCollection.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java create mode 100644 tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaSingleAttribute.java create mode 100644 tooling/metamodel-generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor create mode 100644 tooling/metamodel-generator/src/main/xsd/orm_2_0.xsd create mode 100644 tooling/metamodel-generator/src/main/xsd/persistence_2_0.xsd create mode 100644 tooling/metamodel-generator/src/test/java/model/Address.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Area.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Building.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Country.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Customer.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Detail.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Hominidae.java create mode 100644 tooling/metamodel-generator/src/test/java/model/House.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Human.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Inhabitant.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Item.java create mode 100644 tooling/metamodel-generator/src/test/java/model/LivingBeing.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Mammals.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Order.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Pet.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Product.java create mode 100644 tooling/metamodel-generator/src/test/java/model/Shop.java create mode 100644 tooling/metamodel-generator/src/test/java/model/User.java create mode 100644 tooling/metamodel-generator/src/test/java/model/xmlmapped/Address.java create mode 100644 tooling/metamodel-generator/src/test/java/model/xmlmapped/Building.java create mode 100644 tooling/metamodel-generator/src/test/java/model/xmlmapped/LivingBeing.java create mode 100644 tooling/metamodel-generator/src/test/java/model/xmlmapped/Mammal.java create mode 100644 tooling/metamodel-generator/src/test/java/test/AccessTypeTest.java create mode 100644 tooling/metamodel-generator/src/test/java/test/InheritanceTest.java create mode 100644 tooling/metamodel-generator/src/test/java/test/QueryTest.java create mode 100644 tooling/metamodel-generator/src/test/java/test/XmlMappingTest.java create mode 100644 tooling/metamodel-generator/src/test/resources/META-INF/dummy.xml create mode 100644 tooling/metamodel-generator/src/test/resources/META-INF/jpa1-orm.xml create mode 100644 tooling/metamodel-generator/src/test/resources/META-INF/malformed-mapping-xml.xml create mode 100644 tooling/metamodel-generator/src/test/resources/META-INF/orm.xml create mode 100644 tooling/metamodel-generator/src/test/resources/META-INF/persistence.xml create mode 100644 tooling/metamodel-generator/src/test/resources/model/xmlmapped/address.xml create mode 100644 tooling/metamodel-generator/src/test/resources/model/xmlmapped/building.xml create mode 100644 tooling/metamodel-generator/src/test/resources/model/xmlmapped/mammal.xml create mode 100644 tooling/metamodel-generator/src/test/suite/unit-tests.xml diff --git a/tooling/metamodel-generator/issues.txt b/tooling/metamodel-generator/issues.txt new file mode 100644 index 0000000000..fe67e2d89e --- /dev/null +++ b/tooling/metamodel-generator/issues.txt @@ -0,0 +1,19 @@ + +- Find host for project + +- Implement XML overriding of annotation metadata + +- Implement access Type rules for XML metadata + +- Investigate why it is not possible to use the Filer API to load non class resources, eg + /META-INF/orm.xml. The API throws a FilerException with the message "Illegal name /META-INF". + The call is processingEnv.getFiler().getResource((StandardLocation.CLASS_OUTPUT, "/META-INF", "orm.xml" ) + Currently we work around this by using Class.getResourceAsStream() + +- Optimize XML parsing by only processing XML files if they have changed since last run (maybe write + a tmp file against which to compare the last modified time stamp) + +- Reduce the amount of logging and make logging configurable using the possibility to pass arguments to + the processor using -Akey[=value] + +- Write IDE specific plugins which allow to cache processing steps diff --git a/tooling/metamodel-generator/license.txt b/tooling/metamodel-generator/license.txt new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/tooling/metamodel-generator/license.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/tooling/metamodel-generator/pom.xml b/tooling/metamodel-generator/pom.xml new file mode 100644 index 0000000000..11cc4955a8 --- /dev/null +++ b/tooling/metamodel-generator/pom.xml @@ -0,0 +1,323 @@ + + + 4.0.0 + + org.hibernate + hibernate-jpamodelgen + 1.0.0-SNAPSHOT + + JPA 2 Static-Metamodel Generator + Annotation Processor to generate JPA 2 static metamodel classes + + 2009 + + + + org.hibernate.java-persistence + jpa-api + 2.0-cr-1 + + + org.testng + testng + 5.8 + jdk15 + test + + + + + + Apache License, Version 2.0 + license.txt + + + + + scm:svn:https://svn.jboss.org/repos/hibernate/jpamodelgen/trunk + http://fisheye.jboss.org/browse/Hibernate/jpamodelgen/trunk + + + + + epbernard + Emmanuel Bernard + emmanuel@hibernate.org + http://in.relation.to/Bloggers/Emmanuel + + + hardy.ferentschik + Hardy Ferentschik + hferents@redhat.com + JBoss, a division of Red Hat + http://in.relation.to/Bloggers/Hardy + + + max.andersen@jboss.com + Max Andersen + max.andersen@redhat.com + http://in.relation.to/Bloggers/Max + + + + + test + + + + src/main/resources + + + src/main/xsd + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + 1.6 + 1.6 + -proc:none + + + + org.apache.maven.plugins + maven-antrun-plugin + + + process_annotations + process-test-resources + + + + + + + + + + + + + ${project.build.directory}/generated-src/jpamodelgen + + + run + + + + + + org.codehaus.mojo + jaxb2-maven-plugin + 1.2 + + + + xjc + + + + + org.hibernate.jpamodelgen.xml.jaxb + ${basedir}/target/generated-sources + true + + + + true + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${basedir}/src/test/suite/unit-tests.xml + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + + generate-test-report + test + + report-only + + + + + ${project.build.directory}/surefire-reports + test-report + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + ${pom.artifactId} + ${pom.version} + ${pom.groupId} + ${pom.groupId} + ${pom.url} + JPA2 Model Generator + + + + + + maven-source-plugin + + + attach-sources + + jar + + + + + + maven-assembly-plugin + + + src/main/assembly/dist.xml + + + + + make-assembly + site + + assembly + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.0-beta-9 + + true + true + true + package deploy + + + + + + + + org.apache.maven.wagon + wagon-scm + 1.0-beta-6 + + + org.apache.maven.scm + maven-scm-manager-plexus + 1.0 + + + org.apache.maven.scm + maven-scm-provider-svnexe + 1.0 + + + + + + + repository.jboss.org + JBoss Release Repository + scm:svn:https://svn.jboss.org/repos/repository.jboss.org/maven2 + + + snapshots.jboss.org + JBoss Snapshot Repository + dav:https://snapshots.jboss.org/maven2 + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.0.1 + + + maven-javadoc-plugin + + + html + + + + todo + a + ToDo: + + + + + javadoc + + + + + + org.codehaus.mojo + jxr-maven-plugin + + + maven-surefire-plugin + + + maven-clover-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + 1.5 + + + + org.codehaus.mojo + taglist-maven-plugin + + + org.codehaus.mojo + changelog-maven-plugin + + + org.codehaus.mojo + changes-maven-plugin + + + + diff --git a/tooling/metamodel-generator/readme.txt b/tooling/metamodel-generator/readme.txt new file mode 100644 index 0000000000..95c79254ce --- /dev/null +++ b/tooling/metamodel-generator/readme.txt @@ -0,0 +1,65 @@ + JPA Model Generator + + What is it? + ----------- + + This is a Java 6 annotation processor generating meta model classes for the JPA 2 criteria queries. + The processor (JPAMetaModelEntityProcessor) processes all classes annotated with @Entity, as well as + entities mapped in /META-INF/orm.xml and mapping files specified in persistence.xml. + + + Status + ------ + + This is an alpha release of the annotation processor. The implemented functionality includes: + - full support for annotations honoring the access type (v2.0) + - support for persistence.xml, orm.xml and + - tests (both via compilation failure and regular assertion failure) + + + System Requirements + ------------------- + + JDK 1.6 or above. + + + Issues + ------ + + See issues.txt + + + Using JPA Model Generator + ------------------------- + + - Copy jpamodelgen-*.jar together will all jar files from lib into the classpath of your application. + The jpamodelgen jar file contains a service file (/META-INF/services/javax.annotation.processing.Processor) + so that the annotation processor will automatically be executed during compilation. + You can also explicitly specify the processor using the -processor flag: + > javac -cp -d -sourcepath -processor org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + + + * Maven + This distribution contains a pom.xml file showing one of three possible ways to integrate the processor in a maven project. + You can just add org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor to the maven-compiler-plugin. + This approach has, however, the shortcoming that messages from the annotation processor are not displayed. This is a known + issue. See also - http://weblogs.java.net/blog/ss141213/archive/2007/11/my_maven_experi.html + The second alternative is the maven-annotation-plugin (http://code.google.com/p/maven-annotation-plugin/). This approach + hasn't been tested yet. + Last but not least, you can use the maven-antrun-plugin to just run the annotation processor and ignore the processor in + in the maven-compiler-plugin via '-proc:none'. This is the approach chosen in the POM for this project. + + * Ant + Make sure the annotation processor and its dependencies are in the classpath. Due the service file the processor will be + automatically executed when the javac task executes. + If not try adding + + * Idea + Again, if in the classpath the JPAMetaModelEntityProcessor should execute automatically. If not add the following under + 'Compiler->Java Compiler': -target 1.6 -processor org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + You can also turn of annotation processing via: -target 1.6 -proc:none + + + + + diff --git a/tooling/metamodel-generator/src/main/assembly/dist.xml b/tooling/metamodel-generator/src/main/assembly/dist.xml new file mode 100644 index 0000000000..d65a8d8785 --- /dev/null +++ b/tooling/metamodel-generator/src/main/assembly/dist.xml @@ -0,0 +1,81 @@ + + + + + dist + + tar.gz + tar.bz2 + zip + + + + + false + lib + runtime + + + + + + readme.txt + / + true + + + license.txt + / + + + issues.txt + / + + + + + + target + + + *-javadoc.jar + *-sources.jar + + + jpamodelgen-*.jar + + + + target/site/apidocs + docs/api + + + . + + true + + *.txt + **/target/** + *.iml + + + + + diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java new file mode 100644 index 0000000000..29552db433 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java @@ -0,0 +1,140 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.util.List; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.FilerException; +import javax.annotation.Generated; +import javax.tools.FileObject; +import javax.tools.Diagnostic; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +/** + * @author Emmanuel Bernard + */ +public class ClassWriter { + + public static void writeFile(IMetaEntity entity, ProcessingEnvironment processingEnv, Context context) { + try { + String metaModelPackage = entity.getPackageName(); + + StringBuffer body = generateBody( entity, context ); + + FileObject fo = processingEnv.getFiler().createSourceFile( + metaModelPackage + "." + entity.getSimpleName() + "_" + ); + OutputStream os = fo.openOutputStream(); + PrintWriter pw = new PrintWriter( os ); + + pw.println( "package " + metaModelPackage + ";" ); + + pw.println(); + + pw.println( entity.generateImports() ); + + pw.println( body ); + + pw.flush(); + pw.close(); + + } + catch ( FilerException filerEx ) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.ERROR, + "Problem with Processing Environment Filer: " + + filerEx.getMessage() + ); + } + catch ( IOException ioEx ) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.ERROR, + "Problem opening file to write MetaModel for " + entity.getSimpleName() + + ioEx.getMessage() + ); + } + } + + /** + * Generate everything after import statements. + * + * @param entity The meta entity for which to write the body + * + * @return body content + */ + private static StringBuffer generateBody(IMetaEntity entity, Context context) { + + StringWriter sw = new StringWriter(); + PrintWriter pw = null; + try { + + pw = new PrintWriter( sw ); + + //pw.println( "@" + entity.importType( Generated.class.getName() ) + "(\"JPA MetaModel for " + entity.getQualifiedName() + "\")" ); + + pw.println( "@" + entity.importType( "javax.persistence.metamodel.StaticMetamodel" ) + "(" + entity.getSimpleName() + ".class)" ); + + + + printClassDeclaration( entity, pw, context ); + + pw.println(); + + List members = entity.getMembers(); + + for ( IMetaAttribute metaMember : members ) { + pw.println( " " + metaMember.getDeclarationString() ); + } + pw.println(); + pw.println( "}" ); + return sw.getBuffer(); + } + finally { + if ( pw != null ) { + pw.close(); + } + } + } + + private static void printClassDeclaration(IMetaEntity entity, PrintWriter pw, Context context) { + pw.print( "public abstract class " + entity.getSimpleName() + "_" ); + + final TypeMirror superClass = entity.getTypeElement().getSuperclass(); + //superclass of Object is of NoType which returns some other kind + String superclassDeclaration = ""; + if (superClass.getKind() == TypeKind.DECLARED ) { + //F..king Ch...t Have those people used their horrible APIs even once? + final Element superClassElement = ( ( DeclaredType ) superClass ).asElement(); + String superClassName = ( ( TypeElement ) superClassElement ).getQualifiedName().toString(); + if ( context.getMetaEntitiesToProcess().containsKey( superClassName ) + || context.getMetaSuperclassAndEmbeddableToProcess().containsKey( superClassName ) ) { + pw.print( " extends " + superClassName + "_" ); + } + } + + pw.println( " {" ); + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java new file mode 100644 index 0000000000..19f711c4b9 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java @@ -0,0 +1,104 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; +import javax.lang.model.element.TypeElement; +import javax.persistence.AccessType; +import javax.annotation.processing.ProcessingEnvironment; +import javax.tools.Diagnostic; + +import org.hibernate.jpamodelgen.annotation.MetaEntity; + +/** + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public class Context { + //used to cache access types + private Map accessTypes = new HashMap(); + private Set elementsAlreadyProcessed = new HashSet(); + private ProcessingEnvironment pe; + private final Map metaEntitiesToProcess = new HashMap(); + private final Map metaSuperclassAndEmbeddableToProcess = new HashMap(); + + private static class AccessTypeHolder { + public AccessType elementAccessType; + public AccessType hierarchyAccessType; + } + + public Context(ProcessingEnvironment pe) { + this.pe = pe; + } + + public Map getMetaEntitiesToProcess() { + return metaEntitiesToProcess; + } + + public Map getMetaSuperclassAndEmbeddableToProcess() { + return metaSuperclassAndEmbeddableToProcess; + } + + public void addAccessType(TypeElement element, AccessType accessType) { + AccessTypeHolder typeHolder = accessTypes.get( element ); + if ( typeHolder == null ) { + typeHolder = new AccessTypeHolder(); + accessTypes.put( element, typeHolder ); + } + typeHolder.elementAccessType = accessType; + } + + public void addAccessTypeForHierarchy(TypeElement element, AccessType accessType) { + AccessTypeHolder typeHolder = accessTypes.get( element ); + if ( typeHolder == null ) { + typeHolder = new AccessTypeHolder(); + accessTypes.put( element, typeHolder ); + } + typeHolder.hierarchyAccessType = accessType; + } + + public AccessType getAccessType(TypeElement element) { + final AccessTypeHolder typeHolder = accessTypes.get( element ); + return typeHolder != null ? typeHolder.elementAccessType : null; + } + + public AccessType getDefaultAccessTypeForHerarchy(TypeElement element) { + final AccessTypeHolder typeHolder = accessTypes.get( element ); + return typeHolder != null ? typeHolder.hierarchyAccessType : null; + } + + public Set getElementsAlreadyProcessed() { + return elementsAlreadyProcessed; + } + + //only process Embeddable or Superclass + //does not work for Entity (risk of circularity) + public void processElement(TypeElement element, AccessType defaultAccessTypeForHierarchy) { + if ( elementsAlreadyProcessed.contains( element.getQualifiedName().toString() ) ) { + pe.getMessager().printMessage( Diagnostic.Kind.WARNING, "Element already processed (ignoring): " + element ); + return; + } + + ClassWriter.writeFile( new MetaEntity( pe, element, this, defaultAccessTypeForHierarchy ), pe, this ); + elementsAlreadyProcessed.add( element.getQualifiedName().toString() ); + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaAttribute.java new file mode 100644 index 0000000000..4bab627ff0 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaAttribute.java @@ -0,0 +1,31 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +/** + * @author Hardy Ferentschik + */ +public interface IMetaAttribute { + String getDeclarationString(); + + String getMetaType(); + + String getPropertyName(); + + String getTypeDeclaration(); +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaCollection.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaCollection.java new file mode 100644 index 0000000000..b478f56377 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaCollection.java @@ -0,0 +1,26 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +import org.hibernate.jpamodelgen.IMetaAttribute; + +/** + * @author Hardy Ferentschik + */ +public interface IMetaCollection extends IMetaAttribute { +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaEntity.java new file mode 100644 index 0000000000..b764d5e9dc --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaEntity.java @@ -0,0 +1,45 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import java.util.List; + +/** + * @author Hardy Ferentschik + */ +public interface IMetaEntity extends ImportContext { + String getSimpleName(); + + String getQualifiedName(); + + String getPackageName(); + + List getMembers(); + + String generateImports(); + + String importType(String fqcn); + + String staticImport(String fqcn, String member); + + String importType(Name qualifiedName); + + TypeElement getTypeElement(); +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaSingleAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaSingleAttribute.java new file mode 100644 index 0000000000..a865e5fcf2 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/IMetaSingleAttribute.java @@ -0,0 +1,24 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +/** + * @author Hardy Ferentschik + */ +public interface IMetaSingleAttribute extends IMetaAttribute { +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContext.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContext.java new file mode 100644 index 0000000000..a9c2b6fd48 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContext.java @@ -0,0 +1,46 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public interface ImportContext { + + /** + * Add fqcn to the import list. Returns fqcn as needed in source code. + * Attempts to handle fqcn with array and generics references. + *

+ * e.g. + * java.util.Collection imports java.util.Collection and returns Collection + * org.marvel.Hulk[] imports org.marvel.Hulk and returns Hulk + * + * @param fqcn Fully qualified class name of the type to import. + * + * @return import string + */ + public abstract String importType(String fqcn); + + public abstract String staticImport(String fqcn, String member); + + public abstract String generateImports(); + +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContextImpl.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContextImpl.java new file mode 100644 index 0000000000..0a705a193c --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContextImpl.java @@ -0,0 +1,184 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public class ImportContextImpl implements ImportContext { + + Set imports = new TreeSet(); + Set staticImports = new TreeSet(); + Map simpleNames = new HashMap(); + + String basePackage = ""; + + private static final Map PRIMITIVES = new HashMap(); + static { + PRIMITIVES.put( "char", "Character" ); + + PRIMITIVES.put( "byte", "Byte" ); + PRIMITIVES.put( "short", "Short" ); + PRIMITIVES.put( "int", "Integer" ); + PRIMITIVES.put( "long", "Long" ); + + PRIMITIVES.put( "boolean", "Boolean" ); + + PRIMITIVES.put( "float", "Float" ); + PRIMITIVES.put( "double", "Double" ); + + } + + public ImportContextImpl(String basePackage) { + this.basePackage = basePackage; + } + + /** + * Add fqcn to the import list. Returns fqcn as needed in source code. + * Attempts to handle fqcn with array and generics references. + * + * e.g. + * java.util.Collection imports java.util.Collection and returns Collection + * org.marvel.Hulk[] imports org.marvel.Hulk and returns Hulk + * + * + * @param fqcn + * @return import string + */ + public String importType(String fqcn) { + String result = fqcn; + + //if(fqcn==null) return "/** (null) **/"; + + String additionalTypePart = null; + if(fqcn.indexOf('<')>=0) { + additionalTypePart = result.substring(fqcn.indexOf('<')); + result = result.substring(0,fqcn.indexOf('<')); + fqcn = result; + } else if(fqcn.indexOf('[')>=0) { + additionalTypePart = result.substring(fqcn.indexOf('[')); + result = result.substring(0,fqcn.indexOf('[')); + fqcn = result; + } + + String pureFqcn = fqcn.replace( '$', '.' ); + + boolean canBeSimple = true; + + + String simpleName = unqualify(fqcn); + if(simpleNames.containsKey(simpleName)) { + String existingFqcn = simpleNames.get(simpleName); + if(existingFqcn.equals(pureFqcn)) { + canBeSimple = true; + } else { + canBeSimple = false; + } + } else { + canBeSimple = true; + simpleNames.put(simpleName, pureFqcn); + imports.add( pureFqcn ); + } + + + if ( inSamePackage(fqcn) || (imports.contains( pureFqcn ) && canBeSimple) ) { + result = unqualify( result ); // dequalify + } else if ( inJavaLang( fqcn ) ) { + result = result.substring( "java.lang.".length() ); + } + + if(additionalTypePart!=null) { + result = result + additionalTypePart; + } + + result = result.replace( '$', '.' ); + return result; + } + + public String staticImport(String fqcn, String member) { + String local = fqcn + "." + member; + imports.add(local); + staticImports.add(local); + + if(member.equals("*")) { + return ""; + } else { + return member; + } + } + + private boolean inDefaultPackage(String className) { + return className.indexOf( "." ) < 0; + } + + private boolean isPrimitive(String className) { + return PRIMITIVES.containsKey( className ); + } + + private boolean inSamePackage(String className) { + String other = qualifier( className ); + return other == basePackage + || (other != null && other.equals( basePackage ) ); + } + + private boolean inJavaLang(String className) { + return "java.lang".equals( qualifier( className ) ); + } + + public String generateImports() { + StringBuffer buf = new StringBuffer(); + + for ( Iterator imps = imports.iterator(); imps.hasNext(); ) { + String next = imps.next(); + if(isPrimitive(next) || inDefaultPackage(next) || inJavaLang(next) || inSamePackage(next)) { + // dont add automatically "imported" stuff + } else { + if(staticImports.contains(next)) { + buf.append("import static " + next + ";\r\n"); + } else { + buf.append("import " + next + ";\r\n"); + } + } + } + + if(buf.indexOf( "$" )>=0) { + return buf.toString(); + } + return buf.toString(); + } + + public static String unqualify(String qualifiedName) { + int loc = qualifiedName.lastIndexOf("."); + return ( loc < 0 ) ? qualifiedName : qualifiedName.substring( qualifiedName.lastIndexOf(".") + 1 ); + } + + public static String qualifier(String qualifiedName) { + int loc = qualifiedName.lastIndexOf("."); + return ( loc < 0 ) ? "" : qualifiedName.substring( 0, loc ); + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java new file mode 100644 index 0000000000..a03b1363a8 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java @@ -0,0 +1,443 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import static javax.lang.model.SourceVersion.RELEASE_6; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; +import javax.persistence.AccessType; +import javax.persistence.Embeddable; +import javax.persistence.MappedSuperclass; +import javax.tools.Diagnostic; +import javax.tools.FileObject; +import javax.tools.StandardLocation; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.xml.sax.SAXException; + +import org.hibernate.jpamodelgen.annotation.MetaEntity; +import org.hibernate.jpamodelgen.xml.XmlMetaEntity; +import org.hibernate.jpamodelgen.xml.jaxb.Entity; +import org.hibernate.jpamodelgen.xml.jaxb.EntityMappings; +import org.hibernate.jpamodelgen.xml.jaxb.ObjectFactory; +import org.hibernate.jpamodelgen.xml.jaxb.Persistence; +import org.hibernate.jpamodelgen.xml.jaxb.PersistenceUnitDefaults; +import org.hibernate.jpamodelgen.xml.jaxb.PersistenceUnitMetadata; + +/** + * Main annotation processor. + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +//@SupportedAnnotationTypes("javax.persistence.Entity") +@SupportedAnnotationTypes("*") +@SupportedSourceVersion(RELEASE_6) +// TODO Extract all the XML parsing into a separate class +public class JPAMetaModelEntityProcessor extends AbstractProcessor { + + private static final String PATH_SEPARATOR = "/"; + private static final String PERSISTENCE_XML = "/META-INF/persistence.xml"; + private static final String ORM_XML = "/META-INF/orm.xml"; + private static final Boolean ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS = Boolean.FALSE; + private static final String ENTITY_ANN = javax.persistence.Entity.class.getName(); + private static final String MAPPED_SUPERCLASS_ANN = MappedSuperclass.class.getName(); + private static final String EMBEDDABLE_ANN = Embeddable.class.getName(); + private static final AccessType DEFAULT_XML_ACCESS_TYPE = AccessType.PROPERTY; + private static final String PERSISTENCE_XML_XSD = "persistence_2_0.xsd"; + private static final String ORM_XSD = "orm_2_0.xsd"; + + private boolean xmlProcessed = false; + private Context context; + + public void init(ProcessingEnvironment env) { + super.init( env ); + context = new Context( env ); + processingEnv.getMessager().printMessage( Diagnostic.Kind.NOTE, "Init Processor " + this ); + } + + @Override + public boolean process(final Set annotations, + final RoundEnvironment roundEnvironment) { + + if ( roundEnvironment.processingOver() ) { + processingEnv.getMessager() + .printMessage( Diagnostic.Kind.NOTE, "Last processing round." ); + + createMetaModelClasses(); + + processingEnv.getMessager() + .printMessage( Diagnostic.Kind.NOTE, "Finished processing" ); + return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS; + } + + if ( !xmlProcessed ) { + parsePersistenceXml(); + } + + if ( !hostJPAAnnotations( annotations ) ) { + processingEnv.getMessager() + .printMessage( Diagnostic.Kind.NOTE, "Current processing round does not contain entities" ); + return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS; + } + + Set elements = roundEnvironment.getRootElements(); + for ( Element element : elements ) { + processingEnv.getMessager().printMessage( Diagnostic.Kind.NOTE, "Processing " + element.toString() ); + handleRootElementAnnotationMirrors( element ); + } + + return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS; + } + + private void createMetaModelClasses() { + for ( IMetaEntity entity : context.getMetaEntitiesToProcess().values() ) { + processingEnv.getMessager() + .printMessage( Diagnostic.Kind.NOTE, "Writing meta model for " + entity ); + ClassWriter.writeFile( entity, processingEnv, context ); + } + + //process left over, in most cases is empty + for ( String className : context.getElementsAlreadyProcessed() ) { + context.getMetaSuperclassAndEmbeddableToProcess().remove( className ); + } + + for ( IMetaEntity entity : context.getMetaSuperclassAndEmbeddableToProcess().values() ) { + processingEnv.getMessager() + .printMessage( Diagnostic.Kind.NOTE, "Writing meta model for " + entity ); + ClassWriter.writeFile( entity, processingEnv, context ); + } + } + + private boolean hostJPAAnnotations(Set annotations) { + for ( TypeElement type : annotations ) { + final String typeName = type.getQualifiedName().toString(); + if ( typeName.equals( ENTITY_ANN ) ) { + return true; + } + else if ( typeName.equals( EMBEDDABLE_ANN ) ) { + return true; + } + else if ( typeName.equals( MAPPED_SUPERCLASS_ANN ) ) { + return true; + } + } + return false; + } + + private void parsePersistenceXml() { + Persistence persistence = parseXml( PERSISTENCE_XML, Persistence.class, PERSISTENCE_XML_XSD ); + if ( persistence != null ) + { + List persistenceUnits = persistence.getPersistenceUnit(); + for ( Persistence.PersistenceUnit unit : persistenceUnits ) { + List mappingFiles = unit.getMappingFile(); + for ( String mappingFile : mappingFiles ) { + parsingOrmXml( mappingFile ); + } + } + } + parsingOrmXml( ORM_XML ); // /META-INF/orm.xml is implicit + xmlProcessed = true; + } + + private void parsingOrmXml(String resource) { + EntityMappings mappings = parseXml( resource, EntityMappings.class, ORM_XSD ); + if ( mappings == null ) { + return; + } + + AccessType accessType = determineGlobalAccessType( mappings ); + + parseEntities( mappings, accessType ); + parseEmbeddable( mappings, accessType ); + parseMappedSuperClass( mappings, accessType ); + } + + private AccessType determineGlobalAccessType(EntityMappings mappings) { + AccessType accessType = DEFAULT_XML_ACCESS_TYPE; + + if ( mappings.getAccess() != null ) { + accessType = mapXmlAccessTypeToJpaAccessType( mappings.getAccess() ); + return accessType; // no need to check persistence unit default + } + + PersistenceUnitMetadata meta = mappings.getPersistenceUnitMetadata(); + if ( meta != null ) { + PersistenceUnitDefaults persistenceUnitDefaults = meta.getPersistenceUnitDefaults(); + if ( persistenceUnitDefaults != null ) { + org.hibernate.jpamodelgen.xml.jaxb.AccessType xmlAccessType = persistenceUnitDefaults.getAccess(); + if ( xmlAccessType != null ) { + accessType = mapXmlAccessTypeToJpaAccessType( xmlAccessType ); + } + } + } + return accessType; + } + + private AccessType mapXmlAccessTypeToJpaAccessType(org.hibernate.jpamodelgen.xml.jaxb.AccessType xmlAccessType) { + switch ( xmlAccessType ) { + case FIELD: { + return AccessType.FIELD; + } + case PROPERTY: { + return AccessType.PROPERTY; + } + } + return null; + } + + private void parseEntities(EntityMappings mappings, AccessType accessType) { + String packageName = mappings.getPackage(); + Collection entities = mappings.getEntity(); + for ( Entity entity : entities ) { + String fullyQualifiedClassName = packageName + "." + entity.getClazz(); + + if ( !xmlMappedTypeExists( fullyQualifiedClassName ) ) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.WARNING, + fullyQualifiedClassName + " is mapped in xml, but class does not exists. Skipping meta model generation." + ); + continue; + } + + XmlMetaEntity metaEntity = new XmlMetaEntity( + entity, packageName, getXmlMappedType( fullyQualifiedClassName ) + ); + + if ( context.getMetaEntitiesToProcess().containsKey( fullyQualifiedClassName ) ) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.WARNING, + fullyQualifiedClassName + " was already processed once. Skipping second occurance." + ); + } + context.getMetaEntitiesToProcess().put( fullyQualifiedClassName, metaEntity ); + } + } + + private boolean xmlMappedTypeExists(String fullyQualifiedClassName) { + Elements utils = processingEnv.getElementUtils(); + return utils.getTypeElement( fullyQualifiedClassName ) != null; + } + + private TypeElement getXmlMappedType(String fullyQualifiedClassName) { + Elements utils = processingEnv.getElementUtils(); + return utils.getTypeElement( fullyQualifiedClassName ); + } + + private void parseEmbeddable(EntityMappings mappings, AccessType accessType) { + String packageName = mappings.getPackage(); + Collection embeddables = mappings.getEmbeddable(); + for ( org.hibernate.jpamodelgen.xml.jaxb.Embeddable embeddable : embeddables ) { + String fullyQualifiedClassName = packageName + "." + embeddable.getClazz(); + + if ( !xmlMappedTypeExists( fullyQualifiedClassName ) ) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.WARNING, + fullyQualifiedClassName + " is mapped in xml, but class does not exists. Skipping meta model generation." + ); + continue; + } + + XmlMetaEntity metaEntity = new XmlMetaEntity( + embeddable, packageName, getXmlMappedType( fullyQualifiedClassName ) + ); + + if ( context.getMetaSuperclassAndEmbeddableToProcess().containsKey( fullyQualifiedClassName ) ) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.WARNING, + fullyQualifiedClassName + " was already processed once. Skipping second occurance." + ); + } + context.getMetaSuperclassAndEmbeddableToProcess().put( fullyQualifiedClassName, metaEntity ); + } + } + + private void parseMappedSuperClass(EntityMappings mappings, AccessType accessType) { + String packageName = mappings.getPackage(); + Collection mappedSuperClasses = mappings.getMappedSuperclass(); + for ( org.hibernate.jpamodelgen.xml.jaxb.MappedSuperclass mappedSuperClass : mappedSuperClasses ) { + String fullyQualifiedClassName = packageName + "." + mappedSuperClass.getClazz(); + + if ( !xmlMappedTypeExists( fullyQualifiedClassName ) ) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.WARNING, + fullyQualifiedClassName + " is mapped in xml, but class does not exists. Skipping meta model generation." + ); + continue; + } + + XmlMetaEntity metaEntity = new XmlMetaEntity( + mappedSuperClass, packageName, getXmlMappedType( fullyQualifiedClassName ) + ); + + if ( context.getMetaSuperclassAndEmbeddableToProcess().containsKey( fullyQualifiedClassName ) ) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.WARNING, + fullyQualifiedClassName + " was already processed once. Skipping second occurance." + ); + } + context.getMetaSuperclassAndEmbeddableToProcess().put( fullyQualifiedClassName, metaEntity ); + } + } + + private void handleRootElementAnnotationMirrors(final Element element) { + + List annotationMirrors = element + .getAnnotationMirrors(); + + for ( AnnotationMirror mirror : annotationMirrors ) { + final String annotationType = mirror.getAnnotationType().toString(); + + if ( element.getKind() == ElementKind.CLASS ) { + if ( annotationType.equals( ENTITY_ANN ) ) { + MetaEntity metaEntity = new MetaEntity( processingEnv, ( TypeElement ) element, context ); + // TODO instead of just adding the entity we have to do some merging. + context.getMetaEntitiesToProcess().put( metaEntity.getQualifiedName(), metaEntity ); + } + else if ( annotationType.equals( MAPPED_SUPERCLASS_ANN ) + || annotationType.equals( EMBEDDABLE_ANN ) ) { + MetaEntity metaEntity = new MetaEntity( processingEnv, ( TypeElement ) element, context ); + + // TODO instead of just adding the entity we have to do some merging. + context.getMetaSuperclassAndEmbeddableToProcess().put( metaEntity.getQualifiedName(), metaEntity ); + } + } + } + } + + private InputStream getInputStreamForResource(String resource) { + String pkg = getPackage( resource ); + String name = getRelativeName( resource ); + processingEnv.getMessager() + .printMessage( Diagnostic.Kind.NOTE, "Reading resource " + resource ); + InputStream ormStream; + try { + FileObject fileObject = processingEnv.getFiler().getResource( StandardLocation.CLASS_OUTPUT, pkg, name ); + ormStream = fileObject.openInputStream(); + } + catch ( IOException e1 ) { + processingEnv.getMessager() + .printMessage( + Diagnostic.Kind.WARNING, + "Could not load " + resource + " using processingEnv.getFiler().getResource(). Using classpath..." + ); + + // TODO + // unfortunately, the Filer.getResource API seems not to be able to load from /META-INF. One gets a + // FilerException with the message with "Illegal name /META-INF". This means that we have to revert to + // using the classpath. This might mean that we find a persistence.xml which is 'part of another jar. + // Not sure what else we can do here + ormStream = this.getClass().getResourceAsStream( resource ); + } + return ormStream; + } + + /** + * Tries to open the specified xml file and return an instance of the specified class using JAXB. + * + * @param resource the xml file name + * @param clazz The type of jaxb node to return + * @param schemaName The schema to validate against (can be {@code null}); + * + * @return The top level jaxb instance contained in the xml file or {@code null} in case the file could not be found. + */ + private T parseXml(String resource, Class clazz, String schemaName) { + + InputStream stream = getInputStreamForResource( resource ); + + if ( stream == null ) { + processingEnv.getMessager().printMessage( Diagnostic.Kind.NOTE, resource + " not found." ); + return null; + } + try { + JAXBContext jc = JAXBContext.newInstance( ObjectFactory.class ); + Unmarshaller unmarshaller = jc.createUnmarshaller(); + if ( schemaName != null ) { + unmarshaller.setSchema( getSchema( schemaName ) ); + } + return clazz.cast( unmarshaller.unmarshal( stream ) ); + } + catch ( JAXBException e ) { + String message = "Error unmarshalling " + resource + " with exception :\n " + e; + processingEnv.getMessager().printMessage( Diagnostic.Kind.WARNING, message ); + return null; + } + catch ( Exception e ) { + String message = "Error reading " + resource + " with exception :\n " + e; + processingEnv.getMessager().printMessage( Diagnostic.Kind.WARNING, message ); + return null; + } + } + + private String getPackage(String resourceName) { + if ( !resourceName.contains( PATH_SEPARATOR ) ) { + return ""; + } + else { + return resourceName.substring( 0, resourceName.lastIndexOf( PATH_SEPARATOR ) ); + } + } + + private String getRelativeName(String resourceName) { + if ( !resourceName.contains( PATH_SEPARATOR ) ) { + return resourceName; + } + else { + return resourceName.substring( resourceName.lastIndexOf( PATH_SEPARATOR ) + 1 ); + } + } + + private Schema getSchema(String schemaName) { + Schema schema = null; + URL schemaUrl = this.getClass().getClassLoader().getResource( schemaName ); + if ( schemaUrl == null ) { + return schema; + } + + SchemaFactory sf = SchemaFactory.newInstance( javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI ); + try { + schema = sf.newSchema( schemaUrl ); + } + catch ( SAXException e ) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.WARNING, "Unable to create schema for " + schemaName + ": " + e.getMessage() + ); + } + return schema; + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/TypeUtils.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/TypeUtils.java new file mode 100644 index 0000000000..26a7f0d01e --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/TypeUtils.java @@ -0,0 +1,75 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen; + +import java.util.HashMap; +import java.util.Map; + +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.Element; + +/** + * Utility class. + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public class TypeUtils { + + private static final Map PRIMITIVES = new HashMap(); + static { + PRIMITIVES.put( "char", "Character" ); + + PRIMITIVES.put( "byte", "Byte" ); + PRIMITIVES.put( "short", "Short" ); + PRIMITIVES.put( "int", "Integer" ); + PRIMITIVES.put( "long", "Long" ); + + PRIMITIVES.put( "boolean", "Boolean" ); + + PRIMITIVES.put( "float", "Float" ); + PRIMITIVES.put( "double", "Double" ); + + } + + static public String toTypeString(TypeMirror type) { + if(type.getKind().isPrimitive()) { + return PRIMITIVES.get(type.toString()); + } + + return type.toString(); + } + + static public TypeElement getSuperclass(TypeElement element) { + final TypeMirror superClass = element.getSuperclass(); + //superclass of Object is of NoType which returns some other kind + String superclassDeclaration = ""; + if (superClass.getKind() == TypeKind.DECLARED ) { + //F..king Ch...t Have those people used their horrible APIs even once? + final Element superClassElement = ( ( DeclaredType ) superClass ).asElement(); + return ( TypeElement ) superClassElement; + } + else { + return null; + } + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttribute.java new file mode 100644 index 0000000000..c905410897 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttribute.java @@ -0,0 +1,74 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen.annotation; + +import org.hibernate.jpamodelgen.IMetaAttribute; + +import java.beans.Introspector; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public abstract class MetaAttribute implements IMetaAttribute { + + final protected Element element; + final protected MetaEntity parent; + final protected ProcessingEnvironment pe; + private final String type; + + public MetaAttribute(MetaEntity parent, Element element, String type) { + this.element = element; + this.parent = parent; + this.type = type; + this.pe = parent.pe; + } + + public String getDeclarationString() { + return "public static volatile " + parent.importType(getMetaType()) + "<" + parent.importType(parent.getQualifiedName()) + ", " + parent.importType(getTypeDeclaration()) + "> " + getPropertyName() + ";"; + } + + public String getPropertyName() { + if(element.getKind()==ElementKind.FIELD) { + return element.getSimpleName().toString(); + } else if (element.getKind()==ElementKind.METHOD) { + + String name = element.getSimpleName().toString(); + if(name.startsWith("get")) { + return pe.getElementUtils().getName(Introspector.decapitalize(name.substring("get".length()))).toString(); + } else if(name.startsWith("is")) { + return (pe.getElementUtils().getName(Introspector.decapitalize(name.substring("is".length())))).toString(); + } + return pe.getElementUtils().getName(Introspector.decapitalize(name)).toString(); + } else { + return pe.getElementUtils().getName(element.getSimpleName() + "/* " + element.getKind() + " */").toString(); + } + } + + abstract public String getMetaType(); + + public String getTypeDeclaration() { + return type; + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaCollection.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaCollection.java new file mode 100644 index 0000000000..e25633705b --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaCollection.java @@ -0,0 +1,46 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen.annotation; + +import org.hibernate.jpamodelgen.IMetaCollection; + +import javax.lang.model.element.Element; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public class MetaCollection extends MetaAttribute implements IMetaCollection { + + private String collectionType; + + + public MetaCollection(MetaEntity parent, Element element, String collectionType, String elementType) { + super(parent, element, elementType); + this.collectionType = collectionType; + } + + @Override + public String getMetaType() { + return collectionType; + } + + +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaEntity.java new file mode 100644 index 0000000000..2cd07df255 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaEntity.java @@ -0,0 +1,433 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen.annotation; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Name; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.ExecutableType; +import javax.lang.model.type.PrimitiveType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.SimpleTypeVisitor6; +import javax.persistence.EmbeddedId; +import javax.persistence.Id; +import javax.persistence.AccessType; +import javax.persistence.Entity; +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; +import javax.persistence.Embedded; +import javax.persistence.Embeddable; +import javax.persistence.Access; +import javax.persistence.ElementCollection; +import javax.tools.Diagnostic.Kind; +import javax.tools.Diagnostic; + +import org.hibernate.jpamodelgen.IMetaEntity; +import org.hibernate.jpamodelgen.IMetaAttribute; +import org.hibernate.jpamodelgen.ImportContext; +import org.hibernate.jpamodelgen.ImportContextImpl; +import org.hibernate.jpamodelgen.TypeUtils; +import org.hibernate.jpamodelgen.Context; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public class MetaEntity implements IMetaEntity { + + final TypeElement element; + final protected ProcessingEnvironment pe; + + final ImportContext importContext; + private Context context; + //used to propagate the access type of the root entity over to subclasses, superclasses and embeddable + private AccessType defaultAccessTypeForHierarchy; + private AccessType defaultAccessTypeForElement; + + public MetaEntity(ProcessingEnvironment pe, TypeElement element, Context context) { + this.element = element; + this.pe = pe; + importContext = new ImportContextImpl( getPackageName() ); + this.context = context; + } + + public MetaEntity(ProcessingEnvironment pe, TypeElement element, Context context, AccessType accessType) { + this(pe, element, context); + this.defaultAccessTypeForHierarchy = accessType; + } + + public String getSimpleName() { + return element.getSimpleName().toString(); + } + + public Element getOriginalElement() { + return element; + } + + public String getQualifiedName() { + return element.getQualifiedName().toString(); + } + + public String getPackageName() { + PackageElement packageOf = pe.getElementUtils().getPackageOf( element ); + return pe.getElementUtils().getName( packageOf.getQualifiedName() ).toString(); + } + + public List getMembers() { + List membersFound = new ArrayList(); + final AccessType elementAccessType = getAccessTypeForElement(); + + List fieldsOfClass = ElementFilter.fieldsIn( element.getEnclosedElements() ); + addPersistentMembers( membersFound, elementAccessType, fieldsOfClass, AccessType.FIELD ); + + List methodsOfClass = ElementFilter.methodsIn( element.getEnclosedElements() ); + addPersistentMembers( membersFound, elementAccessType, methodsOfClass, AccessType.PROPERTY ); + + //process superclasses + for(TypeElement superclass = TypeUtils.getSuperclass(element) ; + superclass != null ; + superclass = TypeUtils.getSuperclass( superclass ) ) { + if ( superclass.getAnnotation( Entity.class ) != null ) { + break; //will be handled or has been handled already + } + else if ( superclass.getAnnotation( MappedSuperclass.class ) != null ) { + //FIXME use the class defalut access type + context.processElement( superclass, defaultAccessTypeForHierarchy ); + } + } + + //this is valid to not have properties (ie subentities) +// if ( membersFound.size() == 0 ) { +// pe.getMessager().printMessage( Kind.WARNING, "No properties found on " + element, element ); +// } + return membersFound; + } + + private void addPersistentMembers( + List membersFound, + AccessType elementAccessType, + List membersOfClass, + AccessType membersKind) { + pe.getMessager() + .printMessage( Kind.NOTE, "Scanning " + membersOfClass.size() + " " + membersKind + " for " + element.toString() ); + AccessType explicitAccessType; + if (elementAccessType == membersKind) { + //all membersKind considered + explicitAccessType = null; + } + else { + //use membersKind only if marked with @Access(membersKind) + explicitAccessType = membersKind; + } + for ( Element memberOfClass : membersOfClass ) { + + MetaAttribute result = memberOfClass.asType().accept( new TypeVisitor( this, explicitAccessType ), + memberOfClass + ); + if ( result != null ) { + membersFound.add( result ); + } +//EBE not sure why? +// else { +// pe.getMessager().printMessage( Kind.WARNING, "Could not find valid info for JPA property", mymember ); +// } + } + } + + private AccessType getAccessTypeForElement() { + + //get local strategy + AccessType accessType = getAccessTypeForClass(element); + if (accessType == null) { + accessType = this.defaultAccessTypeForHierarchy; + } + if (accessType == null) { + //we dont' know + //if an enity go up + // + //superclasses alre always treated after their entities + //and their access type are discovered + //FIXME is it really true if only the superclass is changed + TypeElement superClass = element; + do { + superClass = TypeUtils.getSuperclass( superClass ); + if (superClass != null) { + if ( superClass.getAnnotation( Entity.class ) != null + || superClass.getAnnotation( MappedSuperclass.class ) != null ) { + //FIXME make it work for XML + AccessType superClassAccessType = getAccessTypeForClass(superClass); + //we've reach the root entity and resolved Ids + if ( superClassAccessType != null && defaultAccessTypeForHierarchy != null) { + break; //we've found it + } + } + else { + break; //neither @Entity nor @MappedSuperclass + } + } + } + while ( superClass != null ); + } + + if ( accessType == null ) { + accessType = AccessType.PROPERTY; //default to property + this.defaultAccessTypeForElement = accessType; + } + //this is a subclass so caching is OK + //this.defaultAccessTypeForHierarchy = accessType; + context.addAccessType( this.element, accessType ); + this.defaultAccessTypeForElement = accessType; + return accessType; + } + + private AccessType getAccessTypeForClass(TypeElement searchedElement) { + pe.getMessager().printMessage( Diagnostic.Kind.NOTE, "check class" + searchedElement ); + AccessType accessType = context.getAccessType( searchedElement ); + + if (defaultAccessTypeForHierarchy == null) { + this.defaultAccessTypeForHierarchy = context.getDefaultAccessTypeForHerarchy( searchedElement ); + } + if ( accessType != null ) { + pe.getMessager().printMessage( Diagnostic.Kind.NOTE, "Found in cache" + searchedElement + ":" + accessType ); + return accessType; + } + + /** + * when forcing access type, we can only override the defaultAccessTypeForHierarchy + * if we are the entity root (identified by having @Id or @EmbeddedId + */ + final Access accessAnn = searchedElement.getAnnotation( Access.class ); + AccessType forcedAccessType = accessAnn != null ? accessAnn.value() : null; + if ( forcedAccessType != null) { + pe.getMessager().printMessage( Diagnostic.Kind.NOTE, "access type " + searchedElement + ":" + forcedAccessType ); + context.addAccessType( searchedElement, forcedAccessType ); + } + + //continue nevertheless to check if we are root and if defaultAccessTypeForHierarchy + //should be overridden + if ( forcedAccessType == null || defaultAccessTypeForHierarchy == null) { + List myMembers = searchedElement.getEnclosedElements(); + for ( Element subElement : myMembers ) { + List entityAnnotations = + pe.getElementUtils().getAllAnnotationMirrors( subElement ); + + for ( Object entityAnnotation : entityAnnotations ) { + AnnotationMirror annotationMirror = ( AnnotationMirror ) entityAnnotation; + + final String annotationType = annotationMirror.getAnnotationType().toString(); + + //FIXME consider XML + if ( annotationType.equals( Id.class.getName() ) + || annotationType.equals( EmbeddedId.class.getName() ) ) { + pe.getMessager().printMessage( Diagnostic.Kind.NOTE, "Found id on" + searchedElement ); + final ElementKind kind = subElement.getKind(); + if ( kind == ElementKind.FIELD || kind == ElementKind.METHOD ) { + accessType = kind == ElementKind.FIELD ? AccessType.FIELD : AccessType.PROPERTY; + //FIXME enlever in niveau + if (defaultAccessTypeForHierarchy == null) { + this.defaultAccessTypeForHierarchy = context.getDefaultAccessTypeForHerarchy( searchedElement ); + //we've discovered the class hierarchy, let's cache it + if ( defaultAccessTypeForHierarchy == null ) { + this.defaultAccessTypeForHierarchy = accessType; + context.addAccessTypeForHierarchy( searchedElement, defaultAccessTypeForHierarchy ); + //FIXME should we add + //context.addAccessTypeForHierarchy( element, defaultAccessTypeForHierarchy ); + } + } + if ( forcedAccessType == null) { + context.addAccessType( searchedElement, accessType ); + pe.getMessager().printMessage( Diagnostic.Kind.NOTE, "access type " + searchedElement + ":" + accessType ); + return accessType; + } + else { + return forcedAccessType; + } + } + } + } + } + } + return forcedAccessType; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "MetaEntity" ); + sb.append( "{element=" ).append( element ); + sb.append( '}' ); + return sb.toString(); + } + + static Map COLLECTIONS = new HashMap(); + + static { + COLLECTIONS.put( "java.util.Collection", "javax.persistence.metamodel.CollectionAttribute" ); + COLLECTIONS.put( "java.util.Set", "javax.persistence.metamodel.SetAttribute" ); + COLLECTIONS.put( "java.util.List", "javax.persistence.metamodel.ListAttribute" ); + COLLECTIONS.put( "java.util.Map", "javax.persistence.metamodel.MapAttribute" ); + } + + class TypeVisitor extends SimpleTypeVisitor6 { + + MetaEntity parent; + //if null, process all members as implicit + //if not null, only process members marked as @Access(explicitAccessType) + private AccessType explicitAccessType; + + TypeVisitor(MetaEntity parent, AccessType explicitAccessType) { + this.parent = parent; + this.explicitAccessType = explicitAccessType; + } + + @Override + protected MetaAttribute defaultAction(TypeMirror e, Element p) { + return super.defaultAction( e, p ); + } + + @Override + public MetaAttribute visitPrimitive(PrimitiveType t, Element element) { + if ( isPersistent( element ) ) { + return new MetaSingleAttribute( parent, element, TypeUtils.toTypeString( t ) ); + } + else { + return null; + } + } + + private boolean isPersistent(Element element) { + //FIXME consider XML + boolean correctAccessType = false; + if (this.explicitAccessType == null) { + correctAccessType = true; + } + else { + final Access accessAnn = element.getAnnotation( Access.class ); + if ( accessAnn != null && explicitAccessType.equals( accessAnn.value() ) ) { + correctAccessType = true; + } + } + return correctAccessType + && element.getAnnotation( Transient.class ) == null + && !element.getModifiers().contains( Modifier.TRANSIENT ) + && !element.getModifiers().contains( Modifier.STATIC ); + + } + + + @Override + public MetaAttribute visitDeclared(DeclaredType t, Element element) { + //FIXME consider XML + if ( isPersistent( element ) ) { + TypeElement returnedElement = ( TypeElement ) pe.getTypeUtils().asElement( t ); + String collection = COLLECTIONS.get( returnedElement.getQualifiedName().toString() ); // WARNING: .toString() is necessary here since Name equals does not compare to String + + if ( collection != null ) { + //collection of element + if ( element.getAnnotation( ElementCollection.class ) != null ) { + final TypeMirror collectionType = t.getTypeArguments().get( 0 ); + final TypeElement collectionElement = ( TypeElement ) pe.getTypeUtils().asElement( collectionType ); + this.parent.context.processElement( collectionElement, + this.parent.defaultAccessTypeForElement ); + } + if ( collection.equals( "javax.persistence.metamodel.MapAttribute" ) ) { + return new MetaMap( parent, element, collection, getKeyType( t ), getElementType( t ) ); + } + else { + return new MetaCollection( parent, element, collection, getElementType( t ) ); + } + } + else { + //FIXME Consider XML + if ( element.getAnnotation( Embedded.class ) != null + || returnedElement.getAnnotation( Embeddable.class ) != null ) { + this.parent.context.processElement( returnedElement, + this.parent.defaultAccessTypeForElement ); + } + return new MetaSingleAttribute( parent, element, returnedElement.getQualifiedName().toString() ); + } + } + else { + return null; + } + } + + + @Override + public MetaAttribute visitExecutable(ExecutableType t, Element p) { + String string = p.getSimpleName().toString(); + + // TODO: implement proper property get/is/boolean detection + if ( string.startsWith( "get" ) || string.startsWith( "is" ) ) { + TypeMirror returnType = t.getReturnType(); + + return returnType.accept( this, p ); + } + else { + return null; + } + } + } + + public String generateImports() { + return importContext.generateImports(); + } + + public String importType(String fqcn) { + return importContext.importType( fqcn ); + } + + public String staticImport(String fqcn, String member) { + return importContext.staticImport( fqcn, member ); + } + + public String importType(Name qualifiedName) { + return importType( qualifiedName.toString() ); + } + + public TypeElement getTypeElement() { + return element; + } + + private String getKeyType(DeclaredType t) { + return t.getTypeArguments().get( 0 ).toString(); + } + + + private String getElementType(DeclaredType declaredType) { + if ( declaredType.getTypeArguments().size() == 1 ) { + return declaredType.getTypeArguments().get( 0 ).toString(); + } + else { + return declaredType.getTypeArguments().get( 1 ).toString(); + } + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaMap.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaMap.java new file mode 100644 index 0000000000..106e926146 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaMap.java @@ -0,0 +1,42 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen.annotation; + +import javax.lang.model.element.Element; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public class MetaMap extends MetaCollection { + + private final String keyType; + + public MetaMap(MetaEntity parent, Element element, String collectionType, + String keyType, String elementType) { + super(parent, element, collectionType, elementType); + this.keyType = keyType; + } + + public String getDeclarationString() { + return "public static volatile " + parent.importType(getMetaType()) + "<" + parent.importType(parent.getQualifiedName()) + ", " + parent.importType(keyType) + ", " + parent.importType(getTypeDeclaration()) + "> " + getPropertyName() + ";"; + } + +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaSingleAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaSingleAttribute.java new file mode 100644 index 0000000000..2507ef5bba --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaSingleAttribute.java @@ -0,0 +1,41 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen.annotation; + +import org.hibernate.jpamodelgen.IMetaSingleAttribute; + +import javax.lang.model.element.Element; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public class MetaSingleAttribute extends MetaAttribute implements IMetaSingleAttribute { + + public MetaSingleAttribute(MetaEntity parent, Element element, String type) { + super(parent, element, type); + } + + @Override + public String getMetaType() { + return "javax.persistence.metamodel.SingularAttribute"; + } + +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaAttribute.java new file mode 100644 index 0000000000..6ed7322422 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaAttribute.java @@ -0,0 +1,56 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package org.hibernate.jpamodelgen.xml; + +import org.hibernate.jpamodelgen.IMetaAttribute; + +/** + * @author Hardy Ferentschik + */ +public abstract class XmlMetaAttribute implements IMetaAttribute { + + private XmlMetaEntity parentEntity; + + private String propertyName; + + private String type; + + XmlMetaAttribute(XmlMetaEntity parent, String propertyName, String type) { + this.parentEntity = parent; + this.propertyName = propertyName; + this.type = type; + } + + + @Override + public String getDeclarationString() { + return "public static volatile " + parentEntity.importType(getMetaType()) + "<" + parentEntity.importType(parentEntity.getQualifiedName()) + ", " + parentEntity.importType(getTypeDeclaration()) + "> " + getPropertyName() + ";"; + } + + public String getPropertyName() { + return propertyName; + } + + public String getTypeDeclaration() { + return type; + } + + @Override + abstract public String getMetaType(); +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaCollection.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaCollection.java new file mode 100644 index 0000000000..18c2a216f9 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaCollection.java @@ -0,0 +1,38 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen.xml; + +import org.hibernate.jpamodelgen.IMetaCollection; + +/** + * @author Hardy Ferentschik + */ +public class XmlMetaCollection extends XmlMetaAttribute implements IMetaCollection { + + String collectionType; + + public XmlMetaCollection(XmlMetaEntity parent, String propertyName, String type, String collectionType) { + super(parent, propertyName, type); + this.collectionType = collectionType; + } + + @Override + public String getMetaType() { + return collectionType; + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java new file mode 100644 index 0000000000..5c86fd70d7 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java @@ -0,0 +1,255 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen.xml; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.lang.model.element.Element; +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; + +import org.hibernate.jpamodelgen.IMetaAttribute; +import org.hibernate.jpamodelgen.ImportContextImpl; +import org.hibernate.jpamodelgen.IMetaEntity; +import org.hibernate.jpamodelgen.ImportContext; +import org.hibernate.jpamodelgen.xml.jaxb.Attributes; +import org.hibernate.jpamodelgen.xml.jaxb.Basic; +import org.hibernate.jpamodelgen.xml.jaxb.ElementCollection; +import org.hibernate.jpamodelgen.xml.jaxb.Embeddable; +import org.hibernate.jpamodelgen.xml.jaxb.EmbeddableAttributes; +import org.hibernate.jpamodelgen.xml.jaxb.Entity; +import org.hibernate.jpamodelgen.xml.jaxb.Id; +import org.hibernate.jpamodelgen.xml.jaxb.ManyToOne; +import org.hibernate.jpamodelgen.xml.jaxb.MappedSuperclass; +import org.hibernate.jpamodelgen.xml.jaxb.OneToMany; +import org.hibernate.jpamodelgen.xml.jaxb.OneToOne; + +/** + * @author Hardy Ferentschik + */ +public class XmlMetaEntity implements IMetaEntity { + + static Map COLLECTIONS = new HashMap(); + + static { + COLLECTIONS.put( "java.util.Collection", "javax.persistence.metamodel.CollectionAttribute" ); + COLLECTIONS.put( "java.util.Set", "javax.persistence.metamodel.SetAttribute" ); + COLLECTIONS.put( "java.util.List", "javax.persistence.metamodel.ListAttribute" ); + COLLECTIONS.put( "java.util.Map", "javax.persistence.metamodel.MapAttribute" ); + } + + final private String clazzName; + + final private String packageName; + + final private ImportContext importContext; + + final private List members = new ArrayList(); + + private TypeElement element; + + public XmlMetaEntity(Entity ormEntity, String packageName, TypeElement element) { + this.clazzName = ormEntity.getClazz(); + this.packageName = packageName; + importContext = new ImportContextImpl( getPackageName() ); + this.element = element; + Attributes attributes = ormEntity.getAttributes(); + + parseAttributes( attributes ); + } + + public XmlMetaEntity(MappedSuperclass mappedSuperclass, String packageName, TypeElement element) { + this.clazzName = mappedSuperclass.getClazz(); + this.packageName = packageName; + importContext = new ImportContextImpl( getPackageName() ); + this.element = element; + Attributes attributes = mappedSuperclass.getAttributes(); + + parseAttributes( attributes ); + } + + public XmlMetaEntity(Embeddable embeddable, String packageName, TypeElement element) { + this.clazzName = embeddable.getClazz(); + this.packageName = packageName; + importContext = new ImportContextImpl( getPackageName() ); + this.element = element; + EmbeddableAttributes attributes = embeddable.getAttributes(); + + XmlMetaSingleAttribute attribute; + for ( Basic basic : attributes.getBasic() ) { + attribute = new XmlMetaSingleAttribute( this, basic.getName(), getType( basic.getName() ) ); + members.add( attribute ); + } + + for ( ManyToOne manyToOne : attributes.getManyToOne() ) { + attribute = new XmlMetaSingleAttribute( this, manyToOne.getName(), getType( manyToOne.getName() ) ); + members.add( attribute ); + } + + for ( OneToOne oneToOne : attributes.getOneToOne() ) { + attribute = new XmlMetaSingleAttribute( this, oneToOne.getName(), getType( oneToOne.getName() ) ); + members.add( attribute ); + } + + XmlMetaCollection metaCollection; + for ( OneToMany oneToMany : attributes.getOneToMany() ) { + String[] types = getCollectionType( oneToMany.getName() ); + metaCollection = new XmlMetaCollection( this, oneToMany.getName(), types[0], types[1] ); + members.add( metaCollection ); + } + + for ( ElementCollection collection : attributes.getElementCollection() ) { + String[] types = getCollectionType( collection.getName() ); + metaCollection = new XmlMetaCollection( this, collection.getName(), types[0], types[1] ); + members.add( metaCollection ); + } + } + + public String getSimpleName() { + return clazzName; + } + + public String getQualifiedName() { + return packageName + "." + getSimpleName(); + } + + public String getPackageName() { + return packageName; + } + + public List getMembers() { + return members; + } + + public String generateImports() { + return importContext.generateImports(); + } + + public String importType(String fqcn) { + return importContext.importType( fqcn ); + } + + public String staticImport(String fqcn, String member) { + return importContext.staticImport( fqcn, member ); + } + + public String importType(Name qualifiedName) { + return importType( qualifiedName.toString() ); + } + + public TypeElement getTypeElement() { + return element; + } + + private String[] getCollectionType(String propertyName) { + String types[] = new String[2]; + for ( Element elem : element.getEnclosedElements() ) { + if ( elem.getSimpleName().toString().equals( propertyName ) ) { + DeclaredType type = ( ( DeclaredType ) elem.asType() ); + types[0] = type.getTypeArguments().get( 0 ).toString(); + types[1] = COLLECTIONS.get( type.asElement().toString() ); + } + } + return types; + } + + private String getType(String propertyName) { + String typeName = null; + for ( Element elem : element.getEnclosedElements() ) { + if ( elem.getSimpleName().toString().equals( propertyName ) ) { + switch ( elem.asType().getKind() ) { + case INT: { + typeName = "java.lang.Integer"; + break; + } + case LONG: { + typeName = "java.lang.Long"; + break; + } + case BOOLEAN: { + typeName = "java.lang.Boolean"; + break; + } + case DECLARED: { + typeName = elem.asType().toString(); + break; + } + case TYPEVAR: { + typeName = elem.asType().toString(); + break; + } + } + break; + } + } + return typeName; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "XmlMetaEntity" ); + sb.append( "{type=" ).append( element ); + sb.append( '}' ); + return sb.toString(); + } + + private void parseAttributes(Attributes attributes) { + XmlMetaSingleAttribute attribute; + + if ( !attributes.getId().isEmpty() ) { + // TODO what do we do if there are more than one id nodes? + Id id = attributes.getId().get( 0 ); + attribute = new XmlMetaSingleAttribute( + this, id.getName(), getType( id.getName() ) + ); + members.add( attribute ); + } + + for ( Basic basic : attributes.getBasic() ) { + attribute = new XmlMetaSingleAttribute( this, basic.getName(), getType( basic.getName() ) ); + members.add( attribute ); + } + + for ( ManyToOne manyToOne : attributes.getManyToOne() ) { + attribute = new XmlMetaSingleAttribute( this, manyToOne.getName(), getType( manyToOne.getName() ) ); + members.add( attribute ); + } + + for ( OneToOne oneToOne : attributes.getOneToOne() ) { + attribute = new XmlMetaSingleAttribute( this, oneToOne.getName(), getType( oneToOne.getName() ) ); + members.add( attribute ); + } + + XmlMetaCollection metaCollection; + for ( OneToMany oneToMany : attributes.getOneToMany() ) { + String[] types = getCollectionType( oneToMany.getName() ); + metaCollection = new XmlMetaCollection( this, oneToMany.getName(), types[0], types[1] ); + members.add( metaCollection ); + } + + for ( ElementCollection collection : attributes.getElementCollection() ) { + String[] types = getCollectionType( collection.getName() ); + metaCollection = new XmlMetaCollection( this, collection.getName(), types[0], types[1] ); + members.add( metaCollection ); + } + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaSingleAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaSingleAttribute.java new file mode 100644 index 0000000000..654639f82a --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaSingleAttribute.java @@ -0,0 +1,35 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.jpamodelgen.xml; + +import org.hibernate.jpamodelgen.IMetaSingleAttribute; + +/** + * @author Hardy Ferentschik + */ +public class XmlMetaSingleAttribute extends XmlMetaAttribute implements IMetaSingleAttribute { + + public XmlMetaSingleAttribute(XmlMetaEntity parent, String propertyName, String type) { + super(parent, propertyName, type); + } + + @Override + public String getMetaType() { + return "javax.persistence.metamodel.SingularAttribute"; + } +} diff --git a/tooling/metamodel-generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/tooling/metamodel-generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 0000000000..b5af4a8d94 --- /dev/null +++ b/tooling/metamodel-generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor \ No newline at end of file diff --git a/tooling/metamodel-generator/src/main/xsd/orm_2_0.xsd b/tooling/metamodel-generator/src/main/xsd/orm_2_0.xsd new file mode 100644 index 0000000000..7347b2ff60 --- /dev/null +++ b/tooling/metamodel-generator/src/main/xsd/orm_2_0.xsd @@ -0,0 +1,1504 @@ + + + + + + @(#)orm_2_0.xsd 2.0 August 27 2008 + + + + + +... + +]]> + + + + + + + + + + + + + + The entity-mappings element is the root element of + an mapping file. It contains the following four + types of elements: 1. The persistence-unit-metadata + element contains metadata for the entire persistence + unit. It is undefined if this element occurs in + multiple mapping files within the same persistence + unit. 2. The package, schema, catalog and access + elements apply to all of the entity, + mapped-superclass and embeddable elements defined in + the same file in which they occur. 3. The + sequence-generator, table-generator, named-query, + named-native-query and sql-result-set-mapping + elements are global to the persistence unit. It is + undefined to have more than one sequence-generator + or table-generator of the same name in the same or + different mapping files in a persistence unit. It is + also undefined to have more than one named-query, + named-native-query, or result-set-mapping of the + same name in the same or different mapping files in + a persistence unit. 4. The entity, mapped-superclass + and embeddable elements each define the mapping + information for a managed persistent class. The + mapping information contained in these elements may + be complete or it may be partial. + + + + + + + + + + + + + + + + + + + + + + + + + + Metadata that applies to the persistence unit and not + just to the mapping file in which it is contained. If + the xml-mapping-metadata-complete element is specified, + the complete set of mapping metadata for the persistence + unit is contained in the XML mapping files for the + persistence unit. + + + + + + + + + + + + + These defaults are applied to the persistence unit as a + whole unless they are overridden by local annotation or + XML element settings. schema - Used as the schema for + all tables, secondary tables, collection tables, + sequence generators, and table generators that apply to + the persistence unit catalog - Used as the catalog for + all tables, secondary tables, collection tables, + sequence generators, and table generators that apply to + the persistence unit access - Used as the access type + for all managed classes in the persistence unit + cascade-persist - Adds cascade-persist to the set of + cascade options in all entity relationships of the + persistence unit entity-listeners - List of default + entity listeners to be invoked on each entity in the + persistence unit. + + + + + + + + + + + + + + + + Defines the settings and mappings for an entity. Is + allowed to be sparsely populated and used in conjunction + with the annotations. Alternatively, the + metadata-complete attribute can be used to indicate that + no annotations on the entity class (and its fields or + properties) are to be processed. If this is the case + then the defaulting rules for the entity and its + subelements will be recursively applied. @Target(TYPE) + @Retention(RUNTIME) public @interface Entity { String + name() default ""; } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element determines how the persistence provider + accesses the state of an entity or embedded object. + + + + + + + + + + + + @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) + public @interface AssociationOverride { String name(); + JoinColumn[] joinColumns() default{}; JoinTable + joinTable() default @JoinTable; } + + + + + + + + + + + + + + @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) + public @interface AttributeOverride { String name(); + Column column(); } + + + + + + + + + + + + + This element contains the entity field or property + mappings. It may be sparsely populated to include only a + subset of the fields or properties. If metadata-complete + for the entity is true then the remainder of the + attributes will be defaulted according to the default + rules. + + + + + + + + + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface Basic { FetchType fetch() default EAGER; + boolean optional() default true; } + + + + + + + + + + + + + + + + + + + + public enum CascadeType { ALL, PERSIST, MERGE, REMOVE, + REFRESH}; + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface CollectionTable { String name() default ""; + String catalog() default ""; String schema() default ""; + JoinColumn[] joinColumns() default {}; + UniqueConstraint[] uniqueConstraints() default {}; } + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface Column { String name() default ""; boolean + unique() default false; boolean nullable() default true; + boolean insertable() default true; boolean updatable() + default true; String columnDefinition() default ""; + String table() default ""; int length() default 255; int + precision() default 0; // decimal precision int scale() + default 0; // decimal scale } + + + + + + + + + + + + + + + + + + @Target({}) @Retention(RUNTIME) public @interface + ColumnResult { String name(); } + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + DiscriminatorColumn { String name() default "DTYPE"; + DiscriminatorType discriminatorType() default STRING; + String columnDefinition() default ""; int length() + default 31; } + + + + + + + + + + + + public enum DiscriminatorType { STRING, CHAR, INTEGER }; + + + + + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + DiscriminatorValue { String value(); } + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface ElementCollection { Class targetClass() + default void.class; FetchType fetch() default LAZY; } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines the settings and mappings for embeddable + objects. Is allowed to be sparsely populated and used in + conjunction with the annotations. Alternatively, the + metadata-complete attribute can be used to indicate that + no annotations are to be processed in the class. If this + is the case then the defaulting rules will be + recursively applied. @Target({TYPE}) @Retention(RUNTIME) + public @interface Embeddable {} + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface Embedded {} + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface EmbeddedId {} + + + + + + + + + + + + + Defines an entity listener to be invoked at lifecycle + events for the entities that list this listener. + + + + + + + + + + + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + EntityListeners { Class[] value(); } + + + + + + + + + + + @Target({}) @Retention(RUNTIME) public @interface + EntityResult { Class entityClass(); FieldResult[] + fields() default {}; String discriminatorColumn() + default ""; } + + + + + + + + + + + + + public enum EnumType { ORDINAL, STRING } + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface Enumerated { EnumType value() default + ORDINAL; } + + + + + + + + + public enum FetchType { LAZY, EAGER }; + + + + + + + + + + + + @Target({}) @Retention(RUNTIME) public @interface + FieldResult { String name(); String column(); } + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface GeneratedValue { GenerationType strategy() + default AUTO; String generator() default ""; } + + + + + + + + + + public enum GenerationType { TABLE, SEQUENCE, IDENTITY, + AUTO }; + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface Id {} + + + + + + + + + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + IdClass { Class value(); } + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + Inheritance { InheritanceType strategy() default + SINGLE_TABLE; } + + + + + + + + + public enum InheritanceType { SINGLE_TABLE, JOINED, + TABLE_PER_CLASS}; + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface JoinColumn { String name() default ""; String + referencedColumnName() default ""; boolean unique() + default false; boolean nullable() default true; boolean + insertable() default true; boolean updatable() default + true; String columnDefinition() default ""; String + table() default ""; } + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface JoinTable { String name() default ""; String + catalog() default ""; String schema() default ""; + JoinColumn[] joinColumns() default {}; JoinColumn[] + inverseJoinColumns() default {}; UniqueConstraint[] + uniqueConstraints() default {}; } + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface Lob {} + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface ManyToMany { Class targetEntity() default + void.class; CascadeType[] cascade() default {}; + FetchType fetch() default LAZY; String mappedBy() + default ""; } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface ManyToOne { Class targetEntity() default + void.class; CascadeType[] cascade() default {}; + FetchType fetch() default EAGER; boolean optional() + default true; } + + + + + + + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface MapKey { String name() default ""; } + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface MapKeyClass { Class value(); } + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface MapKeyColumn { String name() default ""; + boolean unique() default false; boolean nullable() + default false; boolean insertable() default true; + boolean updatable() default true; String + columnDefinition() default ""; String table() default + ""; int length() default 255; int precision() default 0; + // decimal precision int scale() default 0; // decimal + scale } + + + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface MapKeyJoinColumn { String name() default ""; + String referencedColumnName() default ""; boolean + unique() default false; boolean nullable() default + false; boolean insertable() default true; boolean + updatable() default true; String columnDefinition() + default ""; String table() default ""; } + + + + + + + + + + + + + + + + Defines the settings and mappings for a mapped + superclass. Is allowed to be sparsely populated and used + in conjunction with the annotations. Alternatively, the + metadata-complete attribute can be used to indicate that + no annotations are to be processed If this is the case + then the defaulting rules will be recursively applied. + @Target(TYPE) @Retention(RUNTIME) public @interface + MappedSuperclass{} + + + + + + + + + + + + + + + + + + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + NamedNativeQuery { String name(); String query(); + QueryHint[] hints() default {}; Class resultClass() + default void.class; String resultSetMapping() default + ""; //named SqlResultSetMapping } + + + + + + + + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + NamedQuery { String name(); String query(); QueryHint[] + hints() default {}; } + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface OneToMany { Class targetEntity() default + void.class; CascadeType[] cascade() default {}; + FetchType fetch() default LAZY; String mappedBy() + default ""; } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface OneToOne { Class targetEntity() default + void.class; CascadeType[] cascade() default {}; + FetchType fetch() default EAGER; boolean optional() + default true; String mappedBy() default ""; boolean + orphanRemoval() default false; } + + + + + + + + + + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface OrderBy { String value() default ""; } + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface OrderColumn { String name() default ""; + boolean nullable() default true; boolean insertable() + default true; boolean updatable() default true; String + columnDefinition() default ""; boolean contiguous() + default true; int base() default 0; String table() + default ""; } + + + + + + + + + + + + + + + + @Target({METHOD}) @Retention(RUNTIME) public @interface + PostLoad {} + + + + + + + + + + + + @Target({METHOD}) @Retention(RUNTIME) public @interface + PostPersist {} + + + + + + + + + + + + @Target({METHOD}) @Retention(RUNTIME) public @interface + PostRemove {} + + + + + + + + + + + + @Target({METHOD}) @Retention(RUNTIME) public @interface + PostUpdate {} + + + + + + + + + + + + @Target({METHOD}) @Retention(RUNTIME) public @interface + PrePersist {} + + + + + + + + + + + + @Target({METHOD}) @Retention(RUNTIME) public @interface + PreRemove {} + + + + + + + + + + + + @Target({METHOD}) @Retention(RUNTIME) public @interface + PreUpdate {} + + + + + + + + + + + + @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) + public @interface PrimaryKeyJoinColumn { String name() + default ""; String referencedColumnName() default ""; + String columnDefinition() default ""; } + + + + + + + + + + + @Target({}) @Retention(RUNTIME) public @interface + QueryHint { String name(); String value(); } + + + + + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + SecondaryTable { String name(); String catalog() default + ""; String schema() default ""; PrimaryKeyJoinColumn[] + pkJoinColumns() default {}; UniqueConstraint[] + uniqueConstraints() default {}; } + + + + + + + + + + + + + + + @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) + public @interface SequenceGenerator { String name(); + String sequenceName() default ""; String catalog() + default ""; String schema() default ""; int + initialValue() default 1; int allocationSize() default + 50; } + + + + + + + + + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + SqlResultSetMapping { String name(); EntityResult[] + entities() default {}; ColumnResult[] columns() default + {}; } + + + + + + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) public @interface + Table { String name() default ""; String catalog() + default ""; String schema() default ""; + UniqueConstraint[] uniqueConstraints() default {}; } + + + + + + + + + + + + + + @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) + public @interface TableGenerator { String name(); String + table() default ""; String catalog() default ""; String + schema() default ""; String pkColumnName() default ""; + String valueColumnName() default ""; String + pkColumnValue() default ""; int initialValue() default + 0; int allocationSize() default 50; UniqueConstraint[] + uniqueConstraints() default {}; } + + + + + + + + + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface Temporal { TemporalType value(); } + + + + + + + + + public enum TemporalType { DATE, // java.sql.Date TIME, + // java.sql.Time TIMESTAMP // java.sql.Timestamp } + + + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface Transient {} + + + + + + + + + @Target({}) @Retention(RUNTIME) public @interface + UniqueConstraint { String[] columnNames(); } + + + + + + + + + + + @Target({METHOD, FIELD}) @Retention(RUNTIME) public + @interface Version {} + + + + + + + + + + \ No newline at end of file diff --git a/tooling/metamodel-generator/src/main/xsd/persistence_2_0.xsd b/tooling/metamodel-generator/src/main/xsd/persistence_2_0.xsd new file mode 100644 index 0000000000..c593a9820d --- /dev/null +++ b/tooling/metamodel-generator/src/main/xsd/persistence_2_0.xsd @@ -0,0 +1,247 @@ + + + + + + @(#)persistence_2_0.xsd 1.0 August 27 2008 + + + + +... + +]]> + + + + + + + + + + + + + + + Configuration of a persistence unit. + + + + + + + + Description of this persistence unit. + + + + + + + + Provider class that supplies EntityManagers for this + persistence unit. + + + + + + + + The container-specific name of the JTA datasource to use. + + + + + + + + The container-specific name of a non-JTA datasource to use. + + + + + + + File containing mapping information. Loaded as a resource + by the persistence provider. + + + + + + + + Jar file that should be scanned for entities. + Not applicable to Java SE persistence units. + + + + + + + + Class to scan for annotations. It should be annotated + with either @Entity, @Embeddable or @MappedSuperclass. + + + + + + + + When set to true then only listed classes and jars will + be scanned for persistent classes, otherwise the enclosing + jar or directory will also be scanned. Not applicable to + Java SE persistence units. + + + + + + + + Defines whether caching is enabled for the + persistence unit if caching is supported by the + persistence provider. When set to ALL, all entities + will be cached. When set to NONE, no entities will + be cached. When set to ENABLE_SELECTIVE, only entities + specified as cacheable will be cached. When set toDISABLE_SELECTIVE, entities specified as not cacheable + will not be cached. + + + + + + + + Specifies the validation mode to be used for the + persistence unit. + + + + + + + + A list of vendor-specific properties. + + + + + + + + A name-value pair. + + + + + + + + + + + + + + + + Name used in code to reference this persistence unit. + + + + + + + Type of transactions used by EntityManagers from this + persistence unit. + + + + + + + + + + + + + + public enum TransactionType { JTA, RESOURCE_LOCAL }; + + + + + + + + + + + + public enum CachingType { ALL, NONE, ENABLE_SELECTIVE, + DISABLE_SELECTIVE}; + + + + + + + + + + + + + public enum ValidationMode { AUTO, CALLBACK, NONE}; + + + + + + + + + \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/model/Address.java b/tooling/metamodel-generator/src/test/java/model/Address.java new file mode 100644 index 0000000000..0dc36351f8 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Address.java @@ -0,0 +1,71 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import java.util.Set; +import javax.persistence.Embeddable; +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.ElementCollection; +import javax.persistence.CollectionTable; + +/** + * @author Emmanuel Bernard + */ +@Embeddable +@Access(javax.persistence.AccessType.PROPERTY) +public class Address { + private String street1; + private String city; + private Country country; + private Set inhabitants; + + public String getStreet1() { + return street1; + } + + public void setStreet1(String street1) { + this.street1 = street1; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public Country getCountry() { + return country; + } + + public void setCountry(Country country) { + this.country = country; + } + + @ElementCollection + @CollectionTable(name = "Add_Inh") + public Set getInhabitants() { + return inhabitants; + } + + public void setInhabitants(Set inhabitants) { + this.inhabitants = inhabitants; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Area.java b/tooling/metamodel-generator/src/test/java/model/Area.java new file mode 100644 index 0000000000..633afa4ef8 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Area.java @@ -0,0 +1,59 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.MappedSuperclass; + +/** + * @author Emmanuel Bernard + */ +@MappedSuperclass +public class Area { + private int length; + private int width; + private int height; + + //should not be persistent + public int getVolume() { + return length*width*height; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Building.java b/tooling/metamodel-generator/src/test/java/model/Building.java new file mode 100644 index 0000000000..ea1d153998 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Building.java @@ -0,0 +1,36 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.MappedSuperclass; + +/** + * @author Emmanuel Bernard + */ +@MappedSuperclass +public class Building extends Area { + private Address address; + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Country.java b/tooling/metamodel-generator/src/test/java/model/Country.java new file mode 100644 index 0000000000..b38c8b035b --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Country.java @@ -0,0 +1,46 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.Embeddable; + +/** + * @author Emmanuel Bernard + */ +@Embeddable +public class Country { + String name; + String iso2Code; + String nonPersistent; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIso2Code() { + return iso2Code; + } + + public void setIso2Code(String iso2Code) { + this.iso2Code = iso2Code; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Customer.java b/tooling/metamodel-generator/src/test/java/model/Customer.java new file mode 100644 index 0000000000..d05fd6a284 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Customer.java @@ -0,0 +1,45 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.OneToMany; +import javax.persistence.Access; +import javax.persistence.AccessType; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class Customer extends User { + private Set orders; + private String nonPersistent; + + @Access(AccessType.FIELD) + boolean goodPayer; + + public Set getOrders() { + return orders; + } + + @OneToMany + public void setOrders(Set orders) { + this.orders = orders; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Detail.java b/tooling/metamodel-generator/src/test/java/model/Detail.java new file mode 100644 index 0000000000..b9480d6027 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Detail.java @@ -0,0 +1,55 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.Embeddable; + +/** + * @author Emmanuel Bernard + */ +@Embeddable +public class Detail { + Integer length; + Integer width; + Integer height; + Integer nonPersistent; + + public Integer getLength() { + return length; + } + + public void setLength(Integer length) { + this.length = length; + } + + public Integer getWidth() { + return width; + } + + public void setWidth(Integer width) { + this.width = width; + } + + public Integer getHeight() { + return height; + } + + public void setHeight(Integer height) { + this.height = height; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Hominidae.java b/tooling/metamodel-generator/src/test/java/model/Hominidae.java new file mode 100644 index 0000000000..7b7812c5e8 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Hominidae.java @@ -0,0 +1,43 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.Entity; +import javax.persistence.Access; +import javax.persistence.AccessType; + +/** + * @author Emmanuel Bernard + */ +@Entity +@Access(javax.persistence.AccessType.FIELD) +public class Hominidae extends Mammals { + private int intelligence; + + public int getIntelligence() { + return intelligence; + } + + public void setIntelligence(int intelligence) { + this.intelligence = intelligence; + } + + public int getNonPersistent() { + return 0; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/House.java b/tooling/metamodel-generator/src/test/java/model/House.java new file mode 100644 index 0000000000..c00fe85755 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/House.java @@ -0,0 +1,38 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.Id; +import javax.persistence.Entity; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class House extends Building { + @Id + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Human.java b/tooling/metamodel-generator/src/test/java/model/Human.java new file mode 100644 index 0000000000..2d486f2167 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Human.java @@ -0,0 +1,37 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.Entity; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class Human extends Hominidae { + private int nonPersistent; + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Inhabitant.java b/tooling/metamodel-generator/src/test/java/model/Inhabitant.java new file mode 100644 index 0000000000..a4030bde23 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Inhabitant.java @@ -0,0 +1,43 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import java.util.Set; +import javax.persistence.Embeddable; +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.ElementCollection; + +/** + * @author Emmanuel Bernard + */ +@Embeddable +@Access(javax.persistence.AccessType.FIELD) +public class Inhabitant { + private String name; + @ElementCollection + private Set pets; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Item.java b/tooling/metamodel-generator/src/test/java/model/Item.java new file mode 100644 index 0000000000..d7b33baa6a --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Item.java @@ -0,0 +1,94 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import java.util.Map; +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +@Entity +public class Item { + + long _id; + + int _quantity; + + Product _product; + + Order _order; + + Detail detail; + + @Id + public long getId() { + return _id; + } + + public void setId(long id) { + this._id = id; + } + + public int getQuantity() { + return _quantity; + } + + public void setQuantity(int quantity) { + this._quantity = quantity; + } + + @ManyToOne + public Product getProduct() { + return _product; + } + + public void setProduct(Product product) { + this._product = product; + } + + @ManyToOne + public Order getOrder() { + return _order; + } + + public void setOrder(Order order) { + this._order = order; + } + + @OneToMany + public Map getNamedOrders() { + return null; + } + + public Detail getDetail() { + return detail; + } + + public void setDetail(Detail detail) { + this.detail = detail; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/LivingBeing.java b/tooling/metamodel-generator/src/test/java/model/LivingBeing.java new file mode 100644 index 0000000000..3d30b85a2a --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/LivingBeing.java @@ -0,0 +1,43 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.MappedSuperclass; +import javax.persistence.Access; +import javax.persistence.AccessType; + +/** + * @author Emmanuel Bernard + */ +@MappedSuperclass +@Access(javax.persistence.AccessType.FIELD) +public class LivingBeing { + boolean isReallyAlive; + + public boolean isReallyAlive() { + return isReallyAlive; + } + + public void setReallyAlive(boolean reallyAlive) { + isReallyAlive = reallyAlive; + } + + public int nonPersistent() { + return 0; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Mammals.java b/tooling/metamodel-generator/src/test/java/model/Mammals.java new file mode 100644 index 0000000000..0101dc7a2b --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Mammals.java @@ -0,0 +1,47 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class Mammals extends LivingBeing { + private String id; + private String nbrOfMammals; + + @Id + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getNbrOfMammals() { + return nbrOfMammals; + } + + public void setNbrOfMammals(String nbrOfMammals) { + this.nbrOfMammals = nbrOfMammals; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Order.java b/tooling/metamodel-generator/src/test/java/model/Order.java new file mode 100644 index 0000000000..51de07bd8a --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Order.java @@ -0,0 +1,47 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +//@Entity +public class Order { + + //@Id + long id; + + //@OneToMany + Set items; + + boolean filled; + Date date; + + //@OneToMany + List notes; + + //@ManyToOne + Shop shop; +} diff --git a/tooling/metamodel-generator/src/test/java/model/Pet.java b/tooling/metamodel-generator/src/test/java/model/Pet.java new file mode 100644 index 0000000000..3ad0ef44f2 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Pet.java @@ -0,0 +1,40 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.Embeddable; + +/** + * @author Emmanuel Bernard + */ +@Embeddable +public class Pet { + String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNonPersistent() { + return null; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/Product.java b/tooling/metamodel-generator/src/test/java/model/Product.java new file mode 100644 index 0000000000..d598e19895 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Product.java @@ -0,0 +1,53 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import java.math.BigDecimal; +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +@Entity +public class Product { + + transient String nonPersistent; + static String nonPersistent2; + + @Id + long id; + + int test; + + String description; + BigDecimal price; + + @ManyToOne + Shop shop; + + @OneToMany + Set items; +} diff --git a/tooling/metamodel-generator/src/test/java/model/Shop.java b/tooling/metamodel-generator/src/test/java/model/Shop.java new file mode 100644 index 0000000000..953860f7b0 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/Shop.java @@ -0,0 +1,35 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +@Entity +public class Shop { + @Id + long id; + String name; +} + \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/model/User.java b/tooling/metamodel-generator/src/test/java/model/User.java new file mode 100644 index 0000000000..15926ee876 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/User.java @@ -0,0 +1,58 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Transient; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class User { + private Long id; + private String nonPersistent; + private String name; + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Transient + public String getNonPersistent() { + return nonPersistent; + } + + public void setNonPersistent(String nonPersistent) { + this.nonPersistent = nonPersistent; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/tooling/metamodel-generator/src/test/java/model/xmlmapped/Address.java b/tooling/metamodel-generator/src/test/java/model/xmlmapped/Address.java new file mode 100644 index 0000000000..f6d9bb08ba --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/xmlmapped/Address.java @@ -0,0 +1,51 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model.xmlmapped; + +/** + * @author Hardy Ferentschik + */ +public class Address { + private String street1; + private String city; + private String country; + + public String getStreet1() { + return street1; + } + + public void setStreet1(String street1) { + this.street1 = street1; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/model/xmlmapped/Building.java b/tooling/metamodel-generator/src/test/java/model/xmlmapped/Building.java new file mode 100644 index 0000000000..21315643b0 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/xmlmapped/Building.java @@ -0,0 +1,36 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model.xmlmapped; + +import model.Address; +import model.Area; + +/** + * @author Hardy Ferentschik + */ +public class Building extends Area { + private Address address; + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/model/xmlmapped/LivingBeing.java b/tooling/metamodel-generator/src/test/java/model/xmlmapped/LivingBeing.java new file mode 100644 index 0000000000..e27616d15d --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/xmlmapped/LivingBeing.java @@ -0,0 +1,37 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model.xmlmapped; + +/** + * @author Hardy Ferentschik + */ +public class LivingBeing { + boolean isReallyAlive; + + public boolean isReallyAlive() { + return isReallyAlive; + } + + public void setReallyAlive(boolean reallyAlive) { + isReallyAlive = reallyAlive; + } + + public int nonPersistent() { + return 0; + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/model/xmlmapped/Mammal.java b/tooling/metamodel-generator/src/test/java/model/xmlmapped/Mammal.java new file mode 100644 index 0000000000..d0213e6872 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/model/xmlmapped/Mammal.java @@ -0,0 +1,42 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package model.xmlmapped; + +/** + * @author Hardy Ferentschik + */ +public class Mammal extends LivingBeing { + private String id; + private String subclass; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getSubclass() { + return subclass; + } + + public void setSubclass(String subclass) { + this.subclass = subclass; + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/test/AccessTypeTest.java b/tooling/metamodel-generator/src/test/java/test/AccessTypeTest.java new file mode 100644 index 0000000000..20f4fedc80 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/test/AccessTypeTest.java @@ -0,0 +1,94 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package test; + +import org.testng.annotations.Test; +import org.testng.Assert; + +/** + * @author Emmanuel Bernard + */ +@Test +public class AccessTypeTest { + + @Test + public void testExcludeTransientFieldAndStatic() throws Exception{ + absenceOfField( "model.Product_", "nonPersistent" ); + absenceOfField( "model.Product_", "nonPersistent2" ); + } + + @Test + public void testDefaultAccessTypeOnEntity() throws Exception{ + absenceOfField( "model.User_", "nonPersistent" ); + } + + @Test + public void testDefaultAccessTypeForSubclassOfEntity() throws Exception{ + absenceOfField( "model.Customer_", "nonPersistent" ); + } + + @Test + public void testDefaultAccessTypeForEmbeddable() throws Exception{ + absenceOfField( "model.Detail_", "nonPersistent" ); + } + + @Test + public void testInheritedAccessTypeForEmbeddable() throws Exception{ + absenceOfField( "model.Country_", "nonPersistent" ); + absenceOfField( "model.Pet_", "nonPersistent", "Colleciton of membeddable not taken care of" ); + } + + @Test + public void testDefaultAccessTypeForMappedSuperclass() throws Exception{ + absenceOfField( "model.Detail_", "volume" ); + } + + @Test + public void testExplicitAccessTypeAndDefaultFromRootEntity() throws Exception{ + absenceOfField( "model.LivingBeing_", "nonPersistent", "eplicit access type on mapped superclass" ); + absenceOfField( "model.Hominidae_", "nonPersistent", "eplicit access type on entity" ); + absenceOfField( "model.Human_", "nonPersistent", "proper inheritance from root entity access type" ); + } + + @Test + public void testMemberAccessType() throws Exception{ + presenceOfField( "model.Customer_", "goodPayer", "access type overriding" ); + } + + private void absenceOfField(String className, String fieldName) throws ClassNotFoundException { + absenceOfField( className, fieldName, "field should not be persistent" ); + } + private void absenceOfField(String className, String fieldName, String errorString) throws ClassNotFoundException { + Assert.assertFalse( isFieldHere(className, fieldName), errorString ); + } + + private void presenceOfField(String className, String fieldName, String errorString) throws ClassNotFoundException { + Assert.assertTrue( isFieldHere(className, fieldName), errorString ); + } + + private boolean isFieldHere(String className, String fieldName) throws ClassNotFoundException { + Class user_ = Class.forName( className ); + try { + user_.getField( fieldName ); + return true; + } + catch (NoSuchFieldException e) { + return false; + } + } +} diff --git a/tooling/metamodel-generator/src/test/java/test/InheritanceTest.java b/tooling/metamodel-generator/src/test/java/test/InheritanceTest.java new file mode 100644 index 0000000000..627a7d5eb1 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/test/InheritanceTest.java @@ -0,0 +1,46 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package test; + +import org.testng.annotations.Test; +import org.testng.Assert; +import model.Customer_; +import model.User_; +import model.House_; +import model.Building_; +import model.Area_; + +/** + * @author Emmanuel Bernard + */ +@Test +public class InheritanceTest { + @Test + public void testSuperEntity() throws Exception { + Assert.assertEquals( Customer_.class.getSuperclass(), User_.class, + "Entity with super entity should inherit at the metamodel level"); + } + + @Test + public void testMappedSuperclass() throws Exception { + Assert.assertEquals( House_.class.getSuperclass(), Building_.class, + "Entity with mapped superclass should inherit at the metamodel level"); + Assert.assertEquals( Building_.class.getSuperclass(), Area_.class, + "mapped superclass with mapped superclass should inherit at the metamodel level"); + } +} diff --git a/tooling/metamodel-generator/src/test/java/test/QueryTest.java b/tooling/metamodel-generator/src/test/java/test/QueryTest.java new file mode 100644 index 0000000000..324b02f281 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/test/QueryTest.java @@ -0,0 +1,166 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package test; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.Set; +import javax.persistence.Tuple; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Join; +import static javax.persistence.criteria.JoinType.INNER; +import javax.persistence.criteria.ListJoin; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Root; + +import model.Item; +import model.Item_; +import model.Order; +import model.Order_; +import model.Product; +import model.Product_; +import model.Shop_; + +/** + * Writing queries involves passing typesafe, statically cached, metamodel + * objects to the query builder in order to create the various parts of + * the query. The typesafe metamodel objects were validated at init time, + * so it is impossible to build invalid queries in the application code. + * + * @author Max Andersen + * @author Hardy Ferentschik + * @author Emmanuel Bernard + */ +public class QueryTest { + + CriteriaBuilder qb; + + public void test() { + CriteriaQuery q = qb.createTupleQuery(); + + Root order = q.from( Order.class ); + Join product = order.join( Order_.items ) + .join( Item_.product ); + + Path price = product.get( Product_.price ); + Path filled = order.get( Order_.filled ); + Path date = order.get( Order_.date ); + + q.select( qb.tuple( order, product ) ) + .where( qb.and( qb.gt( price, 100.00 ), qb.not( filled ) ) ) + .orderBy( qb.asc( price ), qb.desc( date ) ); + } + + public void testUntypesafe() { + CriteriaQuery q = qb.createTupleQuery(); + + Root order = q.from( Order.class ); + Join product = order.join( "items" ) + .join( "product" ); + + Path price = product.get( "price" ); + Path filled = order.get( "filled" ); + Path date = order.get( "date" ); + + q.select( qb.tuple( order, product ) ) + .where( qb.and( qb.gt( price, 100.00 ), qb.not( filled ) ) ) + .orderBy( qb.asc( price ), qb.desc( date ) ); + } + + /** + * Navigation by joining + */ + public void test2() { + CriteriaQuery q = qb.createQuery( Product.class ); + + Root product = q.from( Product.class ); + Join order = product.join( Product_.items ) + .join( Item_.order ); + + q.select( product ) + .where( qb.equal( order.get( Order_.id ), 12345l ) ); + } + + public void testMap() { + CriteriaQuery q = qb.createQuery( Item.class ); + + Root item = q.from( Item.class ); + item.join( Item_.namedOrders ); + } + + /** + * Navigation by compound Path + */ + public void test3() { + CriteriaQuery q = qb.createQuery( Item.class ); + + Root item = q.from( Item.class ); + Path shopName = item.get( Item_.order ) + .get( Order_.shop ) + .get( Shop_.name ); + q.select( item ) + .where( qb.equal( shopName, "amazon.com" ) ); + } + +// public void test4() { +// CriteriaQuery q = qb.create(); +// +// Root order = q.from(Order.class); +// ListJoin note = order.join(Order_.notes); +// Expression> items = order.get(Order_.items); +// order.fetch(Order_.items, JoinType.INNER); +// +// q.select(note) +// .where( qb.and( qb.lt(note.index(), 10), qb.isNotEmpty(items) ) ); +// } + + public void test4Untypesafe() { + CriteriaQuery q = qb.createQuery( String.class ); + + Root order = q.from( Order.class ); + ListJoin note = order.joinList( "notes" ); + Expression> items = order.get( "items" ); + order.fetch( "items", INNER ); + + q.select( note ) + .where( qb.and( qb.lt( note.index(), 10 ), qb.isNotEmpty( items ) ) ); + } + + /*public void test5() { + Expression l= null; + Expression i= null; + Expression x= null; + Expression y= null; + + Expression n; + Expression f; + Expression s = null; + + n = qb.quot(l, i); + + f = qb.sum(x, y); + + n = qb.quot(x, y); + + javax.jpamodelgen.criteria.Order o = qb.asc(n); + javax.jpamodelgen.criteria.Order p = qb.ascending(s); + }*/ + +} diff --git a/tooling/metamodel-generator/src/test/java/test/XmlMappingTest.java b/tooling/metamodel-generator/src/test/java/test/XmlMappingTest.java new file mode 100644 index 0000000000..84155896ae --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/test/XmlMappingTest.java @@ -0,0 +1,55 @@ +// $Id$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2008, Red Hat Middleware LLC, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package test; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; + +/** + * @author Hardy Ferentschik + */ +public class XmlMappingTest { + @Test + public void testXmlConfiguredEmbeddedClassGenerated() throws Exception { + assertNotNull( Class.forName( "model.xmlmapped.Address_" ) ); + } + + @Test + public void testXmlConfiguredMappedSuperclassGenerated() throws Exception { + Class building = Class.forName( "model.xmlmapped.Building_" ); + assertNotNull( building ); + assertNotNull( building.getField( "address" ) ); + } + + @Test + public void testClassHierarchy() throws Exception { + Class mammal = Class.forName( "model.xmlmapped.Mammal_" ); + assertNotNull( mammal ); + + Class being = Class.forName( "model.xmlmapped.LivingBeing_" ); + assertNotNull( being ); + + assertTrue( mammal.getSuperclass().equals( being ) ); + } + + @Test(expectedExceptions = ClassNotFoundException.class) + public void testNonExistentMappedClassesGetIgnored() throws Exception { + Class.forName( "model.Dummy_" ); + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/dummy.xml b/tooling/metamodel-generator/src/test/resources/META-INF/dummy.xml new file mode 100644 index 0000000000..289c09d9ec --- /dev/null +++ b/tooling/metamodel-generator/src/test/resources/META-INF/dummy.xml @@ -0,0 +1,14 @@ + + + + model + + + + + + diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/jpa1-orm.xml b/tooling/metamodel-generator/src/test/resources/META-INF/jpa1-orm.xml new file mode 100644 index 0000000000..3d2d93046b --- /dev/null +++ b/tooling/metamodel-generator/src/test/resources/META-INF/jpa1-orm.xml @@ -0,0 +1,14 @@ + + + + model + + + + + + \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/malformed-mapping-xml.xml b/tooling/metamodel-generator/src/test/resources/META-INF/malformed-mapping-xml.xml new file mode 100644 index 0000000000..26e679f6f1 --- /dev/null +++ b/tooling/metamodel-generator/src/test/resources/META-INF/malformed-mapping-xml.xml @@ -0,0 +1,13 @@ + + + + model + + + + + diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/orm.xml b/tooling/metamodel-generator/src/test/resources/META-INF/orm.xml new file mode 100644 index 0000000000..3ec7df5579 --- /dev/null +++ b/tooling/metamodel-generator/src/test/resources/META-INF/orm.xml @@ -0,0 +1,29 @@ + + + + model + + + + + + + + + + + + + + + + + + + diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/persistence.xml b/tooling/metamodel-generator/src/test/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..3b120d9ad4 --- /dev/null +++ b/tooling/metamodel-generator/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,14 @@ + + + + Test persistence unit + /META-INF/dummy.xml + /META-INF/malformed-mapping-xml.xml + /META-INF/jpa1-orm.xml + /model/xmlmapped/address.xml + /model/xmlmapped/building.xml + /model/xmlmapped/mammal.xml + + diff --git a/tooling/metamodel-generator/src/test/resources/model/xmlmapped/address.xml b/tooling/metamodel-generator/src/test/resources/model/xmlmapped/address.xml new file mode 100644 index 0000000000..3688245ff3 --- /dev/null +++ b/tooling/metamodel-generator/src/test/resources/model/xmlmapped/address.xml @@ -0,0 +1,17 @@ + + + + model.xmlmapped + + + + + + + + + diff --git a/tooling/metamodel-generator/src/test/resources/model/xmlmapped/building.xml b/tooling/metamodel-generator/src/test/resources/model/xmlmapped/building.xml new file mode 100644 index 0000000000..e112bef012 --- /dev/null +++ b/tooling/metamodel-generator/src/test/resources/model/xmlmapped/building.xml @@ -0,0 +1,15 @@ + + + + model.xmlmapped + + + + + + + diff --git a/tooling/metamodel-generator/src/test/resources/model/xmlmapped/mammal.xml b/tooling/metamodel-generator/src/test/resources/model/xmlmapped/mammal.xml new file mode 100644 index 0000000000..3024096ea0 --- /dev/null +++ b/tooling/metamodel-generator/src/test/resources/model/xmlmapped/mammal.xml @@ -0,0 +1,20 @@ + + + + model.xmlmapped + + + + + + + + + + + + diff --git a/tooling/metamodel-generator/src/test/suite/unit-tests.xml b/tooling/metamodel-generator/src/test/suite/unit-tests.xml new file mode 100644 index 0000000000..b63742033e --- /dev/null +++ b/tooling/metamodel-generator/src/test/suite/unit-tests.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file