├── .gitignore ├── .travis.yml ├── LICENSE ├── README.asciidoc ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── jboss │ │ └── forge │ │ └── addon │ │ └── angularjs │ │ ├── AngularScaffoldProvider.java │ │ ├── CopyResourcesStrategy.java │ │ ├── DetailTemplateStrategy.java │ │ ├── InspectionResultProcessor.java │ │ ├── JSONRestResourceFromEntityCommand.java │ │ ├── ProcessTemplateStrategy.java │ │ ├── ProcessingStrategy.java │ │ ├── ResourcePathVisitor.java │ │ ├── ResourceProvider.java │ │ ├── ScaffoldResource.java │ │ ├── ScaffoldableEntitySelectionWizard.java │ │ ├── SearchTemplateStrategy.java │ │ └── util │ │ └── RestResourceTypeVisitor.java └── resources │ ├── META-INF │ └── beans.xml │ └── org │ └── jboss │ └── forge │ └── addon │ └── angularjs │ ├── app.html.ftl │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 │ ├── img │ └── forge-logo.png │ ├── index.html.ftl │ ├── scripts │ ├── app.js.ftl │ ├── controllers │ │ ├── editEntityController.js.ftl │ │ ├── flashController.js.ftl │ │ ├── newEntityController.js.ftl │ │ └── searchEntityController.js.ftl │ ├── directives │ │ ├── datepicker.js.ftl │ │ ├── datetimepicker.js.ftl │ │ └── timepicker.js.ftl │ ├── filters │ │ ├── genericSearchFilter.js.ftl │ │ └── startFromFilter.js.ftl │ ├── offcanvas.js │ ├── services │ │ ├── entityFactory.js.ftl │ │ ├── flash.js.ftl │ │ └── locationParser.js.ftl │ └── vendor │ │ ├── angular-resource.js │ │ ├── angular-route.js │ │ ├── angular.js │ │ ├── bootstrap.js │ │ ├── jquery-2.1.1.js │ │ └── modernizr-2.8.3.min.js │ ├── styles │ ├── bootstrap-theme.css │ ├── bootstrap.css │ └── main.css │ └── views │ ├── detail.html.ftl │ ├── includes │ ├── basicPropertyDetail.html.ftl │ ├── lookupPropertyDetail.html.ftl │ ├── nToManyPropertyDetail.html.ftl │ ├── nToOnePropertyDetail.html.ftl │ ├── searchFormInput.html.ftl │ ├── searchResults.html.ftl │ └── searchResultsPaginator.html.ftl │ ├── landing.html │ └── search.html.ftl └── test └── java └── org └── jboss └── forge └── addon └── angularjs ├── ProjectHelper.java ├── PropertyBuilder.java ├── TestHelpers.java ├── matchers └── InspectionResultMatcher.java └── tests ├── freemarker ├── Deployments.java ├── FreemarkerClientPartialsBasicPropertyTest.java ├── FreemarkerClientPartialsLookupPropertyTest.java ├── FreemarkerClientPartialsNToManyPropertyTest.java ├── FreemarkerClientPartialsNToOnePropertyTest.java ├── FreemarkerClientPartialsSearchInputTest.java ├── FreemarkerClientPartialsSearchResultsPaginatorTest.java ├── FreemarkerClientPartialsSearchResultsTest.java └── FreemarkerClientTest.java └── metawidget └── InspectionResultProcessorTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .settings 4 | .DS_Store 5 | dependency-reduced-pom.xml 6 | target/ 7 | *.iml 8 | *.ipr 9 | *.iws 10 | *.swp 11 | /*/src/main/java/META-INF 12 | .gitignore.swp 13 | docs/reference/src/main/docbook/en-US/version_info.xml 14 | .idea 15 | .forge_settings 16 | .factorypath 17 | atlassian-ide-plugin.xml 18 | .externalToolBuilders 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - oraclejdk8 5 | 6 | notifications: 7 | irc: chat.freenode.net#forge 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 1.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial code and documentation 12 | distributed under this Agreement, and 13 | b) in the case of each subsequent Contributor: 14 | i) changes to the Program, and 15 | ii) additions to the Program; 16 | 17 | where such changes and/or additions to the Program originate from and are 18 | distributed by that particular Contributor. A Contribution 'originates' 19 | from a Contributor if it was added to the Program by such Contributor 20 | itself or anyone acting on such Contributor's behalf. Contributions do not 21 | include additions to the Program which: (i) are separate modules of 22 | software distributed in conjunction with the Program under their own 23 | license agreement, and (ii) are not derivative works of the Program. 24 | 25 | "Contributor" means any person or entity that distributes the Program. 26 | 27 | "Licensed Patents" mean patent claims licensable by a Contributor which are 28 | necessarily infringed by the use or sale of its Contribution alone or when 29 | combined with the Program. 30 | 31 | "Program" means the Contributions distributed in accordance with this 32 | Agreement. 33 | 34 | "Recipient" means anyone who receives the Program under this Agreement, 35 | including all Contributors. 36 | 37 | 2. GRANT OF RIGHTS 38 | a) Subject to the terms of this Agreement, each Contributor hereby grants 39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 40 | reproduce, prepare derivative works of, publicly display, publicly 41 | perform, distribute and sublicense the Contribution of such Contributor, 42 | if any, and such derivative works, in source code and object code form. 43 | b) Subject to the terms of this Agreement, each Contributor hereby grants 44 | Recipient a non-exclusive, worldwide, royalty-free patent license under 45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 46 | transfer the Contribution of such Contributor, if any, in source code and 47 | object code form. This patent license shall apply to the combination of 48 | the Contribution and the Program if, at the time the Contribution is 49 | added by the Contributor, such addition of the Contribution causes such 50 | combination to be covered by the Licensed Patents. The patent license 51 | shall not apply to any other combinations which include the Contribution. 52 | No hardware per se is licensed hereunder. 53 | c) Recipient understands that although each Contributor grants the licenses 54 | to its Contributions set forth herein, no assurances are provided by any 55 | Contributor that the Program does not infringe the patent or other 56 | intellectual property rights of any other entity. Each Contributor 57 | disclaims any liability to Recipient for claims brought by any other 58 | entity based on infringement of intellectual property rights or 59 | otherwise. As a condition to exercising the rights and licenses granted 60 | hereunder, each Recipient hereby assumes sole responsibility to secure 61 | any other intellectual property rights needed, if any. For example, if a 62 | third party patent license is required to allow Recipient to distribute 63 | the Program, it is Recipient's responsibility to acquire that license 64 | before distributing the Program. 65 | d) Each Contributor represents that to its knowledge it has sufficient 66 | copyright rights in its Contribution, if any, to grant the copyright 67 | license set forth in this Agreement. 68 | 69 | 3. REQUIREMENTS 70 | 71 | A Contributor may choose to distribute the Program in object code form under 72 | its own license agreement, provided that: 73 | 74 | a) it complies with the terms and conditions of this Agreement; and 75 | b) its license agreement: 76 | i) effectively disclaims on behalf of all Contributors all warranties 77 | and conditions, express and implied, including warranties or 78 | conditions of title and non-infringement, and implied warranties or 79 | conditions of merchantability and fitness for a particular purpose; 80 | ii) effectively excludes on behalf of all Contributors all liability for 81 | damages, including direct, indirect, special, incidental and 82 | consequential damages, such as lost profits; 83 | iii) states that any provisions which differ from this Agreement are 84 | offered by that Contributor alone and not by any other party; and 85 | iv) states that source code for the Program is available from such 86 | Contributor, and informs licensees how to obtain it in a reasonable 87 | manner on or through a medium customarily used for software exchange. 88 | 89 | When the Program is made available in source code form: 90 | 91 | a) it must be made available under this Agreement; and 92 | b) a copy of this Agreement must be included with each copy of the Program. 93 | Contributors may not remove or alter any copyright notices contained 94 | within the Program. 95 | 96 | Each Contributor must identify itself as the originator of its Contribution, 97 | if 98 | any, in a manner that reasonably allows subsequent Recipients to identify the 99 | originator of the Contribution. 100 | 101 | 4. COMMERCIAL DISTRIBUTION 102 | 103 | Commercial distributors of software may accept certain responsibilities with 104 | respect to end users, business partners and the like. While this license is 105 | intended to facilitate the commercial use of the Program, the Contributor who 106 | includes the Program in a commercial product offering should do so in a manner 107 | which does not create potential liability for other Contributors. Therefore, 108 | if a Contributor includes the Program in a commercial product offering, such 109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify 110 | every other Contributor ("Indemnified Contributor") against any losses, 111 | damages and costs (collectively "Losses") arising from claims, lawsuits and 112 | other legal actions brought by a third party against the Indemnified 113 | Contributor to the extent caused by the acts or omissions of such Commercial 114 | Contributor in connection with its distribution of the Program in a commercial 115 | product offering. The obligations in this section do not apply to any claims 116 | or Losses relating to any actual or alleged intellectual property 117 | infringement. In order to qualify, an Indemnified Contributor must: 118 | a) promptly notify the Commercial Contributor in writing of such claim, and 119 | b) allow the Commercial Contributor to control, and cooperate with the 120 | Commercial Contributor in, the defense and any related settlement 121 | negotiations. The Indemnified Contributor may participate in any such claim at 122 | its own expense. 123 | 124 | For example, a Contributor might include the Program in a commercial product 125 | offering, Product X. That Contributor is then a Commercial Contributor. If 126 | that Commercial Contributor then makes performance claims, or offers 127 | warranties related to Product X, those performance claims and warranties are 128 | such Commercial Contributor's responsibility alone. Under this section, the 129 | Commercial Contributor would have to defend claims against the other 130 | Contributors related to those performance claims and warranties, and if a 131 | court requires any other Contributor to pay any damages as a result, the 132 | Commercial Contributor must pay those damages. 133 | 134 | 5. NO WARRANTY 135 | 136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN 137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each 140 | Recipient is solely responsible for determining the appropriateness of using 141 | and distributing the Program and assumes all risks associated with its 142 | exercise of rights under this Agreement , including but not limited to the 143 | risks and costs of program errors, compliance with applicable laws, damage to 144 | or loss of data, programs or equipment, and unavailability or interruption of 145 | operations. 146 | 147 | 6. DISCLAIMER OF LIABILITY 148 | 149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 156 | OF SUCH DAMAGES. 157 | 158 | 7. GENERAL 159 | 160 | If any provision of this Agreement is invalid or unenforceable under 161 | applicable law, it shall not affect the validity or enforceability of the 162 | remainder of the terms of this Agreement, and without further action by the 163 | parties hereto, such provision shall be reformed to the minimum extent 164 | necessary to make such provision valid and enforceable. 165 | 166 | If Recipient institutes patent litigation against any entity (including a 167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 168 | (excluding combinations of the Program with other software or hardware) 169 | infringes such Recipient's patent(s), then such Recipient's rights granted 170 | under Section 2(b) shall terminate as of the date such litigation is filed. 171 | 172 | All Recipient's rights under this Agreement shall terminate if it fails to 173 | comply with any of the material terms or conditions of this Agreement and does 174 | not cure such failure in a reasonable period of time after becoming aware of 175 | such noncompliance. If all Recipient's rights under this Agreement terminate, 176 | Recipient agrees to cease use and distribution of the Program as soon as 177 | reasonably practicable. However, Recipient's obligations under this Agreement 178 | and any licenses granted by Recipient relating to the Program shall continue 179 | and survive. 180 | 181 | Everyone is permitted to copy and distribute copies of this Agreement, but in 182 | order to avoid inconsistency the Agreement is copyrighted and may only be 183 | modified in the following manner. The Agreement Steward reserves the right to 184 | publish new versions (including revisions) of this Agreement from time to 185 | time. No one other than the Agreement Steward has the right to modify this 186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 187 | Eclipse Foundation may assign the responsibility to serve as the Agreement 188 | Steward to a suitable separate entity. Each new version of the Agreement will 189 | be given a distinguishing version number. The Program (including 190 | Contributions) may always be distributed subject to the version of the 191 | Agreement under which it was received. In addition, after a new version of the 192 | Agreement is published, Contributor may elect to distribute the Program 193 | (including its Contributions) under the new version. Except as expressly 194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 195 | licenses to the intellectual property of any Contributor under this Agreement, 196 | whether expressly, by implication, estoppel or otherwise. All rights in the 197 | Program not expressly granted under this Agreement are reserved. 198 | 199 | This Agreement is governed by the laws of the State of New York and the 200 | intellectual property laws of the United States of America. No party to this 201 | Agreement will bring a legal action under this Agreement more than one year 202 | after the cause of action arose. Each party waives its rights to a jury trial in 203 | any resulting litigation. -------------------------------------------------------------------------------- /README.asciidoc: -------------------------------------------------------------------------------- 1 | == AngularJS Addon for JBoss Forge 2 2 | :idprefix: id_ 3 | 4 | image:https://travis-ci.org/forge/angularjs-addon.svg?branch=master["Build Status", link="https://travis-ci.org/forge/angularjs-addon"] 5 | 6 | The angularjs-addon enables developers to automate several tasks in the construction of applications that use AngularJS, in JBoss Forge. 7 | This addon provides *standalone* functionality, and it can be re-used in other addons. 8 | 9 | === Dependencies: 10 | === Depends on 11 | [options="header"] 12 | |=== 13 | |Addon |Exported |Optional 14 | |scaffold-spi 15 | |no 16 | |no 17 | |javaee 18 | |no 19 | |no 20 | |templates 21 | |no 22 | |no 23 | |text 24 | |no 25 | |no 26 | |convert 27 | |no 28 | |no 29 | |parser-java 30 | |no 31 | |no 32 | |cdi 33 | |no 34 | |no 35 | |=== 36 | 37 | == Setup 38 | This Addon requires the following installation steps. 39 | 40 | === Add configuration to pom.xml 41 | To use this addon, you must add it as a dependency in the *pom.xml* of your `forge-addon` classified artifact: 42 | (Make sure the dependency is put all the way to the left, and uses 3 spaces for indentation of GAV) 43 | [source,xml] 44 | ---- 45 | 46 | org.jboss.forge.addon 47 | angularjs 48 | forge-addon 49 | ${version} 50 | 51 | ---- 52 | == Features 53 | * Scaffold web-apps from JPA entities. The generated scaffold uses a thick-client based on AngularJS, and a JAX-RS RESTful backend. 54 | 55 | == Usage 56 | 57 | === Prerequsites 58 | 59 | JBoss Tools with Forge 2.4.1, or JBoss Forge-CLI 2.4.1. 60 | 61 | === Install the addon: 62 | 63 | Assuming JBoss Tools with Forge, or Forge-CLI is installed: 64 | 65 | *(JBT)* 66 | 67 | Ctrl+5. Run the "Install the addon from Git" command, using these coordinates: https://github.com/forge/angularjs-addon.git 68 | 69 | *(Forge-CLI)* 70 | 71 | ---- 72 | $ addon-install-from-git --url https://github.com/forge/angularjs-addon.git 73 | ---- 74 | 75 | === Create a new project 76 | 77 | *(JBT)* 78 | 79 | Ctrl+5. Run the "Project: New" command. Create a new web application, named 'hello-angular'. 80 | 81 | *(Forge-CLI)* 82 | 83 | ---- 84 | $ project-new --named hello-angular 85 | ---- 86 | 87 | === Setup JPA 88 | 89 | *(JBT)* 90 | 91 | Ctrl+5. Run the "JPA: Setup" command. Defaults should be sufficient. 92 | 93 | *(Forge-CLI)* 94 | 95 | ---- 96 | $ jpa-setup 97 | ---- 98 | 99 | === Create a few JPA entities with fields 100 | 101 | *(JBT)* 102 | 103 | Ctrl+5. Run the "JPA: New Entity" command. Create a new entity (with an auto-generated Id) named 'Customer'. 104 | 105 | Select the newly created Customer Java source file in the navigator. Ctrl+5. Run the "JPA: New Field" command. Create a new field of type String in the Customer entity named 'fullName'. 106 | 107 | Ctrl+5 again and re-run the same command. Create a new field of type int in the Customer entity named 'age'. 108 | 109 | 110 | *(Forge-CLI)* 111 | 112 | ---- 113 | $ jpa-new-entity --named Customer 114 | $ jpa-new-field --named fullName 115 | $ jpa-new-field --named age --type int 116 | ---- 117 | 118 | === Setup Bean Validation and create new constraints 119 | 120 | *(JBT)* 121 | 122 | Ctrl+5. Run the "Constraint: Setup" command. Choose the "Generic Java EE" BV provider to use. 123 | 124 | Ctrl+5. Run the "Constraint: Add" command. Create a NotNull constraint on the fullName field. 125 | 126 | Ctrl+5. Run the "Constraint: Add" command. Create a Min constraint on the age field, with min value of 0. 127 | 128 | *(Forge-CLI)* 129 | 130 | ---- 131 | $ constraint-setup --providers Generic\ Java\ EE 132 | $ constraint-add --onProperty fullName --constraint NotNull 133 | $ constraint-add --onProperty age --constraint Min --value 0 134 | ---- 135 | 136 | 137 | === Setup and generate the AngularJS scaffold 138 | 139 | *(JBT)* 140 | 141 | Ctrl+5. Run the "Scaffold: Setup" command. Choose the "AngularJS" type to use. 142 | 143 | Ctrl+5. Run the "Scaffold: Generate" command. Choose the "AngularJS" type to use. Select the Customer entity to scaffold. (I'll rework this bit across scaffold providers when fixing FORGE-1501 and FORGE-1731). 144 | 145 | On completion, a JAX-RS resource that can handle requests and responses of media type application/json should be created, in conjunction with the AngularJS views. 146 | 147 | *(Forge-CLI)* 148 | 149 | ---- 150 | $ scaffold-setup --provider AngularJS 151 | $ scaffold-generate --provider AngularJS --targets org.hello.angular.model.Customer 152 | ---- 153 | 154 | This app can now be deployed to JBoss EAP. 155 | 156 | == Issue Tracker 157 | 158 | We do not use GitHub issues for issue tracking. 159 | Please raise issues in the https://issues.jboss.org//secure/CreateIssueDetails!init.jspa?pid=12312020&components=12317568&issuetype=1&priority=3[JBoss JIRA Issue tracker]. The project and component is *FORGEPLUGINS* and *AngularJS Scaffold* respectively. We also track feature requests in the same space. 160 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.jboss 6 | jboss-parent 7 | 20 8 | 9 | org.jboss.forge.addon 10 | angularjs 11 | 2.1.8-SNAPSHOT 12 | 13 | UTF-8 14 | true 15 | 16 | 0.0.4.Final 17 | 2.23.7.Final 18 | 3.2.3.Final 19 | 20 | 21 | scm:git:git://github.com/forge/angularjs-addon.git 22 | scm:git:git@github.com:forge/angularjs-addon.git 23 | http://github.com/forge/angularjs-addon 24 | 25 | 26 | 27 | 28 | org.jboss.forge 29 | forge-bom 30 | ${version.forge} 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | org.jboss.forge.addon 39 | scaffold-spi 40 | forge-addon 41 | provided 42 | 43 | 44 | 45 | org.jboss.forge.descriptors 46 | javaee-descriptors 47 | ${version.forge.descriptors} 48 | provided 49 | 50 | 51 | org.jboss.forge.addon 52 | javaee 53 | forge-addon 54 | provided 55 | 56 | 57 | org.jboss.forge.addon 58 | projects 59 | forge-addon 60 | provided 61 | 62 | 63 | 64 | org.jboss.forge.addon 65 | templates 66 | forge-addon 67 | provided 68 | 69 | 70 | org.jboss.forge.addon 71 | text 72 | forge-addon 73 | provided 74 | 75 | 76 | org.jboss.forge.addon 77 | convert 78 | forge-addon 79 | provided 80 | 81 | 82 | org.jboss.forge.addon 83 | parser-java 84 | forge-addon 85 | provided 86 | 87 | 88 | org.jboss.forge.furnace.container 89 | cdi 90 | forge-addon 91 | provided 92 | 93 | 94 | org.jboss.forge.addon 95 | maven 96 | forge-addon 97 | test 98 | 99 | 100 | org.jboss.forge.furnace.test 101 | furnace-test-harness 102 | test 103 | 104 | 105 | org.jboss.forge.furnace.test 106 | arquillian-furnace-classpath 107 | test 108 | 109 | 110 | org.jsoup 111 | jsoup 112 | 1.7.1 113 | test 114 | 115 | 116 | 117 | 118 | 119 | maven-jar-plugin 120 | 121 | 122 | create-forge-addon 123 | package 124 | 125 | jar 126 | 127 | 128 | forge-addon 129 | 130 | 131 | 132 | 133 | 134 | 135 | org.jboss.jandex 136 | jandex-maven-plugin 137 | 1.0.3 138 | 139 | 140 | make-index 141 | 142 | jandex 143 | 144 | true 145 | 146 | 147 | 148 | 149 | org.apache.maven.plugins 150 | maven-release-plugin 151 | true 152 | 153 | -DskipTests 154 | clean install 155 | gpg-sign,jboss-release 156 | @{project.version} 157 | 158 | 159 | 160 | org.sonatype.plugins 161 | nexus-staging-maven-plugin 162 | 1.6.3 163 | true 164 | 165 | true 166 | ossrh 167 | https://oss.sonatype.org/ 168 | 169 | 170 | 171 | 172 | 173 | 175 | 176 | org.eclipse.m2e 177 | lifecycle-mapping 178 | 1.0.0 179 | 180 | 181 | 182 | 183 | 184 | org.jboss.jandex 185 | jandex-maven-plugin 186 | [1.0.3,) 187 | 188 | jandex 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | ${forge.angularjs.scm.connection} 205 | ${forge.angularjs.developer.connection} 206 | ${forge.angularjs.scm.url} 207 | HEAD 208 | 209 | 210 | 211 | 212 | ossrh 213 | https://oss.sonatype.org/content/repositories/snapshots 214 | 215 | 216 | ossrh 217 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/CopyResourcesStrategy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2014 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import org.jboss.forge.addon.projects.facets.WebResourcesFacet; 10 | import org.jboss.forge.addon.resource.Resource; 11 | import org.jboss.forge.addon.scaffold.util.ScaffoldUtil; 12 | 13 | /** 14 | * A {@link ProcessingStrategy} to copy the contents of the {@link ScaffoldResource} from it's source on the classpath 15 | * to it's destination in the project's web resources. 16 | */ 17 | public class CopyResourcesStrategy implements ProcessingStrategy 18 | { 19 | 20 | private final WebResourcesFacet web; 21 | 22 | public CopyResourcesStrategy(WebResourcesFacet web) 23 | { 24 | this.web = web; 25 | } 26 | 27 | @Override 28 | public Resource execute(ScaffoldResource scaffoldResource) 29 | { 30 | return ScaffoldUtil.createOrOverwrite(web.getWebResource(scaffoldResource.getDestination()), getClass() 31 | .getResourceAsStream(scaffoldResource.getSource())); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/DetailTemplateStrategy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import static org.jboss.forge.addon.angularjs.AngularScaffoldProvider.SCAFFOLD_DIR; 10 | 11 | import java.io.IOException; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | import org.jboss.forge.addon.projects.Project; 16 | import org.jboss.forge.addon.projects.facets.WebResourcesFacet; 17 | import org.jboss.forge.addon.resource.Resource; 18 | import org.jboss.forge.addon.resource.ResourceFactory; 19 | import org.jboss.forge.addon.templates.Template; 20 | import org.jboss.forge.addon.templates.TemplateFactory; 21 | import org.jboss.forge.addon.templates.facets.TemplateFacet; 22 | import org.jboss.forge.addon.templates.freemarker.FreemarkerTemplate; 23 | 24 | /** 25 | * A strategy for generating the detail page with included files. 26 | */ 27 | public class DetailTemplateStrategy implements ProcessingStrategy 28 | { 29 | private static final String BASIC_PROPERTY_DETAIL = "/views/includes/basicPropertyDetail.html.ftl"; 30 | private static final String LOOKUP_PROPERTY_DETAIL = "/views/includes/lookupPropertyDetail.html.ftl"; 31 | private static final String N_TO_MANY_PROPERTY_DETAIL = "/views/includes/nToManyPropertyDetail.html.ftl"; 32 | private static final String N_TO_ONE_PROPERTY_DETAIL = "/views/includes/nToOnePropertyDetail.html.ftl"; 33 | 34 | private final WebResourcesFacet web; 35 | 36 | private final Project project; 37 | 38 | private final Map dataModel; 39 | 40 | private final ResourceFactory resourceFactory; 41 | 42 | private final TemplateFactory templateFactory; 43 | 44 | public DetailTemplateStrategy(WebResourcesFacet web, ResourceFactory resourceFactory, Project project, 45 | TemplateFactory templateFactory, Map dataModel) 46 | { 47 | this.web = web; 48 | this.resourceFactory = resourceFactory; 49 | this.project = project; 50 | this.templateFactory = templateFactory; 51 | this.dataModel = dataModel; 52 | } 53 | 54 | @Override 55 | public Resource execute(ScaffoldResource scaffoldResource) 56 | { 57 | @SuppressWarnings("unchecked") 58 | List> properties = (List>) dataModel.get("properties"); 59 | StringBuilder formProperties = new StringBuilder(); 60 | for (Map property : properties) 61 | { 62 | dataModel.put("property", property); 63 | Include includeFile; 64 | if ("true".equals(property.get("many-to-one")) || "true".equals(property.get("one-to-one"))) 65 | { 66 | includeFile = new Include(N_TO_ONE_PROPERTY_DETAIL); 67 | } 68 | else if ("true".equals(property.get("n-to-many"))) 69 | { 70 | includeFile = new Include(N_TO_MANY_PROPERTY_DETAIL); 71 | } 72 | else if (property.containsKey("lookup")) 73 | { 74 | includeFile = new Include(LOOKUP_PROPERTY_DETAIL); 75 | } 76 | else 77 | { 78 | includeFile = new Include(BASIC_PROPERTY_DETAIL); 79 | } 80 | String output = includeFile.processInclude(dataModel); 81 | formProperties.append(output).append('\n'); 82 | } 83 | dataModel.put("formProperties", formProperties.toString()); 84 | ProcessTemplateStrategy strategy = new ProcessTemplateStrategy(web, resourceFactory, project, 85 | templateFactory, dataModel); 86 | return strategy.execute(scaffoldResource); 87 | } 88 | 89 | class Include 90 | { 91 | private final String source; 92 | 93 | Include(String source) 94 | { 95 | this.source = source; 96 | } 97 | 98 | private String processInclude(Map dataModel) 99 | { 100 | Resource resource = resourceFactory.create(getClass().getResource( 101 | SCAFFOLD_DIR + source)); 102 | if (project.hasFacet(TemplateFacet.class)) 103 | { 104 | TemplateFacet templates = project.getFacet(TemplateFacet.class); 105 | Resource templateResource = templates.getResource(source); 106 | if (templateResource.exists()) 107 | { 108 | resource = templateResource; 109 | } 110 | } 111 | 112 | Template template = templateFactory.create(resource, FreemarkerTemplate.class); 113 | String output = null; 114 | try 115 | { 116 | output = template.process(dataModel); 117 | } 118 | catch (IOException ioEx) 119 | { 120 | throw new IllegalStateException(ioEx); 121 | } 122 | return output; 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/JSONRestResourceFromEntityCommand.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2014 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.HashSet; 12 | import java.util.List; 13 | import java.util.Set; 14 | 15 | import javax.inject.Inject; 16 | import javax.ws.rs.core.MediaType; 17 | 18 | import org.jboss.forge.addon.javaee.jpa.JPAFacet; 19 | import org.jboss.forge.addon.javaee.rest.generation.RestGenerationConstants; 20 | import org.jboss.forge.addon.javaee.rest.generation.RestGenerationContext; 21 | import org.jboss.forge.addon.javaee.rest.generation.RestResourceGenerator; 22 | import org.jboss.forge.addon.parser.java.facets.JavaSourceFacet; 23 | import org.jboss.forge.addon.parser.java.resources.JavaResource; 24 | import org.jboss.forge.addon.projects.Project; 25 | import org.jboss.forge.addon.projects.ProjectFactory; 26 | import org.jboss.forge.addon.projects.Projects; 27 | import org.jboss.forge.addon.resource.Resource; 28 | import org.jboss.forge.addon.scaffold.spi.ResourceCollection; 29 | import org.jboss.forge.addon.text.Inflector; 30 | import org.jboss.forge.addon.ui.context.UIBuilder; 31 | import org.jboss.forge.addon.ui.context.UIContext; 32 | import org.jboss.forge.addon.ui.context.UIExecutionContext; 33 | import org.jboss.forge.addon.ui.hints.InputType; 34 | import org.jboss.forge.addon.ui.input.UIInput; 35 | import org.jboss.forge.addon.ui.input.UISelectOne; 36 | import org.jboss.forge.addon.ui.metadata.UICommandMetadata; 37 | import org.jboss.forge.addon.ui.metadata.WithAttributes; 38 | import org.jboss.forge.addon.ui.result.Result; 39 | import org.jboss.forge.addon.ui.result.Results; 40 | import org.jboss.forge.addon.ui.util.Metadata; 41 | import org.jboss.forge.addon.ui.wizard.UIWizardStep; 42 | import org.jboss.forge.furnace.services.Imported; 43 | import org.jboss.forge.roaster.model.source.JavaClassSource; 44 | import org.jboss.shrinkwrap.descriptor.api.persistence.PersistenceCommonDescriptor; 45 | import org.jboss.shrinkwrap.descriptor.api.persistence.PersistenceUnitCommon; 46 | 47 | /** 48 | * A wizard step to perform creation of REST resources. It re-uses services from the Java EE addon to create JAX-RS 49 | * based REST resources. 50 | */ 51 | public class JSONRestResourceFromEntityCommand implements UIWizardStep 52 | { 53 | 54 | @Inject 55 | @WithAttributes(label = "Generator", required = true) 56 | private UISelectOne generator; 57 | 58 | @Inject 59 | @WithAttributes(label = "Persistence Unit", required = true) 60 | private UISelectOne persistenceUnit; 61 | 62 | @Inject 63 | @WithAttributes(label = "Target Package Name", required = true, type = InputType.JAVA_PACKAGE_PICKER) 64 | private UIInput packageName; 65 | 66 | @Inject 67 | private Imported resourceGenerators; 68 | 69 | @Inject 70 | private Inflector inflector; 71 | 72 | @Inject 73 | private ProjectFactory projectFactory; 74 | 75 | private List targets; 76 | 77 | @Override 78 | public UICommandMetadata getMetadata(UIContext context) 79 | { 80 | return Metadata.forCommand(getClass()).name("REST: Generate Endpoints From Entities") 81 | .description("Generate REST endpoints from JPA entities"); 82 | } 83 | 84 | @Override 85 | public boolean isEnabled(UIContext context) 86 | { 87 | return true; 88 | } 89 | 90 | @SuppressWarnings({ "rawtypes", "unchecked" }) 91 | @Override 92 | public void initializeUI(UIBuilder builder) throws Exception 93 | { 94 | UIContext context = builder.getUIContext(); 95 | Project project = getSelectedProject(context); 96 | JPAFacet persistenceFacet = project.getFacet(JPAFacet.class); 97 | JavaSourceFacet javaSourceFacet = project.getFacet(JavaSourceFacet.class); 98 | List persistenceUnits = new ArrayList<>(); 99 | List allUnits = persistenceFacet.getConfig().getAllPersistenceUnit(); 100 | for (PersistenceUnitCommon persistenceUnit : allUnits) 101 | { 102 | persistenceUnits.add(persistenceUnit.getName()); 103 | } 104 | if (!persistenceUnits.isEmpty()) 105 | { 106 | persistenceUnit.setValueChoices(persistenceUnits).setDefaultValue(persistenceUnits.get(0)); 107 | } 108 | 109 | // TODO: May detect where @Path resources are located 110 | packageName.setDefaultValue(javaSourceFacet.getBasePackage() + ".rest"); 111 | 112 | RestResourceGenerator defaultResourceGenerator = null; 113 | for (RestResourceGenerator generator : resourceGenerators) 114 | { 115 | if (generator.getName().equals(RestGenerationConstants.JPA_ENTITY)) 116 | { 117 | defaultResourceGenerator = generator; 118 | } 119 | } 120 | generator.setDefaultValue(defaultResourceGenerator); 121 | generator.setItemLabelConverter( 122 | context.getProvider().isGUI() ? RestResourceGenerator::getDescription : RestResourceGenerator::getName); 123 | builder.add(generator).add(packageName).add(persistenceUnit); 124 | } 125 | 126 | @Override 127 | public Result execute(final UIExecutionContext context) throws Exception 128 | { 129 | UIContext uiContext = context.getUIContext(); 130 | ResourceCollection resourceCollection = (ResourceCollection) uiContext.getAttributeMap().get( 131 | ResourceCollection.class); 132 | 133 | targets = new ArrayList<>(); 134 | for (Resource resource : resourceCollection.getResources()) 135 | { 136 | JavaResource javaResource = (JavaResource) resource; 137 | JavaClassSource javaClass = javaResource.getJavaType(); 138 | targets.add(javaClass); 139 | } 140 | 141 | RestGenerationContext generationContext = createContextFor(uiContext); 142 | Set endpoints = generateEndpoints(generationContext); 143 | Project project = generationContext.getProject(); 144 | JavaSourceFacet javaSourceFacet = project.getFacet(JavaSourceFacet.class); 145 | List selection = new ArrayList<>(); 146 | 147 | for (JavaClassSource javaClass : endpoints) 148 | { 149 | selection.add(javaSourceFacet.saveJavaSource(javaClass)); 150 | } 151 | uiContext.setSelection(selection); 152 | return Results.success("Endpoint created"); 153 | } 154 | 155 | private Set generateEndpoints(RestGenerationContext generationContext) throws Exception 156 | { 157 | RestResourceGenerator selectedGenerator = generator.getValue(); 158 | Set classes = new HashSet<>(); 159 | for (JavaClassSource target : targets) 160 | { 161 | generationContext.setEntity(target); 162 | List artifacts = selectedGenerator.generateFrom(generationContext); 163 | classes.addAll(artifacts); 164 | } 165 | return classes; 166 | } 167 | 168 | private RestGenerationContext createContextFor(final UIContext context) 169 | { 170 | RestGenerationContext generationContext = new RestGenerationContext(); 171 | generationContext.setProject(getSelectedProject(context)); 172 | generationContext.setContentType(Arrays.asList(MediaType.APPLICATION_JSON)); 173 | generationContext.setPersistenceUnitName(persistenceUnit.getValue()); 174 | generationContext.setTargetPackageName(packageName.getValue()); 175 | generationContext.setInflector(inflector); 176 | return generationContext; 177 | } 178 | 179 | private Project getSelectedProject(UIContext context) 180 | { 181 | return Projects.getSelectedProject(projectFactory, context); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/ProcessTemplateStrategy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2014 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import static org.jboss.forge.addon.angularjs.AngularScaffoldProvider.SCAFFOLD_DIR; 10 | 11 | import java.io.IOException; 12 | import java.util.Map; 13 | 14 | import org.jboss.forge.addon.projects.Project; 15 | import org.jboss.forge.addon.projects.facets.WebResourcesFacet; 16 | import org.jboss.forge.addon.resource.Resource; 17 | import org.jboss.forge.addon.resource.ResourceFactory; 18 | import org.jboss.forge.addon.scaffold.util.ScaffoldUtil; 19 | import org.jboss.forge.addon.templates.Template; 20 | import org.jboss.forge.addon.templates.TemplateFactory; 21 | import org.jboss.forge.addon.templates.facets.TemplateFacet; 22 | import org.jboss.forge.addon.templates.freemarker.FreemarkerTemplate; 23 | 24 | /** 25 | * A {@link ProcessingStrategy} to process the contents of the {@link ScaffoldResource} from it's source on the 26 | * classpath or the project file system with the Freemarker Template engine. The produced output is then written to the 27 | * destination in the project's web resources. 28 | */ 29 | public class ProcessTemplateStrategy implements ProcessingStrategy 30 | { 31 | 32 | private final WebResourcesFacet web; 33 | 34 | private final ResourceFactory resourceFactory; 35 | 36 | private final Project project; 37 | 38 | private final TemplateFactory templateFactory; 39 | 40 | private final Map dataModel; 41 | 42 | public ProcessTemplateStrategy(WebResourcesFacet web, ResourceFactory resourceFactory, Project project, 43 | TemplateFactory templateFactory, Map dataModel) 44 | { 45 | this.web = web; 46 | this.resourceFactory = resourceFactory; 47 | this.project = project; 48 | this.templateFactory = templateFactory; 49 | this.dataModel = dataModel; 50 | } 51 | 52 | @Override 53 | public Resource execute(ScaffoldResource scaffoldResource) 54 | { 55 | Resource resource = resourceFactory.create(getClass().getResource( 56 | SCAFFOLD_DIR + scaffoldResource.getSource())); 57 | if (project.hasFacet(TemplateFacet.class)) 58 | { 59 | TemplateFacet templates = project.getFacet(TemplateFacet.class); 60 | Resource templateResource = templates.getResource(scaffoldResource.getSource()); 61 | if (templateResource.exists()) 62 | { 63 | resource = templateResource; 64 | } 65 | } 66 | 67 | Template template = templateFactory.create(resource, FreemarkerTemplate.class); 68 | String output = null; 69 | try 70 | { 71 | output = template.process(dataModel); 72 | } 73 | catch (IOException ioEx) 74 | { 75 | throw new IllegalStateException(ioEx); 76 | } 77 | return ScaffoldUtil.createOrOverwrite(web.getWebResource(scaffoldResource.getDestination()), output); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/ProcessingStrategy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2014 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import org.jboss.forge.addon.resource.Resource; 10 | 11 | /** 12 | * The base class of a strategy pattern used to implement how {@link ScaffoldResource}s should be processed. 13 | */ 14 | public interface ProcessingStrategy 15 | { 16 | public Resource execute(ScaffoldResource scaffoldResource); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/ResourcePathVisitor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import java.io.FileNotFoundException; 10 | 11 | import javax.ws.rs.Path; 12 | 13 | import org.jboss.forge.addon.parser.java.resources.JavaResource; 14 | import org.jboss.forge.addon.parser.java.resources.JavaResourceVisitor; 15 | import org.jboss.forge.addon.resource.visit.VisitContext; 16 | import org.jboss.forge.roaster.model.JavaClass; 17 | import org.jboss.forge.roaster.model.source.JavaSource; 18 | 19 | /** 20 | * A {@link JavaResourceVisitor} that inspects {@link JavaResource}s and verifies whether they are JAX-RS Resources that 21 | * employ the same conventions as the ones generated by the Forge REST plugin. 22 | */ 23 | class ResourcePathVisitor extends JavaResourceVisitor 24 | { 25 | 26 | private String entityName; 27 | private String path = null; 28 | private boolean found = false; 29 | 30 | public ResourcePathVisitor(String entityName) 31 | { 32 | this.entityName = entityName; 33 | } 34 | 35 | @Override 36 | public void visit(VisitContext context, JavaResource javaResource) 37 | { 38 | if (!found) 39 | { 40 | try 41 | { 42 | JavaSource javaSource = javaResource.getJavaType(); 43 | if (javaSource instanceof JavaClass) 44 | { 45 | JavaClass javaClass = (JavaClass) javaSource; 46 | if (javaClass.getName().equals(entityName + "Endpoint") && javaClass.hasAnnotation(Path.class)) 47 | { 48 | this.path = javaClass.getAnnotation(Path.class).getStringValue(); 49 | found = true; 50 | } 51 | } 52 | } 53 | catch (FileNotFoundException e) 54 | { 55 | throw new RuntimeException(e); 56 | } 57 | } 58 | } 59 | 60 | public String getPath() 61 | { 62 | return path; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/ResourceProvider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import static org.jboss.forge.addon.angularjs.AngularScaffoldProvider.SCAFFOLD_DIR; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * A collection of utility methods that return collections representing groups of {@link ScaffoldResource}s for further 16 | * processing. 17 | * 18 | */ 19 | public class ResourceProvider { 20 | 21 | static final String INDEX_HTML = "/index.html"; 22 | 23 | static final String LANDING_VIEW = "/views/landing.html"; 24 | 25 | static final String GLYPHICONS_EOT = "/fonts/glyphicons-halflings-regular.eot"; 26 | 27 | static final String GLYPHICONS_SVG = "/fonts/glyphicons-halflings-regular.svg"; 28 | 29 | static final String GLYPHICONS_TTF = "/fonts/glyphicons-halflings-regular.ttf"; 30 | 31 | static final String GLYPHICONS_WOFF = "/fonts/glyphicons-halflings-regular.woff"; 32 | 33 | static final String GLYPHICONS_WOFF2 = "/fonts/glyphicons-halflings-regular.woff2"; 34 | 35 | static final String FORGE_LOGO_PNG = "/img/forge-logo.png"; 36 | 37 | static final String ANGULAR_RESOURCE_JS = "/scripts/vendor/angular-resource.js"; 38 | 39 | static final String ANGULAR_ROUTE_JS = "/scripts/vendor/angular-route.js"; 40 | 41 | static final String ANGULAR_JS = "/scripts/vendor/angular.js"; 42 | 43 | static final String MODERNIZR_JS = "/scripts/vendor/modernizr-2.8.3.min.js"; 44 | 45 | static final String JQUERY_JS = "/scripts/vendor/jquery-2.1.1.js"; 46 | 47 | static final String BOOTSTRAP_JS = "/scripts/vendor/bootstrap.js"; 48 | 49 | static final String MAIN_CSS = "/styles/main.css"; 50 | 51 | static final String BOOTSTRAP_CSS = "/styles/bootstrap.css"; 52 | 53 | static final String BOOTSTRAP_THEME_CSS = "/styles/bootstrap-theme.css"; 54 | 55 | static final String OFFCANVAS_JS = "/scripts/offcanvas.js"; 56 | 57 | /** 58 | * Provides a list of {@link ScaffoldResource}s representing static files that are to be copied upon scaffolding setup. 59 | * 60 | * @param targetDir The target directory that serves as the root directory of the destination for the generated resources to 61 | * be copied to. 62 | * @param strategy The {@link ProcessingStrategy} to use for processing the static file. Usually this involves a strategy to copy 63 | * files from a source to destination. 64 | * @return A list of {@link ScaffoldResource}s representing static files that are to be copied upon scaffolding setup. 65 | */ 66 | public static List getStatics(String targetDir, ProcessingStrategy strategy) { 67 | List statics = new ArrayList<>(); 68 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + BOOTSTRAP_CSS, targetDir + BOOTSTRAP_CSS, strategy)); 69 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + MAIN_CSS, targetDir + MAIN_CSS, strategy)); 70 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + BOOTSTRAP_THEME_CSS, targetDir + BOOTSTRAP_THEME_CSS, strategy)); 71 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + OFFCANVAS_JS, targetDir + OFFCANVAS_JS, strategy)); 72 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + JQUERY_JS, targetDir + JQUERY_JS, strategy)); 73 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + BOOTSTRAP_JS, targetDir + BOOTSTRAP_JS, strategy)); 74 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + ANGULAR_JS, targetDir + ANGULAR_JS, strategy)); 75 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + ANGULAR_ROUTE_JS, targetDir + ANGULAR_ROUTE_JS, strategy)); 76 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + ANGULAR_RESOURCE_JS, targetDir + ANGULAR_RESOURCE_JS, strategy)); 77 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + MODERNIZR_JS, targetDir + MODERNIZR_JS, strategy)); 78 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + FORGE_LOGO_PNG, targetDir + FORGE_LOGO_PNG, strategy)); 79 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + GLYPHICONS_EOT, targetDir + GLYPHICONS_EOT, strategy)); 80 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + GLYPHICONS_SVG, targetDir + GLYPHICONS_SVG, strategy)); 81 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + GLYPHICONS_TTF, targetDir + GLYPHICONS_TTF, strategy)); 82 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + GLYPHICONS_WOFF, targetDir + GLYPHICONS_WOFF, strategy)); 83 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + GLYPHICONS_WOFF2, targetDir + GLYPHICONS_WOFF2, strategy)); 84 | statics.add(new ScaffoldResource(SCAFFOLD_DIR + LANDING_VIEW, targetDir + LANDING_VIEW, strategy)); 85 | return statics; 86 | } 87 | 88 | /** 89 | * Provides a list of {@link ScaffoldResource}s representing Freemarker templates that are to be processed only once for a 90 | * scaffold generation run. 91 | * 92 | * @param targetDir The target directory that serves as the root directory of the destination for the generated resources to 93 | * be written to. 94 | * @param strategy The {@link ProcessingStrategy} to use for processing the static file. Usually this involves a strategy to process 95 | * the file as a Freemarker template before copying it from a source to destination. 96 | * @return A list of {@link ScaffoldResource}s representing Freemarker templates that are to be processed only once for a 97 | * scaffold generation run. 98 | */ 99 | public static List getGlobalTemplates(String targetDir, ProcessingStrategy strategy) { 100 | List resources = new ArrayList<>(); 101 | resources.add(new ScaffoldResource("/index.html.ftl", targetDir+ INDEX_HTML, strategy)); 102 | resources.add(new ScaffoldResource("/app.html.ftl", targetDir + "/app.html", strategy)); 103 | resources.add(new ScaffoldResource("/scripts/app.js.ftl", targetDir + "/scripts/app.js", strategy)); 104 | resources.add(new ScaffoldResource("/scripts/directives/datepicker.js.ftl", targetDir 105 | + "/scripts/directives/datepicker.js", strategy)); 106 | resources.add(new ScaffoldResource("/scripts/directives/timepicker.js.ftl", targetDir 107 | + "/scripts/directives/timepicker.js", strategy)); 108 | resources.add(new ScaffoldResource("/scripts/directives/datetimepicker.js.ftl", targetDir 109 | + "/scripts/directives/datetimepicker.js", strategy)); 110 | resources.add(new ScaffoldResource("/scripts/services/flash.js.ftl", targetDir 111 | + "/scripts/services/flash.js", strategy)); 112 | resources.add(new ScaffoldResource("/scripts/services/locationParser.js.ftl", targetDir 113 | + "/scripts/services/locationParser.js", strategy)); 114 | resources.add(new ScaffoldResource("/scripts/filters/genericSearchFilter.js.ftl", targetDir 115 | + "/scripts/filters/genericSearchFilter.js", strategy)); 116 | resources.add(new ScaffoldResource("/scripts/filters/startFromFilter.js.ftl", targetDir 117 | + "/scripts/filters/startFromFilter.js", strategy)); 118 | resources.add(new ScaffoldResource("/scripts/controllers/flashController.js.ftl", targetDir 119 | + "/scripts/controllers/flashController.js", strategy)); 120 | return resources; 121 | } 122 | 123 | /** 124 | * Provides a list of {@link ScaffoldResource}s representing Freemarker templates that are to be processed for every entity 125 | * during a scaffold generation run. 126 | * 127 | * @param targetDir The target directory that serves as the root directory of the destination for the generated resources to 128 | * be written to. 129 | * @param entityName The name of the JPA entity 130 | * @param strategy The {@link ProcessingStrategy} to use for processing the static file. Usually this involves a strategy to process 131 | * the file as a Freemarker template before copying it from a source to destination. 132 | * @return A list of {@link ScaffoldResource}s representing Freemarker templates that are to be processed for every entity 133 | * during a scaffold generation run. 134 | */ 135 | public static List getEntityTemplates(String targetDir, String entityName, ProcessingStrategy strategy) { 136 | List resources = new ArrayList<>(); 137 | resources.add(new ScaffoldResource("/scripts/services/entityFactory.js.ftl", targetDir + "/scripts/services/" 138 | + entityName + "Factory.js", strategy)); 139 | resources.add(new ScaffoldResource("/scripts/controllers/newEntityController.js.ftl", targetDir 140 | + "/scripts/controllers/new" + entityName + "Controller.js", strategy)); 141 | resources.add(new ScaffoldResource("/scripts/controllers/searchEntityController.js.ftl", targetDir 142 | + "/scripts/controllers/search" + entityName + "Controller.js", strategy)); 143 | resources.add(new ScaffoldResource("/scripts/controllers/editEntityController.js.ftl", targetDir 144 | + "/scripts/controllers/edit" + entityName + "Controller.js", strategy)); 145 | return resources; 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/ScaffoldResource.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2014 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import org.jboss.forge.addon.resource.Resource; 10 | import org.jboss.forge.addon.scaffold.util.ScaffoldUtil; 11 | 12 | /** 13 | * An abstraction of a resource used by the Scaffold provider. The scaffold resources will specify the source from where 14 | * they can be read, and the destination to which they are to be copied to, so that this information is available to 15 | * utlity classes like the {@link ScaffoldUtil} class. 16 | * 17 | * This abstraction is meant to reduce the verbosity involved in using the {@link ScaffoldUtil} class, since resource 18 | * paths can now be stored and passed around in collections, and iterated through. 19 | * 20 | */ 21 | public class ScaffoldResource 22 | { 23 | 24 | private final String source; 25 | private final String destination; 26 | private final ProcessingStrategy strategy; 27 | 28 | public ScaffoldResource(String source, String destination, ProcessingStrategy strategy) 29 | { 30 | this.source = source; 31 | this.destination = destination; 32 | this.strategy = strategy; 33 | } 34 | 35 | public String getSource() 36 | { 37 | return source; 38 | } 39 | 40 | public String getDestination() 41 | { 42 | return destination; 43 | } 44 | 45 | public Resource generate() 46 | { 47 | return strategy.execute(this); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/ScaffoldableEntitySelectionWizard.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2014 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | import javax.inject.Inject; 14 | import javax.persistence.Entity; 15 | import javax.persistence.Id; 16 | 17 | import org.jboss.forge.addon.angularjs.util.RestResourceTypeVisitor; 18 | import org.jboss.forge.addon.javaee.jpa.JPAFacet; 19 | import org.jboss.forge.addon.parser.java.facets.JavaSourceFacet; 20 | import org.jboss.forge.addon.projects.Project; 21 | import org.jboss.forge.addon.projects.ProjectFactory; 22 | import org.jboss.forge.addon.projects.Projects; 23 | import org.jboss.forge.addon.resource.Resource; 24 | import org.jboss.forge.addon.scaffold.spi.ResourceCollection; 25 | import org.jboss.forge.addon.text.Inflector; 26 | import org.jboss.forge.addon.ui.context.UIBuilder; 27 | import org.jboss.forge.addon.ui.context.UIContext; 28 | import org.jboss.forge.addon.ui.context.UIExecutionContext; 29 | import org.jboss.forge.addon.ui.context.UINavigationContext; 30 | import org.jboss.forge.addon.ui.context.UIValidationContext; 31 | import org.jboss.forge.addon.ui.input.UIInput; 32 | import org.jboss.forge.addon.ui.input.UISelectMany; 33 | import org.jboss.forge.addon.ui.metadata.UICommandMetadata; 34 | import org.jboss.forge.addon.ui.metadata.WithAttributes; 35 | import org.jboss.forge.addon.ui.result.NavigationResult; 36 | import org.jboss.forge.addon.ui.result.Result; 37 | import org.jboss.forge.addon.ui.result.Results; 38 | import org.jboss.forge.addon.ui.util.Metadata; 39 | import org.jboss.forge.addon.ui.wizard.UIWizardStep; 40 | import org.jboss.forge.roaster.model.Annotation; 41 | import org.jboss.forge.roaster.model.JavaClass; 42 | import org.jboss.forge.roaster.model.Member; 43 | import org.jboss.forge.roaster.model.source.JavaClassSource; 44 | import org.jboss.forge.roaster.model.util.Strings; 45 | 46 | public class ScaffoldableEntitySelectionWizard implements UIWizardStep 47 | { 48 | 49 | @Inject 50 | @WithAttributes(label = "Targets", required = true) 51 | private UISelectMany targets; 52 | 53 | @Inject 54 | @WithAttributes(label = "Generate REST resources", required = false, description = "If enabled, REST resources for the selected JPA entities will be generated", defaultValue = "true") 55 | private UIInput generateRestResources; 56 | 57 | @Inject 58 | private ProjectFactory projectFactory; 59 | 60 | @Inject 61 | private Inflector inflector; 62 | 63 | @Override 64 | public NavigationResult next(UINavigationContext context) throws Exception 65 | { 66 | UIContext uiContext = context.getUIContext(); 67 | Map attributeMap = uiContext.getAttributeMap(); 68 | ResourceCollection resourceCollection = new ResourceCollection(); 69 | if (targets.getValue() != null) 70 | { 71 | for (JavaClassSource klass : targets.getValue()) 72 | { 73 | Project project = getSelectedProject(uiContext); 74 | JavaSourceFacet javaSource = project.getFacet(JavaSourceFacet.class); 75 | Resource resource = javaSource.getJavaResource(klass); 76 | if (resource != null) 77 | { 78 | resourceCollection.addToCollection(resource); 79 | } 80 | } 81 | } 82 | 83 | attributeMap.put(ResourceCollection.class, resourceCollection); 84 | Boolean shouldGenerateRestResources = generateRestResources.getValue(); 85 | if (shouldGenerateRestResources.equals(Boolean.TRUE)) 86 | { 87 | return Results.navigateTo(JSONRestResourceFromEntityCommand.class); 88 | } 89 | return null; 90 | } 91 | 92 | @Override 93 | public UICommandMetadata getMetadata(UIContext context) 94 | { 95 | return Metadata.forCommand(getClass()).name("Select JPA entities") 96 | .description("Select the JPA entities to be used for scaffolding."); 97 | } 98 | 99 | @Override 100 | public boolean isEnabled(UIContext context) 101 | { 102 | return true; 103 | } 104 | 105 | @Override 106 | public void initializeUI(UIBuilder builder) throws Exception 107 | { 108 | UIContext uiContext = builder.getUIContext(); 109 | Project project = getSelectedProject(uiContext); 110 | 111 | JPAFacet persistenceFacet = project.getFacet(JPAFacet.class); 112 | List allEntities = persistenceFacet.getAllEntities(); 113 | List supportedEntities = new ArrayList<>(); 114 | for (JavaClassSource entity : allEntities) 115 | { 116 | for (Member member : entity.getMembers()) 117 | { 118 | // FORGE-823 Only add entities with @Id as valid entities for REST resource generation. 119 | // Composite keys are not yet supported. 120 | if (member.hasAnnotation(Id.class)) 121 | { 122 | supportedEntities.add(entity); 123 | } 124 | } 125 | } 126 | targets.setValueChoices(supportedEntities); 127 | targets.setItemLabelConverter(JavaClassSource::getQualifiedName); 128 | builder.add(targets).add(generateRestResources); 129 | } 130 | 131 | @Override 132 | public Result execute(UIExecutionContext context) throws Exception 133 | { 134 | return null; 135 | } 136 | 137 | @Override 138 | public void validate(UIValidationContext context) 139 | { 140 | // Verify if the selected JPA entities have corresponding JAX-RS resources. 141 | // If yes, then raise warnings if they will be overwritten 142 | Boolean shouldGenerateRestResources = generateRestResources.getValue(); 143 | List entitiesWithRestResources = new ArrayList<>(); 144 | if (shouldGenerateRestResources.equals(Boolean.TRUE) && targets.getValue() != null) 145 | { 146 | for (JavaClassSource klass : targets.getValue()) 147 | { 148 | Project project = getSelectedProject(context.getUIContext()); 149 | JavaSourceFacet javaSource = project.getFacet(JavaSourceFacet.class); 150 | RestResourceTypeVisitor restTypeVisitor = new RestResourceTypeVisitor(); 151 | String entityTable = getEntityTable(klass); 152 | String proposedResourcePath = "/" + inflector.pluralize(entityTable.toLowerCase()); 153 | restTypeVisitor.setProposedPath(proposedResourcePath); 154 | javaSource.visitJavaSources(restTypeVisitor); 155 | if (restTypeVisitor.isFound()) 156 | { 157 | entitiesWithRestResources.add(klass.getQualifiedName()); 158 | } 159 | } 160 | } 161 | if (!entitiesWithRestResources.isEmpty()) 162 | { 163 | context.addValidationWarning(targets, "Some of the selected entities " + entitiesWithRestResources.toString() 164 | + " already have associated REST resources that will be overwritten."); 165 | } 166 | } 167 | 168 | public static String getEntityTable(final JavaClass entity) 169 | { 170 | String table = entity.getName(); 171 | if (entity.hasAnnotation(Entity.class)) 172 | { 173 | Annotation a = entity.getAnnotation(Entity.class); 174 | if (!Strings.isNullOrEmpty(a.getStringValue("name"))) 175 | { 176 | table = a.getStringValue("name"); 177 | } 178 | else if (!Strings.isNullOrEmpty(a.getStringValue())) 179 | { 180 | table = a.getStringValue(); 181 | } 182 | } 183 | return table; 184 | } 185 | 186 | private Project getSelectedProject(UIContext uiContext) 187 | { 188 | return Projects.getSelectedProject(projectFactory, uiContext); 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/SearchTemplateStrategy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import static org.jboss.forge.addon.angularjs.AngularScaffoldProvider.SCAFFOLD_DIR; 10 | 11 | import java.io.IOException; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | import org.jboss.forge.addon.projects.Project; 16 | import org.jboss.forge.addon.projects.facets.WebResourcesFacet; 17 | import org.jboss.forge.addon.resource.Resource; 18 | import org.jboss.forge.addon.resource.ResourceFactory; 19 | import org.jboss.forge.addon.templates.Template; 20 | import org.jboss.forge.addon.templates.TemplateFactory; 21 | import org.jboss.forge.addon.templates.facets.TemplateFacet; 22 | import org.jboss.forge.addon.templates.freemarker.FreemarkerTemplate; 23 | 24 | /** 25 | * A strategy for generating the search page with included files. 26 | */ 27 | public class SearchTemplateStrategy implements ProcessingStrategy 28 | { 29 | private static final String SEARCH_FORM_INPUT = "/views/includes/searchFormInput.html.ftl"; 30 | private static final String SEARCH_RESULTS = "/views/includes/searchResults.html.ftl"; 31 | private static final String SEARCH_RESULTS_PAGINATOR = "/views/includes/searchResultsPaginator.html.ftl"; 32 | 33 | private final WebResourcesFacet web; 34 | 35 | private final Project project; 36 | 37 | private final Map dataModel; 38 | 39 | private final ResourceFactory resourceFactory; 40 | 41 | private final TemplateFactory templateFactory; 42 | 43 | public SearchTemplateStrategy(WebResourcesFacet web, ResourceFactory resourceFactory, Project project, 44 | TemplateFactory templateFactory, Map dataModel) 45 | { 46 | this.web = web; 47 | this.resourceFactory = resourceFactory; 48 | this.project = project; 49 | this.templateFactory = templateFactory; 50 | this.dataModel = dataModel; 51 | } 52 | 53 | @SuppressWarnings("unchecked") 54 | @Override 55 | public Resource execute(ScaffoldResource scaffoldResource) 56 | { 57 | List> properties = (List>) dataModel.get("properties"); 58 | StringBuilder searchFormProperties = new StringBuilder(); 59 | for (Map property : properties) 60 | { 61 | dataModel.put("property", property); 62 | Include includeFile = new Include(SEARCH_FORM_INPUT); 63 | String output = includeFile.processInclude(dataModel); 64 | searchFormProperties.append(output).append('\n'); 65 | } 66 | Include searchResultsInclude = new Include(SEARCH_RESULTS); 67 | Include searchResultsPaginatorInclude = new Include(SEARCH_RESULTS_PAGINATOR); 68 | String searchResults = searchResultsInclude.processInclude(dataModel); 69 | String searchResultsPaginator = searchResultsPaginatorInclude.processInclude(dataModel); 70 | dataModel.put("searchFormProperties", searchFormProperties.toString()); 71 | dataModel.put("searchResults", searchResults); 72 | dataModel.put("searchResultsPaginator", searchResultsPaginator); 73 | ProcessTemplateStrategy strategy = new ProcessTemplateStrategy(web, resourceFactory, project, 74 | templateFactory, dataModel); 75 | return strategy.execute(scaffoldResource); 76 | } 77 | 78 | class Include 79 | { 80 | private final String source; 81 | 82 | Include(String source) 83 | { 84 | this.source = source; 85 | } 86 | 87 | private String processInclude(Map dataModel) 88 | { 89 | Resource resource = resourceFactory.create(getClass().getResource( 90 | SCAFFOLD_DIR + source)); 91 | if (project.hasFacet(TemplateFacet.class)) 92 | { 93 | TemplateFacet templates = project.getFacet(TemplateFacet.class); 94 | Resource templateResource = templates.getResource(source); 95 | if (templateResource.exists()) 96 | { 97 | resource = templateResource; 98 | } 99 | } 100 | 101 | Template template = templateFactory.create(resource, FreemarkerTemplate.class); 102 | String output = null; 103 | try 104 | { 105 | output = template.process(dataModel); 106 | } 107 | catch (IOException ioEx) 108 | { 109 | throw new IllegalStateException(ioEx); 110 | } 111 | return output; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/jboss/forge/addon/angularjs/util/RestResourceTypeVisitor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs.util; 8 | 9 | import org.jboss.forge.addon.parser.java.resources.JavaResource; 10 | import org.jboss.forge.addon.parser.java.resources.JavaResourceVisitor; 11 | import org.jboss.forge.addon.resource.visit.VisitContext; 12 | import org.jboss.forge.roaster.model.source.JavaSource; 13 | 14 | import java.io.FileNotFoundException; 15 | 16 | public class RestResourceTypeVisitor extends JavaResourceVisitor 17 | { 18 | private String proposedPath; 19 | private boolean found; 20 | private JavaSource javaSource; 21 | 22 | public void setProposedPath(String proposedPath) 23 | { 24 | this.proposedPath = proposedPath; 25 | } 26 | 27 | public String getQualifiedClassNameForMatch() 28 | { 29 | if (javaSource != null) 30 | { 31 | return javaSource.getQualifiedName(); 32 | } 33 | return null; 34 | } 35 | 36 | public boolean isFound() 37 | { 38 | return found; 39 | } 40 | 41 | public void setFound(boolean found) 42 | { 43 | this.found = found; 44 | } 45 | 46 | @Override 47 | public void visit(VisitContext context, JavaResource javaResource) 48 | { 49 | if (!found) 50 | { 51 | try 52 | { 53 | JavaSource javaType = javaResource.getJavaType(); 54 | if (javaType.getAnnotation("javax.ws.rs.Path") != null) 55 | { 56 | String path = javaType.getAnnotation("javax.ws.rs.Path") 57 | .getStringValue(); 58 | String absolutePath = path.endsWith("/") ? path.substring(0, path.lastIndexOf('/')) : path; 59 | if (absolutePath.equals(proposedPath)) 60 | { 61 | javaSource = javaType; 62 | found = true; 63 | } 64 | } 65 | } 66 | catch (FileNotFoundException e) 67 | { 68 | throw new RuntimeException(e); 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/app.html.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ${projectTitle} 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 27 | 28 |
29 |
30 | 31 | 43 | 44 |
45 | 49 |
50 |
51 |
52 |
53 |
54 |
55 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | <#list entityNames as entityName> 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forge/angularjs-addon/d16be8fba98db9b4fe72bfef0db8616b4e19fd37/src/main/resources/org/jboss/forge/addon/angularjs/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forge/angularjs-addon/d16be8fba98db9b4fe72bfef0db8616b4e19fd37/src/main/resources/org/jboss/forge/addon/angularjs/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forge/angularjs-addon/d16be8fba98db9b4fe72bfef0db8616b4e19fd37/src/main/resources/org/jboss/forge/addon/angularjs/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forge/angularjs-addon/d16be8fba98db9b4fe72bfef0db8616b4e19fd37/src/main/resources/org/jboss/forge/addon/angularjs/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/img/forge-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forge/angularjs-addon/d16be8fba98db9b4fe72bfef0db8616b4e19fd37/src/main/resources/org/jboss/forge/addon/angularjs/img/forge-logo.png -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/index.html.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/app.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign angularApp = "${projectId}"> 2 | 'use strict'; 3 | 4 | angular.module('${angularApp}',['ngRoute','ngResource']) 5 | .config(['$routeProvider', function($routeProvider) { 6 | $routeProvider 7 | .when('/',{templateUrl:'views/landing.html',controller:'LandingPageController'}) 8 | <#list entityNames as entityName> 9 | <#assign 10 | searchEntityController = "Search${entityName}Controller" 11 | newEntityController = "New${entityName}Controller" 12 | editEntityController = "Edit${entityName}Controller" 13 | entityIdJsVar = "${entityName}Id" 14 | entityRoute = "/${pluralizedEntityNames[entityName_index]}" 15 | entityPartialsLocation = "views/${entityName}"> 16 | .when('${entityRoute}',{templateUrl:'${entityPartialsLocation}/search.html',controller:'${searchEntityController}'}) 17 | .when('${entityRoute}/new',{templateUrl:'${entityPartialsLocation}/detail.html',controller:'${newEntityController}'}) 18 | .when('${entityRoute}/edit/:${entityIdJsVar}',{templateUrl:'${entityPartialsLocation}/detail.html',controller:'${editEntityController}'}) 19 | 20 | .otherwise({ 21 | redirectTo: '/' 22 | }); 23 | }]) 24 | .controller('LandingPageController', function LandingPageController() { 25 | }) 26 | .controller('NavController', function NavController($scope, $location) { 27 | $scope.matchesRoute = function(route) { 28 | var path = $location.path(); 29 | return (path === ("/" + route) || path.indexOf("/" + route + "/") == 0); 30 | }; 31 | }); 32 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/controllers/editEntityController.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign 2 | angularApp = "${projectId}" 3 | angularController = "Edit${entityName}Controller" 4 | angularResource = "${entityName}Resource" 5 | entityIdJsVar = "${entityName}Id" 6 | model = "$scope.${entityName?uncap_first}" 7 | entityText = "${entityName?uncap_first}" 8 | entityRoute = "/${pluralizedEntityName}" 9 | > 10 | 11 | <#assign relatedResources> 12 | <#list properties as property> 13 | <#if (property["many-to-one"]!) == "true" || (property["one-to-one"]!) == "true" || (property["n-to-many"]!) == "true"> 14 | , ${property.simpleType}Resource<#t> 15 | 16 | 17 | 18 | 19 | angular.module('${angularApp}').controller('${angularController}', function($scope, $routeParams, $location, flash, ${angularResource} ${relatedResources}) { 20 | var self = this; 21 | $scope.disabled = false; 22 | $scope.$location = $location; 23 | 24 | $scope.get = function() { 25 | var successCallback = function(data){ 26 | self.original = data; 27 | ${model} = new ${angularResource}(self.original); 28 | <#list properties as property> 29 | <#assign 30 | relatedResource = "${property.simpleType!}Resource" 31 | relatedCollection ="$scope.${property.identifier}SelectionList" 32 | modelProperty = "${model}.${property.name}" 33 | originalProperty = "self.original.${property.name}" 34 | reverseId = property["reverse-primary-key"]!> 35 | <#if (property["many-to-one"]!) == "true" || (property["one-to-one"]!) == "true"> 36 | ${relatedResource}.queryAll(function(items) { 37 | ${relatedCollection} = $.map(items, function(item) { 38 | var wrappedObject = { 39 | ${reverseId} : item.${reverseId} 40 | }; 41 | var labelObject = { 42 | value : item.${reverseId}, 43 | text : item.${property.optionLabel} 44 | }; 45 | if(${modelProperty} && item.${reverseId} == ${modelProperty}.${reverseId}) { 46 | $scope.${property.identifier}Selection = labelObject; 47 | ${modelProperty} = wrappedObject; 48 | ${originalProperty} = ${modelProperty}; 49 | } 50 | return labelObject; 51 | }); 52 | }); 53 | <#elseif (property["n-to-many"]!) == "true"> 54 | ${relatedResource}.queryAll(function(items) { 55 | ${relatedCollection} = $.map(items, function(item) { 56 | var wrappedObject = { 57 | ${reverseId} : item.${reverseId} 58 | }; 59 | var labelObject = { 60 | value : item.${reverseId}, 61 | text : item.${property.optionLabel} 62 | }; 63 | if(${modelProperty}){ 64 | $.each(${modelProperty}, function(idx, element) { 65 | if(item.${reverseId} == element.${reverseId}) { 66 | $scope.${property.name}Selection.push(labelObject); 67 | ${modelProperty}.push(wrappedObject); 68 | } 69 | }); 70 | ${originalProperty} = ${modelProperty}; 71 | } 72 | return labelObject; 73 | }); 74 | }); 75 | 76 | 77 | }; 78 | var errorCallback = function() { 79 | flash.setMessage({'type': 'error', 'text': 'The ${entityText} could not be found.'}); 80 | $location.path("${entityRoute}"); 81 | }; 82 | ${angularResource}.get({${entityIdJsVar}:$routeParams.${entityIdJsVar}}, successCallback, errorCallback); 83 | }; 84 | 85 | $scope.isClean = function() { 86 | return angular.equals(self.original, ${model}); 87 | }; 88 | 89 | $scope.save = function() { 90 | var successCallback = function(){ 91 | flash.setMessage({'type':'success','text':'The ${entityText} was updated successfully.'}, true); 92 | $scope.get(); 93 | }; 94 | var errorCallback = function(response) { 95 | if(response && response.data && response.data.message) { 96 | flash.setMessage({'type': 'error', 'text': response.data.message}, true); 97 | } else { 98 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 99 | } 100 | }; 101 | ${model}.$update(successCallback, errorCallback); 102 | }; 103 | 104 | $scope.cancel = function() { 105 | $location.path("${entityRoute}"); 106 | }; 107 | 108 | $scope.remove = function() { 109 | var successCallback = function() { 110 | flash.setMessage({'type': 'error', 'text': 'The ${entityText} was deleted.'}); 111 | $location.path("${entityRoute}"); 112 | }; 113 | var errorCallback = function(response) { 114 | if(response && response.data && response.data.message) { 115 | flash.setMessage({'type': 'error', 'text': response.data.message}, true); 116 | } else { 117 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 118 | } 119 | }; 120 | ${model}.$remove(successCallback, errorCallback); 121 | }; 122 | 123 | <#list properties as property> 124 | <#if (property["many-to-one"]!) == "true" || (property["one-to-one"]!) == "true"> 125 | <#assign 126 | modelProperty = "${model}.${property.name}" 127 | selectedItem="${property.identifier}Selection" 128 | reverseId = property["reverse-primary-key"]!> 129 | $scope.$watch("${selectedItem}", function(selection) { 130 | if (typeof selection != 'undefined') { 131 | ${modelProperty} = {}; 132 | ${modelProperty}.${reverseId} = selection.value; 133 | } 134 | }); 135 | <#elseif (property["n-to-many"]!"false") == "true"> 136 | <#assign 137 | modelProperty = "${model}.${property.name}" 138 | selectedItem="${property.identifier}Selection" 139 | reverseId = property["reverse-primary-key"]!> 140 | $scope.${selectedItem} = $scope.${selectedItem} || []; 141 | $scope.$watch("${selectedItem}", function(selection) { 142 | if (typeof selection != 'undefined' && ${model}) { 143 | ${modelProperty} = []; 144 | $.each(selection, function(idx,selectedItem) { 145 | var collectionItem = {}; 146 | collectionItem.${reverseId} = selectedItem.value; 147 | ${modelProperty}.push(collectionItem); 148 | }); 149 | } 150 | }); 151 | <#elseif property.type == "boolean"> 152 | <#assign 153 | lookupCollection = "$scope.${property.identifier}List"> 154 | ${lookupCollection} = [ 155 | "true", 156 | "false" 157 | ]; 158 | <#elseif property["lookup"]??> 159 | <#assign 160 | lookupCollection = "$scope.${property.identifier}List"> 161 | ${lookupCollection} = [ 162 | <#list property["lookup"]?split(",") as option> 163 | "${option}"<#if option_has_next>, 164 | 165 | ]; 166 | 167 | 168 | 169 | $scope.get(); 170 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/controllers/flashController.js.ftl: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('${projectId}').controller('FlashController', ['$scope','flash', function ($scope, flash) { 4 | $scope.flash = flash; 5 | $scope.showAlert = false; 6 | 7 | $scope.$watch('flash.getMessage()', function(newVal) { 8 | var message = newVal; 9 | if(message && message.text) { 10 | $scope.showAlert = message.text.length > 0; 11 | } else { 12 | $scope.showAlert = false; 13 | } 14 | }); 15 | 16 | $scope.hideAlert = function() { 17 | $scope.showAlert = false; 18 | } 19 | }]); 20 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/controllers/newEntityController.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign 2 | angularApp = "${projectId}" 3 | angularController = "New${entityName}Controller" 4 | angularResource = "${entityName}Resource" 5 | model = "$scope.${entityName?uncap_first}" 6 | entityText = "${entityName?uncap_first}" 7 | entityRoute = "/${pluralizedEntityName}" 8 | > 9 | <#--An assignment expression that 'captures' all the related resources --> 10 | <#assign relatedResources> 11 | <#list properties as property> 12 | <#if (property["many-to-one"]!) == "true" || (property["one-to-one"]!) == "true" || (property["n-to-many"]!) == "true"> 13 | , ${property.simpleType}Resource<#t> 14 | 15 | 16 | 17 | 18 | angular.module('${angularApp}').controller('${angularController}', function ($scope, $location, locationParser, flash, ${angularResource} ${relatedResources}) { 19 | $scope.disabled = false; 20 | $scope.$location = $location; 21 | ${model} = ${model} || {}; 22 | 23 | <#list properties as property> 24 | <#if (property["many-to-one"]!) == "true" || (property["one-to-one"]!) == "true"> 25 | <#assign 26 | relatedResource="${property.simpleType}Resource" 27 | relatedCollection="$scope.${property.identifier}List" 28 | modelProperty = "${model}.${property.name}" 29 | selectCollection="$scope.${property.identifier}SelectionList" 30 | selectedItem="${property.identifier}Selection" 31 | reverseId = property["reverse-primary-key"]!> 32 | ${relatedCollection} = ${relatedResource}.queryAll(function(items){ 33 | ${selectCollection} = $.map(items, function(item) { 34 | return ( { 35 | value : item.${reverseId}, 36 | text : item.${property.optionLabel} 37 | }); 38 | }); 39 | }); 40 | $scope.$watch("${selectedItem}", function(selection) { 41 | if ( typeof selection != 'undefined') { 42 | ${modelProperty} = {}; 43 | ${modelProperty}.${reverseId} = selection.value; 44 | } 45 | }); 46 | 47 | <#elseif (property["n-to-many"]!) == "true"> 48 | <#assign 49 | relatedResource = "${property.simpleType}Resource" 50 | relatedCollection = "$scope.${property.identifier}List" 51 | modelProperty = "${model}.${property.name}" 52 | selectCollection="$scope.${property.identifier}SelectionList" 53 | selectedItem="${property.identifier}Selection" 54 | reverseId = property["reverse-primary-key"]!> 55 | ${relatedCollection} = ${relatedResource}.queryAll(function(items){ 56 | ${selectCollection} = $.map(items, function(item) { 57 | return ( { 58 | value : item.${reverseId}, 59 | text : item.${property.optionLabel} 60 | }); 61 | }); 62 | }); 63 | $scope.$watch("${selectedItem}", function(selection) { 64 | if (typeof selection != 'undefined') { 65 | ${modelProperty} = []; 66 | $.each(selection, function(idx,selectedItem) { 67 | var collectionItem = {}; 68 | collectionItem.${reverseId} = selectedItem.value; 69 | ${modelProperty}.push(collectionItem); 70 | }); 71 | } 72 | }); 73 | 74 | <#elseif property.type == "boolean"> 75 | <#assign 76 | lookupCollection = "$scope.${property.identifier}List"> 77 | ${lookupCollection} = [ 78 | "true", 79 | "false" 80 | ]; 81 | 82 | <#elseif property["lookup"]??> 83 | <#assign 84 | lookupCollection ="$scope.${property.identifier}List"> 85 | ${lookupCollection} = [ 86 | <#list property["lookup"]?split(",") as option> 87 | "${option}"<#if option_has_next>, 88 | 89 | ]; 90 | 91 | 92 | 93 | 94 | $scope.save = function() { 95 | var successCallback = function(data,responseHeaders){ 96 | var id = locationParser(responseHeaders); 97 | flash.setMessage({'type':'success','text':'The ${entityText} was created successfully.'}); 98 | $location.path('${entityRoute}'); 99 | }; 100 | var errorCallback = function(response) { 101 | if(response && response.data) { 102 | flash.setMessage({'type': 'error', 'text': response.data.message || response.data}, true); 103 | } else { 104 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 105 | } 106 | }; 107 | ${angularResource}.save(${model}, successCallback, errorCallback); 108 | }; 109 | 110 | $scope.cancel = function() { 111 | $location.path("${entityRoute}"); 112 | }; 113 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/controllers/searchEntityController.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign 2 | angularApp = "${projectId}" 3 | angularController = "Search${entityName}Controller" 4 | angularResource = "${entityName}Resource" 5 | model = "$scope.${entityName?uncap_first}" 6 | entityRoute = "/${pluralizedEntityName}" 7 | > 8 | 9 | <#assign relatedResources> 10 | <#list properties as property> 11 | <#if (property["many-to-one"]!) == "true" || (property["one-to-one"]!) == "true" || (property["n-to-many"]!) == "true"> 12 | , ${property.simpleType}Resource<#t> 13 | 14 | 15 | 16 | 17 | angular.module('${angularApp}').controller('${angularController}', function($scope, $http, $filter, ${angularResource} ${relatedResources}) { 18 | 19 | $scope.search={}; 20 | $scope.currentPage = 0; 21 | $scope.pageSize= 10; 22 | $scope.searchResults = []; 23 | $scope.filteredResults = []; 24 | $scope.pageRange = []; 25 | $scope.numberOfPages = function() { 26 | var result = Math.ceil($scope.filteredResults.length/$scope.pageSize); 27 | var max = (result == 0) ? 1 : result; 28 | $scope.pageRange = []; 29 | for(var ctr=0;ctr 35 | <#if (property["many-to-one"]!) == "true" || (property["one-to-one"]!) == "true"> 36 | <#assign 37 | relatedCollection = "$scope.${property.identifier}List" 38 | relatedResource = "${property.simpleType}Resource"> 39 | ${relatedCollection} = ${relatedResource}.queryAll(); 40 | <#elseif property.type == "boolean"> 41 | <#assign 42 | lookupCollection = "$scope.${property.identifier}List"> 43 | ${lookupCollection} = [ 44 | "true", 45 | "false" 46 | ]; 47 | <#elseif property["lookup"]??> 48 | <#assign 49 | lookupCollection = "$scope.${property.identifier}List"> 50 | ${lookupCollection} = [ 51 | <#list property["lookup"]?split(",") as option> 52 | "${option}"<#if option_has_next>, 53 | 54 | ]; 55 | 56 | 57 | 58 | $scope.performSearch = function() { 59 | $scope.searchResults = ${angularResource}.queryAll(function(){ 60 | $scope.filteredResults = $filter('searchFilter')($scope.searchResults, $scope); 61 | $scope.currentPage = 0; 62 | }); 63 | }; 64 | 65 | $scope.previous = function() { 66 | if($scope.currentPage > 0) { 67 | $scope.currentPage--; 68 | } 69 | }; 70 | 71 | $scope.next = function() { 72 | if($scope.currentPage < ($scope.numberOfPages() - 1) ) { 73 | $scope.currentPage++; 74 | } 75 | }; 76 | 77 | $scope.setPage = function(n) { 78 | $scope.currentPage = n; 79 | }; 80 | 81 | $scope.performSearch(); 82 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/directives/datepicker.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign angularApp = "${projectId}"> 2 | 'use strict'; 3 | 4 | var DATE_REGEX = /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])$/; 5 | angular.module('${angularApp}').directive('date', function($parse, dateFilter) { 6 | return { 7 | restrict : "E", 8 | replace : true, 9 | transclude : false, 10 | require: '?ngModel', 11 | compile : function(element, attrs) { 12 | var modelAccessor = $parse(attrs.ngModel); 13 | 14 | var isRequired = ""; 15 | if(attrs.required) { 16 | isRequired = "required"; 17 | } 18 | var html = ""; 19 | 20 | var $newElem = $(html); 21 | element.replaceWith($newElem); 22 | 23 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 24 | if(!ngModelCtrl) return; 25 | 26 | var dateParser = function(value) { 27 | var date; 28 | if(value) { 29 | date = new Date(Date.parse(value)); 30 | } else { 31 | date = value; 32 | } 33 | return date; 34 | } 35 | var dateFormatter = function(value) { 36 | if(value) { 37 | var date = dateFilter(value,"yyyy-MM-dd"); 38 | return date; 39 | } 40 | return; 41 | } 42 | 43 | ngModelCtrl.$parsers.unshift(dateParser); 44 | ngModelCtrl.$formatters.unshift(dateFormatter); 45 | 46 | element.bind("blur keyup change", function() { 47 | scope.$apply(function() { 48 | ngModelCtrl.$setViewValue(element.val()); 49 | }); 50 | }); 51 | 52 | ngModelCtrl.$render = function() { 53 | element.val(ngModelCtrl.$viewValue); 54 | } 55 | } 56 | 57 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 58 | if(!ngModelCtrl) return; 59 | 60 | var dateParser = function(value) { 61 | if(value) { 62 | var d = value.match(DATE_REGEX); 63 | if(d) { 64 | var formattedDate = d[1] + "-" + d[2] + "-" + d[3]; 65 | var date = new Date(Date.parse(formattedDate)); 66 | ngModelCtrl.$setValidity("dateFormat", true); 67 | return date; 68 | } else { 69 | ngModelCtrl.$setValidity("dateFormat", false); 70 | return; 71 | } 72 | } 73 | return; 74 | } 75 | var dateFormatter = function(value) { 76 | if(value) { 77 | var date = dateFilter(value,"yyyy-MM-dd"); 78 | return date; 79 | } 80 | return; 81 | } 82 | 83 | ngModelCtrl.$parsers.unshift(dateParser); 84 | ngModelCtrl.$formatters.unshift(dateFormatter); 85 | 86 | element.bind("blur keyup change", function() { 87 | scope.$apply(function() { 88 | ngModelCtrl.$setViewValue(element.val()); 89 | }); 90 | }); 91 | 92 | ngModelCtrl.$render = function() { 93 | element.val(ngModelCtrl.$viewValue); 94 | } 95 | } 96 | 97 | if(Modernizr.inputtypes["date"]) { 98 | return nativeLinker; 99 | } else { 100 | return enhancedLinker; 101 | } 102 | } 103 | } 104 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/directives/datetimepicker.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign angularApp = "${projectId}"> 2 | 'use strict'; 3 | 4 | var LOCAL_DATETIME_REGEX = /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])\ ([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])$/; 5 | angular.module('${angularApp}').directive('datetime', function($parse, dateFilter) { 6 | return { 7 | restrict : "E", 8 | replace : true, 9 | transclude : false, 10 | require: '?ngModel', 11 | compile : function(element, attrs) { 12 | var modelAccessor = $parse(attrs.ngModel); 13 | 14 | var isRequired = ""; 15 | if(attrs.required) { 16 | isRequired = "required"; 17 | } 18 | var html = ""; 19 | 20 | var $newElem = $(html); 21 | element.replaceWith($newElem); 22 | 23 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 24 | if(!ngModelCtrl) return; 25 | 26 | var localDateTimeParser = function(value) { 27 | var date; 28 | if(value) { 29 | date = new Date(Date.parse(value)); 30 | date.setTime(date.getTime() + date.getTimezoneOffset()*60000); 31 | } else { 32 | date = value; 33 | } 34 | return date; 35 | } 36 | var localDateTimeFormatter = function(value) { 37 | if(value) { 38 | var date = dateFilter(value,"yyyy-MM-ddTHH:mm:ss"); 39 | return date; 40 | } 41 | return; 42 | } 43 | 44 | ngModelCtrl.$parsers.unshift(localDateTimeParser); 45 | ngModelCtrl.$formatters.unshift(localDateTimeFormatter); 46 | 47 | element.bind("blur keyup change", function() { 48 | scope.$apply(function() { 49 | ngModelCtrl.$setViewValue(element.val()); 50 | }); 51 | }); 52 | 53 | ngModelCtrl.$render = function() { 54 | element.val(ngModelCtrl.$viewValue); 55 | } 56 | } 57 | 58 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 59 | if(!ngModelCtrl) return; 60 | 61 | var localDateTimeParser = function(value) { 62 | if(value) { 63 | var d = value.match(LOCAL_DATETIME_REGEX); 64 | if(d) { 65 | var formattedDate = d[1] + "-" + d[2] + "-" + d[3] + "T" 66 | + d[4] + ":" + d[5] + ":" + d[6]; 67 | var date = new Date(Date.parse(formattedDate)); 68 | ngModelCtrl.$setValidity("datetimeFormat", true); 69 | return date; 70 | } else { 71 | ngModelCtrl.$setValidity("datetimeFormat", false); 72 | return; 73 | } 74 | } 75 | return; 76 | } 77 | var localDateTimeFormatter = function(value) { 78 | if(value) { 79 | var date = dateFilter(value,"yyyy-MM-dd HH:mm:ss"); 80 | return date; 81 | } 82 | return; 83 | } 84 | 85 | ngModelCtrl.$parsers.unshift(localDateTimeParser); 86 | ngModelCtrl.$formatters.unshift(localDateTimeFormatter); 87 | 88 | element.bind("blur keyup change", function() { 89 | scope.$apply(function() { 90 | ngModelCtrl.$setViewValue(element.val()); 91 | }); 92 | }); 93 | 94 | ngModelCtrl.$render = function() { 95 | element.val(ngModelCtrl.$viewValue); 96 | } 97 | } 98 | 99 | if(Modernizr.inputtypes["datetime-local"]) { 100 | return nativeLinker; 101 | } else { 102 | return enhancedLinker; 103 | } 104 | } 105 | } 106 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/directives/timepicker.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign angularApp = "${projectId}"> 2 | 'use strict'; 3 | 4 | var TIME_REGEX = /^([0-5][0-9])\:([0-5][0-9])(?:\:([0-5][0-9]))?$/; 5 | angular.module('${angularApp}').directive('time', function($parse, dateFilter) { 6 | return { 7 | restrict : "E", 8 | replace : true, 9 | transclude : false, 10 | require: '?ngModel', 11 | compile : function(element, attrs) { 12 | var modelAccessor = $parse(attrs.ngModel); 13 | 14 | var isRequired = ""; 15 | if(attrs.required) { 16 | isRequired = "required"; 17 | } 18 | var html = ""; 19 | 20 | var $newElem = $(html); 21 | element.replaceWith($newElem); 22 | 23 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 24 | if(!ngModelCtrl) return; 25 | 26 | var timeParser = function(value) { 27 | var date; 28 | if(value) { 29 | var d = value.match(TIME_REGEX); 30 | if(d) { 31 | date = new Date(0); 32 | if(!d[3]) { 33 | d[3] = "0"; 34 | } 35 | date.setHours(d[1], d[2], d[3]); 36 | } else { 37 | date = value; 38 | } 39 | } else { 40 | date = value; 41 | } 42 | return date; 43 | } 44 | var timeFormatter = function(value) { 45 | if(value) { 46 | var date = dateFilter(value,"HH:mm:ss"); 47 | return date; 48 | } 49 | return; 50 | } 51 | 52 | ngModelCtrl.$parsers.unshift(timeParser); 53 | ngModelCtrl.$formatters.unshift(timeFormatter); 54 | 55 | element.bind("blur keyup change", function() { 56 | scope.$apply(function() { 57 | ngModelCtrl.$setViewValue(element.val()); 58 | }); 59 | }); 60 | 61 | ngModelCtrl.$render = function() { 62 | element.val(ngModelCtrl.$viewValue); 63 | } 64 | } 65 | 66 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 67 | if(!ngModelCtrl) return; 68 | 69 | var timeParser = function(value) { 70 | if(value) { 71 | var d = value.match(TIME_REGEX); 72 | if(d) { 73 | var date = new Date(0); 74 | if(!d[3]) { 75 | d[3] = "0"; 76 | } 77 | date.setHours(d[1], d[2], d[3]); 78 | ngModelCtrl.$setValidity("timeFormat", true); 79 | return date; 80 | } else { 81 | ngModelCtrl.$setValidity("timeFormat", false); 82 | return; 83 | } 84 | } 85 | return; 86 | } 87 | var timeFormatter = function(value) { 88 | if(value) { 89 | var date = dateFilter(value,"HH:mm:ss"); 90 | return date; 91 | } 92 | return; 93 | } 94 | 95 | ngModelCtrl.$parsers.unshift(timeParser); 96 | ngModelCtrl.$formatters.unshift(timeFormatter); 97 | 98 | element.bind("blur keyup change", function() { 99 | scope.$apply(function() { 100 | ngModelCtrl.$setViewValue(element.val()); 101 | }); 102 | }); 103 | 104 | ngModelCtrl.$render = function() { 105 | element.val(ngModelCtrl.$viewValue); 106 | } 107 | } 108 | 109 | if(Modernizr.inputtypes["time"]) { 110 | return nativeLinker; 111 | } else { 112 | return enhancedLinker; 113 | } 114 | } 115 | } 116 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/filters/genericSearchFilter.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign angularApp = "${projectId}"> 2 | 'use strict'; 3 | 4 | angular.module('${projectId}').filter('searchFilter', function() { 5 | 6 | function matchObjectProperties(expectedObject, actualObject) { 7 | var flag = true; 8 | for(var key in expectedObject) { 9 | if(expectedObject.hasOwnProperty(key)) { 10 | var expectedProperty = expectedObject[key]; 11 | if (expectedProperty == null || expectedProperty === "") { 12 | continue; 13 | } 14 | var actualProperty = actualObject[key]; 15 | if (angular.isUndefined(actualProperty)) { 16 | continue; 17 | } 18 | if (actualProperty == null) { 19 | flag = false; 20 | } else if (angular.isObject(expectedProperty)) { 21 | flag = flag && matchObjectProperties(expectedProperty, actualProperty); 22 | } else { 23 | flag = flag && (actualProperty.toString().indexOf(expectedProperty.toString()) != -1); 24 | } 25 | } 26 | } 27 | return flag; 28 | } 29 | 30 | return function(results, scope) { 31 | 32 | scope.filteredResults = []; 33 | for (var ctr = 0; ctr < results.length; ctr++) { 34 | var flag = true; 35 | var searchCriteria = scope.search; 36 | var result = results[ctr]; 37 | for (var key in searchCriteria) { 38 | if (searchCriteria.hasOwnProperty(key)) { 39 | var expected = searchCriteria[key]; 40 | if (expected == null || expected === "") { 41 | continue; 42 | } 43 | var actual = result[key]; 44 | if (actual == null) { 45 | flag = false; 46 | } else if (angular.isObject(expected)) { 47 | flag = flag && matchObjectProperties(expected, actual); 48 | } else { 49 | flag = flag && (actual.toString().indexOf(expected.toString()) != -1); 50 | } 51 | } 52 | } 53 | if (flag == true) { 54 | scope.filteredResults.push(result); 55 | } 56 | } 57 | scope.numberOfPages(); 58 | return scope.filteredResults; 59 | }; 60 | }); 61 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/filters/startFromFilter.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign angularApp = "${projectId}"> 2 | 'use strict'; 3 | 4 | angular.module('${angularApp}').filter('startFrom', function() { 5 | return function(input, start) { 6 | start = +start; //parse to int 7 | return input.slice(start); 8 | }; 9 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/offcanvas.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $('[data-toggle=offcanvas]').click(function() { 3 | $('.row-offcanvas').toggleClass('active'); 4 | }); 5 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/services/entityFactory.js.ftl: -------------------------------------------------------------------------------- 1 | <#assign 2 | angularApp = "${projectId}" 3 | entityModule = "${entityName?uncap_first}Module" 4 | entityResource = "${entityName}Resource" 5 | entityIdJsVar = "${entityName}Id" 6 | > 7 | angular.module('${angularApp}').factory('${entityResource}', function($resource){ 8 | var resource = $resource('${parentDirectories}${resourceRootPath}/${resourcePath}/:${entityIdJsVar}',{${entityIdJsVar}:'@${entityId}'},{'queryAll':{method:'GET',isArray:true},'query':{method:'GET',isArray:false},'update':{method:'PUT'}}); 9 | return resource; 10 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/services/flash.js.ftl: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('${projectId}').factory('flash', ['$rootScope', function ($rootScope) { 4 | var messages = []; 5 | var currentMessage = {}; 6 | 7 | $rootScope.$on('$routeChangeSuccess', function() { 8 | currentMessage = messages.shift() || {}; 9 | }); 10 | 11 | return { 12 | getMessage: function () { 13 | return currentMessage; 14 | }, 15 | setMessage: function(message, pop) { 16 | switch(message.type) { 17 | case "error" : message.cssClass = "danger"; break; 18 | case "success" : message.cssClass = "success"; break; 19 | case "info" : message.cssClass = "info"; break; 20 | case "warning" : message.cssClass = "warning"; break; 21 | } 22 | messages.push(message); 23 | if(pop) { 24 | currentMessage = messages.shift() || {}; 25 | } 26 | } 27 | }; 28 | }]); 29 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/services/locationParser.js.ftl: -------------------------------------------------------------------------------- 1 | angular.module('${projectId}').value('locationParser', function(responseHeaders){ 2 | // Get the Location header and parse it. 3 | var locationHeader = responseHeaders('Location'); 4 | var fragments = locationHeader.split('/'); 5 | var id = fragments[fragments.length -1]; 6 | return id; 7 | }); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/scripts/vendor/modernizr-2.8.3.min.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.8.3 (Custom Build) | MIT & BSD 2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-canvas-canvastext-input-inputtypes-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes 3 | */ 4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b)&&c(b).matches||!1;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.flexboxlegacy=function(){return J("boxDirection")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document); -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/styles/main.css: -------------------------------------------------------------------------------- 1 | @CHARSET "UTF-8"; 2 | 3 | /* Sticky footer styles 4 | -------------------------------------------------- */ 5 | 6 | html, body { 7 | height: 100%; 8 | /* The html and body elements cannot have any padding or margin. */ 9 | } 10 | 11 | /* Wrapper for page content to push down footer */ 12 | #wrap { 13 | min-height: 100%; 14 | height: auto; 15 | /* Negative indent footer by it's height */ 16 | margin: 0 auto -60px; 17 | /* Pad bottom by footer height */ 18 | padding: 0 0 60px; 19 | } 20 | 21 | #wrap > .container { 22 | padding-top: 50px; 23 | } 24 | 25 | /* Set the fixed height of the footer here */ 26 | #footer { 27 | height: 60px; 28 | } 29 | 30 | #footer { 31 | background-color: #F5F5F5; 32 | text-align: center; 33 | border-top: 1px solid #E5E5E5; 34 | } 35 | 36 | h2 i.icon-check { 37 | vertical-align: middle; 38 | } 39 | 40 | table { 41 | table-layout: fixed; 42 | word-wrap: break-word; 43 | } 44 | 45 | /* Lastly, apply responsive CSS fixes as necessary */ 46 | @media (max-width: 767px) { 47 | table { 48 | table-layout: auto; 49 | } 50 | .row-offcanvas { 51 | position: relative; 52 | transition: all 0.25s ease-out; 53 | } 54 | .row-offcanvas-left .sidebar-offcanvas { 55 | display:none; 56 | } 57 | .row-offcanvas-left.active .sidebar-offcanvas { 58 | display:inherit; 59 | } 60 | .row-offcanvas-left.active .mainarea { 61 | display:none; 62 | } 63 | .sidebar-offcanvas { 64 | position: absolute; 65 | top: 0; 66 | width: 100%; 67 | } 68 | } -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/detail.html.ftl: -------------------------------------------------------------------------------- 1 | <#assign formName = "${entityName}Form" 2 | model = "${entityName?uncap_first}"> 3 |
4 |

Create a new ${entityName}

5 |

View or edit ${entityName}

6 |
7 |
8 | ${formProperties} 9 |
10 |
11 | 12 | 13 | 14 |
15 |
16 |
-------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/includes/basicPropertyDetail.html.ftl: -------------------------------------------------------------------------------- 1 | <#assign formName="${entityName}Form" 2 | formProperty = "${formName}.${property.name}" 3 | modelProperty = "${entityName?uncap_first}.${property.name}" 4 | propertyLabel = "${property.label}" /> 5 | <#if (property.hidden!"false") == "false"> 6 |
7 | 8 |
9 | <#if (property["datetime-type"]!"") == "both"> 10 | 11 | <#if (property.required!"false") == "true"> required<#t/> 12 | <#lt/> ng-model="${modelProperty}" placeholder="Enter the ${entityName} ${propertyLabel}"> 13 | <#elseif (property["datetime-type"]!"") == "date"> 14 | 15 | <#if (property.required!"false") == "true"> required<#t/> 16 | <#lt/> ng-model="${modelProperty}" placeholder="Enter the ${entityName} ${propertyLabel}"> 17 | <#elseif (property["datetime-type"]!"") == "time"> 18 | 21 | <#else> 22 | 23 | <#if property.type == "number"> type="number"<#t/> 24 | <#if property["minimum-value"]??> min="${property["minimum-value"]}"<#t/> 25 | <#if property["maximum-value"]??> max="${property["maximum-value"]}"<#t/> 26 | <#elseif property.type == "boolean"> type="checkbox"<#t/> 27 | <#else> type="text"<#t/> 28 | <#if (property.required!"false") == "true"> required<#t/> 29 | <#if property["maximum-length"]??> ng-maxlength="${property["maximum-length"]}"<#if property["minimum-length"]??> ng-minlength="${property["minimum-length"]}"<#lt/><#if property.type == "boolean"> class="checkbox"<#else> class="form-control"<#lt/> ng-model="${modelProperty}" placeholder="Enter the ${entityName} ${propertyLabel}"> 30 | 31 | <#if (property.required!) == "true"> 32 | required 33 | 34 | <#if property.type == "number"> 35 | not a number 36 | <#if property["minimum-value"]??> 37 | minimum allowed is ${property["minimum-value"]} 38 | 39 | <#if property["maximum-value"]??> 40 | maximum allowed is ${property["maximum-value"]} 41 | 42 | 43 | <#if property["minimum-length"]??> 44 | minimum length is ${property["minimum-length"]} 45 | 46 | <#if property["maximum-length"]??> 47 | maximum length is ${property["maximum-length"]} 48 | 49 | <#if (property["datetime-type"]!"") == "both"> 50 | does not match format "yyyy-MM-dd hh:mm:ss" (e.g. 2013-12-01 22:00:00) 51 | 52 | <#if (property["datetime-type"]!"") == "date"> 53 | does not match format "yyyy-MM-dd" (e.g. 2013-12-01) 54 | 55 | <#if (property["datetime-type"]!"") == "time"> 56 | does not match format "hh:mm" or "hh:mm:ss" (e.g. 05:00 or 22:00:00) 57 | 58 |
59 |
60 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/includes/lookupPropertyDetail.html.ftl: -------------------------------------------------------------------------------- 1 | <#assign formName="${entityName}Form" 2 | formProperty = "${formName}.${property.name}" 3 | modelProperty = "${entityName?uncap_first}.${property.name}" 4 | propertyLabel = "${property.label}" 5 | collectionVar = "${property.name?substring(0, 1)}" 6 | collection = "${property.identifier}List"> 7 | <#if (property.hidden!"false") == "false"> 8 |
9 | 10 |
11 | 14 | <#if (property.required!) == "true"> 15 | required 16 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/includes/nToManyPropertyDetail.html.ftl: -------------------------------------------------------------------------------- 1 | <#assign formName="${entityName}Form" 2 | formProperty = "${formName}.${property.name}" 3 | modelProperty = "${property.identifier}Selection" 4 | propertyLabel = "${property.label}" 5 | collectionVar = "${property.name?substring(0, 1)}" 6 | collection = "${property.identifier}SelectionList"> 7 | <#if (property.hidden!"false") == "false"> 8 |
9 | 10 |
11 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/includes/nToOnePropertyDetail.html.ftl: -------------------------------------------------------------------------------- 1 | <#assign formName="${entityName}Form" 2 | formProperty = "${formName}.${property.name}" 3 | modelProperty = "${entityName?uncap_first}.${property.name}" 4 | propertyLabel = "${property.label}" 5 | collectionVar = "${property.name?substring(0, 1)}" 6 | collection = "${property.identifier}SelectionList"> 7 | <#if (property.hidden!"false") == "false"> 8 |
9 | 10 |
11 | 14 | <#if (property.required!) == "true"> 15 | required 16 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/includes/searchFormInput.html.ftl: -------------------------------------------------------------------------------- 1 | <#assign propertyLabel = "${property.label}" 2 | collectionVar = "${property.name?substring(0, 1)}" 3 | collection = "${property.identifier}List"> 4 | <#-- Display only non-hidden singular properties as search criteria. Omit collections and date/time properties --> 5 | <#if (property.hidden!"false") != "true" && (property["n-to-many"]!"false") != "true" && (property["temporal"]!"false") != "true"> 6 |
7 | 8 |
9 | <#if (property["many-to-one"]!"false") == "true" || (property["one-to-one"]!"false") == "true"> 10 | 13 | <#elseif property.type == "boolean"> 14 | 17 | <#elseif property["lookup"]??> 18 | 21 | <#else> 22 | 23 | 24 |
25 |
26 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/includes/searchResults.html.ftl: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | <#list properties as property><#t> 6 | <#if (property.hidden!"false") != "true"> 7 | <#if (property["n-to-many"]!"false") != "true"> 8 | <#-- Display only singular properties for now. Exclude collections as they cannot be displayed "meaningfully". --> 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | <#list properties as property> 18 | <#if (property.hidden!"false") != "true"> 19 | <#if (property["many-to-one"]!"false") == "true" || (property["one-to-one"]!"false") == "true"> 20 | <#if (property["option-label-temporal-type"]!"") == "date"> 21 | 22 | <#elseif (property["option-label-temporal-type"]!"") == "time"> 23 | 24 | <#elseif (property["option-label-temporal-type"]!"") == "both"> 25 | 26 | <#else> 27 | 28 | 29 | <#elseif (property["n-to-many"]!"false") == "true"> 30 | <#-- Do nothing. We won't allow for display of collection properties in search results for now. --> 31 | <#elseif (property["datetime-type"]!"") == "date"> 32 | 33 | <#elseif (property["datetime-type"]!"") == "time"> 34 | 35 | <#elseif (property["datetime-type"]!"") == "both"> 36 | 37 | <#else> 38 | 39 | 40 | 41 | 42 | 43 | 44 |
${property.label}
{{result.${property.name}.${property.optionLabel}| date:'mediumDate'}}{{result.${property.name}.${property.optionLabel}| date:'mediumTime'}}{{result.${property.name}.${property.optionLabel}| date:'medium'}}{{result.${property.name}.${property.optionLabel}}}{{result.${property.name}| date:'mediumDate'}}{{result.${property.name}| date:'mediumTime'}}{{result.${property.name}| date:'yyyy-MM-dd HH:mm:ss Z'}}{{result.${property.name}}}
45 |
46 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/includes/searchResultsPaginator.html.ftl: -------------------------------------------------------------------------------- 1 |
    2 |
  • 3 | 4 |
  • 5 |
  • 6 | 1 7 |
  • 8 |
  • 9 | 10 |
  • 11 |
12 | -------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/landing.html: -------------------------------------------------------------------------------- 1 |

2 | Your application is running. 3 |

4 |

5 | Documentation 7 | | Get Excited!

9 | Forge Project
| User 11 | Forums | Report an issue 13 |

-------------------------------------------------------------------------------- /src/main/resources/org/jboss/forge/addon/angularjs/views/search.html.ftl: -------------------------------------------------------------------------------- 1 |
2 |

Create a new ${entityName}

3 |
4 |
5 | Create 6 |
7 |
8 |
9 |
10 |
11 |

Search for ${pluralizedEntityName}

12 |
13 | ${searchFormProperties} 14 |
15 |
16 | Search 17 |
18 |
19 |
20 |
21 |
22 | ${searchResults} 23 | ${searchResultsPaginator} 24 |
-------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/PropertyBuilder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import java.util.Collections; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * A builder to help in creation of Metawidget inspection results to be used in tests, without actually inspecting classes or 15 | * objects. 16 | */ 17 | class PropertyBuilder { 18 | private Map properties = new HashMap(); 19 | 20 | public Map create() { 21 | return Collections.unmodifiableMap(properties); 22 | } 23 | 24 | public PropertyBuilder withName(String name) { 25 | properties.put("name", name); 26 | return this; 27 | } 28 | 29 | public PropertyBuilder withIdentifier(String identifier) { 30 | properties.put("identifier", identifier); 31 | return this; 32 | } 33 | 34 | public PropertyBuilder withLabel(String label) { 35 | properties.put("label", label); 36 | return this; 37 | } 38 | 39 | public PropertyBuilder withType(String type) { 40 | properties.put("type", type); 41 | return this; 42 | } 43 | 44 | public PropertyBuilder asRequired() { 45 | properties.put("required", "true"); 46 | return this; 47 | } 48 | 49 | public PropertyBuilder asHidden() { 50 | properties.put("hidden", "true"); 51 | return this; 52 | } 53 | 54 | public PropertyBuilder withMinLen(String len) { 55 | properties.put("minimum-length", len); 56 | return this; 57 | } 58 | 59 | public PropertyBuilder withMaxLen(String len) { 60 | properties.put("maximum-length", len); 61 | return this; 62 | } 63 | 64 | public PropertyBuilder withMinVal(String min) { 65 | properties.put("minimum-value", min); 66 | return this; 67 | } 68 | 69 | public PropertyBuilder withMaxVal(String min) { 70 | properties.put("maximum-value", min); 71 | return this; 72 | } 73 | 74 | public PropertyBuilder asDate() { 75 | properties.put("datetime-type", "date"); 76 | return this; 77 | } 78 | 79 | public PropertyBuilder asTime() { 80 | properties.put("datetime-type", "time"); 81 | return this; 82 | } 83 | 84 | public PropertyBuilder asDateTime() { 85 | properties.put("datetime-type", "both"); 86 | return this; 87 | } 88 | 89 | public PropertyBuilder asNToMany() { 90 | properties.put("n-to-many", "true"); 91 | return this; 92 | } 93 | 94 | public PropertyBuilder withParameterizedType(String parameterizedType) { 95 | properties.put("parameterized-type", parameterizedType); 96 | return this; 97 | } 98 | 99 | public PropertyBuilder withSimpleType(String simpleType) { 100 | properties.put("simpleType", simpleType); 101 | return this; 102 | } 103 | 104 | public PropertyBuilder withOptionLabel(String optionLabel) { 105 | properties.put("optionLabel", optionLabel); 106 | return this; 107 | } 108 | 109 | public PropertyBuilder as1To1() { 110 | properties.put("one-to-one", "true"); 111 | return this; 112 | } 113 | 114 | public PropertyBuilder asMTo1() { 115 | properties.put("many-to-one", "true"); 116 | return this; 117 | } 118 | 119 | public PropertyBuilder withLookupValues(String lookupValues) { 120 | properties.put("lookup", lookupValues); 121 | return this; 122 | } 123 | } -------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/TestHelpers.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs; 8 | 9 | import org.metawidget.util.simple.StringUtils; 10 | 11 | import java.util.*; 12 | 13 | /** 14 | * A Helper class to create simulated inspection results of various kinds. 15 | */ 16 | public class TestHelpers { 17 | 18 | static 19 | { 20 | STRING_CLASS = String.class.getName(); 21 | SET_CLASS = Set.class.getName(); 22 | DATE_CLASS = Date.class.getName(); 23 | } 24 | 25 | public static final String PROJECT_ID = "testProject"; 26 | 27 | public static final String ENTITY_NAME = "SampleEntity"; 28 | 29 | public static final String PLURALIZED_ENTITY_NAME = "SampleEntities"; 30 | 31 | public static final Map ENTITY_VERSION_PROP = createVersionProperty(); 32 | 33 | public static final Map ENTITY_ID_PROP = createIdProperty(); 34 | 35 | public static final Map BASIC_STRING_PROP = createBasicStringProperty(); 36 | 37 | public static final Map STRING_PROP_WITH_MIN_LEN = createStringPropertyWithMinLen(); 38 | 39 | public static final Map STRING_PROP_WITH_MAX_LEN = createStringPropertyWithMaxLen(); 40 | 41 | public static final Map NUMBER_PROP = createNumberProperty(); 42 | 43 | public static final Map NUMBER_PROP_WITH_MIN_VAL = createNumberPropertyWithMinVal(); 44 | 45 | public static final Map NUMBER_PROP_WITH_MAX_VAL = createNumberPropertyWithMaxVal(); 46 | 47 | public static final Map DATE_PROP = createDateProperty(); 48 | 49 | public static final Map TIME_PROP = createTimeProperty(); 50 | 51 | public static final Map DATETIME_PROP = createDateTimeProperty(); 52 | 53 | public static final Map BOOLEAN_PROP = createBooleanProperty(); 54 | 55 | public static final Map ONE_TO_MANY_PROP = createOneToManyProperty(); 56 | 57 | public static final Map MANY_TO_MANY_PROP = createManyToManyProperty(); 58 | 59 | public static final Map ONE_TO_ONE_PROP = createOneToOneProperty(); 60 | 61 | public static final Map MANY_TO_ONE_PROP = createManyToOneProperty(); 62 | 63 | public static final Map ENUM_PROP = createEnumProperty(); 64 | 65 | private static final String DATE_CLASS; 66 | 67 | private static final String SET_CLASS; 68 | 69 | private static final String STRING_CLASS; 70 | 71 | private static final String BOOLEAN = "boolean"; 72 | 73 | private static final String NUMBER = "number"; 74 | 75 | public static Map createGlobalRootmap() { 76 | Map root = new HashMap(); 77 | root.put("projectId", StringUtils.camelCase(PROJECT_ID)); 78 | root.put("projectTitle", StringUtils.uncamelCase(PROJECT_ID)); 79 | root.put("entityNames", Arrays.asList(new String[]{ENTITY_NAME})); 80 | root.put("pluralizedEntityNames", Arrays.asList(new String[]{PLURALIZED_ENTITY_NAME})); 81 | root.put("targetDir", ""); 82 | return Collections.unmodifiableMap(root); 83 | } 84 | 85 | public static Map createEntityRootmap(List> entityAttributeProperties) { 86 | Map root = new HashMap(); 87 | root.put("projectId", StringUtils.camelCase(PROJECT_ID)); 88 | root.put("projectTitle", StringUtils.uncamelCase(PROJECT_ID)); 89 | root.put("entityName", ENTITY_NAME); 90 | root.put("pluralizedEntityName", PLURALIZED_ENTITY_NAME); 91 | root.put("entityId", "id"); 92 | root.put("resourceRootPath", "rest"); 93 | root.put("resourcePath", ENTITY_NAME + "s"); 94 | root.put("parentDirectories", ""); 95 | root.put("properties", entityAttributeProperties); 96 | root.put("formProperties", "
"); 97 | root.put("searchFormProperties", "
"); 98 | root.put("searchResults", "
"); 99 | root.put("searchResultsPaginator", "
"); 100 | return Collections.unmodifiableMap(root); 101 | } 102 | 103 | public static Map createInspectionResultWrapper(String entityName, Map propertyAttributes) { 104 | Map root = new HashMap(); 105 | root.put("entityName", entityName); 106 | root.put("entityId", "id"); 107 | root.put("property", propertyAttributes); 108 | return root; 109 | } 110 | 111 | private static Map createVersionProperty() { 112 | String propertyName = "version"; 113 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 114 | .withLabel(StringUtils.uncamelCase(propertyName)).asHidden().withType(NUMBER).create(); 115 | return properties; 116 | } 117 | 118 | private static Map createIdProperty() { 119 | String propertyName = "id"; 120 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 121 | .withLabel(StringUtils.uncamelCase(propertyName)).asHidden().asRequired().withType(NUMBER).create(); 122 | return properties; 123 | } 124 | 125 | private static Map createBasicStringProperty() { 126 | String propertyName = "fullName"; 127 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 128 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(STRING_CLASS).create(); 129 | return properties; 130 | } 131 | 132 | private static Map createStringPropertyWithMinLen() { 133 | String propertyName = "fullName"; 134 | String minimumLength = "5"; 135 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 136 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(STRING_CLASS).withMinLen(minimumLength).create(); 137 | return properties; 138 | } 139 | 140 | private static Map createStringPropertyWithMaxLen() { 141 | String propertyName = "fullName"; 142 | String maximumLength = "100"; 143 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 144 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(STRING_CLASS).withMaxLen(maximumLength).create(); 145 | return properties; 146 | } 147 | 148 | private static Map createNumberProperty() { 149 | String propertyName = "score"; 150 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 151 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(NUMBER).create(); 152 | return properties; 153 | } 154 | 155 | private static Map createNumberPropertyWithMinVal() { 156 | String propertyName = "score"; 157 | String min = "0"; 158 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 159 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(NUMBER).withMinVal(min).create(); 160 | return properties; 161 | } 162 | 163 | private static Map createNumberPropertyWithMaxVal() { 164 | String propertyName = "score"; 165 | String max = "100"; 166 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 167 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(NUMBER).withMaxVal(max).create(); 168 | return properties; 169 | } 170 | 171 | private static Map createDateProperty() { 172 | String propertyName = "dateOfBirth"; 173 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 174 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(DATE_CLASS).asDate().create(); 175 | return properties; 176 | } 177 | 178 | private static Map createTimeProperty() { 179 | String propertyName = "alarmTime"; 180 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 181 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(DATE_CLASS).asTime().create(); 182 | return properties; 183 | } 184 | 185 | private static Map createDateTimeProperty() { 186 | String propertyName = "auditTimestamp"; 187 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 188 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(DATE_CLASS).asDateTime().create(); 189 | return properties; 190 | } 191 | 192 | private static Map createBooleanProperty() { 193 | String propertyName = "optForMail"; 194 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 195 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(BOOLEAN).create(); 196 | return properties; 197 | } 198 | 199 | private static Map createOneToManyProperty() { 200 | String lhsProperty = "orders"; 201 | String rhsType = "com.example.scaffoldtester.model.StoreOrder"; 202 | String rhsSimpleType = "StoreOrder"; 203 | String rhsOptionLabel = "id"; 204 | Map properties = new PropertyBuilder().withName(lhsProperty).withIdentifier(lhsProperty) 205 | .withLabel(StringUtils.uncamelCase(lhsProperty)).withType(SET_CLASS).asNToMany().withParameterizedType(rhsType) 206 | .withSimpleType(rhsSimpleType).withOptionLabel(rhsOptionLabel).create(); 207 | return properties; 208 | } 209 | 210 | private static Map createManyToManyProperty() { 211 | String lhsProperty = "users"; 212 | String rhsType = "com.example.scaffoldtester.model.UserIdentity"; 213 | String rhsSimpleType = "UserIdentity"; 214 | String rhsOptionLabel = "id"; 215 | Map properties = new PropertyBuilder().withName(lhsProperty).withIdentifier(lhsProperty) 216 | .withLabel(StringUtils.uncamelCase(lhsProperty)).withType(SET_CLASS).asNToMany().withParameterizedType(rhsType) 217 | .withSimpleType(rhsSimpleType).withOptionLabel(rhsOptionLabel).create(); 218 | return properties; 219 | } 220 | 221 | private static Map createOneToOneProperty() { 222 | String lhsProperty = "voucher"; 223 | String rhsType = "com.example.scaffoldtester.model.DiscountVoucher"; 224 | String rhsSimpleType = "DiscountVoucher"; 225 | String rhsOptionLabel = "id"; 226 | Map properties = new PropertyBuilder().withName(lhsProperty).withIdentifier(lhsProperty) 227 | .withLabel(StringUtils.uncamelCase(lhsProperty)).withType(rhsType).as1To1().withSimpleType(rhsSimpleType) 228 | .withOptionLabel(rhsOptionLabel).create(); 229 | return properties; 230 | } 231 | 232 | private static Map createManyToOneProperty() { 233 | String lhsProperty = "customer"; 234 | String rhsType = "com.example.scaffoldtester.model.Customer"; 235 | String rhsSimpleType = "Customer"; 236 | String rhsOptionLabel = "id"; 237 | Map properties = new PropertyBuilder().withName(lhsProperty).withIdentifier(lhsProperty) 238 | .withLabel(StringUtils.uncamelCase(lhsProperty)).withType(rhsType).asMTo1().withSimpleType(rhsSimpleType) 239 | .withOptionLabel(rhsOptionLabel).create(); 240 | return properties; 241 | } 242 | 243 | private static Map createEnumProperty() { 244 | String propertyName = "paymentType"; 245 | String lookupValues = "CASH,CREDIT_CARD,DEBIT_CARD"; 246 | String propertyType = "com.example.scaffoldtester.model.DeliveryType"; 247 | Map properties = new PropertyBuilder().withName(propertyName).withIdentifier(propertyName) 248 | .withLabel(StringUtils.uncamelCase(propertyName)).withType(propertyType).withLookupValues(lookupValues).create(); 249 | return properties; 250 | } 251 | 252 | } 253 | -------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/matchers/InspectionResultMatcher.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs.matchers; 8 | 9 | import org.hamcrest.Description; 10 | import org.hamcrest.Matcher; 11 | import org.hamcrest.TypeSafeMatcher; 12 | 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.Map.Entry; 16 | 17 | /** 18 | * A Hamcrest matcher to aid in verifying that inspection results represented as a List of Map of String key-value pairs, 19 | * contains a key-value pair in one of the Maps (i.e. one of the class/object properties). 20 | */ 21 | public class InspectionResultMatcher extends TypeSafeMatcher>> { 22 | 23 | private String key; 24 | private String value; 25 | private Entry attributeEntry; 26 | 27 | public InspectionResultMatcher(final String key, final String value) { 28 | this.key = key; 29 | this.value = value; 30 | this.attributeEntry = new Entry() { 31 | 32 | @Override 33 | public String getKey() { 34 | return key; 35 | } 36 | 37 | @Override 38 | public String getValue() { 39 | return value; 40 | } 41 | 42 | @Override 43 | public String setValue(String value) { 44 | // Doing nothing here. We're just matching keys and values, not modifying them 45 | return null; 46 | } 47 | }; 48 | } 49 | 50 | @Override 51 | protected boolean matchesSafely(List> allPropertyAttributes) { 52 | for (Map singlePropertyAttributes : allPropertyAttributes) { 53 | for (Entry propertyAttribute : singlePropertyAttributes.entrySet()) { 54 | if (propertyAttribute.equals(attributeEntry)) { 55 | return true; 56 | } 57 | } 58 | } 59 | return false; 60 | } 61 | 62 | @Override 63 | public void describeTo(Description description) { 64 | description.appendText("a Map with entry containing " + key + "= " + value); 65 | } 66 | 67 | public static Matcher>> hasItemWithEntry(String key, String value) { 68 | return new InspectionResultMatcher>>(key, value); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/tests/freemarker/Deployments.java: -------------------------------------------------------------------------------- 1 | package org.jboss.forge.addon.angularjs.tests.freemarker; 2 | 3 | import java.io.File; 4 | 5 | import org.jboss.forge.addon.angularjs.AngularScaffoldProvider; 6 | import org.jboss.forge.addon.angularjs.matchers.InspectionResultMatcher; 7 | import org.jboss.forge.addon.angularjs.util.RestResourceTypeVisitor; 8 | import org.jboss.forge.arquillian.archive.AddonArchive; 9 | import org.jboss.shrinkwrap.api.ShrinkWrap; 10 | import org.jsoup.Jsoup; 11 | 12 | public class Deployments 13 | { 14 | public static AddonArchive getDeployment() 15 | { 16 | System.out.println(); 17 | return ShrinkWrap 18 | .create(AddonArchive.class) 19 | .addClass(Deployments.class) 20 | .addClass(InspectionResultMatcher.class) 21 | .addAsLibrary(new File(Jsoup.class.getProtectionDomain().getCodeSource().getLocation().getFile())) 22 | .addPackage(AngularScaffoldProvider.class.getPackage()) 23 | .addPackages(true, Jsoup.class.getPackage()) 24 | .addClass(RestResourceTypeVisitor.class) 25 | .addAsResources(Deployments.BASE_PACKAGE, 26 | Deployments.NEW_ENTITY_CONTROLLER_JS, 27 | Deployments.EDIT_ENTITY_CONTROLLER_JS, 28 | Deployments.SEARCH_ENTITY_CONTROLLER_JS, 29 | Deployments.ENTITY_FACTORY, Deployments.DETAIL_VIEW, 30 | Deployments.SEARCH_VIEW, 31 | Deployments.SEARCH_RESULTS_PAGINATOR_INCLUDE, 32 | Deployments.SEARCH_RESULTS, 33 | Deployments.SEARCH_FORM_INPUT, 34 | Deployments.BASIC_PROPERTY_DETAIL_INCLUDE, 35 | Deployments.LOOKUP_PROPERTY_DETAIL_INCLUDE, 36 | Deployments.N_TO_ONE_PROPERTY_DETAIL_INCLUDE, 37 | Deployments.N_TO_MANY_PROPERTY_DETAIL_INCLUDE, 38 | Deployments.INDEX_PAGE, 39 | Deployments.APP_JS) 40 | .addBeansXML(); 41 | } 42 | 43 | public static final Package BASE_PACKAGE = AngularScaffoldProvider.class 44 | .getPackage(); 45 | public static final String BASE_PACKAGE_PATH = "/" + BASE_PACKAGE.getName().replace('.', '/') + File.separator; 46 | public static final String NEW_ENTITY_CONTROLLER_JS = "scripts/controllers/newEntityController.js.ftl"; 47 | public static final String EDIT_ENTITY_CONTROLLER_JS = "scripts/controllers/editEntityController.js.ftl"; 48 | public static final String SEARCH_ENTITY_CONTROLLER_JS = "scripts/controllers/searchEntityController.js.ftl"; 49 | public static final String ENTITY_FACTORY = "scripts/services/entityFactory.js.ftl"; 50 | public static final String DETAIL_VIEW = "views/detail.html.ftl"; 51 | public static final String SEARCH_VIEW = "views/search.html.ftl"; 52 | public static final String SEARCH_RESULTS_PAGINATOR_INCLUDE = "views/includes/searchResultsPaginator.html.ftl"; 53 | public static final String SEARCH_RESULTS = "views/includes/searchResults.html.ftl"; 54 | public static final String SEARCH_FORM_INPUT = "views/includes/searchFormInput.html.ftl"; 55 | public static final String BASIC_PROPERTY_DETAIL_INCLUDE = "views/includes/basicPropertyDetail.html.ftl"; 56 | public static final String LOOKUP_PROPERTY_DETAIL_INCLUDE = "views/includes/lookupPropertyDetail.html.ftl"; 57 | public static final String N_TO_ONE_PROPERTY_DETAIL_INCLUDE = "views/includes/nToOnePropertyDetail.html.ftl"; 58 | public static final String N_TO_MANY_PROPERTY_DETAIL_INCLUDE = "views/includes/nToManyPropertyDetail.html.ftl"; 59 | public static final String INDEX_PAGE = "index.html.ftl"; 60 | public static final String APP_JS = "scripts/app.js.ftl"; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/tests/freemarker/FreemarkerClientPartialsLookupPropertyTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs.tests.freemarker; 8 | 9 | import static org.hamcrest.core.IsEqual.equalTo; 10 | import static org.hamcrest.core.IsNot.not; 11 | import static org.hamcrest.core.IsNull.notNullValue; 12 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_ID_PROP; 13 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_NAME; 14 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_VERSION_PROP; 15 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENUM_PROP; 16 | import static org.jboss.forge.addon.angularjs.TestHelpers.createInspectionResultWrapper; 17 | import static org.junit.Assert.assertThat; 18 | 19 | import java.net.URL; 20 | import java.util.Map; 21 | 22 | import javax.inject.Inject; 23 | 24 | import org.hamcrest.core.IsEqual; 25 | import org.jboss.arquillian.container.test.api.Deployment; 26 | import org.jboss.arquillian.junit.Arquillian; 27 | import org.jboss.forge.addon.resource.Resource; 28 | import org.jboss.forge.addon.resource.ResourceFactory; 29 | import org.jboss.forge.addon.templates.Template; 30 | import org.jboss.forge.addon.templates.TemplateFactory; 31 | import org.jboss.forge.addon.templates.freemarker.FreemarkerTemplate; 32 | import org.jboss.forge.arquillian.AddonDependencies; 33 | import org.jboss.forge.arquillian.AddonDependency; 34 | import org.jboss.forge.arquillian.archive.AddonArchive; 35 | import org.jsoup.Jsoup; 36 | import org.jsoup.nodes.Document; 37 | import org.jsoup.select.Elements; 38 | import org.junit.Test; 39 | import org.junit.runner.RunWith; 40 | import org.metawidget.util.simple.StringUtils; 41 | 42 | /** 43 | * Tests to verify that the generated HTML for Enum properties of JPA entities are generated correctly. 44 | */ 45 | @RunWith(Arquillian.class) 46 | public class FreemarkerClientPartialsLookupPropertyTest { 47 | 48 | @Inject 49 | private ResourceFactory resourceFactory; 50 | 51 | @Inject 52 | private TemplateFactory processorFactory; 53 | 54 | @Deployment 55 | @AddonDependencies({ 56 | @AddonDependency(name = "org.jboss.forge.addon:scaffold-spi"), 57 | @AddonDependency(name = "org.jboss.forge.addon:javaee"), 58 | @AddonDependency(name = "org.jboss.forge.addon:templates"), 59 | @AddonDependency(name = "org.jboss.forge.addon:text"), 60 | @AddonDependency(name = "org.jboss.forge.addon:convert"), 61 | @AddonDependency(name = "org.jboss.forge.addon:parser-java"), 62 | @AddonDependency(name = "org.jboss.forge.furnace.container:cdi") 63 | }) 64 | public static AddonArchive getDeployment() 65 | { 66 | return Deployments.getDeployment(); 67 | } 68 | 69 | @Test 70 | public void testGenerateHiddenProperty() throws Exception { 71 | Map root = createInspectionResultWrapper(ENTITY_NAME, ENTITY_VERSION_PROP); 72 | 73 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.LOOKUP_PROPERTY_DETAIL_INCLUDE)); 74 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 75 | String output = processor.process(root); 76 | assertThat(output.trim(), IsEqual.equalTo("")); 77 | } 78 | 79 | @Test 80 | public void testGenerateHiddenAndRequiredProperty() throws Exception { 81 | Map root = createInspectionResultWrapper(ENTITY_NAME, ENTITY_ID_PROP); 82 | 83 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.LOOKUP_PROPERTY_DETAIL_INCLUDE)); 84 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 85 | String output = processor.process(root); 86 | assertThat(output.trim(), IsEqual.equalTo("")); 87 | } 88 | 89 | @Test 90 | public void testGenerateEnumProperty() throws Exception { 91 | String enumProperty = "paymentType"; 92 | Map root = createInspectionResultWrapper(ENTITY_NAME, ENUM_PROP); 93 | 94 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.LOOKUP_PROPERTY_DETAIL_INCLUDE)); 95 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 96 | String output = processor.process(root); 97 | Document html = Jsoup.parseBodyFragment(output); 98 | assertThat(output.trim(), not(equalTo(""))); 99 | 100 | Elements container = html.select("div.form-group"); 101 | assertThat(container, notNullValue()); 102 | assertThat(container.attr("ng-class"), not(equalTo(""))); 103 | 104 | Elements nToManyWidgetElement = html.select("div.form-group > div.col-sm-10"); 105 | assertThat(nToManyWidgetElement, notNullValue()); 106 | 107 | Elements selectElement = nToManyWidgetElement.select(" > select"); 108 | assertThat(selectElement.attr("id"), equalTo(enumProperty)); 109 | assertThat(selectElement.attr("ng-model"), equalTo(StringUtils.camelCase(ENTITY_NAME) + "." + enumProperty)); 110 | String collectionElement = enumProperty.substring(0, 1); 111 | String optionsExpression = collectionElement +" for "+ collectionElement +" in " + enumProperty + "List"; 112 | assertThat(selectElement.attr("ng-options"), equalTo(optionsExpression)); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/tests/freemarker/FreemarkerClientPartialsNToManyPropertyTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs.tests.freemarker; 8 | 9 | import static org.hamcrest.core.IsEqual.equalTo; 10 | import static org.hamcrest.core.IsNot.not; 11 | import static org.hamcrest.core.IsNull.notNullValue; 12 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_ID_PROP; 13 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_NAME; 14 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_VERSION_PROP; 15 | import static org.jboss.forge.addon.angularjs.TestHelpers.MANY_TO_MANY_PROP; 16 | import static org.jboss.forge.addon.angularjs.TestHelpers.ONE_TO_MANY_PROP; 17 | import static org.jboss.forge.addon.angularjs.TestHelpers.createInspectionResultWrapper; 18 | import static org.junit.Assert.assertThat; 19 | 20 | import java.net.URL; 21 | import java.util.Map; 22 | 23 | import javax.inject.Inject; 24 | 25 | import org.hamcrest.core.IsEqual; 26 | import org.jboss.arquillian.container.test.api.Deployment; 27 | import org.jboss.arquillian.junit.Arquillian; 28 | import org.jboss.forge.addon.resource.Resource; 29 | import org.jboss.forge.addon.resource.ResourceFactory; 30 | import org.jboss.forge.addon.templates.Template; 31 | import org.jboss.forge.addon.templates.TemplateFactory; 32 | import org.jboss.forge.addon.templates.freemarker.FreemarkerTemplate; 33 | import org.jboss.forge.arquillian.AddonDependencies; 34 | import org.jboss.forge.arquillian.AddonDependency; 35 | import org.jboss.forge.arquillian.archive.AddonArchive; 36 | import org.jsoup.Jsoup; 37 | import org.jsoup.nodes.Document; 38 | import org.jsoup.select.Elements; 39 | import org.junit.Test; 40 | import org.junit.runner.RunWith; 41 | 42 | /** 43 | * Tests to verify that the generated HTML for 1:M and M:M associations of JPA entities are generated correctly. 44 | */ 45 | @RunWith(Arquillian.class) 46 | public class FreemarkerClientPartialsNToManyPropertyTest 47 | { 48 | 49 | @Inject 50 | private ResourceFactory resourceFactory; 51 | 52 | @Inject 53 | private TemplateFactory processorFactory; 54 | 55 | @Deployment 56 | @AddonDependencies({ 57 | @AddonDependency(name = "org.jboss.forge.addon:scaffold-spi"), 58 | @AddonDependency(name = "org.jboss.forge.addon:javaee"), 59 | @AddonDependency(name = "org.jboss.forge.addon:templates"), 60 | @AddonDependency(name = "org.jboss.forge.addon:text"), 61 | @AddonDependency(name = "org.jboss.forge.addon:convert"), 62 | @AddonDependency(name = "org.jboss.forge.addon:parser-java"), 63 | @AddonDependency(name = "org.jboss.forge.furnace.container:cdi") 64 | }) 65 | public static AddonArchive getDeployment() 66 | { 67 | return Deployments.getDeployment(); 68 | } 69 | 70 | @Test 71 | public void testGenerateHiddenProperty() throws Exception 72 | { 73 | Map root = createInspectionResultWrapper(ENTITY_NAME, ENTITY_VERSION_PROP); 74 | 75 | Resource templateResource = resourceFactory.create(getClass().getResource( 76 | Deployments.BASE_PACKAGE_PATH + Deployments.N_TO_MANY_PROPERTY_DETAIL_INCLUDE)); 77 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 78 | String output = processor.process(root); 79 | assertThat(output.trim(), IsEqual.equalTo("")); 80 | } 81 | 82 | @Test 83 | public void testGenerateHiddenAndRequiredProperty() throws Exception 84 | { 85 | Map root = createInspectionResultWrapper(ENTITY_NAME, ENTITY_ID_PROP); 86 | 87 | Resource templateResource = resourceFactory.create(getClass().getResource( 88 | Deployments.BASE_PACKAGE_PATH + Deployments.N_TO_MANY_PROPERTY_DETAIL_INCLUDE)); 89 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 90 | String output = processor.process(root); 91 | assertThat(output.trim(), IsEqual.equalTo("")); 92 | } 93 | 94 | @Test 95 | public void testGenerateOneToManyProperty() throws Exception 96 | { 97 | String oneToManyProperty = "orders"; 98 | Map root = createInspectionResultWrapper(ENTITY_NAME, ONE_TO_MANY_PROP); 99 | 100 | Resource templateResource = resourceFactory.create(getClass().getResource( 101 | Deployments.BASE_PACKAGE_PATH + Deployments.N_TO_MANY_PROPERTY_DETAIL_INCLUDE)); 102 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 103 | String output = processor.process(root); 104 | Document html = Jsoup.parseBodyFragment(output); 105 | assertThat(output.trim(), not(equalTo(""))); 106 | 107 | Elements container = html.select("div.form-group"); 108 | assertThat(container, notNullValue()); 109 | assertThat(container.attr("ng-class"), not(equalTo(""))); 110 | 111 | Elements nToManyWidgetElement = html.select("div.form-group > div.col-sm-10"); 112 | assertThat(nToManyWidgetElement, notNullValue()); 113 | 114 | Elements selectElement = nToManyWidgetElement.select(" > select"); 115 | assertThat(selectElement.attr("id"), equalTo(oneToManyProperty)); 116 | assertThat(selectElement.attr("multiple"), notNullValue()); 117 | assertThat(selectElement.attr("ng-model"), equalTo(oneToManyProperty + "Selection")); 118 | String collectionElement = oneToManyProperty.substring(0, 1); 119 | String optionsExpression = collectionElement + ".text for " + collectionElement + " in " + oneToManyProperty 120 | + "SelectionList"; 121 | assertThat(selectElement.attr("ng-options"), equalTo(optionsExpression)); 122 | } 123 | 124 | @Test 125 | public void testGenerateManyToManyProperty() throws Exception 126 | { 127 | String manyToManyProperty = "users"; 128 | Map root = createInspectionResultWrapper(ENTITY_NAME, MANY_TO_MANY_PROP); 129 | 130 | Resource templateResource = resourceFactory.create(getClass().getResource( 131 | Deployments.BASE_PACKAGE_PATH + Deployments.N_TO_MANY_PROPERTY_DETAIL_INCLUDE)); 132 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 133 | String output = processor.process(root); 134 | Document html = Jsoup.parseBodyFragment(output); 135 | assertThat(output.trim(), not(equalTo(""))); 136 | 137 | Elements container = html.select("div.form-group"); 138 | assertThat(container, notNullValue()); 139 | assertThat(container.attr("ng-class"), not(equalTo(""))); 140 | 141 | Elements nToManyWidgetElement = html.select("div.form-group > div.col-sm-10"); 142 | assertThat(nToManyWidgetElement, notNullValue()); 143 | 144 | Elements selectElement = nToManyWidgetElement.select(" > select"); 145 | assertThat(selectElement.attr("id"), equalTo(manyToManyProperty)); 146 | assertThat(selectElement.attr("multiple"), notNullValue()); 147 | assertThat(selectElement.attr("ng-model"), equalTo(manyToManyProperty + "Selection")); 148 | String collectionElement = manyToManyProperty.substring(0, 1); 149 | String optionsExpression = collectionElement + ".text for " + collectionElement + " in " + manyToManyProperty 150 | + "SelectionList"; 151 | assertThat(selectElement.attr("ng-options"), equalTo(optionsExpression)); 152 | } 153 | 154 | } 155 | -------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/tests/freemarker/FreemarkerClientPartialsNToOnePropertyTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs.tests.freemarker; 8 | 9 | import static org.hamcrest.core.IsEqual.equalTo; 10 | import static org.hamcrest.core.IsNot.not; 11 | import static org.hamcrest.core.IsNull.notNullValue; 12 | import static org.junit.Assert.assertThat; 13 | 14 | import java.net.URL; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | import javax.inject.Inject; 19 | 20 | import org.hamcrest.core.IsEqual; 21 | import org.jboss.arquillian.container.test.api.Deployment; 22 | import org.jboss.arquillian.junit.Arquillian; 23 | import org.jboss.forge.addon.resource.Resource; 24 | import org.jboss.forge.addon.resource.ResourceFactory; 25 | import org.jboss.forge.addon.templates.Template; 26 | import org.jboss.forge.addon.templates.TemplateFactory; 27 | import org.jboss.forge.addon.templates.freemarker.FreemarkerTemplate; 28 | import org.jboss.forge.arquillian.AddonDependencies; 29 | import org.jboss.forge.arquillian.AddonDependency; 30 | import org.jboss.forge.arquillian.archive.AddonArchive; 31 | import org.jsoup.Jsoup; 32 | import org.jsoup.nodes.Document; 33 | import org.jsoup.select.Elements; 34 | import org.junit.Test; 35 | import org.junit.runner.RunWith; 36 | 37 | /** 38 | * Tests to verify that the generated HTML for 1:1 and M:1 associations of JPA entities are generated correctly. 39 | */ 40 | @RunWith(Arquillian.class) 41 | public class FreemarkerClientPartialsNToOnePropertyTest 42 | { 43 | 44 | @Inject 45 | private ResourceFactory resourceFactory; 46 | 47 | @Inject 48 | private TemplateFactory processorFactory; 49 | 50 | @Deployment 51 | @AddonDependencies({ 52 | @AddonDependency(name = "org.jboss.forge.addon:scaffold-spi"), 53 | @AddonDependency(name = "org.jboss.forge.addon:javaee"), 54 | @AddonDependency(name = "org.jboss.forge.addon:templates"), 55 | @AddonDependency(name = "org.jboss.forge.addon:text"), 56 | @AddonDependency(name = "org.jboss.forge.addon:convert"), 57 | @AddonDependency(name = "org.jboss.forge.addon:parser-java"), 58 | @AddonDependency(name = "org.jboss.forge.furnace.container:cdi") 59 | }) 60 | public static AddonArchive getDeployment() 61 | { 62 | return Deployments.getDeployment(); 63 | } 64 | 65 | @Test 66 | public void testGenerateHiddenProperty() throws Exception 67 | { 68 | Map idProperties = new HashMap(); 69 | idProperties.put("name", "id"); 70 | idProperties.put("identifier", "id"); 71 | idProperties.put("label", "Id"); 72 | idProperties.put("hidden", "true"); 73 | idProperties.put("type", "number"); 74 | 75 | Map root = new HashMap(); 76 | root.put("entityName", "SampleEntity"); 77 | root.put("property", idProperties); 78 | Resource templateResource = resourceFactory.create(getClass().getResource( 79 | Deployments.BASE_PACKAGE_PATH + Deployments.N_TO_ONE_PROPERTY_DETAIL_INCLUDE)); 80 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 81 | String output = processor.process(root); 82 | assertThat(output.trim(), IsEqual.equalTo("")); 83 | } 84 | 85 | @Test 86 | public void testGenerateHiddenAndRequiredProperty() throws Exception 87 | { 88 | Map idProperties = new HashMap(); 89 | idProperties.put("name", "id"); 90 | idProperties.put("identifier", "id"); 91 | idProperties.put("label", "Id"); 92 | idProperties.put("hidden", "true"); 93 | idProperties.put("required", "true"); 94 | idProperties.put("type", "number"); 95 | 96 | Map root = new HashMap(); 97 | root.put("entityName", "SampleEntity"); 98 | root.put("property", idProperties); 99 | Resource templateResource = resourceFactory.create(getClass().getResource( 100 | Deployments.BASE_PACKAGE_PATH + Deployments.N_TO_ONE_PROPERTY_DETAIL_INCLUDE)); 101 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 102 | String output = processor.process(root); 103 | assertThat(output.trim(), IsEqual.equalTo("")); 104 | } 105 | 106 | @Test 107 | public void testGenerateOneToOneProperty() throws Exception 108 | { 109 | Map voucherProperties = new HashMap(); 110 | String oneToOneProperty = "voucher"; 111 | voucherProperties.put("name", oneToOneProperty); 112 | voucherProperties.put("identifier", oneToOneProperty); 113 | voucherProperties.put("label", "Voucher"); 114 | voucherProperties.put("type", "com.example.scaffoldtester.model.DiscountVoucher"); 115 | voucherProperties.put("one-to-one", "true"); 116 | voucherProperties.put("simpleType", "DiscountVoucher"); 117 | voucherProperties.put("optionLabel", "id"); 118 | 119 | Map root = new HashMap(); 120 | String entityName = "SampleEntity"; 121 | root.put("entityName", entityName); 122 | root.put("property", voucherProperties); 123 | Resource templateResource = resourceFactory.create(getClass().getResource( 124 | Deployments.BASE_PACKAGE_PATH + Deployments.N_TO_ONE_PROPERTY_DETAIL_INCLUDE)); 125 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 126 | String output = processor.process(root); 127 | Document html = Jsoup.parseBodyFragment(output); 128 | assertThat(output.trim(), not(equalTo(""))); 129 | 130 | Elements container = html.select("div.form-group"); 131 | assertThat(container, notNullValue()); 132 | assertThat(container.attr("ng-class"), not(equalTo(""))); 133 | 134 | Elements oneToOneWidgetElement = html.select("div.form-group > div.col-sm-10"); 135 | assertThat(oneToOneWidgetElement, notNullValue()); 136 | 137 | Elements selectElement = oneToOneWidgetElement.select(" > select"); 138 | assertThat(selectElement, notNullValue()); 139 | assertThat(selectElement.attr("id"), equalTo(oneToOneProperty)); 140 | String collectionElement = oneToOneProperty.substring(0, 1); 141 | String optionsExpression = collectionElement + ".text for " + collectionElement + " in " 142 | + oneToOneProperty + "SelectionList"; 143 | assertThat(selectElement.attr("ng-options"), equalTo(optionsExpression)); 144 | assertThat(selectElement.attr("ng-model"), equalTo(oneToOneProperty + "Selection")); 145 | } 146 | 147 | @Test 148 | public void testGenerateManyToOneProperty() throws Exception 149 | { 150 | Map customerProperties = new HashMap(); 151 | String oneToOneProperty = "customer"; 152 | customerProperties.put("name", oneToOneProperty); 153 | customerProperties.put("identifier", oneToOneProperty); 154 | customerProperties.put("label", "Customer"); 155 | customerProperties.put("type", "com.example.scaffoldtester.model.Customer"); 156 | customerProperties.put("many-to-one", "true"); 157 | customerProperties.put("simpleType", "Customer"); 158 | customerProperties.put("optionLabel", "id"); 159 | 160 | Map root = new HashMap(); 161 | String entityName = "SampleEntity"; 162 | root.put("entityName", entityName); 163 | root.put("property", customerProperties); 164 | Resource templateResource = resourceFactory.create(getClass().getResource( 165 | Deployments.BASE_PACKAGE_PATH + Deployments.N_TO_ONE_PROPERTY_DETAIL_INCLUDE)); 166 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 167 | String output = processor.process(root); 168 | Document html = Jsoup.parseBodyFragment(output); 169 | assertThat(output.trim(), not(equalTo(""))); 170 | 171 | Elements container = html.select("div.form-group"); 172 | assertThat(container, notNullValue()); 173 | assertThat(container.attr("ng-class"), not(equalTo(""))); 174 | 175 | Elements oneToOneWidgetElement = html.select("div.form-group > div.col-sm-10"); 176 | assertThat(oneToOneWidgetElement, notNullValue()); 177 | 178 | Elements selectElement = oneToOneWidgetElement.select(" > select"); 179 | assertThat(selectElement, notNullValue()); 180 | assertThat(selectElement.attr("id"), equalTo(oneToOneProperty)); 181 | String collectionElement = oneToOneProperty.substring(0, 1); 182 | String optionsExpression = collectionElement + ".text for " + collectionElement + " in " 183 | + oneToOneProperty + "SelectionList"; 184 | assertThat(selectElement.attr("ng-options"), equalTo(optionsExpression)); 185 | assertThat(selectElement.attr("ng-model"), equalTo(oneToOneProperty + "Selection")); 186 | } 187 | 188 | } 189 | -------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/tests/freemarker/FreemarkerClientPartialsSearchInputTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2014 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs.tests.freemarker; 8 | 9 | import static org.hamcrest.core.IsEqual.equalTo; 10 | import static org.hamcrest.core.IsNot.not; 11 | import static org.hamcrest.core.IsNull.notNullValue; 12 | import static org.jboss.forge.addon.angularjs.TestHelpers.BASIC_STRING_PROP; 13 | import static org.jboss.forge.addon.angularjs.TestHelpers.BOOLEAN_PROP; 14 | import static org.jboss.forge.addon.angularjs.TestHelpers.DATE_PROP; 15 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_ID_PROP; 16 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_NAME; 17 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_VERSION_PROP; 18 | import static org.jboss.forge.addon.angularjs.TestHelpers.MANY_TO_MANY_PROP; 19 | import static org.jboss.forge.addon.angularjs.TestHelpers.MANY_TO_ONE_PROP; 20 | import static org.jboss.forge.addon.angularjs.TestHelpers.NUMBER_PROP; 21 | import static org.jboss.forge.addon.angularjs.TestHelpers.ONE_TO_MANY_PROP; 22 | import static org.jboss.forge.addon.angularjs.TestHelpers.ONE_TO_ONE_PROP; 23 | import static org.jboss.forge.addon.angularjs.TestHelpers.createInspectionResultWrapper; 24 | import static org.junit.Assert.assertThat; 25 | 26 | import java.net.URL; 27 | import java.util.Map; 28 | 29 | import javax.inject.Inject; 30 | 31 | import org.hamcrest.core.IsEqual; 32 | import org.jboss.arquillian.container.test.api.Deployment; 33 | import org.jboss.arquillian.junit.Arquillian; 34 | import org.jboss.forge.addon.angularjs.TestHelpers; 35 | import org.jboss.forge.addon.resource.Resource; 36 | import org.jboss.forge.addon.resource.ResourceFactory; 37 | import org.jboss.forge.addon.templates.Template; 38 | import org.jboss.forge.addon.templates.TemplateFactory; 39 | import org.jboss.forge.addon.templates.freemarker.FreemarkerTemplate; 40 | import org.jboss.forge.arquillian.AddonDependencies; 41 | import org.jboss.forge.arquillian.AddonDependency; 42 | import org.jboss.forge.arquillian.archive.AddonArchive; 43 | import org.jsoup.Jsoup; 44 | import org.jsoup.nodes.Document; 45 | import org.jsoup.select.Elements; 46 | import org.junit.Test; 47 | import org.junit.runner.RunWith; 48 | 49 | /** 50 | * Tests to verify that the generated HTML of the search page is generated correctly. 51 | */ 52 | @RunWith(Arquillian.class) 53 | public class FreemarkerClientPartialsSearchInputTest { 54 | 55 | @Inject 56 | private ResourceFactory resourceFactory; 57 | 58 | @Inject 59 | private TemplateFactory processorFactory; 60 | 61 | @Deployment 62 | @AddonDependencies({ 63 | @AddonDependency(name = "org.jboss.forge.addon:scaffold-spi"), 64 | @AddonDependency(name = "org.jboss.forge.addon:javaee"), 65 | @AddonDependency(name = "org.jboss.forge.addon:templates"), 66 | @AddonDependency(name = "org.jboss.forge.addon:text"), 67 | @AddonDependency(name = "org.jboss.forge.addon:convert"), 68 | @AddonDependency(name = "org.jboss.forge.addon:parser-java"), 69 | @AddonDependency(name = "org.jboss.forge.furnace.container:cdi") 70 | }) 71 | public static AddonArchive getDeployment() 72 | { 73 | return Deployments.getDeployment(); 74 | } 75 | 76 | @Test 77 | public void testGenerateHiddenProperty() throws Exception { 78 | Map root = createInspectionResultWrapper(ENTITY_NAME, ENTITY_VERSION_PROP); 79 | 80 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 81 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 82 | String output = processor.process(root); 83 | assertThat(output.trim(), IsEqual.equalTo("")); 84 | } 85 | 86 | @Test 87 | public void testGenerateHiddenAndRequiredProperty() throws Exception { 88 | Map root = createInspectionResultWrapper(ENTITY_NAME, ENTITY_ID_PROP); 89 | 90 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 91 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 92 | String output = processor.process(root); 93 | assertThat(output.trim(), IsEqual.equalTo("")); 94 | } 95 | 96 | @Test 97 | public void testGenerateOneToManyProperty() throws Exception { 98 | Map root = TestHelpers.createInspectionResultWrapper(ENTITY_NAME, ONE_TO_MANY_PROP); 99 | 100 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 101 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 102 | String output = processor.process(root); 103 | assertThat(output.trim(), IsEqual.equalTo("")); 104 | } 105 | 106 | @Test 107 | public void testGenerateManyToManyProperty() throws Exception { 108 | Map root = TestHelpers.createInspectionResultWrapper(ENTITY_NAME, MANY_TO_MANY_PROP); 109 | 110 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 111 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 112 | String output = processor.process(root); 113 | assertThat(output.trim(), IsEqual.equalTo("")); 114 | } 115 | 116 | @Test 117 | public void testGenerateBasicStringProperty() throws Exception { 118 | Map root = TestHelpers.createInspectionResultWrapper(ENTITY_NAME, BASIC_STRING_PROP); 119 | 120 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 121 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 122 | String output = processor.process(root); 123 | Document html = Jsoup.parseBodyFragment(output); 124 | assertThat(output.trim(), not(equalTo(""))); 125 | 126 | Elements container = html.select("div.form-group"); 127 | assertThat(container, notNullValue()); 128 | 129 | Elements formInputElement = container.select("div.col-sm-10 > input"); 130 | assertThat(formInputElement.attr("id"), equalTo("fullName")); 131 | assertThat(formInputElement.attr("type"), equalTo("text")); 132 | assertThat(formInputElement.attr("ng-model"), equalTo("search" + "." + "fullName")); 133 | } 134 | 135 | @Test 136 | public void testGenerateBasicNumberProperty() throws Exception { 137 | Map root = TestHelpers.createInspectionResultWrapper(ENTITY_NAME, NUMBER_PROP); 138 | 139 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 140 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 141 | String output = processor.process(root); 142 | Document html = Jsoup.parseBodyFragment(output); 143 | assertThat(output.trim(), not(equalTo(""))); 144 | 145 | Elements container = html.select("div.form-group"); 146 | assertThat(container, notNullValue()); 147 | 148 | Elements formInputElement = container.select("div.col-sm-10 > input"); 149 | assertThat(formInputElement.attr("id"), equalTo("score")); 150 | assertThat(formInputElement.attr("type"), equalTo("text")); 151 | assertThat(formInputElement.attr("ng-model"), equalTo("search" + "." + "score")); 152 | } 153 | 154 | @Test 155 | public void testGenerateBasicBooleanProperty() throws Exception { 156 | Map root = TestHelpers.createInspectionResultWrapper(ENTITY_NAME, BOOLEAN_PROP); 157 | 158 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 159 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 160 | String output = processor.process(root); 161 | Document html = Jsoup.parseBodyFragment(output); 162 | assertThat(output.trim(), not(equalTo(""))); 163 | 164 | Elements container = html.select("div.form-group"); 165 | assertThat(container, notNullValue()); 166 | 167 | Elements formInputElement = container.select("div.col-sm-10 > select"); 168 | assertThat(formInputElement.attr("id"), equalTo("optForMail")); 169 | assertThat(formInputElement.attr("ng-model"), equalTo("search" + "." + "optForMail")); 170 | } 171 | 172 | @Test 173 | public void testGenerateBasicDateProperty() throws Exception { 174 | Map root = TestHelpers.createInspectionResultWrapper(ENTITY_NAME, DATE_PROP); 175 | 176 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 177 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 178 | String output = processor.process(root); 179 | Document html = Jsoup.parseBodyFragment(output); 180 | assertThat(output.trim(), not(equalTo(""))); 181 | 182 | Elements container = html.select("div.form-group"); 183 | assertThat(container, notNullValue()); 184 | 185 | Elements formInputElement = container.select("div.col-sm-10 > input"); 186 | assertThat(formInputElement.attr("id"), equalTo("dateOfBirth")); 187 | assertThat(formInputElement.attr("type"), equalTo("text")); 188 | assertThat(formInputElement.attr("ng-model"), equalTo("search" + "." + "dateOfBirth")); 189 | } 190 | 191 | @Test 192 | public void testGenerateOneToOneProperty() throws Exception { 193 | Map root = TestHelpers.createInspectionResultWrapper(ENTITY_NAME, ONE_TO_ONE_PROP); 194 | 195 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 196 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 197 | String output = processor.process(root); 198 | Document html = Jsoup.parseBodyFragment(output); 199 | assertThat(output.trim(), not(equalTo(""))); 200 | 201 | Elements container = html.select("div.form-group"); 202 | assertThat(container, notNullValue()); 203 | 204 | Elements formInputElement = container.select("div.col-sm-10 > select"); 205 | assertThat(formInputElement.attr("id"), equalTo("voucher")); 206 | assertThat(formInputElement.attr("ng-model"), equalTo("search" + "." + "voucher")); 207 | } 208 | 209 | @Test 210 | public void testGenerateManyToOneProperty() throws Exception { 211 | Map root = TestHelpers.createInspectionResultWrapper(ENTITY_NAME, MANY_TO_ONE_PROP); 212 | 213 | Resource templateResource = resourceFactory.create(getClass().getResource(Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_FORM_INPUT)); 214 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 215 | String output = processor.process(root); 216 | Document html = Jsoup.parseBodyFragment(output); 217 | assertThat(output.trim(), not(equalTo(""))); 218 | 219 | Elements container = html.select("div.form-group"); 220 | assertThat(container, notNullValue()); 221 | 222 | Elements formInputElement = container.select("div.col-sm-10 > select"); 223 | assertThat(formInputElement.attr("id"), equalTo("customer")); 224 | assertThat(formInputElement.attr("ng-model"), equalTo("search" + "." + "customer")); 225 | } 226 | 227 | } 228 | -------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/tests/freemarker/FreemarkerClientPartialsSearchResultsPaginatorTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2014 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs.tests.freemarker; 8 | 9 | import static org.junit.Assert.assertThat; 10 | 11 | import java.net.URL; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | import javax.inject.Inject; 16 | 17 | import org.hamcrest.core.IsEqual; 18 | import org.jboss.arquillian.container.test.api.Deployment; 19 | import org.jboss.arquillian.junit.Arquillian; 20 | import org.jboss.forge.addon.resource.Resource; 21 | import org.jboss.forge.addon.resource.ResourceFactory; 22 | import org.jboss.forge.addon.templates.Template; 23 | import org.jboss.forge.addon.templates.TemplateFactory; 24 | import org.jboss.forge.addon.templates.freemarker.FreemarkerTemplate; 25 | import org.jboss.forge.arquillian.AddonDependencies; 26 | import org.jboss.forge.arquillian.AddonDependency; 27 | import org.jboss.forge.arquillian.archive.AddonArchive; 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 30 | 31 | /** 32 | * Tests to verify that the generated HTML the paginator in the search page is generated correctly. 33 | */ 34 | @RunWith(Arquillian.class) 35 | public class FreemarkerClientPartialsSearchResultsPaginatorTest 36 | { 37 | 38 | @Inject 39 | private ResourceFactory resourceFactory; 40 | 41 | @Inject 42 | private TemplateFactory processorFactory; 43 | 44 | @Deployment 45 | @AddonDependencies({ 46 | @AddonDependency(name = "org.jboss.forge.addon:scaffold-spi"), 47 | @AddonDependency(name = "org.jboss.forge.addon:javaee"), 48 | @AddonDependency(name = "org.jboss.forge.addon:templates"), 49 | @AddonDependency(name = "org.jboss.forge.addon:text"), 50 | @AddonDependency(name = "org.jboss.forge.addon:convert"), 51 | @AddonDependency(name = "org.jboss.forge.addon:parser-java"), 52 | @AddonDependency(name = "org.jboss.forge.furnace.container:cdi") 53 | }) 54 | public static AddonArchive getDeployment() 55 | { 56 | return Deployments.getDeployment(); 57 | } 58 | 59 | private static String PAGINATOR_OUTPUT = "
    \n" 60 | + 61 | "
  • \n" 62 | + 63 | " «\n" 64 | + 65 | "
  • \n" 66 | + 67 | "
  • \n" 68 | + 69 | " 1\n" + 70 | "
  • \n" + 71 | "
  • \n" + 72 | " »\n" + 73 | "
  • \n" + 74 | "
\n"; 75 | 76 | @Test 77 | public void testGenerateSearchResultsPaginator() throws Exception 78 | { 79 | Map idProperties = new HashMap(); 80 | idProperties.put("name", "id"); 81 | idProperties.put("hidden", "true"); 82 | idProperties.put("type", "number"); 83 | 84 | Map root = new HashMap(); 85 | root.put("entityName", "SampleEntity"); 86 | root.put("property", idProperties); 87 | Resource templateResource = resourceFactory.create(getClass().getResource( 88 | Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_RESULTS_PAGINATOR_INCLUDE)); 89 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 90 | String output = processor.process(root); 91 | assertThat(output, IsEqual.equalTo(PAGINATOR_OUTPUT)); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/test/java/org/jboss/forge/addon/angularjs/tests/freemarker/FreemarkerClientTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2014 Red Hat, Inc. and/or its affiliates. 3 | * 4 | * Licensed under the Eclipse Public License version 1.0, available at 5 | * http://www.eclipse.org/legal/epl-v10.html 6 | */ 7 | package org.jboss.forge.addon.angularjs.tests.freemarker; 8 | 9 | import static org.jboss.forge.addon.angularjs.TestHelpers.BASIC_STRING_PROP; 10 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_ID_PROP; 11 | import static org.jboss.forge.addon.angularjs.TestHelpers.ENTITY_VERSION_PROP; 12 | import static org.jboss.forge.addon.angularjs.TestHelpers.createEntityRootmap; 13 | import static org.jboss.forge.addon.angularjs.TestHelpers.createGlobalRootmap; 14 | import static org.junit.Assert.assertThat; 15 | 16 | import java.net.URL; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | import javax.inject.Inject; 22 | 23 | import org.hamcrest.core.IsNull; 24 | import org.jboss.arquillian.container.test.api.Deployment; 25 | import org.jboss.arquillian.junit.Arquillian; 26 | import org.jboss.forge.addon.resource.Resource; 27 | import org.jboss.forge.addon.resource.ResourceFactory; 28 | import org.jboss.forge.addon.templates.Template; 29 | import org.jboss.forge.addon.templates.TemplateFactory; 30 | import org.jboss.forge.addon.templates.freemarker.FreemarkerTemplate; 31 | import org.jboss.forge.arquillian.AddonDependencies; 32 | import org.jboss.forge.arquillian.AddonDependency; 33 | import org.jboss.forge.arquillian.archive.AddonArchive; 34 | import org.junit.Test; 35 | import org.junit.runner.RunWith; 36 | 37 | /** 38 | * Tests to verify that Freemarker templates that generate JavaScript work. Verifies that the templates dont error out 39 | * during processing. Functional tests verify whether the generated JavaScript actually work. 40 | */ 41 | @RunWith(Arquillian.class) 42 | public class FreemarkerClientTest 43 | { 44 | 45 | @Inject 46 | private ResourceFactory resourceFactory; 47 | 48 | @Inject 49 | private TemplateFactory processorFactory; 50 | 51 | @Deployment 52 | @AddonDependencies({ 53 | @AddonDependency(name = "org.jboss.forge.addon:projects"), 54 | @AddonDependency(name = "org.jboss.forge.addon:scaffold-spi"), 55 | @AddonDependency(name = "org.jboss.forge.addon:javaee"), 56 | @AddonDependency(name = "org.jboss.forge.addon:templates"), 57 | @AddonDependency(name = "org.jboss.forge.addon:text"), 58 | @AddonDependency(name = "org.jboss.forge.addon:convert"), 59 | @AddonDependency(name = "org.jboss.forge.addon:parser-java"), 60 | @AddonDependency(name = "org.jboss.forge.furnace.container:cdi") 61 | }) 62 | public static AddonArchive getDeployment() 63 | { 64 | return Deployments.getDeployment(); 65 | } 66 | 67 | @Test 68 | public void testGenerateNewEntityController() throws Exception 69 | { 70 | List> entityAttributeProperties = new ArrayList>(); 71 | entityAttributeProperties.add(ENTITY_ID_PROP); 72 | entityAttributeProperties.add(ENTITY_VERSION_PROP); 73 | entityAttributeProperties.add(BASIC_STRING_PROP); 74 | Map root = createEntityRootmap(entityAttributeProperties); 75 | 76 | Resource templateResource = resourceFactory.create(getClass().getResource( 77 | Deployments.BASE_PACKAGE_PATH + Deployments.NEW_ENTITY_CONTROLLER_JS)); 78 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 79 | String output = processor.process(root); 80 | assertThat(output, IsNull.notNullValue()); 81 | } 82 | 83 | @Test 84 | public void testGenerateEditEntityController() throws Exception 85 | { 86 | List> entityAttributeProperties = new ArrayList>(); 87 | entityAttributeProperties.add(ENTITY_ID_PROP); 88 | entityAttributeProperties.add(ENTITY_VERSION_PROP); 89 | entityAttributeProperties.add(BASIC_STRING_PROP); 90 | Map root = createEntityRootmap(entityAttributeProperties); 91 | 92 | Resource templateResource = resourceFactory.create(getClass().getResource( 93 | Deployments.BASE_PACKAGE_PATH + Deployments.EDIT_ENTITY_CONTROLLER_JS)); 94 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 95 | String output = processor.process(root); 96 | assertThat(output, IsNull.notNullValue()); 97 | } 98 | 99 | @Test 100 | public void testGenerateSearchEntityController() throws Exception 101 | { 102 | List> entityAttributeProperties = new ArrayList>(); 103 | entityAttributeProperties.add(ENTITY_ID_PROP); 104 | entityAttributeProperties.add(ENTITY_VERSION_PROP); 105 | entityAttributeProperties.add(BASIC_STRING_PROP); 106 | Map root = createEntityRootmap(entityAttributeProperties); 107 | 108 | Resource templateResource = resourceFactory.create(getClass().getResource( 109 | Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_ENTITY_CONTROLLER_JS)); 110 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 111 | String output = processor.process(root); 112 | assertThat(output, IsNull.notNullValue()); 113 | } 114 | 115 | @Test 116 | public void testGenerateEntityFactory() throws Exception 117 | { 118 | List> entityAttributeProperties = new ArrayList>(); 119 | entityAttributeProperties.add(ENTITY_ID_PROP); 120 | entityAttributeProperties.add(ENTITY_VERSION_PROP); 121 | entityAttributeProperties.add(BASIC_STRING_PROP); 122 | Map root = createEntityRootmap(entityAttributeProperties); 123 | 124 | Resource templateResource = resourceFactory.create(getClass().getResource( 125 | Deployments.BASE_PACKAGE_PATH + Deployments.ENTITY_FACTORY)); 126 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 127 | String output = processor.process(root); 128 | assertThat(output, IsNull.notNullValue()); 129 | } 130 | 131 | @Test 132 | public void testGenerateDetailPartial() throws Exception 133 | { 134 | List> entityAttributeProperties = new ArrayList>(); 135 | entityAttributeProperties.add(ENTITY_ID_PROP); 136 | entityAttributeProperties.add(ENTITY_VERSION_PROP); 137 | entityAttributeProperties.add(BASIC_STRING_PROP); 138 | Map root = createEntityRootmap(entityAttributeProperties); 139 | 140 | Resource templateResource = resourceFactory.create(getClass().getResource( 141 | Deployments.BASE_PACKAGE_PATH + Deployments.DETAIL_VIEW)); 142 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 143 | String output = processor.process(root); 144 | assertThat(output, IsNull.notNullValue()); 145 | } 146 | 147 | @Test 148 | public void testGenerateSearchPartial() throws Exception 149 | { 150 | List> entityAttributeProperties = new ArrayList>(); 151 | entityAttributeProperties.add(ENTITY_ID_PROP); 152 | entityAttributeProperties.add(ENTITY_VERSION_PROP); 153 | entityAttributeProperties.add(BASIC_STRING_PROP); 154 | Map root = createEntityRootmap(entityAttributeProperties); 155 | 156 | Resource templateResource = resourceFactory.create(getClass().getResource( 157 | Deployments.BASE_PACKAGE_PATH + Deployments.SEARCH_VIEW)); 158 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 159 | String output = processor.process(root); 160 | assertThat(output, IsNull.notNullValue()); 161 | } 162 | 163 | @Test 164 | public void testGenerateIndex() throws Exception 165 | { 166 | Map root = createGlobalRootmap(); 167 | 168 | Resource templateResource = resourceFactory.create(getClass().getResource( 169 | Deployments.BASE_PACKAGE_PATH + Deployments.INDEX_PAGE)); 170 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 171 | String output = processor.process(root); 172 | assertThat(output, IsNull.notNullValue()); 173 | } 174 | 175 | @Test 176 | public void testGenerateAngularApplication() throws Exception 177 | { 178 | Map root = createGlobalRootmap(); 179 | 180 | Resource templateResource = resourceFactory.create(getClass().getResource( 181 | Deployments.BASE_PACKAGE_PATH + Deployments.APP_JS)); 182 | Template processor = processorFactory.create(templateResource, FreemarkerTemplate.class); 183 | String output = processor.process(root); 184 | assertThat(output, IsNull.notNullValue()); 185 | } 186 | 187 | } 188 | --------------------------------------------------------------------------------