diff --git a/README.md b/README.md
index da77a81..dc1fe36 100644
--- a/README.md
+++ b/README.md
@@ -25,11 +25,12 @@ The list of what Damascus automatically generate is as follows
* Template generation
### Required environment
-* Liferay 7.0 CE GA7 and Liferay DXP SP11 or higher versions.
-* Liferay 7.1 CE GA1 and higher.
+* Liferay 7.3 CE GA2 and higher.
* Liferay 7.2 CE GA1 and higher.
+* Liferay 7.1 CE GA1 and higher.
+* Liferay 7.0 CE GA7 and Liferay DXP SP11 or higher versions.
* Java 1.8 or above
-* gradle 3.0 or above need to be installed
+* gradle 5.4.6 or above need to be installed
* jpm needs to be installed. (instruction to install is as follows)
### How to Install
@@ -58,7 +59,7 @@ Let's make a Todo app with damascus
### How to compile Damascus on your own?
1. Clone this repository to your local. Please make sure you've already installed Gradle 3.0 or above and jpm.
-2. At the root directory, run ```gradle assemble``` then ```damascus.jar``` will be created under ```/build/libs/``` directory.
+2. At the root directory, run ```./gradlew assemble``` then ```damascus.jar``` will be created under ```/build/libs/``` directory.
3. If you've already installed damascus, uninstall it first with ```jpm remove damascus```. Then install your jar with ```jpm install ./damascus.jar```.
### Proxy settings
@@ -69,7 +70,7 @@ Damascus is including lombok library, so annotation library for lombok needs to
##### Eclipse (Not Liferay Developer Studio)
1. Download lombok https://projectlombok.org/download
2. double click ```lombok.jar``` and select the directory where ```eclipse.exe``` exist
-3. Run ```gradle eclipse``` at the project directory and restart IDE, and right click on the project and display context name, and choose ```gradle > Refresh gradle project```
+3. Run ```./gradlew eclipse``` at the project directory and restart IDE, and right click on the project and display context name, and choose ```gradle > Refresh gradle project```
4. Java files will be displayed properly without errors.
##### IntelliJ
1. ```Preferences - Plugins``` and search Lombok. Install the Lombok plugin.
@@ -79,14 +80,14 @@ Damascus is including lombok library, so annotation library for lombok needs to
In terms of bugs, please post Github issues or send me a PR. To send me PR, please follow the process below.
1. Fix bugs at your local
2. Remove ```${user}/.damascus``` folder.
-3. Run test locally with this command ```gradle clean test``` and confirm your fix pass all tests.
+3. Run test locally with this command ```./gradlew clean test --info``` and confirm your fix pass all tests.
4. Send PR to /development repository. I'll create a fix brunch accordingly.
### Enhancement requests
A contribution is always welcome! In terms of an Enhancement request, please follow the process below. If you wonder it's a complex feature, please create an issue first and let's discuss. In terms of simple enhancement, please follow steps below.
1. After implementing your feature, please add a test as well. Spock test is preferable because it's more readable and flexible to add tests later on. To add tests, tests are separated by classes, and in a test class, each test should be written each method basis.
-2. Run test locally with ```gradle clean test``` until your code pass all tests
+2. Run test locally with ```./gradlew clean test --info``` until your code pass all tests
3. Send a PR to /development branch. According to the status of Travis CI / Appveyor, I may create a feature branch and request you to make it pass the test on Travis CI / Appveyor environment.
4. After all tests pass on Travis CI / Appveyor, will merge into the development branch and release into master at some points according to the impact of the code.
diff --git a/build.gradle b/build.gradle
index d2a644e..0355504 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,7 +9,7 @@ buildscript {
}
plugins {
- id 'io.franzbecker.gradle-lombok' version '3.2.0'
+ id "io.freefair.lombok" version "5.1.0"
id 'java'
id 'groovy'
id 'eclipse'
@@ -20,11 +20,6 @@ plugins {
apply plugin: 'com.github.kt3k.coveralls'
-lombok { // optional: values below are the defaults
- version = "1.18.10"
- sha256 = ""
-}
-
sourceCompatibility = 1.8
targetCompatibility = 1.8
@@ -34,17 +29,16 @@ def defaultEncoding = 'UTF-8'
repositories {
mavenCentral()
jcenter()
- maven {
- url 'https://repo.gradle.org/gradle/libs-releases'
- url "http://repository.jboss.org/nexus/content/groups/public-jboss" // JBoss
- url "http://repository.apache.org/content/groups/public" // Apache
- url "http://repository.springsource.com/maven/bundles/release" // SpringSource
- url "http://repository.codehaus.org" // Codehaus
- url "http://download.java.net/maven/2" // Java.NET
- url "http://download.java.net/maven/glassfish" // Glassfish
- url "http://m2repo.spockframework.org/snapshots" // Spock Snapshot
- url "http://repository.sonatype.org/content/groups/public"
- }
+ maven { url 'https://repo.gradle.org/gradle/libs-releases'}
+ maven { url 'https://repo.gradle.org/gradle/libs-releases-local' }
+ maven { url "http://repository.jboss.org/nexus/content/groups/public-jboss" }
+ maven { url "http://repository.apache.org/content/groups/public" }
+ maven { url "http://repository.springsource.com/maven/bundles/release" }
+ maven { url "http://repository.codehaus.org" }
+ maven { url "http://download.java.net/maven/2" }
+ maven { url "http://download.java.net/maven/glassfish" }
+ maven { url "http://m2repo.spockframework.org/snapshots" }
+ maven { url "http://repository.sonatype.org/content/groups/public" }
}
generateGrammarSource {
@@ -53,12 +47,11 @@ generateGrammarSource {
outputDirectory = file('src/main/java/com/liferay/damascus/antlr/template')
}
-
jar {
manifest {
attributes(
"Bundle-SymbolicName": "com.liferay.damascus.cli",
- "Bundle-Version": "1.1.5",
+ "Bundle-Version": "1.1.6",
"Bundle-Description": "Liferay extension tool for scaffolding service builder portlet",
"Main-Class": "com.liferay.damascus.cli.Damascus",
"JPM-Command": "damascus"
@@ -71,33 +64,33 @@ jar {
dependencies {
compile 'com.beust:jcommander:1.72'
- compile 'com.google.guava:guava:28.1-jre'
- compile 'commons-io:commons-io:2.6'
- compile 'org.apache.commons:commons-lang3:3.7'
- compile 'org.apache.commons:commons-configuration2:2.6'
- compile 'commons-beanutils:commons-beanutils:1.9.+'
+ compile 'com.google.guava:guava:29.0-jre'
+ compile 'commons-io:commons-io:2.7'
+ compile 'org.apache.commons:commons-lang3:3.10'
+ compile 'org.apache.commons:commons-configuration2:2.7'
+ compile 'commons-beanutils:commons-beanutils:1.9.4'
compile 'com.jayway.jsonpath:json-path:2.4.+'
- compile 'org.freemarker:freemarker:2.3.28'
- compile 'com.liferay:com.liferay.project.templates:5.0.2'
- compile 'org.slf4j:slf4j-api:1.7.25'
- compile 'org.slf4j:slf4j-log4j12:1.7.25'
- compile 'com.fasterxml.jackson.core:jackson-core:2.9.+'
- compile 'com.fasterxml.jackson.core:jackson-databind:2.9.+'
- compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.+'
- compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.+'
- compile 'joda-time:joda-time:2.9.+'
- compile 'org.gradle:gradle-tooling-api:4.3'
+ compile 'org.freemarker:freemarker:2.3.30'
+ compile 'com.liferay:com.liferay.project.templates:5.0.32'
+ compile 'org.gradle:gradle-tooling-api:4.10.3'
+ compile 'org.slf4j:slf4j-api:1.7.+'
+ compile 'org.slf4j:slf4j-log4j12:1.7.+'
+ compile 'com.fasterxml.jackson.core:jackson-core:2.11.+'
+ compile 'com.fasterxml.jackson.core:jackson-databind:2.11.+'
+ compile 'com.fasterxml.jackson.core:jackson-annotations:2.11.+'
+ compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.11.+'
+ compile 'joda-time:joda-time:2.10.+'
compile 'org.codehaus.groovy:groovy-all:2.5.8'
- compile group: 'org.antlr', name: 'antlr4', version: '4.7.2'
- compile group: 'org.antlr', name: 'antlr4-runtime', version: '4.7.2'
+ compile group: 'org.antlr', name: 'antlr4', version: '4.8-1'
+ compile group: 'org.antlr', name: 'antlr4-runtime', version: '4.8-1'
compile group: 'org.antlr', name: 'antlr4-annotations', version: '4.3'
- antlr 'org.antlr:antlr4:4.7.2'
+ antlr 'org.antlr:antlr4:4.8-1'
- testCompile group: 'org.antlr', name: 'antlr4-runtime-testsuite', version: '4.7.1'
- testCompile group: 'cglib', name: 'cglib-nodep', version:'3.2.5'
+ testCompile group: 'org.antlr', name: 'antlr4-runtime-testsuite', version: '4.8-1'
+ testCompile group: 'cglib', name: 'cglib-nodep', version:'3.3.0'
testCompile group: 'junit', name: 'junit', version:'4.12'
testCompile group: 'org.hamcrest', name: 'hamcrest-core', version:'1.3'
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 7c62705..ce152f6 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
\ No newline at end of file
diff --git a/latest/damascus.jar b/latest/damascus.jar
index 7d3f331..79280f9 100644
Binary files a/latest/damascus.jar and b/latest/damascus.jar differ
diff --git a/src/main/java/com/liferay/damascus/antlr/template/DmscSrcLexer.java b/src/main/java/com/liferay/damascus/antlr/template/DmscSrcLexer.java
index 175118a..83d6e73 100644
--- a/src/main/java/com/liferay/damascus/antlr/template/DmscSrcLexer.java
+++ b/src/main/java/com/liferay/damascus/antlr/template/DmscSrcLexer.java
@@ -1,4 +1,4 @@
-// Generated from DmscSrcLexer.g4 by ANTLR 4.7.2
+// Generated from DmscSrcLexer.g4 by ANTLR 4.8
package com.liferay.damascus.antlr.template;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
@@ -11,7 +11,7 @@
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class DmscSrcLexer extends Lexer {
- static { RuntimeMetaData.checkVersion("4.7.2", RuntimeMetaData.VERSION); }
+ static { RuntimeMetaData.checkVersion("4.8", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
diff --git a/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParser.java b/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParser.java
index 2d0851d..92157c4 100644
--- a/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParser.java
+++ b/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParser.java
@@ -1,4 +1,4 @@
-// Generated from DmscSrcParser.g4 by ANTLR 4.7.2
+// Generated from DmscSrcParser.g4 by ANTLR 4.8
package com.liferay.damascus.antlr.template;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
@@ -11,7 +11,7 @@
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class DmscSrcParser extends Parser {
- static { RuntimeMetaData.checkVersion("4.7.2", RuntimeMetaData.VERSION); }
+ static { RuntimeMetaData.checkVersion("4.8", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
diff --git a/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParserBaseListener.java b/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParserBaseListener.java
index eab54e9..2d69d01 100644
--- a/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParserBaseListener.java
+++ b/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParserBaseListener.java
@@ -1,4 +1,4 @@
-// Generated from DmscSrcParser.g4 by ANTLR 4.7.2
+// Generated from DmscSrcParser.g4 by ANTLR 4.8
package com.liferay.damascus.antlr.template;
import org.antlr.v4.runtime.ParserRuleContext;
diff --git a/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParserListener.java b/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParserListener.java
index cfa2cb8..d28391c 100644
--- a/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParserListener.java
+++ b/src/main/java/com/liferay/damascus/antlr/template/DmscSrcParserListener.java
@@ -1,4 +1,4 @@
-// Generated from DmscSrcParser.g4 by ANTLR 4.7.2
+// Generated from DmscSrcParser.g4 by ANTLR 4.8
package com.liferay.damascus.antlr.template;
import org.antlr.v4.runtime.tree.ParseTreeListener;
diff --git a/src/main/java/com/liferay/damascus/cli/Damascus.java b/src/main/java/com/liferay/damascus/cli/Damascus.java
index ae678ac..e8eeee3 100644
--- a/src/main/java/com/liferay/damascus/cli/Damascus.java
+++ b/src/main/java/com/liferay/damascus/cli/Damascus.java
@@ -19,7 +19,7 @@
@Slf4j
public class Damascus {
- public final static String VERSION = "1.1.5";// + "_" + LocalDateTime.now().toString();
+ public final static String VERSION = "1.1.6";// + "_" + LocalDateTime.now().toString();
/**
* Main
diff --git a/src/main/java/com/liferay/damascus/cli/TemplateGeneratorCommand.java b/src/main/java/com/liferay/damascus/cli/TemplateGeneratorCommand.java
index 56081ff..c03e57b 100644
--- a/src/main/java/com/liferay/damascus/cli/TemplateGeneratorCommand.java
+++ b/src/main/java/com/liferay/damascus/cli/TemplateGeneratorCommand.java
@@ -15,9 +15,6 @@
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
/**
* Template Generator command
*
diff --git a/src/main/java/com/liferay/damascus/cli/common/DamascusProps.java b/src/main/java/com/liferay/damascus/cli/common/DamascusProps.java
index ca5708b..da99fee 100644
--- a/src/main/java/com/liferay/damascus/cli/common/DamascusProps.java
+++ b/src/main/java/com/liferay/damascus/cli/common/DamascusProps.java
@@ -69,6 +69,7 @@ public class DamascusProps {
public static final String VERSION_70 = "7.0";
public static final String VERSION_71 = "7.1";
public static final String VERSION_72 = "7.2";
+ public static final String VERSION_73 = "7.3";
/**
* Service Builder command
diff --git a/src/main/java/com/liferay/damascus/cli/json/Application.java b/src/main/java/com/liferay/damascus/cli/json/Application.java
index aba8e9b..f2017a1 100644
--- a/src/main/java/com/liferay/damascus/cli/json/Application.java
+++ b/src/main/java/com/liferay/damascus/cli/json/Application.java
@@ -1,20 +1,19 @@
package com.liferay.damascus.cli.json;
-import java.security.InvalidParameterException;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.liferay.damascus.cli.json.fields.FieldBase;
-
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
+import java.security.InvalidParameterException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* JSON structure POJO : Application
*
@@ -42,9 +41,6 @@ public class Application {
@JsonProperty(required = true)
public Asset asset = null;
- @JsonProperty(required = true)
- public String fieldsName = null;
-
@JsonProperty(required = true)
public List fields = null;
diff --git a/src/main/java/com/liferay/damascus/cli/json/DamascusBase.java b/src/main/java/com/liferay/damascus/cli/json/DamascusBase.java
index 7cdd22a..9eab4e4 100644
--- a/src/main/java/com/liferay/damascus/cli/json/DamascusBase.java
+++ b/src/main/java/com/liferay/damascus/cli/json/DamascusBase.java
@@ -35,6 +35,9 @@ public class DamascusBase {
public Map customValue;
+ @JsonProperty
+ public boolean useTargetPlatform = false;
+
@JsonProperty(required = true)
public List applications = null;
diff --git a/src/main/resources/templates/7.0/base.json b/src/main/resources/templates/7.0/base.json
index 23ba076..f3c18ed 100644
--- a/src/main/resources/templates/7.0/base.json
+++ b/src/main/resources/templates/7.0/base.json
@@ -20,7 +20,6 @@
"generateActivity": "true",
"trash":"true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/main/resources/templates/7.1/Portlet_XXXXAPI_build.gradle.ftl b/src/main/resources/templates/7.1/Portlet_XXXXAPI_build.gradle.ftl
index c5a53cd..5be98bb 100644
--- a/src/main/resources/templates/7.1/Portlet_XXXXAPI_build.gradle.ftl
+++ b/src/main/resources/templates/7.1/Portlet_XXXXAPI_build.gradle.ftl
@@ -7,9 +7,9 @@ apply plugin: 'eclipse'
dependencies {
compileOnly group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.1.0"
- compileOnly group: "com.liferay", name: "com.liferay.osgi.util", version: "3.0.0"
- compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "3.0.0"
- compileOnly group: "javax.portlet", name: "portlet-api", version: "2.0"
- compileOnly group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
- compileOnly group: "org.osgi", name: "org.osgi.core", version: "6.0.0"
+ compileOnly group: "com.liferay", name: "com.liferay.osgi.util"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "2.0"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.core"<#if useTP?? && false == useTP>, version: "6.0.0"#if>
}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.1/Portlet_XXXXSVC_build.gradle.ftl b/src/main/resources/templates/7.1/Portlet_XXXXSVC_build.gradle.ftl
index 8eec1bc..a350aec 100644
--- a/src/main/resources/templates/7.1/Portlet_XXXXSVC_build.gradle.ftl
+++ b/src/main/resources/templates/7.1/Portlet_XXXXSVC_build.gradle.ftl
@@ -27,19 +27,21 @@ repositories {
dependencies {
compile 'com.google.errorprone:error_prone_annotations:2.0.19'
- compile 'commons-digester:commons-digester:1.8.1'
- compile "com.google.guava:guava:21.0"
- compile "commons-io:commons-io:2.5"
- compile "commons-validator:commons-validator:1.6"
+ compile 'commons-digester:commons-digester<#if useTP?? && false == useTP>:1.8.1#if>'
+ compile "com.google.guava:guava<#if useTP?? && false == useTP>:21.0#if>"
+ compile "commons-io:commons-io<#if useTP?? && false == useTP>:2.5#if>"
+ compile "commons-validator:commons-validator<#if useTP?? && false == useTP>:1.6#if>"
compile "org.apache.commons:commons-lang3:3.5"
- compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.1.0"
- compile group: "com.liferay", name: "com.liferay.portal.spring.extender.api", version: "3.0.0"
- compile group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.osgi.util", version: "3.0.0"
- compile group: "javax.portlet", name: "portlet-api", version: "3.0.0"
- compile group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
- compile group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
+ compileOnly group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.1.0"
+ compileOnly group: "com.liferay", name: "com.liferay.portal.spring.extender.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.osgi.util"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.lang"<#if useTP?? && false == useTP>, version: "1.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.string"<#if useTP?? && false == useTP>, version: "1.0.0"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
compile project(":${dashcaseProjectName}-api")
}
diff --git a/src/main/resources/templates/7.1/Portlet_XXXXWEB_build.gradle.ftl b/src/main/resources/templates/7.1/Portlet_XXXXWEB_build.gradle.ftl
index 2e904ed..8aba91f 100644
--- a/src/main/resources/templates/7.1/Portlet_XXXXWEB_build.gradle.ftl
+++ b/src/main/resources/templates/7.1/Portlet_XXXXWEB_build.gradle.ftl
@@ -28,41 +28,37 @@ repositories {
}
}
-// TODO : This can be removed once you set up IDE. When you import this project into a IDE, you may be asked
-// a path to the gradle root. Then you run "gradle getHomeDir" and use the path for the IDE.
-task getHomeDir << {
- println gradle.gradleHomeDir
-}
-
dependencies {
+ // TODO : Please remove the comment when the project is built. This becomes the cause of error while generating this project
+ // implementation enforcedPlatform(group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1")
compile 'com.google.errorprone:error_prone_annotations:2.0.19'
- compile 'commons-digester:commons-digester:1.8.1'
- compile "com.google.guava:guava:21.0"
- compile "commons-io:commons-io:2.5"
- compile "commons-validator:commons-validator:1.6"
+ compile 'commons-digester:commons-digester<#if useTP?? && false == useTP>:1.8.1#if>'
+ compile "com.google.guava:guava<#if useTP?? && false == useTP>:21.0#if>"
+ compile "commons-io:commons-io<#if useTP?? && false == useTP>:2.5#if>"
+ compile "commons-validator:commons-validator<#if useTP?? && false == useTP>:1.6#if>"
compile "org.apache.commons:commons-lang3:3.5"
compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.1.0"
- compile group: "com.liferay", name: "com.liferay.portal.spring.extender.api", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.application.list.api", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.frontend.taglib", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.item.selector.api", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.item.selector.criteria.api", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.item.selector.taglib", version: "1.0.0"
- compile group: "com.liferay", name: "com.liferay.trash.taglib", version: "3.0.0"
- compile group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "3.0.0"
- compile group: "com.liferay.portal", name: "com.liferay.portal.impl", version: "3.0.0"
- compile group: "com.liferay.portal", name: "com.liferay.util.taglib", version: "3.0.0"
- compile group: "javax.portlet", name: "portlet-api", version: "2.0"
- compile group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
- compile group: "jstl", name: "jstl", version: "1.2"
- compile group: "org.osgi", name: "osgi.cmpn", version: "6.0.0"
- compile group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
- compile group: 'org.apache.poi', name: 'poi-ooxml', version: '4.0.1'
- compile group: 'org.apache.poi', name: 'poi', version: '4.0.1'
- compile group: 'org.apache.poi', name: 'poi-ooxml-schemas', version: '4.0.1'
- compile group: 'org.apache.xmlbeans', name: 'xmlbeans', version: '3.0.2'
- compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.2'
- compile group: 'org.apache.commons', name: 'commons-compress', version: '1.18'
+ compile group: "com.liferay", name: "com.liferay.portal.spring.extender.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.application.list.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.frontend.taglib"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.item.selector.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.item.selector.criteria.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.item.selector.taglib"<#if useTP?? && false == useTP>, version: "1.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.trash.taglib"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay.portal", name: "com.liferay.portal.impl"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay.portal", name: "com.liferay.util.taglib"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "2.0"#if>
+ compile group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compile group: "jstl", name: "jstl"<#if useTP?? && false == useTP>, version: "1.2"#if>
+ compile group: "org.osgi", name: "osgi.cmpn"<#if useTP?? && false == useTP>, version: "6.0.0"#if>
+ compile group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
+ compile group: 'org.apache.poi', name: 'poi-ooxml'<#if useTP?? && false == useTP>, version: '4.0.1'#if>
+ compile group: 'org.apache.poi', name: 'poi'<#if useTP?? && false == useTP>, version: '4.0.1'#if>
+ compile group: 'org.apache.poi', name: 'poi-ooxml-schemas'<#if useTP?? && false == useTP>, version: '4.0.1'#if>
+ compile group: 'org.apache.xmlbeans', name: 'xmlbeans'<#if useTP?? && false == useTP>, version: '3.0.2'#if>
+ compile group: 'org.apache.commons', name: 'commons-collections4'<#if useTP?? && false == useTP>, version: '4.2'#if>
+ compile group: 'org.apache.commons', name: 'commons-compress'<#if useTP?? && false == useTP>, version: '1.18'#if>
compileOnly project(":${dashcaseProjectName}-api")
compileOnly project(":${dashcaseProjectName}-service")
diff --git a/src/main/resources/templates/7.1/base.json b/src/main/resources/templates/7.1/base.json
index 163d949..90badd6 100644
--- a/src/main/resources/templates/7.1/base.json
+++ b/src/main/resources/templates/7.1/base.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.entityName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/main/resources/templates/7.1/valuables.ftl b/src/main/resources/templates/7.1/valuables.ftl
index ecaea31..728c8cb 100644
--- a/src/main/resources/templates/7.1/valuables.ftl
+++ b/src/main/resources/templates/7.1/valuables.ftl
@@ -3,6 +3,7 @@
<#assign packageName = "${damascus.packageName}">
<#assign packagePath = "${packageName?replace(\".\", \"/\")}">
<#assign packageSnake = "${packageName?replace(\".\", \"_\")}">
+<#assign useTP = damascus.isUseTargetPlatform() >
<#assign camelcaseProjectName = "${damascus.projectName?replace(\"-\", \"\")}">
<#assign dashcaseProjectName = "${caseUtil.camelCaseToDashCase(camelcaseProjectName)}">
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXAPI_build.gradle.ftl b/src/main/resources/templates/7.2/Portlet_XXXXAPI_build.gradle.ftl
index 9f92ce9..ae4f46f 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXAPI_build.gradle.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXAPI_build.gradle.ftl
@@ -12,11 +12,11 @@ apply plugin: 'eclipse'
def defaultEncoding = 'UTF-8'
dependencies {
- compile group: "javax.portlet", name: "portlet-api", version: "3.0.1"
- compile group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
- compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "4.13.0"
- compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning", version: "1.1.0"
- compileOnly group: "org.osgi", name: "org.osgi.core", version: "6.0.0"
- compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "4.13.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"<#if useTP?? && false == useTP>, version: "1.1.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.core"<#if useTP?? && false == useTP>, version: "6.0.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXROOT_README.md.ftl b/src/main/resources/templates/7.2/Portlet_XXXXROOT_README.md.ftl
index c5aa547..1b94242 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXROOT_README.md.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXROOT_README.md.ftl
@@ -2,32 +2,44 @@
<#assign createPath = "${createPath_val}/${dashcaseProjectName}/README.md">
# Damascus generated service
-Damascus generates scaffolding files to save time for the tedious parts of the development.
+Damascus generates scaffolding files to save time for the tedious parts of the development.
This document explains the tips of adding custom implementations on top of Damascus0generated files and adding your implementations.
# Misc
### TODO comments
-Todo comments are inserted where customizations/modifications are needed. Please look for TODO tags in the generated project and add your implementations according to your requirements.
+Todo comments are inserted where customizations/modifications are needed. Please look for TODO tags in the generated project and add your implementations according to your requirements.
### How to add pages?
Once Damascus generates the bundles, you can add pages as you want according to the basic Liferay portlet mechanism. Damascus generates both Admin and User pages and renders classes separately.
-* ```*ViewMVCRenderCommand.java``` renders ```view.jsp```.
-* ```*CrudMVCActionCommand.java``` process view/delete/update/ create a record command. ```*CrudMVCRenderCommand.java``` renders ```edit.jsp``` and ```view.jsp``` according to the actions.
+| File name | Note |
+| :-- | :-- |
+| *ViewMVCRenderCommand.java | Renders ```view.jsp``` |
+| *CrudMVCActionCommand.java | Process ```view/delete/update/``` create a record |
+| *CrudMVCRenderCommand.java | Renders ```edit.jsp``` and ```view.jsp``` according to the actions. |
### How can I modify CRUD implementation?
-According to Liferay's best practices, all model manipulation methods are stored in ```*LocalServiceImpl.java```. Please see ```*LocalServiceImpl.java``` for more details.
+According to Liferay's best practices, all model manipulation methods are stored in ```*LocalServiceImpl.java```. Please see ```*LocalServiceImpl.java``` for more details.
From 7.2, permission checking are all delegated into ```*ServiceImpl.java```. ```*LocalServiceImpl.java``` is now only responsible for processing business logic. For more details, please see ```Blogs``` implimentations in the Liferay's source code.
When you modify the signature of methods or add new methods, please run ```gradle buildService``` to regenerate interfaces.
-
+
### How can I implement validations?
```*Validator.java``` includes validations. Please see the comments in the file for more details.
### How can I implement Indexer?
-```*Indexer.java``` includes all required methods and enable your custom models to be searched in Liferay. However, this template implementation is legacy for the convenience in order to keep template files as less as possible.
+| File name | Note |
+| :-- | :-- |
+| *SearchRegistrar.java | Register all search related components in there.|
+| *ModelIndexerWriterContributor.java | This class is used during bulk reindexing to identify records to reindex.|
+| *ModelDocumentContributor.java | This class is used to contribute fields to the document to be indexed..|
+| *ModelPreFilterContributor.java | Filters search results before they are returned from the search engine.
+| *ModelResourcePermissionRegistrar.java | Model Resource Permission Registrar |
+| *ModelSummaryContributor.java | Manipulates the Summary object for each entity search result. |
+| *ModelVisibilityContributor.java | Controls the visibility of entities that can be attached to other asset types in the search context. |
+| *KeywordQueryContributor.java | Contributes clauses to the ongoing search query to control how the model entities are searched.|
-From 7.2, Search introduces new framework for the implementation, which is more modular and divides each search related functionality into different classes separately. For more details, please see the [official documents](https://portal.liferay.dev/docs/7-2/frameworks/-/knowledge_base/f/search)
+From 7.2, Search introduces new framework for the implementation, which is more modular and divides each search related functionality into different classes separately. For more details, please see the [official documents](https://help.liferay.com/hc/en-us/sections/360004656871-Search)
### How can I modify permissions?
```*ModelResourcePermissionRegistrar.java``` and ```*PortletResourcePermissionRegistrar.java``` register permission helpers to the search framework. Please modify these files according to your requirements.
@@ -40,25 +52,16 @@ From 7.2, Search introduces new framework for the implementation, which is more
```*AssetRenderer.java``` and ```*AssetRendererFactory.java``` render ```abstract.jsp```, ```abstract.jsp``` and ```prewview.jsp``` for ```Asset Framework```. For more details, please see the [official document](https://portal.liferay.dev/docs/7-2/frameworks/-/knowledge_base/f/creating-an-asset-renderer)
# *-web
-This bundle includes classes and java files related to display portlets. This also contains utility classes to handle requests.
-
-### *WebPortlet.java
-This is an entry point of displaying a portlet in the user area.
-
-### *PanelApp.java, *AdminPortlet.java
-This is an entry point of displaying a portlet in the administration area (inside of Control Panel)
+This bundle includes classes and java files related to display portlets. This also contains utility classes to handle requests.
-### *PortletLayoutFinder.java
-This is used for displaying contents in Asset Publisher with
-
-### *AssetRendererFactory.java, *AssetRenderer.java
-These classes are used to associate with an asset and generated model.
-
-### *ItemSelectorHelper.java
-This is used for Documents and Media related operations (such as uploading assets, selecting assets, e.g.)
-
-### *ViewHelper.java
-This class is a utility class mainly for handling search (search container)
+| File name | Note |
+| :-- | :-- |
+| *WebPortlet.java | This is an entry point of displaying a portlet in the user area. |
+| *PanelApp.java, *AdminPortlet.java | This is an entry point of displaying a portlet in the administration area (inside of Control Panel) |
+| *PortletLayoutFinder.java | This is used for displaying contents in Asset Publisher with |
+| *AssetRendererFactory.java, *AssetRenderer.java | These classes are used to associate with an asset and generated model. |
+| *ItemSelectorHelper.java | This is used for Documents and Media related operations (such as uploading assets, selecting assets, e.g.) |
+| *ViewHelper.java | This class is a utility class mainly for handling search (search container) |
# *-service
```*-service``` includes files which allow access to persistent layer, and it's service layer classes, which furthermore allows access database through the models/services. This README is a reference to Damascus-generated files. For more details of files that Liferay service builder generates, please check out http://dev.liferay.com.
@@ -82,20 +85,15 @@ These methods are for moving records into the trash instead of deleting them fro
According to Liferay's contract, ```find*``` methods are for retrieving a record from the database. For searching, you may want to use the search engine instead of directory searching on the database for better performance as a best practice.
## Permission
-There are 4 files related to permission management
+There are 5 files related to permission management
| File name | Note |
| :-- | :-- |
-| *Permission.java | Manage Portlet permission |
+| *Permission.java | Manage Portlet permission |
| *EntryPermission.java | Manage Model permission |
| *ModelResourcePermissionRegistrar.java | Register Model permission handler and configure details of permission types |
| *PortletResourcePermissionRegistrar.java | Register portlet permission handler and configure details of permission types |
| default.xml | Permission mapping |
-## *Indexer.java
-This class is for indexing custom model data into the search engine. To ensure the search is working correctly, this class needs to be appropriately modified according to your requirements.
-
-From 7.2, the search introduced a new framework. For more details, please refer [the official document.](https://portal.liferay.dev/docs/7-2/frameworks/-/knowledge_base/f/search)
-
## *Validator.java
This class is for validating data coming from a form in ```edit.jsp``` of ```*-web``` bundle. According to the comments inside, you can implement error handling. After implementing validation, each error method returns the error message key, so you need to add an appropriate error message handler in ```view.jsp``` accordingly. Please refer to the default messages that have already been in place in the ```view.jsp```.
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl
new file mode 100644
index 0000000..69682a5
--- /dev/null
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl
@@ -0,0 +1,50 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/query/contributor/${capFirstModel}KeywordQueryContributor.java">
+/* */
+package ${packageName}.internal.search.query.contributor;
+
+import com.liferay.portal.kernel.search.BooleanQuery;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.search.query.QueryHelper;
+import com.liferay.portal.search.spi.model.query.contributor.KeywordQueryContributor;
+import com.liferay.portal.search.spi.model.query.contributor.helper.KeywordQueryContributorHelper;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Keyword Query Contributor
+ *
+ * Contributes clauses to the ongoing search query to control how the model entities are searched.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = KeywordQueryContributor.class
+)
+public class ${capFirstModel}KeywordQueryContributor implements KeywordQueryContributor {
+
+ @Override
+ public void contribute(String keywords, BooleanQuery booleanQuery,KeywordQueryContributorHelper keywordQueryContributorHelper) {
+ SearchContext searchContext = keywordQueryContributorHelper.getSearchContext();
+
+ // TODO: Adjust as necessary to support the search for the entity
+
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.ARTICLE_ID, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.CLASS_PK, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.ENTRY_CLASS_PK, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.USER_NAME, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.CONTENT, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.DESCRIPTION, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.TITLE, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.SUBTITLE, false);
+ }
+
+ @Reference
+ protected QueryHelper queryHelper;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_LocalServiceImpl.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
index 0db4ac7..dbbad25 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
@@ -21,8 +21,6 @@ import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.ModelHintsUtil;
import com.liferay.portal.kernel.model.ResourceConstants;
import com.liferay.portal.kernel.model.SystemEventConstants;
@@ -75,6 +73,9 @@ import javax.portlet.PortletRequest;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* The implementation of the ${capFirstModel} local service.
*
@@ -1274,7 +1275,7 @@ public class ${capFirstModel}LocalServiceImpl extends ${capFirstModel}LocalServi
WorkflowConstants.STATUS_SCHEDULED
};
- private static Log _log = LogFactoryUtil.getLog(
+ private static Logger _log = LoggerFactory.getLogger(
${capFirstModel}LocalServiceImpl.class);
@Reference
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl
new file mode 100644
index 0000000..d4375b6
--- /dev/null
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl
@@ -0,0 +1,45 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/index/contributor/${capFirstModel}ModelDocumentContributor.java">
+/* */
+package ${packageName}.internal.search.index.contributor;
+
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.search.spi.model.index.contributor.ModelDocumentContributor;
+import org.osgi.service.component.annotations.Component;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Model Document Contributor
+ *
+ * This class is used to contribute fields to the document to be indexed.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelDocumentContributor.class
+)
+public class ${capFirstModel}ModelDocumentContributor implements ModelDocumentContributor<${capFirstModel}> {
+
+ @Override
+ public void contribute(Document document, ${capFirstModel} entry) {
+
+ // TODO : These fields should be modified according to your requirements.
+
+ document.addText(Field.CAPTION, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(
+ Field.CONTENT,
+ HtmlUtil.extractText(entry.get${application.asset.assetSummaryFieldName?cap_first}()));
+ document.addText(Field.DESCRIPTION, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(Field.SUBTITLE, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(Field.TITLE, entry.get${application.asset.assetTitleFieldName?cap_first}());
+
+ document.addDate(Field.MODIFIED_DATE, entry.getModifiedDate());
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl
new file mode 100644
index 0000000..c7f86c0
--- /dev/null
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl
@@ -0,0 +1,89 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/index/contributor/${capFirstModel}ModelIndexerWriterContributor.java">
+/* */
+package ${packageName}.internal.search.index.contributor;
+
+import com.liferay.portal.kernel.dao.orm.Property;
+import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.search.batch.BatchIndexingActionable;
+import com.liferay.portal.search.batch.DynamicQueryBatchIndexingActionableFactory;
+import com.liferay.portal.search.spi.model.index.contributor.ModelIndexerWriterContributor;
+import com.liferay.portal.search.spi.model.index.contributor.helper.IndexerWriterMode;
+import com.liferay.portal.search.spi.model.index.contributor.helper.ModelIndexerWriterDocumentHelper;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+/**
+ * ${capFirstModel} Model Indexer Writer Contributor
+ *
+ * This class is used during bulk reindexing to identify records to reindex.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelIndexerWriterContributor.class
+)
+public class ${capFirstModel}ModelIndexerWriterContributor implements ModelIndexerWriterContributor<${capFirstModel}> {
+
+ @Override
+ public void customize(BatchIndexingActionable batchIndexingActionable, ModelIndexerWriterDocumentHelper modelIndexerWriterDocumentHelper) {
+
+ // TODO: add criteria to the DQ to select the entities to include in the reindex.
+ batchIndexingActionable.setAddCriteriaMethod(dynamicQuery -> {
+ Property statusProperty = PropertyFactoryUtil.forName("status");
+
+ Integer[] statuses = {
+ WorkflowConstants.STATUS_APPROVED,
+ WorkflowConstants.STATUS_IN_TRASH
+ };
+
+ // reindex any entry that is approved or in the trash
+ dynamicQuery.add(statusProperty.in(statuses));
+ });
+
+ // add any matched entry into the documents to index.
+ batchIndexingActionable.setPerformActionMethod((${capFirstModel} entry) -> {
+ batchIndexingActionable.addDocuments(modelIndexerWriterDocumentHelper.getDocument(entry));
+ });
+ }
+
+ @Override
+ public IndexerWriterMode getIndexerWriterMode(${capFirstModel} entry) {
+
+ // TODO: Update as necessary to control the indexer writer mode for the given entry.
+
+ int status = entry.getStatus();
+
+ if ((status == WorkflowConstants.STATUS_APPROVED) || (status == WorkflowConstants.STATUS_IN_TRASH) || (status == WorkflowConstants.STATUS_DRAFT)) {
+ return IndexerWriterMode.UPDATE;
+ }
+
+ return IndexerWriterMode.DELETE;
+ }
+
+ @Override
+ public BatchIndexingActionable getBatchIndexingActionable() {
+ return dynamicQueryBatchIndexingActionableFactory.getBatchIndexingActionable(
+ _${uncapFirstModel}LocalService.getIndexableActionableDynamicQuery());
+ }
+
+ @Override
+ public long getCompanyId(${capFirstModel} entry) {
+ return entry.getCompanyId();
+ }
+
+ @Reference
+ protected ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+ @Reference
+ protected DynamicQueryBatchIndexingActionableFactory dynamicQueryBatchIndexingActionableFactory;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl
new file mode 100644
index 0000000..5cc6f50
--- /dev/null
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl
@@ -0,0 +1,45 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/query/contributor/${capFirstModel}ModelPreFilterContributor.java">
+/* */
+package ${packageName}.internal.search.query.contributor;
+
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.kernel.search.filter.BooleanFilter;
+import com.liferay.portal.search.spi.model.query.contributor.ModelPreFilterContributor;
+import com.liferay.portal.search.spi.model.registrar.ModelSearchSettings;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model PreFilter Contributor
+ *
+ * Filters search results before they are returned from the search engine.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelPreFilterContributor.class
+)
+public class ${capFirstModel}ModelPreFilterContributor implements ModelPreFilterContributor {
+
+ @Override
+ public void contribute(BooleanFilter booleanFilter, ModelSearchSettings modelSearchSettings, SearchContext searchContext) {
+
+ // TODO: Adjust as necessary to filter results that should not normally be included as search results.
+
+ // exclude non-approved entities from the search results.
+ addWorkflowStatusFilter(booleanFilter, modelSearchSettings, searchContext);
+ }
+
+ protected void addWorkflowStatusFilter(BooleanFilter booleanFilter, ModelSearchSettings modelSearchSettings, SearchContext searchContext) {
+ workflowStatusModelPreFilterContributor.contribute(booleanFilter, modelSearchSettings, searchContext);
+ }
+
+ @Reference(target = "(model.pre.filter.contributor.id=WorkflowStatus)")
+ protected ModelPreFilterContributor workflowStatusModelPreFilterContributor;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl
new file mode 100644
index 0000000..d60444e
--- /dev/null
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl
@@ -0,0 +1,58 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/result/contributor/${capFirstModel}ModelSummaryContributor.java">
+/* */
+package ${packageName}.internal.search.result.contributor;
+
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.Summary;
+import com.liferay.portal.kernel.util.LocaleUtil;
+import com.liferay.portal.kernel.util.LocalizationUtil;
+import com.liferay.portal.search.spi.model.result.contributor.ModelSummaryContributor;
+import org.osgi.service.component.annotations.Component;
+
+import java.util.Locale;
+
+/**
+ * ${capFirstModel} Model Summary Contributor
+ *
+ * Manipulates the Summary object for each entity search result.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelSummaryContributor.class
+)
+public class ${capFirstModel}ModelSummaryContributor implements ModelSummaryContributor {
+
+ @Override
+ public Summary getSummary(Document document, Locale locale, String snippet) {
+ String languageId = LocaleUtil.toLanguageId(locale);
+
+ // TODO: Modify as necessary to use the corrected fields for the summary
+
+ return _createSummary(document,
+ LocalizationUtil.getLocalizedName(Field.CONTENT, languageId),
+ LocalizationUtil.getLocalizedName(Field.TITLE, languageId));
+ }
+
+ protected Summary _createSummary(Document document, String contentField, String titleField) {
+
+ String prefix = Field.SNIPPET + StringPool.UNDERLINE;
+
+ String title = document.get(prefix + titleField, titleField);
+ String content = document.get(prefix + contentField, contentField);
+
+ Summary summary = new Summary(title,content);
+
+ summary.setMaxContentLength(200);
+
+ return summary;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl
new file mode 100644
index 0000000..323c014
--- /dev/null
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl
@@ -0,0 +1,53 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/result/contributor/${capFirstModel}ModelVisibilityContributor.java">
+/* */
+package ${packageName}.internal.search.result.contributor;
+
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.search.spi.model.result.contributor.ModelVisibilityContributor;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model Visibility Contributor
+ *
+ * Controls the visibility of entities that can be attached to other asset types in the search context.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelVisibilityContributor.class
+)
+public class ${capFirstModel}ModelVisibilityContributor implements ModelVisibilityContributor {
+
+ @Override
+ public boolean isVisible(long classPK, int status) {
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.fetch${capFirstModel}(classPK);
+
+ if (entry == null) {
+ return false;
+ }
+
+ return isVisible(entry.getStatus(), status);
+ }
+
+ protected boolean isVisible(int entryStatus, int queryStatus) {
+ if (((queryStatus != WorkflowConstants.STATUS_ANY) && (entryStatus == queryStatus)) || (entryStatus != WorkflowConstants.STATUS_IN_TRASH)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Reference
+ protected ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_SearchRegistrar.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_SearchRegistrar.java.ftl
new file mode 100644
index 0000000..6b87de4
--- /dev/null
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_SearchRegistrar.java.ftl
@@ -0,0 +1,70 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/${capFirstModel}SearchRegistrar.java">
+/* */
+package ${packageName}.internal.search;
+
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.search.spi.model.index.contributor.ModelIndexerWriterContributor;
+import com.liferay.portal.search.spi.model.registrar.ModelSearchRegistrarHelper;
+import com.liferay.portal.search.spi.model.result.contributor.ModelSummaryContributor;
+import com.liferay.portal.search.spi.model.result.contributor.ModelVisibilityContributor;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Search Registrar
+ *
+ * Registers the ${capFirstModel} entity with Liferay's search framework.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ service = {}
+)
+public class ${capFirstModel}SearchRegistrar {
+
+ @Activate
+ protected void activate(BundleContext bundleContext) {
+ _serviceRegistration = modelSearchRegistrarHelper.register(
+ ${capFirstModel}.class, bundleContext,
+ modelSearchDefinition -> {
+ modelSearchDefinition.setDefaultSelectedFieldNames(
+ Field.ASSET_TAG_NAMES, Field.COMPANY_ID, Field.CONTENT,
+ Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID,
+ Field.MODIFIED_DATE, Field.SCOPE_GROUP_ID, Field.TITLE, Field.UID);
+ modelSearchDefinition.setDefaultSelectedLocalizedFieldNames(Field.TITLE, Field.CONTENT);
+
+ modelSearchDefinition.setModelIndexWriteContributor(modelIndexWriterContributor);
+ modelSearchDefinition.setModelSummaryContributor(modelSummaryContributor);
+ modelSearchDefinition.setModelVisibilityContributor(modelVisibilityContributor);
+ });
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ _serviceRegistration.unregister();
+ }
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelIndexerWriterContributor<${capFirstModel}> modelIndexWriterContributor;
+
+ @Reference
+ protected ModelSearchRegistrarHelper modelSearchRegistrarHelper;
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelSummaryContributor modelSummaryContributor;
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelVisibilityContributor modelVisibilityContributor;
+
+ private ServiceRegistration> _serviceRegistration;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_Searcher.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_Searcher.java.ftl
new file mode 100644
index 0000000..917b60e
--- /dev/null
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_Searcher.java.ftl
@@ -0,0 +1,48 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/${capFirstModel}Searcher.java">
+/* */
+package ${packageName}.internal.search;
+
+import com.liferay.portal.kernel.search.BaseSearcher;
+import com.liferay.portal.kernel.search.Field;
+import org.osgi.service.component.annotations.Component;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Searcher
+ *
+ * Sets up the searcher instance for ${capFirstModel}.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = BaseSearcher.class
+)
+public class ${capFirstModel}Searcher extends BaseSearcher {
+
+ public static final String CLASS_NAME = ${capFirstModel}.class.getName();
+
+ public ${capFirstModel}Searcher() {
+
+ // TODO: Adjust the fields as necessary.
+ setDefaultSelectedFieldNames(
+ Field.ASSET_TAG_NAMES, Field.COMPANY_ID, Field.CONTENT,
+ Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID,
+ Field.MODIFIED_DATE, Field.SCOPE_GROUP_ID, Field.TITLE, Field.UID);
+ setFilterSearch(true);
+ setPermissionAware(true);
+
+ // TODO Adjust localized fields as well
+ setDefaultSelectedLocalizedFieldNames(Field.TITLE, Field.CONTENT);
+ }
+
+ @Override
+ public String getClassName() {
+ return CLASS_NAME;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_WorkflowManager.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_WorkflowManager.java.ftl
index 8c23004..4174378 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXSVC_WorkflowManager.java.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_WorkflowManager.java.ftl
@@ -10,8 +10,6 @@ package ${packageName}.service.workflow;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.model.WorkflowInstanceLink;
import com.liferay.portal.kernel.service.WorkflowInstanceLinkLocalServiceUtil;
@@ -27,6 +25,9 @@ import ${packageName}.model.${capFirstModel};
import java.util.ArrayList;
import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* ${capFirstModel} Workflow Utility class
*
@@ -361,7 +362,7 @@ public class ${capFirstModel}WorkflowManager {
user.getCompanyId(), scorpGroupId, _className, classPK);
}
- private static Log _log = LogFactoryUtil.getLog(
+ private static Logger _log = LoggerFactory.getLogger(
${capFirstModel}WorkflowManager.class);
}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_build.gradle.ftl b/src/main/resources/templates/7.2/Portlet_XXXXSVC_build.gradle.ftl
index 4d13cae..302bdf0 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXSVC_build.gradle.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXSVC_build.gradle.ftl
@@ -29,27 +29,28 @@ repositories {
}
dependencies {
- compile group: "com.google.guava", name: "guava", version: "28.1-jre", transitive: false
- compile group: "com.liferay", name: "com.liferay.friendly.url.api", version: "2.0.0"
- compile group: "com.liferay", name: "com.liferay.petra.function", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.petra.lang", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.petra.string", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.portal.aop.api", version: "1.0.0"
- compile group: "com.liferay", name: "com.liferay.portal.search.api", version: "3.7.0"
- compile group: "com.liferay", name: "com.liferay.portal.search.spi", version: "3.2.0"
- compile group: "com.liferay", name: "com.liferay.trash.api", version: "2.0.0"
- compile group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "4.13.0"
- compile group: "commons-io", name: "commons-io", version: "2.6"
- compile group: "commons-validator", name: "commons-validator", version: "1.6"
- compile group: "javax.portlet", name: "portlet-api", version: "3.0.1"
- compile group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
- compile group: "javax.servlet.jsp", name: "javax.servlet.jsp-api", version: "2.3.1"
+ compile group: "com.google.guava", name: "guava"<#if useTP?? && false == useTP>, version: "28.1-jre"#if>, transitive: false
+ compileOnly group: "com.liferay", name: "com.liferay.friendly.url.api"<#if useTP?? && false == useTP>, version: "2.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.function"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.lang"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.string"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"<#if useTP?? && false == useTP>, version: "1.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.search.api"<#if useTP?? && false == useTP>, version: "3.12.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.search.spi"<#if useTP?? && false == useTP>, version: "3.3.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.trash.api"<#if useTP?? && false == useTP>, version: "2.0.0"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "4.13.0"#if>
+ compileOnly group: "commons-io", name: "commons-io"<#if useTP?? && false == useTP>, version: "2.6"#if>
+ compile group: "commons-validator", name: "commons-validator"<#if useTP?? && false == useTP>, version: "1.6"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet.jsp", name: "jsp-api"<#if useTP?? && false == useTP>, version: "2.1"#if>
compile group: "org.apache.commons", name: "commons-lang3", version: "3.9"
compile group: "org.apache.felix", name: "org.apache.felix.http.servlet-api", version: "1.1.2"
- compile group: "org.osgi", name: "org.osgi.annotation.versioning", version: "1.1.0"
- compile group: "org.osgi", name: "org.osgi.service.cm", version: "1.5.0"
- compile group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
+ compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"<#if useTP?? && false == useTP>, version: "1.1.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.cm"<#if useTP?? && false == useTP>, version: "1.5.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
compile group: "org.osgi", name: "osgi.core", version: "6.0.0"
+ compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.26'
compile project(":${dashcaseProjectName}-api")
}
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
index 8e97a8a..8a70af8 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
@@ -10,8 +10,6 @@ package ${packageName}.web.portlet.action;
import com.liferay.asset.display.page.portlet.AssetDisplayPageEntryFormProcessor;
import com.liferay.petra.reflect.ReflectionUtil;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.TrashedModel;
import com.liferay.portal.kernel.portlet.bridges.mvc.BaseMVCActionCommand;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCActionCommand;
@@ -46,6 +44,9 @@ import javax.portlet.ActionResponse;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* @author ${damascus_author}
*/
@@ -248,7 +249,7 @@ public class ${capFirstModel}AdminCrudMVCActionCommand extends BaseMVCActionComm
hideDefaultSuccessMessage(request);
}
catch (Exception t) {
- _log.error(t, t);
+ _log.error(t.getLocalizedMessage(), t);
SessionErrors.add(request, PortalException.class);
hideDefaultSuccessMessage(request);
}
@@ -274,7 +275,7 @@ public class ${capFirstModel}AdminCrudMVCActionCommand extends BaseMVCActionComm
_${uncapFirstModel}Service = ${uncapFirstModel}Service;
}
- private static Log _log = LogFactoryUtil.getLog(
+ private static Logger _log = LoggerFactory.getLogger(
${capFirstModel}AdminCrudMVCActionCommand.class);
@Reference
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXWEB_AssetRenderer.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXWEB_AssetRenderer.java.ftl
index 749f21f..7950112 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXWEB_AssetRenderer.java.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXWEB_AssetRenderer.java.ftl
@@ -13,8 +13,6 @@ import com.liferay.asset.kernel.model.AssetRendererFactory;
import com.liferay.asset.kernel.model.BaseJSPAssetRenderer;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
@@ -26,7 +24,6 @@ import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.trash.TrashRenderer;
import com.liferay.portal.kernel.util.Constants;
-import com.liferay.portal.kernel.util.HtmlUtil;
import com.liferay.portal.kernel.util.PortalUtil;
import com.liferay.portal.kernel.util.ResourceBundleLoader;
import com.liferay.portal.kernel.util.Validator;
@@ -44,6 +41,9 @@ import javax.portlet.WindowState;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* Asset Renderer
*
@@ -306,14 +306,14 @@ public class ${capFirstModel}AssetRenderer
}
catch (PortalException pe) {
if (_log.isDebugEnabled()) {
- _log.debug(pe, pe);
+ _log.debug(pe.getLocalizedMessage(), pe);
}
return false;
}
}
- private static final Log _log = LogFactoryUtil.getLog(
+ private static final Logger _log = LoggerFactory.getLogger(
${capFirstModel}AssetRenderer.class);
private AssetDisplayPageFriendlyURLProvider
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXWEB_AssetRendererFactory.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
index 147817d..b0ffa57 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
@@ -12,8 +12,6 @@ import com.liferay.asset.kernel.model.AssetRendererFactory;
import com.liferay.asset.kernel.model.BaseAssetRendererFactory;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
import com.liferay.portal.kernel.portlet.LiferayPortletURL;
@@ -39,6 +37,9 @@ import javax.servlet.ServletContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* ${capFirstModel} Asset Renderer Factory
*
@@ -181,7 +182,7 @@ public class ${capFirstModel}AssetRendererFactory
_servletContext = servletContext;
}
- private static final Log _log = LogFactoryUtil.getLog(
+ private static final Logger _log = LoggerFactory.getLogger(
${capFirstModel}AssetRendererFactory.class);
@Reference
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXWEB_ConfigurationAction.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXWEB_ConfigurationAction.java.ftl
index 9663055..5777e34 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXWEB_ConfigurationAction.java.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXWEB_ConfigurationAction.java.ftl
@@ -9,8 +9,6 @@ package ${packageName}.web.portlet.action;
import aQute.bnd.annotation.metatype.Configurable;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.portlet.ConfigurationAction;
import com.liferay.portal.kernel.portlet.DefaultConfigurationAction;
import com.liferay.portal.kernel.servlet.SessionMessages;
@@ -34,6 +32,9 @@ import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Modified;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* ${capFirstModel} Configuraion Aciton
*
@@ -152,7 +153,7 @@ public class ${capFirstModel}ConfigurationAction extends DefaultConfigurationAct
return valid;
}
- private static final Log _log = LogFactoryUtil.getLog(
+ private static final Logger _log = LoggerFactory.getLogger(
${capFirstModel}ConfigurationAction.class);
private volatile ${capFirstModel}Configuration _${uncapFirstModel}Configuration;
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
index f50469b..5bec50f 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
@@ -10,8 +10,6 @@ package ${packageName}.web.portlet.action;
import com.liferay.asset.display.page.portlet.AssetDisplayPageEntryFormProcessor;
import com.liferay.petra.reflect.ReflectionUtil;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.TrashedModel;
import com.liferay.portal.kernel.portlet.bridges.mvc.BaseMVCActionCommand;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCActionCommand;
@@ -46,6 +44,9 @@ import javax.portlet.ActionResponse;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* @author ${damascus_author}
*/
@@ -248,7 +249,7 @@ public class ${capFirstModel}CrudMVCActionCommand extends BaseMVCActionCommand {
hideDefaultSuccessMessage(request);
}
catch (Exception t) {
- _log.error(t, t);
+ _log.error(t.getLocalizedMessage(), t);
SessionErrors.add(request, PortalException.class);
hideDefaultSuccessMessage(request);
}
@@ -274,7 +275,7 @@ public class ${capFirstModel}CrudMVCActionCommand extends BaseMVCActionCommand {
_${uncapFirstModel}Service = ${uncapFirstModel}Service;
}
- private static Log _log = LogFactoryUtil.getLog(
+ private static Logger _log = LoggerFactory.getLogger(
${capFirstModel}CrudMVCActionCommand.class);
@Reference
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXWEB_DisplayContext.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXWEB_DisplayContext.java.ftl
index 4d76c3c..fe3bbae 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXWEB_DisplayContext.java.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXWEB_DisplayContext.java.ftl
@@ -11,8 +11,6 @@ import com.liferay.portal.kernel.dao.search.DisplayTerms;
import com.liferay.portal.kernel.dao.search.SearchContainer;
import com.liferay.portal.kernel.dao.search.SearchContainerResults;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
import com.liferay.portal.kernel.portlet.PortalPreferences;
@@ -42,6 +40,9 @@ import javax.portlet.PortletURL;
import javax.servlet.http.HttpServletRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* ${capFirstModel} Display Context
*
@@ -174,7 +175,7 @@ public class ${capFirstModel}DisplayContext {
return _searchContainer;
}
- private static final Log _log = LogFactoryUtil.getLog(
+ private static final Logger _log = LoggerFactory.getLogger(
${capFirstModel}DisplayContext.class);
private final HttpServletRequest _httpServletRequest;
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXWEB_ViewHelper.java.ftl b/src/main/resources/templates/7.2/Portlet_XXXXWEB_ViewHelper.java.ftl
index 1f336c3..d80a6f2 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXWEB_ViewHelper.java.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXWEB_ViewHelper.java.ftl
@@ -10,8 +10,6 @@ package ${packageName}.web.util;
import com.liferay.portal.kernel.dao.search.DisplayTerms;
import com.liferay.portal.kernel.dao.search.SearchContainer;
import com.liferay.portal.kernel.dao.search.SearchContainerResults;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.Hits;
@@ -41,6 +39,9 @@ import javax.portlet.PortletRequest;
import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* View Helper
*
@@ -276,6 +277,6 @@ public class ${capFirstModel}ViewHelper {
return false;
}
- private static Log _log = LogFactoryUtil.getLog(${capFirstModel}ViewHelper.class);
+ private static Logger _log = LoggerFactory.getLogger(${capFirstModel}ViewHelper.class);
}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXWEB_build.gradle.ftl b/src/main/resources/templates/7.2/Portlet_XXXXWEB_build.gradle.ftl
index be1e44f..3735625 100644
--- a/src/main/resources/templates/7.2/Portlet_XXXXWEB_build.gradle.ftl
+++ b/src/main/resources/templates/7.2/Portlet_XXXXWEB_build.gradle.ftl
@@ -17,33 +17,37 @@ def defaultEncoding = 'UTF-8'
dependencies {
compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.5.0"
- compile group: "org.apache.poi", name: "poi", version: "4.0.1"
- compile group: "org.apache.poi", name: "poi-ooxml", version: "4.0.1"
- compile group: "org.apache.poi", name: "poi-ooxml-schemas", version: "4.0.1"
+ compile group: "org.apache.poi", name: "poi"<#if useTP?? && false == useTP>, version: "4.0.1"#if>
+ compile group: "org.apache.poi", name: "poi-ooxml"<#if useTP?? && false == useTP>, version: "4.0.1"#if>
+ compile group: "org.apache.poi", name: "poi-ooxml-schemas"<#if useTP?? && false == useTP>, version: "4.0.1"#if>
- compileOnly group: "com.liferay", name: "com.liferay.application.list.api", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.asset.api", version: "2.1.+"
- compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.api", version: "5.1.0"
- compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.item.selector.api", version: "2.0.0"
- compileOnly group: "com.liferay", name: "com.liferay.asset.info.display.api", version: "2.1.0"
- compileOnly group: "com.liferay", name: "com.liferay.asset.taglib", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.comment.taglib", version: "2.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.clay", version: "2.1.+"
- compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.soy", version: "3.0.0"
- compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.util", version: "2.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.info.api", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.item.selector.api", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.item.selector.criteria.api", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.item.selector.taglib", version: "3.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.petra.reflect", version: "3.0.+"
- compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "4.13.0"
- compileOnly group: "com.liferay.portal", name: "com.liferay.util.taglib", version: "4.1.0"
- compileOnly group: "javax.portlet", name: "portlet-api", version: "3.0.1"
- compileOnly group: "javax.servlet.jsp", name: "javax.servlet.jsp-api", version: "2.3.1"
- compileOnly group: "jstl", name: "jstl", version: "1.2"
+ compileOnly group: "com.liferay", name: "com.liferay.application.list.api"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.api"<#if useTP?? && false == useTP>, version: "2.1.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.api"<#if useTP?? && false == useTP>, version: "5.1.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.item.selector.api"<#if useTP?? && false == useTP>, version: "2.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.info.display.api"<#if useTP?? && false == useTP>, version: "2.1.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.taglib"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.comment.taglib"<#if useTP?? && false == useTP>, version: "2.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.clay"<#if useTP?? && false == useTP>, version: "2.1.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.soy"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.util"<#if useTP?? && false == useTP>, version: "2.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.info.api"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.api"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.criteria.api"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.taglib"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.reflect"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.string"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.function"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.trash.api"<#if useTP?? && false == useTP>, version: "2.0.+"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "4.13.0"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.util.taglib"<#if useTP?? && false == useTP>, version: "4.1.0"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet.jsp", name: "jsp-api"<#if useTP?? && false == useTP>, version: "2.1"#if>
+ compileOnly group: "jstl", name: "jstl"<#if useTP?? && false == useTP>, version: "1.2"#if>
compileOnly group: "org.apache.felix", name: "org.apache.felix.http.servlet-api", version: "1.1.2"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
+ compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.26'
compileOnly project(":${dashcaseProjectName}-api")
compileOnly project(":${dashcaseProjectName}-service")
}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.2/base.json b/src/main/resources/templates/7.2/base.json
index d32a8a6..9cd3602 100644
--- a/src/main/resources/templates/7.2/base.json
+++ b/src/main/resources/templates/7.2/base.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.entityName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/main/resources/templates/7.2/valuables.ftl b/src/main/resources/templates/7.2/valuables.ftl
index ecaea31..728c8cb 100644
--- a/src/main/resources/templates/7.2/valuables.ftl
+++ b/src/main/resources/templates/7.2/valuables.ftl
@@ -3,6 +3,7 @@
<#assign packageName = "${damascus.packageName}">
<#assign packagePath = "${packageName?replace(\".\", \"/\")}">
<#assign packageSnake = "${packageName?replace(\".\", \"_\")}">
+<#assign useTP = damascus.isUseTargetPlatform() >
<#assign camelcaseProjectName = "${damascus.projectName?replace(\"-\", \"\")}">
<#assign dashcaseProjectName = "${caseUtil.camelCaseToDashCase(camelcaseProjectName)}">
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXAPI_Constants.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXAPI_Constants.java.ftl
new file mode 100644
index 0000000..f079f8c
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXAPI_Constants.java.ftl
@@ -0,0 +1,22 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/src/main/java/${packagePath}/constants/${capFirstModel}Constants.java">
+/* */
+package ${packageName}.constants;
+
+/**
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}Constants {
+
+ // This name is defined in default.xml, model-name
+
+ public static final String RESOURCE_NAME = "${packageName}";
+
+ // This name is defined in service.xml, package-path
+
+ public static final String SERVICE_NAME = "${packageName}";
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXAPI_PortletKeys.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXAPI_PortletKeys.java.ftl
new file mode 100644
index 0000000..cbe4d86
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXAPI_PortletKeys.java.ftl
@@ -0,0 +1,24 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/src/main/java/${packagePath}/constants/${capFirstModel}PortletKeys.java">
+/* */
+
+package ${packageName}.constants;
+
+/**
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}PortletKeys {
+
+ public static final String ${uppercaseModel} =
+ "${packageSnake}_web_${capFirstModel}Portlet";
+
+ public static final String ${uppercaseModel}_ADMIN =
+ "${packageSnake}_web_${capFirstModel}AdminPortlet";
+
+ public static final String ${uppercaseModel}_CONFIG =
+ "${packageName}.web.portlet.action.${capFirstModel}Configuration";
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXAPI_ValidateException.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXAPI_ValidateException.java.ftl
new file mode 100644
index 0000000..5f7cc34
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXAPI_ValidateException.java.ftl
@@ -0,0 +1,35 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/src/main/java/${packagePath}/exception/${capFirstModel}ValidateException.java">
+/* */
+
+package ${packageName}.exception;
+
+import com.liferay.portal.kernel.exception.PortalException;
+
+import java.util.List;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * @author ${damascus_author}
+ */
+@ProviderType
+public class ${capFirstModel}ValidateException extends PortalException {
+
+ public ${capFirstModel}ValidateException() {
+ }
+
+ public ${capFirstModel}ValidateException(List errors) {
+ _errors = errors;
+ }
+
+ public List getErrors() {
+ return _errors;
+ }
+
+ protected List _errors = null;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXAPI_bnd.bnd.ftl b/src/main/resources/templates/7.3/Portlet_XXXXAPI_bnd.bnd.ftl
new file mode 100644
index 0000000..15675a1
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXAPI_bnd.bnd.ftl
@@ -0,0 +1,16 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/bnd.bnd">
+# #
+Bundle-Name: ${dashcaseProjectName}-api
+Bundle-SymbolicName: ${packageName}.api
+Bundle-Version: 1.0.0
+Export-Package:\
+ ${packageName}.exception,\
+ ${packageName}.model,\
+ ${packageName}.service,\
+ ${packageName}.service.persistence,\
+ ${packageName}.constants
+-check: EXPORTS
+-includeresource: META-INF/service.xml=../${dashcaseProjectName}-service/service.xml
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXAPI_build.gradle.ftl b/src/main/resources/templates/7.3/Portlet_XXXXAPI_build.gradle.ftl
new file mode 100644
index 0000000..80a7214
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXAPI_build.gradle.ftl
@@ -0,0 +1,22 @@
+//
+// //
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/build.gradle">
+// //
+apply plugin: 'java'
+apply plugin: 'groovy'
+apply plugin: 'idea'
+apply plugin: 'eclipse'
+
+//Need for Windows
+def defaultEncoding = 'UTF-8'
+
+dependencies {
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "7.2.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"<#if useTP?? && false == useTP>, version: "1.1.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.core"<#if useTP?? && false == useTP>, version: "6.0.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXROOT_README.md.ftl b/src/main/resources/templates/7.3/Portlet_XXXXROOT_README.md.ftl
new file mode 100644
index 0000000..1b94242
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXROOT_README.md.ftl
@@ -0,0 +1,110 @@
+<#include "./valuables.ftl">
+<#assign createPath = "${createPath_val}/${dashcaseProjectName}/README.md">
+# Damascus generated service
+
+Damascus generates scaffolding files to save time for the tedious parts of the development.
+This document explains the tips of adding custom implementations on top of Damascus0generated files and adding your implementations.
+
+# Misc
+### TODO comments
+Todo comments are inserted where customizations/modifications are needed. Please look for TODO tags in the generated project and add your implementations according to your requirements.
+
+### How to add pages?
+Once Damascus generates the bundles, you can add pages as you want according to the basic Liferay portlet mechanism. Damascus generates both Admin and User pages and renders classes separately.
+| File name | Note |
+| :-- | :-- |
+| *ViewMVCRenderCommand.java | Renders ```view.jsp``` |
+| *CrudMVCActionCommand.java | Process ```view/delete/update/``` create a record |
+| *CrudMVCRenderCommand.java | Renders ```edit.jsp``` and ```view.jsp``` according to the actions. |
+
+### How can I modify CRUD implementation?
+According to Liferay's best practices, all model manipulation methods are stored in ```*LocalServiceImpl.java```. Please see ```*LocalServiceImpl.java``` for more details.
+
+From 7.2, permission checking are all delegated into ```*ServiceImpl.java```. ```*LocalServiceImpl.java``` is now only responsible for processing business logic. For more details, please see ```Blogs``` implimentations in the Liferay's source code.
+
+When you modify the signature of methods or add new methods, please run ```gradle buildService``` to regenerate interfaces.
+
+### How can I implement validations?
+```*Validator.java``` includes validations. Please see the comments in the file for more details.
+
+### How can I implement Indexer?
+| File name | Note |
+| :-- | :-- |
+| *SearchRegistrar.java | Register all search related components in there.|
+| *ModelIndexerWriterContributor.java | This class is used during bulk reindexing to identify records to reindex.|
+| *ModelDocumentContributor.java | This class is used to contribute fields to the document to be indexed..|
+| *ModelPreFilterContributor.java | Filters search results before they are returned from the search engine.
+| *ModelResourcePermissionRegistrar.java | Model Resource Permission Registrar |
+| *ModelSummaryContributor.java | Manipulates the Summary object for each entity search result. |
+| *ModelVisibilityContributor.java | Controls the visibility of entities that can be attached to other asset types in the search context. |
+| *KeywordQueryContributor.java | Contributes clauses to the ongoing search query to control how the model entities are searched.|
+
+From 7.2, Search introduces new framework for the implementation, which is more modular and divides each search related functionality into different classes separately. For more details, please see the [official documents](https://help.liferay.com/hc/en-us/sections/360004656871-Search)
+
+### How can I modify permissions?
+```*ModelResourcePermissionRegistrar.java``` and ```*PortletResourcePermissionRegistrar.java``` register permission helpers to the search framework. Please modify these files according to your requirements.
+
+```*Permission.java``` classes are helper classes to check permission.
+
+```default.xml``` under ```*-web/src/main/resources/resource-actions/default.xml``` and ```*-service/src/main/resources/META-INF/resource-actions/default.xml``` contain permission configurations.
+
+### How can I modify view for Asset Publisher?
+```*AssetRenderer.java``` and ```*AssetRendererFactory.java``` render ```abstract.jsp```, ```abstract.jsp``` and ```prewview.jsp``` for ```Asset Framework```. For more details, please see the [official document](https://portal.liferay.dev/docs/7-2/frameworks/-/knowledge_base/f/creating-an-asset-renderer)
+
+# *-web
+This bundle includes classes and java files related to display portlets. This also contains utility classes to handle requests.
+
+| File name | Note |
+| :-- | :-- |
+| *WebPortlet.java | This is an entry point of displaying a portlet in the user area. |
+| *PanelApp.java, *AdminPortlet.java | This is an entry point of displaying a portlet in the administration area (inside of Control Panel) |
+| *PortletLayoutFinder.java | This is used for displaying contents in Asset Publisher with |
+| *AssetRendererFactory.java, *AssetRenderer.java | These classes are used to associate with an asset and generated model. |
+| *ItemSelectorHelper.java | This is used for Documents and Media related operations (such as uploading assets, selecting assets, e.g.) |
+| *ViewHelper.java | This class is a utility class mainly for handling search (search container) |
+
+# *-service
+```*-service``` includes files which allow access to persistent layer, and it's service layer classes, which furthermore allows access database through the models/services. This README is a reference to Damascus-generated files. For more details of files that Liferay service builder generates, please check out http://dev.liferay.com.
+
+## *LocalServiceImpl.java
+This class is an implementation of the service to access the database. Liferay service builder generates the base code for transactions and accessing the database, so you usually don't need to implement database connections/transactions by yourself as long as following Liferay's best practices.
+
+### addEntry* methods
+These methods are for adding records on a database.
+
+### updateEntry* methods
+These methods are for updating records on a database.
+
+### deleteEntry* methods
+These methods are for deleting records on a database.
+
+### moveEntryToTrash* methods
+These methods are for moving records into the trash instead of deleting them from a database.
+
+### find* methods
+According to Liferay's contract, ```find*``` methods are for retrieving a record from the database. For searching, you may want to use the search engine instead of directory searching on the database for better performance as a best practice.
+
+## Permission
+There are 5 files related to permission management
+| File name | Note |
+| :-- | :-- |
+| *Permission.java | Manage Portlet permission |
+| *EntryPermission.java | Manage Model permission |
+| *ModelResourcePermissionRegistrar.java | Register Model permission handler and configure details of permission types |
+| *PortletResourcePermissionRegistrar.java | Register portlet permission handler and configure details of permission types |
+| default.xml | Permission mapping |
+
+## *Validator.java
+This class is for validating data coming from a form in ```edit.jsp``` of ```*-web``` bundle. According to the comments inside, you can implement error handling. After implementing validation, each error method returns the error message key, so you need to add an appropriate error message handler in ```view.jsp``` accordingly. Please refer to the default messages that have already been in place in the ```view.jsp```.
+
+## *WorkflowHandler.java
+This model handles workflows.
+
+## *DisplayContext.java
+This class holds search related context and display contexts.
+
+## *ManagementToolbarDisplayContext.java
+This class process the contents and state of management bar in both Admin and user portlet.
+
+## *ExportMVCResourceCommand.java
+This class process Export model data as csv with Apache POI.
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXROOT_build.gradle.ftl b/src/main/resources/templates/7.3/Portlet_XXXXROOT_build.gradle.ftl
new file mode 100644
index 0000000..c3036e9
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXROOT_build.gradle.ftl
@@ -0,0 +1,27 @@
+//
+// //
+<#include "./valuables.ftl">
+<#assign createPath = "${createPath_val}/${dashcaseProjectName}/build.gradle">
+// //
+
+buildscript {
+ dependencies {
+ classpath group: "com.liferay", name: "com.liferay.gradle.plugins", version: "7.0.+"
+ }
+
+ repositories {
+ maven {
+ url "https://repository-cdn.liferay.com/nexus/content/groups/public"
+ }
+ }
+}
+
+subprojects {
+ apply plugin: "com.liferay.plugin"
+
+ repositories {
+ maven {
+ url "https://repository-cdn.liferay.com/nexus/content/groups/public"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXROOT_settings.gradle.ftl b/src/main/resources/templates/7.3/Portlet_XXXXROOT_settings.gradle.ftl
new file mode 100644
index 0000000..8a7ee6e
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXROOT_settings.gradle.ftl
@@ -0,0 +1,3 @@
+<#include "./valuables.ftl">
+<#assign createPath = "${createPath_val}/${dashcaseProjectName}/settings.gradle">
+include "${dashcaseProjectName}-api", "${dashcaseProjectName}-service"<#if anyGeneratedWeb>, "${dashcaseProjectName}-web"#if>
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl
new file mode 100644
index 0000000..69682a5
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl
@@ -0,0 +1,50 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/query/contributor/${capFirstModel}KeywordQueryContributor.java">
+/* */
+package ${packageName}.internal.search.query.contributor;
+
+import com.liferay.portal.kernel.search.BooleanQuery;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.search.query.QueryHelper;
+import com.liferay.portal.search.spi.model.query.contributor.KeywordQueryContributor;
+import com.liferay.portal.search.spi.model.query.contributor.helper.KeywordQueryContributorHelper;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Keyword Query Contributor
+ *
+ * Contributes clauses to the ongoing search query to control how the model entities are searched.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = KeywordQueryContributor.class
+)
+public class ${capFirstModel}KeywordQueryContributor implements KeywordQueryContributor {
+
+ @Override
+ public void contribute(String keywords, BooleanQuery booleanQuery,KeywordQueryContributorHelper keywordQueryContributorHelper) {
+ SearchContext searchContext = keywordQueryContributorHelper.getSearchContext();
+
+ // TODO: Adjust as necessary to support the search for the entity
+
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.ARTICLE_ID, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.CLASS_PK, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.ENTRY_CLASS_PK, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.USER_NAME, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.CONTENT, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.DESCRIPTION, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.TITLE, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.SUBTITLE, false);
+ }
+
+ @Reference
+ protected QueryHelper queryHelper;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_LocalServiceImpl.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
new file mode 100644
index 0000000..dbbad25
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
@@ -0,0 +1,1293 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/impl/${capFirstModel}LocalServiceImpl.java">
+/* */
+
+package ${packageName}.service.impl;
+
+import com.liferay.asset.kernel.model.AssetEntry;
+import com.liferay.asset.kernel.model.AssetLinkConstants;
+import com.liferay.exportimport.kernel.lar.ExportImportThreadLocal;
+import com.liferay.friendly.url.exception.DuplicateFriendlyURLEntryException;
+import com.liferay.friendly.url.model.FriendlyURLEntry;
+import com.liferay.friendly.url.service.FriendlyURLEntryLocalService;
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.aop.AopService;
+import com.liferay.portal.kernel.comment.CommentManagerUtil;
+import com.liferay.portal.kernel.dao.orm.QueryUtil;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.exception.SystemException;
+import com.liferay.portal.kernel.json.JSONFactoryUtil;
+import com.liferay.portal.kernel.json.JSONObject;
+import com.liferay.portal.kernel.model.ModelHintsUtil;
+import com.liferay.portal.kernel.model.ResourceConstants;
+import com.liferay.portal.kernel.model.SystemEventConstants;
+import com.liferay.portal.kernel.model.User;
+import com.liferay.portal.kernel.repository.model.ModelValidator;
+import com.liferay.portal.kernel.search.Indexable;
+import com.liferay.portal.kernel.search.IndexableType;
+import com.liferay.portal.kernel.service.ClassNameLocalService;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.service.permission.ModelPermissions;
+import com.liferay.portal.kernel.systemevent.SystemEvent;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ContentTypes;
+import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.kernel.util.OrderByComparator;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Portal;
+import com.liferay.portal.kernel.util.StringUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.base.${capFirstModel}LocalServiceBaseImpl;
+import ${packageName}.service.util.${capFirstModel}Validator;
+import com.liferay.trash.exception.RestoreEntryException;
+import com.liferay.trash.exception.TrashEntryException;
+import com.liferay.trash.model.TrashEntry;
+import com.liferay.trash.service.TrashEntryLocalService;
+
+import java.io.Serializable;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The implementation of the ${capFirstModel} local service.
+ *
+ *
+ * All custom service methods should be put in this class. Whenever methods are
+ * added, rerun ServiceBuilder to copy their definitions into the
+ * ${packageName}.service.${capFirstModel}LocalService
interface.
+ *
+ *
+ * This is a local service. Methods of this service will not have security
+ * checks based on the propagated JAAS credentials because this service can only
+ * be accessed from within the same VM.
+ *
+ *
+ * @author ${damascus_author}
+ * @see ${capFirstModel}LocalServiceBaseImpl
+ */
+@Component(
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = AopService.class
+)
+public class ${capFirstModel}LocalServiceImpl extends ${capFirstModel}LocalServiceBaseImpl {
+
+ /**
+ * Add Entry
+ *
+ * @param orgEntry ${capFirstModel} model
+ * @param serviceContext ServiceContext
+ * @exception PortalException
+ * @exception ${capFirstModel}ValidateException
+ * @return created ${capFirstModel} model.
+ */
+ @Indexable(type = IndexableType.REINDEX)
+ @Override
+ public ${capFirstModel} addEntry(${capFirstModel} orgEntry, ServiceContext serviceContext)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ long userId = serviceContext.getUserId();
+
+ // Validation
+
+ ModelValidator<${capFirstModel}> modelValidator = new ${capFirstModel}Validator();
+ modelValidator.validate(orgEntry);
+
+ ${capFirstModel} entry = _addEntry(orgEntry, serviceContext);
+
+ // Resources
+
+ if (serviceContext.isAddGroupPermissions() ||
+ serviceContext.isAddGuestPermissions()) {
+
+ addEntryResources(
+ entry, serviceContext.isAddGroupPermissions(),
+ serviceContext.isAddGuestPermissions());
+ }
+ else {
+ addEntryResources(entry, serviceContext.getModelPermissions());
+ }
+
+ // Asset
+
+ updateAsset(
+ userId, entry, serviceContext.getAssetCategoryIds(),
+ serviceContext.getAssetTagNames(),
+ serviceContext.getAssetLinkEntryIds(),
+ serviceContext.getAssetPriority());
+
+ // Workflow
+
+ return startWorkflowInstance(userId, entry, serviceContext);
+ }
+
+ @Override
+ public void addEntryResources(
+ long entryId, boolean addGroupPermissions,
+ boolean addGuestPermissions)
+ throws PortalException {
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ addEntryResources(entry, addGroupPermissions, addGuestPermissions);
+ }
+
+ @Override
+ public void addEntryResources(
+ long entryId, ModelPermissions modelPermissions)
+ throws PortalException {
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ addEntryResources(entry, modelPermissions);
+ }
+
+ @Override
+ public void addEntryResources(
+ ${capFirstModel} entry, boolean addGroupPermissions,
+ boolean addGuestPermissions)
+ throws PortalException {
+
+ resourceLocalService.addResources(
+ entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), false,
+ addGroupPermissions, addGuestPermissions);
+ }
+
+ @Override
+ public void addEntryResources(
+ ${capFirstModel} entry, ModelPermissions modelPermissions)
+ throws PortalException {
+
+ resourceLocalService.addModelResources(
+ entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), modelPermissions);
+ }
+
+ public int countAllInGroup(long groupId) {
+ int count = ${uncapFirstModel}Persistence.countByGroupId(groupId);
+
+ return count;
+ }
+
+ public int countAllInGroup(long groupId, int[] status) {
+ int count = ${uncapFirstModel}Persistence.countByG_S(groupId, status);
+
+ return count;
+ }
+
+ public int countAllInUser(long userId) {
+ int count = ${uncapFirstModel}Persistence.countByUserId(userId);
+
+ return count;
+ }
+
+ public int countAllInUser(long userId, int[] status) {
+ int count = ${uncapFirstModel}Persistence.countByU_S(userId, status);
+
+ return count;
+ }
+
+ public int countAllInUserAndGroup(long userId, long groupId) {
+ int count = ${uncapFirstModel}Persistence.countByUserIdGroupId(userId, groupId);
+
+ return count;
+ }
+
+ public int countAllInUserAndGroup(long userId, long groupId, int[] status) {
+ int count = ${uncapFirstModel}Persistence.countByG_U_S(groupId, userId, status);
+
+ return count;
+ }
+
+ /**
+ * Delete entry
+ */
+ public ${capFirstModel} deleteEntry(long primaryKey) throws PortalException {
+ ${capFirstModel} entry = get${capFirstModel}(primaryKey);
+
+ return deleteEntry(entry);
+ }
+
+ /**
+ * Delete entry
+ *
+ * @param entry ${capFirstModel}
+ * @return ${capFirstModel} oject
+ * @exception PortalException
+ */
+ @Indexable(type = IndexableType.DELETE)
+ @Override
+ @SystemEvent(type = SystemEventConstants.TYPE_DELETE)
+ public ${capFirstModel} deleteEntry(${capFirstModel} entry) throws PortalException {
+
+ // Entry
+
+ ${uncapFirstModel}Persistence.remove(entry);
+
+ // Resources
+
+ resourceLocalService.deleteResource(
+ entry.getCompanyId(), ${capFirstModel}.class.getName(),
+ ResourceConstants.SCOPE_INDIVIDUAL, entry.getPrimaryKey());
+
+ // Asset
+
+ assetEntryLocalService.deleteEntry(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey());
+
+ // Comment
+
+ deleteDiscussion(entry);
+
+ // Friendly URL
+
+ _friendlyURLEntryLocalService.deleteFriendlyURLEntry(
+ entry.getGroupId(), ${capFirstModel}.class, entry.getPrimaryKey());
+
+ // Trash
+
+ _trashEntryLocalService.deleteEntry(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey());
+
+ // Workflow
+
+ workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
+ entry.getCompanyId(), entry.getGroupId(), ${capFirstModel}.class.getName(),
+ entry.getPrimaryKey());
+
+ return entry;
+ }
+
+ public List<${capFirstModel}> findAllInGroup(long groupId) {
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByGroupId(
+ groupId);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInGroup(
+ long groupId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ return findAllInGroup(
+ groupId, start, end, orderByComparator,
+ new int[] {WorkflowConstants.STATUS_APPROVED});
+ }
+
+ public List<${capFirstModel}> findAllInGroup(
+ long groupId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator, int[] status) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByG_S(
+ groupId, status, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInGroup(long groupId, int[] status) {
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByG_S(
+ groupId, status);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInGroup(
+ long groupId, OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)findAllInGroup(
+ groupId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(long userId) {
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByUserId(
+ userId);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(
+ long userId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByUserId(
+ userId, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(
+ long userId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator, int[] status) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByU_S(
+ userId, status, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(long userId, int[] status) {
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByU_S(
+ userId, status);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(
+ long userId, OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)findAllInUser(
+ userId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(long userId, long groupId) {
+ List<${capFirstModel}> list =
+ (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByUserIdGroupId(
+ userId, groupId);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(
+ long userId, long groupId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list =
+ (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByUserIdGroupId(
+ groupId, userId, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(
+ long userId, long groupId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator, int[] status) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByG_U_S(
+ groupId, userId, status, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(
+ long userId, long groupId, int[] status) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByG_U_S(
+ groupId, userId, status);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(
+ long userId, long groupId,
+ OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)findAllInUserAndGroup(
+ groupId, userId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
+ orderByComparator);
+
+ return list;
+ }
+
+ /**
+ * Get Company entries
+ *
+ * @param companyId Company Id
+ * @param status Workflow status
+ * @param start start index of entries
+ * @param end end index of entries
+ * @return
+ * @throws SystemException
+ */
+ public List<${capFirstModel}> getCompanyEntries(
+ long companyId, int status, int start, int end) {
+
+ if (status == WorkflowConstants.STATUS_ANY) {
+ return ${uncapFirstModel}Persistence.findByCompanyId(companyId, start, end);
+ }
+
+ return ${uncapFirstModel}Persistence.findByC_S(companyId, status, start, end);
+ }
+
+ /**
+ * Get Company entries
+ *
+ * @param companyId Company Id
+ * @param status Workflow status
+ * @param start start index of entries
+ * @param end end index of entries
+ * @param obc Comparator for the order
+ * @return List of entries
+ * @throws SystemException
+ */
+ public List<${capFirstModel}> getCompanyEntries(
+ long companyId, int status, int start, int end,
+ OrderByComparator<${capFirstModel}> obc) {
+
+ if (status == WorkflowConstants.STATUS_ANY) {
+ return ${uncapFirstModel}Persistence.findByCompanyId(
+ companyId, start, end, obc);
+ }
+
+ return ${uncapFirstModel}Persistence.findByC_S(
+ companyId, status, start, end, obc);
+ }
+
+ /**
+ * Get Company entries counts
+ *
+ * @param companyId
+ * @param status
+ * @return
+ * @throws SystemException
+ */
+ public int getCompanyEntriesCount(long companyId, int status) {
+ if (status == WorkflowConstants.STATUS_ANY) {
+ return ${uncapFirstModel}Persistence.countByCompanyId(companyId);
+ }
+
+ return ${uncapFirstModel}Persistence.countByC_S(companyId, status);
+ }
+
+ /**
+ * Converte Date Time into Date()
+ *
+ * @param request PortletRequest
+ * @param prefix Prefix of the parameter
+ * @return Date object
+ */
+ public Date getDateTimeFromRequest(PortletRequest request, String prefix) {
+ int Year = ParamUtil.getInteger(request, prefix + "Year");
+ int Month = ParamUtil.getInteger(request, prefix + "Month") + 1;
+ int Day = ParamUtil.getInteger(request, prefix + "Day");
+ int Hour = ParamUtil.getInteger(request, prefix + "Hour");
+ int Minute = ParamUtil.getInteger(request, prefix + "Minute");
+ int AmPm = ParamUtil.getInteger(request, prefix + "AmPm");
+
+ if (AmPm == Calendar.PM) {
+ Hour += 12;
+ }
+
+ LocalDateTime ldt;
+
+ try {
+ ldt = LocalDateTime.of(Year, Month, Day, Hour, Minute, 0);
+ }
+ catch (Exception e) {
+ _log.error(
+ "Unnable get date data. Initialize with current date", e);
+ Date in = new Date();
+
+ Instant instant = in.toInstant();
+
+ return Date.from(instant);
+ }
+
+ return Date.from(
+ ldt.atZone(
+ ZoneId.systemDefault()
+ ).toInstant());
+ }
+
+ /**
+ * Populate Model with values from a form
+ *
+ * @param primaryKey primary key
+ * @param request PortletRequest
+ * @return ${capFirstModel} Object
+ * @throws PortletException
+ */
+ public ${capFirstModel} getInitialized${capFirstModel}(
+ long primaryKey, PortletRequest request)
+ throws PortletException {
+
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ // Create or fetch existing data
+
+ ${capFirstModel} entry = getNewObject(primaryKey);
+
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Long" >
+ <#if field.primary?? && field.primary == true >
+ entry.set${field.name?cap_first}(primaryKey);
+ <#else>
+ entry.set${field.name?cap_first}(0);
+ #if>
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" >
+ entry.set${field.name?cap_first}("");
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Date" >
+ entry.set${field.name?cap_first}(new Date());
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" >
+ entry.set${field.name?cap_first}(new Date());
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" >
+ entry.set${field.name?cap_first}(true);
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+ entry.set${field.name?cap_first}("");
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Double" >
+ entry.set${field.name?cap_first}(0.0);
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Integer" >
+ entry.set${field.name?cap_first}(0);
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ entry.set${field.name?cap_first}("");
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Text" >
+ entry.set${field.name?cap_first}("");
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+ entry.set${application.asset.assetTitleFieldName?cap_first}("");
+ entry.set${application.asset.assetSummaryFieldName?cap_first}("");
+
+ entry.setCompanyId(themeDisplay.getCompanyId());
+ entry.setGroupId(themeDisplay.getScopeGroupId());
+ entry.setUserId(themeDisplay.getUserId());
+
+ return entry;
+ }
+
+ /**
+ * Get Record
+ *
+ * @param primaryKey Primary key
+ * @return ${capFirstModel} object
+ * @throws PortletException
+ */
+ public ${capFirstModel} getNewObject(long primaryKey) {
+ primaryKey = (primaryKey <= 0) ? 0 :
+ counterLocalService.increment(${capFirstModel}.class.getName());
+
+ return create${capFirstModel}(primaryKey);
+ }
+
+ /**
+ * Get Entity
+ *
+ * @param groupId
+ * @param urlTitle
+ * @return
+ * @throws PortalException
+ */
+ public ${capFirstModel} get${capFirstModel}(long groupId, String urlTitle)
+ throws PortalException {
+
+ FriendlyURLEntry friendlyURLEntry =
+ _friendlyURLEntryLocalService.fetchFriendlyURLEntry(
+ groupId, ${capFirstModel}.class, urlTitle);
+
+ if (friendlyURLEntry != null) {
+ return ${uncapFirstModel}Persistence.findByPrimaryKey(
+ friendlyURLEntry.getClassPK());
+ }
+
+ return ${uncapFirstModel}Persistence.findByG_UT(groupId, urlTitle);
+ }
+
+ /**
+ * Populate Model with values from a form
+ *
+ * @param request PortletRequest
+ * @return ${capFirstModel} Object
+ * @throws PortletException
+ * @throws ${capFirstModel}ValidateException
+ */
+ public ${capFirstModel} get${capFirstModel}FromRequest(
+ long primaryKey, PortletRequest request)
+ throws PortletException, ${capFirstModel}ValidateException {
+
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ // Create or fetch existing data
+
+ ${capFirstModel} entry;
+
+ if (primaryKey <= 0) {
+ entry = getNewObject(primaryKey);
+ }
+ else {
+ entry = fetch${capFirstModel}(primaryKey);
+ }
+
+ try {
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Long" >
+ <#if field.primary?? && field.primary == true >
+ entry.set${field.name?cap_first}(primaryKey);
+ <#else>
+ entry.set${field.name?cap_first}(ParamUtil.getLong(request, "${field.name}"));
+ #if>
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" >
+ entry.set${field.name?cap_first}(ParamUtil.getString(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Date" >
+ entry.set${field.name?cap_first}(getDateTimeFromRequest(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" >
+ entry.set${field.name?cap_first}(getDateTimeFromRequest(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" >
+ entry.set${field.name?cap_first}(ParamUtil.getBoolean(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+ entry.set${field.name?cap_first}(ParamUtil.getString(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Double" >
+ entry.set${field.name?cap_first}(ParamUtil.getDouble(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Integer" >
+ entry.set${field.name?cap_first}(ParamUtil.getInteger(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ entry.set${field.name?cap_first}(ParamUtil.getString(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Text" >
+ entry.set${field.name?cap_first}(ParamUtil.getString(request, "${field.name}"));
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+
+ entry.set${application.asset.assetTitleFieldName?cap_first}(
+ ParamUtil.getString(request, "${application.asset.assetTitleFieldName}"));
+ entry.set${application.asset.assetSummaryFieldName?cap_first}(
+ ParamUtil.getString(request, "${application.asset.assetSummaryFieldName}"));
+
+ entry.setCompanyId(themeDisplay.getCompanyId());
+ entry.setGroupId(themeDisplay.getScopeGroupId());
+ entry.setUserId(themeDisplay.getUserId());
+ }
+ catch (Exception e) {
+ _log.error("Errors occur while populating the model", e);
+ List error = new ArrayList<>();
+ error.add("value-convert-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ return entry;
+ }
+
+ /**
+ * Get STATUS_ANY for DB
+ *
+ * This is equivalent of WorkflowConstants.STATUS_ANY
+ *
+ * @return All statuses for Workflow
+ */
+ public int[] getStatusAny() {
+ return STATUS_ANY;
+ }
+
+ public ${capFirstModel} moveEntryToTrash(long userId, long entryId)
+ throws PortalException {
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ return moveEntryToTrash(userId, entry);
+ }
+
+ /**
+ * Moves the entry to the recycle bin.
+ *
+ * Social activity counters for this entry get disabled.
+ *
+ * @param userId the primary key of the user moving the entry
+ * @param entry the entry to be moved
+ * @return the moved entry
+ */
+ @Indexable(type = IndexableType.REINDEX)
+ @Override
+ public ${capFirstModel} moveEntryToTrash(long userId, ${capFirstModel} entry)
+ throws PortalException {
+
+ // Entry
+
+ if (entry.isInTrash()) {
+ throw new TrashEntryException();
+ }
+
+ int oldStatus = entry.getStatus();
+
+ if (oldStatus == WorkflowConstants.STATUS_PENDING) {
+ entry.setStatus(WorkflowConstants.STATUS_DRAFT);
+
+ ${uncapFirstModel}Persistence.update(entry);
+ }
+
+ entry = updateStatus(
+ userId, entry.getPrimaryKey(), WorkflowConstants.STATUS_IN_TRASH,
+ new ServiceContext(), new HashMap());
+
+ // Workflow
+
+ if (oldStatus == WorkflowConstants.STATUS_PENDING) {
+ workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
+ entry.getCompanyId(), entry.getGroupId(),
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey());
+ }
+
+ return entry;
+ }
+
+ /**
+ * Restores the entry with the ID from the recycle bin. Social activity counters
+ * for this entry get activated.
+ *
+ * @param userId the primary key of the user restoring the entry
+ * @param entryId the primary key of the entry to be restored
+ * @return the restored entry from the recycle bin
+ */
+ @Indexable(type = IndexableType.REINDEX)
+ @Override
+ public ${capFirstModel} restoreEntryFromTrash(long userId, long entryId)
+ throws PortalException {
+
+ // Entry
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ if (!entry.isInTrash()) {
+ throw new RestoreEntryException(
+ RestoreEntryException.INVALID_STATUS);
+ }
+
+ TrashEntry trashEntry = _trashEntryLocalService.getEntry(
+ ${capFirstModel}.class.getName(), entryId);
+
+ updateStatus(
+ userId, entryId, trashEntry.getStatus(), new ServiceContext(),
+ new HashMap());
+
+ return entry;
+ }
+
+ @Override
+ public void updateAsset(
+ long userId, ${capFirstModel} entry, long[] assetCategoryIds,
+ String[] assetTagNames, long[] assetLinkEntryIds, Double priority)
+ throws PortalException {
+
+ boolean visible = false;
+
+ if (entry.isApproved()) {
+ visible = true;
+ }
+
+ String summary = HtmlUtil.extractText(
+ StringUtil.shorten(entry.get${application.asset.assetSummaryFieldName?cap_first}(), 500));
+
+ AssetEntry assetEntry = assetEntryLocalService.updateEntry(
+ userId, entry.getGroupId(), entry.getCreateDate(),
+ entry.getModifiedDate(), ${capFirstModel}.class.getName(),
+ entry.getPrimaryKey(), entry.getUuid(), 0, assetCategoryIds,
+ assetTagNames, true, visible, null, null, null, null,
+ ContentTypes.TEXT_HTML, entry.get${application.asset.assetTitleFieldName?cap_first}(), null, summary,
+ null, null, 0, 0, priority);
+
+ assetLinkLocalService.updateLinks(
+ userId, assetEntry.getEntryId(), assetLinkEntryIds,
+ AssetLinkConstants.TYPE_RELATED);
+ }
+
+ /**
+ * Edit Entry
+ *
+ * @param orgEntry ${capFirstModel} model
+ * @param serviceContext ServiceContext
+ * @exception PortalException
+ * @exception ${capFirstModel}ValidateException
+ * @return updated ${capFirstModel} model.
+ */
+ @Indexable(type = IndexableType.REINDEX)
+ @Override
+ public ${capFirstModel} updateEntry(
+ ${capFirstModel} orgEntry, ServiceContext serviceContext)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ User user = userLocalService.getUser(orgEntry.getUserId());
+
+ // Validation
+
+ ModelValidator<${capFirstModel}> modelValidator = new ${capFirstModel}Validator();
+ modelValidator.validate(orgEntry);
+
+ // Update entry
+
+ ${capFirstModel} entry = _updateEntry(
+ orgEntry.getPrimaryKey(), orgEntry, serviceContext);
+
+ if (!entry.isPending() && !entry.isDraft()) {
+ entry.setStatus(WorkflowConstants.STATUS_DRAFT);
+ }
+
+ ${capFirstModel} updatedEntry = ${uncapFirstModel}Persistence.update(entry);
+
+ // Asset
+
+ updateAsset(
+ updatedEntry.getUserId(), updatedEntry,
+ serviceContext.getAssetCategoryIds(),
+ serviceContext.getAssetTagNames(),
+ serviceContext.getAssetLinkEntryIds(),
+ serviceContext.getAssetPriority());
+
+ updatedEntry = startWorkflowInstance(
+ user.getUserId(), updatedEntry, serviceContext);
+
+ return updatedEntry;
+ }
+
+ @Override
+ public void updateEntryResources(
+ ${capFirstModel} entry, String[] groupPermissions,
+ String[] guestPermissions)
+ throws PortalException {
+
+ resourceLocalService.updateResources(
+ entry.getCompanyId(), entry.getGroupId(), ${capFirstModel}.class.getName(),
+ entry.getPrimaryKey(), groupPermissions, guestPermissions);
+ }
+
+ @Indexable(type = IndexableType.REINDEX)
+ public ${capFirstModel} updateStatus(
+ long userId, long entryId, int status,
+ ServiceContext serviceContext,
+ Map workflowContext)
+ throws PortalException {
+
+ // Entry
+
+ User user = userLocalService.getUser(userId);
+ Date now = new Date();
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ int oldStatus = entry.getStatus();
+
+ entry.setModifiedDate(serviceContext.getModifiedDate(now));
+ entry.setStatus(status);
+ entry.setStatusByUserId(user.getUserId());
+ entry.setStatusByUserName(user.getFullName());
+ entry.setStatusDate(serviceContext.getModifiedDate(now));
+
+ ${uncapFirstModel}Persistence.update(entry);
+
+ AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
+ ${capFirstModel}.class.getName(), entryId);
+
+ if ((assetEntry == null) || (assetEntry.getPublishDate() == null)) {
+ serviceContext.setCommand(Constants.ADD);
+ }
+
+ JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
+
+ extraDataJSONObject.put("title", entry.get${application.asset.assetTitleFieldName?cap_first}());
+
+ if (status == WorkflowConstants.STATUS_APPROVED) {
+
+ // Asset
+
+ assetEntryLocalService.updateEntry(
+ ${capFirstModel}.class.getName(), entryId, entry.getModifiedDate(),
+ null, true, true);
+
+ // Trash
+
+ if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
+ CommentManagerUtil.restoreDiscussionFromTrash(
+ ${capFirstModel}.class.getName(), entryId);
+
+ _trashEntryLocalService.deleteEntry(
+ ${capFirstModel}.class.getName(), entryId);
+ }
+ }
+ else {
+
+ // Asset
+
+ assetEntryLocalService.updateVisible(
+ ${capFirstModel}.class.getName(), entryId, false);
+
+ // Trash
+
+ if (status == WorkflowConstants.STATUS_IN_TRASH) {
+ CommentManagerUtil.moveDiscussionToTrash(
+ ${capFirstModel}.class.getName(), entryId);
+ _trashEntryLocalService.addTrashEntry(
+ userId, entry.getGroupId(), ${capFirstModel}.class.getName(),
+ entry.getPrimaryKey(), entry.getUuid(), null, oldStatus,
+ null, null);
+ }
+ else if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
+ CommentManagerUtil.restoreDiscussionFromTrash(
+ ${capFirstModel}.class.getName(), entryId);
+
+ _trashEntryLocalService.deleteEntry(
+ ${capFirstModel}.class.getName(), entryId);
+ }
+ }
+
+ return entry;
+ }
+
+ /**
+ * Copy models at add entry
+ *
+ * To process storing a record into database, copy the model passed into a new
+ * model object here.
+ *
+ * @param entry model object
+ * @param serviceContext ServiceContext
+ * @return
+ * @throws PortalException
+ */
+ protected ${capFirstModel} _addEntry(${capFirstModel} entry, ServiceContext serviceContext)
+ throws PortalException {
+
+ long id = counterLocalService.increment(${capFirstModel}.class.getName());
+
+ ${capFirstModel} newEntry = ${uncapFirstModel}Persistence.create(id);
+
+ User user = userLocalService.getUser(entry.getUserId());
+
+ Date now = new Date();
+ newEntry.setCompanyId(entry.getCompanyId());
+ newEntry.setGroupId(entry.getGroupId());
+ newEntry.setUserId(user.getUserId());
+ newEntry.setUserName(user.getFullName());
+ newEntry.setCreateDate(now);
+ newEntry.setModifiedDate(now);
+
+ newEntry.setUuid(serviceContext.getUuid());
+
+ // Friendly URLs
+ String urlTitle = getUniqueUrlTitle(newEntry, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ urlTitle = updateFriendlyURLs(newEntry, urlTitle, serviceContext);
+ newEntry.setUrlTitle(urlTitle);
+
+ newEntry.set${application.asset.assetTitleFieldName?cap_first}(entry.get${application.asset.assetTitleFieldName?cap_first}());
+ newEntry.set${application.asset.assetSummaryFieldName?cap_first}(entry.get${application.asset.assetSummaryFieldName?cap_first}());
+
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- Primary key is ommited here because the pk is already created in newEntry -->
+ <#if field.primary?? && field.primary == false >
+ newEntry.set${field.name?cap_first}(entry.get${field.name?cap_first}());
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+
+ return ${uncapFirstModel}Persistence.update(newEntry);
+ }
+
+ /**
+ * Copy models at update entry
+ *
+ * To process storing a record into database, copy the model passed into a new
+ * model object here.
+ *
+ * @param primaryKey Primary key
+ * @param entry model object
+ * @param serviceContext ServiceContext
+ * @return updated entry
+ * @throws PortalException
+ */
+ protected ${capFirstModel} _updateEntry(
+ long primaryKey, ${capFirstModel} entry, ServiceContext serviceContext)
+ throws PortalException {
+
+ ${capFirstModel} updateEntry = fetch${capFirstModel}(primaryKey);
+
+ User user = userLocalService.getUser(entry.getUserId());
+
+ Date now = new Date();
+ updateEntry.setCompanyId(entry.getCompanyId());
+ updateEntry.setGroupId(entry.getGroupId());
+ updateEntry.setUserId(user.getUserId());
+ updateEntry.setUserName(user.getFullName());
+ updateEntry.setCreateDate(entry.getCreateDate());
+ updateEntry.setModifiedDate(now);
+
+ updateEntry.setUuid(entry.getUuid());
+ String urlTitle = entry.get${application.asset.assetTitleFieldName?cap_first}();
+ if (Validator.isNotNull(urlTitle)) {
+ long classNameId = _classNameLocalService.getClassNameId(
+ ${capFirstModel}.class);
+
+ try{
+ _friendlyURLEntryLocalService.validate(
+ entry.getGroupId(), classNameId, primaryKey, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ } catch(DuplicateFriendlyURLEntryException e) {
+ List error = new ArrayList();
+ error.add("duplicated-url-title");
+ throw new ${capFirstModel}ValidateException(error);
+ }
+ }
+ else {
+ urlTitle = getUniqueUrlTitle(entry, urlTitle);
+ }
+
+ if (!urlTitle.equals(entry.getUrlTitle())) {
+ urlTitle = updateFriendlyURLs(entry, urlTitle, serviceContext);
+ }
+
+ updateEntry.setUrlTitle(
+ getUniqueUrlTitle(updateEntry, urlTitle));
+
+ updateEntry.set${application.asset.assetTitleFieldName?cap_first}(entry.get${application.asset.assetTitleFieldName?cap_first}());
+ updateEntry.set${application.asset.assetSummaryFieldName?cap_first}(entry.get${application.asset.assetSummaryFieldName?cap_first}());
+
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ updateEntry.set${field.name?cap_first}(entry.get${field.name?cap_first}());
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+
+ return updateEntry;
+ }
+
+ /**
+ * Update Friendly URLs
+ *
+ * @param entry ${capFirstModel}
+ * @param urlTitle
+ * @param serviceContext
+ * @return string
+ * @throws PortalException
+ */
+ protected String updateFriendlyURLs(
+ ${capFirstModel} entry, String urlTitle,
+ ServiceContext serviceContext)
+ throws PortalException {
+
+ if (ExportImportThreadLocal.isImportInProcess() ||
+ ExportImportThreadLocal.isStagingInProcess()) {
+
+ return urlTitle;
+ }
+
+ List friendlyURLEntries =
+ _friendlyURLEntryLocalService.getFriendlyURLEntries(
+ entry.getGroupId(),
+ classNameLocalService.getClassNameId(${capFirstModel}.class),
+ entry.getPrimaryKey());
+
+ FriendlyURLEntry newFriendlyURLEntry =
+ _friendlyURLEntryLocalService.addFriendlyURLEntry(
+ entry.getGroupId(),
+ classNameLocalService.getClassNameId(${capFirstModel}.class),
+ entry.getPrimaryKey(), urlTitle, serviceContext);
+
+ for (FriendlyURLEntry friendlyURLEntry : friendlyURLEntries) {
+ if (newFriendlyURLEntry.getFriendlyURLEntryId() ==
+ friendlyURLEntry.getFriendlyURLEntryId()) {
+
+ continue;
+ }
+
+ _friendlyURLEntryLocalService.deleteFriendlyURLEntry(friendlyURLEntry);
+ }
+
+ return newFriendlyURLEntry.getUrlTitle();
+ }
+
+ /**
+ * Delete discussion (comments)
+ *
+ * @param entry
+ * @throws PortalException
+ */
+ protected void deleteDiscussion(${capFirstModel} entry) throws PortalException {
+ CommentManagerUtil.deleteDiscussion(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey());
+ }
+
+ /**
+ * Generating a unique URL for asset
+ */
+ protected String getUniqueUrlTitle(${capFirstModel} entry, String newTitle) {
+ long entryId = entry.getPrimaryKey();
+
+ String urlTitle = null;
+
+ if (newTitle == null || newTitle.equals("")) {
+ urlTitle = String.valueOf(entryId);
+ }
+ else {
+ urlTitle = StringUtil.toLowerCase(newTitle.trim());
+
+ if (Validator.isNull(urlTitle) || Validator.isNumber(urlTitle) ||
+ urlTitle.equals("rss")) {
+
+ urlTitle = String.valueOf(entryId);
+ }
+ else {
+ urlTitle =
+ FriendlyURLNormalizerUtil.normalizeWithPeriodsAndSlashes(
+ urlTitle);
+ }
+
+ urlTitle = ModelHintsUtil.trimString(
+ ${capFirstModel}.class.getName(), "urlTitle", urlTitle);
+ }
+
+ long classNameId = _classNameLocalService.getClassNameId(
+ ${capFirstModel}.class);
+
+ return _friendlyURLEntryLocalService.getUniqueUrlTitle(
+ entry.getGroupId(), classNameId, entry.getPrimaryKey(), urlTitle);
+ }
+
+ /**
+ * Generating URL Title for unique URL
+ *
+ * @param entryId primaryKey of the model
+ * @param title title for the asset
+ * @return URL title string
+ */
+ protected String getUrlTitle(long entryId, String title) {
+ if (title == null) {
+ return String.valueOf(entryId);
+ }
+
+ title = StringUtil.toLowerCase(title.trim());
+
+ if (Validator.isNull(title) || Validator.isNumber(title)) {
+ title = String.valueOf(entryId);
+ }
+ else {
+ title = FriendlyURLNormalizerUtil.normalizeWithPeriodsAndSlashes(
+ title);
+ }
+
+ return ModelHintsUtil.trimString(
+ ${capFirstModel}.class.getName(), "urlTitle", title);
+ }
+
+ /**
+ * Start workflow
+ *
+ * @param userId User id of this model's owner
+ * @param entry model object
+ * @param serviceContext ServiceContext
+ * @return model with workflow configrations.
+ * @throws PortalException
+ */
+ protected ${capFirstModel} startWorkflowInstance(
+ long userId, ${capFirstModel} entry, ServiceContext serviceContext)
+ throws PortalException {
+
+ Map workflowContext = new HashMap<>();
+
+ String userPortraitURL = StringPool.BLANK;
+ String userURL = StringPool.BLANK;
+
+ if (serviceContext.getThemeDisplay() != null) {
+ User user = userLocalService.getUser(userId);
+
+ userPortraitURL = user.getPortraitURL(
+ serviceContext.getThemeDisplay());
+ userURL = user.getDisplayURL(serviceContext.getThemeDisplay());
+ }
+
+ workflowContext.put(
+ WorkflowConstants.CONTEXT_USER_PORTRAIT_URL, userPortraitURL);
+ workflowContext.put(WorkflowConstants.CONTEXT_USER_URL, userURL);
+
+ return WorkflowHandlerRegistryUtil.startWorkflowInstance(
+ entry.getCompanyId(), entry.getGroupId(), userId,
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), entry,
+ serviceContext, workflowContext);
+ }
+
+ private static final int[] STATUS_ANY = {
+ WorkflowConstants.STATUS_APPROVED, WorkflowConstants.STATUS_DENIED,
+ WorkflowConstants.STATUS_DRAFT, WorkflowConstants.STATUS_EXPIRED,
+ WorkflowConstants.STATUS_IN_TRASH, WorkflowConstants.STATUS_INACTIVE,
+ WorkflowConstants.STATUS_INCOMPLETE, WorkflowConstants.STATUS_PENDING,
+ WorkflowConstants.STATUS_SCHEDULED
+ };
+
+ private static Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}LocalServiceImpl.class);
+
+ @Reference
+ private ClassNameLocalService _classNameLocalService;
+
+ @Reference
+ private FriendlyURLEntryLocalService _friendlyURLEntryLocalService;
+
+ @Reference
+ private Portal _portal;
+
+ @Reference
+ private TrashEntryLocalService _trashEntryLocalService;
+
+}
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl
new file mode 100644
index 0000000..d4375b6
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl
@@ -0,0 +1,45 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/index/contributor/${capFirstModel}ModelDocumentContributor.java">
+/* */
+package ${packageName}.internal.search.index.contributor;
+
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.search.spi.model.index.contributor.ModelDocumentContributor;
+import org.osgi.service.component.annotations.Component;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Model Document Contributor
+ *
+ * This class is used to contribute fields to the document to be indexed.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelDocumentContributor.class
+)
+public class ${capFirstModel}ModelDocumentContributor implements ModelDocumentContributor<${capFirstModel}> {
+
+ @Override
+ public void contribute(Document document, ${capFirstModel} entry) {
+
+ // TODO : These fields should be modified according to your requirements.
+
+ document.addText(Field.CAPTION, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(
+ Field.CONTENT,
+ HtmlUtil.extractText(entry.get${application.asset.assetSummaryFieldName?cap_first}()));
+ document.addText(Field.DESCRIPTION, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(Field.SUBTITLE, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(Field.TITLE, entry.get${application.asset.assetTitleFieldName?cap_first}());
+
+ document.addDate(Field.MODIFIED_DATE, entry.getModifiedDate());
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl
new file mode 100644
index 0000000..c7f86c0
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl
@@ -0,0 +1,89 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/index/contributor/${capFirstModel}ModelIndexerWriterContributor.java">
+/* */
+package ${packageName}.internal.search.index.contributor;
+
+import com.liferay.portal.kernel.dao.orm.Property;
+import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.search.batch.BatchIndexingActionable;
+import com.liferay.portal.search.batch.DynamicQueryBatchIndexingActionableFactory;
+import com.liferay.portal.search.spi.model.index.contributor.ModelIndexerWriterContributor;
+import com.liferay.portal.search.spi.model.index.contributor.helper.IndexerWriterMode;
+import com.liferay.portal.search.spi.model.index.contributor.helper.ModelIndexerWriterDocumentHelper;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+/**
+ * ${capFirstModel} Model Indexer Writer Contributor
+ *
+ * This class is used during bulk reindexing to identify records to reindex.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelIndexerWriterContributor.class
+)
+public class ${capFirstModel}ModelIndexerWriterContributor implements ModelIndexerWriterContributor<${capFirstModel}> {
+
+ @Override
+ public void customize(BatchIndexingActionable batchIndexingActionable, ModelIndexerWriterDocumentHelper modelIndexerWriterDocumentHelper) {
+
+ // TODO: add criteria to the DQ to select the entities to include in the reindex.
+ batchIndexingActionable.setAddCriteriaMethod(dynamicQuery -> {
+ Property statusProperty = PropertyFactoryUtil.forName("status");
+
+ Integer[] statuses = {
+ WorkflowConstants.STATUS_APPROVED,
+ WorkflowConstants.STATUS_IN_TRASH
+ };
+
+ // reindex any entry that is approved or in the trash
+ dynamicQuery.add(statusProperty.in(statuses));
+ });
+
+ // add any matched entry into the documents to index.
+ batchIndexingActionable.setPerformActionMethod((${capFirstModel} entry) -> {
+ batchIndexingActionable.addDocuments(modelIndexerWriterDocumentHelper.getDocument(entry));
+ });
+ }
+
+ @Override
+ public IndexerWriterMode getIndexerWriterMode(${capFirstModel} entry) {
+
+ // TODO: Update as necessary to control the indexer writer mode for the given entry.
+
+ int status = entry.getStatus();
+
+ if ((status == WorkflowConstants.STATUS_APPROVED) || (status == WorkflowConstants.STATUS_IN_TRASH) || (status == WorkflowConstants.STATUS_DRAFT)) {
+ return IndexerWriterMode.UPDATE;
+ }
+
+ return IndexerWriterMode.DELETE;
+ }
+
+ @Override
+ public BatchIndexingActionable getBatchIndexingActionable() {
+ return dynamicQueryBatchIndexingActionableFactory.getBatchIndexingActionable(
+ _${uncapFirstModel}LocalService.getIndexableActionableDynamicQuery());
+ }
+
+ @Override
+ public long getCompanyId(${capFirstModel} entry) {
+ return entry.getCompanyId();
+ }
+
+ @Reference
+ protected ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+ @Reference
+ protected DynamicQueryBatchIndexingActionableFactory dynamicQueryBatchIndexingActionableFactory;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl
new file mode 100644
index 0000000..5cc6f50
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl
@@ -0,0 +1,45 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/query/contributor/${capFirstModel}ModelPreFilterContributor.java">
+/* */
+package ${packageName}.internal.search.query.contributor;
+
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.kernel.search.filter.BooleanFilter;
+import com.liferay.portal.search.spi.model.query.contributor.ModelPreFilterContributor;
+import com.liferay.portal.search.spi.model.registrar.ModelSearchSettings;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model PreFilter Contributor
+ *
+ * Filters search results before they are returned from the search engine.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelPreFilterContributor.class
+)
+public class ${capFirstModel}ModelPreFilterContributor implements ModelPreFilterContributor {
+
+ @Override
+ public void contribute(BooleanFilter booleanFilter, ModelSearchSettings modelSearchSettings, SearchContext searchContext) {
+
+ // TODO: Adjust as necessary to filter results that should not normally be included as search results.
+
+ // exclude non-approved entities from the search results.
+ addWorkflowStatusFilter(booleanFilter, modelSearchSettings, searchContext);
+ }
+
+ protected void addWorkflowStatusFilter(BooleanFilter booleanFilter, ModelSearchSettings modelSearchSettings, SearchContext searchContext) {
+ workflowStatusModelPreFilterContributor.contribute(booleanFilter, modelSearchSettings, searchContext);
+ }
+
+ @Reference(target = "(model.pre.filter.contributor.id=WorkflowStatus)")
+ protected ModelPreFilterContributor workflowStatusModelPreFilterContributor;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelResourcePermissionRegistrar.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelResourcePermissionRegistrar.java.ftl
new file mode 100644
index 0000000..8ba96a7
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelResourcePermissionRegistrar.java.ftl
@@ -0,0 +1,91 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/security/permission/resource/${capFirstModel}ModelResourcePermissionRegistrar.java">
+/* */
+package ${packageName}.internal.security.permission.resource;
+
+import com.liferay.exportimport.kernel.staging.permission.StagingPermission;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermissionFactory;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.StagedModelPermissionLogic;
+import com.liferay.portal.kernel.security.permission.resource.WorkflowedModelPermissionLogic;
+import com.liferay.portal.kernel.service.GroupLocalService;
+import com.liferay.portal.kernel.util.HashMapDictionary;
+import com.liferay.portal.kernel.workflow.permission.WorkflowPermission;
+import ${packageName}.constants.${capFirstModel}Constants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import java.util.Dictionary;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model Resource Permission Registrar
+ *
+ * @author ${damascus_author}
+ *
+ */
+@Component(immediate = true, service = {})
+public class ${capFirstModel}ModelResourcePermissionRegistrar {
+
+ @Activate
+ public void activate(BundleContext bundleContext) {
+ Dictionary properties = new HashMapDictionary<>();
+
+ properties.put("model.class.name", ${capFirstModel}.class.getName());
+
+ _serviceRegistration = bundleContext.registerService(
+ ModelResourcePermission.class,
+ ModelResourcePermissionFactory.create(
+ ${capFirstModel}.class, ${capFirstModel}::getPrimaryKey,
+ _${lowercaseModel}LocalService::get${capFirstModel}, _portletResourcePermission,
+ (modelResourcePermission, consumer) -> {
+ consumer.accept(
+ new StagedModelPermissionLogic<>(
+ _stagingPermission, ${capFirstModel}PortletKeys.${uppercaseModel},
+ ${capFirstModel}::getPrimaryKey));
+
+ consumer.accept(
+ new WorkflowedModelPermissionLogic<>(
+ _workflowPermission, modelResourcePermission,
+ _groupLocalService, ${capFirstModel}::getPrimaryKey));
+ }),
+ properties);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ _serviceRegistration.unregister();
+ }
+
+ @Reference
+ private GroupLocalService _groupLocalService;
+
+ @Reference(
+ target = "(resource.name=" + ${capFirstModel}Constants.RESOURCE_NAME + ")"
+ )
+ private PortletResourcePermission _portletResourcePermission;
+
+ @Reference
+ private ${capFirstModel}LocalService _${lowercaseModel}LocalService;
+
+ @SuppressWarnings("rawtypes")
+ private ServiceRegistration _serviceRegistration;
+
+ @Reference
+ private StagingPermission _stagingPermission;
+
+ @Reference
+ private WorkflowPermission _workflowPermission;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl
new file mode 100644
index 0000000..d60444e
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl
@@ -0,0 +1,58 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/result/contributor/${capFirstModel}ModelSummaryContributor.java">
+/* */
+package ${packageName}.internal.search.result.contributor;
+
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.Summary;
+import com.liferay.portal.kernel.util.LocaleUtil;
+import com.liferay.portal.kernel.util.LocalizationUtil;
+import com.liferay.portal.search.spi.model.result.contributor.ModelSummaryContributor;
+import org.osgi.service.component.annotations.Component;
+
+import java.util.Locale;
+
+/**
+ * ${capFirstModel} Model Summary Contributor
+ *
+ * Manipulates the Summary object for each entity search result.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelSummaryContributor.class
+)
+public class ${capFirstModel}ModelSummaryContributor implements ModelSummaryContributor {
+
+ @Override
+ public Summary getSummary(Document document, Locale locale, String snippet) {
+ String languageId = LocaleUtil.toLanguageId(locale);
+
+ // TODO: Modify as necessary to use the corrected fields for the summary
+
+ return _createSummary(document,
+ LocalizationUtil.getLocalizedName(Field.CONTENT, languageId),
+ LocalizationUtil.getLocalizedName(Field.TITLE, languageId));
+ }
+
+ protected Summary _createSummary(Document document, String contentField, String titleField) {
+
+ String prefix = Field.SNIPPET + StringPool.UNDERLINE;
+
+ String title = document.get(prefix + titleField, titleField);
+ String content = document.get(prefix + contentField, contentField);
+
+ Summary summary = new Summary(title,content);
+
+ summary.setMaxContentLength(200);
+
+ return summary;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl
new file mode 100644
index 0000000..323c014
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl
@@ -0,0 +1,53 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/result/contributor/${capFirstModel}ModelVisibilityContributor.java">
+/* */
+package ${packageName}.internal.search.result.contributor;
+
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.search.spi.model.result.contributor.ModelVisibilityContributor;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model Visibility Contributor
+ *
+ * Controls the visibility of entities that can be attached to other asset types in the search context.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelVisibilityContributor.class
+)
+public class ${capFirstModel}ModelVisibilityContributor implements ModelVisibilityContributor {
+
+ @Override
+ public boolean isVisible(long classPK, int status) {
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.fetch${capFirstModel}(classPK);
+
+ if (entry == null) {
+ return false;
+ }
+
+ return isVisible(entry.getStatus(), status);
+ }
+
+ protected boolean isVisible(int entryStatus, int queryStatus) {
+ if (((queryStatus != WorkflowConstants.STATUS_ANY) && (entryStatus == queryStatus)) || (entryStatus != WorkflowConstants.STATUS_IN_TRASH)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Reference
+ protected ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_PortletResourcePermissionRegistrar.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_PortletResourcePermissionRegistrar.java.ftl
new file mode 100644
index 0000000..3e469dc
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_PortletResourcePermissionRegistrar.java.ftl
@@ -0,0 +1,60 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/security/permission/resource/${capFirstModel}PortletResourcePermissionRegistrar.java">
+/* */
+
+package ${packageName}.internal.security.permission.resource;
+
+import com.liferay.exportimport.kernel.staging.permission.StagingPermission;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermissionFactory;
+import com.liferay.portal.kernel.security.permission.resource.StagedPortletPermissionLogic;
+import com.liferay.portal.kernel.util.HashMapDictionary;
+import ${packageName}.constants.${capFirstModel}Constants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import java.util.Dictionary;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Portlet Resource Permission Regsitra
+ *
+ * @author ${damascus_author}
+ */
+@Component(immediate = true, service = {})
+public class ${capFirstModel}PortletResourcePermissionRegistrar {
+
+ @Activate
+ public void activate(BundleContext bundleContext) {
+ Dictionary properties = new HashMapDictionary<>();
+
+ properties.put("resource.name", ${capFirstModel}Constants.RESOURCE_NAME);
+
+ _serviceRegistration = bundleContext.registerService(
+ PortletResourcePermission.class,
+ PortletResourcePermissionFactory.create(
+ ${capFirstModel}Constants.RESOURCE_NAME,
+ new StagedPortletPermissionLogic(
+ _stagingPermission, ${capFirstModel}PortletKeys.${uppercaseModel})),
+ properties);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ _serviceRegistration.unregister();
+ }
+
+ private ServiceRegistration _serviceRegistration;
+
+ @Reference
+ private StagingPermission _stagingPermission;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_SearchRegistrar.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_SearchRegistrar.java.ftl
new file mode 100644
index 0000000..6b87de4
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_SearchRegistrar.java.ftl
@@ -0,0 +1,70 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/${capFirstModel}SearchRegistrar.java">
+/* */
+package ${packageName}.internal.search;
+
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.search.spi.model.index.contributor.ModelIndexerWriterContributor;
+import com.liferay.portal.search.spi.model.registrar.ModelSearchRegistrarHelper;
+import com.liferay.portal.search.spi.model.result.contributor.ModelSummaryContributor;
+import com.liferay.portal.search.spi.model.result.contributor.ModelVisibilityContributor;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Search Registrar
+ *
+ * Registers the ${capFirstModel} entity with Liferay's search framework.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ service = {}
+)
+public class ${capFirstModel}SearchRegistrar {
+
+ @Activate
+ protected void activate(BundleContext bundleContext) {
+ _serviceRegistration = modelSearchRegistrarHelper.register(
+ ${capFirstModel}.class, bundleContext,
+ modelSearchDefinition -> {
+ modelSearchDefinition.setDefaultSelectedFieldNames(
+ Field.ASSET_TAG_NAMES, Field.COMPANY_ID, Field.CONTENT,
+ Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID,
+ Field.MODIFIED_DATE, Field.SCOPE_GROUP_ID, Field.TITLE, Field.UID);
+ modelSearchDefinition.setDefaultSelectedLocalizedFieldNames(Field.TITLE, Field.CONTENT);
+
+ modelSearchDefinition.setModelIndexWriteContributor(modelIndexWriterContributor);
+ modelSearchDefinition.setModelSummaryContributor(modelSummaryContributor);
+ modelSearchDefinition.setModelVisibilityContributor(modelVisibilityContributor);
+ });
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ _serviceRegistration.unregister();
+ }
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelIndexerWriterContributor<${capFirstModel}> modelIndexWriterContributor;
+
+ @Reference
+ protected ModelSearchRegistrarHelper modelSearchRegistrarHelper;
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelSummaryContributor modelSummaryContributor;
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelVisibilityContributor modelVisibilityContributor;
+
+ private ServiceRegistration> _serviceRegistration;
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_Searcher.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_Searcher.java.ftl
new file mode 100644
index 0000000..917b60e
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_Searcher.java.ftl
@@ -0,0 +1,48 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/${capFirstModel}Searcher.java">
+/* */
+package ${packageName}.internal.search;
+
+import com.liferay.portal.kernel.search.BaseSearcher;
+import com.liferay.portal.kernel.search.Field;
+import org.osgi.service.component.annotations.Component;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Searcher
+ *
+ * Sets up the searcher instance for ${capFirstModel}.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = BaseSearcher.class
+)
+public class ${capFirstModel}Searcher extends BaseSearcher {
+
+ public static final String CLASS_NAME = ${capFirstModel}.class.getName();
+
+ public ${capFirstModel}Searcher() {
+
+ // TODO: Adjust the fields as necessary.
+ setDefaultSelectedFieldNames(
+ Field.ASSET_TAG_NAMES, Field.COMPANY_ID, Field.CONTENT,
+ Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID,
+ Field.MODIFIED_DATE, Field.SCOPE_GROUP_ID, Field.TITLE, Field.UID);
+ setFilterSearch(true);
+ setPermissionAware(true);
+
+ // TODO Adjust localized fields as well
+ setDefaultSelectedLocalizedFieldNames(Field.TITLE, Field.CONTENT);
+ }
+
+ @Override
+ public String getClassName() {
+ return CLASS_NAME;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_ServiceImpl.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ServiceImpl.java.ftl
new file mode 100644
index 0000000..4a89566
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_ServiceImpl.java.ftl
@@ -0,0 +1,238 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/impl/${capFirstModel}ServiceImpl.java">
+/* */
+
+
+package ${packageName}.service.impl;
+
+import com.liferay.portal.aop.AopService;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.security.auth.PrincipalException;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermissionFactory;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.service.ServiceContextFactory;
+import ${packageName}.constants.${capFirstModel}Constants;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.base.${capFirstModel}ServiceBaseImpl;
+
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * The implementation of the ${capFirstModel} remote service.
+ *
+ *
+ * All custom service methods should be put in this class. Whenever methods are added, rerun ServiceBuilder to copy their definitions into the ${packageName}.service.${capFirstModel}Service
interface.
+ *
+ *
+ * This is a remote service. Methods of this service are expected to have security checks based on the propagated JAAS credentials because this service can be accessed remotely.
+ *
+ *
+ * @author ${damascus_author}
+ * @see ${capFirstModel}ServiceBaseImpl
+ */
+@Component(
+ property = {
+ "json.web.service.context.name=${lowercaseModel}",
+ "json.web.service.context.path=${capFirstModel}"
+ },
+ service = AopService.class
+)
+public class ${capFirstModel}ServiceImpl extends ${capFirstModel}ServiceBaseImpl {
+
+ /**
+ * Add Entry
+ *
+ * @param orgEntry ${capFirstModel} model
+ * @param serviceContext ServiceContext
+ * @exception PortalException
+ * @exception ${capFirstModel}ValidateException
+ * @return created ${capFirstModel} model.
+ */
+ @Override
+ public ${capFirstModel} addEntry(${capFirstModel} orgEntry, ServiceContext serviceContext)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ _portletResourcePermission.check(
+ getPermissionChecker(), serviceContext.getScopeGroupId(),
+ ActionKeys.ADD_ENTRY);
+
+ return ${uncapFirstModel}LocalService.addEntry(orgEntry, serviceContext);
+ }
+
+ /**
+ * Delete Entry
+ *
+ * @param primaryKey
+ * @return ${capFirstModel}
+ * @throws PortalException
+ */
+ public void deleteEntry(long primaryKey) throws PortalException {
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), primaryKey, ActionKeys.DELETE);
+
+ ${uncapFirstModel}LocalService.deleteEntry(primaryKey);
+ }
+
+ /**
+ * Populate Model with values from a form
+ *
+ * @param primaryKey primary key
+ * @param request PortletRequest
+ * @return ${capFirstModel} Object
+ * @throws PortletException
+ * @throws PortalException
+ */
+ public ${capFirstModel} getInitialized${capFirstModel}(
+ long primaryKey, PortletRequest request)
+ throws PortalException, PortletException {
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ request);
+
+ _portletResourcePermission.check(
+ getPermissionChecker(), serviceContext.getScopeGroupId(),
+ ActionKeys.ADD_ENTRY);
+
+ return ${uncapFirstModel}LocalService.getNewObject(primaryKey);
+ }
+
+ /**
+ * Get Record
+ *
+ * @param primaryKey Primary key
+ * @return ServiceContext serviceContext
+ * @throws PrincipalException
+ * @throws PortletException
+ */
+ public ${capFirstModel} getNewObject(long primaryKey, ServiceContext serviceContext)
+ throws PrincipalException {
+
+ primaryKey = (primaryKey <= 0) ? 0 :
+ counterLocalService.increment(${capFirstModel}.class.getName());
+
+ _portletResourcePermission.check(
+ getPermissionChecker(), serviceContext.getScopeGroupId(),
+ ActionKeys.UPDATE);
+
+ return ${uncapFirstModel}LocalService.getNewObject(primaryKey);
+ }
+
+ /**
+ * Returns the ${lowercaseModel} with the primary key.
+ *
+ * @param ${lowercaseModel}Id the primary key of the sample sb
+ * @return the ${lowercaseModel}
+ * @throws PortalException if a ${lowercaseModel} with the primary key could not be found
+ */
+ @Override
+ public ${capFirstModel} get${capFirstModel}(long primaryKey) throws PortalException {
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), primaryKey, ActionKeys.VIEW);
+
+ return ${uncapFirstModel}LocalService.get${capFirstModel}(primaryKey);
+ }
+
+ /**
+ * Returns the ${lowercaseModel}
+ *
+ * @param groupId
+ * @param urlTitle
+ * @return
+ * @throws PortalException
+ */
+ public ${capFirstModel} get${capFirstModel}(long groupId, String urlTitle)
+ throws PortalException {
+
+ ${capFirstModel} entry = ${uncapFirstModel}LocalService.get${capFirstModel}(groupId, urlTitle);
+
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), entry, ActionKeys.VIEW);
+
+ return entry;
+ }
+
+ /**
+ * Populate Model with values from a form
+ *
+ * @param request PortletRequest
+ * @return ${capFirstModel} Object
+ * @throws PortletException
+ * @throws PortalException
+ */
+ public ${capFirstModel} get${capFirstModel}FromRequest(
+ long primaryKey, PortletRequest request)
+ throws PortalException, PortletException {
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ request);
+
+ _portletResourcePermission.check(
+ getPermissionChecker(), serviceContext.getScopeGroupId(),
+ ActionKeys.VIEW);
+
+ return ${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(primaryKey, request);
+ }
+
+ /**
+ * Move an entry to the trush can
+ *
+ * @param userId
+ * @param entryId
+ * @return ${capFirstModel}
+ * @throws PortalException
+ */
+ public ${capFirstModel} moveEntryToTrash(long entryId) throws PortalException {
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), entryId, ActionKeys.DELETE);
+
+ return ${uncapFirstModel}LocalService.moveEntryToTrash(getUserId(), entryId);
+ }
+
+ /**
+ * Edit Entry
+ *
+ * @param orgEntry ${capFirstModel} model
+ * @param serviceContext ServiceContext
+ * @exception PortalException
+ * @exception ${capFirstModel}ValidateException
+ * @return updated ${capFirstModel} model.
+ */
+ @Override
+ public ${capFirstModel} updateEntry(
+ ${capFirstModel} orgEntry, ServiceContext serviceContext)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), orgEntry.getPrimaryKey(),
+ ActionKeys.UPDATE);
+
+ return ${uncapFirstModel}LocalService.updateEntry(orgEntry, serviceContext);
+ }
+
+ private static volatile ModelResourcePermission<${capFirstModel}>
+ _${uncapFirstModel}ModelResourcePermission =
+ ModelResourcePermissionFactory.getInstance(
+ ${capFirstModel}ServiceImpl.class, "_${uncapFirstModel}ModelResourcePermission",
+ ${capFirstModel}.class);
+
+ @Reference(
+ policy = ReferencePolicy.DYNAMIC,
+ policyOption = ReferencePolicyOption.GREEDY,
+ target = "(resource.name=" + ${capFirstModel}Constants.RESOURCE_NAME + ")"
+ )
+ private volatile PortletResourcePermission _portletResourcePermission;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_TrashHandler.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_TrashHandler.java.ftl
new file mode 100644
index 0000000..881a4d7
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_TrashHandler.java.ftl
@@ -0,0 +1,218 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/trash/${capFirstModel}TrashHandler.java">
+/* */
+
+package ${packageName}.internal.trash;
+
+import com.liferay.asset.kernel.AssetRendererFactoryRegistryUtil;
+import com.liferay.asset.kernel.model.AssetRendererFactory;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.LayoutConstants;
+import com.liferay.portal.kernel.model.TrashedModel;
+import com.liferay.portal.kernel.portlet.PortletProvider;
+import com.liferay.portal.kernel.portlet.PortletProviderUtil;
+import com.liferay.portal.kernel.portlet.PortletURLFactoryUtil;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.security.permission.PermissionThreadLocal;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermissionHelper;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.trash.BaseTrashHandler;
+import com.liferay.portal.kernel.trash.TrashHandler;
+import com.liferay.portal.kernel.trash.TrashRenderer;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.Portal;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+import com.liferay.trash.constants.TrashActionKeys;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletURL;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Trash handler
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = TrashHandler.class
+)
+public class ${capFirstModel}TrashHandler extends BaseTrashHandler {
+
+ @Override
+ public void deleteTrashEntry(long classPK) throws PortalException {
+ _${uncapFirstModel}LocalService.deleteEntry(classPK);
+ }
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public String getRestoreContainedModelLink(
+ PortletRequest portletRequest, long classPK)
+ throws PortalException {
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+
+ PortletURL portletURL = getRestoreURL(portletRequest, classPK, false);
+
+ portletURL.setParameter("urlTitle", entry.getUrlTitle());
+ portletURL.setParameter(Constants.CMD, Constants.UPDATE);
+ portletURL.setParameter(
+ "resourcePrimKey", String.valueOf(entry.getPrimaryKey()));
+
+ return portletURL.toString();
+ }
+
+ @Override
+ public String getRestoreContainerModelLink(
+ PortletRequest portletRequest, long classPK)
+ throws PortalException {
+
+ PortletURL portletURL = getRestoreURL(portletRequest, classPK, true);
+
+ return portletURL.toString();
+ }
+
+ @Override
+ public String getRestoreMessage(
+ PortletRequest portletRequest, long classPK) {
+
+ ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ return themeDisplay.translate("${lowercaseModel}");
+ }
+
+ @Override
+ public TrashedModel getTrashedModel(long classPK) {
+ return _${uncapFirstModel}LocalService.fetch${capFirstModel}(classPK);
+ }
+
+ @Override
+ public TrashRenderer getTrashRenderer(long classPK) throws PortalException {
+ AssetRendererFactory<${capFirstModel}> assetRendererFactory =
+ AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClass(
+ ${capFirstModel}.class);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+
+ return (TrashRenderer)assetRendererFactory.getAssetRenderer(
+ entry.getPrimaryKey());
+ }
+
+ @Override
+ public boolean hasTrashPermission(
+ PermissionChecker permissionChecker, long groupId, long classPK,
+ String trashActionId)
+ throws PortalException {
+
+ if (trashActionId.equals(TrashActionKeys.MOVE)) {
+ return ModelResourcePermissionHelper.contains(
+ _${uncapFirstModel}ModelResourcePermission, permissionChecker, groupId,
+ classPK, ActionKeys.ADD_ARTICLE);
+ }
+
+ return super.hasTrashPermission(
+ permissionChecker, groupId, classPK, trashActionId);
+ }
+
+ @Override
+ public boolean isInTrash(long classPK) throws PortalException {
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+
+ return entry.isInTrash();
+ }
+
+ @Override
+ public boolean isRestorable(long classPK) throws PortalException {
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+
+ if (!hasTrashPermission(
+ PermissionThreadLocal.getPermissionChecker(),
+ entry.getGroupId(), classPK, TrashActionKeys.RESTORE)) {
+
+ return false;
+ }
+
+ return !entry.isInTrashContainer();
+ }
+
+ @Override
+ public void restoreTrashEntry(long userId, long classPK)
+ throws PortalException {
+
+ _${uncapFirstModel}LocalService.restoreEntryFromTrash(userId, classPK);
+ }
+
+ /**
+ * Get Restore URL
+ *
+ * @param portletRequest
+ * @param classPK
+ * @param containerModel
+ * @return
+ * @throws PortalException
+ */
+ protected PortletURL getRestoreURL(
+ PortletRequest portletRequest, long classPK, boolean containerModel)
+ throws PortalException {
+
+ PortletURL portletURL = null;
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+ String portletId = PortletProviderUtil.getPortletId(
+ ${capFirstModel}.class.getName(), PortletProvider.Action.VIEW);
+
+ long plid = _portal.getPlidFromPortletId(entry.getGroupId(), portletId);
+
+ if (plid == LayoutConstants.DEFAULT_PLID) {
+ portletId = PortletProviderUtil.getPortletId(
+ ${capFirstModel}.class.getName(), PortletProvider.Action.MANAGE);
+
+ portletURL = _portal.getControlPanelPortletURL(
+ portletRequest, portletId, PortletRequest.RENDER_PHASE);
+ }
+ else {
+ portletURL = PortletURLFactoryUtil.create(
+ portletRequest, portletId, plid, PortletRequest.RENDER_PHASE);
+ }
+
+ if (!containerModel) {
+ portletURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/view");
+ }
+
+ return portletURL;
+ }
+
+ @Override
+ protected boolean hasPermission(
+ PermissionChecker permissionChecker, long classPK, String actionId)
+ throws PortalException {
+
+ return _${uncapFirstModel}ModelResourcePermission.contains(
+ permissionChecker, classPK, actionId);
+ }
+
+ @Reference
+ private Portal _portal;
+
+ @Reference
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+ @Reference(target = "(model.class.name=${packageName}.model.${capFirstModel})")
+ private ModelResourcePermission<${capFirstModel}> _${uncapFirstModel}ModelResourcePermission;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_Validator.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_Validator.java.ftl
new file mode 100644
index 0000000..47287b4
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_Validator.java.ftl
@@ -0,0 +1,139 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/util/${capFirstModel}Validator.java">
+/* */
+
+package ${packageName}.service.util;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.ModelHintsUtil;
+import com.liferay.portal.kernel.repository.model.ModelValidator;
+import com.liferay.portal.kernel.util.Validator;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+
+/* */
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalServiceUtil;
+ #if>
+#list>
+/* */
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * ${capFirstModel} Validator
+ *
+ * @author ${damascus_author}
+ *
+ */
+public class ${capFirstModel}Validator implements ModelValidator<${capFirstModel}> {
+
+ @Override
+ public void validate(${capFirstModel} entry) throws PortalException {
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ // Field ${field.name}
+ validate${field.name?cap_first}(entry.get${field.name?cap_first}());
+
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+ validate${application.asset.assetTitleFieldName?cap_first}(entry.get${application.asset.assetTitleFieldName?cap_first}());
+
+ if (0 < _errors.size()) {
+ throw new ${capFirstModel}ValidateException(_errors);
+ }
+
+ }
+
+ /**
+ * ${application.asset.assetTitleFieldName} field Validation
+ *
+ * @param ${application.asset.assetTitleFieldName}
+ */
+ protected void validate${application.asset.assetTitleFieldName?cap_first}(String ${application.asset.assetTitleFieldName}) {
+ if (Validator.isNotNull(${application.asset.assetTitleFieldName})) {
+ int ${application.asset.assetTitleFieldName}MaxLength = ModelHintsUtil.getMaxLength(
+ ${capFirstModel}.class.getName(), "${application.asset.assetTitleFieldName}");
+
+ if (${application.asset.assetTitleFieldName}.length() > ${application.asset.assetTitleFieldName}MaxLength) {
+ _errors.add("${application.asset.assetTitleFieldName} has more than " + ${application.asset.assetTitleFieldName}MaxLength +
+ " characters");
+ }
+ }
+ }
+
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ /**
+ * ${field.name} field Validation
+ *
+ * @param field ${field.name}
+ */
+ protected void validate${field.name?cap_first}(${templateUtil?api.getTypeParameter(field.type?string)} field) {
+ //TODO : This validation needs to be implemented. Add error message key into _errors when an error occurs.
+ <#if field.primary?? && field.primary == false >
+ <#if field.required == true >
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.RichText" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar"
+ >
+ if (!StringUtils.isNotEmpty(field)) {
+ _errors.add("${lowercaseModel}-${field.name?lower_case}-required");
+ }
+ #if>
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer"
+ >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ if(field <= 0) {
+ _errors.add("${lowercaseModel}-${field.name?lower_case}-required");
+ }
+ #if>
+ #if>
+ #if>
+
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ try {
+ ${capFirstValidationModel}LocalServiceUtil.get${capFirstValidationModel}(field);
+ } catch(PortalException e) {
+ _errors.add("${lowercaseModel}-${field.name?lower_case}-not-found");
+ }
+ #if>
+ #if>
+ }
+
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+
+
+ protected List _errors = new ArrayList<>();
+
+}
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_WorkflowHandler.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_WorkflowHandler.java.ftl
new file mode 100644
index 0000000..bc7f811
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_WorkflowHandler.java.ftl
@@ -0,0 +1,77 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/workflow/${capFirstModel}WorkflowHandler.java">
+/* */
+
+
+package ${packageName}.service.workflow;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.security.permission.ResourceActionsUtil;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.util.GetterUtil;
+import com.liferay.portal.kernel.workflow.BaseWorkflowHandler;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.kernel.workflow.WorkflowHandler;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import java.io.Serializable;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Workflow Handler
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = WorkflowHandler.class
+)
+public class ${capFirstModel}WorkflowHandler extends BaseWorkflowHandler<${capFirstModel}> {
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public String getType(Locale locale) {
+ return ResourceActionsUtil.getModelResource(locale, getClassName());
+ }
+
+ @Override
+ public ${capFirstModel} updateStatus(
+ int status, Map workflowContext)
+ throws PortalException {
+
+ long userId = GetterUtil.getLong(
+ (String)workflowContext.get(WorkflowConstants.CONTEXT_USER_ID));
+ long classPK = GetterUtil.getLong(
+ (String)workflowContext.get(
+ WorkflowConstants.CONTEXT_ENTRY_CLASS_PK));
+
+ ServiceContext serviceContext = (ServiceContext)workflowContext.get(
+ "serviceContext");
+
+ return _${uncapFirstModel}LocalService.updateStatus(
+ userId, classPK, status, serviceContext, workflowContext);
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}LocalService(
+ ${capFirstModel}LocalService ${uncapFirstModel}LocalService) {
+
+ _${uncapFirstModel}LocalService = ${uncapFirstModel}LocalService;
+ }
+
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_WorkflowManager.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_WorkflowManager.java.ftl
new file mode 100644
index 0000000..4174378
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_WorkflowManager.java.ftl
@@ -0,0 +1,368 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/workflow/${capFirstModel}WorkflowManager.java">
+/* */
+
+
+package ${packageName}.service.workflow;
+
+import com.liferay.portal.kernel.dao.orm.QueryUtil;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.User;
+import com.liferay.portal.kernel.model.WorkflowInstanceLink;
+import com.liferay.portal.kernel.service.WorkflowInstanceLinkLocalServiceUtil;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.workflow.WorkflowException;
+import com.liferay.portal.kernel.workflow.WorkflowInstance;
+import com.liferay.portal.kernel.workflow.WorkflowInstanceManagerUtil;
+import com.liferay.portal.kernel.workflow.WorkflowTask;
+import com.liferay.portal.kernel.workflow.WorkflowTaskManagerUtil;
+import ${packageName}.model.${capFirstModel};
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ${capFirstModel} Workflow Utility class
+ *
+ * TODO: This class has been generated as a model specific for convenience of code generation.
+ * Please feel free to refactor this as a common library according to your requirements.
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}WorkflowManager {
+
+ private static final String _className = ${capFirstModel}.class.getName();
+
+ /**
+ * Complete workflow at once
+ *
+ * Without assigning a task to a user, this method automatically assign user and update the workflow.
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param classPK
+ * @param transitionName
+ * @return WorkflowTask object
+ * @throws PortalException
+ */
+ static public WorkflowTask completeWorkflowTaskAtOnce(
+ User user, long scorpGroupId, long classPK, String transitionName)
+ throws PortalException {
+
+ return completeWorkflowTaskAtOnce(
+ user, scorpGroupId, _className, classPK, transitionName);
+ }
+
+ /**
+ * Complete workflow at once
+ *
+ * Without assigning a task to a user, this method automatically assign user and update the workflow.
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @param transitionName
+ * @return WorkflowTask object
+ * @throws PortalException
+ */
+ static public WorkflowTask completeWorkflowTaskAtOnce(
+ User user, long scorpGroupId, String className, long classPK,
+ String transitionName)
+ throws PortalException {
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ // Get workflow instance
+
+ WorkflowTask workflowTask = getWorkflowTask(
+ user, scorpGroupId, className, classPK);
+
+ if (Validator.isNull(workflowTask)) {
+ return null;
+ }
+
+ // Assign a task to the user
+
+ WorkflowTaskManagerUtil.assignWorkflowTaskToUser(
+ user.getCompanyId(), user.getUserId(),
+ workflowTask.getWorkflowTaskId(), user.getUserId(), "", null, null);
+
+ // Complete workflow
+
+ WorkflowTask completeWorkflowTask =
+ WorkflowTaskManagerUtil.completeWorkflowTask(
+ user.getCompanyId(), user.getUserId(),
+ workflowTask.getWorkflowTaskId(), transitionName, "", null);
+
+ return completeWorkflowTask;
+ }
+
+ /**
+ * Check if workflow is enabled.
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param classPK
+ * @return true if workflow is enabled or false
+ * @throws PortalException
+ */
+ static public boolean isWorkflowEnable(
+ User user, long scorpGroupId, long classPK)
+ throws PortalException {
+
+ List transitionNames = getTransitionNames(
+ user, scorpGroupId, null, classPK);
+
+ return (transitionNames.size() == 0) ? false : true;
+ }
+
+ /**
+ * Get Transition names
+ *
+ * A task includes transitions. This method retrieve a list of transition names
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param classPK
+ * @return Escaped transition names
+ * @throws PortalException
+ */
+ static public List getTransitionNames(
+ User user, long scorpGroupId, long classPK)
+ throws PortalException {
+
+ return getTransitionNames(user, scorpGroupId, null, classPK);
+ }
+
+ /**
+ * Get Transition names
+ *
+ * A task includes transitions. This method retrieve a list of transition names
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @return Transition name string List
+ * @throws PortalException
+ */
+ static public List getTransitionNames(
+ User user, long scorpGroupId, String className, long classPK)
+ throws PortalException {
+
+ WorkflowTask workflowTask = getWorkflowTask(
+ user, scorpGroupId, className, classPK);
+
+ if (Validator.isNull(workflowTask)) {
+ return new ArrayList<>();
+ }
+
+ List transitionNames =
+ WorkflowTaskManagerUtil.getNextTransitionNames(
+ user.getCompanyId(), user.getUserId(),
+ workflowTask.getWorkflowTaskId());
+
+ List convertedNames = new ArrayList<>();
+
+ for (String transitionName : transitionNames) {
+ if (_log.isDebugEnabled()) {
+ _log.debug("Transition name : <" + transitionName + ">");
+ }
+
+ convertedNames.add(getTransitionName(transitionName));
+ }
+
+ return convertedNames;
+ }
+
+ /**
+ * Get Transition Message
+ *
+ * @param transitionName
+ * @return Escaped Transition name
+ */
+ static public String getTransitionName(String transitionName) {
+ if (Validator.isNull(transitionName)) {
+ return "proceed";
+ }
+
+ return HtmlUtil.escape(transitionName);
+ }
+
+ /**
+ * Get WorkFlow
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @return WorkflowTask object
+ * @throws WorkflowException
+ */
+ static public WorkflowTask getWorkflowTask(
+ User user, long scorpGroupId, String className, long classPK)
+ throws WorkflowException {
+
+ WorkflowInstance workflowInstance = getWorkflowInstance(
+ user, scorpGroupId, className, classPK);
+ List workflowTasks = getWorkflowTasks(user, className);
+
+ return workflowTasks.stream(
+ ).filter(
+ wft ->
+ wft.getWorkflowInstanceId() ==
+ workflowInstance.getWorkflowInstanceId()
+ ).findFirst(
+ ).orElse(
+ null
+ );
+ }
+
+ /**
+ * Get Workflow Instance
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @return Workflow task instances if those exist
+ * @throws WorkflowException
+ */
+ static public WorkflowInstance getWorkflowInstance(
+ User user, long scorpGroupId, String className, long classPK)
+ throws WorkflowException {
+
+ if (Validator.isNull(classPK)) {
+ _log.debug("classPK is null");
+
+ return null;
+ }
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ WorkflowInstanceLink workflowInstanceLink =
+ WorkflowInstanceLinkLocalServiceUtil.fetchWorkflowInstanceLink(
+ user.getCompanyId(), scorpGroupId, _className, classPK);
+
+ if (Validator.isNull(workflowInstanceLink)) {
+ _log.debug("WorkflowInstanceLink is null");
+
+ return null;
+ }
+
+ WorkflowInstance workflowInstance =
+ WorkflowInstanceManagerUtil.getWorkflowInstance(
+ user.getCompanyId(),
+ workflowInstanceLink.getWorkflowInstanceId());
+
+ if (_log.isDebugEnabled()) {
+ _log.debug(workflowInstance.toString());
+ }
+
+ return workflowInstance;
+ }
+
+ /**
+ * Get WorkflowTasks
+ *
+ * Get unasigned tasks available for the current user.
+ *
+ * @param user
+ * @param className
+ * @return WorkflowTasks of corresponding class
+ * @throws WorkflowException
+ */
+ static public List getWorkflowTasks(
+ User user, String className)
+ throws WorkflowException {
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ List workflowTasks = new ArrayList<>();
+
+ // Fetch workflow tasks has asinged to the user
+
+ List workflowTasksToMyRoles = getWorkflowTasks(
+ user, className, true);
+
+ workflowTasks.addAll(workflowTasksToMyRoles);
+
+ // Fetch workflow tasks has asigned to my roles, but not asigned to the user yet.
+
+ List workflowTasksToMe = getWorkflowTasks(
+ user, className, false);
+
+ workflowTasks.addAll(workflowTasksToMe);
+
+ return workflowTasks;
+ }
+
+ /**
+ * Get WorkflowTasks
+ *
+ * Get unasigned tasks available for the current user.
+ *
+ * @param user
+ * @param className
+ * @param searchByUserRoles
+ * @return WorkflowTasks of corresponding class
+ * @throws WorkflowException
+ */
+ static public List getWorkflowTasks(
+ User user, String className, boolean searchByUserRoles)
+ throws WorkflowException {
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ return WorkflowTaskManagerUtil.search(
+ user.getCompanyId(), // companyId
+ user.getUserId(), // userId
+ "", // keywords
+ new String[]{className}, // assetTypes
+ false, // completed
+ searchByUserRoles, // searchByUserRoles
+ QueryUtil.ALL_POS, // start
+ QueryUtil.ALL_POS, // end
+ null); //OrderByComparator orderByComparator)
+ }
+
+ /**
+ * Is Workflow Exist
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @return true if a workflow exists or false
+ */
+ static public boolean isWorkflowExist(
+ User user, long scorpGroupId, String className, long classPK) {
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ return WorkflowInstanceLinkLocalServiceUtil.hasWorkflowInstanceLink(
+ user.getCompanyId(), scorpGroupId, _className, classPK);
+ }
+
+ private static Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}WorkflowManager.class);
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_bnd.bnd.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_bnd.bnd.ftl
new file mode 100644
index 0000000..85a0f7f
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_bnd.bnd.ftl
@@ -0,0 +1,18 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/bnd.bnd">
+# #
+Bundle-Name: ${dashcaseProjectName}-service
+Bundle-SymbolicName: ${packageName}.service
+Bundle-Version: 1.0.0
+Import-Package:\
+ !com.google.*,\
+ !org.checkerframework.* ,\
+ *
+Liferay-Require-SchemaVersion: 1.0.0
+Liferay-Service: true
+-dsannotations-options: inherit
+-includeresource:\
+ @guava-*.jar,\
+ @commons-lang3-*.jar
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_build.gradle.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_build.gradle.ftl
new file mode 100644
index 0000000..37b9fab
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_build.gradle.ftl
@@ -0,0 +1,75 @@
+//
+// //
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/build.gradle">
+// //
+apply plugin: 'eclipse'
+apply plugin: 'groovy'
+apply plugin: 'idea'
+apply plugin: 'java'
+
+
+//Need for Windows
+def defaultEncoding = 'UTF-8'
+
+repositories {
+ mavenCentral()
+ jcenter()
+ maven {
+ url "http://repository.jboss.org/nexus/content/groups/public-jboss" // JBoss
+ url "http://repository.apache.org/content/groups/public" // Apache
+ url "http://repository.springsource.com/maven/bundles/release" // SpringSource
+ url "http://repository.codehaus.org" // Codehaus
+ url "http://download.java.net/maven/2" // Java.NET
+ url "http://download.java.net/maven/glassfish" // Glassfish
+ url "http://m2repo.spockframework.org/snapshots" // Spock Snapshot
+ url "http://repository.sonatype.org/content/groups/public"
+ url "https://mvnrepository.com/artifact/com.sun/tools"
+ }
+}
+
+dependencies {
+ compile group: "com.google.guava", name: "guava"<#if useTP?? && false == useTP>, version: "28.1-jre"#if>, transitive: false
+ compileOnly group: "com.liferay", name: "com.liferay.friendly.url.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.function"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.lang"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.string"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.sql.dsl.api"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"<#if useTP?? && false == useTP>, version: "2.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.search.api"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.search.spi"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.trash.api"<#if useTP?? && false == useTP>, version: "3.2.+"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "7.2.0"#if>
+ compileOnly group: "commons-io", name: "commons-io"<#if useTP?? && false == useTP>, version: "2.6"#if>
+ compile group: "commons-validator", name: "commons-validator"<#if useTP?? && false == useTP>, version: "1.6"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet.jsp", name: "jsp-api"<#if useTP?? && false == useTP>, version: "2.1"#if>
+ compile group: "org.apache.commons", name: "commons-lang3", version: "3.9"
+ compile group: "org.apache.felix", name: "org.apache.felix.http.servlet-api", version: "1.1.2"
+ compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"<#if useTP?? && false == useTP>, version: "1.1.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
+ compile group: "org.osgi", name: "osgi.core", version: "6.0.0"
+ compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.26'
+ compile project(":${dashcaseProjectName}-api")
+}
+
+buildscript {
+ dependencies {
+ classpath group: "com.liferay", name: "com.liferay.gradle.plugins.service.builder", version: "4.0.+"
+ }
+
+ repositories {
+ maven {
+ url "https://repository-cdn.liferay.com/nexus/content/groups/public"
+ }
+ }
+}
+
+apply plugin: "com.liferay.portal.tools.service.builder"
+
+buildService {
+ apiDir = "../${dashcaseProjectName}-api/src/main/java"
+}
+
+group = "${packageName}"
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_default.xml.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_default.xml.ftl
new file mode 100644
index 0000000..f860069
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_default.xml.ftl
@@ -0,0 +1,77 @@
+
+
+
+
+ <#include "./valuables.ftl">
+ <#assign createPath = "${serviceModulePath}/src/main/resources/META-INF/resource-actions/default.xml">
+
+
+
+ ${packageName}
+
+ ${packageSnake}_web_${capFirstModel}Portlet
+ ${packageSnake}_web_${capFirstModel}AdminPortlet
+
+ true
+ 1
+
+
+ ACCESS_IN_CONTROL_PANEL
+ UPDATE
+ VIEW
+ ADD_ENTRY
+ PERMISSIONS
+
+
+ UPDATE
+ VIEW
+ ADD_ENTRY
+
+
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ UPDATE
+ ADD_ENTRY
+ PERMISSIONS
+
+
+
+
+ <#list damascus.applications as app >
+ <#assign capFirstModel = "${app.model?cap_first}">
+
+ ${packageName}.model.${capFirstModel}
+
+ ${packageSnake}_web_${capFirstModel}Portlet
+ ${packageSnake}_web_${capFirstModel}AdminPortlet
+
+ 2
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_ENTRY
+ DELETE
+ PERMISSIONS
+ UPDATE
+ VIEW
+
+
+ VIEW
+
+
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_ENTRY
+ DELETE
+ PERMISSIONS
+ UPDATE
+
+
+
+ #list>
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_portlet-model-hints.xml.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_portlet-model-hints.xml.ftl
new file mode 100644
index 0000000..9c3f0c9
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_portlet-model-hints.xml.ftl
@@ -0,0 +1,95 @@
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/resources/META-INF/portlet-model-hints.xml">
+
+
+
+<#list damascus.applications as application>
+
+
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Long" >
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" >
+
+ ${field.length}
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Date" >
+
+ false
+ 80
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" >
+
+ true
+ 80
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" >
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+
+ 60
+ 512
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Double" >
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Integer" >
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+
+
+ 4001
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Text" >
+
+
+ 4001
+
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+ 200
+ 255
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+
+ 4001
+
+ #if>
+
+
+
+
+
+
+
+
+
+
+
+
+
+#list>
+
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXSVC_portlet.properties.ftl b/src/main/resources/templates/7.3/Portlet_XXXXSVC_portlet.properties.ftl
new file mode 100644
index 0000000..5f0f1ad
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXSVC_portlet.properties.ftl
@@ -0,0 +1,12 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/resources/portlet.properties">
+# #
+
+include-and-override=portlet-ext.properties
+
+# Input a list of comma delimited resource action configurations that will be
+# read from the class path.
+#
+resource.actions.configs=META-INF/resource-actions/default.xml
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
new file mode 100644
index 0000000..8a70af8
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
@@ -0,0 +1,291 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}AdminCrudMVCActionCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.asset.display.page.portlet.AssetDisplayPageEntryFormProcessor;
+import com.liferay.petra.reflect.ReflectionUtil;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.TrashedModel;
+import com.liferay.portal.kernel.portlet.bridges.mvc.BaseMVCActionCommand;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCActionCommand;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.service.ServiceContextFactory;
+import com.liferay.portal.kernel.servlet.SessionErrors;
+import com.liferay.portal.kernel.servlet.SessionMessages;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.PortalUtil;
+import com.liferay.portal.kernel.util.StringUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+import ${packageName}.service.${capFirstModel}Service;
+import com.liferay.trash.service.TrashEntryService;
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "mvc.command.name=/${lowercaseModel}/crud"
+ },
+ service = MVCActionCommand.class
+)
+public class ${capFirstModel}AdminCrudMVCActionCommand extends BaseMVCActionCommand {
+
+ /**
+ * Add Entry
+ *
+ * @param request
+ * @param response
+ * @throws ${capFirstModel}ValidateException, Exception
+ */
+ public void addEntry(ActionRequest request, ActionResponse response)
+ throws Exception, ${capFirstModel}ValidateException {
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(
+ primaryKey, request);
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ ${capFirstModel}.class.getName(), request);
+
+ // Add entry
+
+ _${uncapFirstModel}Service.addEntry(entry, serviceContext);
+
+ _assetDisplayPageEntryFormProcessor.process(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), request);
+
+ SessionMessages.add(request, "${lowercaseModel}AddedSuccessfully");
+ }
+
+ /**
+ * Delte Entry
+ *
+ * @param request
+ * @param response
+ * @param moveToTrash true to move to trush.
+ * @throws PortalException
+ * @throws Exception
+ */
+ public void deleteEntry(
+ ActionRequest request, ActionResponse response, boolean moveToTrash)
+ throws PortalException {
+
+ long[] deleteEntryIds = null;
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ long entryId = ParamUtil.getLong(request, "resourcePrimKey", 0L);
+
+ if (entryId > 0) {
+ deleteEntryIds = new long[] {entryId};
+ }
+ else {
+ deleteEntryIds = StringUtil.split(
+ ParamUtil.getString(request, "deleteEntryIds"), 0L);
+ }
+
+ List trashedModels = new ArrayList<>();
+
+ for (long deleteEntryId : deleteEntryIds) {
+ try {
+ if (moveToTrash) {
+ ${capFirstModel} entry = _${uncapFirstModel}Service.moveEntryToTrash(
+ deleteEntryId);
+
+ trashedModels.add(entry);
+ }
+ else {
+ _${uncapFirstModel}Service.deleteEntry(deleteEntryId);
+ }
+ }
+ catch (PortalException pe) {
+ ReflectionUtil.throwException(pe);
+ }
+ }
+
+ if (moveToTrash && !trashedModels.isEmpty()) {
+ Map data = new HashMap<>();
+
+ data.put("trashedModels", trashedModels);
+
+ addDeleteSuccessData(request, data);
+ }
+ }
+
+ /**
+ * Restore Entries
+ *
+ * @param actionRequest
+ * @throws Exception
+ */
+ public void restoreTrashEntries(ActionRequest actionRequest)
+ throws Exception {
+
+ long[] restoreTrashEntryIds = StringUtil.split(
+ ParamUtil.getString(actionRequest, "restoreTrashEntryIds"), 0L);
+
+ for (long restoreTrashEntryId : restoreTrashEntryIds) {
+ _trashEntryService.restoreEntry(restoreTrashEntryId);
+ }
+ }
+
+ /**
+ * Update Entry
+ *
+ * @param request
+ * @param response
+ * @throws Exception
+ */
+ public void updateEntry(ActionRequest request, ActionResponse response)
+ throws Exception {
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(
+ primaryKey, request);
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ ${capFirstModel}.class.getName(), request);
+
+ //Update entry
+ _${uncapFirstModel}Service.updateEntry(entry, serviceContext);
+
+ _assetDisplayPageEntryFormProcessor.process(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), request);
+
+ SessionMessages.add(request, "${lowercaseModel}UpdatedSuccessfully");
+ }
+
+ /**
+ * Single Delete
+ *
+ * @param entry
+ * @param moveToTrash
+ * @param trashedModels
+ */
+ protected void _deleteEntry(
+ ${capFirstModel} entry, boolean moveToTrash, List trashedModels) {
+
+ try {
+ if (moveToTrash) {
+ trashedModels.add(
+ _${uncapFirstModel}Service.moveEntryToTrash(entry.getPrimaryKey()));
+ }
+ else {
+ _${uncapFirstModel}Service.deleteEntry(entry.getPrimaryKey());
+ }
+ }
+ catch (PortalException pe) {
+ ReflectionUtil.throwException(pe);
+ }
+ }
+
+ @Override
+ protected void doProcessAction(
+ ActionRequest request, ActionResponse response)
+ throws IOException {
+
+ try {
+
+ // Fetch command
+
+ String cmd = ParamUtil.getString(request, Constants.CMD);
+
+ if (cmd.equals(Constants.ADD)) {
+ addEntry(request, response);
+ }
+ else if (cmd.equals(Constants.UPDATE)) {
+ updateEntry(request, response);
+ }
+ else if (cmd.equals(Constants.DELETE)) {
+ deleteEntry(request, response, false);
+ }
+ else if (cmd.equals(Constants.MOVE_TO_TRASH)) {
+ deleteEntry(request, response, true);
+ }
+ else if (cmd.equals(Constants.RESTORE)) {
+ restoreTrashEntries(request);
+ }
+ }
+ catch (${capFirstModel}ValidateException ssbve) {
+ for (String error : ssbve.getErrors()) {
+ SessionErrors.add(request, error);
+ }
+
+ PortalUtil.copyRequestParameters(request, response);
+ response.setRenderParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/crud");
+ hideDefaultSuccessMessage(request);
+ }
+ catch (Exception t) {
+ _log.error(t.getLocalizedMessage(), t);
+ SessionErrors.add(request, PortalException.class);
+ hideDefaultSuccessMessage(request);
+ }
+
+ //For access from Asset Publisher
+ String redirect = ParamUtil.getString(request, "redirect");
+ Boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+
+ if (Validator.isNotNull(redirect) && (true == fromAsset)) {
+ sendRedirect(request, response, redirect);
+ }
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}LocalService(
+ ${capFirstModel}LocalService ${uncapFirstModel}LocalService) {
+
+ _${uncapFirstModel}LocalService = ${uncapFirstModel}LocalService;
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}Service(${capFirstModel}Service ${uncapFirstModel}Service) {
+ _${uncapFirstModel}Service = ${uncapFirstModel}Service;
+ }
+
+ private static Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}AdminCrudMVCActionCommand.class);
+
+ @Reference
+ private AssetDisplayPageEntryFormProcessor
+ _assetDisplayPageEntryFormProcessor;
+
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+ private ${capFirstModel}Service _${uncapFirstModel}Service;
+
+ @Reference
+ private TrashEntryService _trashEntryService;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCRenderCommand.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCRenderCommand.java.ftl
new file mode 100644
index 0000000..ee4855f
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCRenderCommand.java.ftl
@@ -0,0 +1,247 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}AdminCrudMVCRenderCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCRenderCommand;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}Service;
+import ${packageName}.web.constants.${capFirstModel}WebKeys;
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}EntryPermission;
+import ${packageName}.web.upload.${capFirstModel}ItemSelectorHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalService;
+import ${packageName}.web.constants.${capFirstValidationModel}WebKeys;
+import ${packageName}.web.util.${capFirstValidationModel}ViewHelper;
+ #if>
+#list>
+// //
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} CRUD Render
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "mvc.command.name=/${lowercaseModel}/crud"
+ },
+ service = MVCRenderCommand.class
+)
+public class ${capFirstModel}AdminCrudMVCRenderCommand implements MVCRenderCommand {
+
+ /**
+ * Edit Page JSP file
+ */
+ public String getEditPageJSP() {
+ return ${capFirstModel}WebKeys.ADMIN_EDIT_JSP;
+ }
+
+ /**
+ * View Page JSP file
+ */
+ public String getViewPageJSP() {
+ return ${capFirstModel}WebKeys.ADMIN_VIEW_JSP;
+ }
+
+ /**
+ * View Record JSP file
+ */
+ public String getViewRecordPageJSP() {
+ return ${capFirstModel}WebKeys.ADMIN_VIEW_RECORD_JSP;
+ }
+
+ @Override
+ public String render(RenderRequest request, RenderResponse response)
+ throws PortletException {
+
+ String renderJSP = getViewPageJSP();
+
+ // Fetch command
+
+ String cmd = ParamUtil.getString(request, Constants.CMD);
+
+ // Fetch primary key
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ try {
+ if (cmd.equalsIgnoreCase(Constants.UPDATE)) {
+ renderJSP = update(request, themeDisplay, primaryKey);
+ }
+ else if (cmd.equalsIgnoreCase(Constants.VIEW)) {
+ renderJSP = view(request, themeDisplay, primaryKey);
+ }
+ else {
+ renderJSP = add(request, themeDisplay, primaryKey);
+ }
+ }
+ catch (PortalException pe) {
+ throw new PortletException(pe.getMessage());
+ }
+
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+
+ request.setAttribute(${capFirstValidationModel}WebKeys.${uppercaseValidationModel}_VIEW_HELPER, _${uncapFirstValidationModel}ViewHelper);
+ request.setAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE, _${uncapFirstValidationModel}LocalService);
+ #if>
+#list>
+// //
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_ITEM_SELECTOR_HELPER,
+ _${uncapFirstModel}ItemSelectorHelper);
+
+ return renderJSP;
+ }
+
+ /**
+ * Add record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return JSP file path
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ * @throws PortletException
+ */
+ protected String add(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, PortletException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = null;
+
+ if (Validator.isNull(request.getParameter("addErrors"))) {
+ record = _${uncapFirstModel}Service.getInitialized${capFirstModel}(
+ primaryKey, request);
+ }
+ else {
+ record = _${uncapFirstModel}Service.get${capFirstModel}FromRequest(
+ primaryKey, request);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getEditPageJSP();
+ }
+
+ /**
+ * Update record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return JSP file path to open
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ */
+ protected String update(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = _${uncapFirstModel}Service.get${capFirstModel}(primaryKey);
+
+ if (!${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), record,
+ ActionKeys.UPDATE)) {
+
+ List error = new ArrayList<>();
+ error.add("permission-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getEditPageJSP();
+ }
+
+ /**
+ * View record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ */
+ protected String view(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = _${uncapFirstModel}Service.get${capFirstModel}(primaryKey);
+
+ if (!${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), record, ActionKeys.VIEW)) {
+
+ List error = new ArrayList<>();
+ error.add("permission-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getViewRecordPageJSP();
+ }
+ @Reference
+ private ${capFirstModel}Service _${uncapFirstModel}Service;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+
+ @Reference
+ private ${capFirstValidationModel}ViewHelper _${uncapFirstValidationModel}ViewHelper;
+
+ @Reference
+ private ${capFirstValidationModel}LocalService _${uncapFirstValidationModel}LocalService;
+ #if>
+#list>
+// //
+
+ @Reference
+ private ${capFirstModel}ItemSelectorHelper _${uncapFirstModel}ItemSelectorHelper;
+
+}
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminPortlet.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminPortlet.java.ftl
new file mode 100644
index 0000000..95a0232
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminPortlet.java.ftl
@@ -0,0 +1,78 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}AdminPortlet.java">
+<#assign skipTemplate = !generateWeb>
+// //
+
+package ${packageName}.web.portlet;
+
+import com.liferay.asset.constants.AssetWebKeys;
+import com.liferay.asset.util.AssetHelper;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import com.liferay.trash.TrashHelper;
+import com.liferay.trash.util.TrashWebKeys;
+
+import java.io.IOException;
+
+import javax.portlet.Portlet;
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Admin Portlet
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "com.liferay.portlet.css-class-wrapper=portlet-${lowercaseModel}",
+ "com.liferay.portlet.display-category=category.hidden",
+ "com.liferay.portlet.header-portlet-css=/${snakecaseModel}_admin/css/main.css",
+ "com.liferay.portlet.preferences-unique-per-layout=true",
+ "com.liferay.portlet.preferences-owned-by-group=true",
+ "com.liferay.portlet.private-request-attributes=false",
+ "com.liferay.portlet.private-session-attributes=false",
+ "com.liferay.portlet.render-weight=50",
+ "com.liferay.portlet.scopeable=true",
+ "com.liferay.portlet.struts-path=${lowercaseModel}_admin",
+ "com.liferay.portlet.use-default-template=true",
+ "javax.portlet.display-name=${capFirstModel} Admin",
+ "javax.portlet.init-param.mvc-command-names-default-views=/${lowercaseModel}/view",
+ "javax.portlet.init-param.portlet-title-based-navigation=true",
+ "javax.portlet.expiration-cache=0",
+ "javax.portlet.init-param.template-path=/META-INF/resources/",
+ "javax.portlet.init-param.view-template=/${snakecaseModel}_admin/view.jsp",
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "javax.portlet.resource-bundle=content.Language",
+ "javax.portlet.security-role-ref=administrator"
+ },
+ service = Portlet.class
+)
+public class ${capFirstModel}AdminPortlet extends MVCPortlet {
+
+ @Override
+ public void render(
+ RenderRequest renderRequest, RenderResponse renderResponse)
+ throws IOException, PortletException {
+
+ renderRequest.setAttribute(AssetWebKeys.ASSET_HELPER, _assetHelper);
+ renderRequest.setAttribute(TrashWebKeys.TRASH_HELPER, _trashHelper);
+
+ super.render(renderRequest, renderResponse);
+ }
+
+ @Reference
+ private AssetHelper _assetHelper;
+
+ @Reference
+ private TrashHelper _trashHelper;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminPortletProvider.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminPortletProvider.java.ftl
new file mode 100644
index 0000000..cb2a95a
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminPortletProvider.java.ftl
@@ -0,0 +1,43 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}AdminPortletProvider.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import com.liferay.portal.kernel.portlet.BasePortletProvider;
+import com.liferay.portal.kernel.portlet.EditPortletProvider;
+import com.liferay.portal.kernel.portlet.ManagePortletProvider;
+import com.liferay.portal.kernel.portlet.ViewPortletProvider;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * ${capFirstModel} Portlet Provider
+ *
+ * This class returns Portlet ID for PortletProviderUtil which is used in TrashHandler.
+ * This Portlet ID is used to create a restore URL.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = {
+ EditPortletProvider.class, ManagePortletProvider.class,
+ ViewPortletProvider.class
+ }
+)
+public class ${capFirstModel}AdminPortletProvider
+ extends BasePortletProvider
+ implements EditPortletProvider, ManagePortletProvider, ViewPortletProvider {
+
+ @Override
+ public String getPortletName() {
+ return ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminViewMVCRenderCommand.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminViewMVCRenderCommand.java.ftl
new file mode 100644
index 0000000..922fbfc
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AdminViewMVCRenderCommand.java.ftl
@@ -0,0 +1,92 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}AdminViewMVCRenderCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCRenderCommand;
+import com.liferay.portal.kernel.util.Portal;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.web.constants.${capFirstModel}WebKeys;
+import ${packageName}.web.internal.display.context.${capFirstModel}DisplayContext;
+import ${packageName}.web.util.${capFirstModel}ViewHelper;
+import com.liferay.trash.TrashHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalService;
+import ${packageName}.web.constants.${capFirstValidationModel}WebKeys;
+ #if>
+#list>
+// //
+
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "mvc.command.name=/", "mvc.command.name=/${lowercaseModel}/view"
+ },
+ service = MVCRenderCommand.class
+)
+public class ${capFirstModel}AdminViewMVCRenderCommand implements MVCRenderCommand {
+
+ @Override
+ public String render(RenderRequest request, RenderResponse response) {
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_DISPLAY_CONTEXT,
+ new ${capFirstModel}DisplayContext(
+ _portal.getLiferayPortletRequest(request),
+ _portal.getLiferayPortletResponse(response), _trashHelper,
+ _${uncapFirstModel}ViewHelper));
+
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_VIEW_HELPER, _${uncapFirstModel}ViewHelper);
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+ request.setAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE, _${uncapFirstValidationModel}LocalService);
+ #if>
+#list>
+// //
+
+ return ${capFirstModel}WebKeys.ADMIN_VIEW_JSP;
+ }
+
+ @Reference
+ private Portal _portal;
+
+ @Reference
+ private ${capFirstModel}ViewHelper _${uncapFirstModel}ViewHelper;
+
+ @Reference
+ private TrashHelper _trashHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ @Reference
+ private ${capFirstValidationModel}LocalService _${uncapFirstValidationModel}LocalService;
+ #if>
+#list>
+// //
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_AssetInfoDisplayContributor.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AssetInfoDisplayContributor.java.ftl
new file mode 100644
index 0000000..83f2c1c
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AssetInfoDisplayContributor.java.ftl
@@ -0,0 +1,44 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/info/display/contributor/${capFirstModel}AssetInfoDisplayContributor.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.info.display.contributor;
+
+import com.liferay.asset.info.display.contributor.BaseAssetInfoDisplayContributor;
+import com.liferay.info.display.contributor.InfoDisplayContributor;
+import ${packageName}.model.${capFirstModel};
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * ${capFirstModel} Asset Info Display Contributor
+ *
+ * @author ${damascus_author}
+ *
+ */
+@Component(immediate = true, service = InfoDisplayContributor.class)
+public class ${capFirstModel}AssetInfoDisplayContributor extends BaseAssetInfoDisplayContributor<${capFirstModel}> {
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public String getInfoURLSeparator() {
+ return "/${lowercaseModel}/";
+ }
+
+ @Override
+ protected Map getClassTypeValues(${capFirstModel} assetEntryObject, Locale locale) {
+ return new HashMap<>();
+ }
+
+}
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_AssetRenderer.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AssetRenderer.java.ftl
new file mode 100644
index 0000000..7950112
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AssetRenderer.java.ftl
@@ -0,0 +1,324 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/asset/${capFirstModel}AssetRenderer.java">
+<#assign skipTemplate = !generateWeb>
+// //
+
+package ${packageName}.web.asset;
+
+import com.liferay.asset.display.page.portlet.AssetDisplayPageFriendlyURLProvider;
+import com.liferay.asset.kernel.model.AssetRendererFactory;
+import com.liferay.asset.kernel.model.BaseJSPAssetRenderer;
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.Group;
+import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
+import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
+import com.liferay.portal.kernel.portlet.PortletLayoutFinder;
+import com.liferay.portal.kernel.portlet.PortletLayoutFinderRegistryUtil;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.trash.TrashRenderer;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.PortalUtil;
+import com.liferay.portal.kernel.util.ResourceBundleLoader;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}EntryPermission;
+
+import java.util.Locale;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletResponse;
+import javax.portlet.PortletURL;
+import javax.portlet.WindowState;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Asset Renderer
+ *
+ * This class is used to display contents in Asset Publisher.
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}AssetRenderer
+ extends BaseJSPAssetRenderer<${capFirstModel}> implements TrashRenderer {
+
+ public ${capFirstModel}AssetRenderer(
+ ${capFirstModel} entry, ResourceBundleLoader resourceBundleLoader) {
+
+ _entry = entry;
+ _resourceBundleLoader = resourceBundleLoader;
+ }
+
+ @Override
+ public ${capFirstModel} getAssetObject() {
+ return _entry;
+ }
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public long getClassPK() {
+ return _entry.getPrimaryKey();
+ }
+
+ @Override
+ public String getDiscussionPath() {
+ return null;
+ }
+
+ @Override
+ public long getGroupId() {
+ return _entry.getGroupId();
+ }
+
+ @Override
+ public String getJspPath(HttpServletRequest request, String template) {
+ if (template.equals(TEMPLATE_ABSTRACT) ||
+ template.equals(TEMPLATE_FULL_CONTENT)) {
+
+ request.setAttribute("${uncapFirstModel}", _entry);
+
+ return "/${snakecaseModel}/asset/" + template + ".jsp";
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getPortletId() {
+ AssetRendererFactory<${capFirstModel}> assetRendererFactory =
+ getAssetRendererFactory();
+
+ return assetRendererFactory.getPortletId();
+ }
+
+ @Override
+ public int getStatus() {
+ return _entry.getStatus();
+ }
+
+ @Override
+ public String getSummary(
+ PortletRequest portletRequest, PortletResponse portletResponse) {
+// //
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+ return _entry.get${application.asset.assetTitleFieldName?cap_first}();
+ <#else>
+ // TODO : This need to be customized
+ return "Asset Renderer need to be implimented";
+ #if>
+// //
+ }
+
+ @Override
+ public String getTitle(Locale locale) {
+// //
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+ return _entry.get${application.asset.assetTitleFieldName?cap_first}();
+ <#else>
+ // TODO : This need to be customized
+ return "Asset Renderer need to be implimented";
+ #if>
+// //
+ }
+
+ @Override
+ public String getType() {
+ return ${capFirstModel}AssetRendererFactory.TYPE;
+ }
+
+ @Override
+ public PortletURL getURLEdit(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse)
+ throws Exception {
+
+ Group group = GroupLocalServiceUtil.fetchGroup(_entry.getGroupId());
+
+ if (group.isCompany()) {
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)liferayPortletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ group = themeDisplay.getScopeGroup();
+ }
+
+ PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
+ liferayPortletRequest, group, ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN, 0,
+ 0, PortletRequest.RENDER_PHASE);
+
+ portletURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/crud");
+ portletURL.setParameter("fromAsset", StringPool.TRUE);
+ portletURL.setParameter(Constants.CMD, Constants.UPDATE);
+ portletURL.setParameter(
+ "resourcePrimKey", String.valueOf(_entry.getPrimaryKey()));
+
+ return portletURL;
+ }
+
+ @Override
+ public String getUrlTitle() {
+ return _entry.getUrlTitle();
+ }
+
+ @Override
+ public String getURLView(
+ LiferayPortletResponse liferayPortletResponse,
+ WindowState windowState)
+ throws Exception {
+
+ AssetRendererFactory<${capFirstModel}> assetRendererFactory =
+ getAssetRendererFactory();
+
+ PortletURL portletURL = assetRendererFactory.getURLView(
+ liferayPortletResponse, windowState);
+
+ portletURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/crud");
+ portletURL.setParameter("fromAsset", StringPool.TRUE);
+ portletURL.setParameter(Constants.CMD, Constants.VIEW);
+ portletURL.setParameter(
+ "resourcePrimKey", String.valueOf(_entry.getPrimaryKey()));
+ portletURL.setWindowState(windowState);
+
+ return portletURL.toString();
+ }
+
+ @Override
+ public String getURLViewInContext(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse,
+ String noSuchEntryRedirect)
+ throws PortalException {
+
+ if (_assetDisplayPageFriendlyURLProvider != null) {
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)liferayPortletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ String friendlyURL =
+ _assetDisplayPageFriendlyURLProvider.getFriendlyURL(
+ getClassName(), getClassPK(), themeDisplay);
+
+ if (Validator.isNotNull(friendlyURL)) {
+ return friendlyURL;
+ }
+ }
+
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)liferayPortletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ if (!_hasViewInContextGroupLayout(_entry.getGroupId(), themeDisplay)) {
+ return null;
+ }
+
+ return getURLViewInContext(
+ liferayPortletRequest, noSuchEntryRedirect, "/${lowercaseModel}/crud",
+ "resourcePrimKey", _entry.getPrimaryKey());
+ }
+
+ @Override
+ public long getUserId() {
+ return _entry.getUserId();
+ }
+
+ @Override
+ public String getUserName() {
+ return _entry.getUserName();
+ }
+
+ @Override
+ public String getUuid() {
+ return _entry.getUuid();
+ }
+
+ @Override
+ public boolean hasEditPermission(PermissionChecker permissionChecker)
+ throws PortalException {
+
+ return ${capFirstModel}EntryPermission.contains(
+ permissionChecker, _entry, ActionKeys.UPDATE);
+ }
+
+ @Override
+ public boolean hasViewPermission(PermissionChecker permissionChecker)
+ throws PortalException {
+
+ return ${capFirstModel}EntryPermission.contains(
+ permissionChecker, _entry, ActionKeys.VIEW);
+ }
+
+ @Override
+ public boolean include(
+ HttpServletRequest request, HttpServletResponse response,
+ String template)
+ throws Exception {
+
+ request.setAttribute("${uncapFirstModel}", _entry);
+
+ return super.include(request, response, template);
+ }
+
+ @Override
+ public boolean isPrintable() {
+ return true;
+ }
+
+ public void setAssetDisplayPageFriendlyURLProvider(
+ AssetDisplayPageFriendlyURLProvider
+ assetDisplayPageFriendlyURLProvider) {
+
+ _assetDisplayPageFriendlyURLProvider =
+ assetDisplayPageFriendlyURLProvider;
+ }
+
+ private boolean _hasViewInContextGroupLayout(
+ long groupId, ThemeDisplay themeDisplay) {
+
+ try {
+ PortletLayoutFinder portletLayoutFinder =
+ PortletLayoutFinderRegistryUtil.getPortletLayoutFinder(
+ ${capFirstModel}.class.getName());
+
+ PortletLayoutFinder.Result result = portletLayoutFinder.find(
+ themeDisplay, groupId);
+
+ if ((result == null) || Validator.isNull(result.getPortletId())) {
+ return false;
+ }
+
+ return true;
+ }
+ catch (PortalException pe) {
+ if (_log.isDebugEnabled()) {
+ _log.debug(pe.getLocalizedMessage(), pe);
+ }
+
+ return false;
+ }
+ }
+
+ private static final Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}AssetRenderer.class);
+
+ private AssetDisplayPageFriendlyURLProvider
+ _assetDisplayPageFriendlyURLProvider;
+ private final ${capFirstModel} _entry;
+ private final ResourceBundleLoader _resourceBundleLoader;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_AssetRendererFactory.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
new file mode 100644
index 0000000..b0ffa57
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
@@ -0,0 +1,205 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/asset/${capFirstModel}AssetRendererFactory.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.asset;
+
+import com.liferay.asset.kernel.model.AssetRenderer;
+import com.liferay.asset.kernel.model.AssetRendererFactory;
+import com.liferay.asset.kernel.model.BaseAssetRendererFactory;
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
+import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
+import com.liferay.portal.kernel.portlet.LiferayPortletURL;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.Portal;
+import com.liferay.portal.kernel.util.ResourceBundleLoaderUtil;
+import ${packageName}.constants.${capFirstModel}Constants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletURL;
+import javax.portlet.WindowState;
+import javax.portlet.WindowStateException;
+
+import javax.servlet.ServletContext;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ${capFirstModel} Asset Renderer Factory
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ service = AssetRendererFactory.class
+)
+public class ${capFirstModel}AssetRendererFactory
+ extends BaseAssetRendererFactory<${capFirstModel}> {
+
+ public static final String SYMBOLIC_NAME =
+ ${capFirstModel}Constants.RESOURCE_NAME + ".web";
+
+ public static final String TYPE = "${lowercaseModel}";
+
+ public ${capFirstModel}AssetRendererFactory() {
+ setClassName(${capFirstModel}.class.getName());
+ setCategorizable(true);
+ setPortletId(${capFirstModel}PortletKeys.${uppercaseModel});
+ setLinkable(true);
+ setSearchable(true);
+ setSelectable(true);
+ }
+
+ @Override
+ public AssetRenderer<${capFirstModel}> getAssetRenderer(long classPK, int type)
+ throws PortalException {
+
+ ${capFirstModel}AssetRenderer ${uncapFirstModel}AssetRenderer = new ${capFirstModel}AssetRenderer(
+ _${uncapFirstModel}LocalService.get${capFirstModel}(classPK),
+ ResourceBundleLoaderUtil.
+ getResourceBundleLoaderByBundleSymbolicName(SYMBOLIC_NAME));
+
+ ${uncapFirstModel}AssetRenderer.setAssetRendererType(type);
+ ${uncapFirstModel}AssetRenderer.setServletContext(_servletContext);
+
+ return ${uncapFirstModel}AssetRenderer;
+ }
+
+ @Override
+ public AssetRenderer<${capFirstModel}> getAssetRenderer(
+ long groupId, String urlTitle)
+ throws PortalException {
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(groupId, urlTitle);
+
+ ${capFirstModel}AssetRenderer ${uncapFirstModel}AssetRenderer = new ${capFirstModel}AssetRenderer(
+ entry,
+ ResourceBundleLoaderUtil.
+ getResourceBundleLoaderByBundleSymbolicName(SYMBOLIC_NAME));
+
+ ${uncapFirstModel}AssetRenderer.setServletContext(_servletContext);
+
+ return ${uncapFirstModel}AssetRenderer;
+ }
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public PortletURL getURLAdd(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse, long classTypeId) {
+
+ PortletURL portletURL = _portal.getControlPanelPortletURL(
+ liferayPortletRequest, getGroup(liferayPortletRequest),
+ ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN, 0, 0,
+ PortletRequest.RENDER_PHASE);
+
+ portletURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/crud");
+ portletURL.setParameter(Constants.CMD, Constants.ADD);
+ portletURL.setParameter("fromAsset", StringPool.TRUE);
+
+ return portletURL;
+ }
+
+ @Override
+ public PortletURL getURLView(
+ LiferayPortletResponse liferayPortletResponse,
+ WindowState windowState) {
+
+ LiferayPortletURL liferayPortletURL =
+ liferayPortletResponse.createLiferayPortletURL(
+ ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ PortletRequest.RENDER_PHASE);
+
+ liferayPortletURL.setParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/view");
+ liferayPortletURL.setParameter(Constants.CMD, Constants.VIEW);
+ liferayPortletURL.setParameter("fromAsset", StringPool.TRUE);
+
+ try {
+ liferayPortletURL.setWindowState(windowState);
+ }
+ catch (WindowStateException wse) {
+ _log.error("Windos state is not valid. Skip.", wse);
+ }
+
+ return liferayPortletURL;
+ }
+
+ @Override
+ public boolean hasAddPermission(
+ PermissionChecker permissionChecker, long groupId, long classTypeId)
+ throws Exception {
+
+ if (_portletResourcePermission.contains(
+ permissionChecker, groupId, ActionKeys.VIEW)) {
+
+ return false;
+ }
+
+ return _portletResourcePermission.contains(
+ permissionChecker, groupId, ActionKeys.ADD_ENTRY);
+ }
+
+ @Override
+ public boolean hasPermission(
+ PermissionChecker permissionChecker, long classPK, String actionId)
+ throws Exception {
+
+ return _${uncapFirstModel}ModelResourcePermission.contains(
+ permissionChecker, classPK, actionId);
+ }
+
+ @Reference(
+ target = "(osgi.web.symbolicname=${packageName}.web)", unbind = "-"
+ )
+ public void setServletContext(ServletContext servletContext) {
+ _servletContext = servletContext;
+ }
+
+ private static final Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}AssetRendererFactory.class);
+
+ @Reference
+ private Portal _portal;
+
+ @Reference(
+ target = "(resource.name=" + ${capFirstModel}Constants.RESOURCE_NAME + ")"
+ )
+ private PortletResourcePermission _portletResourcePermission;
+
+ @Reference
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+ @Reference(target = "(model.class.name=${packageName}.model.${capFirstModel})")
+ private ModelResourcePermission<${capFirstModel}> _${uncapFirstModel}ModelResourcePermission;
+
+ @Reference(target = "(osgi.web.symbolicname=" + SYMBOLIC_NAME + ")")
+ private ServletContext _servletContext;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_Configuration.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_Configuration.java.ftl
new file mode 100644
index 0000000..01be10b
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_Configuration.java.ftl
@@ -0,0 +1,46 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}Configuration.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import aQute.bnd.annotation.metatype.Meta;
+
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+/**
+ * ${capFirstModel} Configuration
+ *
+ * @author ${damascus_author}
+ */
+@Meta.OCD(id = ${capFirstModel}PortletKeys.${uppercaseModel}_CONFIG)
+public interface ${capFirstModel}Configuration {
+
+ public static final String CONF_PREFS_VIEW_TYPE = "prefsViewType";
+
+ public static final String CONF_DATE_FORMAT = "dateFormat";
+
+ public static final String CONF_DATETIME_FORMAT = "datetimeFormat";
+
+ public static final String PREFS_VIEW_TYPE_DEFAULT = "0";
+
+ public static final String PREFS_VIEW_TYPE_USER = "1";
+
+ public static final String PREFS_VIEW_TYPE_USER_GROUP = "2";
+
+ @Meta.AD(deflt = PREFS_VIEW_TYPE_DEFAULT, required = false)
+ public int prefsViewType();
+
+ @Meta.AD(deflt = "yyyy/MM/dd", required = false)
+ public String dateFormat();
+
+ @Meta.AD(deflt = "yyyy/MM/dd HH:mm", required = false)
+ public String datetimeFormat();
+
+ @Meta.AD(deflt = "%Y/%m/%d", required = false)
+ public String datePickerFormat();
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_ConfigurationAction.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ConfigurationAction.java.ftl
new file mode 100644
index 0000000..5777e34
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ConfigurationAction.java.ftl
@@ -0,0 +1,161 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}ConfigurationAction.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import aQute.bnd.annotation.metatype.Configurable;
+
+import com.liferay.portal.kernel.portlet.ConfigurationAction;
+import com.liferay.portal.kernel.portlet.DefaultConfigurationAction;
+import com.liferay.portal.kernel.servlet.SessionMessages;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletConfig;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Modified;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ${capFirstModel} Configuraion Aciton
+ *
+ * Determine the scope of the portlet configuration in DS properties of Portlet
+ * class The default of this generator is Portlet Instance scope.
+ *
+ * Look at the elements preferences-company-wide, preferences-unique-per-layout
+ * and preferences-owned-by-group to determine the right scope. The following
+ * table maps out the scopes:
+ *
+ * liferay-portlet.xml Scope preferences-company-wide=true Company
+ * preferences-owned-by-group=true AND preferences-unique-per-layout=false Group
+ * preferences-owned-by-group=true AND preferences-unique-per-layout=true
+ * Portlet Instance
+ *
+ * @author ${damascus_author}
+ *
+ */
+@Component(
+ configurationPid = ${capFirstModel}PortletKeys.${uppercaseModel}_CONFIG,
+ configurationPolicy = ConfigurationPolicy.OPTIONAL, immediate = true,
+ property = "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ service = ConfigurationAction.class
+)
+public class ${capFirstModel}ConfigurationAction extends DefaultConfigurationAction {
+
+ @Override
+ public String getJspPath(HttpServletRequest httpServletRequest) {
+ return "/${snakecaseModel}/configuration.jsp";
+ }
+
+ @Override
+ public void include(
+ PortletConfig portletConfig, HttpServletRequest httpServletRequest,
+ HttpServletResponse httpServletResponse)
+ throws Exception {
+
+ if (_log.isDebugEnabled()) {
+ _log.debug("${capFirstModel} Portlet configuration include");
+ }
+
+ httpServletRequest.setAttribute(
+ ${capFirstModel}Configuration.class.getName(), _${uncapFirstModel}Configuration);
+
+ super.include(portletConfig, httpServletRequest, httpServletResponse);
+ }
+
+ @Override
+ public void processAction(
+ PortletConfig portletConfig, ActionRequest actionRequest,
+ ActionResponse actionResponse)
+ throws Exception {
+
+ int prefsViewType = ParamUtil.getInteger(
+ actionRequest, ${capFirstModel}Configuration.CONF_PREFS_VIEW_TYPE,
+ Integer.valueOf(${capFirstModel}Configuration.PREFS_VIEW_TYPE_DEFAULT));
+ String dateFormat = ParamUtil.getString(
+ actionRequest, ${capFirstModel}Configuration.CONF_DATE_FORMAT);
+ String datetimeFormat = ParamUtil.getString(
+ actionRequest, ${capFirstModel}Configuration.CONF_DATETIME_FORMAT);
+
+ if (_log.isDebugEnabled()) {
+ _log.debug("Prefs View Type :" + prefsViewType);
+ _log.debug("Date Format :" + dateFormat);
+ _log.debug("Date Time Format:" + datetimeFormat);
+ }
+
+ List errors = new ArrayList<>();
+
+ if (validate(dateFormat, datetimeFormat, errors)) {
+ setPreference(
+ actionRequest, ${capFirstModel}Configuration.CONF_PREFS_VIEW_TYPE,
+ String.valueOf(prefsViewType));
+ setPreference(
+ actionRequest, ${capFirstModel}Configuration.CONF_DATE_FORMAT,
+ dateFormat);
+ setPreference(
+ actionRequest, ${capFirstModel}Configuration.CONF_DATETIME_FORMAT,
+ datetimeFormat);
+
+ SessionMessages.add(actionRequest, "prefsSuccess");
+ }
+
+ super.processAction(portletConfig, actionRequest, actionResponse);
+ }
+
+ @Activate
+ @Modified
+ protected void activate(Map properties) {
+ _${uncapFirstModel}Configuration = Configurable.createConfigurable(
+ ${capFirstModel}Configuration.class, properties);
+ }
+
+ /**
+ * Validate Preference
+ *
+ * @param dateFormat Date Format
+ * @param datetimeFormat Date Time Format
+ * @param errors
+ * @return boolean
+ */
+ protected boolean validate(
+ String dateFormat, String datetimeFormat, List errors) {
+
+ boolean valid = true;
+
+ if (Validator.isNull(dateFormat)) {
+ errors.add("date-format-required");
+ valid = false;
+ }
+ else if (Validator.isNull(datetimeFormat)) {
+ errors.add("datetime-format.required");
+ valid = false;
+ }
+
+ return valid;
+ }
+
+ private static final Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}ConfigurationAction.class);
+
+ private volatile ${capFirstModel}Configuration _${uncapFirstModel}Configuration;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
new file mode 100644
index 0000000..5bec50f
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
@@ -0,0 +1,291 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}CrudMVCActionCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.asset.display.page.portlet.AssetDisplayPageEntryFormProcessor;
+import com.liferay.petra.reflect.ReflectionUtil;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.TrashedModel;
+import com.liferay.portal.kernel.portlet.bridges.mvc.BaseMVCActionCommand;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCActionCommand;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.service.ServiceContextFactory;
+import com.liferay.portal.kernel.servlet.SessionErrors;
+import com.liferay.portal.kernel.servlet.SessionMessages;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.PortalUtil;
+import com.liferay.portal.kernel.util.StringUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+import ${packageName}.service.${capFirstModel}Service;
+import com.liferay.trash.service.TrashEntryService;
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "mvc.command.name=/${lowercaseModel}/crud"
+ },
+ service = MVCActionCommand.class
+)
+public class ${capFirstModel}CrudMVCActionCommand extends BaseMVCActionCommand {
+
+ /**
+ * Add Entry
+ *
+ * @param request
+ * @param response
+ * @throws ${capFirstModel}ValidateException, Exception
+ */
+ public void addEntry(ActionRequest request, ActionResponse response)
+ throws Exception, ${capFirstModel}ValidateException {
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(
+ primaryKey, request);
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ ${capFirstModel}.class.getName(), request);
+
+ // Add entry
+
+ _${uncapFirstModel}Service.addEntry(entry, serviceContext);
+
+ _assetDisplayPageEntryFormProcessor.process(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), request);
+
+ SessionMessages.add(request, "${lowercaseModel}AddedSuccessfully");
+ }
+
+ /**
+ * Delte Entry
+ *
+ * @param request
+ * @param response
+ * @param moveToTrash true to move to trush.
+ * @throws PortalException
+ * @throws Exception
+ */
+ public void deleteEntry(
+ ActionRequest request, ActionResponse response, boolean moveToTrash)
+ throws PortalException {
+
+ long[] deleteEntryIds = null;
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ long entryId = ParamUtil.getLong(request, "resourcePrimKey", 0L);
+
+ if (entryId > 0) {
+ deleteEntryIds = new long[] {entryId};
+ }
+ else {
+ deleteEntryIds = StringUtil.split(
+ ParamUtil.getString(request, "deleteEntryIds"), 0L);
+ }
+
+ List trashedModels = new ArrayList<>();
+
+ for (long deleteEntryId : deleteEntryIds) {
+ try {
+ if (moveToTrash) {
+ ${capFirstModel} entry = _${uncapFirstModel}Service.moveEntryToTrash(
+ deleteEntryId);
+
+ trashedModels.add(entry);
+ }
+ else {
+ _${uncapFirstModel}Service.deleteEntry(deleteEntryId);
+ }
+ }
+ catch (PortalException pe) {
+ ReflectionUtil.throwException(pe);
+ }
+ }
+
+ if (moveToTrash && !trashedModels.isEmpty()) {
+ Map data = new HashMap<>();
+
+ data.put("trashedModels", trashedModels);
+
+ addDeleteSuccessData(request, data);
+ }
+ }
+
+ /**
+ * Restore Entries
+ *
+ * @param actionRequest
+ * @throws Exception
+ */
+ public void restoreTrashEntries(ActionRequest actionRequest)
+ throws Exception {
+
+ long[] restoreTrashEntryIds = StringUtil.split(
+ ParamUtil.getString(actionRequest, "restoreTrashEntryIds"), 0L);
+
+ for (long restoreTrashEntryId : restoreTrashEntryIds) {
+ _trashEntryService.restoreEntry(restoreTrashEntryId);
+ }
+ }
+
+ /**
+ * Update Entry
+ *
+ * @param request
+ * @param response
+ * @throws Exception
+ */
+ public void updateEntry(ActionRequest request, ActionResponse response)
+ throws Exception {
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(
+ primaryKey, request);
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ ${capFirstModel}.class.getName(), request);
+
+ //Update entry
+ _${uncapFirstModel}Service.updateEntry(entry, serviceContext);
+
+ _assetDisplayPageEntryFormProcessor.process(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), request);
+
+ SessionMessages.add(request, "${lowercaseModel}UpdatedSuccessfully");
+ }
+
+ /**
+ * Single Delete
+ *
+ * @param entry
+ * @param moveToTrash
+ * @param trashedModels
+ */
+ protected void _deleteEntry(
+ ${capFirstModel} entry, boolean moveToTrash, List trashedModels) {
+
+ try {
+ if (moveToTrash) {
+ trashedModels.add(
+ _${uncapFirstModel}Service.moveEntryToTrash(entry.getPrimaryKey()));
+ }
+ else {
+ _${uncapFirstModel}Service.deleteEntry(entry.getPrimaryKey());
+ }
+ }
+ catch (PortalException pe) {
+ ReflectionUtil.throwException(pe);
+ }
+ }
+
+ @Override
+ protected void doProcessAction(
+ ActionRequest request, ActionResponse response)
+ throws IOException {
+
+ try {
+
+ // Fetch command
+
+ String cmd = ParamUtil.getString(request, Constants.CMD);
+
+ if (cmd.equals(Constants.ADD)) {
+ addEntry(request, response);
+ }
+ else if (cmd.equals(Constants.UPDATE)) {
+ updateEntry(request, response);
+ }
+ else if (cmd.equals(Constants.DELETE)) {
+ deleteEntry(request, response, false);
+ }
+ else if (cmd.equals(Constants.MOVE_TO_TRASH)) {
+ deleteEntry(request, response, true);
+ }
+ else if (cmd.equals(Constants.RESTORE)) {
+ restoreTrashEntries(request);
+ }
+ }
+ catch (${capFirstModel}ValidateException ssbve) {
+ for (String error : ssbve.getErrors()) {
+ SessionErrors.add(request, error);
+ }
+
+ PortalUtil.copyRequestParameters(request, response);
+ response.setRenderParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/crud");
+ hideDefaultSuccessMessage(request);
+ }
+ catch (Exception t) {
+ _log.error(t.getLocalizedMessage(), t);
+ SessionErrors.add(request, PortalException.class);
+ hideDefaultSuccessMessage(request);
+ }
+
+ //For access from Asset Publisher
+ String redirect = ParamUtil.getString(request, "redirect");
+ Boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+
+ if (Validator.isNotNull(redirect) && (true == fromAsset)) {
+ sendRedirect(request, response, redirect);
+ }
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}LocalService(
+ ${capFirstModel}LocalService ${uncapFirstModel}LocalService) {
+
+ _${uncapFirstModel}LocalService = ${uncapFirstModel}LocalService;
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}Service(${capFirstModel}Service ${uncapFirstModel}Service) {
+ _${uncapFirstModel}Service = ${uncapFirstModel}Service;
+ }
+
+ private static Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}CrudMVCActionCommand.class);
+
+ @Reference
+ private AssetDisplayPageEntryFormProcessor
+ _assetDisplayPageEntryFormProcessor;
+
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+ private ${capFirstModel}Service _${uncapFirstModel}Service;
+
+ @Reference
+ private TrashEntryService _trashEntryService;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCRenderCommand.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCRenderCommand.java.ftl
new file mode 100644
index 0000000..d7f8f62
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCRenderCommand.java.ftl
@@ -0,0 +1,248 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}CrudMVCRenderCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCRenderCommand;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}Service;
+import ${packageName}.web.constants.${capFirstModel}WebKeys;
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}EntryPermission;
+import ${packageName}.web.upload.${capFirstModel}ItemSelectorHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalService;
+import ${packageName}.web.constants.${capFirstValidationModel}WebKeys;
+import ${packageName}.web.util.${capFirstValidationModel}ViewHelper;
+ #if>
+#list>
+// //
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * CRUD Render
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "mvc.command.name=/${lowercaseModel}/crud"
+ },
+ service = MVCRenderCommand.class
+)
+public class ${capFirstModel}CrudMVCRenderCommand implements MVCRenderCommand {
+
+ /**
+ * Edit Page JSP file
+ */
+ public String getEditPageJSP() {
+ return ${capFirstModel}WebKeys.EDIT_JSP;
+ }
+
+ /**
+ * View Page JSP file
+ */
+ public String getViewPageJSP() {
+ return ${capFirstModel}WebKeys.VIEW_JSP;
+ }
+
+ /**
+ * View Record JSP file
+ */
+ public String getViewRecordPageJSP() {
+ return ${capFirstModel}WebKeys.VIEW_RECORD_JSP;
+ }
+
+ @Override
+ public String render(RenderRequest request, RenderResponse response)
+ throws PortletException {
+
+ String renderJSP = getViewPageJSP();
+
+ // Fetch command
+
+ String cmd = ParamUtil.getString(request, Constants.CMD);
+
+ // Fetch primary key
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ try {
+ if (cmd.equalsIgnoreCase(Constants.UPDATE)) {
+ renderJSP = update(request, themeDisplay, primaryKey);
+ }
+ else if (cmd.equalsIgnoreCase(Constants.VIEW)) {
+ renderJSP = view(request, themeDisplay, primaryKey);
+ }
+ else {
+ renderJSP = add(request, themeDisplay, primaryKey);
+ }
+ }
+ catch (PortalException pe) {
+ throw new PortletException(pe.getMessage());
+ }
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+
+ request.setAttribute(${capFirstValidationModel}WebKeys.${uppercaseValidationModel}_VIEW_HELPER, _${uncapFirstValidationModel}ViewHelper);
+ request.setAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE, _${uncapFirstValidationModel}LocalService);
+ #if>
+#list>
+// //
+
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_ITEM_SELECTOR_HELPER,
+ _${uncapFirstModel}ItemSelectorHelper);
+
+ return renderJSP;
+ }
+
+ /**
+ * Add record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return JSP file path
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ * @throws PortletException
+ */
+ protected String add(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, PortletException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = null;
+
+ if (Validator.isNull(request.getParameter("addErrors"))) {
+ record = _${uncapFirstModel}Service.getInitialized${capFirstModel}(
+ primaryKey, request);
+ }
+ else {
+ record = _${uncapFirstModel}Service.get${capFirstModel}FromRequest(
+ primaryKey, request);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getEditPageJSP();
+ }
+
+ /**
+ * Update record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return JSP file path to open
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ */
+ protected String update(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = _${uncapFirstModel}Service.get${capFirstModel}(primaryKey);
+
+ if (!${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), record,
+ ActionKeys.UPDATE)) {
+
+ List error = new ArrayList<>();
+ error.add("permission-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getEditPageJSP();
+ }
+
+ /**
+ * View record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ */
+ protected String view(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = _${uncapFirstModel}Service.get${capFirstModel}(primaryKey);
+
+ if (!${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), record, ActionKeys.VIEW)) {
+
+ List error = new ArrayList<>();
+ error.add("permission-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getViewRecordPageJSP();
+ }
+
+ @Reference
+ private ${capFirstModel}Service _${uncapFirstModel}Service;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+
+ @Reference
+ private ${capFirstValidationModel}ViewHelper _${uncapFirstValidationModel}ViewHelper;
+
+ @Reference
+ private ${capFirstValidationModel}LocalService _${uncapFirstValidationModel}LocalService;
+ #if>
+#list>
+// //
+
+ @Reference
+ private ${capFirstModel}ItemSelectorHelper _${uncapFirstModel}ItemSelectorHelper;
+
+}
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_DisplayContext.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_DisplayContext.java.ftl
new file mode 100644
index 0000000..fe3bbae
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_DisplayContext.java.ftl
@@ -0,0 +1,188 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/internal/display/context/${capFirstModel}DisplayContext.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.internal.display.context;
+
+import com.liferay.portal.kernel.dao.search.DisplayTerms;
+import com.liferay.portal.kernel.dao.search.SearchContainer;
+import com.liferay.portal.kernel.dao.search.SearchContainerResults;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
+import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
+import com.liferay.portal.kernel.portlet.PortalPreferences;
+import com.liferay.portal.kernel.portlet.PortletPreferencesFactoryUtil;
+import com.liferay.portal.kernel.portlet.PortletURLUtil;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}EntryPermission;
+import ${packageName}.web.util.${capFirstModel}ViewHelper;
+import com.liferay.trash.TrashHelper;
+
+import java.text.ParseException;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.PortletException;
+import javax.portlet.PortletURL;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ${capFirstModel} Display Context
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}DisplayContext {
+
+ public ${capFirstModel}DisplayContext(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse, TrashHelper trashHelper,
+ ${capFirstModel}ViewHelper ${uncapFirstModel}ViewHelper) {
+
+ _liferayPortletRequest = liferayPortletRequest;
+ _liferayPortletResponse = liferayPortletResponse;
+ _trashHelper = trashHelper;
+
+ _portalPreferences = PortletPreferencesFactoryUtil.getPortalPreferences(
+ liferayPortletRequest);
+
+ _httpServletRequest = _liferayPortletRequest.getHttpServletRequest();
+ _${uncapFirstModel}ViewHelper = ${uncapFirstModel}ViewHelper;
+ }
+
+ public List getAvailableActions(${capFirstModel} entry)
+ throws PortalException {
+
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)_httpServletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ if (${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), entry,
+ ActionKeys.DELETE)) {
+
+ return Collections.singletonList("deleteEntries");
+ }
+
+ return Collections.emptyList();
+ }
+
+ public Map getComponentContext() throws PortalException {
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)_httpServletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ return new HashMap() {
+ {
+ put(
+ "trashEnabled",
+ _trashHelper.isTrashEnabled(
+ themeDisplay.getScopeGroupId()));
+ }
+ };
+ }
+
+ public String getDisplayStyle() {
+ String displayStyle = ParamUtil.getString(
+ _httpServletRequest, "displayStyle");
+
+ if (Validator.isNull(displayStyle)) {
+ return _portalPreferences.getValue(
+ ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN, "entries-display-style",
+ "icon");
+ }
+
+ _portalPreferences.setValue(
+ ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN, "entries-display-style",
+ displayStyle);
+
+ _httpServletRequest.setAttribute(
+ WebKeys.SINGLE_PAGE_APPLICATION_CLEAR_CACHE, Boolean.TRUE);
+
+ return displayStyle;
+ }
+
+ public SearchContainer<${capFirstModel}> getSearchContainer()
+ throws ParseException, PortalException, PortletException {
+
+ PortletURL navigationPortletURL =
+ _liferayPortletResponse.createRenderURL();
+
+ String keywords = ParamUtil.getString(
+ _httpServletRequest, DisplayTerms.KEYWORDS);
+ int cur = ParamUtil.getInteger(
+ _httpServletRequest, SearchContainer.DEFAULT_CUR_PARAM);
+ String orderByCol = ParamUtil.getString(
+ _httpServletRequest, SearchContainer.DEFAULT_ORDER_BY_COL_PARAM,
+ "${lowercaseModel}Id");
+ String orderByType = ParamUtil.getString(
+ _httpServletRequest, SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM,
+ "asc");
+
+ navigationPortletURL.setParameter(DisplayTerms.KEYWORDS, keywords);
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_CUR_PARAM, String.valueOf(cur));
+ navigationPortletURL.setParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/view");
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_COL_PARAM, orderByCol);
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM, orderByType);
+
+ SearchContainer<${capFirstModel}> _searchContainer = new SearchContainer<>(
+ _liferayPortletRequest,
+ PortletURLUtil.clone(navigationPortletURL, _liferayPortletResponse),
+ null, "no-records-were-found");
+
+ _searchContainer.setId("entryList");
+ _searchContainer.setDeltaConfigurable(true);
+
+ _searchContainer.setOrderByCol(orderByCol);
+ _searchContainer.setOrderByType(orderByType);
+
+ SearchContainerResults<${capFirstModel}> searchContainerResults = null;
+
+ if (Validator.isNull(keywords)) {
+ searchContainerResults = _${uncapFirstModel}ViewHelper.getListFromDB(
+ _liferayPortletRequest, _searchContainer,
+ new int[] {WorkflowConstants.STATUS_APPROVED});
+ }
+ else {
+ searchContainerResults = _${uncapFirstModel}ViewHelper.getListFromIndex(
+ _liferayPortletRequest, _searchContainer,
+ WorkflowConstants.STATUS_APPROVED);
+ }
+
+ _searchContainer.setTotal(searchContainerResults.getTotal());
+ _searchContainer.setResults(searchContainerResults.getResults());
+
+ return _searchContainer;
+ }
+
+ private static final Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}DisplayContext.class);
+
+ private final HttpServletRequest _httpServletRequest;
+ private final LiferayPortletRequest _liferayPortletRequest;
+ private final LiferayPortletResponse _liferayPortletResponse;
+ private final PortalPreferences _portalPreferences;
+ private ${capFirstModel}ViewHelper _${uncapFirstModel}ViewHelper;
+ private final TrashHelper _trashHelper;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_EntryPermission.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_EntryPermission.java.ftl
new file mode 100644
index 0000000..5addb3b
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_EntryPermission.java.ftl
@@ -0,0 +1,63 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/internal/security/permission/resource/${capFirstModel}EntryPermission.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.internal.security.permission.resource;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import ${packageName}.model.${capFirstModel};
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * Entry Permission
+ *
+ * @author ${damascus_author}
+ */
+@Component(immediate = true, service = {})
+public class ${capFirstModel}EntryPermission {
+
+ public static boolean contains(
+ PermissionChecker permissionChecker, long entryId, String actionId)
+ throws PortalException {
+
+ return _${uncapFirstModel}ModelResourcePermission.contains(
+ permissionChecker, entryId, actionId);
+ }
+
+ public static boolean contains(
+ PermissionChecker permissionChecker, ${capFirstModel} entry,
+ String actionId)
+ throws PortalException {
+
+ return _${uncapFirstModel}ModelResourcePermission.contains(
+ permissionChecker, entry, actionId);
+ }
+
+ @Reference(
+ policy = ReferencePolicy.DYNAMIC,
+ policyOption = ReferencePolicyOption.GREEDY,
+ target = "(model.class.name=${packageName}.model.${capFirstModel})"
+ )
+ protected void set${capFirstModel}ModelResourcePermission(
+ ModelResourcePermission<${capFirstModel}> modelResourcePermission) {
+
+ _${uncapFirstModel}ModelResourcePermission = modelResourcePermission;
+ }
+
+ protected void unset${capFirstModel}ModelResourcePermission(
+ ModelResourcePermission<${capFirstModel}> modelResourcePermission) {
+ }
+
+ private static ModelResourcePermission<${capFirstModel}>
+ _${uncapFirstModel}ModelResourcePermission;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_ExportMVCResourceCommand.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ExportMVCResourceCommand.java.ftl
new file mode 100644
index 0000000..5e00cce
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ExportMVCResourceCommand.java.ftl
@@ -0,0 +1,193 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}ExportMVCResourceCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.dao.search.DisplayTerms;
+import com.liferay.portal.kernel.dao.search.SearchContainer;
+import com.liferay.portal.kernel.dao.search.SearchContainerResults;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCResourceCommand;
+import com.liferay.portal.kernel.search.SearchException;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ContentTypes;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.web.util.${capFirstModel}ViewHelper;
+
+import java.io.IOException;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.portlet.PortletPreferences;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Export Resource Command
+ *
+ * @author Softbless
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "mvc.command.name=/${lowercaseModel}/export"
+ },
+ service = MVCResourceCommand.class
+)
+public class ${capFirstModel}ExportMVCResourceCommand implements MVCResourceCommand {
+
+ @Override
+ public boolean serveResource(
+ ResourceRequest resourceRequest, ResourceResponse resourceResponse) {
+
+ String cmd = ParamUtil.getString(resourceRequest, Constants.CMD, "");
+
+// //
+ if (!cmd.equals(Constants.EXPORT)) {
+ return false;
+ }
+
+ ${capFirstModel}Configuration ${uncapFirstModel}Configuration =
+ (${capFirstModel}Configuration)resourceRequest.getAttribute(
+ ${capFirstModel}Configuration.class.getName());
+
+ PortletPreferences portletPreferences =
+ resourceRequest.getPreferences();
+
+ String dateFormatVal = HtmlUtil.escape(
+ portletPreferences.getValue(
+ "dateFormat",
+ Validator.isNull(${uncapFirstModel}Configuration) ? "yyyy/MM/dd" :
+ ${uncapFirstModel}Configuration.dateFormat()));
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatVal);
+
+ String keywords = ParamUtil.getString(
+ resourceRequest, DisplayTerms.KEYWORDS);
+ String orderByCol = ParamUtil.getString(
+ resourceRequest, SearchContainer.DEFAULT_ORDER_BY_COL_PARAM,
+ "${lowercaseModel}Id");
+ String orderByType = ParamUtil.getString(
+ resourceRequest, SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM,
+ "asc");
+
+ String filename = Constants.EXPORT;
+
+ SearchContainerResults<${capFirstModel}> searchContainerResults = null;
+
+ try {
+ if (Validator.isNull(keywords)) {
+ searchContainerResults = _${uncapFirstModel}ViewHelper.getListFromDB(
+ resourceRequest, -1, -1, orderByCol, orderByType,
+ new int[] {WorkflowConstants.STATUS_APPROVED});
+ }
+ else {
+ searchContainerResults = _${uncapFirstModel}ViewHelper.getListFromIndex(
+ resourceRequest, -1, -1, WorkflowConstants.STATUS_APPROVED);
+ }
+ }
+ catch (ParseException | SearchException e) {
+ e.printStackTrace();
+ }
+
+ try (Workbook workbook = new HSSFWorkbook()) {
+ Sheet sheet = workbook.createSheet("data");
+
+ List headers = new LinkedList<>();
+
+ <#list application.fields as field >
+ headers.add("${field.name?cap_first}");
+ #list>
+
+ // Header
+
+ Row headerRow = sheet.createRow(0);
+
+ for (int i = 0; i < headers.size(); i++) {
+ Cell cell = headerRow.createCell(i);
+
+ cell.setCellValue(headers.get(i));
+ }
+
+ if (Validator.isNotNull(searchContainerResults) &&
+ (searchContainerResults.getTotal() > 0)) {
+
+ List<${capFirstModel}> datas = searchContainerResults.getResults();
+
+ for (int i = 0; i < searchContainerResults.getTotal(); i++) {
+ Row row = sheet.createRow(i + 1);
+
+ for (int j = 0; j < headers.size(); j++) {
+ Cell cell = row.createCell(j);
+ switch (j) {
+ <#assign counter = 0>
+ <#list application.fields as field >
+ case ${counter}:
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime"
+ >
+ cell.setCellValue(dateFormat.format(datas.get(i).get${field.name?cap_first}()));
+ <#else>
+ cell.setCellValue(datas.get(i).get${field.name?cap_first}());
+ #if>
+
+ break;
+ <#assign counter += 1>
+ #list>
+ default:
+
+ break;
+ }
+ }
+ }
+ }
+
+ resourceResponse.setContentType(
+ ContentTypes.APPLICATION_VND_MS_EXCEL);
+ resourceResponse.setProperty(
+ "Content-Disposition",
+ "attachment; filename=\"" + filename + ".xls\"");
+ workbook.write(resourceResponse.getPortletOutputStream());
+
+ return true;
+ }
+ catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+// //
+
+ return false;
+ }
+
+ @Reference(unbind = "-")
+ public void setViewHelper(${capFirstModel}ViewHelper ${uncapFirstModel}ViewHelper) {
+ _${uncapFirstModel}ViewHelper = ${uncapFirstModel}ViewHelper;
+ }
+
+ private ${capFirstModel}ViewHelper _${uncapFirstModel}ViewHelper;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_FriendlyURLMapper.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_FriendlyURLMapper.java.ftl
new file mode 100644
index 0000000..7f0700b
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_FriendlyURLMapper.java.ftl
@@ -0,0 +1,39 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/route/${capFirstModel}FriendlyURLMapper.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.route;
+
+import com.liferay.portal.kernel.portlet.DefaultFriendlyURLMapper;
+import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * FriendlyURL Mapper
+ *
+ * This is used to mapping Friendly URL to the portlet. This class is reqired for routing path correctly for Asset Publisher.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ property = {
+ "com.liferay.portlet.friendly-url-routes=META-INF/friendly-url-routes/routes.xml",
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}
+ },
+ service = FriendlyURLMapper.class
+)
+public class ${capFirstModel}FriendlyURLMapper extends DefaultFriendlyURLMapper {
+
+ @Override
+ public String getMapping() {
+ return _MAPPING;
+ }
+
+ private static final String _MAPPING = "${uncapFirstModel}";
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_ItemSelectorHelper.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ItemSelectorHelper.java.ftl
new file mode 100644
index 0000000..ac145cc
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ItemSelectorHelper.java.ftl
@@ -0,0 +1,75 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/upload/${capFirstModel}ItemSelectorHelper.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.upload;
+
+import com.liferay.item.selector.ItemSelector;
+import com.liferay.item.selector.ItemSelectorReturnType;
+import com.liferay.item.selector.criteria.FileEntryItemSelectorReturnType;
+import com.liferay.item.selector.criteria.file.criterion.FileItemSelectorCriterion;
+import com.liferay.portal.kernel.portlet.RequestBackedPortletURLFactory;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.PortletURL;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * Item Selector Helper
+ *
+ * This is used for Documents and Media related operations (such as uploading assets, selecting assets, e.g)
+ *
+ * @author ${damascus_author}
+ */
+@Component(service = ${capFirstModel}ItemSelectorHelper.class)
+public class ${capFirstModel}ItemSelectorHelper {
+
+ public String getItemSelectorURL(
+ RequestBackedPortletURLFactory requestBackedPortletURLFactory,
+ ThemeDisplay themeDisplay, String itemSelectedEventName) {
+
+ List desiredItemSelectorReturnTypes =
+ new ArrayList<>();
+ desiredItemSelectorReturnTypes.add(
+ new FileEntryItemSelectorReturnType());
+
+ FileItemSelectorCriterion fileItemSelectorCriterion =
+ new FileItemSelectorCriterion();
+
+ fileItemSelectorCriterion.setDesiredItemSelectorReturnTypes(
+ desiredItemSelectorReturnTypes);
+
+ PortletURL itemSelectorURL = _itemSelector.getItemSelectorURL(
+ requestBackedPortletURLFactory, itemSelectedEventName,
+ fileItemSelectorCriterion);
+
+ return itemSelectorURL.toString();
+ }
+
+ @Reference(
+ cardinality = ReferenceCardinality.OPTIONAL,
+ policy = ReferencePolicy.DYNAMIC,
+ policyOption = ReferencePolicyOption.GREEDY
+ )
+ public void setItemSelector(ItemSelector itemSelector) {
+ _itemSelector = itemSelector;
+ }
+
+ public void unsetItemSelector(ItemSelector itemSelector) {
+ _itemSelector = null;
+ }
+
+ private ItemSelector _itemSelector;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_Language.properties.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_Language.properties.ftl
new file mode 100644
index 0000000..165b544
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_Language.properties.ftl
@@ -0,0 +1,33 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/content/Language.properties">
+<#assign skipTemplate = !generateWeb>
+# #
+
+# #
+model.resource.${packageName}=${damascus.projectName}
+
+<#list damascus.applications as application>
+javax.portlet.short-title.${application.model?lower_case}web=${camelcaseProjectName}Web
+javax.portlet.title.${application.model?lower_case}web=${camelcaseProjectName}Web
+model.resource.${packageName}.model.${application.model?cap_first}=${application.model?cap_first}
+ <#list application.fields as field >
+${application.model?lower_case}-${field.name?lower_case}=${field.title}
+${field.name?lower_case}=${field.title}
+ <#if field.required?? && field.required == true>
+${application.model?lower_case}-${field.name?lower_case}-required=The field ${field.title} must be filled!
+ #if>
+ #list>
+add-${application.model?lower_case}=Add ${application.model?lower_case}
+${application.model?lower_case}-added-successfully=The data has been added.
+${application.model?lower_case}-updated-successfully=The data has been updated.
+${application.model?lower_case}-deleted-successfully=The data has been deleted.
+#list>
+there-was-an-unexpected-error.-please-refresh-the-current-page=Unexpected error. Please refresh.
+permissions=Permissions
+view=View
+edit=Update
+remove=Delete
+trash=Move to trash
+# #
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_LayoutFinder.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_LayoutFinder.java.ftl
new file mode 100644
index 0000000..447bf6a
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_LayoutFinder.java.ftl
@@ -0,0 +1,30 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}LayoutFinder.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import com.liferay.portal.kernel.portlet.BasePortletLayoutFinder;
+import com.liferay.portal.kernel.portlet.PortletLayoutFinder;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = PortletLayoutFinder.class
+)
+public class ${capFirstModel}LayoutFinder extends BasePortletLayoutFinder {
+
+ @Override
+ protected String[] getPortletIds() {
+ return _PORTLET_IDS;
+ }
+
+ private static final String[] _PORTLET_IDS = {${capFirstModel}PortletKeys.${uppercaseModel}};
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_ManagementToolbarDisplayContext.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ManagementToolbarDisplayContext.java.ftl
new file mode 100644
index 0000000..4dd75dd
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ManagementToolbarDisplayContext.java.ftl
@@ -0,0 +1,346 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/internal/display/context/${capFirstModel}ManagementToolbarDisplayContext.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.internal.display.context;
+
+import com.liferay.frontend.taglib.clay.servlet.taglib.display.context.SearchContainerManagementToolbarDisplayContext;
+import com.liferay.frontend.taglib.clay.servlet.taglib.util.CreationMenu;
+import com.liferay.frontend.taglib.clay.servlet.taglib.util.DropdownItem;
+import com.liferay.frontend.taglib.clay.servlet.taglib.util.DropdownItemList;
+import com.liferay.frontend.taglib.clay.servlet.taglib.util.ViewTypeItem;
+import com.liferay.portal.kernel.dao.search.DisplayTerms;
+import com.liferay.portal.kernel.dao.search.SearchContainer;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.language.LanguageUtil;
+import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
+import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}Permission;
+import com.liferay.trash.TrashHelper;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.PortletURL;
+import javax.portlet.ResourceURL;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * ${capFirstModel} Management Toolbar Display Context
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}ManagementToolbarDisplayContext
+ extends SearchContainerManagementToolbarDisplayContext {
+
+ public ${capFirstModel}ManagementToolbarDisplayContext(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse,
+ HttpServletRequest httpServletRequest,
+ SearchContainer> searchContainer, TrashHelper trashHelper,
+ String displayStyle) {
+
+ super(
+ liferayPortletRequest, liferayPortletResponse, httpServletRequest,
+ searchContainer);
+
+ _trashHelper = trashHelper;
+ _displayStyle = displayStyle;
+
+ _themeDisplay = (ThemeDisplay)httpServletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+ }
+
+ /**
+ * Order Dropdown items
+ *
+ * @return
+ */
+ public List _getOrderByDropdownItems() {
+ return new DropdownItemList() {
+ {
+// //
+<#list application.fields as field >
+ <#if field.primary?? && field.primary == false >
+ add(
+ dropdownItem -> {
+ dropdownItem.setActive(
+ Objects.equals(getOrderByCol(), "${field.name}"));
+ dropdownItem.setHref(
+ _getCurrentSortingURL(), "orderByCol", "${field.name}");
+ dropdownItem.setLabel(
+ LanguageUtil.get(request, "${field.name}"));
+ });
+ #if>
+#list>
+// //
+ }
+ };
+ }
+
+ /**
+ * Action Items
+ */
+ @Override
+ public List getActionDropdownItems() {
+ return new DropdownItemList() {
+ {
+
+ // Delete action
+
+ add(
+ dropdownItem -> {
+ dropdownItem.putData("action", "deleteEntries");
+ dropdownItem.setHref(
+ "javascript:" +
+ liferayPortletResponse.getNamespace() +
+ "deleteEntries();");
+
+ boolean trashEnabled = _trashHelper.isTrashEnabled(
+ _themeDisplay.getScopeGroupId());
+
+ dropdownItem.setIcon(
+ trashEnabled ? "trash" : "times-circle");
+
+ String label = "delete";
+
+ if (trashEnabled) {
+ label = "move-to-recycle-bin";
+ }
+
+ dropdownItem.setLabel(LanguageUtil.get(request, label));
+
+ dropdownItem.setQuickAction(true);
+ });
+// //
+<#if exportExcel>
+ // Export Action
+
+ add(
+ dropdownItem -> {
+ dropdownItem.setHref(_getExportResourceURL());
+
+ dropdownItem.setIcon("download");
+
+ dropdownItem.setLabel(
+ LanguageUtil.get(request, "download"));
+
+ dropdownItem.setQuickAction(true);
+ });
+#if>
+// //
+ }
+ };
+ }
+
+ @Override
+ public String getClearResultsURL() {
+ return getSearchActionURL();
+ }
+
+ public Map getComponentContext() throws PortalException {
+ Map context = new HashMap<>();
+
+ String cmd = Constants.DELETE;
+
+ if (_trashHelper.isTrashEnabled(_themeDisplay.getScopeGroup())) {
+ cmd = Constants.MOVE_TO_TRASH;
+ }
+
+ context.put(Constants.CMD, cmd);
+
+ PortletURL deleteEntriesURL = liferayPortletResponse.createActionURL();
+
+ deleteEntriesURL.setParameter(
+ ActionRequest.ACTION_NAME, "/${lowercaseModel}/crud");
+
+ context.put("deleteEntryIds", deleteEntriesURL.toString());
+
+ context.put(
+ "trashEnabled",
+ _trashHelper.isTrashEnabled(_themeDisplay.getScopeGroupId()));
+
+ return context;
+ }
+
+ @Override
+ public CreationMenu getCreationMenu() {
+ if (!${capFirstModel}Permission.contains(
+ _themeDisplay.getPermissionChecker(),
+ _themeDisplay.getScopeGroupId(), ActionKeys.ADD_ENTRY)) {
+
+ return null;
+ }
+
+ return new CreationMenu() {
+ {
+ addDropdownItem(
+ dropdownItem -> {
+ dropdownItem.setHref(
+ liferayPortletResponse.createRenderURL(),
+ Constants.CMD, Constants.ADD,
+ "mvcRenderCommandName", "/${lowercaseModel}/crud",
+ "redirect", currentURLObj.toString());
+ dropdownItem.setLabel(
+ LanguageUtil.get(request, "add-${lowercaseModel}"));
+ });
+ }
+ };
+ }
+
+ /**
+ * Returns the filter menu options.
+ *
+ * @return menu options list
+ */
+ @Override
+ public List getFilterDropdownItems() {
+ return new DropdownItemList() {
+ {
+ addGroup(
+ dropdownGroupItem -> {
+ dropdownGroupItem.setDropdownItems(
+ _getOrderByDropdownItems());
+ dropdownGroupItem.setLabel(
+ LanguageUtil.get(request, "order-by"));
+ });
+ }
+ };
+ }
+
+ public String getOrderByType() {
+ return searchContainer.getOrderByType();
+ }
+
+ @Override
+ public String getSearchActionURL() {
+ PortletURL searchURL = liferayPortletResponse.createRenderURL();
+
+ searchURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/view");
+
+ String navigation = ParamUtil.getString(
+ request, "navigation", "entries");
+
+ searchURL.setParameter("navigation", navigation);
+
+ searchURL.setParameter("orderByCol", getOrderByCol());
+ searchURL.setParameter("orderByType", getOrderByType());
+
+ return searchURL.toString();
+ }
+
+ @Override
+ public String getSortingURL() {
+ PortletURL sortingURL = _getCurrentSortingURL();
+
+ sortingURL.setParameter(
+ "orderByType",
+ Objects.equals(getOrderByType(), "asc") ? "desc" : "asc");
+
+ return sortingURL.toString();
+ }
+
+ @Override
+ public List getViewTypeItems() {
+ return null;
+
+ // TODO : Configure if you need to switch view type
+
+ // return new ViewTypeItemList(getPortletURL(), getDisplayStyle()) {
+
+ // {
+ // if (ArrayUtil.contains(getDisplayViews(), "icon")) {
+ // addCardViewTypeItem();
+ // }
+ //
+ // if (ArrayUtil.contains(getDisplayViews(), "descriptive")) {
+ // addListViewTypeItem();
+ // }
+ //
+ // if (ArrayUtil.contains(getDisplayViews(), "list")) {
+ // addTableViewTypeItem();
+ // }
+ // }
+ // };
+
+ }
+
+ /**
+ * Export Resource URL
+ *
+ * @return Export resource URL
+ */
+ protected String _getExportResourceURL() {
+ String keywords = ParamUtil.getString(request, DisplayTerms.KEYWORDS);
+
+ ResourceURL exportResourceURL =
+ liferayPortletResponse.createResourceURL(
+ _themeDisplay.getPortletDisplay(
+ ).getId());
+
+ exportResourceURL.setParameter(Constants.CMD, Constants.EXPORT);
+ exportResourceURL.setParameter(DisplayTerms.KEYWORDS, keywords);
+ exportResourceURL.setResourceID("/${lowercaseModel}/export");
+ exportResourceURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_COL_PARAM,
+ searchContainer.getOrderByCol());
+ exportResourceURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM,
+ searchContainer.getOrderByType());
+
+ return exportResourceURL.toString();
+ }
+
+ /**
+ * Search Sort URL
+ *
+ * @return Search filter URL string
+ */
+ private PortletURL _getCurrentSortingURL() {
+ String keywords = ParamUtil.getString(request, DisplayTerms.KEYWORDS);
+ int cur = ParamUtil.getInteger(
+ request, SearchContainer.DEFAULT_CUR_PARAM);
+ int delta = ParamUtil.getInteger(
+ request, SearchContainer.DEFAULT_DELTA_PARAM);
+ String orderByCol = ParamUtil.getString(
+ request, SearchContainer.DEFAULT_ORDER_BY_COL_PARAM, "${lowercaseModel}Id");
+ String orderByType = ParamUtil.getString(
+ request, SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM, "asc");
+
+ PortletURL navigationPortletURL =
+ liferayPortletResponse.createRenderURL();
+
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_CUR_PARAM, String.valueOf(cur));
+ navigationPortletURL.setParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/view");
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_COL_PARAM, orderByCol);
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM, orderByType);
+
+ if (Validator.isNotNull(keywords)) {
+ navigationPortletURL.setParameter(DisplayTerms.KEYWORDS, keywords);
+ }
+
+ return navigationPortletURL;
+ }
+
+ private final String _displayStyle;
+ private final ThemeDisplay _themeDisplay;
+ private final TrashHelper _trashHelper;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_PanelApp.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_PanelApp.java.ftl
new file mode 100644
index 0000000..b5eb35b
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_PanelApp.java.ftl
@@ -0,0 +1,50 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}PanelApp.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import com.liferay.application.list.BasePanelApp;
+import com.liferay.application.list.PanelApp;
+import com.liferay.application.list.constants.PanelCategoryKeys;
+import com.liferay.portal.kernel.model.Portlet;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * PanelApp
+ *
+ * This class is used to display a portet in the product menu
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "panel.app.order:Integer=100", //TODO : this number determin the order in the panel
+ "panel.category.key=" + PanelCategoryKeys.SITE_ADMINISTRATION_CONTENT
+ },
+ service = PanelApp.class
+)
+public class ${capFirstModel}PanelApp extends BasePanelApp {
+
+ @Override
+ public String getPortletId() {
+ return ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN;
+ }
+
+ @Override
+ @Reference(
+ target = "(javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN + ")",
+ unbind = "-"
+ )
+ public void setPortlet(Portlet portlet) {
+ super.setPortlet(portlet);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_Permission.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_Permission.java.ftl
new file mode 100644
index 0000000..a2bedb0
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_Permission.java.ftl
@@ -0,0 +1,44 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/internal/security/permission/resource/${capFirstModel}Permission.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.internal.security.permission.resource;
+
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import ${packageName}.constants.${capFirstModel}Constants;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Permission
+ *
+ * @author ${damascus_author}
+ */
+@Component(immediate = true, service = {})
+public class ${capFirstModel}Permission {
+
+ public static boolean contains(
+ PermissionChecker permissionChecker, long groupId, String actionId) {
+
+ return _portletResourcePermission.contains(
+ permissionChecker, groupId, actionId);
+ }
+
+ @Reference(
+ target = "(resource.name=" + ${capFirstModel}Constants.RESOURCE_NAME + ")",
+ unbind = "-"
+ )
+ protected void setPortletResourcePermission(
+ PortletResourcePermission portletResourcePermission) {
+
+ _portletResourcePermission = portletResourcePermission;
+ }
+
+ private static PortletResourcePermission _portletResourcePermission;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_Portlet.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_Portlet.java.ftl
new file mode 100644
index 0000000..d7ee64c
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_Portlet.java.ftl
@@ -0,0 +1,108 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}Portlet.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import aQute.bnd.annotation.metatype.Configurable;
+
+import com.liferay.asset.constants.AssetWebKeys;
+import com.liferay.asset.util.AssetHelper;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.web.portlet.action.${capFirstModel}Configuration;
+import com.liferay.trash.TrashHelper;
+import com.liferay.trash.util.TrashWebKeys;
+
+import java.io.IOException;
+
+import java.util.Map;
+
+import javax.portlet.Portlet;
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Modified;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Portlet
+ *
+ * @author yasuflatland
+ */
+@Component(
+ configurationPid = ${capFirstModel}PortletKeys.${uppercaseModel}_CONFIG, immediate = true,
+ property = {
+ "com.liferay.portlet.add-default-resource=true",
+ "com.liferay.portlet.application-type=full-page-application",
+ "com.liferay.portlet.application-type=widget",
+ "com.liferay.portlet.css-class-wrapper=portlet-${lowercaseModel}",
+ "com.liferay.portlet.display-category=category.sample",
+ "com.liferay.portlet.header-portlet-css=/${snakecaseModel}/css/main.css",
+ "com.liferay.portlet.layout-cacheable=true",
+ "com.liferay.portlet.preferences-owned-by-group=true",
+ "com.liferay.portlet.private-request-attributes=false",
+ "com.liferay.portlet.private-session-attributes=false",
+ "com.liferay.portlet.render-weight=50",
+ "com.liferay.portlet.scopeable=true",
+ "com.liferay.portlet.struts-path=${lowercaseModel}",
+ "com.liferay.portlet.use-default-template=true",
+ "javax.portlet.display-name=${capFirstModel}",
+ "javax.portlet.init-param.mvc-command-names-default-views=/${lowercaseModel}/view",
+ "javax.portlet.expiration-cache=0",
+ "javax.portlet.init-param.always-display-default-configuration-icons=true",
+ "javax.portlet.init-param.template-path=/META-INF/resources/",
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "javax.portlet.resource-bundle=content.Language",
+ "javax.portlet.security-role-ref=guest,power-user,user"
+ },
+ service = Portlet.class
+)
+public class ${capFirstModel}Portlet extends MVCPortlet {
+
+ @Override
+ public void render(
+ RenderRequest renderRequest, RenderResponse renderResponse)
+ throws IOException, PortletException {
+
+ renderRequest.setAttribute(AssetWebKeys.ASSET_HELPER, _assetHelper);
+ renderRequest.setAttribute(TrashWebKeys.TRASH_HELPER, _trashHelper);
+ renderRequest.setAttribute(
+ ${capFirstModel}Configuration.class.getName(), _${uncapFirstModel}Configuration);
+
+ super.render(renderRequest, renderResponse);
+ }
+
+ @Activate
+ @Modified
+ protected void activate(Map properties) {
+ _${uncapFirstModel}Configuration = Configurable.createConfigurable(
+ ${capFirstModel}Configuration.class, properties);
+ }
+
+ @Override
+ protected void doDispatch(
+ RenderRequest renderRequest, RenderResponse renderResponse)
+ throws IOException, PortletException {
+
+ renderRequest.setAttribute(
+ ${capFirstModel}Configuration.class.getName(), _${uncapFirstModel}Configuration);
+
+ super.doDispatch(renderRequest, renderResponse);
+ }
+
+ @Reference
+ private AssetHelper _assetHelper;
+
+ private volatile ${capFirstModel}Configuration _${uncapFirstModel}Configuration;
+
+ @Reference
+ private TrashHelper _trashHelper;
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_PortletLayoutFinder.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_PortletLayoutFinder.java.ftl
new file mode 100644
index 0000000..3b6738d
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_PortletLayoutFinder.java.ftl
@@ -0,0 +1,33 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}PortletLayoutFinder.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.portlet.BasePortletLayoutFinder;
+import com.liferay.portal.kernel.portlet.PortletLayoutFinder;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = PortletLayoutFinder.class
+)
+public class ${capFirstModel}PortletLayoutFinder extends BasePortletLayoutFinder {
+
+ @Override
+ protected String[] getPortletIds() {
+ return _PORTLET_IDS;
+ }
+
+ private static final String[] _PORTLET_IDS = {${capFirstModel}PortletKeys.${uppercaseModel}};
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_PortletProvider.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_PortletProvider.java.ftl
new file mode 100644
index 0000000..f63dc3e
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_PortletProvider.java.ftl
@@ -0,0 +1,43 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}PortletProvider.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import com.liferay.portal.kernel.portlet.BasePortletProvider;
+import com.liferay.portal.kernel.portlet.EditPortletProvider;
+import com.liferay.portal.kernel.portlet.ManagePortletProvider;
+import com.liferay.portal.kernel.portlet.ViewPortletProvider;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * Portlet Provider
+ *
+ * This class returns Portlet ID for PortletProviderUtil which is used in TrashHandler.
+ * This Portlet ID is used to create a restore URL.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = {
+ EditPortletProvider.class, ManagePortletProvider.class,
+ ViewPortletProvider.class
+ }
+)
+public class ${capFirstModel}PortletProvider
+ extends BasePortletProvider
+ implements EditPortletProvider, ManagePortletProvider, ViewPortletProvider {
+
+ @Override
+ public String getPortletName() {
+ return ${capFirstModel}PortletKeys.${uppercaseModel};
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_ViewHelper.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ViewHelper.java.ftl
new file mode 100644
index 0000000..d80a6f2
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ViewHelper.java.ftl
@@ -0,0 +1,282 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/util/${capFirstModel}ViewHelper.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.util;
+
+import com.liferay.portal.kernel.dao.search.DisplayTerms;
+import com.liferay.portal.kernel.dao.search.SearchContainer;
+import com.liferay.portal.kernel.dao.search.SearchContainerResults;
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.Hits;
+import com.liferay.portal.kernel.search.Indexer;
+import com.liferay.portal.kernel.search.IndexerRegistryUtil;
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.kernel.search.SearchContextFactory;
+import com.liferay.portal.kernel.search.SearchException;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.GetterUtil;
+import com.liferay.portal.kernel.util.OrderByComparator;
+import com.liferay.portal.kernel.util.OrderByComparatorFactoryUtil;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.PortalUtil;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalServiceUtil;
+import ${packageName}.web.portlet.action.${capFirstModel}Configuration;
+
+import java.text.ParseException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.PortletPreferences;
+import javax.portlet.PortletRequest;
+
+import org.osgi.service.component.annotations.Component;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * View Helper
+ *
+ * @author ${damascus_author}
+ */
+@Component(immediate = true, service = ${capFirstModel}ViewHelper.class)
+public class ${capFirstModel}ViewHelper {
+
+ /**
+ * Get Data list from Database
+ *
+ * @param request PortletRequest
+ * @param start int
+ * @param end int
+ * @param orderByCol String
+ * @param orderByType String
+ * @return SearchContainerResults<${capFirstModel}>
+ * @throws ParseException
+ */
+ public SearchContainerResults<${capFirstModel}> getListFromDB(
+ PortletRequest request, int start, int end, String orderByCol,
+ String orderByType, int[] state)
+ throws ParseException {
+
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+ PortletPreferences portletPreferences = request.getPreferences();
+
+ // Filter type
+
+ String prefsViewType = portletPreferences.getValue(
+ ${capFirstModel}Configuration.CONF_PREFS_VIEW_TYPE,
+ ${capFirstModel}Configuration.PREFS_VIEW_TYPE_DEFAULT);
+
+ long groupId = themeDisplay.getScopeGroupId();
+ int containerStart = start;
+ int containerEnd = end;
+
+ List<${capFirstModel}> results = new ArrayList<>();
+
+ int total = 0;
+
+ // Get Order
+
+ OrderByComparator<${capFirstModel}> orderByComparator = getOrderByComparator(
+ orderByCol, orderByType);
+
+ if (prefsViewType.equals(
+ ${capFirstModel}Configuration.PREFS_VIEW_TYPE_DEFAULT)) {
+
+ results = ${capFirstModel}LocalServiceUtil.findAllInGroup(
+ groupId, containerStart, containerEnd, orderByComparator,
+ state);
+ total = ${capFirstModel}LocalServiceUtil.countAllInGroup(groupId, state);
+ }
+ else if (prefsViewType.equals(
+ ${capFirstModel}Configuration.PREFS_VIEW_TYPE_USER)) {
+
+ results = ${capFirstModel}LocalServiceUtil.findAllInUser(
+ themeDisplay.getUserId(), containerStart, containerEnd,
+ orderByComparator, state);
+ total = ${capFirstModel}LocalServiceUtil.countAllInUser(
+ themeDisplay.getUserId(), state);
+ }
+ else {
+ results = ${capFirstModel}LocalServiceUtil.findAllInUserAndGroup(
+ themeDisplay.getUserId(), groupId, containerStart, containerEnd,
+ orderByComparator, state);
+ total = ${capFirstModel}LocalServiceUtil.countAllInUserAndGroup(
+ themeDisplay.getUserId(), groupId, state);
+ }
+
+ return new SearchContainerResults<>(results, total);
+ }
+
+ /**
+ * Get Data list from Database
+ *
+ * @param request PortletRequest
+ * @param searchContainer SearchContainer>
+ * @return SearchContainerResults<${capFirstModel}>
+ * @throws ParseException
+ */
+ public SearchContainerResults<${capFirstModel}> getListFromDB(
+ PortletRequest request, SearchContainer> searchContainer,
+ int[] state)
+ throws ParseException {
+
+ return getListFromDB(
+ request, searchContainer.getStart(), searchContainer.getEnd(),
+ searchContainer.getOrderByCol(), searchContainer.getOrderByType(),
+ state);
+ }
+
+ /**
+ * Get Data list from Index
+ *
+ * @param request PortletRequest
+ * @param start int
+ * @param end int
+ * @throws SearchException
+ */
+ public SearchContainerResults<${capFirstModel}> getListFromIndex(
+ PortletRequest request, int start, int end, int state)
+ throws SearchException {
+
+ // Search Key
+
+ String searchFilter = ParamUtil.getString(
+ request, DisplayTerms.KEYWORDS);
+
+ Indexer<${capFirstModel}> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
+ ${capFirstModel}.class);
+
+ SearchContext searchContext = SearchContextFactory.getInstance(
+ PortalUtil.getHttpServletRequest(request));
+
+ // TODO : When WorkflowConstants.STATUS_ANY, this parameter should be set to
+ // display all records in the list
+ // searchContext.setAndSearch(true);
+
+ searchContext.setAttribute(Field.STATUS, state);
+
+ searchContext.setKeywords(searchFilter);
+ searchContext.setStart(start);
+ searchContext.setEnd(end);
+
+ // Search in index
+
+ Hits results = indexer.search(searchContext);
+
+ // Initialize return values
+
+ int total = results.getLength();
+ List<${capFirstModel}> tempResults = new ArrayList<>();
+
+ for (int i = 0; i < results.getDocs().length; i++) {
+ Document doc = results.doc(i);
+
+ ${capFirstModel} resReg = null;
+
+ // Entry
+
+ long entryId = GetterUtil.getLong(doc.get(Field.ENTRY_CLASS_PK));
+
+ try {
+ resReg = ${capFirstModel}LocalServiceUtil.get${capFirstModel}(entryId);
+
+ resReg = resReg.toEscapedModel();
+
+ tempResults.add(resReg);
+ }
+ catch (Exception e) {
+ if (_log.isWarnEnabled()) {
+ _log.warn(
+ "${capFirstModel} search index is stale and contains entry " +
+ entryId);
+ }
+
+ continue;
+ }
+ }
+
+ return new SearchContainerResults<>(tempResults, total);
+ }
+
+ /**
+ * Get Data list from Index
+ *
+ * @param request PortletRequest
+ * @return searchContainer SearchContainer>
+ * @throws SearchException
+ */
+ public SearchContainerResults<${capFirstModel}> getListFromIndex(
+ PortletRequest request, SearchContainer> searchContainer,
+ int state)
+ throws SearchException {
+
+ return getListFromIndex(
+ request, searchContainer.getStart(), searchContainer.getEnd(),
+ state);
+ }
+
+ /**
+ *
+ * Order Comparetor
+ *
+ * @param searchContainer
+ * @return OrderByComparator
+ */
+ public OrderByComparator<${capFirstModel}> getOrderByComparator(
+ SearchContainer> searchContainer) {
+
+ return getOrderByComparator(
+ searchContainer.getOrderByCol(), searchContainer.getOrderByType());
+ }
+
+ /**
+ *
+ * Order Comparetor
+ *
+ * @param orderByCol
+ * @param orderByType
+ * @return OrderByComparator
+ */
+ public OrderByComparator<${capFirstModel}> getOrderByComparator(
+ String orderByCol, String orderByType) {
+
+ if (_log.isDebugEnabled()) {
+ _log.debug(
+ "searchContainer.getOrderByCol()" +
+ (null != orderByCol ? orderByCol : "null"));
+ _log.debug(
+ "searchContainer.getOrderByType()" +
+ (null != orderByType ? orderByType : "null"));
+ }
+
+ return OrderByComparatorFactoryUtil.create(
+ "${capFirstModel}_${capFirstModel}", orderByCol, getOrder(orderByType));
+ }
+
+ /**
+ * Order string to boolean
+ *
+ * @param order
+ * @return if true if order is "asc" or false
+ */
+ protected boolean getOrder(String order) {
+ if ("asc".equalsIgnoreCase(order)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static Logger _log = LoggerFactory.getLogger(${capFirstModel}ViewHelper.class);
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_ViewMVCRenderCommand.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ViewMVCRenderCommand.java.ftl
new file mode 100644
index 0000000..602d8b5
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_ViewMVCRenderCommand.java.ftl
@@ -0,0 +1,97 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}ViewMVCRenderCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.asset.util.AssetHelper;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCRenderCommand;
+import com.liferay.portal.kernel.util.Portal;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.web.constants.${capFirstModel}WebKeys;
+import ${packageName}.web.internal.display.context.${capFirstModel}DisplayContext;
+import ${packageName}.web.util.${capFirstModel}ViewHelper;
+import com.liferay.trash.TrashHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalService;
+import ${packageName}.web.constants.${capFirstValidationModel}WebKeys;
+ #if>
+#list>
+// //
+
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "mvc.command.name=/", "mvc.command.name=/${lowercaseModel}/view"
+ },
+ service = MVCRenderCommand.class
+)
+public class ${capFirstModel}ViewMVCRenderCommand implements MVCRenderCommand {
+
+ @Override
+ public String render(RenderRequest request, RenderResponse response)
+ throws PortletException {
+
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_DISPLAY_CONTEXT,
+ new ${capFirstModel}DisplayContext(
+ _portal.getLiferayPortletRequest(request),
+ _portal.getLiferayPortletResponse(response), _trashHelper,
+ _${uncapFirstModel}ViewHelper));
+
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_VIEW_HELPER, _${uncapFirstModel}ViewHelper);
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+ request.setAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE, _${uncapFirstValidationModel}LocalService);
+ #if>
+#list>
+// //
+
+ return ${capFirstModel}WebKeys.VIEW_JSP;
+ }
+
+ @Reference
+ private AssetHelper _assetHelper;
+
+ @Reference
+ private Portal _portal;
+
+ @Reference
+ private ${capFirstModel}ViewHelper _${uncapFirstModel}ViewHelper;
+
+ @Reference
+ private TrashHelper _trashHelper;
+
+//<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ @Reference
+ private ${capFirstValidationModel}LocalService _${uncapFirstValidationModel}LocalService;
+ #if>
+#list>
+// //
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_WebKeys.java.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_WebKeys.java.ftl
new file mode 100644
index 0000000..1ebb844
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_WebKeys.java.ftl
@@ -0,0 +1,48 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/constants/${capFirstModel}WebKeys.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.constants;
+
+/**
+ * ${capFirstModel} Web Keys
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}WebKeys {
+
+ public static final String ADMIN_EDIT_JSP = "/${snakecaseModel}_admin/edit.jsp";
+
+ public static final String ADMIN_VIEW_JSP = "/${snakecaseModel}_admin/view.jsp";
+
+ public static final String ADMIN_VIEW_RECORD_JSP =
+ "/${snakecaseModel}_admin/view_record.jsp";
+
+ public static final String EDIT_JSP = "/${snakecaseModel}/edit.jsp";
+
+ public static final String ${uppercaseModel}_DISPLAY_CONTEXT =
+ "${uppercaseModel}_DISPLAY_CONTEXT";
+
+ public static final String ${uppercaseModel}_ITEM_SELECTOR_HELPER =
+ "${uppercaseModel}_ITEM_SELECTOR_HELPER";
+
+ public static final String ${uppercaseModel}_VIEW_HELPER = "${uppercaseModel}_VIEW_HELPER";
+
+ public static final String VIEW_JSP = "/${snakecaseModel}/view.jsp";
+
+ public static final String VIEW_RECORD_JSP = "/${snakecaseModel}/view_record.jsp";
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+ public static final String ${uppercaseValidationModel}_LOCAL_SERVICE =
+ "${uppercaseValidationModel}_LOCAL_SERVICE";
+ #if>
+#list>
+// //
+
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_abstract.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_abstract.jsp.ftl
new file mode 100644
index 0000000..cd34b59
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_abstract.jsp.ftl
@@ -0,0 +1,15 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/asset/abstract.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="/${snakecaseModel}/init.jsp" %>
+
+
+
+<%-- --%>
+<#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}() %>
+#if>
+<%-- --%>
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_abstract.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_abstract.jsp.ftl
new file mode 100644
index 0000000..c14f55d
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_abstract.jsp.ftl
@@ -0,0 +1,17 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/asset/abstract.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="../init.jsp" %>
+
+
+
+
+
+<%-- --%>
+<#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}() %>
+#if>
+<%-- --%>
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_edit.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_edit.jsp.ftl
new file mode 100644
index 0000000..857f5e2
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_edit.jsp.ftl
@@ -0,0 +1,360 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/edit.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+PortletURL portletURL = PortletURLUtil.clone(renderResponse.createRenderURL(), liferayPortletResponse);
+boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+String CMD = ParamUtil.getString(request, Constants.CMD, Constants.UPDATE);
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})request.getAttribute("${uncapFirstModel}");
+String redirect = ParamUtil.getString(request, "redirect");
+portletDisplay.setShowBackIcon(true);
+portletDisplay.setURLBack(redirect);
+
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<%-- --%>
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+ #if>
+<%-- --%>
+
+ <%
+ String requiredLabel = "";
+ %>
+
+<%-- --%>
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- primary key check -->
+ <#if field.primary?? && field.primary == true >
+ <#continue>
+ #if>
+ <#if field.required?? && field.required == true>
+ <%
+ requiredLabel = "*";
+ %>
+
+ <#else>
+ <%
+ requiredLabel = "";
+ %>
+ #if>
+
+ <#-- ---------------- -->
+ <#-- Long -->
+ <#-- Varchar -->
+ <#-- Date -->
+ <#-- DateTime -->
+ <#-- Boolean -->
+ <#-- Double -->
+ <#-- Integer -->
+ <#-- Text -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Double" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text"
+ >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+
+ <#assign fieldName = "PrimaryKey">
+ <#if field.validation.fieldName??>
+ <#assign fieldName = "${field.validation.fieldName?cap_first}">
+ #if>
+
+ <#assign orderByField = "PrimaryKey">
+ <#if field.validation.orderByField??>
+ <#assign orderByField = "${field.validation.orderByField?uncap_first}">
+ #if>
+ <%
+ ${capFirstValidationModel}ViewHelper ${uncapFirstValidationModel}ViewHelper = (${capFirstValidationModel}ViewHelper) request
+ .getAttribute(${capFirstValidationModel}WebKeys.${uppercaseValidationModel}_VIEW_HELPER);
+
+ SearchContainerResults<${capFirstValidationModel}> ${uncapFirstValidationModel}Results = ${uncapFirstValidationModel}ViewHelper.getListFromDB(
+ renderRequest, -1, -1, "${orderByField?uncap_first}", "asc", new int[] {WorkflowConstants.STATUS_APPROVED});
+ %>
+
+
+
+ <%=LanguageUtil.get(request, "please-select") %>
+ <% for(${capFirstValidationModel} ${uncapFirstValidationModel} : ${uncapFirstValidationModel}Results.getResults()) { %>
+ <%=${uncapFirstValidationModel}.get${orderByField?cap_first}() %>
+ <% } %>
+
+
+ <#else>
+
+ #if>
+ #if>
+ <#-- ---------------- -->
+ <#-- Document Library -->
+ <#-- ---------------- -->
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+
+ <%
+ String ${field.name}Click = renderResponse.getNamespace() + "dlBrowse('${field.name} Files select','" +
+ renderResponse.getNamespace()+"${field.name}')";
+ %>
+
+
+ #if>
+ <#-- ---------------- -->
+ <#-- RichText -->
+ <#-- ---------------- -->
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ ">
+
+
+
+ #if>
+ #list>
+<%-- --%>
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+
+
+
+
+
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0 && false == fromAsset) {
+ %>
+
+
+
+
+
+
+
+ <%
+ }
+ %>
+
+
+
+ <%
+ String publishButtonLabel = "submit";
+ %>
+
+ <%
+ if (WorkflowDefinitionLinkLocalServiceUtil
+ .hasWorkflowDefinitionLink(themeDisplay.getCompanyId(), scopeGroupId, ${capFirstModel}.class.getName())) {
+
+ publishButtonLabel = "submit-for-publication";
+ }
+ %>
+
+
+
+ <%
+ if (!fromAsset) {
+ %>
+
+ − −
+
+
+ <%
+ }
+ %>
+
+
+
+
+
+
+
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0 && false == fromAsset) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+
+ function init${field.name}Editor() {
+ return '<%=UnicodeFormatter.toString(${uncapFirstModel}.get${field.name?cap_first}())%>';
+ }
+
+ #if>
+#list>
+<%-- --%>
+
+
+ function saveEditors() {
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ document. ${lowercaseModel}Edit. ${field.name}.value =
+ window. ${field.name}Editor.getHTML();
+ #if>
+#list>
+<%-- --%>
+ submitForm(document. ${lowercaseModel}Edit);
+ }
+
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+<%
+${capFirstModel}ItemSelectorHelper ${uncapFirstModel}ItemSelectorHelper = (${capFirstModel}ItemSelectorHelper)request
+ .getAttribute(${capFirstModel}WebKeys.${uppercaseModel}_ITEM_SELECTOR_HELPER);
+RequestBackedPortletURLFactory requestBackedPortletURLFactory = RequestBackedPortletURLFactoryUtil
+ .create(liferayPortletRequest);
+String selectItemName = liferayPortletResponse.getNamespace()
+ + "selectItem";
+%>
+
+
+ function dlBrowse (title, inputField) {
+ var itemSrc = $('#'+inputField);
+ AUI().use(
+ 'liferay-item-selector-dialog',
+ function(A) {
+ var itemSelectorDialog = new A.LiferayItemSelectorDialog(
+ {
+ eventName: '<%= selectItemName %>',
+ on: {
+ selectedItemChange: function(event) {
+ var selectedItem = event.newVal;
+
+ if (selectedItem) {
+ var itemValue = JSON.parse(
+ selectedItem.value
+ );
+ itemSrc.val(itemValue.url);
+ }
+ }
+ },
+ title: title,
+ url: '<%= ${uncapFirstModel}ItemSelectorHelper.getItemSelectorURL(
+ requestBackedPortletURLFactory, themeDisplay, selectItemName) %>'
+ }
+ );
+ itemSelectorDialog.open();
+ }
+ );
+ }
+
+ <#break>
+ #if>
+#list>
+<%-- --%>
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_edit_actions.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_edit_actions.jsp.ftl
new file mode 100644
index 0000000..4ae946b
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_edit_actions.jsp.ftl
@@ -0,0 +1,99 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/edit_actions.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+PortletURL navigationPortletURL = renderResponse.createRenderURL();
+PortletURL portletURL = PortletURLUtil.clone(navigationPortletURL, liferayPortletResponse);
+
+ResultRow row = (ResultRow)request.getAttribute(WebKeys.SEARCH_CONTAINER_RESULT_ROW);
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})row.getObject();
+
+long groupId = ${uncapFirstModel}.getGroupId();
+String name = ${capFirstModel}.class.getName();
+String primKey = String.valueOf(${uncapFirstModel}.getPrimaryKey());
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_full_content.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_full_content.jsp.ftl
new file mode 100644
index 0000000..04f3112
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_full_content.jsp.ftl
@@ -0,0 +1,18 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/asset/full_content.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+
+<%@ include file="../init.jsp" %>
+
+
+
+
+
+<%-- --%>
+<#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}()
+#if>
+<%-- --%>
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_init.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_init.jsp.ftl
new file mode 100644
index 0000000..b9ed51a
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_init.jsp.ftl
@@ -0,0 +1,92 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/init.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
+
+<%@ taglib uri="http://liferay.com/tld/asset" prefix="liferay-asset" %><%@
+taglib uri="http://liferay.com/tld/aui" prefix="aui" %><%@
+taglib uri="http://liferay.com/tld/clay" prefix="clay" %><%@
+taglib uri="http://liferay.com/tld/comment" prefix="liferay-comment" %><%@
+taglib uri="http://liferay.com/tld/frontend" prefix="liferay-frontend" %><%@
+taglib uri="http://liferay.com/tld/item-selector" prefix="liferay-item-selector" %><%@
+taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %><%@
+taglib uri="http://liferay.com/tld/security" prefix="liferay-security" %><%@
+taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %><%@
+taglib uri="http://liferay.com/tld/trash" prefix="liferay-trash" %><%@
+taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %><%@
+taglib uri="http://liferay.com/tld/util" prefix="liferay-util" %>
+
+<%@ page import="com.liferay.asset.constants.AssetWebKeys" %><%@
+page import="com.liferay.asset.util.AssetHelper" %><%@
+page import="com.liferay.portal.kernel.dao.search.*" %><%@
+page import="com.liferay.portal.kernel.language.*" %><%@
+page import="com.liferay.portal.kernel.portlet.*" %><%@
+page import="com.liferay.portal.kernel.security.permission.ActionKeys" %><%@
+page import="com.liferay.portal.kernel.service.WorkflowDefinitionLinkLocalServiceUtil" %><%@
+page import="com.liferay.portal.kernel.util.*" %><%@
+page import="com.liferay.portal.kernel.workflow.*" %><%@
+page import="com.liferay.frontend.taglib.clay.servlet.taglib.util.JSPNavigationItemList" %><%@
+page import="${packageName}.model.${capFirstModel}" %><%@
+page import="${packageName}.web.constants.*" %><%@
+page import="${packageName}.web.constants.${capFirstModel}WebKeys" %><%@
+page import="${packageName}.web.internal.display.context.*" %><%@
+page import="${packageName}.web.internal.security.permission.resource.*" %><%@
+page import="${packageName}.web.portlet.action.${capFirstModel}Configuration" %><%@
+page import="${packageName}.web.upload.${capFirstModel}ItemSelectorHelper" %><%@
+page import="com.liferay.trash.TrashHelper" %><%@
+page import="com.liferay.trash.util.TrashWebKeys" %><%@
+page import="com.liferay.petra.string.StringPool" %>
+
+<%@ page import="javax.portlet.PortletPreferences" %>
+<%@ page import="java.text.SimpleDateFormat" %>
+<%@ page import="java.util.ArrayList" %>
+<%@ page import="java.util.Calendar"%>
+<%@ page import="java.util.Date" %>
+<%@ page import="java.util.List" %>
+<%@ page import="java.util.Map"%>
+
+<%@ page import="javax.portlet.PortletURL" %>
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+<%@page import="${packageName}.model.${field.validation.className}"%>
+<%@page import="${packageName}.web.constants.${field.validation.className}WebKeys"%>
+<%@page import="${packageName}.web.util.${field.validation.className}ViewHelper"%>
+<%@page import="${packageName}.service.${field.validation.className}LocalService"%>
+ #if>
+#list>
+<%-- --%>
+
+
+
+
+
+<%
+AssetHelper assetHelper = (AssetHelper)request.getAttribute(AssetWebKeys.ASSET_HELPER);
+TrashHelper trashHelper = (TrashHelper)request.getAttribute(TrashWebKeys.TRASH_HELPER);
+
+${capFirstModel}Configuration ${uncapFirstModel}Configuration =
+(${capFirstModel}Configuration)
+ renderRequest.getAttribute(${capFirstModel}Configuration.class.getName());
+
+String prefsViewType = StringPool.BLANK;
+String dateFormatVal = StringPool.BLANK;
+String datetimeFormatVal = StringPool.BLANK;
+String datePickerFormatVal = StringPool.BLANK;
+
+if (Validator.isNotNull(${uncapFirstModel}Configuration)) {
+prefsViewType = HtmlUtil.escape(portletPreferences.getValue("prefsViewType", String.valueOf(${uncapFirstModel}Configuration.prefsViewType())));
+
+dateFormatVal = HtmlUtil.escape(portletPreferences.getValue("dateFormat", ${uncapFirstModel}Configuration.dateFormat()));
+
+datetimeFormatVal = HtmlUtil.escape(portletPreferences.getValue("datetimeFormat", ${uncapFirstModel}Configuration.datetimeFormat()));
+
+datePickerFormatVal = HtmlUtil.escape(portletPreferences.getValue("datePickerFormat", ${uncapFirstModel}Configuration.datePickerFormat()));
+}
+%>
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_main.css.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_main.css.ftl
new file mode 100644
index 0000000..b14a30d
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_main.css.ftl
@@ -0,0 +1,6 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/css/main.css">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_view.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_view.jsp.ftl
new file mode 100644
index 0000000..d1bd56b
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_view.jsp.ftl
@@ -0,0 +1,216 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/view.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+String iconChecked = "checked";
+String iconUnchecked = "unchecked";
+SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatVal);
+SimpleDateFormat dateTimeFormat = new SimpleDateFormat(datetimeFormatVal);
+
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+${capFirstValidationModel}LocalService ${uncapFirstValidationModel}LocalService = (${capFirstValidationModel}LocalService) request
+.getAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE);
+ #if>
+#list>
+
+${capFirstModel}DisplayContext ${uncapFirstModel}DisplayContext = (${capFirstModel}DisplayContext)request.getAttribute(${capFirstModel}WebKeys.${uppercaseModel}_DISPLAY_CONTEXT);
+
+String displayStyle = ${uncapFirstModel}DisplayContext.getDisplayStyle();
+SearchContainer entriesSearchContainer = ${uncapFirstModel}DisplayContext.getSearchContainer();
+
+PortletURL portletURL = entriesSearchContainer.getIteratorURL();
+
+${capFirstModel}ManagementToolbarDisplayContext ${uncapFirstModel}ManagementToolbarDisplayContext = new ${capFirstModel}ManagementToolbarDisplayContext(liferayPortletRequest, liferayPortletResponse, request, entriesSearchContainer, trashHelper, displayStyle);
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<%-- --%>
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- ---------------- -->
+ <#-- Long -->
+ <#-- Varchar -->
+ <#-- Boolean -->
+ <#-- Double -->
+ <#-- Document Library -->
+ <#-- Integer -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Double" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer"
+ >
+
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+
+ <#assign fieldName = "PrimaryKey">
+ <#if field.validation.fieldName??>
+ <#assign fieldName = "${field.validation.fieldName?cap_first}">
+ #if>
+
+ <#assign orderByField = "PrimaryKey">
+ <#if field.validation.orderByField??>
+ <#assign orderByField = "${field.validation.orderByField?cap_first}">
+ #if>
+ <%
+ String ${field.name}Text = "";
+ try {
+ ${capFirstValidationModel} ${uncapFirstValidationModel} = ${uncapFirstValidationModel}LocalService.get${capFirstValidationModel}(GetterUtil.getLong(${uncapFirstModel}.get${field.name?cap_first}()));
+ ${field.name}Text = ${uncapFirstValidationModel}.get${orderByField}();
+ } catch(Exception e) {}
+ %>
+
+ <#else>
+
+ #if>
+ #if>
+ <#-- ---------------- -->
+ <#-- Date -->
+ <#-- DateTime -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime"
+ >
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- RichText -->
+ <#-- Text -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.RichText" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text"
+ >
+
+ <%
+ String ${field.name}Icon = iconUnchecked;
+ String ${field.name} = ${uncapFirstModel}.get${field.name?cap_first}();
+ if (!${field.name}.equals("")) {
+ ${field.name}Icon= iconChecked;
+ }
+ %>
+
+
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+<%-- --%>
+
+
+
+
+
+
+
+
+
+
+ function deleteEntries() {
+ if (<%=trashHelper.isTrashEnabled(scopeGroupId) %> || confirm('<%=UnicodeLanguageUtil.get(request, "are-you-sure-you-want-to-delete-the-selected-entries") %>')) {
+ var form = AUI.$(document. fm);
+
+ form.attr('method', 'post');
+ form.fm('<%=Constants.CMD%>').val('<%=trashHelper.isTrashEnabled(scopeGroupId) ? Constants.MOVE_TO_TRASH : Constants.DELETE%>');
+ form.fm('deleteEntryIds').val(Liferay.Util.listCheckedExcept(form, ' allRowIds'));
+
+ submitForm(form, ' ');
+ }
+ }
+
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_view_record.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_view_record.jsp.ftl
new file mode 100644
index 0000000..2666fd2
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_admin_view_record.jsp.ftl
@@ -0,0 +1,91 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/view_record.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})request.getAttribute("${uncapFirstModel}");
+String redirect = ParamUtil.getString(request, "redirect");
+boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+portletDisplay.setShowBackIcon(true);
+portletDisplay.setURLBack(redirect);
+
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+${capFirstValidationModel}LocalService ${uncapFirstValidationModel}LocalService = (${capFirstValidationModel}LocalService) request
+.getAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE);
+ #if>
+#list>
+%>
+
+
+
+
+
+
+<%-- --%>
+
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop end -->
+ <#-- ---------------- -->
+<%-- --%>
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_bnd.bnd.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_bnd.bnd.ftl
new file mode 100644
index 0000000..8127acf
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_bnd.bnd.ftl
@@ -0,0 +1,26 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/bnd.bnd">
+<#assign skipTemplate = !generateWeb>
+# #
+Bundle-Name: ${dashcaseProjectName}-web
+Bundle-SymbolicName: ${packageName}.web
+Bundle-Version: 1.0.0
+Import-Package:\
+ !com.google.*,\
+ !com.graphbuilder.*,\
+ !com.microsoft.*,\
+ !org.apache.*,\
+ !org.bouncycastle.*,\
+ !org.etsi.uri.*,\
+ !org.openxmlformats.*,\
+ !com.zaxxer.*,\
+ *
+Web-ContextPath: /${dashcaseProjectName}-web
+-dsannotations-options: inherit
+-includeresource:\
+ @poi-*.jar,\
+ @poi-ooxml-*.jar,\
+ @poi-ooxml-schemas-*.jar
+-metatype: *
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_build.gradle.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_build.gradle.ftl
new file mode 100644
index 0000000..92e86ef
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_build.gradle.ftl
@@ -0,0 +1,53 @@
+//
+// //
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/build.gradle">
+<#assign skipTemplate = !generateWeb>
+// //
+apply plugin: 'java'
+apply plugin: 'groovy'
+apply plugin: 'idea'
+apply plugin: 'eclipse'
+
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
+
+//Need for Windows
+def defaultEncoding = 'UTF-8'
+
+dependencies {
+ compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.5.0"
+ compile group: "org.apache.poi", name: "poi"<#if useTP?? && false == useTP>, version: "4.1.2"#if>
+ compile group: "org.apache.poi", name: "poi-ooxml"<#if useTP?? && false == useTP>, version: "4.1.2"#if>
+ compile group: "org.apache.poi", name: "poi-ooxml-schemas"<#if useTP?? && false == useTP>, version: "4.1.2"#if>
+
+ compileOnly group: "com.liferay", name: "com.liferay.application.list.api"<#if useTP?? && false == useTP>, version: "5.1.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.api"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.api"<#if useTP?? && false == useTP>, version: "6.3.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.item.selector.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.info.display.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.taglib"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.comment.taglib"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.clay"<#if useTP?? && false == useTP>, version: "3.5.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.soy"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.util"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.info.api"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.api"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.criteria.api"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.taglib"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.reflect"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.string"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.function"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.trash.api"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "7.2.0"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.util.taglib"<#if useTP?? && false == useTP>, version: "5.1.0"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet.jsp", name: "jsp-api"<#if useTP?? && false == useTP>, version: "2.1"#if>
+ compileOnly group: "jstl", name: "jstl"<#if useTP?? && false == useTP>, version: "1.2"#if>
+ compileOnly group: "org.apache.felix", name: "org.apache.felix.http.servlet-api", version: "1.1.+"
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
+ compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.+'
+ compileOnly project(":${dashcaseProjectName}-api")
+ compileOnly project(":${dashcaseProjectName}-service")
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_configuration.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_configuration.jsp.ftl
new file mode 100644
index 0000000..78094b8
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_configuration.jsp.ftl
@@ -0,0 +1,47 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/configuration.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+<%@ page contentType="text/html; charset=UTF-8" %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_default.xml.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_default.xml.ftl
new file mode 100644
index 0000000..ad745b0
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_default.xml.ftl
@@ -0,0 +1,74 @@
+
+
+
+
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/resource-actions/default.xml">
+<#assign skipTemplate = !generateWeb>
+
+
+
+<#list damascus.applications as app >
+
+ ${packageSnake}_web_${app.model?cap_first}Portlet
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ PERMISSIONS
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ VIEW
+
+
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ PERMISSIONS
+
+
+
+
+ ${packageSnake}_web_${app.model?cap_first}AdminPortlet
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ PERMISSIONS
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ VIEW
+
+
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ PERMISSIONS
+
+
+
+#list>
+
+
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_edit.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_edit.jsp.ftl
new file mode 100644
index 0000000..0334fa6
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_edit.jsp.ftl
@@ -0,0 +1,370 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/edit.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+ PortletURL portletURL = PortletURLUtil.clone(renderResponse.createRenderURL(), liferayPortletResponse);
+ boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+ String CMD = ParamUtil.getString(request, Constants.CMD, Constants.UPDATE);
+ ${capFirstModel} ${uncapFirstModel} = (${capFirstModel})request.getAttribute("${uncapFirstModel}");
+ String redirect = ParamUtil.getString(request, "redirect");
+ portletDisplay.setShowBackIcon(true);
+ portletDisplay.setURLBack(redirect);
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <%
+
+ //This tag is only necessary in Asset publisher
+
+ if (fromAsset) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+
+
+<%--
--%>
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+ #if>
+<%-- --%>
+
+ <%
+ String requiredLabel = "";
+ %>
+<%--
--%>
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- primary key check -->
+ <#if field.primary?? && field.primary == true >
+ <#continue>
+ #if>
+ <#if field.required?? && field.required == true>
+ <%
+ requiredLabel = "*";
+ %>
+
+ <#else>
+ <%
+ requiredLabel = "";
+ %>
+ #if>
+
+ <#-- ---------------- -->
+ <#-- Long -->
+ <#-- Varchar -->
+ <#-- Date -->
+ <#-- DateTime -->
+ <#-- Boolean -->
+ <#-- Double -->
+ <#-- Integer -->
+ <#-- Text -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Double" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text"
+ >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+
+ <#assign fieldName = "PrimaryKey">
+ <#if field.validation.fieldName??>
+ <#assign fieldName = "${field.validation.fieldName?cap_first}">
+ #if>
+
+ <#assign orderByField = "PrimaryKey">
+ <#if field.validation.orderByField??>
+ <#assign orderByField = "${field.validation.orderByField?uncap_first}">
+ #if>
+ <%
+ ${capFirstValidationModel}ViewHelper ${uncapFirstValidationModel}ViewHelper = (${capFirstValidationModel}ViewHelper) request
+ .getAttribute(${capFirstValidationModel}WebKeys.${uppercaseValidationModel}_VIEW_HELPER);
+
+ SearchContainerResults<${capFirstValidationModel}> ${uncapFirstValidationModel}Results = ${uncapFirstValidationModel}ViewHelper.getListFromDB(
+ renderRequest, -1, -1, "${orderByField?uncap_first}", "asc", new int[] {WorkflowConstants.STATUS_APPROVED});
+ %>
+
+
+
+ <%=LanguageUtil.get(request, "please-select") %>
+ <% for(${capFirstValidationModel} ${uncapFirstValidationModel} : ${uncapFirstValidationModel}Results.getResults()) { %>
+ <%=${uncapFirstValidationModel}.get${orderByField?cap_first}() %>
+ <% } %>
+
+
+ <#else>
+
+ #if>
+ #if>
+ <#-- ---------------- -->
+ <#-- Document Library -->
+ <#-- ---------------- -->
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+
+ <%
+ String ${field.name}Click = renderResponse.getNamespace() + "dlBrowse('${field.name} Files select','" +
+ renderResponse.getNamespace()+"${field.name}')";
+ %>
+
+
+ #if>
+ <#-- ---------------- -->
+ <#-- RichText -->
+ <#-- ---------------- -->
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ ">
+
+
+
+ #if>
+ #list>
+<%-- --%>
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+
+
+
+
+
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0 && false == fromAsset) {
+ %>
+
+
+
+
+
+
+
+ <%
+ }
+ %>
+
+ <%
+
+ //This tag is only necessary in Asset publisher
+
+ if (fromAsset) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+ <%
+ String publishButtonLabel = "submit";
+ %>
+
+ <%
+ if (WorkflowDefinitionLinkLocalServiceUtil
+ .hasWorkflowDefinitionLink(themeDisplay.getCompanyId(), scopeGroupId, ${capFirstModel}.class.getName())) {
+
+ publishButtonLabel = "submit-for-publication";
+ }
+ %>
+
+
+
+ <%
+ if (!fromAsset) {
+ %>
+
+ − −
+
+
+ <%
+ }
+ %>
+
+
+
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0 && false == fromAsset) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+
+ function init${field.name}Editor() {
+ return '<%=UnicodeFormatter.toString(${uncapFirstModel}.get${field.name?cap_first}())%>';
+ }
+
+ #if>
+#list>
+<%-- --%>
+
+
+ function saveEditors() {
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ document. ${lowercaseModel}Edit. ${field.name}.value =
+ window. ${field.name}Editor.getHTML();
+ #if>
+#list>
+<%-- --%>
+ submitForm(document. ${lowercaseModel}Edit);
+ }
+
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+<%
+${capFirstModel}ItemSelectorHelper ${uncapFirstModel}ItemSelectorHelper = (${capFirstModel}ItemSelectorHelper)request
+ .getAttribute(${capFirstModel}WebKeys.${uppercaseModel}_ITEM_SELECTOR_HELPER);
+RequestBackedPortletURLFactory requestBackedPortletURLFactory = RequestBackedPortletURLFactoryUtil
+ .create(liferayPortletRequest);
+String selectItemName = liferayPortletResponse.getNamespace()
+ + "selectItem";
+%>
+
+
+ function dlBrowse (title, inputField) {
+ var itemSrc = $('#'+inputField);
+ AUI().use(
+ 'liferay-item-selector-dialog',
+ function(A) {
+ var itemSelectorDialog = new A.LiferayItemSelectorDialog(
+ {
+ eventName: '<%= selectItemName %>',
+ on: {
+ selectedItemChange: function(event) {
+ var selectedItem = event.newVal;
+
+ if (selectedItem) {
+ var itemValue = JSON.parse(
+ selectedItem.value
+ );
+ itemSrc.val(itemValue.url);
+ }
+ }
+ },
+ title: title,
+ url: '<%= ${uncapFirstModel}ItemSelectorHelper.getItemSelectorURL(
+ requestBackedPortletURLFactory, themeDisplay, selectItemName) %>'
+ }
+ );
+ itemSelectorDialog.open();
+ }
+ );
+ }
+
+ <#break>
+ #if>
+#list>
+<%-- --%>
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_edit_actions.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_edit_actions.jsp.ftl
new file mode 100644
index 0000000..97bb94d
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_edit_actions.jsp.ftl
@@ -0,0 +1,99 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/edit_actions.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+PortletURL navigationPortletURL = renderResponse.createRenderURL();
+PortletURL portletURL = PortletURLUtil.clone(navigationPortletURL, liferayPortletResponse);
+
+ResultRow row = (ResultRow)request.getAttribute(WebKeys.SEARCH_CONTAINER_RESULT_ROW);
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})row.getObject();
+
+long groupId = ${uncapFirstModel}.getGroupId();
+String name = ${capFirstModel}.class.getName();
+String primKey = String.valueOf(${uncapFirstModel}.getPrimaryKey());
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_full_content.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_full_content.jsp.ftl
new file mode 100644
index 0000000..d074b86
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_full_content.jsp.ftl
@@ -0,0 +1,15 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/asset/full_content.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="/${snakecaseModel}/init.jsp" %>
+
+
+
+<%-- --%>
+<#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}()
+#if>
+<%-- --%>
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_init.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_init.jsp.ftl
new file mode 100644
index 0000000..953f36f
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_init.jsp.ftl
@@ -0,0 +1,91 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/init.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
+
+<%@ taglib uri="http://liferay.com/tld/asset" prefix="liferay-asset" %><%@
+taglib uri="http://liferay.com/tld/aui" prefix="aui" %><%@
+taglib uri="http://liferay.com/tld/clay" prefix="clay" %><%@
+taglib uri="http://liferay.com/tld/comment" prefix="liferay-comment" %><%@
+taglib uri="http://liferay.com/tld/frontend" prefix="liferay-frontend" %><%@
+taglib uri="http://liferay.com/tld/item-selector" prefix="liferay-item-selector" %><%@
+taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %><%@
+taglib uri="http://liferay.com/tld/security" prefix="liferay-security" %><%@
+taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %><%@
+taglib uri="http://liferay.com/tld/trash" prefix="liferay-trash" %><%@
+taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %><%@
+taglib uri="http://liferay.com/tld/util" prefix="liferay-util" %>
+
+<%@ page import="com.liferay.asset.constants.AssetWebKeys" %><%@
+page import="com.liferay.asset.util.AssetHelper" %><%@
+page import="com.liferay.portal.kernel.dao.search.*" %><%@
+page import="com.liferay.portal.kernel.language.*" %><%@
+page import="com.liferay.portal.kernel.portlet.*" %><%@
+page import="com.liferay.portal.kernel.security.permission.ActionKeys" %><%@
+page import="com.liferay.portal.kernel.service.WorkflowDefinitionLinkLocalServiceUtil" %><%@
+page import="com.liferay.portal.kernel.util.*" %><%@
+page import="com.liferay.portal.kernel.workflow.*" %><%@
+page import="${packageName}.model.${capFirstModel}" %><%@
+page import="${packageName}.web.constants.*" %><%@
+page import="${packageName}.web.constants.${capFirstModel}WebKeys" %><%@
+page import="${packageName}.web.internal.display.context.*" %><%@
+page import="${packageName}.web.internal.security.permission.resource.*" %><%@
+page import="${packageName}.web.portlet.action.${capFirstModel}Configuration" %><%@
+page import="${packageName}.web.upload.${capFirstModel}ItemSelectorHelper" %><%@
+page import="com.liferay.trash.TrashHelper" %><%@
+page import="com.liferay.trash.util.TrashWebKeys" %><%@
+page import="com.liferay.petra.string.StringPool" %>
+
+<%@ page import="javax.portlet.PortletPreferences" %>
+<%@ page import="java.text.SimpleDateFormat" %>
+<%@ page import="java.util.ArrayList" %>
+<%@ page import="java.util.Calendar"%>
+<%@ page import="java.util.Date" %>
+<%@ page import="java.util.List" %>
+<%@ page import="java.util.Map"%>
+
+<%@ page import="javax.portlet.PortletURL" %>
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+<%@page import="${packageName}.model.${field.validation.className}"%>
+<%@page import="${packageName}.web.constants.${field.validation.className}WebKeys"%>
+<%@page import="${packageName}.web.util.${field.validation.className}ViewHelper"%>
+<%@page import="${packageName}.service.${field.validation.className}LocalService"%>
+ #if>
+#list>
+<%-- --%>
+
+
+
+
+
+<%
+AssetHelper assetHelper = (AssetHelper)request.getAttribute(AssetWebKeys.ASSET_HELPER);
+TrashHelper trashHelper = (TrashHelper)request.getAttribute(TrashWebKeys.TRASH_HELPER);
+
+${capFirstModel}Configuration ${uncapFirstModel}Configuration =
+(${capFirstModel}Configuration)
+ renderRequest.getAttribute(${capFirstModel}Configuration.class.getName());
+
+String prefsViewType = StringPool.BLANK;
+String dateFormatVal = StringPool.BLANK;
+String datetimeFormatVal = StringPool.BLANK;
+String datePickerFormatVal = StringPool.BLANK;
+
+if (Validator.isNotNull(${uncapFirstModel}Configuration)) {
+prefsViewType = HtmlUtil.escape(portletPreferences.getValue("prefsViewType", String.valueOf(${uncapFirstModel}Configuration.prefsViewType())));
+
+dateFormatVal = HtmlUtil.escape(portletPreferences.getValue("dateFormat", ${uncapFirstModel}Configuration.dateFormat()));
+
+datetimeFormatVal = HtmlUtil.escape(portletPreferences.getValue("datetimeFormat", ${uncapFirstModel}Configuration.datetimeFormat()));
+
+datePickerFormatVal = HtmlUtil.escape(portletPreferences.getValue("datePickerFormat", ${uncapFirstModel}Configuration.datePickerFormat()));
+}
+%>
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_main.css.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_main.css.ftl
new file mode 100644
index 0000000..06c9573
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_main.css.ftl
@@ -0,0 +1,6 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/css/main.css">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_portlet.properties.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_portlet.properties.ftl
new file mode 100644
index 0000000..6392dac
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_portlet.properties.ftl
@@ -0,0 +1,15 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/portlet.properties">
+<#assign skipTemplate = !generateWeb>
+# #
+include-and-override=portlet-ext.properties
+
+language.bundle=content.Language
+
+#
+# Input a list of comma delimited resource action configurations that will be
+# read from the class path.
+#
+resource.actions.configs=resource-actions/default.xml
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_preview.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_preview.jsp.ftl
new file mode 100644
index 0000000..34a96ee
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_preview.jsp.ftl
@@ -0,0 +1,11 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/asset/preview.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="/${snakecaseModel}/init.jsp" %>
+
+
+
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}() %>
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_routes.xml.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_routes.xml.ftl
new file mode 100644
index 0000000..21fcd51
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_routes.xml.ftl
@@ -0,0 +1,54 @@
+
+
+
+
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/friendly-url-routes/routes.xml">
+<#assign skipTemplate = !generateWeb>
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_view.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_view.jsp.ftl
new file mode 100644
index 0000000..81bc20c
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_view.jsp.ftl
@@ -0,0 +1,196 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/view.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+String iconChecked = "checked";
+String iconUnchecked = "unchecked";
+SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatVal);
+SimpleDateFormat dateTimeFormat = new SimpleDateFormat(datetimeFormatVal);
+
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+${capFirstValidationModel}LocalService ${uncapFirstValidationModel}LocalService = (${capFirstValidationModel}LocalService) request
+.getAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE);
+ #if>
+#list>
+
+${capFirstModel}DisplayContext ${uncapFirstModel}DisplayContext = (${capFirstModel}DisplayContext)request.getAttribute(${capFirstModel}WebKeys.${uppercaseModel}_DISPLAY_CONTEXT);
+
+String displayStyle = ${uncapFirstModel}DisplayContext.getDisplayStyle();
+SearchContainer entriesSearchContainer = ${uncapFirstModel}DisplayContext.getSearchContainer();
+
+PortletURL portletURL = entriesSearchContainer.getIteratorURL();
+
+${capFirstModel}ManagementToolbarDisplayContext ${uncapFirstModel}ManagementToolbarDisplayContext = new ${capFirstModel}ManagementToolbarDisplayContext(liferayPortletRequest, liferayPortletResponse, request, entriesSearchContainer, trashHelper, displayStyle);
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<%-- --%>
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- ---------------- -->
+ <#-- Long -->
+ <#-- Varchar -->
+ <#-- Boolean -->
+ <#-- Double -->
+ <#-- Document Library -->
+ <#-- Integer -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Double" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer"
+ >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+
+ <#assign fieldName = "PrimaryKey">
+ <#if field.validation.fieldName??>
+ <#assign fieldName = "${field.validation.fieldName?cap_first}">
+ #if>
+
+ <#assign orderByField = "PrimaryKey">
+ <#if field.validation.orderByField??>
+ <#assign orderByField = "${field.validation.orderByField?cap_first}">
+ #if>
+ <%
+ String ${field.name}Text = "";
+ try {
+ ${capFirstValidationModel} ${uncapFirstValidationModel} = ${uncapFirstValidationModel}LocalService.get${capFirstValidationModel}(GetterUtil.getLong(${uncapFirstModel}.get${field.name?cap_first}()));
+ ${field.name}Text = ${uncapFirstValidationModel}.get${orderByField}();
+ } catch(Exception e) {}
+ %>
+
+ <#else>
+
+ #if>
+ #if>
+ <#-- ---------------- -->
+ <#-- Date -->
+ <#-- DateTime -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime"
+ >
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- RichText -->
+ <#-- Text -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.RichText" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text"
+ >
+
+ <%
+ String ${field.name}Icon = iconUnchecked;
+ String ${field.name} = ${uncapFirstModel}.get${field.name?cap_first}();
+ if (!${field.name}.equals("")) {
+ ${field.name}Icon= iconChecked;
+ }
+ %>
+
+
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+<%-- --%>
+
+
+
+
+
+
+
+
+
+ function deleteEntries() {
+ if (<%=trashHelper.isTrashEnabled(scopeGroupId) %> || confirm('<%=UnicodeLanguageUtil.get(request, "are-you-sure-you-want-to-delete-the-selected-entries") %>')) {
+ var form = AUI.$(document. fm);
+
+ form.attr('method', 'post');
+ form.fm('<%=Constants.CMD%>').val('<%=trashHelper.isTrashEnabled(scopeGroupId) ? Constants.MOVE_TO_TRASH : Constants.DELETE%>');
+ form.fm('deleteEntryIds').val(Liferay.Util.listCheckedExcept(form, ' allRowIds'));
+
+ submitForm(form, ' ');
+ }
+ }
+
diff --git a/src/main/resources/templates/7.3/Portlet_XXXXWEB_view_record.jsp.ftl b/src/main/resources/templates/7.3/Portlet_XXXXWEB_view_record.jsp.ftl
new file mode 100644
index 0000000..fc209a5
--- /dev/null
+++ b/src/main/resources/templates/7.3/Portlet_XXXXWEB_view_record.jsp.ftl
@@ -0,0 +1,83 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/view_record.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})request.getAttribute("${uncapFirstModel}");
+String redirect = ParamUtil.getString(request, "redirect");
+boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+portletDisplay.setShowBackIcon(true);
+portletDisplay.setURLBack(redirect);
+
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+${capFirstValidationModel}LocalService ${uncapFirstValidationModel}LocalService = (${capFirstValidationModel}LocalService) request
+.getAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE);
+ #if>
+#list>
+%>
+
+
+
+<%-- --%>
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop end -->
+ <#-- ---------------- -->
+<%-- --%>
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/7.3/base.json b/src/main/resources/templates/7.3/base.json
new file mode 100644
index 0000000..9cd3602
--- /dev/null
+++ b/src/main/resources/templates/7.3/base.json
@@ -0,0 +1,87 @@
+{
+ "projectName": "${damascus.projectName}",
+ "packageName" : "${damascus.packageName}",
+ "liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
+ "applications": [
+ {
+ "model" : "${damascus.entityName}",
+ "title" : "${damascus.projectName} Test",
+ "web" : "true",
+ "asset": {
+ "assetTitleFieldName": "${damascus.entityNameLower}TitleName",
+ "assetSummaryFieldName": "${damascus.entityNameLower}SummaryName",
+ "categories": "true",
+ "discussion": "true",
+ "ratings": "true",
+ "tags": "true",
+ "relatedAssets": "true",
+ "fullContentFieldName": "${damascus.entityNameLower}fullContent",
+ "workflow": "true",
+ "generateActivity": "true",
+ "trash":"true",
+ "advancedSearch": "true",
+ "exportExcel": "true"
+ },
+ "fields": [
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "primary":true,
+ "name": "${damascus.entityNameLower}Id",
+ "title": "${damascus.projectName} Id",
+ "showFieldInView": "false",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Varchar",
+ "name": "title",
+ "title": "Title",
+ "length": "80",
+ "showFieldInView": "true",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Boolean",
+ "name": "${damascus.entityNameLower}BooleanStat",
+ "title": "${damascus.projectName} Boolean Stat"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.DateTime",
+ "name": "${damascus.entityNameLower}DateTime",
+ "title": "${damascus.projectName} DateTime"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.DocumentLibrary",
+ "name": "${damascus.entityNameLower}DocumentLibrary",
+ "title": "${damascus.projectName} DocumentLibrary"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Double",
+ "name": "${damascus.entityNameLower}Double",
+ "title": "${damascus.projectName} Double"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Integer",
+ "name": "${damascus.entityNameLower}Integer",
+ "title": "${damascus.projectName} Integer"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.RichText",
+ "name": "${damascus.entityNameLower}RichText",
+ "title": "${damascus.projectName} RichText"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Text",
+ "name": "${damascus.entityNameLower}Text",
+ "title": "${damascus.projectName} Text"
+ }
+ ],
+ "customValue" : {
+ "your_own_id" : "your_custom_value_for_template_here"
+ },
+ "replacements" : {
+ "original_string_to_be_replaced" : "replacement_string"
+ }
+ }
+ ]
+}
diff --git a/src/main/resources/templates/7.3/license.ftl b/src/main/resources/templates/7.3/license.ftl
new file mode 100644
index 0000000..69a69b8
--- /dev/null
+++ b/src/main/resources/templates/7.3/license.ftl
@@ -0,0 +1,13 @@
+/**
+* Copyright (C) ${.now?date?string.yyyy} Yasuyuki Takeo All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*/
diff --git a/src/main/resources/templates/7.3/service.xml b/src/main/resources/templates/7.3/service.xml
new file mode 100644
index 0000000..ae7ca10
--- /dev/null
+++ b/src/main/resources/templates/7.3/service.xml
@@ -0,0 +1,148 @@
+
+
+
+
+<#include "./valuables.ftl">
+<#assign createPath = "${createPath_val}/service.xml">
+
+
+
+ "${damascus_author}"
+ ${camelcaseProjectName}
+
+ <#list damascus.applications as app>
+
+
+
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list app.fields as field >
+ <#if field.primary?? && field.primary == true >
+
+ #if>
+ primary="true"#if> />
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+
+
+
+
+
+
+
+
+
+
+
+ <#-- ---------------- -->
+ <#-- Asset Commons -->
+ <#-- ---------------- -->
+ <#if app.asset?? >
+
+
+
+
+
+ <#-- ---------------- -->
+ <#-- Workflow -->
+ <#-- ---------------- -->
+ <#if app.asset.workflow?? && true == app.asset.workflow >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #if>
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- Asset related -->
+ <#-- ---------------- -->
+ <#if app.asset?? >
+
+
+
+
+
+
+
+
+ #if>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <#-- ---------------- -->
+ <#-- Fields Finders -->
+ <#-- ---------------- -->
+ <#list app.fields as field >
+
+
+
+ #list>
+
+
+
+
+
+
+
+
+
+
+ #list>
+
+ <#list damascus.applications as app >
+ NoSuch${app.model}
+ ${app.model?cap_first}Validate
+ #list>
+
+
+
+
diff --git a/src/main/resources/templates/7.3/valuables.ftl b/src/main/resources/templates/7.3/valuables.ftl
new file mode 100644
index 0000000..728c8cb
--- /dev/null
+++ b/src/main/resources/templates/7.3/valuables.ftl
@@ -0,0 +1,43 @@
+<#assign void><#-- Just to prevent unexpected whitespace or line breaks -->
+
+<#assign packageName = "${damascus.packageName}">
+<#assign packagePath = "${packageName?replace(\".\", \"/\")}">
+<#assign packageSnake = "${packageName?replace(\".\", \"_\")}">
+<#assign useTP = damascus.isUseTargetPlatform() >
+
+<#assign camelcaseProjectName = "${damascus.projectName?replace(\"-\", \"\")}">
+<#assign dashcaseProjectName = "${caseUtil.camelCaseToDashCase(camelcaseProjectName)}">
+<#assign projectPath = "${createPath_val}/${dashcaseProjectName}">
+<#assign apiModulePath = "${projectPath}/${dashcaseProjectName}-api">
+<#assign serviceModulePath = "${projectPath}/${dashcaseProjectName}-service">
+<#assign webModulePath = "${projectPath}/${dashcaseProjectName}-web">
+
+<#if application?exists>
+<#assign capFirstModel = "${application.model?cap_first}">
+<#assign uncapFirstModel = "${application.model?uncap_first}">
+<#assign lowercaseModel = "${application.model?lower_case}">
+<#assign uppercaseModel = "${application.model?upper_case}">
+<#assign snakecaseModel = "${caseUtil.camelCaseToSnakeCase(application.model)}">
+
+<#assign categories = application.asset?exists && application.asset.categories>
+<#assign discussion = application.asset?exists && application.asset.discussion>
+<#assign advancedSearch = application.asset?exists && application.asset.advancedSearch>
+<#assign exportExcel = application.asset?exists && application.asset.exportExcel>
+<#assign ratings = application.asset?exists && application.asset.ratings>
+<#assign tags = application.asset?exists && application.asset.tags>
+<#assign relatedAssets = application.asset?exists && application.asset.relatedAssets>
+<#assign generateActivity = application.asset?exists && application.asset.generateActivity>
+<#assign generateWeb = application.web?exists && application.web>
+<#assign anyGeneratedWeb = damascus.isWebExist()>
+
+<#assign entityWebResourcesPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}">
+
+<#assign primaryKeyParam = "">
+<#list application.fields as field >
+ <#if field.primary?? && field.primary == true >
+ <#assign primaryKeyParam = "${field.name}">
+ #if>
+#list>
+#if>
+
+#assign>
diff --git a/src/test/groovy/com/liferay/damascus/cli/CreateCommandTest.groovy b/src/test/groovy/com/liferay/damascus/cli/CreateCommandTest.groovy
index 6c7040c..d9e28e1 100644
--- a/src/test/groovy/com/liferay/damascus/cli/CreateCommandTest.groovy
+++ b/src/test/groovy/com/liferay/damascus/cli/CreateCommandTest.groovy
@@ -207,7 +207,7 @@ class CreateCommandTest extends Specification {
//Target path map of a project
def pathMap = TestUtils.getPathMap(expectedProjectDirName)
- def checkLoop = getCheckLoop(expectedProjectDirName);
+ def checkLoop = getCheckLoop(expectedProjectDirName, liferayVersion);
then:
//*-service / *-api
@@ -232,10 +232,75 @@ class CreateCommandTest extends Specification {
}
- def getCheckLoop(expectedProjectDirName) {
+ def getCheckLoop(expectedProjectDirName, liferayVersion) {
def pathMap = TestUtils.getPathMap(expectedProjectDirName)
+ // if liferayVersion = 7.2
+ if (liferayVersion.equals(DamascusProps.VERSION_72)) {
+
+ return [
+ [path: pathMap["apiPath"], target: ".*bnd.bnd", amount: 1],
+ [path: pathMap["apiPath"], target: ".*build.gradle", amount: 1],
+ [path: pathMap["apiPath"], target: ".*PortletKeys.java", amount: 1],
+ [path: pathMap["apiPath"], target: ".*ValidateException.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*bnd.bnd", amount: 1],
+ [path: pathMap["servicePath"], target: ".*build.gradle", amount: 1],
+ [path: pathMap["servicePath"], target: ".*default.xml", amount: 1],
+
+ [path: pathMap["servicePath"], target: ".*KeywordQueryContributor.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*ModelDocumentContributor.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*ModelIndexWriterContributor.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*ModelPreFilterContributor.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*ModelSummaryContributor.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*ModelVisibilityContributor.java", amount: 1],
+
+ [path: pathMap["servicePath"], target: ".*Indexer.java", amount: 1],
+
+ [path: pathMap["servicePath"], target: ".*LocalServiceImpl.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*PermissionChecker.java", amount: 2],
+ [path: pathMap["servicePath"], target: ".*portlet.properties", amount: 1],
+ [path: pathMap["servicePath"], target: ".*portlet-model-hints.xml", amount: 1],
+ [path: pathMap["servicePath"], target: ".*ResourcePermissionChecker.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*TrashHandler.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*Validator.java", amount: 1],
+ [path: pathMap["servicePath"], target: ".*WorkflowHandler.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*abstract.jsp", amount: 1],
+ [path: pathMap["webPath"], target: ".*AssetRenderer.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*AssetRendererFactory.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*bnd.bnd", amount: 1],
+ [path: pathMap["webPath"], target: ".*build.gradle", amount: 1],
+ [path: pathMap["webPath"], target: ".*ConfigurationAction.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*Configuration.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*configuration.jsp", amount: 1],
+ [path: pathMap["webPath"], target: ".*CrudMVCActionCommand.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*CrudMVCRenderCommand.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*default.xml", amount: 1],
+ [path: pathMap["webPath"], target: ".*edit.jsp", amount: 1],
+ [path: pathMap["webPath"], target: ".*edit_actions.jsp", amount: 1],
+ [path: pathMap["webPath"], target: ".*full_content.jsp", amount: 1],
+ [path: pathMap["webPath"], target: ".*init.jsp", amount: 1],
+ [path: pathMap["webPath"], target: ".*ItemSelectorHelper.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*portlet.properties", amount: 1],
+ [path: pathMap["webPath"], target: ".*search_results.jspf", amount: 1],
+ [path: pathMap["webPath"], target: ".*view.jsp", amount: 1],
+ [path: pathMap["webPath"], target: ".*ViewHelper.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*ViewMVCRenderCommand.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*view_record.jsp", amount: 1],
+ [path: pathMap["webPath"], target: ".*WebKeys.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*WebPortlet.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*portlet.properties", amount: 1],
+ [path: pathMap["webPath"], target: ".*FindEntryAction.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*FindEntryHelper.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*PortletLayoutFinder.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*AdminPortlet.java", amount: 1],
+ [path: pathMap["webPath"], target: ".*PanelApp.java", amount: 1],
+ [path: pathMap["rootPath"], target: ".*build.gradle", amount: 4],
+ [path: pathMap["rootPath"], target: ".*settings.gradle", amount: 1]
+ ];
+ }
+
+
return [
[path: pathMap["apiPath"], target: ".*bnd.bnd", amount: 1],
[path: pathMap["apiPath"], target: ".*build.gradle", amount: 1],
@@ -244,7 +309,9 @@ class CreateCommandTest extends Specification {
[path: pathMap["servicePath"], target: ".*bnd.bnd", amount: 1],
[path: pathMap["servicePath"], target: ".*build.gradle", amount: 1],
[path: pathMap["servicePath"], target: ".*default.xml", amount: 1],
+
[path: pathMap["servicePath"], target: ".*Indexer.java", amount: 1],
+
[path: pathMap["servicePath"], target: ".*LocalServiceImpl.java", amount: 1],
[path: pathMap["servicePath"], target: ".*PermissionChecker.java", amount: 2],
[path: pathMap["servicePath"], target: ".*portlet.properties", amount: 1],
@@ -348,7 +415,7 @@ class CreateCommandTest extends Specification {
//Target path map of a project
def pathMap = TestUtils.getPathMap(expectedProjectDirName)
- def checkLoop = getCheckLoop(expectedProjectDirName)
+ def checkLoop = getCheckLoop(expectedProjectDirName, liferayVersion)
checkLoop.each { trow ->
def targetFile1 = FileUtils.listFiles(new File(trow.path), new RegexFileFilter(trow.target), TrueFileFilter.INSTANCE)
@@ -466,6 +533,7 @@ class CreateCommandTest extends Specification {
where:
projectName | liferayVersion | packageName | expectedProjectDirName
+ "SampleSB" | DamascusProps.VERSION_73 | "com.liferay.test" | "sample-sb"
"SampleSB" | DamascusProps.VERSION_72 | "com.liferay.test" | "sample-sb"
"SampleSB" | DamascusProps.VERSION_71 | "com.liferay.test" | "sample-sb"
"SampleSB" | DamascusProps.VERSION_70 | "com.liferay.test" | "sample-sb"
@@ -496,6 +564,7 @@ class CreateCommandTest extends Specification {
where:
projectName | version | packageName | base_json_name
+ "Employee" | DamascusProps.VERSION_73 | "com.liferay.sb.employee" | "base_relation_fail.json"
"Employee" | DamascusProps.VERSION_72 | "com.liferay.sb.employee" | "base_relation_fail.json"
"Employee" | DamascusProps.VERSION_71 | "com.liferay.sb.employee" | "base_relation_fail.json"
}
@@ -524,6 +593,7 @@ class CreateCommandTest extends Specification {
where:
projectName | version | packageName | base_json_name
+ "Employee" | DamascusProps.VERSION_73 | "com.liferay.sb.employee" | "base_relation_success.json"
"Employee" | DamascusProps.VERSION_72 | "com.liferay.sb.employee" | "base_relation_success.json"
}
}
diff --git a/src/test/groovy/com/liferay/damascus/cli/common/CommonUtilTest.groovy b/src/test/groovy/com/liferay/damascus/cli/common/CommonUtilTest.groovy
index 907a986..4f2cefe 100644
--- a/src/test/groovy/com/liferay/damascus/cli/common/CommonUtilTest.groovy
+++ b/src/test/groovy/com/liferay/damascus/cli/common/CommonUtilTest.groovy
@@ -111,6 +111,7 @@ class CommonUtilTest extends Specification {
where:
name | packageName | liferayVersion
+ "Todo" | "com.liferay.test" | DamascusProps.VERSION_73
"Todo" | "com.liferay.test" | DamascusProps.VERSION_72
"Task" | "jp.co.liferay.test" | DamascusProps.VERSION_71
"Task" | "jp.co.liferay.test.longpackage.namehere" | DamascusProps.VERSION_70
@@ -206,6 +207,7 @@ class CommonUtilTest extends Specification {
where:
name | packageName | liferayVersion
+ "Todo" | "com.liferay.test" | DamascusProps.VERSION_73
"Todo" | "com.liferay.test" | DamascusProps.VERSION_72
"Todo" | "com.liferay.test" | DamascusProps.VERSION_71
"Todo_Dada" | "c.aaa" | DamascusProps.VERSION_70
@@ -237,8 +239,9 @@ class CommonUtilTest extends Specification {
where:
name | packageName | liferayVersion
- "Hoge" | "com.liferay.test" | DamascusProps.VERSION_71
+ "Hoge-web" | "com.liferay" | DamascusProps.VERSION_73
"Hoge-web" | "com.liferay" | DamascusProps.VERSION_72
+ "Hoge" | "com.liferay.test" | DamascusProps.VERSION_71
}
@Unroll("Smoke test for Create workspace name<#name>")
@@ -264,6 +267,7 @@ class CommonUtilTest extends Specification {
"Foo" | DamascusProps.VERSION_70
"Foo-web" | DamascusProps.VERSION_71
"Bar_web" | DamascusProps.VERSION_72
+ "Bar_web" | DamascusProps.VERSION_73
}
void dummyWriter(file, dummy_text) {
diff --git a/src/test/resources/templates/7.0/base.json b/src/test/resources/templates/7.0/base.json
index c80841f..f3c18ed 100644
--- a/src/test/resources/templates/7.0/base.json
+++ b/src/test/resources/templates/7.0/base.json
@@ -1,82 +1,81 @@
-{
- "projectName": "${damascus.projectName}",
- "packageName" : "${damascus.packageName}",
- "liferayVersion": "${damascus.liferayVersion}",
- "applications": [
- {
- "model" : "${damascus.entityName}",
- "title" : "${damascus.projectName} Test",
- "web" : "true",
- "asset": {
- "assetTitleFieldName": "${damascus.entityNameLower}TitleName",
- "assetSummaryFieldName": "${damascus.entityNameLower}SummaryName",
- "categories": "true",
- "discussion": "true",
- "ratings": "true",
- "tags": "true",
- "relatedAssets": "true",
- "fullContentFieldName": "${damascus.entityNameLower}fullContent",
- "workflow": "true",
- "generateActivity": "true",
- "trash":"true"
- },
- "fieldsName" : "${damascus.projectName}s",
- "fields": [
- {
- "type": "com.liferay.damascus.cli.json.fields.Long",
- "primary":true,
- "name": "${damascus.entityNameLower}Id",
- "title": "${damascus.projectName} Id",
- "showFieldInView": "false",
- "required": "true"
- },
- {
- "type": "com.liferay.damascus.cli.json.fields.Varchar",
- "name": "title",
- "title": "Title",
- "length": "80",
- "showFieldInView": "true",
- "required": "true"
- },
- {
- "type": "com.liferay.damascus.cli.json.fields.Boolean",
- "name": "${damascus.entityNameLower}BooleanStat",
- "title": "${damascus.projectName} Boolean Stat"
- },
- {
- "type": "com.liferay.damascus.cli.json.fields.DateTime",
- "name": "${damascus.entityNameLower}DateTime",
- "title": "${damascus.projectName} DateTime"
- },
- {
- "type": "com.liferay.damascus.cli.json.fields.DocumentLibrary",
- "name": "${damascus.entityNameLower}DocumentLibrary",
- "title": "${damascus.projectName} DocumentLibrary"
- },
- {
- "type": "com.liferay.damascus.cli.json.fields.Double",
- "name": "${damascus.entityNameLower}Double",
- "title": "${damascus.projectName} Double"
- },
- {
- "type": "com.liferay.damascus.cli.json.fields.Integer",
- "name": "${damascus.entityNameLower}Integer",
- "title": "${damascus.projectName} Integer"
- },
- {
- "type": "com.liferay.damascus.cli.json.fields.RichText",
- "name": "${damascus.entityNameLower}RichText",
- "title": "${damascus.projectName} RichText"
- },
- {
- "type": "com.liferay.damascus.cli.json.fields.Text",
- "name": "${damascus.entityNameLower}Text",
- "title": "${damascus.projectName} Text"
- }
- ],
- "customValue" : {
- "your_own_id" : "your_custom_value_for_template_here"
- }
- }
- ]
-}
+{
+ "projectName": "${damascus.projectName}",
+ "packageName" : "${damascus.packageName}",
+ "liferayVersion": "${damascus.liferayVersion}",
+ "applications": [
+ {
+ "model" : "${damascus.entityName}",
+ "title" : "${damascus.projectName} Test",
+ "web" : "true",
+ "asset": {
+ "assetTitleFieldName": "${damascus.entityNameLower}TitleName",
+ "assetSummaryFieldName": "${damascus.entityNameLower}SummaryName",
+ "categories": "true",
+ "discussion": "true",
+ "ratings": "true",
+ "tags": "true",
+ "relatedAssets": "true",
+ "fullContentFieldName": "${damascus.entityNameLower}fullContent",
+ "workflow": "true",
+ "generateActivity": "true",
+ "trash":"true"
+ },
+ "fields": [
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "primary":true,
+ "name": "${damascus.entityNameLower}Id",
+ "title": "${damascus.projectName} Id",
+ "showFieldInView": "false",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Varchar",
+ "name": "title",
+ "title": "Title",
+ "length": "80",
+ "showFieldInView": "true",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Boolean",
+ "name": "${damascus.entityNameLower}BooleanStat",
+ "title": "${damascus.projectName} Boolean Stat"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.DateTime",
+ "name": "${damascus.entityNameLower}DateTime",
+ "title": "${damascus.projectName} DateTime"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.DocumentLibrary",
+ "name": "${damascus.entityNameLower}DocumentLibrary",
+ "title": "${damascus.projectName} DocumentLibrary"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Double",
+ "name": "${damascus.entityNameLower}Double",
+ "title": "${damascus.projectName} Double"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Integer",
+ "name": "${damascus.entityNameLower}Integer",
+ "title": "${damascus.projectName} Integer"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.RichText",
+ "name": "${damascus.entityNameLower}RichText",
+ "title": "${damascus.projectName} RichText"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Text",
+ "name": "${damascus.entityNameLower}Text",
+ "title": "${damascus.projectName} Text"
+ }
+ ],
+ "customValue" : {
+ "your_own_id" : "your_custom_value_for_template_here"
+ }
+ }
+ ]
+}
diff --git a/src/test/resources/templates/7.0/base_activity_false.json b/src/test/resources/templates/7.0/base_activity_false.json
index 3f47cb2..4d579e6 100644
--- a/src/test/resources/templates/7.0/base_activity_false.json
+++ b/src/test/resources/templates/7.0/base_activity_false.json
@@ -20,7 +20,6 @@
"generateActivity": "false",
"trash":"true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.0/base_categories_false.json b/src/test/resources/templates/7.0/base_categories_false.json
index c68ebe5..6a1c267 100644
--- a/src/test/resources/templates/7.0/base_categories_false.json
+++ b/src/test/resources/templates/7.0/base_categories_false.json
@@ -20,7 +20,6 @@
"generateActivity": "true",
"trash":"true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.0/base_discussion_false.json b/src/test/resources/templates/7.0/base_discussion_false.json
index 1bb4e03..7743c62 100644
--- a/src/test/resources/templates/7.0/base_discussion_false.json
+++ b/src/test/resources/templates/7.0/base_discussion_false.json
@@ -20,7 +20,6 @@
"generateActivity": "true",
"trash":"true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.0/base_ratings_false.json b/src/test/resources/templates/7.0/base_ratings_false.json
index c36e597..b908be3 100644
--- a/src/test/resources/templates/7.0/base_ratings_false.json
+++ b/src/test/resources/templates/7.0/base_ratings_false.json
@@ -20,7 +20,6 @@
"generateActivity": "true",
"trash":"true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.0/base_related_false.json b/src/test/resources/templates/7.0/base_related_false.json
index 76742f2..b3faf15 100644
--- a/src/test/resources/templates/7.0/base_related_false.json
+++ b/src/test/resources/templates/7.0/base_related_false.json
@@ -20,7 +20,6 @@
"generateActivity": "true",
"trash":"true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.0/base_tags_false.json b/src/test/resources/templates/7.0/base_tags_false.json
index 1782fde..89ddc78 100644
--- a/src/test/resources/templates/7.0/base_tags_false.json
+++ b/src/test/resources/templates/7.0/base_tags_false.json
@@ -20,7 +20,6 @@
"generateActivity": "true",
"trash":"true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.1/Portlet_XXXXWEB_build.gradle.ftl b/src/test/resources/templates/7.1/Portlet_XXXXWEB_build.gradle.ftl
index 2e904ed..7c7db5c 100644
--- a/src/test/resources/templates/7.1/Portlet_XXXXWEB_build.gradle.ftl
+++ b/src/test/resources/templates/7.1/Portlet_XXXXWEB_build.gradle.ftl
@@ -28,42 +28,38 @@ repositories {
}
}
-// TODO : This can be removed once you set up IDE. When you import this project into a IDE, you may be asked
-// a path to the gradle root. Then you run "gradle getHomeDir" and use the path for the IDE.
-task getHomeDir << {
- println gradle.gradleHomeDir
-}
-
dependencies {
+ // TODO : Please remove the comment when the project is built. This becomes the cause of error while generating this project
+ // implementation enforcedPlatform(group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1")
compile 'com.google.errorprone:error_prone_annotations:2.0.19'
- compile 'commons-digester:commons-digester:1.8.1'
- compile "com.google.guava:guava:21.0"
- compile "commons-io:commons-io:2.5"
- compile "commons-validator:commons-validator:1.6"
+ compile 'commons-digester:commons-digester<#if useTP?? && false == useTP>:1.8.1#if>'
+ compile "com.google.guava:guava<#if useTP?? && false == useTP>:21.0#if>"
+ compile "commons-io:commons-io<#if useTP?? && false == useTP>:2.5#if>"
+ compile "commons-validator:commons-validator<#if useTP?? && false == useTP>:1.6#if>"
compile "org.apache.commons:commons-lang3:3.5"
- compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.1.0"
- compile group: "com.liferay", name: "com.liferay.portal.spring.extender.api", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.application.list.api", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.frontend.taglib", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.item.selector.api", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.item.selector.criteria.api", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.item.selector.taglib", version: "1.0.0"
- compile group: "com.liferay", name: "com.liferay.trash.taglib", version: "3.0.0"
- compile group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "3.0.0"
- compile group: "com.liferay.portal", name: "com.liferay.portal.impl", version: "3.0.0"
- compile group: "com.liferay.portal", name: "com.liferay.util.taglib", version: "3.0.0"
- compile group: "javax.portlet", name: "portlet-api", version: "2.0"
- compile group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
- compile group: "jstl", name: "jstl", version: "1.2"
- compile group: "org.osgi", name: "osgi.cmpn", version: "6.0.0"
- compile group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
- compile group: 'org.apache.poi', name: 'poi-ooxml', version: '4.0.1'
- compile group: 'org.apache.poi', name: 'poi', version: '4.0.1'
- compile group: 'org.apache.poi', name: 'poi-ooxml-schemas', version: '4.0.1'
- compile group: 'org.apache.xmlbeans', name: 'xmlbeans', version: '3.0.2'
- compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.2'
- compile group: 'org.apache.commons', name: 'commons-compress', version: '1.18'
-
+ compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.1.0"
+ compile group: "com.liferay", name: "com.liferay.portal.spring.extender.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.application.list.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.frontend.taglib"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.item.selector.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.item.selector.criteria.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.item.selector.taglib"<#if useTP?? && false == useTP>, version: "1.0.0"#if>
+ compile group: "com.liferay", name: "com.liferay.trash.taglib"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay.portal", name: "com.liferay.portal.impl"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "com.liferay.portal", name: "com.liferay.util.taglib"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compile group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "2.0"#if>
+ compile group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compile group: "jstl", name: "jstl"<#if useTP?? && false == useTP>, version: "1.2"#if>
+ compile group: "org.osgi", name: "osgi.cmpn"<#if useTP?? && false == useTP>, version: "6.0.0"#if>
+ compile group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
+ compile group: 'org.apache.poi', name: 'poi-ooxml'<#if useTP?? && false == useTP>, version: '4.0.1'#if>
+ compile group: 'org.apache.poi', name: 'poi'<#if useTP?? && false == useTP>, version: '4.0.1'#if>
+ compile group: 'org.apache.poi', name: 'poi-ooxml-schemas'<#if useTP?? && false == useTP>, version: '4.0.1'#if>
+ compile group: 'org.apache.xmlbeans', name: 'xmlbeans'<#if useTP?? && false == useTP>, version: '3.0.2'#if>
+ compile group: 'org.apache.commons', name: 'commons-collections4'<#if useTP?? && false == useTP>, version: '4.2'#if>
+ compile group: 'org.apache.commons', name: 'commons-compress'<#if useTP?? && false == useTP>, version: '1.18'#if>
+
compileOnly project(":${dashcaseProjectName}-api")
compileOnly project(":${dashcaseProjectName}-service")
}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.1/base.json b/src/test/resources/templates/7.1/base.json
index 163d949..90badd6 100644
--- a/src/test/resources/templates/7.1/base.json
+++ b/src/test/resources/templates/7.1/base.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.entityName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.1/base_activity_false.json b/src/test/resources/templates/7.1/base_activity_false.json
index f7a9455..1d3a994 100644
--- a/src/test/resources/templates/7.1/base_activity_false.json
+++ b/src/test/resources/templates/7.1/base_activity_false.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.projectName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.1/base_categories_false.json b/src/test/resources/templates/7.1/base_categories_false.json
index eba3d1f..cb595f9 100644
--- a/src/test/resources/templates/7.1/base_categories_false.json
+++ b/src/test/resources/templates/7.1/base_categories_false.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.projectName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.1/base_discussion_false.json b/src/test/resources/templates/7.1/base_discussion_false.json
index a647787..056bfd2 100644
--- a/src/test/resources/templates/7.1/base_discussion_false.json
+++ b/src/test/resources/templates/7.1/base_discussion_false.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.projectName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.1/base_ratings_false.json b/src/test/resources/templates/7.1/base_ratings_false.json
index f398fcf..a36679f 100644
--- a/src/test/resources/templates/7.1/base_ratings_false.json
+++ b/src/test/resources/templates/7.1/base_ratings_false.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.projectName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.1/base_related_false.json b/src/test/resources/templates/7.1/base_related_false.json
index 1ecb1a6..890e6e6 100644
--- a/src/test/resources/templates/7.1/base_related_false.json
+++ b/src/test/resources/templates/7.1/base_related_false.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.projectName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.1/base_relation_fail.json b/src/test/resources/templates/7.1/base_relation_fail.json
index a4535a4..d6dd339 100644
--- a/src/test/resources/templates/7.1/base_relation_fail.json
+++ b/src/test/resources/templates/7.1/base_relation_fail.json
@@ -2,6 +2,7 @@
"projectName": "Employee",
"packageName": "com.liferay.sb.employee",
"liferayVersion": "7.1",
+ "useTargetPlatform": "false",
"applications": [{
"model": "Employee",
"title": "Employee Test",
@@ -21,7 +22,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName": "Employees",
"fields": [{
"type": "com.liferay.damascus.cli.json.fields.Long",
"primary": true,
@@ -74,7 +74,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName": "Positions",
"fields": [{
"type": "com.liferay.damascus.cli.json.fields.Long",
"primary": true,
diff --git a/src/test/resources/templates/7.1/base_relation_success.json b/src/test/resources/templates/7.1/base_relation_success.json
index 0b01a65..7d36799 100644
--- a/src/test/resources/templates/7.1/base_relation_success.json
+++ b/src/test/resources/templates/7.1/base_relation_success.json
@@ -2,6 +2,7 @@
"projectName": "Employee",
"packageName": "com.liferay.sb.employee",
"liferayVersion": "7.1",
+ "useTargetPlatform": "false",
"applications": [{
"model": "Employee",
"title": "Employee Test",
@@ -21,7 +22,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName": "Employees",
"fields": [{
"type": "com.liferay.damascus.cli.json.fields.Long",
"primary": true,
@@ -74,7 +74,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName": "Positions",
"fields": [{
"type": "com.liferay.damascus.cli.json.fields.Long",
"primary": true,
diff --git a/src/test/resources/templates/7.1/base_tags_false.json b/src/test/resources/templates/7.1/base_tags_false.json
index a37fdc4..41c65ef 100644
--- a/src/test/resources/templates/7.1/base_tags_false.json
+++ b/src/test/resources/templates/7.1/base_tags_false.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.projectName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.1/valuables.ftl b/src/test/resources/templates/7.1/valuables.ftl
index ecaea31..728c8cb 100644
--- a/src/test/resources/templates/7.1/valuables.ftl
+++ b/src/test/resources/templates/7.1/valuables.ftl
@@ -3,6 +3,7 @@
<#assign packageName = "${damascus.packageName}">
<#assign packagePath = "${packageName?replace(\".\", \"/\")}">
<#assign packageSnake = "${packageName?replace(\".\", \"_\")}">
+<#assign useTP = damascus.isUseTargetPlatform() >
<#assign camelcaseProjectName = "${damascus.projectName?replace(\"-\", \"\")}">
<#assign dashcaseProjectName = "${caseUtil.camelCaseToDashCase(camelcaseProjectName)}">
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXAPI_build.gradle.ftl b/src/test/resources/templates/7.2/Portlet_XXXXAPI_build.gradle.ftl
index 9f92ce9..ae4f46f 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXAPI_build.gradle.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXAPI_build.gradle.ftl
@@ -12,11 +12,11 @@ apply plugin: 'eclipse'
def defaultEncoding = 'UTF-8'
dependencies {
- compile group: "javax.portlet", name: "portlet-api", version: "3.0.1"
- compile group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
- compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "4.13.0"
- compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning", version: "1.1.0"
- compileOnly group: "org.osgi", name: "org.osgi.core", version: "6.0.0"
- compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "4.13.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"<#if useTP?? && false == useTP>, version: "1.1.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.core"<#if useTP?? && false == useTP>, version: "6.0.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl
new file mode 100644
index 0000000..69682a5
--- /dev/null
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl
@@ -0,0 +1,50 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/query/contributor/${capFirstModel}KeywordQueryContributor.java">
+/* */
+package ${packageName}.internal.search.query.contributor;
+
+import com.liferay.portal.kernel.search.BooleanQuery;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.search.query.QueryHelper;
+import com.liferay.portal.search.spi.model.query.contributor.KeywordQueryContributor;
+import com.liferay.portal.search.spi.model.query.contributor.helper.KeywordQueryContributorHelper;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Keyword Query Contributor
+ *
+ * Contributes clauses to the ongoing search query to control how the model entities are searched.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = KeywordQueryContributor.class
+)
+public class ${capFirstModel}KeywordQueryContributor implements KeywordQueryContributor {
+
+ @Override
+ public void contribute(String keywords, BooleanQuery booleanQuery,KeywordQueryContributorHelper keywordQueryContributorHelper) {
+ SearchContext searchContext = keywordQueryContributorHelper.getSearchContext();
+
+ // TODO: Adjust as necessary to support the search for the entity
+
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.ARTICLE_ID, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.CLASS_PK, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.ENTRY_CLASS_PK, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.USER_NAME, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.CONTENT, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.DESCRIPTION, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.TITLE, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.SUBTITLE, false);
+ }
+
+ @Reference
+ protected QueryHelper queryHelper;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_LocalServiceImpl.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
index 0db4ac7..dbbad25 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
@@ -21,8 +21,6 @@ import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.ModelHintsUtil;
import com.liferay.portal.kernel.model.ResourceConstants;
import com.liferay.portal.kernel.model.SystemEventConstants;
@@ -75,6 +73,9 @@ import javax.portlet.PortletRequest;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* The implementation of the ${capFirstModel} local service.
*
@@ -1274,7 +1275,7 @@ public class ${capFirstModel}LocalServiceImpl extends ${capFirstModel}LocalServi
WorkflowConstants.STATUS_SCHEDULED
};
- private static Log _log = LogFactoryUtil.getLog(
+ private static Logger _log = LoggerFactory.getLogger(
${capFirstModel}LocalServiceImpl.class);
@Reference
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl
new file mode 100644
index 0000000..d4375b6
--- /dev/null
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl
@@ -0,0 +1,45 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/index/contributor/${capFirstModel}ModelDocumentContributor.java">
+/* */
+package ${packageName}.internal.search.index.contributor;
+
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.search.spi.model.index.contributor.ModelDocumentContributor;
+import org.osgi.service.component.annotations.Component;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Model Document Contributor
+ *
+ * This class is used to contribute fields to the document to be indexed.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelDocumentContributor.class
+)
+public class ${capFirstModel}ModelDocumentContributor implements ModelDocumentContributor<${capFirstModel}> {
+
+ @Override
+ public void contribute(Document document, ${capFirstModel} entry) {
+
+ // TODO : These fields should be modified according to your requirements.
+
+ document.addText(Field.CAPTION, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(
+ Field.CONTENT,
+ HtmlUtil.extractText(entry.get${application.asset.assetSummaryFieldName?cap_first}()));
+ document.addText(Field.DESCRIPTION, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(Field.SUBTITLE, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(Field.TITLE, entry.get${application.asset.assetTitleFieldName?cap_first}());
+
+ document.addDate(Field.MODIFIED_DATE, entry.getModifiedDate());
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl
new file mode 100644
index 0000000..c7f86c0
--- /dev/null
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl
@@ -0,0 +1,89 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/index/contributor/${capFirstModel}ModelIndexerWriterContributor.java">
+/* */
+package ${packageName}.internal.search.index.contributor;
+
+import com.liferay.portal.kernel.dao.orm.Property;
+import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.search.batch.BatchIndexingActionable;
+import com.liferay.portal.search.batch.DynamicQueryBatchIndexingActionableFactory;
+import com.liferay.portal.search.spi.model.index.contributor.ModelIndexerWriterContributor;
+import com.liferay.portal.search.spi.model.index.contributor.helper.IndexerWriterMode;
+import com.liferay.portal.search.spi.model.index.contributor.helper.ModelIndexerWriterDocumentHelper;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+/**
+ * ${capFirstModel} Model Indexer Writer Contributor
+ *
+ * This class is used during bulk reindexing to identify records to reindex.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelIndexerWriterContributor.class
+)
+public class ${capFirstModel}ModelIndexerWriterContributor implements ModelIndexerWriterContributor<${capFirstModel}> {
+
+ @Override
+ public void customize(BatchIndexingActionable batchIndexingActionable, ModelIndexerWriterDocumentHelper modelIndexerWriterDocumentHelper) {
+
+ // TODO: add criteria to the DQ to select the entities to include in the reindex.
+ batchIndexingActionable.setAddCriteriaMethod(dynamicQuery -> {
+ Property statusProperty = PropertyFactoryUtil.forName("status");
+
+ Integer[] statuses = {
+ WorkflowConstants.STATUS_APPROVED,
+ WorkflowConstants.STATUS_IN_TRASH
+ };
+
+ // reindex any entry that is approved or in the trash
+ dynamicQuery.add(statusProperty.in(statuses));
+ });
+
+ // add any matched entry into the documents to index.
+ batchIndexingActionable.setPerformActionMethod((${capFirstModel} entry) -> {
+ batchIndexingActionable.addDocuments(modelIndexerWriterDocumentHelper.getDocument(entry));
+ });
+ }
+
+ @Override
+ public IndexerWriterMode getIndexerWriterMode(${capFirstModel} entry) {
+
+ // TODO: Update as necessary to control the indexer writer mode for the given entry.
+
+ int status = entry.getStatus();
+
+ if ((status == WorkflowConstants.STATUS_APPROVED) || (status == WorkflowConstants.STATUS_IN_TRASH) || (status == WorkflowConstants.STATUS_DRAFT)) {
+ return IndexerWriterMode.UPDATE;
+ }
+
+ return IndexerWriterMode.DELETE;
+ }
+
+ @Override
+ public BatchIndexingActionable getBatchIndexingActionable() {
+ return dynamicQueryBatchIndexingActionableFactory.getBatchIndexingActionable(
+ _${uncapFirstModel}LocalService.getIndexableActionableDynamicQuery());
+ }
+
+ @Override
+ public long getCompanyId(${capFirstModel} entry) {
+ return entry.getCompanyId();
+ }
+
+ @Reference
+ protected ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+ @Reference
+ protected DynamicQueryBatchIndexingActionableFactory dynamicQueryBatchIndexingActionableFactory;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl
new file mode 100644
index 0000000..5cc6f50
--- /dev/null
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl
@@ -0,0 +1,45 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/query/contributor/${capFirstModel}ModelPreFilterContributor.java">
+/* */
+package ${packageName}.internal.search.query.contributor;
+
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.kernel.search.filter.BooleanFilter;
+import com.liferay.portal.search.spi.model.query.contributor.ModelPreFilterContributor;
+import com.liferay.portal.search.spi.model.registrar.ModelSearchSettings;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model PreFilter Contributor
+ *
+ * Filters search results before they are returned from the search engine.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelPreFilterContributor.class
+)
+public class ${capFirstModel}ModelPreFilterContributor implements ModelPreFilterContributor {
+
+ @Override
+ public void contribute(BooleanFilter booleanFilter, ModelSearchSettings modelSearchSettings, SearchContext searchContext) {
+
+ // TODO: Adjust as necessary to filter results that should not normally be included as search results.
+
+ // exclude non-approved entities from the search results.
+ addWorkflowStatusFilter(booleanFilter, modelSearchSettings, searchContext);
+ }
+
+ protected void addWorkflowStatusFilter(BooleanFilter booleanFilter, ModelSearchSettings modelSearchSettings, SearchContext searchContext) {
+ workflowStatusModelPreFilterContributor.contribute(booleanFilter, modelSearchSettings, searchContext);
+ }
+
+ @Reference(target = "(model.pre.filter.contributor.id=WorkflowStatus)")
+ protected ModelPreFilterContributor workflowStatusModelPreFilterContributor;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl
new file mode 100644
index 0000000..d60444e
--- /dev/null
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl
@@ -0,0 +1,58 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/result/contributor/${capFirstModel}ModelSummaryContributor.java">
+/* */
+package ${packageName}.internal.search.result.contributor;
+
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.Summary;
+import com.liferay.portal.kernel.util.LocaleUtil;
+import com.liferay.portal.kernel.util.LocalizationUtil;
+import com.liferay.portal.search.spi.model.result.contributor.ModelSummaryContributor;
+import org.osgi.service.component.annotations.Component;
+
+import java.util.Locale;
+
+/**
+ * ${capFirstModel} Model Summary Contributor
+ *
+ * Manipulates the Summary object for each entity search result.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelSummaryContributor.class
+)
+public class ${capFirstModel}ModelSummaryContributor implements ModelSummaryContributor {
+
+ @Override
+ public Summary getSummary(Document document, Locale locale, String snippet) {
+ String languageId = LocaleUtil.toLanguageId(locale);
+
+ // TODO: Modify as necessary to use the corrected fields for the summary
+
+ return _createSummary(document,
+ LocalizationUtil.getLocalizedName(Field.CONTENT, languageId),
+ LocalizationUtil.getLocalizedName(Field.TITLE, languageId));
+ }
+
+ protected Summary _createSummary(Document document, String contentField, String titleField) {
+
+ String prefix = Field.SNIPPET + StringPool.UNDERLINE;
+
+ String title = document.get(prefix + titleField, titleField);
+ String content = document.get(prefix + contentField, contentField);
+
+ Summary summary = new Summary(title,content);
+
+ summary.setMaxContentLength(200);
+
+ return summary;
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl
new file mode 100644
index 0000000..323c014
--- /dev/null
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl
@@ -0,0 +1,53 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/result/contributor/${capFirstModel}ModelVisibilityContributor.java">
+/* */
+package ${packageName}.internal.search.result.contributor;
+
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.search.spi.model.result.contributor.ModelVisibilityContributor;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model Visibility Contributor
+ *
+ * Controls the visibility of entities that can be attached to other asset types in the search context.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelVisibilityContributor.class
+)
+public class ${capFirstModel}ModelVisibilityContributor implements ModelVisibilityContributor {
+
+ @Override
+ public boolean isVisible(long classPK, int status) {
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.fetch${capFirstModel}(classPK);
+
+ if (entry == null) {
+ return false;
+ }
+
+ return isVisible(entry.getStatus(), status);
+ }
+
+ protected boolean isVisible(int entryStatus, int queryStatus) {
+ if (((queryStatus != WorkflowConstants.STATUS_ANY) && (entryStatus == queryStatus)) || (entryStatus != WorkflowConstants.STATUS_IN_TRASH)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Reference
+ protected ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_SearchRegistrar.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_SearchRegistrar.java.ftl
new file mode 100644
index 0000000..6b87de4
--- /dev/null
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_SearchRegistrar.java.ftl
@@ -0,0 +1,70 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/${capFirstModel}SearchRegistrar.java">
+/* */
+package ${packageName}.internal.search;
+
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.search.spi.model.index.contributor.ModelIndexerWriterContributor;
+import com.liferay.portal.search.spi.model.registrar.ModelSearchRegistrarHelper;
+import com.liferay.portal.search.spi.model.result.contributor.ModelSummaryContributor;
+import com.liferay.portal.search.spi.model.result.contributor.ModelVisibilityContributor;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Search Registrar
+ *
+ * Registers the ${capFirstModel} entity with Liferay's search framework.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ service = {}
+)
+public class ${capFirstModel}SearchRegistrar {
+
+ @Activate
+ protected void activate(BundleContext bundleContext) {
+ _serviceRegistration = modelSearchRegistrarHelper.register(
+ ${capFirstModel}.class, bundleContext,
+ modelSearchDefinition -> {
+ modelSearchDefinition.setDefaultSelectedFieldNames(
+ Field.ASSET_TAG_NAMES, Field.COMPANY_ID, Field.CONTENT,
+ Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID,
+ Field.MODIFIED_DATE, Field.SCOPE_GROUP_ID, Field.TITLE, Field.UID);
+ modelSearchDefinition.setDefaultSelectedLocalizedFieldNames(Field.TITLE, Field.CONTENT);
+
+ modelSearchDefinition.setModelIndexWriteContributor(modelIndexWriterContributor);
+ modelSearchDefinition.setModelSummaryContributor(modelSummaryContributor);
+ modelSearchDefinition.setModelVisibilityContributor(modelVisibilityContributor);
+ });
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ _serviceRegistration.unregister();
+ }
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelIndexerWriterContributor<${capFirstModel}> modelIndexWriterContributor;
+
+ @Reference
+ protected ModelSearchRegistrarHelper modelSearchRegistrarHelper;
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelSummaryContributor modelSummaryContributor;
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelVisibilityContributor modelVisibilityContributor;
+
+ private ServiceRegistration> _serviceRegistration;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_Searcher.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_Searcher.java.ftl
new file mode 100644
index 0000000..917b60e
--- /dev/null
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_Searcher.java.ftl
@@ -0,0 +1,48 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/${capFirstModel}Searcher.java">
+/* */
+package ${packageName}.internal.search;
+
+import com.liferay.portal.kernel.search.BaseSearcher;
+import com.liferay.portal.kernel.search.Field;
+import org.osgi.service.component.annotations.Component;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Searcher
+ *
+ * Sets up the searcher instance for ${capFirstModel}.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = BaseSearcher.class
+)
+public class ${capFirstModel}Searcher extends BaseSearcher {
+
+ public static final String CLASS_NAME = ${capFirstModel}.class.getName();
+
+ public ${capFirstModel}Searcher() {
+
+ // TODO: Adjust the fields as necessary.
+ setDefaultSelectedFieldNames(
+ Field.ASSET_TAG_NAMES, Field.COMPANY_ID, Field.CONTENT,
+ Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID,
+ Field.MODIFIED_DATE, Field.SCOPE_GROUP_ID, Field.TITLE, Field.UID);
+ setFilterSearch(true);
+ setPermissionAware(true);
+
+ // TODO Adjust localized fields as well
+ setDefaultSelectedLocalizedFieldNames(Field.TITLE, Field.CONTENT);
+ }
+
+ @Override
+ public String getClassName() {
+ return CLASS_NAME;
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_WorkflowManager.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_WorkflowManager.java.ftl
index 8c23004..4174378 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXSVC_WorkflowManager.java.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_WorkflowManager.java.ftl
@@ -10,8 +10,6 @@ package ${packageName}.service.workflow;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.model.WorkflowInstanceLink;
import com.liferay.portal.kernel.service.WorkflowInstanceLinkLocalServiceUtil;
@@ -27,6 +25,9 @@ import ${packageName}.model.${capFirstModel};
import java.util.ArrayList;
import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* ${capFirstModel} Workflow Utility class
*
@@ -361,7 +362,7 @@ public class ${capFirstModel}WorkflowManager {
user.getCompanyId(), scorpGroupId, _className, classPK);
}
- private static Log _log = LogFactoryUtil.getLog(
+ private static Logger _log = LoggerFactory.getLogger(
${capFirstModel}WorkflowManager.class);
}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXSVC_build.gradle.ftl b/src/test/resources/templates/7.2/Portlet_XXXXSVC_build.gradle.ftl
index 4d13cae..302bdf0 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXSVC_build.gradle.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXSVC_build.gradle.ftl
@@ -29,27 +29,28 @@ repositories {
}
dependencies {
- compile group: "com.google.guava", name: "guava", version: "28.1-jre", transitive: false
- compile group: "com.liferay", name: "com.liferay.friendly.url.api", version: "2.0.0"
- compile group: "com.liferay", name: "com.liferay.petra.function", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.petra.lang", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.petra.string", version: "3.0.0"
- compile group: "com.liferay", name: "com.liferay.portal.aop.api", version: "1.0.0"
- compile group: "com.liferay", name: "com.liferay.portal.search.api", version: "3.7.0"
- compile group: "com.liferay", name: "com.liferay.portal.search.spi", version: "3.2.0"
- compile group: "com.liferay", name: "com.liferay.trash.api", version: "2.0.0"
- compile group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "4.13.0"
- compile group: "commons-io", name: "commons-io", version: "2.6"
- compile group: "commons-validator", name: "commons-validator", version: "1.6"
- compile group: "javax.portlet", name: "portlet-api", version: "3.0.1"
- compile group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
- compile group: "javax.servlet.jsp", name: "javax.servlet.jsp-api", version: "2.3.1"
+ compile group: "com.google.guava", name: "guava"<#if useTP?? && false == useTP>, version: "28.1-jre"#if>, transitive: false
+ compileOnly group: "com.liferay", name: "com.liferay.friendly.url.api"<#if useTP?? && false == useTP>, version: "2.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.function"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.lang"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.string"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"<#if useTP?? && false == useTP>, version: "1.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.search.api"<#if useTP?? && false == useTP>, version: "3.12.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.search.spi"<#if useTP?? && false == useTP>, version: "3.3.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.trash.api"<#if useTP?? && false == useTP>, version: "2.0.0"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "4.13.0"#if>
+ compileOnly group: "commons-io", name: "commons-io"<#if useTP?? && false == useTP>, version: "2.6"#if>
+ compile group: "commons-validator", name: "commons-validator"<#if useTP?? && false == useTP>, version: "1.6"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet.jsp", name: "jsp-api"<#if useTP?? && false == useTP>, version: "2.1"#if>
compile group: "org.apache.commons", name: "commons-lang3", version: "3.9"
compile group: "org.apache.felix", name: "org.apache.felix.http.servlet-api", version: "1.1.2"
- compile group: "org.osgi", name: "org.osgi.annotation.versioning", version: "1.1.0"
- compile group: "org.osgi", name: "org.osgi.service.cm", version: "1.5.0"
- compile group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
+ compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"<#if useTP?? && false == useTP>, version: "1.1.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.cm"<#if useTP?? && false == useTP>, version: "1.5.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
compile group: "org.osgi", name: "osgi.core", version: "6.0.0"
+ compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.26'
compile project(":${dashcaseProjectName}-api")
}
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
index 8e97a8a..8a70af8 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
@@ -10,8 +10,6 @@ package ${packageName}.web.portlet.action;
import com.liferay.asset.display.page.portlet.AssetDisplayPageEntryFormProcessor;
import com.liferay.petra.reflect.ReflectionUtil;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.TrashedModel;
import com.liferay.portal.kernel.portlet.bridges.mvc.BaseMVCActionCommand;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCActionCommand;
@@ -46,6 +44,9 @@ import javax.portlet.ActionResponse;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* @author ${damascus_author}
*/
@@ -248,7 +249,7 @@ public class ${capFirstModel}AdminCrudMVCActionCommand extends BaseMVCActionComm
hideDefaultSuccessMessage(request);
}
catch (Exception t) {
- _log.error(t, t);
+ _log.error(t.getLocalizedMessage(), t);
SessionErrors.add(request, PortalException.class);
hideDefaultSuccessMessage(request);
}
@@ -274,7 +275,7 @@ public class ${capFirstModel}AdminCrudMVCActionCommand extends BaseMVCActionComm
_${uncapFirstModel}Service = ${uncapFirstModel}Service;
}
- private static Log _log = LogFactoryUtil.getLog(
+ private static Logger _log = LoggerFactory.getLogger(
${capFirstModel}AdminCrudMVCActionCommand.class);
@Reference
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXWEB_AssetRenderer.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXWEB_AssetRenderer.java.ftl
index 749f21f..7950112 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXWEB_AssetRenderer.java.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXWEB_AssetRenderer.java.ftl
@@ -13,8 +13,6 @@ import com.liferay.asset.kernel.model.AssetRendererFactory;
import com.liferay.asset.kernel.model.BaseJSPAssetRenderer;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
@@ -26,7 +24,6 @@ import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.trash.TrashRenderer;
import com.liferay.portal.kernel.util.Constants;
-import com.liferay.portal.kernel.util.HtmlUtil;
import com.liferay.portal.kernel.util.PortalUtil;
import com.liferay.portal.kernel.util.ResourceBundleLoader;
import com.liferay.portal.kernel.util.Validator;
@@ -44,6 +41,9 @@ import javax.portlet.WindowState;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* Asset Renderer
*
@@ -306,14 +306,14 @@ public class ${capFirstModel}AssetRenderer
}
catch (PortalException pe) {
if (_log.isDebugEnabled()) {
- _log.debug(pe, pe);
+ _log.debug(pe.getLocalizedMessage(), pe);
}
return false;
}
}
- private static final Log _log = LogFactoryUtil.getLog(
+ private static final Logger _log = LoggerFactory.getLogger(
${capFirstModel}AssetRenderer.class);
private AssetDisplayPageFriendlyURLProvider
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXWEB_AssetRendererFactory.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
index 147817d..b0ffa57 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
@@ -12,8 +12,6 @@ import com.liferay.asset.kernel.model.AssetRendererFactory;
import com.liferay.asset.kernel.model.BaseAssetRendererFactory;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
import com.liferay.portal.kernel.portlet.LiferayPortletURL;
@@ -39,6 +37,9 @@ import javax.servlet.ServletContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* ${capFirstModel} Asset Renderer Factory
*
@@ -181,7 +182,7 @@ public class ${capFirstModel}AssetRendererFactory
_servletContext = servletContext;
}
- private static final Log _log = LogFactoryUtil.getLog(
+ private static final Logger _log = LoggerFactory.getLogger(
${capFirstModel}AssetRendererFactory.class);
@Reference
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXWEB_ConfigurationAction.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXWEB_ConfigurationAction.java.ftl
index 9663055..5777e34 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXWEB_ConfigurationAction.java.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXWEB_ConfigurationAction.java.ftl
@@ -9,8 +9,6 @@ package ${packageName}.web.portlet.action;
import aQute.bnd.annotation.metatype.Configurable;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.portlet.ConfigurationAction;
import com.liferay.portal.kernel.portlet.DefaultConfigurationAction;
import com.liferay.portal.kernel.servlet.SessionMessages;
@@ -34,6 +32,9 @@ import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Modified;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* ${capFirstModel} Configuraion Aciton
*
@@ -152,7 +153,7 @@ public class ${capFirstModel}ConfigurationAction extends DefaultConfigurationAct
return valid;
}
- private static final Log _log = LogFactoryUtil.getLog(
+ private static final Logger _log = LoggerFactory.getLogger(
${capFirstModel}ConfigurationAction.class);
private volatile ${capFirstModel}Configuration _${uncapFirstModel}Configuration;
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
index f50469b..5bec50f 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
@@ -10,8 +10,6 @@ package ${packageName}.web.portlet.action;
import com.liferay.asset.display.page.portlet.AssetDisplayPageEntryFormProcessor;
import com.liferay.petra.reflect.ReflectionUtil;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.TrashedModel;
import com.liferay.portal.kernel.portlet.bridges.mvc.BaseMVCActionCommand;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCActionCommand;
@@ -46,6 +44,9 @@ import javax.portlet.ActionResponse;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* @author ${damascus_author}
*/
@@ -248,7 +249,7 @@ public class ${capFirstModel}CrudMVCActionCommand extends BaseMVCActionCommand {
hideDefaultSuccessMessage(request);
}
catch (Exception t) {
- _log.error(t, t);
+ _log.error(t.getLocalizedMessage(), t);
SessionErrors.add(request, PortalException.class);
hideDefaultSuccessMessage(request);
}
@@ -274,7 +275,7 @@ public class ${capFirstModel}CrudMVCActionCommand extends BaseMVCActionCommand {
_${uncapFirstModel}Service = ${uncapFirstModel}Service;
}
- private static Log _log = LogFactoryUtil.getLog(
+ private static Logger _log = LoggerFactory.getLogger(
${capFirstModel}CrudMVCActionCommand.class);
@Reference
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXWEB_DisplayContext.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXWEB_DisplayContext.java.ftl
index 4d76c3c..fe3bbae 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXWEB_DisplayContext.java.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXWEB_DisplayContext.java.ftl
@@ -11,8 +11,6 @@ import com.liferay.portal.kernel.dao.search.DisplayTerms;
import com.liferay.portal.kernel.dao.search.SearchContainer;
import com.liferay.portal.kernel.dao.search.SearchContainerResults;
import com.liferay.portal.kernel.exception.PortalException;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
import com.liferay.portal.kernel.portlet.PortalPreferences;
@@ -42,6 +40,9 @@ import javax.portlet.PortletURL;
import javax.servlet.http.HttpServletRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* ${capFirstModel} Display Context
*
@@ -174,7 +175,7 @@ public class ${capFirstModel}DisplayContext {
return _searchContainer;
}
- private static final Log _log = LogFactoryUtil.getLog(
+ private static final Logger _log = LoggerFactory.getLogger(
${capFirstModel}DisplayContext.class);
private final HttpServletRequest _httpServletRequest;
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXWEB_ViewHelper.java.ftl b/src/test/resources/templates/7.2/Portlet_XXXXWEB_ViewHelper.java.ftl
index 1f336c3..d80a6f2 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXWEB_ViewHelper.java.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXWEB_ViewHelper.java.ftl
@@ -10,8 +10,6 @@ package ${packageName}.web.util;
import com.liferay.portal.kernel.dao.search.DisplayTerms;
import com.liferay.portal.kernel.dao.search.SearchContainer;
import com.liferay.portal.kernel.dao.search.SearchContainerResults;
-import com.liferay.portal.kernel.log.Log;
-import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.Hits;
@@ -41,6 +39,9 @@ import javax.portlet.PortletRequest;
import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* View Helper
*
@@ -276,6 +277,6 @@ public class ${capFirstModel}ViewHelper {
return false;
}
- private static Log _log = LogFactoryUtil.getLog(${capFirstModel}ViewHelper.class);
+ private static Logger _log = LoggerFactory.getLogger(${capFirstModel}ViewHelper.class);
}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/Portlet_XXXXWEB_build.gradle.ftl b/src/test/resources/templates/7.2/Portlet_XXXXWEB_build.gradle.ftl
index be1e44f..3735625 100644
--- a/src/test/resources/templates/7.2/Portlet_XXXXWEB_build.gradle.ftl
+++ b/src/test/resources/templates/7.2/Portlet_XXXXWEB_build.gradle.ftl
@@ -17,33 +17,37 @@ def defaultEncoding = 'UTF-8'
dependencies {
compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.5.0"
- compile group: "org.apache.poi", name: "poi", version: "4.0.1"
- compile group: "org.apache.poi", name: "poi-ooxml", version: "4.0.1"
- compile group: "org.apache.poi", name: "poi-ooxml-schemas", version: "4.0.1"
+ compile group: "org.apache.poi", name: "poi"<#if useTP?? && false == useTP>, version: "4.0.1"#if>
+ compile group: "org.apache.poi", name: "poi-ooxml"<#if useTP?? && false == useTP>, version: "4.0.1"#if>
+ compile group: "org.apache.poi", name: "poi-ooxml-schemas"<#if useTP?? && false == useTP>, version: "4.0.1"#if>
- compileOnly group: "com.liferay", name: "com.liferay.application.list.api", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.asset.api", version: "2.1.+"
- compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.api", version: "5.1.0"
- compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.item.selector.api", version: "2.0.0"
- compileOnly group: "com.liferay", name: "com.liferay.asset.info.display.api", version: "2.1.0"
- compileOnly group: "com.liferay", name: "com.liferay.asset.taglib", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.comment.taglib", version: "2.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.clay", version: "2.1.+"
- compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.soy", version: "3.0.0"
- compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.util", version: "2.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.info.api", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.item.selector.api", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.item.selector.criteria.api", version: "4.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.item.selector.taglib", version: "3.0.+"
- compileOnly group: "com.liferay", name: "com.liferay.petra.reflect", version: "3.0.+"
- compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "4.13.0"
- compileOnly group: "com.liferay.portal", name: "com.liferay.util.taglib", version: "4.1.0"
- compileOnly group: "javax.portlet", name: "portlet-api", version: "3.0.1"
- compileOnly group: "javax.servlet.jsp", name: "javax.servlet.jsp-api", version: "2.3.1"
- compileOnly group: "jstl", name: "jstl", version: "1.2"
+ compileOnly group: "com.liferay", name: "com.liferay.application.list.api"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.api"<#if useTP?? && false == useTP>, version: "2.1.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.api"<#if useTP?? && false == useTP>, version: "5.1.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.item.selector.api"<#if useTP?? && false == useTP>, version: "2.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.info.display.api"<#if useTP?? && false == useTP>, version: "2.1.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.taglib"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.comment.taglib"<#if useTP?? && false == useTP>, version: "2.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.clay"<#if useTP?? && false == useTP>, version: "2.1.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.soy"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.util"<#if useTP?? && false == useTP>, version: "2.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.info.api"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.api"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.criteria.api"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.taglib"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.reflect"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.string"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.function"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.trash.api"<#if useTP?? && false == useTP>, version: "2.0.+"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "4.13.0"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.util.taglib"<#if useTP?? && false == useTP>, version: "4.1.0"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet.jsp", name: "jsp-api"<#if useTP?? && false == useTP>, version: "2.1"#if>
+ compileOnly group: "jstl", name: "jstl"<#if useTP?? && false == useTP>, version: "1.2"#if>
compileOnly group: "org.apache.felix", name: "org.apache.felix.http.servlet-api", version: "1.1.2"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
+ compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.26'
compileOnly project(":${dashcaseProjectName}-api")
compileOnly project(":${dashcaseProjectName}-service")
}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.2/base.json b/src/test/resources/templates/7.2/base.json
index d32a8a6..9cd3602 100644
--- a/src/test/resources/templates/7.2/base.json
+++ b/src/test/resources/templates/7.2/base.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.entityName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.2/base_relation_fail.json b/src/test/resources/templates/7.2/base_relation_fail.json
index a4535a4..d6dd339 100644
--- a/src/test/resources/templates/7.2/base_relation_fail.json
+++ b/src/test/resources/templates/7.2/base_relation_fail.json
@@ -2,6 +2,7 @@
"projectName": "Employee",
"packageName": "com.liferay.sb.employee",
"liferayVersion": "7.1",
+ "useTargetPlatform": "false",
"applications": [{
"model": "Employee",
"title": "Employee Test",
@@ -21,7 +22,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName": "Employees",
"fields": [{
"type": "com.liferay.damascus.cli.json.fields.Long",
"primary": true,
@@ -74,7 +74,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName": "Positions",
"fields": [{
"type": "com.liferay.damascus.cli.json.fields.Long",
"primary": true,
diff --git a/src/test/resources/templates/7.2/base_relation_success.json b/src/test/resources/templates/7.2/base_relation_success.json
index 0b01a65..7d36799 100644
--- a/src/test/resources/templates/7.2/base_relation_success.json
+++ b/src/test/resources/templates/7.2/base_relation_success.json
@@ -2,6 +2,7 @@
"projectName": "Employee",
"packageName": "com.liferay.sb.employee",
"liferayVersion": "7.1",
+ "useTargetPlatform": "false",
"applications": [{
"model": "Employee",
"title": "Employee Test",
@@ -21,7 +22,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName": "Employees",
"fields": [{
"type": "com.liferay.damascus.cli.json.fields.Long",
"primary": true,
@@ -74,7 +74,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName": "Positions",
"fields": [{
"type": "com.liferay.damascus.cli.json.fields.Long",
"primary": true,
diff --git a/src/test/resources/templates/7.2/base_tags_false.json b/src/test/resources/templates/7.2/base_tags_false.json
index a37fdc4..41c65ef 100644
--- a/src/test/resources/templates/7.2/base_tags_false.json
+++ b/src/test/resources/templates/7.2/base_tags_false.json
@@ -2,6 +2,7 @@
"projectName": "${damascus.projectName}",
"packageName" : "${damascus.packageName}",
"liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
"applications": [
{
"model" : "${damascus.projectName}",
@@ -22,7 +23,6 @@
"advancedSearch": "true",
"exportExcel": "true"
},
- "fieldsName" : "${damascus.projectName}s",
"fields": [
{
"type": "com.liferay.damascus.cli.json.fields.Long",
diff --git a/src/test/resources/templates/7.2/valuables.ftl b/src/test/resources/templates/7.2/valuables.ftl
index ecaea31..728c8cb 100644
--- a/src/test/resources/templates/7.2/valuables.ftl
+++ b/src/test/resources/templates/7.2/valuables.ftl
@@ -3,6 +3,7 @@
<#assign packageName = "${damascus.packageName}">
<#assign packagePath = "${packageName?replace(\".\", \"/\")}">
<#assign packageSnake = "${packageName?replace(\".\", \"_\")}">
+<#assign useTP = damascus.isUseTargetPlatform() >
<#assign camelcaseProjectName = "${damascus.projectName?replace(\"-\", \"\")}">
<#assign dashcaseProjectName = "${caseUtil.camelCaseToDashCase(camelcaseProjectName)}">
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXAPI_Constants.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXAPI_Constants.java.ftl
new file mode 100644
index 0000000..f079f8c
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXAPI_Constants.java.ftl
@@ -0,0 +1,22 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/src/main/java/${packagePath}/constants/${capFirstModel}Constants.java">
+/* */
+package ${packageName}.constants;
+
+/**
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}Constants {
+
+ // This name is defined in default.xml, model-name
+
+ public static final String RESOURCE_NAME = "${packageName}";
+
+ // This name is defined in service.xml, package-path
+
+ public static final String SERVICE_NAME = "${packageName}";
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXAPI_PortletKeys.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXAPI_PortletKeys.java.ftl
new file mode 100644
index 0000000..cbe4d86
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXAPI_PortletKeys.java.ftl
@@ -0,0 +1,24 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/src/main/java/${packagePath}/constants/${capFirstModel}PortletKeys.java">
+/* */
+
+package ${packageName}.constants;
+
+/**
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}PortletKeys {
+
+ public static final String ${uppercaseModel} =
+ "${packageSnake}_web_${capFirstModel}Portlet";
+
+ public static final String ${uppercaseModel}_ADMIN =
+ "${packageSnake}_web_${capFirstModel}AdminPortlet";
+
+ public static final String ${uppercaseModel}_CONFIG =
+ "${packageName}.web.portlet.action.${capFirstModel}Configuration";
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXAPI_ValidateException.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXAPI_ValidateException.java.ftl
new file mode 100644
index 0000000..5f7cc34
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXAPI_ValidateException.java.ftl
@@ -0,0 +1,35 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/src/main/java/${packagePath}/exception/${capFirstModel}ValidateException.java">
+/* */
+
+package ${packageName}.exception;
+
+import com.liferay.portal.kernel.exception.PortalException;
+
+import java.util.List;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * @author ${damascus_author}
+ */
+@ProviderType
+public class ${capFirstModel}ValidateException extends PortalException {
+
+ public ${capFirstModel}ValidateException() {
+ }
+
+ public ${capFirstModel}ValidateException(List errors) {
+ _errors = errors;
+ }
+
+ public List getErrors() {
+ return _errors;
+ }
+
+ protected List _errors = null;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXAPI_bnd.bnd.ftl b/src/test/resources/templates/7.3/Portlet_XXXXAPI_bnd.bnd.ftl
new file mode 100644
index 0000000..15675a1
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXAPI_bnd.bnd.ftl
@@ -0,0 +1,16 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/bnd.bnd">
+# #
+Bundle-Name: ${dashcaseProjectName}-api
+Bundle-SymbolicName: ${packageName}.api
+Bundle-Version: 1.0.0
+Export-Package:\
+ ${packageName}.exception,\
+ ${packageName}.model,\
+ ${packageName}.service,\
+ ${packageName}.service.persistence,\
+ ${packageName}.constants
+-check: EXPORTS
+-includeresource: META-INF/service.xml=../${dashcaseProjectName}-service/service.xml
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXAPI_build.gradle.ftl b/src/test/resources/templates/7.3/Portlet_XXXXAPI_build.gradle.ftl
new file mode 100644
index 0000000..80a7214
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXAPI_build.gradle.ftl
@@ -0,0 +1,22 @@
+//
+// //
+<#include "./valuables.ftl">
+<#assign createPath = "${apiModulePath}/build.gradle">
+// //
+apply plugin: 'java'
+apply plugin: 'groovy'
+apply plugin: 'idea'
+apply plugin: 'eclipse'
+
+//Need for Windows
+def defaultEncoding = 'UTF-8'
+
+dependencies {
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "7.2.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"<#if useTP?? && false == useTP>, version: "1.1.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.core"<#if useTP?? && false == useTP>, version: "6.0.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXROOT_README.md.ftl b/src/test/resources/templates/7.3/Portlet_XXXXROOT_README.md.ftl
new file mode 100644
index 0000000..1b94242
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXROOT_README.md.ftl
@@ -0,0 +1,110 @@
+<#include "./valuables.ftl">
+<#assign createPath = "${createPath_val}/${dashcaseProjectName}/README.md">
+# Damascus generated service
+
+Damascus generates scaffolding files to save time for the tedious parts of the development.
+This document explains the tips of adding custom implementations on top of Damascus0generated files and adding your implementations.
+
+# Misc
+### TODO comments
+Todo comments are inserted where customizations/modifications are needed. Please look for TODO tags in the generated project and add your implementations according to your requirements.
+
+### How to add pages?
+Once Damascus generates the bundles, you can add pages as you want according to the basic Liferay portlet mechanism. Damascus generates both Admin and User pages and renders classes separately.
+| File name | Note |
+| :-- | :-- |
+| *ViewMVCRenderCommand.java | Renders ```view.jsp``` |
+| *CrudMVCActionCommand.java | Process ```view/delete/update/``` create a record |
+| *CrudMVCRenderCommand.java | Renders ```edit.jsp``` and ```view.jsp``` according to the actions. |
+
+### How can I modify CRUD implementation?
+According to Liferay's best practices, all model manipulation methods are stored in ```*LocalServiceImpl.java```. Please see ```*LocalServiceImpl.java``` for more details.
+
+From 7.2, permission checking are all delegated into ```*ServiceImpl.java```. ```*LocalServiceImpl.java``` is now only responsible for processing business logic. For more details, please see ```Blogs``` implimentations in the Liferay's source code.
+
+When you modify the signature of methods or add new methods, please run ```gradle buildService``` to regenerate interfaces.
+
+### How can I implement validations?
+```*Validator.java``` includes validations. Please see the comments in the file for more details.
+
+### How can I implement Indexer?
+| File name | Note |
+| :-- | :-- |
+| *SearchRegistrar.java | Register all search related components in there.|
+| *ModelIndexerWriterContributor.java | This class is used during bulk reindexing to identify records to reindex.|
+| *ModelDocumentContributor.java | This class is used to contribute fields to the document to be indexed..|
+| *ModelPreFilterContributor.java | Filters search results before they are returned from the search engine.
+| *ModelResourcePermissionRegistrar.java | Model Resource Permission Registrar |
+| *ModelSummaryContributor.java | Manipulates the Summary object for each entity search result. |
+| *ModelVisibilityContributor.java | Controls the visibility of entities that can be attached to other asset types in the search context. |
+| *KeywordQueryContributor.java | Contributes clauses to the ongoing search query to control how the model entities are searched.|
+
+From 7.2, Search introduces new framework for the implementation, which is more modular and divides each search related functionality into different classes separately. For more details, please see the [official documents](https://help.liferay.com/hc/en-us/sections/360004656871-Search)
+
+### How can I modify permissions?
+```*ModelResourcePermissionRegistrar.java``` and ```*PortletResourcePermissionRegistrar.java``` register permission helpers to the search framework. Please modify these files according to your requirements.
+
+```*Permission.java``` classes are helper classes to check permission.
+
+```default.xml``` under ```*-web/src/main/resources/resource-actions/default.xml``` and ```*-service/src/main/resources/META-INF/resource-actions/default.xml``` contain permission configurations.
+
+### How can I modify view for Asset Publisher?
+```*AssetRenderer.java``` and ```*AssetRendererFactory.java``` render ```abstract.jsp```, ```abstract.jsp``` and ```prewview.jsp``` for ```Asset Framework```. For more details, please see the [official document](https://portal.liferay.dev/docs/7-2/frameworks/-/knowledge_base/f/creating-an-asset-renderer)
+
+# *-web
+This bundle includes classes and java files related to display portlets. This also contains utility classes to handle requests.
+
+| File name | Note |
+| :-- | :-- |
+| *WebPortlet.java | This is an entry point of displaying a portlet in the user area. |
+| *PanelApp.java, *AdminPortlet.java | This is an entry point of displaying a portlet in the administration area (inside of Control Panel) |
+| *PortletLayoutFinder.java | This is used for displaying contents in Asset Publisher with |
+| *AssetRendererFactory.java, *AssetRenderer.java | These classes are used to associate with an asset and generated model. |
+| *ItemSelectorHelper.java | This is used for Documents and Media related operations (such as uploading assets, selecting assets, e.g.) |
+| *ViewHelper.java | This class is a utility class mainly for handling search (search container) |
+
+# *-service
+```*-service``` includes files which allow access to persistent layer, and it's service layer classes, which furthermore allows access database through the models/services. This README is a reference to Damascus-generated files. For more details of files that Liferay service builder generates, please check out http://dev.liferay.com.
+
+## *LocalServiceImpl.java
+This class is an implementation of the service to access the database. Liferay service builder generates the base code for transactions and accessing the database, so you usually don't need to implement database connections/transactions by yourself as long as following Liferay's best practices.
+
+### addEntry* methods
+These methods are for adding records on a database.
+
+### updateEntry* methods
+These methods are for updating records on a database.
+
+### deleteEntry* methods
+These methods are for deleting records on a database.
+
+### moveEntryToTrash* methods
+These methods are for moving records into the trash instead of deleting them from a database.
+
+### find* methods
+According to Liferay's contract, ```find*``` methods are for retrieving a record from the database. For searching, you may want to use the search engine instead of directory searching on the database for better performance as a best practice.
+
+## Permission
+There are 5 files related to permission management
+| File name | Note |
+| :-- | :-- |
+| *Permission.java | Manage Portlet permission |
+| *EntryPermission.java | Manage Model permission |
+| *ModelResourcePermissionRegistrar.java | Register Model permission handler and configure details of permission types |
+| *PortletResourcePermissionRegistrar.java | Register portlet permission handler and configure details of permission types |
+| default.xml | Permission mapping |
+
+## *Validator.java
+This class is for validating data coming from a form in ```edit.jsp``` of ```*-web``` bundle. According to the comments inside, you can implement error handling. After implementing validation, each error method returns the error message key, so you need to add an appropriate error message handler in ```view.jsp``` accordingly. Please refer to the default messages that have already been in place in the ```view.jsp```.
+
+## *WorkflowHandler.java
+This model handles workflows.
+
+## *DisplayContext.java
+This class holds search related context and display contexts.
+
+## *ManagementToolbarDisplayContext.java
+This class process the contents and state of management bar in both Admin and user portlet.
+
+## *ExportMVCResourceCommand.java
+This class process Export model data as csv with Apache POI.
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXROOT_build.gradle.ftl b/src/test/resources/templates/7.3/Portlet_XXXXROOT_build.gradle.ftl
new file mode 100644
index 0000000..f8978dd
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXROOT_build.gradle.ftl
@@ -0,0 +1,27 @@
+//
+// //
+<#include "./valuables.ftl">
+<#assign createPath = "${createPath_val}/${dashcaseProjectName}/build.gradle">
+// //
+
+buildscript {
+ dependencies {
+ classpath group: "com.liferay", name: "com.liferay.gradle.plugins", version: "4.4.49"
+ }
+
+ repositories {
+ maven {
+ url "https://repository-cdn.liferay.com/nexus/content/groups/public"
+ }
+ }
+}
+
+subprojects {
+ apply plugin: "com.liferay.plugin"
+
+ repositories {
+ maven {
+ url "https://repository-cdn.liferay.com/nexus/content/groups/public"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXROOT_settings.gradle.ftl b/src/test/resources/templates/7.3/Portlet_XXXXROOT_settings.gradle.ftl
new file mode 100644
index 0000000..8a7ee6e
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXROOT_settings.gradle.ftl
@@ -0,0 +1,3 @@
+<#include "./valuables.ftl">
+<#assign createPath = "${createPath_val}/${dashcaseProjectName}/settings.gradle">
+include "${dashcaseProjectName}-api", "${dashcaseProjectName}-service"<#if anyGeneratedWeb>, "${dashcaseProjectName}-web"#if>
diff --git a/src/main/resources/templates/7.2/Portlet_XXXXSVC_Indexer.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_Indexer.java.ftl
similarity index 100%
rename from src/main/resources/templates/7.2/Portlet_XXXXSVC_Indexer.java.ftl
rename to src/test/resources/templates/7.3/Portlet_XXXXSVC_Indexer.java.ftl
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl
new file mode 100644
index 0000000..69682a5
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_KeywordQueryContributor.java.ftl
@@ -0,0 +1,50 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/query/contributor/${capFirstModel}KeywordQueryContributor.java">
+/* */
+package ${packageName}.internal.search.query.contributor;
+
+import com.liferay.portal.kernel.search.BooleanQuery;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.search.query.QueryHelper;
+import com.liferay.portal.search.spi.model.query.contributor.KeywordQueryContributor;
+import com.liferay.portal.search.spi.model.query.contributor.helper.KeywordQueryContributorHelper;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Keyword Query Contributor
+ *
+ * Contributes clauses to the ongoing search query to control how the model entities are searched.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = KeywordQueryContributor.class
+)
+public class ${capFirstModel}KeywordQueryContributor implements KeywordQueryContributor {
+
+ @Override
+ public void contribute(String keywords, BooleanQuery booleanQuery,KeywordQueryContributorHelper keywordQueryContributorHelper) {
+ SearchContext searchContext = keywordQueryContributorHelper.getSearchContext();
+
+ // TODO: Adjust as necessary to support the search for the entity
+
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.ARTICLE_ID, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.CLASS_PK, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.ENTRY_CLASS_PK, false);
+ queryHelper.addSearchTerm(booleanQuery, searchContext, Field.USER_NAME, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.CONTENT, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.DESCRIPTION, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.TITLE, false);
+ queryHelper.addSearchLocalizedTerm(booleanQuery, searchContext, Field.SUBTITLE, false);
+ }
+
+ @Reference
+ protected QueryHelper queryHelper;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_LocalServiceImpl.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
new file mode 100644
index 0000000..dbbad25
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_LocalServiceImpl.java.ftl
@@ -0,0 +1,1293 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/impl/${capFirstModel}LocalServiceImpl.java">
+/* */
+
+package ${packageName}.service.impl;
+
+import com.liferay.asset.kernel.model.AssetEntry;
+import com.liferay.asset.kernel.model.AssetLinkConstants;
+import com.liferay.exportimport.kernel.lar.ExportImportThreadLocal;
+import com.liferay.friendly.url.exception.DuplicateFriendlyURLEntryException;
+import com.liferay.friendly.url.model.FriendlyURLEntry;
+import com.liferay.friendly.url.service.FriendlyURLEntryLocalService;
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.aop.AopService;
+import com.liferay.portal.kernel.comment.CommentManagerUtil;
+import com.liferay.portal.kernel.dao.orm.QueryUtil;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.exception.SystemException;
+import com.liferay.portal.kernel.json.JSONFactoryUtil;
+import com.liferay.portal.kernel.json.JSONObject;
+import com.liferay.portal.kernel.model.ModelHintsUtil;
+import com.liferay.portal.kernel.model.ResourceConstants;
+import com.liferay.portal.kernel.model.SystemEventConstants;
+import com.liferay.portal.kernel.model.User;
+import com.liferay.portal.kernel.repository.model.ModelValidator;
+import com.liferay.portal.kernel.search.Indexable;
+import com.liferay.portal.kernel.search.IndexableType;
+import com.liferay.portal.kernel.service.ClassNameLocalService;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.service.permission.ModelPermissions;
+import com.liferay.portal.kernel.systemevent.SystemEvent;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ContentTypes;
+import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.kernel.util.OrderByComparator;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Portal;
+import com.liferay.portal.kernel.util.StringUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.base.${capFirstModel}LocalServiceBaseImpl;
+import ${packageName}.service.util.${capFirstModel}Validator;
+import com.liferay.trash.exception.RestoreEntryException;
+import com.liferay.trash.exception.TrashEntryException;
+import com.liferay.trash.model.TrashEntry;
+import com.liferay.trash.service.TrashEntryLocalService;
+
+import java.io.Serializable;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The implementation of the ${capFirstModel} local service.
+ *
+ *
+ * All custom service methods should be put in this class. Whenever methods are
+ * added, rerun ServiceBuilder to copy their definitions into the
+ * ${packageName}.service.${capFirstModel}LocalService
interface.
+ *
+ *
+ * This is a local service. Methods of this service will not have security
+ * checks based on the propagated JAAS credentials because this service can only
+ * be accessed from within the same VM.
+ *
+ *
+ * @author ${damascus_author}
+ * @see ${capFirstModel}LocalServiceBaseImpl
+ */
+@Component(
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = AopService.class
+)
+public class ${capFirstModel}LocalServiceImpl extends ${capFirstModel}LocalServiceBaseImpl {
+
+ /**
+ * Add Entry
+ *
+ * @param orgEntry ${capFirstModel} model
+ * @param serviceContext ServiceContext
+ * @exception PortalException
+ * @exception ${capFirstModel}ValidateException
+ * @return created ${capFirstModel} model.
+ */
+ @Indexable(type = IndexableType.REINDEX)
+ @Override
+ public ${capFirstModel} addEntry(${capFirstModel} orgEntry, ServiceContext serviceContext)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ long userId = serviceContext.getUserId();
+
+ // Validation
+
+ ModelValidator<${capFirstModel}> modelValidator = new ${capFirstModel}Validator();
+ modelValidator.validate(orgEntry);
+
+ ${capFirstModel} entry = _addEntry(orgEntry, serviceContext);
+
+ // Resources
+
+ if (serviceContext.isAddGroupPermissions() ||
+ serviceContext.isAddGuestPermissions()) {
+
+ addEntryResources(
+ entry, serviceContext.isAddGroupPermissions(),
+ serviceContext.isAddGuestPermissions());
+ }
+ else {
+ addEntryResources(entry, serviceContext.getModelPermissions());
+ }
+
+ // Asset
+
+ updateAsset(
+ userId, entry, serviceContext.getAssetCategoryIds(),
+ serviceContext.getAssetTagNames(),
+ serviceContext.getAssetLinkEntryIds(),
+ serviceContext.getAssetPriority());
+
+ // Workflow
+
+ return startWorkflowInstance(userId, entry, serviceContext);
+ }
+
+ @Override
+ public void addEntryResources(
+ long entryId, boolean addGroupPermissions,
+ boolean addGuestPermissions)
+ throws PortalException {
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ addEntryResources(entry, addGroupPermissions, addGuestPermissions);
+ }
+
+ @Override
+ public void addEntryResources(
+ long entryId, ModelPermissions modelPermissions)
+ throws PortalException {
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ addEntryResources(entry, modelPermissions);
+ }
+
+ @Override
+ public void addEntryResources(
+ ${capFirstModel} entry, boolean addGroupPermissions,
+ boolean addGuestPermissions)
+ throws PortalException {
+
+ resourceLocalService.addResources(
+ entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), false,
+ addGroupPermissions, addGuestPermissions);
+ }
+
+ @Override
+ public void addEntryResources(
+ ${capFirstModel} entry, ModelPermissions modelPermissions)
+ throws PortalException {
+
+ resourceLocalService.addModelResources(
+ entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), modelPermissions);
+ }
+
+ public int countAllInGroup(long groupId) {
+ int count = ${uncapFirstModel}Persistence.countByGroupId(groupId);
+
+ return count;
+ }
+
+ public int countAllInGroup(long groupId, int[] status) {
+ int count = ${uncapFirstModel}Persistence.countByG_S(groupId, status);
+
+ return count;
+ }
+
+ public int countAllInUser(long userId) {
+ int count = ${uncapFirstModel}Persistence.countByUserId(userId);
+
+ return count;
+ }
+
+ public int countAllInUser(long userId, int[] status) {
+ int count = ${uncapFirstModel}Persistence.countByU_S(userId, status);
+
+ return count;
+ }
+
+ public int countAllInUserAndGroup(long userId, long groupId) {
+ int count = ${uncapFirstModel}Persistence.countByUserIdGroupId(userId, groupId);
+
+ return count;
+ }
+
+ public int countAllInUserAndGroup(long userId, long groupId, int[] status) {
+ int count = ${uncapFirstModel}Persistence.countByG_U_S(groupId, userId, status);
+
+ return count;
+ }
+
+ /**
+ * Delete entry
+ */
+ public ${capFirstModel} deleteEntry(long primaryKey) throws PortalException {
+ ${capFirstModel} entry = get${capFirstModel}(primaryKey);
+
+ return deleteEntry(entry);
+ }
+
+ /**
+ * Delete entry
+ *
+ * @param entry ${capFirstModel}
+ * @return ${capFirstModel} oject
+ * @exception PortalException
+ */
+ @Indexable(type = IndexableType.DELETE)
+ @Override
+ @SystemEvent(type = SystemEventConstants.TYPE_DELETE)
+ public ${capFirstModel} deleteEntry(${capFirstModel} entry) throws PortalException {
+
+ // Entry
+
+ ${uncapFirstModel}Persistence.remove(entry);
+
+ // Resources
+
+ resourceLocalService.deleteResource(
+ entry.getCompanyId(), ${capFirstModel}.class.getName(),
+ ResourceConstants.SCOPE_INDIVIDUAL, entry.getPrimaryKey());
+
+ // Asset
+
+ assetEntryLocalService.deleteEntry(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey());
+
+ // Comment
+
+ deleteDiscussion(entry);
+
+ // Friendly URL
+
+ _friendlyURLEntryLocalService.deleteFriendlyURLEntry(
+ entry.getGroupId(), ${capFirstModel}.class, entry.getPrimaryKey());
+
+ // Trash
+
+ _trashEntryLocalService.deleteEntry(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey());
+
+ // Workflow
+
+ workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
+ entry.getCompanyId(), entry.getGroupId(), ${capFirstModel}.class.getName(),
+ entry.getPrimaryKey());
+
+ return entry;
+ }
+
+ public List<${capFirstModel}> findAllInGroup(long groupId) {
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByGroupId(
+ groupId);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInGroup(
+ long groupId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ return findAllInGroup(
+ groupId, start, end, orderByComparator,
+ new int[] {WorkflowConstants.STATUS_APPROVED});
+ }
+
+ public List<${capFirstModel}> findAllInGroup(
+ long groupId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator, int[] status) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByG_S(
+ groupId, status, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInGroup(long groupId, int[] status) {
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByG_S(
+ groupId, status);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInGroup(
+ long groupId, OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)findAllInGroup(
+ groupId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(long userId) {
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByUserId(
+ userId);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(
+ long userId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByUserId(
+ userId, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(
+ long userId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator, int[] status) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByU_S(
+ userId, status, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(long userId, int[] status) {
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByU_S(
+ userId, status);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUser(
+ long userId, OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)findAllInUser(
+ userId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(long userId, long groupId) {
+ List<${capFirstModel}> list =
+ (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByUserIdGroupId(
+ userId, groupId);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(
+ long userId, long groupId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list =
+ (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByUserIdGroupId(
+ groupId, userId, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(
+ long userId, long groupId, int start, int end,
+ OrderByComparator<${capFirstModel}> orderByComparator, int[] status) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByG_U_S(
+ groupId, userId, status, start, end, orderByComparator);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(
+ long userId, long groupId, int[] status) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)${uncapFirstModel}Persistence.findByG_U_S(
+ groupId, userId, status);
+
+ return list;
+ }
+
+ public List<${capFirstModel}> findAllInUserAndGroup(
+ long userId, long groupId,
+ OrderByComparator<${capFirstModel}> orderByComparator) {
+
+ List<${capFirstModel}> list = (List<${capFirstModel}>)findAllInUserAndGroup(
+ groupId, userId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
+ orderByComparator);
+
+ return list;
+ }
+
+ /**
+ * Get Company entries
+ *
+ * @param companyId Company Id
+ * @param status Workflow status
+ * @param start start index of entries
+ * @param end end index of entries
+ * @return
+ * @throws SystemException
+ */
+ public List<${capFirstModel}> getCompanyEntries(
+ long companyId, int status, int start, int end) {
+
+ if (status == WorkflowConstants.STATUS_ANY) {
+ return ${uncapFirstModel}Persistence.findByCompanyId(companyId, start, end);
+ }
+
+ return ${uncapFirstModel}Persistence.findByC_S(companyId, status, start, end);
+ }
+
+ /**
+ * Get Company entries
+ *
+ * @param companyId Company Id
+ * @param status Workflow status
+ * @param start start index of entries
+ * @param end end index of entries
+ * @param obc Comparator for the order
+ * @return List of entries
+ * @throws SystemException
+ */
+ public List<${capFirstModel}> getCompanyEntries(
+ long companyId, int status, int start, int end,
+ OrderByComparator<${capFirstModel}> obc) {
+
+ if (status == WorkflowConstants.STATUS_ANY) {
+ return ${uncapFirstModel}Persistence.findByCompanyId(
+ companyId, start, end, obc);
+ }
+
+ return ${uncapFirstModel}Persistence.findByC_S(
+ companyId, status, start, end, obc);
+ }
+
+ /**
+ * Get Company entries counts
+ *
+ * @param companyId
+ * @param status
+ * @return
+ * @throws SystemException
+ */
+ public int getCompanyEntriesCount(long companyId, int status) {
+ if (status == WorkflowConstants.STATUS_ANY) {
+ return ${uncapFirstModel}Persistence.countByCompanyId(companyId);
+ }
+
+ return ${uncapFirstModel}Persistence.countByC_S(companyId, status);
+ }
+
+ /**
+ * Converte Date Time into Date()
+ *
+ * @param request PortletRequest
+ * @param prefix Prefix of the parameter
+ * @return Date object
+ */
+ public Date getDateTimeFromRequest(PortletRequest request, String prefix) {
+ int Year = ParamUtil.getInteger(request, prefix + "Year");
+ int Month = ParamUtil.getInteger(request, prefix + "Month") + 1;
+ int Day = ParamUtil.getInteger(request, prefix + "Day");
+ int Hour = ParamUtil.getInteger(request, prefix + "Hour");
+ int Minute = ParamUtil.getInteger(request, prefix + "Minute");
+ int AmPm = ParamUtil.getInteger(request, prefix + "AmPm");
+
+ if (AmPm == Calendar.PM) {
+ Hour += 12;
+ }
+
+ LocalDateTime ldt;
+
+ try {
+ ldt = LocalDateTime.of(Year, Month, Day, Hour, Minute, 0);
+ }
+ catch (Exception e) {
+ _log.error(
+ "Unnable get date data. Initialize with current date", e);
+ Date in = new Date();
+
+ Instant instant = in.toInstant();
+
+ return Date.from(instant);
+ }
+
+ return Date.from(
+ ldt.atZone(
+ ZoneId.systemDefault()
+ ).toInstant());
+ }
+
+ /**
+ * Populate Model with values from a form
+ *
+ * @param primaryKey primary key
+ * @param request PortletRequest
+ * @return ${capFirstModel} Object
+ * @throws PortletException
+ */
+ public ${capFirstModel} getInitialized${capFirstModel}(
+ long primaryKey, PortletRequest request)
+ throws PortletException {
+
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ // Create or fetch existing data
+
+ ${capFirstModel} entry = getNewObject(primaryKey);
+
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Long" >
+ <#if field.primary?? && field.primary == true >
+ entry.set${field.name?cap_first}(primaryKey);
+ <#else>
+ entry.set${field.name?cap_first}(0);
+ #if>
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" >
+ entry.set${field.name?cap_first}("");
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Date" >
+ entry.set${field.name?cap_first}(new Date());
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" >
+ entry.set${field.name?cap_first}(new Date());
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" >
+ entry.set${field.name?cap_first}(true);
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+ entry.set${field.name?cap_first}("");
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Double" >
+ entry.set${field.name?cap_first}(0.0);
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Integer" >
+ entry.set${field.name?cap_first}(0);
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ entry.set${field.name?cap_first}("");
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Text" >
+ entry.set${field.name?cap_first}("");
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+ entry.set${application.asset.assetTitleFieldName?cap_first}("");
+ entry.set${application.asset.assetSummaryFieldName?cap_first}("");
+
+ entry.setCompanyId(themeDisplay.getCompanyId());
+ entry.setGroupId(themeDisplay.getScopeGroupId());
+ entry.setUserId(themeDisplay.getUserId());
+
+ return entry;
+ }
+
+ /**
+ * Get Record
+ *
+ * @param primaryKey Primary key
+ * @return ${capFirstModel} object
+ * @throws PortletException
+ */
+ public ${capFirstModel} getNewObject(long primaryKey) {
+ primaryKey = (primaryKey <= 0) ? 0 :
+ counterLocalService.increment(${capFirstModel}.class.getName());
+
+ return create${capFirstModel}(primaryKey);
+ }
+
+ /**
+ * Get Entity
+ *
+ * @param groupId
+ * @param urlTitle
+ * @return
+ * @throws PortalException
+ */
+ public ${capFirstModel} get${capFirstModel}(long groupId, String urlTitle)
+ throws PortalException {
+
+ FriendlyURLEntry friendlyURLEntry =
+ _friendlyURLEntryLocalService.fetchFriendlyURLEntry(
+ groupId, ${capFirstModel}.class, urlTitle);
+
+ if (friendlyURLEntry != null) {
+ return ${uncapFirstModel}Persistence.findByPrimaryKey(
+ friendlyURLEntry.getClassPK());
+ }
+
+ return ${uncapFirstModel}Persistence.findByG_UT(groupId, urlTitle);
+ }
+
+ /**
+ * Populate Model with values from a form
+ *
+ * @param request PortletRequest
+ * @return ${capFirstModel} Object
+ * @throws PortletException
+ * @throws ${capFirstModel}ValidateException
+ */
+ public ${capFirstModel} get${capFirstModel}FromRequest(
+ long primaryKey, PortletRequest request)
+ throws PortletException, ${capFirstModel}ValidateException {
+
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ // Create or fetch existing data
+
+ ${capFirstModel} entry;
+
+ if (primaryKey <= 0) {
+ entry = getNewObject(primaryKey);
+ }
+ else {
+ entry = fetch${capFirstModel}(primaryKey);
+ }
+
+ try {
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Long" >
+ <#if field.primary?? && field.primary == true >
+ entry.set${field.name?cap_first}(primaryKey);
+ <#else>
+ entry.set${field.name?cap_first}(ParamUtil.getLong(request, "${field.name}"));
+ #if>
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" >
+ entry.set${field.name?cap_first}(ParamUtil.getString(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Date" >
+ entry.set${field.name?cap_first}(getDateTimeFromRequest(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" >
+ entry.set${field.name?cap_first}(getDateTimeFromRequest(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" >
+ entry.set${field.name?cap_first}(ParamUtil.getBoolean(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+ entry.set${field.name?cap_first}(ParamUtil.getString(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Double" >
+ entry.set${field.name?cap_first}(ParamUtil.getDouble(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Integer" >
+ entry.set${field.name?cap_first}(ParamUtil.getInteger(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ entry.set${field.name?cap_first}(ParamUtil.getString(request, "${field.name}"));
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Text" >
+ entry.set${field.name?cap_first}(ParamUtil.getString(request, "${field.name}"));
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+
+ entry.set${application.asset.assetTitleFieldName?cap_first}(
+ ParamUtil.getString(request, "${application.asset.assetTitleFieldName}"));
+ entry.set${application.asset.assetSummaryFieldName?cap_first}(
+ ParamUtil.getString(request, "${application.asset.assetSummaryFieldName}"));
+
+ entry.setCompanyId(themeDisplay.getCompanyId());
+ entry.setGroupId(themeDisplay.getScopeGroupId());
+ entry.setUserId(themeDisplay.getUserId());
+ }
+ catch (Exception e) {
+ _log.error("Errors occur while populating the model", e);
+ List error = new ArrayList<>();
+ error.add("value-convert-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ return entry;
+ }
+
+ /**
+ * Get STATUS_ANY for DB
+ *
+ * This is equivalent of WorkflowConstants.STATUS_ANY
+ *
+ * @return All statuses for Workflow
+ */
+ public int[] getStatusAny() {
+ return STATUS_ANY;
+ }
+
+ public ${capFirstModel} moveEntryToTrash(long userId, long entryId)
+ throws PortalException {
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ return moveEntryToTrash(userId, entry);
+ }
+
+ /**
+ * Moves the entry to the recycle bin.
+ *
+ * Social activity counters for this entry get disabled.
+ *
+ * @param userId the primary key of the user moving the entry
+ * @param entry the entry to be moved
+ * @return the moved entry
+ */
+ @Indexable(type = IndexableType.REINDEX)
+ @Override
+ public ${capFirstModel} moveEntryToTrash(long userId, ${capFirstModel} entry)
+ throws PortalException {
+
+ // Entry
+
+ if (entry.isInTrash()) {
+ throw new TrashEntryException();
+ }
+
+ int oldStatus = entry.getStatus();
+
+ if (oldStatus == WorkflowConstants.STATUS_PENDING) {
+ entry.setStatus(WorkflowConstants.STATUS_DRAFT);
+
+ ${uncapFirstModel}Persistence.update(entry);
+ }
+
+ entry = updateStatus(
+ userId, entry.getPrimaryKey(), WorkflowConstants.STATUS_IN_TRASH,
+ new ServiceContext(), new HashMap());
+
+ // Workflow
+
+ if (oldStatus == WorkflowConstants.STATUS_PENDING) {
+ workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
+ entry.getCompanyId(), entry.getGroupId(),
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey());
+ }
+
+ return entry;
+ }
+
+ /**
+ * Restores the entry with the ID from the recycle bin. Social activity counters
+ * for this entry get activated.
+ *
+ * @param userId the primary key of the user restoring the entry
+ * @param entryId the primary key of the entry to be restored
+ * @return the restored entry from the recycle bin
+ */
+ @Indexable(type = IndexableType.REINDEX)
+ @Override
+ public ${capFirstModel} restoreEntryFromTrash(long userId, long entryId)
+ throws PortalException {
+
+ // Entry
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ if (!entry.isInTrash()) {
+ throw new RestoreEntryException(
+ RestoreEntryException.INVALID_STATUS);
+ }
+
+ TrashEntry trashEntry = _trashEntryLocalService.getEntry(
+ ${capFirstModel}.class.getName(), entryId);
+
+ updateStatus(
+ userId, entryId, trashEntry.getStatus(), new ServiceContext(),
+ new HashMap());
+
+ return entry;
+ }
+
+ @Override
+ public void updateAsset(
+ long userId, ${capFirstModel} entry, long[] assetCategoryIds,
+ String[] assetTagNames, long[] assetLinkEntryIds, Double priority)
+ throws PortalException {
+
+ boolean visible = false;
+
+ if (entry.isApproved()) {
+ visible = true;
+ }
+
+ String summary = HtmlUtil.extractText(
+ StringUtil.shorten(entry.get${application.asset.assetSummaryFieldName?cap_first}(), 500));
+
+ AssetEntry assetEntry = assetEntryLocalService.updateEntry(
+ userId, entry.getGroupId(), entry.getCreateDate(),
+ entry.getModifiedDate(), ${capFirstModel}.class.getName(),
+ entry.getPrimaryKey(), entry.getUuid(), 0, assetCategoryIds,
+ assetTagNames, true, visible, null, null, null, null,
+ ContentTypes.TEXT_HTML, entry.get${application.asset.assetTitleFieldName?cap_first}(), null, summary,
+ null, null, 0, 0, priority);
+
+ assetLinkLocalService.updateLinks(
+ userId, assetEntry.getEntryId(), assetLinkEntryIds,
+ AssetLinkConstants.TYPE_RELATED);
+ }
+
+ /**
+ * Edit Entry
+ *
+ * @param orgEntry ${capFirstModel} model
+ * @param serviceContext ServiceContext
+ * @exception PortalException
+ * @exception ${capFirstModel}ValidateException
+ * @return updated ${capFirstModel} model.
+ */
+ @Indexable(type = IndexableType.REINDEX)
+ @Override
+ public ${capFirstModel} updateEntry(
+ ${capFirstModel} orgEntry, ServiceContext serviceContext)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ User user = userLocalService.getUser(orgEntry.getUserId());
+
+ // Validation
+
+ ModelValidator<${capFirstModel}> modelValidator = new ${capFirstModel}Validator();
+ modelValidator.validate(orgEntry);
+
+ // Update entry
+
+ ${capFirstModel} entry = _updateEntry(
+ orgEntry.getPrimaryKey(), orgEntry, serviceContext);
+
+ if (!entry.isPending() && !entry.isDraft()) {
+ entry.setStatus(WorkflowConstants.STATUS_DRAFT);
+ }
+
+ ${capFirstModel} updatedEntry = ${uncapFirstModel}Persistence.update(entry);
+
+ // Asset
+
+ updateAsset(
+ updatedEntry.getUserId(), updatedEntry,
+ serviceContext.getAssetCategoryIds(),
+ serviceContext.getAssetTagNames(),
+ serviceContext.getAssetLinkEntryIds(),
+ serviceContext.getAssetPriority());
+
+ updatedEntry = startWorkflowInstance(
+ user.getUserId(), updatedEntry, serviceContext);
+
+ return updatedEntry;
+ }
+
+ @Override
+ public void updateEntryResources(
+ ${capFirstModel} entry, String[] groupPermissions,
+ String[] guestPermissions)
+ throws PortalException {
+
+ resourceLocalService.updateResources(
+ entry.getCompanyId(), entry.getGroupId(), ${capFirstModel}.class.getName(),
+ entry.getPrimaryKey(), groupPermissions, guestPermissions);
+ }
+
+ @Indexable(type = IndexableType.REINDEX)
+ public ${capFirstModel} updateStatus(
+ long userId, long entryId, int status,
+ ServiceContext serviceContext,
+ Map workflowContext)
+ throws PortalException {
+
+ // Entry
+
+ User user = userLocalService.getUser(userId);
+ Date now = new Date();
+
+ ${capFirstModel} entry = ${uncapFirstModel}Persistence.findByPrimaryKey(entryId);
+
+ int oldStatus = entry.getStatus();
+
+ entry.setModifiedDate(serviceContext.getModifiedDate(now));
+ entry.setStatus(status);
+ entry.setStatusByUserId(user.getUserId());
+ entry.setStatusByUserName(user.getFullName());
+ entry.setStatusDate(serviceContext.getModifiedDate(now));
+
+ ${uncapFirstModel}Persistence.update(entry);
+
+ AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
+ ${capFirstModel}.class.getName(), entryId);
+
+ if ((assetEntry == null) || (assetEntry.getPublishDate() == null)) {
+ serviceContext.setCommand(Constants.ADD);
+ }
+
+ JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
+
+ extraDataJSONObject.put("title", entry.get${application.asset.assetTitleFieldName?cap_first}());
+
+ if (status == WorkflowConstants.STATUS_APPROVED) {
+
+ // Asset
+
+ assetEntryLocalService.updateEntry(
+ ${capFirstModel}.class.getName(), entryId, entry.getModifiedDate(),
+ null, true, true);
+
+ // Trash
+
+ if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
+ CommentManagerUtil.restoreDiscussionFromTrash(
+ ${capFirstModel}.class.getName(), entryId);
+
+ _trashEntryLocalService.deleteEntry(
+ ${capFirstModel}.class.getName(), entryId);
+ }
+ }
+ else {
+
+ // Asset
+
+ assetEntryLocalService.updateVisible(
+ ${capFirstModel}.class.getName(), entryId, false);
+
+ // Trash
+
+ if (status == WorkflowConstants.STATUS_IN_TRASH) {
+ CommentManagerUtil.moveDiscussionToTrash(
+ ${capFirstModel}.class.getName(), entryId);
+ _trashEntryLocalService.addTrashEntry(
+ userId, entry.getGroupId(), ${capFirstModel}.class.getName(),
+ entry.getPrimaryKey(), entry.getUuid(), null, oldStatus,
+ null, null);
+ }
+ else if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
+ CommentManagerUtil.restoreDiscussionFromTrash(
+ ${capFirstModel}.class.getName(), entryId);
+
+ _trashEntryLocalService.deleteEntry(
+ ${capFirstModel}.class.getName(), entryId);
+ }
+ }
+
+ return entry;
+ }
+
+ /**
+ * Copy models at add entry
+ *
+ * To process storing a record into database, copy the model passed into a new
+ * model object here.
+ *
+ * @param entry model object
+ * @param serviceContext ServiceContext
+ * @return
+ * @throws PortalException
+ */
+ protected ${capFirstModel} _addEntry(${capFirstModel} entry, ServiceContext serviceContext)
+ throws PortalException {
+
+ long id = counterLocalService.increment(${capFirstModel}.class.getName());
+
+ ${capFirstModel} newEntry = ${uncapFirstModel}Persistence.create(id);
+
+ User user = userLocalService.getUser(entry.getUserId());
+
+ Date now = new Date();
+ newEntry.setCompanyId(entry.getCompanyId());
+ newEntry.setGroupId(entry.getGroupId());
+ newEntry.setUserId(user.getUserId());
+ newEntry.setUserName(user.getFullName());
+ newEntry.setCreateDate(now);
+ newEntry.setModifiedDate(now);
+
+ newEntry.setUuid(serviceContext.getUuid());
+
+ // Friendly URLs
+ String urlTitle = getUniqueUrlTitle(newEntry, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ urlTitle = updateFriendlyURLs(newEntry, urlTitle, serviceContext);
+ newEntry.setUrlTitle(urlTitle);
+
+ newEntry.set${application.asset.assetTitleFieldName?cap_first}(entry.get${application.asset.assetTitleFieldName?cap_first}());
+ newEntry.set${application.asset.assetSummaryFieldName?cap_first}(entry.get${application.asset.assetSummaryFieldName?cap_first}());
+
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- Primary key is ommited here because the pk is already created in newEntry -->
+ <#if field.primary?? && field.primary == false >
+ newEntry.set${field.name?cap_first}(entry.get${field.name?cap_first}());
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+
+ return ${uncapFirstModel}Persistence.update(newEntry);
+ }
+
+ /**
+ * Copy models at update entry
+ *
+ * To process storing a record into database, copy the model passed into a new
+ * model object here.
+ *
+ * @param primaryKey Primary key
+ * @param entry model object
+ * @param serviceContext ServiceContext
+ * @return updated entry
+ * @throws PortalException
+ */
+ protected ${capFirstModel} _updateEntry(
+ long primaryKey, ${capFirstModel} entry, ServiceContext serviceContext)
+ throws PortalException {
+
+ ${capFirstModel} updateEntry = fetch${capFirstModel}(primaryKey);
+
+ User user = userLocalService.getUser(entry.getUserId());
+
+ Date now = new Date();
+ updateEntry.setCompanyId(entry.getCompanyId());
+ updateEntry.setGroupId(entry.getGroupId());
+ updateEntry.setUserId(user.getUserId());
+ updateEntry.setUserName(user.getFullName());
+ updateEntry.setCreateDate(entry.getCreateDate());
+ updateEntry.setModifiedDate(now);
+
+ updateEntry.setUuid(entry.getUuid());
+ String urlTitle = entry.get${application.asset.assetTitleFieldName?cap_first}();
+ if (Validator.isNotNull(urlTitle)) {
+ long classNameId = _classNameLocalService.getClassNameId(
+ ${capFirstModel}.class);
+
+ try{
+ _friendlyURLEntryLocalService.validate(
+ entry.getGroupId(), classNameId, primaryKey, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ } catch(DuplicateFriendlyURLEntryException e) {
+ List error = new ArrayList();
+ error.add("duplicated-url-title");
+ throw new ${capFirstModel}ValidateException(error);
+ }
+ }
+ else {
+ urlTitle = getUniqueUrlTitle(entry, urlTitle);
+ }
+
+ if (!urlTitle.equals(entry.getUrlTitle())) {
+ urlTitle = updateFriendlyURLs(entry, urlTitle, serviceContext);
+ }
+
+ updateEntry.setUrlTitle(
+ getUniqueUrlTitle(updateEntry, urlTitle));
+
+ updateEntry.set${application.asset.assetTitleFieldName?cap_first}(entry.get${application.asset.assetTitleFieldName?cap_first}());
+ updateEntry.set${application.asset.assetSummaryFieldName?cap_first}(entry.get${application.asset.assetSummaryFieldName?cap_first}());
+
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ updateEntry.set${field.name?cap_first}(entry.get${field.name?cap_first}());
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+
+ return updateEntry;
+ }
+
+ /**
+ * Update Friendly URLs
+ *
+ * @param entry ${capFirstModel}
+ * @param urlTitle
+ * @param serviceContext
+ * @return string
+ * @throws PortalException
+ */
+ protected String updateFriendlyURLs(
+ ${capFirstModel} entry, String urlTitle,
+ ServiceContext serviceContext)
+ throws PortalException {
+
+ if (ExportImportThreadLocal.isImportInProcess() ||
+ ExportImportThreadLocal.isStagingInProcess()) {
+
+ return urlTitle;
+ }
+
+ List friendlyURLEntries =
+ _friendlyURLEntryLocalService.getFriendlyURLEntries(
+ entry.getGroupId(),
+ classNameLocalService.getClassNameId(${capFirstModel}.class),
+ entry.getPrimaryKey());
+
+ FriendlyURLEntry newFriendlyURLEntry =
+ _friendlyURLEntryLocalService.addFriendlyURLEntry(
+ entry.getGroupId(),
+ classNameLocalService.getClassNameId(${capFirstModel}.class),
+ entry.getPrimaryKey(), urlTitle, serviceContext);
+
+ for (FriendlyURLEntry friendlyURLEntry : friendlyURLEntries) {
+ if (newFriendlyURLEntry.getFriendlyURLEntryId() ==
+ friendlyURLEntry.getFriendlyURLEntryId()) {
+
+ continue;
+ }
+
+ _friendlyURLEntryLocalService.deleteFriendlyURLEntry(friendlyURLEntry);
+ }
+
+ return newFriendlyURLEntry.getUrlTitle();
+ }
+
+ /**
+ * Delete discussion (comments)
+ *
+ * @param entry
+ * @throws PortalException
+ */
+ protected void deleteDiscussion(${capFirstModel} entry) throws PortalException {
+ CommentManagerUtil.deleteDiscussion(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey());
+ }
+
+ /**
+ * Generating a unique URL for asset
+ */
+ protected String getUniqueUrlTitle(${capFirstModel} entry, String newTitle) {
+ long entryId = entry.getPrimaryKey();
+
+ String urlTitle = null;
+
+ if (newTitle == null || newTitle.equals("")) {
+ urlTitle = String.valueOf(entryId);
+ }
+ else {
+ urlTitle = StringUtil.toLowerCase(newTitle.trim());
+
+ if (Validator.isNull(urlTitle) || Validator.isNumber(urlTitle) ||
+ urlTitle.equals("rss")) {
+
+ urlTitle = String.valueOf(entryId);
+ }
+ else {
+ urlTitle =
+ FriendlyURLNormalizerUtil.normalizeWithPeriodsAndSlashes(
+ urlTitle);
+ }
+
+ urlTitle = ModelHintsUtil.trimString(
+ ${capFirstModel}.class.getName(), "urlTitle", urlTitle);
+ }
+
+ long classNameId = _classNameLocalService.getClassNameId(
+ ${capFirstModel}.class);
+
+ return _friendlyURLEntryLocalService.getUniqueUrlTitle(
+ entry.getGroupId(), classNameId, entry.getPrimaryKey(), urlTitle);
+ }
+
+ /**
+ * Generating URL Title for unique URL
+ *
+ * @param entryId primaryKey of the model
+ * @param title title for the asset
+ * @return URL title string
+ */
+ protected String getUrlTitle(long entryId, String title) {
+ if (title == null) {
+ return String.valueOf(entryId);
+ }
+
+ title = StringUtil.toLowerCase(title.trim());
+
+ if (Validator.isNull(title) || Validator.isNumber(title)) {
+ title = String.valueOf(entryId);
+ }
+ else {
+ title = FriendlyURLNormalizerUtil.normalizeWithPeriodsAndSlashes(
+ title);
+ }
+
+ return ModelHintsUtil.trimString(
+ ${capFirstModel}.class.getName(), "urlTitle", title);
+ }
+
+ /**
+ * Start workflow
+ *
+ * @param userId User id of this model's owner
+ * @param entry model object
+ * @param serviceContext ServiceContext
+ * @return model with workflow configrations.
+ * @throws PortalException
+ */
+ protected ${capFirstModel} startWorkflowInstance(
+ long userId, ${capFirstModel} entry, ServiceContext serviceContext)
+ throws PortalException {
+
+ Map workflowContext = new HashMap<>();
+
+ String userPortraitURL = StringPool.BLANK;
+ String userURL = StringPool.BLANK;
+
+ if (serviceContext.getThemeDisplay() != null) {
+ User user = userLocalService.getUser(userId);
+
+ userPortraitURL = user.getPortraitURL(
+ serviceContext.getThemeDisplay());
+ userURL = user.getDisplayURL(serviceContext.getThemeDisplay());
+ }
+
+ workflowContext.put(
+ WorkflowConstants.CONTEXT_USER_PORTRAIT_URL, userPortraitURL);
+ workflowContext.put(WorkflowConstants.CONTEXT_USER_URL, userURL);
+
+ return WorkflowHandlerRegistryUtil.startWorkflowInstance(
+ entry.getCompanyId(), entry.getGroupId(), userId,
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), entry,
+ serviceContext, workflowContext);
+ }
+
+ private static final int[] STATUS_ANY = {
+ WorkflowConstants.STATUS_APPROVED, WorkflowConstants.STATUS_DENIED,
+ WorkflowConstants.STATUS_DRAFT, WorkflowConstants.STATUS_EXPIRED,
+ WorkflowConstants.STATUS_IN_TRASH, WorkflowConstants.STATUS_INACTIVE,
+ WorkflowConstants.STATUS_INCOMPLETE, WorkflowConstants.STATUS_PENDING,
+ WorkflowConstants.STATUS_SCHEDULED
+ };
+
+ private static Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}LocalServiceImpl.class);
+
+ @Reference
+ private ClassNameLocalService _classNameLocalService;
+
+ @Reference
+ private FriendlyURLEntryLocalService _friendlyURLEntryLocalService;
+
+ @Reference
+ private Portal _portal;
+
+ @Reference
+ private TrashEntryLocalService _trashEntryLocalService;
+
+}
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl
new file mode 100644
index 0000000..d4375b6
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelDocumentContributor.java.ftl
@@ -0,0 +1,45 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/index/contributor/${capFirstModel}ModelDocumentContributor.java">
+/* */
+package ${packageName}.internal.search.index.contributor;
+
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.search.spi.model.index.contributor.ModelDocumentContributor;
+import org.osgi.service.component.annotations.Component;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Model Document Contributor
+ *
+ * This class is used to contribute fields to the document to be indexed.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelDocumentContributor.class
+)
+public class ${capFirstModel}ModelDocumentContributor implements ModelDocumentContributor<${capFirstModel}> {
+
+ @Override
+ public void contribute(Document document, ${capFirstModel} entry) {
+
+ // TODO : These fields should be modified according to your requirements.
+
+ document.addText(Field.CAPTION, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(
+ Field.CONTENT,
+ HtmlUtil.extractText(entry.get${application.asset.assetSummaryFieldName?cap_first}()));
+ document.addText(Field.DESCRIPTION, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(Field.SUBTITLE, entry.get${application.asset.assetTitleFieldName?cap_first}());
+ document.addText(Field.TITLE, entry.get${application.asset.assetTitleFieldName?cap_first}());
+
+ document.addDate(Field.MODIFIED_DATE, entry.getModifiedDate());
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl
new file mode 100644
index 0000000..c7f86c0
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelIndexWriterContributor.java.ftl
@@ -0,0 +1,89 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/index/contributor/${capFirstModel}ModelIndexerWriterContributor.java">
+/* */
+package ${packageName}.internal.search.index.contributor;
+
+import com.liferay.portal.kernel.dao.orm.Property;
+import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.search.batch.BatchIndexingActionable;
+import com.liferay.portal.search.batch.DynamicQueryBatchIndexingActionableFactory;
+import com.liferay.portal.search.spi.model.index.contributor.ModelIndexerWriterContributor;
+import com.liferay.portal.search.spi.model.index.contributor.helper.IndexerWriterMode;
+import com.liferay.portal.search.spi.model.index.contributor.helper.ModelIndexerWriterDocumentHelper;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+/**
+ * ${capFirstModel} Model Indexer Writer Contributor
+ *
+ * This class is used during bulk reindexing to identify records to reindex.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelIndexerWriterContributor.class
+)
+public class ${capFirstModel}ModelIndexerWriterContributor implements ModelIndexerWriterContributor<${capFirstModel}> {
+
+ @Override
+ public void customize(BatchIndexingActionable batchIndexingActionable, ModelIndexerWriterDocumentHelper modelIndexerWriterDocumentHelper) {
+
+ // TODO: add criteria to the DQ to select the entities to include in the reindex.
+ batchIndexingActionable.setAddCriteriaMethod(dynamicQuery -> {
+ Property statusProperty = PropertyFactoryUtil.forName("status");
+
+ Integer[] statuses = {
+ WorkflowConstants.STATUS_APPROVED,
+ WorkflowConstants.STATUS_IN_TRASH
+ };
+
+ // reindex any entry that is approved or in the trash
+ dynamicQuery.add(statusProperty.in(statuses));
+ });
+
+ // add any matched entry into the documents to index.
+ batchIndexingActionable.setPerformActionMethod((${capFirstModel} entry) -> {
+ batchIndexingActionable.addDocuments(modelIndexerWriterDocumentHelper.getDocument(entry));
+ });
+ }
+
+ @Override
+ public IndexerWriterMode getIndexerWriterMode(${capFirstModel} entry) {
+
+ // TODO: Update as necessary to control the indexer writer mode for the given entry.
+
+ int status = entry.getStatus();
+
+ if ((status == WorkflowConstants.STATUS_APPROVED) || (status == WorkflowConstants.STATUS_IN_TRASH) || (status == WorkflowConstants.STATUS_DRAFT)) {
+ return IndexerWriterMode.UPDATE;
+ }
+
+ return IndexerWriterMode.DELETE;
+ }
+
+ @Override
+ public BatchIndexingActionable getBatchIndexingActionable() {
+ return dynamicQueryBatchIndexingActionableFactory.getBatchIndexingActionable(
+ _${uncapFirstModel}LocalService.getIndexableActionableDynamicQuery());
+ }
+
+ @Override
+ public long getCompanyId(${capFirstModel} entry) {
+ return entry.getCompanyId();
+ }
+
+ @Reference
+ protected ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+ @Reference
+ protected DynamicQueryBatchIndexingActionableFactory dynamicQueryBatchIndexingActionableFactory;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl
new file mode 100644
index 0000000..5cc6f50
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelPreFilterContributor.java.ftl
@@ -0,0 +1,45 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/query/contributor/${capFirstModel}ModelPreFilterContributor.java">
+/* */
+package ${packageName}.internal.search.query.contributor;
+
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.kernel.search.filter.BooleanFilter;
+import com.liferay.portal.search.spi.model.query.contributor.ModelPreFilterContributor;
+import com.liferay.portal.search.spi.model.registrar.ModelSearchSettings;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model PreFilter Contributor
+ *
+ * Filters search results before they are returned from the search engine.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelPreFilterContributor.class
+)
+public class ${capFirstModel}ModelPreFilterContributor implements ModelPreFilterContributor {
+
+ @Override
+ public void contribute(BooleanFilter booleanFilter, ModelSearchSettings modelSearchSettings, SearchContext searchContext) {
+
+ // TODO: Adjust as necessary to filter results that should not normally be included as search results.
+
+ // exclude non-approved entities from the search results.
+ addWorkflowStatusFilter(booleanFilter, modelSearchSettings, searchContext);
+ }
+
+ protected void addWorkflowStatusFilter(BooleanFilter booleanFilter, ModelSearchSettings modelSearchSettings, SearchContext searchContext) {
+ workflowStatusModelPreFilterContributor.contribute(booleanFilter, modelSearchSettings, searchContext);
+ }
+
+ @Reference(target = "(model.pre.filter.contributor.id=WorkflowStatus)")
+ protected ModelPreFilterContributor workflowStatusModelPreFilterContributor;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelResourcePermissionRegistrar.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelResourcePermissionRegistrar.java.ftl
new file mode 100644
index 0000000..8ba96a7
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelResourcePermissionRegistrar.java.ftl
@@ -0,0 +1,91 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/security/permission/resource/${capFirstModel}ModelResourcePermissionRegistrar.java">
+/* */
+package ${packageName}.internal.security.permission.resource;
+
+import com.liferay.exportimport.kernel.staging.permission.StagingPermission;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermissionFactory;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.StagedModelPermissionLogic;
+import com.liferay.portal.kernel.security.permission.resource.WorkflowedModelPermissionLogic;
+import com.liferay.portal.kernel.service.GroupLocalService;
+import com.liferay.portal.kernel.util.HashMapDictionary;
+import com.liferay.portal.kernel.workflow.permission.WorkflowPermission;
+import ${packageName}.constants.${capFirstModel}Constants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import java.util.Dictionary;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model Resource Permission Registrar
+ *
+ * @author ${damascus_author}
+ *
+ */
+@Component(immediate = true, service = {})
+public class ${capFirstModel}ModelResourcePermissionRegistrar {
+
+ @Activate
+ public void activate(BundleContext bundleContext) {
+ Dictionary properties = new HashMapDictionary<>();
+
+ properties.put("model.class.name", ${capFirstModel}.class.getName());
+
+ _serviceRegistration = bundleContext.registerService(
+ ModelResourcePermission.class,
+ ModelResourcePermissionFactory.create(
+ ${capFirstModel}.class, ${capFirstModel}::getPrimaryKey,
+ _${lowercaseModel}LocalService::get${capFirstModel}, _portletResourcePermission,
+ (modelResourcePermission, consumer) -> {
+ consumer.accept(
+ new StagedModelPermissionLogic<>(
+ _stagingPermission, ${capFirstModel}PortletKeys.${uppercaseModel},
+ ${capFirstModel}::getPrimaryKey));
+
+ consumer.accept(
+ new WorkflowedModelPermissionLogic<>(
+ _workflowPermission, modelResourcePermission,
+ _groupLocalService, ${capFirstModel}::getPrimaryKey));
+ }),
+ properties);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ _serviceRegistration.unregister();
+ }
+
+ @Reference
+ private GroupLocalService _groupLocalService;
+
+ @Reference(
+ target = "(resource.name=" + ${capFirstModel}Constants.RESOURCE_NAME + ")"
+ )
+ private PortletResourcePermission _portletResourcePermission;
+
+ @Reference
+ private ${capFirstModel}LocalService _${lowercaseModel}LocalService;
+
+ @SuppressWarnings("rawtypes")
+ private ServiceRegistration _serviceRegistration;
+
+ @Reference
+ private StagingPermission _stagingPermission;
+
+ @Reference
+ private WorkflowPermission _workflowPermission;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl
new file mode 100644
index 0000000..d60444e
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelSummaryContributor.java.ftl
@@ -0,0 +1,58 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/result/contributor/${capFirstModel}ModelSummaryContributor.java">
+/* */
+package ${packageName}.internal.search.result.contributor;
+
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.Summary;
+import com.liferay.portal.kernel.util.LocaleUtil;
+import com.liferay.portal.kernel.util.LocalizationUtil;
+import com.liferay.portal.search.spi.model.result.contributor.ModelSummaryContributor;
+import org.osgi.service.component.annotations.Component;
+
+import java.util.Locale;
+
+/**
+ * ${capFirstModel} Model Summary Contributor
+ *
+ * Manipulates the Summary object for each entity search result.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelSummaryContributor.class
+)
+public class ${capFirstModel}ModelSummaryContributor implements ModelSummaryContributor {
+
+ @Override
+ public Summary getSummary(Document document, Locale locale, String snippet) {
+ String languageId = LocaleUtil.toLanguageId(locale);
+
+ // TODO: Modify as necessary to use the corrected fields for the summary
+
+ return _createSummary(document,
+ LocalizationUtil.getLocalizedName(Field.CONTENT, languageId),
+ LocalizationUtil.getLocalizedName(Field.TITLE, languageId));
+ }
+
+ protected Summary _createSummary(Document document, String contentField, String titleField) {
+
+ String prefix = Field.SNIPPET + StringPool.UNDERLINE;
+
+ String title = document.get(prefix + titleField, titleField);
+ String content = document.get(prefix + contentField, contentField);
+
+ Summary summary = new Summary(title,content);
+
+ summary.setMaxContentLength(200);
+
+ return summary;
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl
new file mode 100644
index 0000000..323c014
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ModelVisibilityContributor.java.ftl
@@ -0,0 +1,53 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/result/contributor/${capFirstModel}ModelVisibilityContributor.java">
+/* */
+package ${packageName}.internal.search.result.contributor;
+
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.search.spi.model.result.contributor.ModelVisibilityContributor;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Model Visibility Contributor
+ *
+ * Controls the visibility of entities that can be attached to other asset types in the search context.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "indexer.class.name=${packageName}.model.${capFirstModel}",
+ service = ModelVisibilityContributor.class
+)
+public class ${capFirstModel}ModelVisibilityContributor implements ModelVisibilityContributor {
+
+ @Override
+ public boolean isVisible(long classPK, int status) {
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.fetch${capFirstModel}(classPK);
+
+ if (entry == null) {
+ return false;
+ }
+
+ return isVisible(entry.getStatus(), status);
+ }
+
+ protected boolean isVisible(int entryStatus, int queryStatus) {
+ if (((queryStatus != WorkflowConstants.STATUS_ANY) && (entryStatus == queryStatus)) || (entryStatus != WorkflowConstants.STATUS_IN_TRASH)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Reference
+ protected ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_PortletResourcePermissionRegistrar.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_PortletResourcePermissionRegistrar.java.ftl
new file mode 100644
index 0000000..3e469dc
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_PortletResourcePermissionRegistrar.java.ftl
@@ -0,0 +1,60 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/security/permission/resource/${capFirstModel}PortletResourcePermissionRegistrar.java">
+/* */
+
+package ${packageName}.internal.security.permission.resource;
+
+import com.liferay.exportimport.kernel.staging.permission.StagingPermission;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermissionFactory;
+import com.liferay.portal.kernel.security.permission.resource.StagedPortletPermissionLogic;
+import com.liferay.portal.kernel.util.HashMapDictionary;
+import ${packageName}.constants.${capFirstModel}Constants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import java.util.Dictionary;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Portlet Resource Permission Regsitra
+ *
+ * @author ${damascus_author}
+ */
+@Component(immediate = true, service = {})
+public class ${capFirstModel}PortletResourcePermissionRegistrar {
+
+ @Activate
+ public void activate(BundleContext bundleContext) {
+ Dictionary properties = new HashMapDictionary<>();
+
+ properties.put("resource.name", ${capFirstModel}Constants.RESOURCE_NAME);
+
+ _serviceRegistration = bundleContext.registerService(
+ PortletResourcePermission.class,
+ PortletResourcePermissionFactory.create(
+ ${capFirstModel}Constants.RESOURCE_NAME,
+ new StagedPortletPermissionLogic(
+ _stagingPermission, ${capFirstModel}PortletKeys.${uppercaseModel})),
+ properties);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ _serviceRegistration.unregister();
+ }
+
+ private ServiceRegistration _serviceRegistration;
+
+ @Reference
+ private StagingPermission _stagingPermission;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_SearchRegistrar.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_SearchRegistrar.java.ftl
new file mode 100644
index 0000000..6b87de4
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_SearchRegistrar.java.ftl
@@ -0,0 +1,70 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/${capFirstModel}SearchRegistrar.java">
+/* */
+package ${packageName}.internal.search;
+
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.search.spi.model.index.contributor.ModelIndexerWriterContributor;
+import com.liferay.portal.search.spi.model.registrar.ModelSearchRegistrarHelper;
+import com.liferay.portal.search.spi.model.result.contributor.ModelSummaryContributor;
+import com.liferay.portal.search.spi.model.result.contributor.ModelVisibilityContributor;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Search Registrar
+ *
+ * Registers the ${capFirstModel} entity with Liferay's search framework.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ service = {}
+)
+public class ${capFirstModel}SearchRegistrar {
+
+ @Activate
+ protected void activate(BundleContext bundleContext) {
+ _serviceRegistration = modelSearchRegistrarHelper.register(
+ ${capFirstModel}.class, bundleContext,
+ modelSearchDefinition -> {
+ modelSearchDefinition.setDefaultSelectedFieldNames(
+ Field.ASSET_TAG_NAMES, Field.COMPANY_ID, Field.CONTENT,
+ Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID,
+ Field.MODIFIED_DATE, Field.SCOPE_GROUP_ID, Field.TITLE, Field.UID);
+ modelSearchDefinition.setDefaultSelectedLocalizedFieldNames(Field.TITLE, Field.CONTENT);
+
+ modelSearchDefinition.setModelIndexWriteContributor(modelIndexWriterContributor);
+ modelSearchDefinition.setModelSummaryContributor(modelSummaryContributor);
+ modelSearchDefinition.setModelVisibilityContributor(modelVisibilityContributor);
+ });
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ _serviceRegistration.unregister();
+ }
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelIndexerWriterContributor<${capFirstModel}> modelIndexWriterContributor;
+
+ @Reference
+ protected ModelSearchRegistrarHelper modelSearchRegistrarHelper;
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelSummaryContributor modelSummaryContributor;
+
+ @Reference(target = "(indexer.class.name=${packageName}.model.${capFirstModel})")
+ protected ModelVisibilityContributor modelVisibilityContributor;
+
+ private ServiceRegistration> _serviceRegistration;
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_Searcher.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_Searcher.java.ftl
new file mode 100644
index 0000000..917b60e
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_Searcher.java.ftl
@@ -0,0 +1,48 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/search/${capFirstModel}Searcher.java">
+/* */
+package ${packageName}.internal.search;
+
+import com.liferay.portal.kernel.search.BaseSearcher;
+import com.liferay.portal.kernel.search.Field;
+import org.osgi.service.component.annotations.Component;
+import ${packageName}.model.${capFirstModel};
+
+/**
+ * ${capFirstModel} Searcher
+ *
+ * Sets up the searcher instance for ${capFirstModel}.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = BaseSearcher.class
+)
+public class ${capFirstModel}Searcher extends BaseSearcher {
+
+ public static final String CLASS_NAME = ${capFirstModel}.class.getName();
+
+ public ${capFirstModel}Searcher() {
+
+ // TODO: Adjust the fields as necessary.
+ setDefaultSelectedFieldNames(
+ Field.ASSET_TAG_NAMES, Field.COMPANY_ID, Field.CONTENT,
+ Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID,
+ Field.MODIFIED_DATE, Field.SCOPE_GROUP_ID, Field.TITLE, Field.UID);
+ setFilterSearch(true);
+ setPermissionAware(true);
+
+ // TODO Adjust localized fields as well
+ setDefaultSelectedLocalizedFieldNames(Field.TITLE, Field.CONTENT);
+ }
+
+ @Override
+ public String getClassName() {
+ return CLASS_NAME;
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_ServiceImpl.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ServiceImpl.java.ftl
new file mode 100644
index 0000000..4a89566
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_ServiceImpl.java.ftl
@@ -0,0 +1,238 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/impl/${capFirstModel}ServiceImpl.java">
+/* */
+
+
+package ${packageName}.service.impl;
+
+import com.liferay.portal.aop.AopService;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.security.auth.PrincipalException;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermissionFactory;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.service.ServiceContextFactory;
+import ${packageName}.constants.${capFirstModel}Constants;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.base.${capFirstModel}ServiceBaseImpl;
+
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * The implementation of the ${capFirstModel} remote service.
+ *
+ *
+ * All custom service methods should be put in this class. Whenever methods are added, rerun ServiceBuilder to copy their definitions into the ${packageName}.service.${capFirstModel}Service
interface.
+ *
+ *
+ * This is a remote service. Methods of this service are expected to have security checks based on the propagated JAAS credentials because this service can be accessed remotely.
+ *
+ *
+ * @author ${damascus_author}
+ * @see ${capFirstModel}ServiceBaseImpl
+ */
+@Component(
+ property = {
+ "json.web.service.context.name=${lowercaseModel}",
+ "json.web.service.context.path=${capFirstModel}"
+ },
+ service = AopService.class
+)
+public class ${capFirstModel}ServiceImpl extends ${capFirstModel}ServiceBaseImpl {
+
+ /**
+ * Add Entry
+ *
+ * @param orgEntry ${capFirstModel} model
+ * @param serviceContext ServiceContext
+ * @exception PortalException
+ * @exception ${capFirstModel}ValidateException
+ * @return created ${capFirstModel} model.
+ */
+ @Override
+ public ${capFirstModel} addEntry(${capFirstModel} orgEntry, ServiceContext serviceContext)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ _portletResourcePermission.check(
+ getPermissionChecker(), serviceContext.getScopeGroupId(),
+ ActionKeys.ADD_ENTRY);
+
+ return ${uncapFirstModel}LocalService.addEntry(orgEntry, serviceContext);
+ }
+
+ /**
+ * Delete Entry
+ *
+ * @param primaryKey
+ * @return ${capFirstModel}
+ * @throws PortalException
+ */
+ public void deleteEntry(long primaryKey) throws PortalException {
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), primaryKey, ActionKeys.DELETE);
+
+ ${uncapFirstModel}LocalService.deleteEntry(primaryKey);
+ }
+
+ /**
+ * Populate Model with values from a form
+ *
+ * @param primaryKey primary key
+ * @param request PortletRequest
+ * @return ${capFirstModel} Object
+ * @throws PortletException
+ * @throws PortalException
+ */
+ public ${capFirstModel} getInitialized${capFirstModel}(
+ long primaryKey, PortletRequest request)
+ throws PortalException, PortletException {
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ request);
+
+ _portletResourcePermission.check(
+ getPermissionChecker(), serviceContext.getScopeGroupId(),
+ ActionKeys.ADD_ENTRY);
+
+ return ${uncapFirstModel}LocalService.getNewObject(primaryKey);
+ }
+
+ /**
+ * Get Record
+ *
+ * @param primaryKey Primary key
+ * @return ServiceContext serviceContext
+ * @throws PrincipalException
+ * @throws PortletException
+ */
+ public ${capFirstModel} getNewObject(long primaryKey, ServiceContext serviceContext)
+ throws PrincipalException {
+
+ primaryKey = (primaryKey <= 0) ? 0 :
+ counterLocalService.increment(${capFirstModel}.class.getName());
+
+ _portletResourcePermission.check(
+ getPermissionChecker(), serviceContext.getScopeGroupId(),
+ ActionKeys.UPDATE);
+
+ return ${uncapFirstModel}LocalService.getNewObject(primaryKey);
+ }
+
+ /**
+ * Returns the ${lowercaseModel} with the primary key.
+ *
+ * @param ${lowercaseModel}Id the primary key of the sample sb
+ * @return the ${lowercaseModel}
+ * @throws PortalException if a ${lowercaseModel} with the primary key could not be found
+ */
+ @Override
+ public ${capFirstModel} get${capFirstModel}(long primaryKey) throws PortalException {
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), primaryKey, ActionKeys.VIEW);
+
+ return ${uncapFirstModel}LocalService.get${capFirstModel}(primaryKey);
+ }
+
+ /**
+ * Returns the ${lowercaseModel}
+ *
+ * @param groupId
+ * @param urlTitle
+ * @return
+ * @throws PortalException
+ */
+ public ${capFirstModel} get${capFirstModel}(long groupId, String urlTitle)
+ throws PortalException {
+
+ ${capFirstModel} entry = ${uncapFirstModel}LocalService.get${capFirstModel}(groupId, urlTitle);
+
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), entry, ActionKeys.VIEW);
+
+ return entry;
+ }
+
+ /**
+ * Populate Model with values from a form
+ *
+ * @param request PortletRequest
+ * @return ${capFirstModel} Object
+ * @throws PortletException
+ * @throws PortalException
+ */
+ public ${capFirstModel} get${capFirstModel}FromRequest(
+ long primaryKey, PortletRequest request)
+ throws PortalException, PortletException {
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ request);
+
+ _portletResourcePermission.check(
+ getPermissionChecker(), serviceContext.getScopeGroupId(),
+ ActionKeys.VIEW);
+
+ return ${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(primaryKey, request);
+ }
+
+ /**
+ * Move an entry to the trush can
+ *
+ * @param userId
+ * @param entryId
+ * @return ${capFirstModel}
+ * @throws PortalException
+ */
+ public ${capFirstModel} moveEntryToTrash(long entryId) throws PortalException {
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), entryId, ActionKeys.DELETE);
+
+ return ${uncapFirstModel}LocalService.moveEntryToTrash(getUserId(), entryId);
+ }
+
+ /**
+ * Edit Entry
+ *
+ * @param orgEntry ${capFirstModel} model
+ * @param serviceContext ServiceContext
+ * @exception PortalException
+ * @exception ${capFirstModel}ValidateException
+ * @return updated ${capFirstModel} model.
+ */
+ @Override
+ public ${capFirstModel} updateEntry(
+ ${capFirstModel} orgEntry, ServiceContext serviceContext)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ _${uncapFirstModel}ModelResourcePermission.check(
+ getPermissionChecker(), orgEntry.getPrimaryKey(),
+ ActionKeys.UPDATE);
+
+ return ${uncapFirstModel}LocalService.updateEntry(orgEntry, serviceContext);
+ }
+
+ private static volatile ModelResourcePermission<${capFirstModel}>
+ _${uncapFirstModel}ModelResourcePermission =
+ ModelResourcePermissionFactory.getInstance(
+ ${capFirstModel}ServiceImpl.class, "_${uncapFirstModel}ModelResourcePermission",
+ ${capFirstModel}.class);
+
+ @Reference(
+ policy = ReferencePolicy.DYNAMIC,
+ policyOption = ReferencePolicyOption.GREEDY,
+ target = "(resource.name=" + ${capFirstModel}Constants.RESOURCE_NAME + ")"
+ )
+ private volatile PortletResourcePermission _portletResourcePermission;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_TrashHandler.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_TrashHandler.java.ftl
new file mode 100644
index 0000000..881a4d7
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_TrashHandler.java.ftl
@@ -0,0 +1,218 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/internal/trash/${capFirstModel}TrashHandler.java">
+/* */
+
+package ${packageName}.internal.trash;
+
+import com.liferay.asset.kernel.AssetRendererFactoryRegistryUtil;
+import com.liferay.asset.kernel.model.AssetRendererFactory;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.LayoutConstants;
+import com.liferay.portal.kernel.model.TrashedModel;
+import com.liferay.portal.kernel.portlet.PortletProvider;
+import com.liferay.portal.kernel.portlet.PortletProviderUtil;
+import com.liferay.portal.kernel.portlet.PortletURLFactoryUtil;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.security.permission.PermissionThreadLocal;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermissionHelper;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.trash.BaseTrashHandler;
+import com.liferay.portal.kernel.trash.TrashHandler;
+import com.liferay.portal.kernel.trash.TrashRenderer;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.Portal;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+import com.liferay.trash.constants.TrashActionKeys;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletURL;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Trash handler
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = TrashHandler.class
+)
+public class ${capFirstModel}TrashHandler extends BaseTrashHandler {
+
+ @Override
+ public void deleteTrashEntry(long classPK) throws PortalException {
+ _${uncapFirstModel}LocalService.deleteEntry(classPK);
+ }
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public String getRestoreContainedModelLink(
+ PortletRequest portletRequest, long classPK)
+ throws PortalException {
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+
+ PortletURL portletURL = getRestoreURL(portletRequest, classPK, false);
+
+ portletURL.setParameter("urlTitle", entry.getUrlTitle());
+ portletURL.setParameter(Constants.CMD, Constants.UPDATE);
+ portletURL.setParameter(
+ "resourcePrimKey", String.valueOf(entry.getPrimaryKey()));
+
+ return portletURL.toString();
+ }
+
+ @Override
+ public String getRestoreContainerModelLink(
+ PortletRequest portletRequest, long classPK)
+ throws PortalException {
+
+ PortletURL portletURL = getRestoreURL(portletRequest, classPK, true);
+
+ return portletURL.toString();
+ }
+
+ @Override
+ public String getRestoreMessage(
+ PortletRequest portletRequest, long classPK) {
+
+ ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ return themeDisplay.translate("${lowercaseModel}");
+ }
+
+ @Override
+ public TrashedModel getTrashedModel(long classPK) {
+ return _${uncapFirstModel}LocalService.fetch${capFirstModel}(classPK);
+ }
+
+ @Override
+ public TrashRenderer getTrashRenderer(long classPK) throws PortalException {
+ AssetRendererFactory<${capFirstModel}> assetRendererFactory =
+ AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClass(
+ ${capFirstModel}.class);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+
+ return (TrashRenderer)assetRendererFactory.getAssetRenderer(
+ entry.getPrimaryKey());
+ }
+
+ @Override
+ public boolean hasTrashPermission(
+ PermissionChecker permissionChecker, long groupId, long classPK,
+ String trashActionId)
+ throws PortalException {
+
+ if (trashActionId.equals(TrashActionKeys.MOVE)) {
+ return ModelResourcePermissionHelper.contains(
+ _${uncapFirstModel}ModelResourcePermission, permissionChecker, groupId,
+ classPK, ActionKeys.ADD_ARTICLE);
+ }
+
+ return super.hasTrashPermission(
+ permissionChecker, groupId, classPK, trashActionId);
+ }
+
+ @Override
+ public boolean isInTrash(long classPK) throws PortalException {
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+
+ return entry.isInTrash();
+ }
+
+ @Override
+ public boolean isRestorable(long classPK) throws PortalException {
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+
+ if (!hasTrashPermission(
+ PermissionThreadLocal.getPermissionChecker(),
+ entry.getGroupId(), classPK, TrashActionKeys.RESTORE)) {
+
+ return false;
+ }
+
+ return !entry.isInTrashContainer();
+ }
+
+ @Override
+ public void restoreTrashEntry(long userId, long classPK)
+ throws PortalException {
+
+ _${uncapFirstModel}LocalService.restoreEntryFromTrash(userId, classPK);
+ }
+
+ /**
+ * Get Restore URL
+ *
+ * @param portletRequest
+ * @param classPK
+ * @param containerModel
+ * @return
+ * @throws PortalException
+ */
+ protected PortletURL getRestoreURL(
+ PortletRequest portletRequest, long classPK, boolean containerModel)
+ throws PortalException {
+
+ PortletURL portletURL = null;
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(classPK);
+ String portletId = PortletProviderUtil.getPortletId(
+ ${capFirstModel}.class.getName(), PortletProvider.Action.VIEW);
+
+ long plid = _portal.getPlidFromPortletId(entry.getGroupId(), portletId);
+
+ if (plid == LayoutConstants.DEFAULT_PLID) {
+ portletId = PortletProviderUtil.getPortletId(
+ ${capFirstModel}.class.getName(), PortletProvider.Action.MANAGE);
+
+ portletURL = _portal.getControlPanelPortletURL(
+ portletRequest, portletId, PortletRequest.RENDER_PHASE);
+ }
+ else {
+ portletURL = PortletURLFactoryUtil.create(
+ portletRequest, portletId, plid, PortletRequest.RENDER_PHASE);
+ }
+
+ if (!containerModel) {
+ portletURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/view");
+ }
+
+ return portletURL;
+ }
+
+ @Override
+ protected boolean hasPermission(
+ PermissionChecker permissionChecker, long classPK, String actionId)
+ throws PortalException {
+
+ return _${uncapFirstModel}ModelResourcePermission.contains(
+ permissionChecker, classPK, actionId);
+ }
+
+ @Reference
+ private Portal _portal;
+
+ @Reference
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+ @Reference(target = "(model.class.name=${packageName}.model.${capFirstModel})")
+ private ModelResourcePermission<${capFirstModel}> _${uncapFirstModel}ModelResourcePermission;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_Validator.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_Validator.java.ftl
new file mode 100644
index 0000000..47287b4
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_Validator.java.ftl
@@ -0,0 +1,139 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/util/${capFirstModel}Validator.java">
+/* */
+
+package ${packageName}.service.util;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.ModelHintsUtil;
+import com.liferay.portal.kernel.repository.model.ModelValidator;
+import com.liferay.portal.kernel.util.Validator;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+
+/* */
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalServiceUtil;
+ #if>
+#list>
+/* */
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * ${capFirstModel} Validator
+ *
+ * @author ${damascus_author}
+ *
+ */
+public class ${capFirstModel}Validator implements ModelValidator<${capFirstModel}> {
+
+ @Override
+ public void validate(${capFirstModel} entry) throws PortalException {
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ // Field ${field.name}
+ validate${field.name?cap_first}(entry.get${field.name?cap_first}());
+
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+ validate${application.asset.assetTitleFieldName?cap_first}(entry.get${application.asset.assetTitleFieldName?cap_first}());
+
+ if (0 < _errors.size()) {
+ throw new ${capFirstModel}ValidateException(_errors);
+ }
+
+ }
+
+ /**
+ * ${application.asset.assetTitleFieldName} field Validation
+ *
+ * @param ${application.asset.assetTitleFieldName}
+ */
+ protected void validate${application.asset.assetTitleFieldName?cap_first}(String ${application.asset.assetTitleFieldName}) {
+ if (Validator.isNotNull(${application.asset.assetTitleFieldName})) {
+ int ${application.asset.assetTitleFieldName}MaxLength = ModelHintsUtil.getMaxLength(
+ ${capFirstModel}.class.getName(), "${application.asset.assetTitleFieldName}");
+
+ if (${application.asset.assetTitleFieldName}.length() > ${application.asset.assetTitleFieldName}MaxLength) {
+ _errors.add("${application.asset.assetTitleFieldName} has more than " + ${application.asset.assetTitleFieldName}MaxLength +
+ " characters");
+ }
+ }
+ }
+
+/* */
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ /**
+ * ${field.name} field Validation
+ *
+ * @param field ${field.name}
+ */
+ protected void validate${field.name?cap_first}(${templateUtil?api.getTypeParameter(field.type?string)} field) {
+ //TODO : This validation needs to be implemented. Add error message key into _errors when an error occurs.
+ <#if field.primary?? && field.primary == false >
+ <#if field.required == true >
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.RichText" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar"
+ >
+ if (!StringUtils.isNotEmpty(field)) {
+ _errors.add("${lowercaseModel}-${field.name?lower_case}-required");
+ }
+ #if>
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer"
+ >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ if(field <= 0) {
+ _errors.add("${lowercaseModel}-${field.name?lower_case}-required");
+ }
+ #if>
+ #if>
+ #if>
+
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ try {
+ ${capFirstValidationModel}LocalServiceUtil.get${capFirstValidationModel}(field);
+ } catch(PortalException e) {
+ _errors.add("${lowercaseModel}-${field.name?lower_case}-not-found");
+ }
+ #if>
+ #if>
+ }
+
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+/* */
+
+
+ protected List _errors = new ArrayList<>();
+
+}
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_WorkflowHandler.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_WorkflowHandler.java.ftl
new file mode 100644
index 0000000..bc7f811
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_WorkflowHandler.java.ftl
@@ -0,0 +1,77 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/workflow/${capFirstModel}WorkflowHandler.java">
+/* */
+
+
+package ${packageName}.service.workflow;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.security.permission.ResourceActionsUtil;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.util.GetterUtil;
+import com.liferay.portal.kernel.workflow.BaseWorkflowHandler;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import com.liferay.portal.kernel.workflow.WorkflowHandler;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import java.io.Serializable;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Workflow Handler
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = WorkflowHandler.class
+)
+public class ${capFirstModel}WorkflowHandler extends BaseWorkflowHandler<${capFirstModel}> {
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public String getType(Locale locale) {
+ return ResourceActionsUtil.getModelResource(locale, getClassName());
+ }
+
+ @Override
+ public ${capFirstModel} updateStatus(
+ int status, Map workflowContext)
+ throws PortalException {
+
+ long userId = GetterUtil.getLong(
+ (String)workflowContext.get(WorkflowConstants.CONTEXT_USER_ID));
+ long classPK = GetterUtil.getLong(
+ (String)workflowContext.get(
+ WorkflowConstants.CONTEXT_ENTRY_CLASS_PK));
+
+ ServiceContext serviceContext = (ServiceContext)workflowContext.get(
+ "serviceContext");
+
+ return _${uncapFirstModel}LocalService.updateStatus(
+ userId, classPK, status, serviceContext, workflowContext);
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}LocalService(
+ ${capFirstModel}LocalService ${uncapFirstModel}LocalService) {
+
+ _${uncapFirstModel}LocalService = ${uncapFirstModel}LocalService;
+ }
+
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_WorkflowManager.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_WorkflowManager.java.ftl
new file mode 100644
index 0000000..4174378
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_WorkflowManager.java.ftl
@@ -0,0 +1,368 @@
+//
+/* */
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/java/${packagePath}/service/workflow/${capFirstModel}WorkflowManager.java">
+/* */
+
+
+package ${packageName}.service.workflow;
+
+import com.liferay.portal.kernel.dao.orm.QueryUtil;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.User;
+import com.liferay.portal.kernel.model.WorkflowInstanceLink;
+import com.liferay.portal.kernel.service.WorkflowInstanceLinkLocalServiceUtil;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.workflow.WorkflowException;
+import com.liferay.portal.kernel.workflow.WorkflowInstance;
+import com.liferay.portal.kernel.workflow.WorkflowInstanceManagerUtil;
+import com.liferay.portal.kernel.workflow.WorkflowTask;
+import com.liferay.portal.kernel.workflow.WorkflowTaskManagerUtil;
+import ${packageName}.model.${capFirstModel};
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ${capFirstModel} Workflow Utility class
+ *
+ * TODO: This class has been generated as a model specific for convenience of code generation.
+ * Please feel free to refactor this as a common library according to your requirements.
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}WorkflowManager {
+
+ private static final String _className = ${capFirstModel}.class.getName();
+
+ /**
+ * Complete workflow at once
+ *
+ * Without assigning a task to a user, this method automatically assign user and update the workflow.
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param classPK
+ * @param transitionName
+ * @return WorkflowTask object
+ * @throws PortalException
+ */
+ static public WorkflowTask completeWorkflowTaskAtOnce(
+ User user, long scorpGroupId, long classPK, String transitionName)
+ throws PortalException {
+
+ return completeWorkflowTaskAtOnce(
+ user, scorpGroupId, _className, classPK, transitionName);
+ }
+
+ /**
+ * Complete workflow at once
+ *
+ * Without assigning a task to a user, this method automatically assign user and update the workflow.
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @param transitionName
+ * @return WorkflowTask object
+ * @throws PortalException
+ */
+ static public WorkflowTask completeWorkflowTaskAtOnce(
+ User user, long scorpGroupId, String className, long classPK,
+ String transitionName)
+ throws PortalException {
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ // Get workflow instance
+
+ WorkflowTask workflowTask = getWorkflowTask(
+ user, scorpGroupId, className, classPK);
+
+ if (Validator.isNull(workflowTask)) {
+ return null;
+ }
+
+ // Assign a task to the user
+
+ WorkflowTaskManagerUtil.assignWorkflowTaskToUser(
+ user.getCompanyId(), user.getUserId(),
+ workflowTask.getWorkflowTaskId(), user.getUserId(), "", null, null);
+
+ // Complete workflow
+
+ WorkflowTask completeWorkflowTask =
+ WorkflowTaskManagerUtil.completeWorkflowTask(
+ user.getCompanyId(), user.getUserId(),
+ workflowTask.getWorkflowTaskId(), transitionName, "", null);
+
+ return completeWorkflowTask;
+ }
+
+ /**
+ * Check if workflow is enabled.
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param classPK
+ * @return true if workflow is enabled or false
+ * @throws PortalException
+ */
+ static public boolean isWorkflowEnable(
+ User user, long scorpGroupId, long classPK)
+ throws PortalException {
+
+ List transitionNames = getTransitionNames(
+ user, scorpGroupId, null, classPK);
+
+ return (transitionNames.size() == 0) ? false : true;
+ }
+
+ /**
+ * Get Transition names
+ *
+ * A task includes transitions. This method retrieve a list of transition names
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param classPK
+ * @return Escaped transition names
+ * @throws PortalException
+ */
+ static public List getTransitionNames(
+ User user, long scorpGroupId, long classPK)
+ throws PortalException {
+
+ return getTransitionNames(user, scorpGroupId, null, classPK);
+ }
+
+ /**
+ * Get Transition names
+ *
+ * A task includes transitions. This method retrieve a list of transition names
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @return Transition name string List
+ * @throws PortalException
+ */
+ static public List getTransitionNames(
+ User user, long scorpGroupId, String className, long classPK)
+ throws PortalException {
+
+ WorkflowTask workflowTask = getWorkflowTask(
+ user, scorpGroupId, className, classPK);
+
+ if (Validator.isNull(workflowTask)) {
+ return new ArrayList<>();
+ }
+
+ List transitionNames =
+ WorkflowTaskManagerUtil.getNextTransitionNames(
+ user.getCompanyId(), user.getUserId(),
+ workflowTask.getWorkflowTaskId());
+
+ List convertedNames = new ArrayList<>();
+
+ for (String transitionName : transitionNames) {
+ if (_log.isDebugEnabled()) {
+ _log.debug("Transition name : <" + transitionName + ">");
+ }
+
+ convertedNames.add(getTransitionName(transitionName));
+ }
+
+ return convertedNames;
+ }
+
+ /**
+ * Get Transition Message
+ *
+ * @param transitionName
+ * @return Escaped Transition name
+ */
+ static public String getTransitionName(String transitionName) {
+ if (Validator.isNull(transitionName)) {
+ return "proceed";
+ }
+
+ return HtmlUtil.escape(transitionName);
+ }
+
+ /**
+ * Get WorkFlow
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @return WorkflowTask object
+ * @throws WorkflowException
+ */
+ static public WorkflowTask getWorkflowTask(
+ User user, long scorpGroupId, String className, long classPK)
+ throws WorkflowException {
+
+ WorkflowInstance workflowInstance = getWorkflowInstance(
+ user, scorpGroupId, className, classPK);
+ List workflowTasks = getWorkflowTasks(user, className);
+
+ return workflowTasks.stream(
+ ).filter(
+ wft ->
+ wft.getWorkflowInstanceId() ==
+ workflowInstance.getWorkflowInstanceId()
+ ).findFirst(
+ ).orElse(
+ null
+ );
+ }
+
+ /**
+ * Get Workflow Instance
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @return Workflow task instances if those exist
+ * @throws WorkflowException
+ */
+ static public WorkflowInstance getWorkflowInstance(
+ User user, long scorpGroupId, String className, long classPK)
+ throws WorkflowException {
+
+ if (Validator.isNull(classPK)) {
+ _log.debug("classPK is null");
+
+ return null;
+ }
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ WorkflowInstanceLink workflowInstanceLink =
+ WorkflowInstanceLinkLocalServiceUtil.fetchWorkflowInstanceLink(
+ user.getCompanyId(), scorpGroupId, _className, classPK);
+
+ if (Validator.isNull(workflowInstanceLink)) {
+ _log.debug("WorkflowInstanceLink is null");
+
+ return null;
+ }
+
+ WorkflowInstance workflowInstance =
+ WorkflowInstanceManagerUtil.getWorkflowInstance(
+ user.getCompanyId(),
+ workflowInstanceLink.getWorkflowInstanceId());
+
+ if (_log.isDebugEnabled()) {
+ _log.debug(workflowInstance.toString());
+ }
+
+ return workflowInstance;
+ }
+
+ /**
+ * Get WorkflowTasks
+ *
+ * Get unasigned tasks available for the current user.
+ *
+ * @param user
+ * @param className
+ * @return WorkflowTasks of corresponding class
+ * @throws WorkflowException
+ */
+ static public List getWorkflowTasks(
+ User user, String className)
+ throws WorkflowException {
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ List workflowTasks = new ArrayList<>();
+
+ // Fetch workflow tasks has asinged to the user
+
+ List workflowTasksToMyRoles = getWorkflowTasks(
+ user, className, true);
+
+ workflowTasks.addAll(workflowTasksToMyRoles);
+
+ // Fetch workflow tasks has asigned to my roles, but not asigned to the user yet.
+
+ List workflowTasksToMe = getWorkflowTasks(
+ user, className, false);
+
+ workflowTasks.addAll(workflowTasksToMe);
+
+ return workflowTasks;
+ }
+
+ /**
+ * Get WorkflowTasks
+ *
+ * Get unasigned tasks available for the current user.
+ *
+ * @param user
+ * @param className
+ * @param searchByUserRoles
+ * @return WorkflowTasks of corresponding class
+ * @throws WorkflowException
+ */
+ static public List getWorkflowTasks(
+ User user, String className, boolean searchByUserRoles)
+ throws WorkflowException {
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ return WorkflowTaskManagerUtil.search(
+ user.getCompanyId(), // companyId
+ user.getUserId(), // userId
+ "", // keywords
+ new String[]{className}, // assetTypes
+ false, // completed
+ searchByUserRoles, // searchByUserRoles
+ QueryUtil.ALL_POS, // start
+ QueryUtil.ALL_POS, // end
+ null); //OrderByComparator orderByComparator)
+ }
+
+ /**
+ * Is Workflow Exist
+ *
+ * @param user
+ * @param scorpGroupId
+ * @param className
+ * @param classPK
+ * @return true if a workflow exists or false
+ */
+ static public boolean isWorkflowExist(
+ User user, long scorpGroupId, String className, long classPK) {
+
+ if (Validator.isNull(className)) {
+ className = _className;
+ }
+
+ return WorkflowInstanceLinkLocalServiceUtil.hasWorkflowInstanceLink(
+ user.getCompanyId(), scorpGroupId, _className, classPK);
+ }
+
+ private static Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}WorkflowManager.class);
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_bnd.bnd.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_bnd.bnd.ftl
new file mode 100644
index 0000000..85a0f7f
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_bnd.bnd.ftl
@@ -0,0 +1,18 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/bnd.bnd">
+# #
+Bundle-Name: ${dashcaseProjectName}-service
+Bundle-SymbolicName: ${packageName}.service
+Bundle-Version: 1.0.0
+Import-Package:\
+ !com.google.*,\
+ !org.checkerframework.* ,\
+ *
+Liferay-Require-SchemaVersion: 1.0.0
+Liferay-Service: true
+-dsannotations-options: inherit
+-includeresource:\
+ @guava-*.jar,\
+ @commons-lang3-*.jar
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_build.gradle.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_build.gradle.ftl
new file mode 100644
index 0000000..37b9fab
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_build.gradle.ftl
@@ -0,0 +1,75 @@
+//
+// //
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/build.gradle">
+// //
+apply plugin: 'eclipse'
+apply plugin: 'groovy'
+apply plugin: 'idea'
+apply plugin: 'java'
+
+
+//Need for Windows
+def defaultEncoding = 'UTF-8'
+
+repositories {
+ mavenCentral()
+ jcenter()
+ maven {
+ url "http://repository.jboss.org/nexus/content/groups/public-jboss" // JBoss
+ url "http://repository.apache.org/content/groups/public" // Apache
+ url "http://repository.springsource.com/maven/bundles/release" // SpringSource
+ url "http://repository.codehaus.org" // Codehaus
+ url "http://download.java.net/maven/2" // Java.NET
+ url "http://download.java.net/maven/glassfish" // Glassfish
+ url "http://m2repo.spockframework.org/snapshots" // Spock Snapshot
+ url "http://repository.sonatype.org/content/groups/public"
+ url "https://mvnrepository.com/artifact/com.sun/tools"
+ }
+}
+
+dependencies {
+ compile group: "com.google.guava", name: "guava"<#if useTP?? && false == useTP>, version: "28.1-jre"#if>, transitive: false
+ compileOnly group: "com.liferay", name: "com.liferay.friendly.url.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.function"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.lang"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.string"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.sql.dsl.api"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"<#if useTP?? && false == useTP>, version: "2.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.search.api"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.portal.search.spi"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.trash.api"<#if useTP?? && false == useTP>, version: "3.2.+"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "7.2.0"#if>
+ compileOnly group: "commons-io", name: "commons-io"<#if useTP?? && false == useTP>, version: "2.6"#if>
+ compile group: "commons-validator", name: "commons-validator"<#if useTP?? && false == useTP>, version: "1.6"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet", name: "javax.servlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet.jsp", name: "jsp-api"<#if useTP?? && false == useTP>, version: "2.1"#if>
+ compile group: "org.apache.commons", name: "commons-lang3", version: "3.9"
+ compile group: "org.apache.felix", name: "org.apache.felix.http.servlet-api", version: "1.1.2"
+ compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"<#if useTP?? && false == useTP>, version: "1.1.0"#if>
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"<#if useTP?? && false == useTP>, version: "1.3.0"#if>
+ compile group: "org.osgi", name: "osgi.core", version: "6.0.0"
+ compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.26'
+ compile project(":${dashcaseProjectName}-api")
+}
+
+buildscript {
+ dependencies {
+ classpath group: "com.liferay", name: "com.liferay.gradle.plugins.service.builder", version: "4.0.+"
+ }
+
+ repositories {
+ maven {
+ url "https://repository-cdn.liferay.com/nexus/content/groups/public"
+ }
+ }
+}
+
+apply plugin: "com.liferay.portal.tools.service.builder"
+
+buildService {
+ apiDir = "../${dashcaseProjectName}-api/src/main/java"
+}
+
+group = "${packageName}"
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_default.xml.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_default.xml.ftl
new file mode 100644
index 0000000..f860069
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_default.xml.ftl
@@ -0,0 +1,77 @@
+
+
+
+
+ <#include "./valuables.ftl">
+ <#assign createPath = "${serviceModulePath}/src/main/resources/META-INF/resource-actions/default.xml">
+
+
+
+ ${packageName}
+
+ ${packageSnake}_web_${capFirstModel}Portlet
+ ${packageSnake}_web_${capFirstModel}AdminPortlet
+
+ true
+ 1
+
+
+ ACCESS_IN_CONTROL_PANEL
+ UPDATE
+ VIEW
+ ADD_ENTRY
+ PERMISSIONS
+
+
+ UPDATE
+ VIEW
+ ADD_ENTRY
+
+
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ UPDATE
+ ADD_ENTRY
+ PERMISSIONS
+
+
+
+
+ <#list damascus.applications as app >
+ <#assign capFirstModel = "${app.model?cap_first}">
+
+ ${packageName}.model.${capFirstModel}
+
+ ${packageSnake}_web_${capFirstModel}Portlet
+ ${packageSnake}_web_${capFirstModel}AdminPortlet
+
+ 2
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_ENTRY
+ DELETE
+ PERMISSIONS
+ UPDATE
+ VIEW
+
+
+ VIEW
+
+
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_ENTRY
+ DELETE
+ PERMISSIONS
+ UPDATE
+
+
+
+ #list>
+
+
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_portlet-model-hints.xml.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_portlet-model-hints.xml.ftl
new file mode 100644
index 0000000..9c3f0c9
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_portlet-model-hints.xml.ftl
@@ -0,0 +1,95 @@
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/resources/META-INF/portlet-model-hints.xml">
+
+
+
+<#list damascus.applications as application>
+
+
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Long" >
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" >
+
+ ${field.length}
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Date" >
+
+ false
+ 80
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" >
+
+ true
+ 80
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" >
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+
+ 60
+ 512
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Double" >
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Integer" >
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+
+
+ 4001
+
+ #if>
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.Text" >
+
+
+ 4001
+
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+ 200
+ 255
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+
+ 4001
+
+ #if>
+
+
+
+
+
+
+
+
+
+
+
+
+
+#list>
+
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXSVC_portlet.properties.ftl b/src/test/resources/templates/7.3/Portlet_XXXXSVC_portlet.properties.ftl
new file mode 100644
index 0000000..5f0f1ad
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXSVC_portlet.properties.ftl
@@ -0,0 +1,12 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${serviceModulePath}/src/main/resources/portlet.properties">
+# #
+
+include-and-override=portlet-ext.properties
+
+# Input a list of comma delimited resource action configurations that will be
+# read from the class path.
+#
+resource.actions.configs=META-INF/resource-actions/default.xml
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
new file mode 100644
index 0000000..8a70af8
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCActionCommand.java.ftl
@@ -0,0 +1,291 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}AdminCrudMVCActionCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.asset.display.page.portlet.AssetDisplayPageEntryFormProcessor;
+import com.liferay.petra.reflect.ReflectionUtil;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.TrashedModel;
+import com.liferay.portal.kernel.portlet.bridges.mvc.BaseMVCActionCommand;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCActionCommand;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.service.ServiceContextFactory;
+import com.liferay.portal.kernel.servlet.SessionErrors;
+import com.liferay.portal.kernel.servlet.SessionMessages;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.PortalUtil;
+import com.liferay.portal.kernel.util.StringUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+import ${packageName}.service.${capFirstModel}Service;
+import com.liferay.trash.service.TrashEntryService;
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "mvc.command.name=/${lowercaseModel}/crud"
+ },
+ service = MVCActionCommand.class
+)
+public class ${capFirstModel}AdminCrudMVCActionCommand extends BaseMVCActionCommand {
+
+ /**
+ * Add Entry
+ *
+ * @param request
+ * @param response
+ * @throws ${capFirstModel}ValidateException, Exception
+ */
+ public void addEntry(ActionRequest request, ActionResponse response)
+ throws Exception, ${capFirstModel}ValidateException {
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(
+ primaryKey, request);
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ ${capFirstModel}.class.getName(), request);
+
+ // Add entry
+
+ _${uncapFirstModel}Service.addEntry(entry, serviceContext);
+
+ _assetDisplayPageEntryFormProcessor.process(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), request);
+
+ SessionMessages.add(request, "${lowercaseModel}AddedSuccessfully");
+ }
+
+ /**
+ * Delte Entry
+ *
+ * @param request
+ * @param response
+ * @param moveToTrash true to move to trush.
+ * @throws PortalException
+ * @throws Exception
+ */
+ public void deleteEntry(
+ ActionRequest request, ActionResponse response, boolean moveToTrash)
+ throws PortalException {
+
+ long[] deleteEntryIds = null;
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ long entryId = ParamUtil.getLong(request, "resourcePrimKey", 0L);
+
+ if (entryId > 0) {
+ deleteEntryIds = new long[] {entryId};
+ }
+ else {
+ deleteEntryIds = StringUtil.split(
+ ParamUtil.getString(request, "deleteEntryIds"), 0L);
+ }
+
+ List trashedModels = new ArrayList<>();
+
+ for (long deleteEntryId : deleteEntryIds) {
+ try {
+ if (moveToTrash) {
+ ${capFirstModel} entry = _${uncapFirstModel}Service.moveEntryToTrash(
+ deleteEntryId);
+
+ trashedModels.add(entry);
+ }
+ else {
+ _${uncapFirstModel}Service.deleteEntry(deleteEntryId);
+ }
+ }
+ catch (PortalException pe) {
+ ReflectionUtil.throwException(pe);
+ }
+ }
+
+ if (moveToTrash && !trashedModels.isEmpty()) {
+ Map data = new HashMap<>();
+
+ data.put("trashedModels", trashedModels);
+
+ addDeleteSuccessData(request, data);
+ }
+ }
+
+ /**
+ * Restore Entries
+ *
+ * @param actionRequest
+ * @throws Exception
+ */
+ public void restoreTrashEntries(ActionRequest actionRequest)
+ throws Exception {
+
+ long[] restoreTrashEntryIds = StringUtil.split(
+ ParamUtil.getString(actionRequest, "restoreTrashEntryIds"), 0L);
+
+ for (long restoreTrashEntryId : restoreTrashEntryIds) {
+ _trashEntryService.restoreEntry(restoreTrashEntryId);
+ }
+ }
+
+ /**
+ * Update Entry
+ *
+ * @param request
+ * @param response
+ * @throws Exception
+ */
+ public void updateEntry(ActionRequest request, ActionResponse response)
+ throws Exception {
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(
+ primaryKey, request);
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ ${capFirstModel}.class.getName(), request);
+
+ //Update entry
+ _${uncapFirstModel}Service.updateEntry(entry, serviceContext);
+
+ _assetDisplayPageEntryFormProcessor.process(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), request);
+
+ SessionMessages.add(request, "${lowercaseModel}UpdatedSuccessfully");
+ }
+
+ /**
+ * Single Delete
+ *
+ * @param entry
+ * @param moveToTrash
+ * @param trashedModels
+ */
+ protected void _deleteEntry(
+ ${capFirstModel} entry, boolean moveToTrash, List trashedModels) {
+
+ try {
+ if (moveToTrash) {
+ trashedModels.add(
+ _${uncapFirstModel}Service.moveEntryToTrash(entry.getPrimaryKey()));
+ }
+ else {
+ _${uncapFirstModel}Service.deleteEntry(entry.getPrimaryKey());
+ }
+ }
+ catch (PortalException pe) {
+ ReflectionUtil.throwException(pe);
+ }
+ }
+
+ @Override
+ protected void doProcessAction(
+ ActionRequest request, ActionResponse response)
+ throws IOException {
+
+ try {
+
+ // Fetch command
+
+ String cmd = ParamUtil.getString(request, Constants.CMD);
+
+ if (cmd.equals(Constants.ADD)) {
+ addEntry(request, response);
+ }
+ else if (cmd.equals(Constants.UPDATE)) {
+ updateEntry(request, response);
+ }
+ else if (cmd.equals(Constants.DELETE)) {
+ deleteEntry(request, response, false);
+ }
+ else if (cmd.equals(Constants.MOVE_TO_TRASH)) {
+ deleteEntry(request, response, true);
+ }
+ else if (cmd.equals(Constants.RESTORE)) {
+ restoreTrashEntries(request);
+ }
+ }
+ catch (${capFirstModel}ValidateException ssbve) {
+ for (String error : ssbve.getErrors()) {
+ SessionErrors.add(request, error);
+ }
+
+ PortalUtil.copyRequestParameters(request, response);
+ response.setRenderParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/crud");
+ hideDefaultSuccessMessage(request);
+ }
+ catch (Exception t) {
+ _log.error(t.getLocalizedMessage(), t);
+ SessionErrors.add(request, PortalException.class);
+ hideDefaultSuccessMessage(request);
+ }
+
+ //For access from Asset Publisher
+ String redirect = ParamUtil.getString(request, "redirect");
+ Boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+
+ if (Validator.isNotNull(redirect) && (true == fromAsset)) {
+ sendRedirect(request, response, redirect);
+ }
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}LocalService(
+ ${capFirstModel}LocalService ${uncapFirstModel}LocalService) {
+
+ _${uncapFirstModel}LocalService = ${uncapFirstModel}LocalService;
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}Service(${capFirstModel}Service ${uncapFirstModel}Service) {
+ _${uncapFirstModel}Service = ${uncapFirstModel}Service;
+ }
+
+ private static Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}AdminCrudMVCActionCommand.class);
+
+ @Reference
+ private AssetDisplayPageEntryFormProcessor
+ _assetDisplayPageEntryFormProcessor;
+
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+ private ${capFirstModel}Service _${uncapFirstModel}Service;
+
+ @Reference
+ private TrashEntryService _trashEntryService;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCRenderCommand.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCRenderCommand.java.ftl
new file mode 100644
index 0000000..ee4855f
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminCrudMVCRenderCommand.java.ftl
@@ -0,0 +1,247 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}AdminCrudMVCRenderCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCRenderCommand;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}Service;
+import ${packageName}.web.constants.${capFirstModel}WebKeys;
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}EntryPermission;
+import ${packageName}.web.upload.${capFirstModel}ItemSelectorHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalService;
+import ${packageName}.web.constants.${capFirstValidationModel}WebKeys;
+import ${packageName}.web.util.${capFirstValidationModel}ViewHelper;
+ #if>
+#list>
+// //
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} CRUD Render
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "mvc.command.name=/${lowercaseModel}/crud"
+ },
+ service = MVCRenderCommand.class
+)
+public class ${capFirstModel}AdminCrudMVCRenderCommand implements MVCRenderCommand {
+
+ /**
+ * Edit Page JSP file
+ */
+ public String getEditPageJSP() {
+ return ${capFirstModel}WebKeys.ADMIN_EDIT_JSP;
+ }
+
+ /**
+ * View Page JSP file
+ */
+ public String getViewPageJSP() {
+ return ${capFirstModel}WebKeys.ADMIN_VIEW_JSP;
+ }
+
+ /**
+ * View Record JSP file
+ */
+ public String getViewRecordPageJSP() {
+ return ${capFirstModel}WebKeys.ADMIN_VIEW_RECORD_JSP;
+ }
+
+ @Override
+ public String render(RenderRequest request, RenderResponse response)
+ throws PortletException {
+
+ String renderJSP = getViewPageJSP();
+
+ // Fetch command
+
+ String cmd = ParamUtil.getString(request, Constants.CMD);
+
+ // Fetch primary key
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ try {
+ if (cmd.equalsIgnoreCase(Constants.UPDATE)) {
+ renderJSP = update(request, themeDisplay, primaryKey);
+ }
+ else if (cmd.equalsIgnoreCase(Constants.VIEW)) {
+ renderJSP = view(request, themeDisplay, primaryKey);
+ }
+ else {
+ renderJSP = add(request, themeDisplay, primaryKey);
+ }
+ }
+ catch (PortalException pe) {
+ throw new PortletException(pe.getMessage());
+ }
+
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+
+ request.setAttribute(${capFirstValidationModel}WebKeys.${uppercaseValidationModel}_VIEW_HELPER, _${uncapFirstValidationModel}ViewHelper);
+ request.setAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE, _${uncapFirstValidationModel}LocalService);
+ #if>
+#list>
+// //
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_ITEM_SELECTOR_HELPER,
+ _${uncapFirstModel}ItemSelectorHelper);
+
+ return renderJSP;
+ }
+
+ /**
+ * Add record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return JSP file path
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ * @throws PortletException
+ */
+ protected String add(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, PortletException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = null;
+
+ if (Validator.isNull(request.getParameter("addErrors"))) {
+ record = _${uncapFirstModel}Service.getInitialized${capFirstModel}(
+ primaryKey, request);
+ }
+ else {
+ record = _${uncapFirstModel}Service.get${capFirstModel}FromRequest(
+ primaryKey, request);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getEditPageJSP();
+ }
+
+ /**
+ * Update record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return JSP file path to open
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ */
+ protected String update(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = _${uncapFirstModel}Service.get${capFirstModel}(primaryKey);
+
+ if (!${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), record,
+ ActionKeys.UPDATE)) {
+
+ List error = new ArrayList<>();
+ error.add("permission-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getEditPageJSP();
+ }
+
+ /**
+ * View record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ */
+ protected String view(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = _${uncapFirstModel}Service.get${capFirstModel}(primaryKey);
+
+ if (!${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), record, ActionKeys.VIEW)) {
+
+ List error = new ArrayList<>();
+ error.add("permission-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getViewRecordPageJSP();
+ }
+ @Reference
+ private ${capFirstModel}Service _${uncapFirstModel}Service;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+
+ @Reference
+ private ${capFirstValidationModel}ViewHelper _${uncapFirstValidationModel}ViewHelper;
+
+ @Reference
+ private ${capFirstValidationModel}LocalService _${uncapFirstValidationModel}LocalService;
+ #if>
+#list>
+// //
+
+ @Reference
+ private ${capFirstModel}ItemSelectorHelper _${uncapFirstModel}ItemSelectorHelper;
+
+}
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminPortlet.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminPortlet.java.ftl
new file mode 100644
index 0000000..95a0232
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminPortlet.java.ftl
@@ -0,0 +1,78 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}AdminPortlet.java">
+<#assign skipTemplate = !generateWeb>
+// //
+
+package ${packageName}.web.portlet;
+
+import com.liferay.asset.constants.AssetWebKeys;
+import com.liferay.asset.util.AssetHelper;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import com.liferay.trash.TrashHelper;
+import com.liferay.trash.util.TrashWebKeys;
+
+import java.io.IOException;
+
+import javax.portlet.Portlet;
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * ${capFirstModel} Admin Portlet
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "com.liferay.portlet.css-class-wrapper=portlet-${lowercaseModel}",
+ "com.liferay.portlet.display-category=category.hidden",
+ "com.liferay.portlet.header-portlet-css=/${snakecaseModel}_admin/css/main.css",
+ "com.liferay.portlet.preferences-unique-per-layout=true",
+ "com.liferay.portlet.preferences-owned-by-group=true",
+ "com.liferay.portlet.private-request-attributes=false",
+ "com.liferay.portlet.private-session-attributes=false",
+ "com.liferay.portlet.render-weight=50",
+ "com.liferay.portlet.scopeable=true",
+ "com.liferay.portlet.struts-path=${lowercaseModel}_admin",
+ "com.liferay.portlet.use-default-template=true",
+ "javax.portlet.display-name=${capFirstModel} Admin",
+ "javax.portlet.init-param.mvc-command-names-default-views=/${lowercaseModel}/view",
+ "javax.portlet.init-param.portlet-title-based-navigation=true",
+ "javax.portlet.expiration-cache=0",
+ "javax.portlet.init-param.template-path=/META-INF/resources/",
+ "javax.portlet.init-param.view-template=/${snakecaseModel}_admin/view.jsp",
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "javax.portlet.resource-bundle=content.Language",
+ "javax.portlet.security-role-ref=administrator"
+ },
+ service = Portlet.class
+)
+public class ${capFirstModel}AdminPortlet extends MVCPortlet {
+
+ @Override
+ public void render(
+ RenderRequest renderRequest, RenderResponse renderResponse)
+ throws IOException, PortletException {
+
+ renderRequest.setAttribute(AssetWebKeys.ASSET_HELPER, _assetHelper);
+ renderRequest.setAttribute(TrashWebKeys.TRASH_HELPER, _trashHelper);
+
+ super.render(renderRequest, renderResponse);
+ }
+
+ @Reference
+ private AssetHelper _assetHelper;
+
+ @Reference
+ private TrashHelper _trashHelper;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminPortletProvider.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminPortletProvider.java.ftl
new file mode 100644
index 0000000..cb2a95a
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminPortletProvider.java.ftl
@@ -0,0 +1,43 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}AdminPortletProvider.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import com.liferay.portal.kernel.portlet.BasePortletProvider;
+import com.liferay.portal.kernel.portlet.EditPortletProvider;
+import com.liferay.portal.kernel.portlet.ManagePortletProvider;
+import com.liferay.portal.kernel.portlet.ViewPortletProvider;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * ${capFirstModel} Portlet Provider
+ *
+ * This class returns Portlet ID for PortletProviderUtil which is used in TrashHandler.
+ * This Portlet ID is used to create a restore URL.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = {
+ EditPortletProvider.class, ManagePortletProvider.class,
+ ViewPortletProvider.class
+ }
+)
+public class ${capFirstModel}AdminPortletProvider
+ extends BasePortletProvider
+ implements EditPortletProvider, ManagePortletProvider, ViewPortletProvider {
+
+ @Override
+ public String getPortletName() {
+ return ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminViewMVCRenderCommand.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminViewMVCRenderCommand.java.ftl
new file mode 100644
index 0000000..922fbfc
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AdminViewMVCRenderCommand.java.ftl
@@ -0,0 +1,92 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}AdminViewMVCRenderCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCRenderCommand;
+import com.liferay.portal.kernel.util.Portal;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.web.constants.${capFirstModel}WebKeys;
+import ${packageName}.web.internal.display.context.${capFirstModel}DisplayContext;
+import ${packageName}.web.util.${capFirstModel}ViewHelper;
+import com.liferay.trash.TrashHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalService;
+import ${packageName}.web.constants.${capFirstValidationModel}WebKeys;
+ #if>
+#list>
+// //
+
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "mvc.command.name=/", "mvc.command.name=/${lowercaseModel}/view"
+ },
+ service = MVCRenderCommand.class
+)
+public class ${capFirstModel}AdminViewMVCRenderCommand implements MVCRenderCommand {
+
+ @Override
+ public String render(RenderRequest request, RenderResponse response) {
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_DISPLAY_CONTEXT,
+ new ${capFirstModel}DisplayContext(
+ _portal.getLiferayPortletRequest(request),
+ _portal.getLiferayPortletResponse(response), _trashHelper,
+ _${uncapFirstModel}ViewHelper));
+
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_VIEW_HELPER, _${uncapFirstModel}ViewHelper);
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+ request.setAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE, _${uncapFirstValidationModel}LocalService);
+ #if>
+#list>
+// //
+
+ return ${capFirstModel}WebKeys.ADMIN_VIEW_JSP;
+ }
+
+ @Reference
+ private Portal _portal;
+
+ @Reference
+ private ${capFirstModel}ViewHelper _${uncapFirstModel}ViewHelper;
+
+ @Reference
+ private TrashHelper _trashHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ @Reference
+ private ${capFirstValidationModel}LocalService _${uncapFirstValidationModel}LocalService;
+ #if>
+#list>
+// //
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_AssetInfoDisplayContributor.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AssetInfoDisplayContributor.java.ftl
new file mode 100644
index 0000000..83f2c1c
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AssetInfoDisplayContributor.java.ftl
@@ -0,0 +1,44 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/info/display/contributor/${capFirstModel}AssetInfoDisplayContributor.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.info.display.contributor;
+
+import com.liferay.asset.info.display.contributor.BaseAssetInfoDisplayContributor;
+import com.liferay.info.display.contributor.InfoDisplayContributor;
+import ${packageName}.model.${capFirstModel};
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * ${capFirstModel} Asset Info Display Contributor
+ *
+ * @author ${damascus_author}
+ *
+ */
+@Component(immediate = true, service = InfoDisplayContributor.class)
+public class ${capFirstModel}AssetInfoDisplayContributor extends BaseAssetInfoDisplayContributor<${capFirstModel}> {
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public String getInfoURLSeparator() {
+ return "/${lowercaseModel}/";
+ }
+
+ @Override
+ protected Map getClassTypeValues(${capFirstModel} assetEntryObject, Locale locale) {
+ return new HashMap<>();
+ }
+
+}
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_AssetRenderer.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AssetRenderer.java.ftl
new file mode 100644
index 0000000..7950112
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AssetRenderer.java.ftl
@@ -0,0 +1,324 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/asset/${capFirstModel}AssetRenderer.java">
+<#assign skipTemplate = !generateWeb>
+// //
+
+package ${packageName}.web.asset;
+
+import com.liferay.asset.display.page.portlet.AssetDisplayPageFriendlyURLProvider;
+import com.liferay.asset.kernel.model.AssetRendererFactory;
+import com.liferay.asset.kernel.model.BaseJSPAssetRenderer;
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.Group;
+import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
+import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
+import com.liferay.portal.kernel.portlet.PortletLayoutFinder;
+import com.liferay.portal.kernel.portlet.PortletLayoutFinderRegistryUtil;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.trash.TrashRenderer;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.PortalUtil;
+import com.liferay.portal.kernel.util.ResourceBundleLoader;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}EntryPermission;
+
+import java.util.Locale;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletResponse;
+import javax.portlet.PortletURL;
+import javax.portlet.WindowState;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Asset Renderer
+ *
+ * This class is used to display contents in Asset Publisher.
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}AssetRenderer
+ extends BaseJSPAssetRenderer<${capFirstModel}> implements TrashRenderer {
+
+ public ${capFirstModel}AssetRenderer(
+ ${capFirstModel} entry, ResourceBundleLoader resourceBundleLoader) {
+
+ _entry = entry;
+ _resourceBundleLoader = resourceBundleLoader;
+ }
+
+ @Override
+ public ${capFirstModel} getAssetObject() {
+ return _entry;
+ }
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public long getClassPK() {
+ return _entry.getPrimaryKey();
+ }
+
+ @Override
+ public String getDiscussionPath() {
+ return null;
+ }
+
+ @Override
+ public long getGroupId() {
+ return _entry.getGroupId();
+ }
+
+ @Override
+ public String getJspPath(HttpServletRequest request, String template) {
+ if (template.equals(TEMPLATE_ABSTRACT) ||
+ template.equals(TEMPLATE_FULL_CONTENT)) {
+
+ request.setAttribute("${uncapFirstModel}", _entry);
+
+ return "/${snakecaseModel}/asset/" + template + ".jsp";
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getPortletId() {
+ AssetRendererFactory<${capFirstModel}> assetRendererFactory =
+ getAssetRendererFactory();
+
+ return assetRendererFactory.getPortletId();
+ }
+
+ @Override
+ public int getStatus() {
+ return _entry.getStatus();
+ }
+
+ @Override
+ public String getSummary(
+ PortletRequest portletRequest, PortletResponse portletResponse) {
+// //
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+ return _entry.get${application.asset.assetTitleFieldName?cap_first}();
+ <#else>
+ // TODO : This need to be customized
+ return "Asset Renderer need to be implimented";
+ #if>
+// //
+ }
+
+ @Override
+ public String getTitle(Locale locale) {
+// //
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+ return _entry.get${application.asset.assetTitleFieldName?cap_first}();
+ <#else>
+ // TODO : This need to be customized
+ return "Asset Renderer need to be implimented";
+ #if>
+// //
+ }
+
+ @Override
+ public String getType() {
+ return ${capFirstModel}AssetRendererFactory.TYPE;
+ }
+
+ @Override
+ public PortletURL getURLEdit(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse)
+ throws Exception {
+
+ Group group = GroupLocalServiceUtil.fetchGroup(_entry.getGroupId());
+
+ if (group.isCompany()) {
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)liferayPortletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ group = themeDisplay.getScopeGroup();
+ }
+
+ PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
+ liferayPortletRequest, group, ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN, 0,
+ 0, PortletRequest.RENDER_PHASE);
+
+ portletURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/crud");
+ portletURL.setParameter("fromAsset", StringPool.TRUE);
+ portletURL.setParameter(Constants.CMD, Constants.UPDATE);
+ portletURL.setParameter(
+ "resourcePrimKey", String.valueOf(_entry.getPrimaryKey()));
+
+ return portletURL;
+ }
+
+ @Override
+ public String getUrlTitle() {
+ return _entry.getUrlTitle();
+ }
+
+ @Override
+ public String getURLView(
+ LiferayPortletResponse liferayPortletResponse,
+ WindowState windowState)
+ throws Exception {
+
+ AssetRendererFactory<${capFirstModel}> assetRendererFactory =
+ getAssetRendererFactory();
+
+ PortletURL portletURL = assetRendererFactory.getURLView(
+ liferayPortletResponse, windowState);
+
+ portletURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/crud");
+ portletURL.setParameter("fromAsset", StringPool.TRUE);
+ portletURL.setParameter(Constants.CMD, Constants.VIEW);
+ portletURL.setParameter(
+ "resourcePrimKey", String.valueOf(_entry.getPrimaryKey()));
+ portletURL.setWindowState(windowState);
+
+ return portletURL.toString();
+ }
+
+ @Override
+ public String getURLViewInContext(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse,
+ String noSuchEntryRedirect)
+ throws PortalException {
+
+ if (_assetDisplayPageFriendlyURLProvider != null) {
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)liferayPortletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ String friendlyURL =
+ _assetDisplayPageFriendlyURLProvider.getFriendlyURL(
+ getClassName(), getClassPK(), themeDisplay);
+
+ if (Validator.isNotNull(friendlyURL)) {
+ return friendlyURL;
+ }
+ }
+
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)liferayPortletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ if (!_hasViewInContextGroupLayout(_entry.getGroupId(), themeDisplay)) {
+ return null;
+ }
+
+ return getURLViewInContext(
+ liferayPortletRequest, noSuchEntryRedirect, "/${lowercaseModel}/crud",
+ "resourcePrimKey", _entry.getPrimaryKey());
+ }
+
+ @Override
+ public long getUserId() {
+ return _entry.getUserId();
+ }
+
+ @Override
+ public String getUserName() {
+ return _entry.getUserName();
+ }
+
+ @Override
+ public String getUuid() {
+ return _entry.getUuid();
+ }
+
+ @Override
+ public boolean hasEditPermission(PermissionChecker permissionChecker)
+ throws PortalException {
+
+ return ${capFirstModel}EntryPermission.contains(
+ permissionChecker, _entry, ActionKeys.UPDATE);
+ }
+
+ @Override
+ public boolean hasViewPermission(PermissionChecker permissionChecker)
+ throws PortalException {
+
+ return ${capFirstModel}EntryPermission.contains(
+ permissionChecker, _entry, ActionKeys.VIEW);
+ }
+
+ @Override
+ public boolean include(
+ HttpServletRequest request, HttpServletResponse response,
+ String template)
+ throws Exception {
+
+ request.setAttribute("${uncapFirstModel}", _entry);
+
+ return super.include(request, response, template);
+ }
+
+ @Override
+ public boolean isPrintable() {
+ return true;
+ }
+
+ public void setAssetDisplayPageFriendlyURLProvider(
+ AssetDisplayPageFriendlyURLProvider
+ assetDisplayPageFriendlyURLProvider) {
+
+ _assetDisplayPageFriendlyURLProvider =
+ assetDisplayPageFriendlyURLProvider;
+ }
+
+ private boolean _hasViewInContextGroupLayout(
+ long groupId, ThemeDisplay themeDisplay) {
+
+ try {
+ PortletLayoutFinder portletLayoutFinder =
+ PortletLayoutFinderRegistryUtil.getPortletLayoutFinder(
+ ${capFirstModel}.class.getName());
+
+ PortletLayoutFinder.Result result = portletLayoutFinder.find(
+ themeDisplay, groupId);
+
+ if ((result == null) || Validator.isNull(result.getPortletId())) {
+ return false;
+ }
+
+ return true;
+ }
+ catch (PortalException pe) {
+ if (_log.isDebugEnabled()) {
+ _log.debug(pe.getLocalizedMessage(), pe);
+ }
+
+ return false;
+ }
+ }
+
+ private static final Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}AssetRenderer.class);
+
+ private AssetDisplayPageFriendlyURLProvider
+ _assetDisplayPageFriendlyURLProvider;
+ private final ${capFirstModel} _entry;
+ private final ResourceBundleLoader _resourceBundleLoader;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_AssetRendererFactory.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
new file mode 100644
index 0000000..b0ffa57
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_AssetRendererFactory.java.ftl
@@ -0,0 +1,205 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/asset/${capFirstModel}AssetRendererFactory.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.asset;
+
+import com.liferay.asset.kernel.model.AssetRenderer;
+import com.liferay.asset.kernel.model.AssetRendererFactory;
+import com.liferay.asset.kernel.model.BaseAssetRendererFactory;
+import com.liferay.petra.string.StringPool;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
+import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
+import com.liferay.portal.kernel.portlet.LiferayPortletURL;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.Portal;
+import com.liferay.portal.kernel.util.ResourceBundleLoaderUtil;
+import ${packageName}.constants.${capFirstModel}Constants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletURL;
+import javax.portlet.WindowState;
+import javax.portlet.WindowStateException;
+
+import javax.servlet.ServletContext;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ${capFirstModel} Asset Renderer Factory
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ service = AssetRendererFactory.class
+)
+public class ${capFirstModel}AssetRendererFactory
+ extends BaseAssetRendererFactory<${capFirstModel}> {
+
+ public static final String SYMBOLIC_NAME =
+ ${capFirstModel}Constants.RESOURCE_NAME + ".web";
+
+ public static final String TYPE = "${lowercaseModel}";
+
+ public ${capFirstModel}AssetRendererFactory() {
+ setClassName(${capFirstModel}.class.getName());
+ setCategorizable(true);
+ setPortletId(${capFirstModel}PortletKeys.${uppercaseModel});
+ setLinkable(true);
+ setSearchable(true);
+ setSelectable(true);
+ }
+
+ @Override
+ public AssetRenderer<${capFirstModel}> getAssetRenderer(long classPK, int type)
+ throws PortalException {
+
+ ${capFirstModel}AssetRenderer ${uncapFirstModel}AssetRenderer = new ${capFirstModel}AssetRenderer(
+ _${uncapFirstModel}LocalService.get${capFirstModel}(classPK),
+ ResourceBundleLoaderUtil.
+ getResourceBundleLoaderByBundleSymbolicName(SYMBOLIC_NAME));
+
+ ${uncapFirstModel}AssetRenderer.setAssetRendererType(type);
+ ${uncapFirstModel}AssetRenderer.setServletContext(_servletContext);
+
+ return ${uncapFirstModel}AssetRenderer;
+ }
+
+ @Override
+ public AssetRenderer<${capFirstModel}> getAssetRenderer(
+ long groupId, String urlTitle)
+ throws PortalException {
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}(groupId, urlTitle);
+
+ ${capFirstModel}AssetRenderer ${uncapFirstModel}AssetRenderer = new ${capFirstModel}AssetRenderer(
+ entry,
+ ResourceBundleLoaderUtil.
+ getResourceBundleLoaderByBundleSymbolicName(SYMBOLIC_NAME));
+
+ ${uncapFirstModel}AssetRenderer.setServletContext(_servletContext);
+
+ return ${uncapFirstModel}AssetRenderer;
+ }
+
+ @Override
+ public String getClassName() {
+ return ${capFirstModel}.class.getName();
+ }
+
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public PortletURL getURLAdd(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse, long classTypeId) {
+
+ PortletURL portletURL = _portal.getControlPanelPortletURL(
+ liferayPortletRequest, getGroup(liferayPortletRequest),
+ ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN, 0, 0,
+ PortletRequest.RENDER_PHASE);
+
+ portletURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/crud");
+ portletURL.setParameter(Constants.CMD, Constants.ADD);
+ portletURL.setParameter("fromAsset", StringPool.TRUE);
+
+ return portletURL;
+ }
+
+ @Override
+ public PortletURL getURLView(
+ LiferayPortletResponse liferayPortletResponse,
+ WindowState windowState) {
+
+ LiferayPortletURL liferayPortletURL =
+ liferayPortletResponse.createLiferayPortletURL(
+ ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ PortletRequest.RENDER_PHASE);
+
+ liferayPortletURL.setParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/view");
+ liferayPortletURL.setParameter(Constants.CMD, Constants.VIEW);
+ liferayPortletURL.setParameter("fromAsset", StringPool.TRUE);
+
+ try {
+ liferayPortletURL.setWindowState(windowState);
+ }
+ catch (WindowStateException wse) {
+ _log.error("Windos state is not valid. Skip.", wse);
+ }
+
+ return liferayPortletURL;
+ }
+
+ @Override
+ public boolean hasAddPermission(
+ PermissionChecker permissionChecker, long groupId, long classTypeId)
+ throws Exception {
+
+ if (_portletResourcePermission.contains(
+ permissionChecker, groupId, ActionKeys.VIEW)) {
+
+ return false;
+ }
+
+ return _portletResourcePermission.contains(
+ permissionChecker, groupId, ActionKeys.ADD_ENTRY);
+ }
+
+ @Override
+ public boolean hasPermission(
+ PermissionChecker permissionChecker, long classPK, String actionId)
+ throws Exception {
+
+ return _${uncapFirstModel}ModelResourcePermission.contains(
+ permissionChecker, classPK, actionId);
+ }
+
+ @Reference(
+ target = "(osgi.web.symbolicname=${packageName}.web)", unbind = "-"
+ )
+ public void setServletContext(ServletContext servletContext) {
+ _servletContext = servletContext;
+ }
+
+ private static final Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}AssetRendererFactory.class);
+
+ @Reference
+ private Portal _portal;
+
+ @Reference(
+ target = "(resource.name=" + ${capFirstModel}Constants.RESOURCE_NAME + ")"
+ )
+ private PortletResourcePermission _portletResourcePermission;
+
+ @Reference
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+
+ @Reference(target = "(model.class.name=${packageName}.model.${capFirstModel})")
+ private ModelResourcePermission<${capFirstModel}> _${uncapFirstModel}ModelResourcePermission;
+
+ @Reference(target = "(osgi.web.symbolicname=" + SYMBOLIC_NAME + ")")
+ private ServletContext _servletContext;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_Configuration.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_Configuration.java.ftl
new file mode 100644
index 0000000..01be10b
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_Configuration.java.ftl
@@ -0,0 +1,46 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}Configuration.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import aQute.bnd.annotation.metatype.Meta;
+
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+/**
+ * ${capFirstModel} Configuration
+ *
+ * @author ${damascus_author}
+ */
+@Meta.OCD(id = ${capFirstModel}PortletKeys.${uppercaseModel}_CONFIG)
+public interface ${capFirstModel}Configuration {
+
+ public static final String CONF_PREFS_VIEW_TYPE = "prefsViewType";
+
+ public static final String CONF_DATE_FORMAT = "dateFormat";
+
+ public static final String CONF_DATETIME_FORMAT = "datetimeFormat";
+
+ public static final String PREFS_VIEW_TYPE_DEFAULT = "0";
+
+ public static final String PREFS_VIEW_TYPE_USER = "1";
+
+ public static final String PREFS_VIEW_TYPE_USER_GROUP = "2";
+
+ @Meta.AD(deflt = PREFS_VIEW_TYPE_DEFAULT, required = false)
+ public int prefsViewType();
+
+ @Meta.AD(deflt = "yyyy/MM/dd", required = false)
+ public String dateFormat();
+
+ @Meta.AD(deflt = "yyyy/MM/dd HH:mm", required = false)
+ public String datetimeFormat();
+
+ @Meta.AD(deflt = "%Y/%m/%d", required = false)
+ public String datePickerFormat();
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_ConfigurationAction.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ConfigurationAction.java.ftl
new file mode 100644
index 0000000..5777e34
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ConfigurationAction.java.ftl
@@ -0,0 +1,161 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}ConfigurationAction.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import aQute.bnd.annotation.metatype.Configurable;
+
+import com.liferay.portal.kernel.portlet.ConfigurationAction;
+import com.liferay.portal.kernel.portlet.DefaultConfigurationAction;
+import com.liferay.portal.kernel.servlet.SessionMessages;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletConfig;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Modified;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ${capFirstModel} Configuraion Aciton
+ *
+ * Determine the scope of the portlet configuration in DS properties of Portlet
+ * class The default of this generator is Portlet Instance scope.
+ *
+ * Look at the elements preferences-company-wide, preferences-unique-per-layout
+ * and preferences-owned-by-group to determine the right scope. The following
+ * table maps out the scopes:
+ *
+ * liferay-portlet.xml Scope preferences-company-wide=true Company
+ * preferences-owned-by-group=true AND preferences-unique-per-layout=false Group
+ * preferences-owned-by-group=true AND preferences-unique-per-layout=true
+ * Portlet Instance
+ *
+ * @author ${damascus_author}
+ *
+ */
+@Component(
+ configurationPid = ${capFirstModel}PortletKeys.${uppercaseModel}_CONFIG,
+ configurationPolicy = ConfigurationPolicy.OPTIONAL, immediate = true,
+ property = "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ service = ConfigurationAction.class
+)
+public class ${capFirstModel}ConfigurationAction extends DefaultConfigurationAction {
+
+ @Override
+ public String getJspPath(HttpServletRequest httpServletRequest) {
+ return "/${snakecaseModel}/configuration.jsp";
+ }
+
+ @Override
+ public void include(
+ PortletConfig portletConfig, HttpServletRequest httpServletRequest,
+ HttpServletResponse httpServletResponse)
+ throws Exception {
+
+ if (_log.isDebugEnabled()) {
+ _log.debug("${capFirstModel} Portlet configuration include");
+ }
+
+ httpServletRequest.setAttribute(
+ ${capFirstModel}Configuration.class.getName(), _${uncapFirstModel}Configuration);
+
+ super.include(portletConfig, httpServletRequest, httpServletResponse);
+ }
+
+ @Override
+ public void processAction(
+ PortletConfig portletConfig, ActionRequest actionRequest,
+ ActionResponse actionResponse)
+ throws Exception {
+
+ int prefsViewType = ParamUtil.getInteger(
+ actionRequest, ${capFirstModel}Configuration.CONF_PREFS_VIEW_TYPE,
+ Integer.valueOf(${capFirstModel}Configuration.PREFS_VIEW_TYPE_DEFAULT));
+ String dateFormat = ParamUtil.getString(
+ actionRequest, ${capFirstModel}Configuration.CONF_DATE_FORMAT);
+ String datetimeFormat = ParamUtil.getString(
+ actionRequest, ${capFirstModel}Configuration.CONF_DATETIME_FORMAT);
+
+ if (_log.isDebugEnabled()) {
+ _log.debug("Prefs View Type :" + prefsViewType);
+ _log.debug("Date Format :" + dateFormat);
+ _log.debug("Date Time Format:" + datetimeFormat);
+ }
+
+ List errors = new ArrayList<>();
+
+ if (validate(dateFormat, datetimeFormat, errors)) {
+ setPreference(
+ actionRequest, ${capFirstModel}Configuration.CONF_PREFS_VIEW_TYPE,
+ String.valueOf(prefsViewType));
+ setPreference(
+ actionRequest, ${capFirstModel}Configuration.CONF_DATE_FORMAT,
+ dateFormat);
+ setPreference(
+ actionRequest, ${capFirstModel}Configuration.CONF_DATETIME_FORMAT,
+ datetimeFormat);
+
+ SessionMessages.add(actionRequest, "prefsSuccess");
+ }
+
+ super.processAction(portletConfig, actionRequest, actionResponse);
+ }
+
+ @Activate
+ @Modified
+ protected void activate(Map properties) {
+ _${uncapFirstModel}Configuration = Configurable.createConfigurable(
+ ${capFirstModel}Configuration.class, properties);
+ }
+
+ /**
+ * Validate Preference
+ *
+ * @param dateFormat Date Format
+ * @param datetimeFormat Date Time Format
+ * @param errors
+ * @return boolean
+ */
+ protected boolean validate(
+ String dateFormat, String datetimeFormat, List errors) {
+
+ boolean valid = true;
+
+ if (Validator.isNull(dateFormat)) {
+ errors.add("date-format-required");
+ valid = false;
+ }
+ else if (Validator.isNull(datetimeFormat)) {
+ errors.add("datetime-format.required");
+ valid = false;
+ }
+
+ return valid;
+ }
+
+ private static final Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}ConfigurationAction.class);
+
+ private volatile ${capFirstModel}Configuration _${uncapFirstModel}Configuration;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
new file mode 100644
index 0000000..5bec50f
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCActionCommand.java.ftl
@@ -0,0 +1,291 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}CrudMVCActionCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.asset.display.page.portlet.AssetDisplayPageEntryFormProcessor;
+import com.liferay.petra.reflect.ReflectionUtil;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.model.TrashedModel;
+import com.liferay.portal.kernel.portlet.bridges.mvc.BaseMVCActionCommand;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCActionCommand;
+import com.liferay.portal.kernel.service.ServiceContext;
+import com.liferay.portal.kernel.service.ServiceContextFactory;
+import com.liferay.portal.kernel.servlet.SessionErrors;
+import com.liferay.portal.kernel.servlet.SessionMessages;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.PortalUtil;
+import com.liferay.portal.kernel.util.StringUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalService;
+import ${packageName}.service.${capFirstModel}Service;
+import com.liferay.trash.service.TrashEntryService;
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "mvc.command.name=/${lowercaseModel}/crud"
+ },
+ service = MVCActionCommand.class
+)
+public class ${capFirstModel}CrudMVCActionCommand extends BaseMVCActionCommand {
+
+ /**
+ * Add Entry
+ *
+ * @param request
+ * @param response
+ * @throws ${capFirstModel}ValidateException, Exception
+ */
+ public void addEntry(ActionRequest request, ActionResponse response)
+ throws Exception, ${capFirstModel}ValidateException {
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(
+ primaryKey, request);
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ ${capFirstModel}.class.getName(), request);
+
+ // Add entry
+
+ _${uncapFirstModel}Service.addEntry(entry, serviceContext);
+
+ _assetDisplayPageEntryFormProcessor.process(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), request);
+
+ SessionMessages.add(request, "${lowercaseModel}AddedSuccessfully");
+ }
+
+ /**
+ * Delte Entry
+ *
+ * @param request
+ * @param response
+ * @param moveToTrash true to move to trush.
+ * @throws PortalException
+ * @throws Exception
+ */
+ public void deleteEntry(
+ ActionRequest request, ActionResponse response, boolean moveToTrash)
+ throws PortalException {
+
+ long[] deleteEntryIds = null;
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ long entryId = ParamUtil.getLong(request, "resourcePrimKey", 0L);
+
+ if (entryId > 0) {
+ deleteEntryIds = new long[] {entryId};
+ }
+ else {
+ deleteEntryIds = StringUtil.split(
+ ParamUtil.getString(request, "deleteEntryIds"), 0L);
+ }
+
+ List trashedModels = new ArrayList<>();
+
+ for (long deleteEntryId : deleteEntryIds) {
+ try {
+ if (moveToTrash) {
+ ${capFirstModel} entry = _${uncapFirstModel}Service.moveEntryToTrash(
+ deleteEntryId);
+
+ trashedModels.add(entry);
+ }
+ else {
+ _${uncapFirstModel}Service.deleteEntry(deleteEntryId);
+ }
+ }
+ catch (PortalException pe) {
+ ReflectionUtil.throwException(pe);
+ }
+ }
+
+ if (moveToTrash && !trashedModels.isEmpty()) {
+ Map data = new HashMap<>();
+
+ data.put("trashedModels", trashedModels);
+
+ addDeleteSuccessData(request, data);
+ }
+ }
+
+ /**
+ * Restore Entries
+ *
+ * @param actionRequest
+ * @throws Exception
+ */
+ public void restoreTrashEntries(ActionRequest actionRequest)
+ throws Exception {
+
+ long[] restoreTrashEntryIds = StringUtil.split(
+ ParamUtil.getString(actionRequest, "restoreTrashEntryIds"), 0L);
+
+ for (long restoreTrashEntryId : restoreTrashEntryIds) {
+ _trashEntryService.restoreEntry(restoreTrashEntryId);
+ }
+ }
+
+ /**
+ * Update Entry
+ *
+ * @param request
+ * @param response
+ * @throws Exception
+ */
+ public void updateEntry(ActionRequest request, ActionResponse response)
+ throws Exception {
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+
+ ${capFirstModel} entry = _${uncapFirstModel}LocalService.get${capFirstModel}FromRequest(
+ primaryKey, request);
+
+ ServiceContext serviceContext = ServiceContextFactory.getInstance(
+ ${capFirstModel}.class.getName(), request);
+
+ //Update entry
+ _${uncapFirstModel}Service.updateEntry(entry, serviceContext);
+
+ _assetDisplayPageEntryFormProcessor.process(
+ ${capFirstModel}.class.getName(), entry.getPrimaryKey(), request);
+
+ SessionMessages.add(request, "${lowercaseModel}UpdatedSuccessfully");
+ }
+
+ /**
+ * Single Delete
+ *
+ * @param entry
+ * @param moveToTrash
+ * @param trashedModels
+ */
+ protected void _deleteEntry(
+ ${capFirstModel} entry, boolean moveToTrash, List trashedModels) {
+
+ try {
+ if (moveToTrash) {
+ trashedModels.add(
+ _${uncapFirstModel}Service.moveEntryToTrash(entry.getPrimaryKey()));
+ }
+ else {
+ _${uncapFirstModel}Service.deleteEntry(entry.getPrimaryKey());
+ }
+ }
+ catch (PortalException pe) {
+ ReflectionUtil.throwException(pe);
+ }
+ }
+
+ @Override
+ protected void doProcessAction(
+ ActionRequest request, ActionResponse response)
+ throws IOException {
+
+ try {
+
+ // Fetch command
+
+ String cmd = ParamUtil.getString(request, Constants.CMD);
+
+ if (cmd.equals(Constants.ADD)) {
+ addEntry(request, response);
+ }
+ else if (cmd.equals(Constants.UPDATE)) {
+ updateEntry(request, response);
+ }
+ else if (cmd.equals(Constants.DELETE)) {
+ deleteEntry(request, response, false);
+ }
+ else if (cmd.equals(Constants.MOVE_TO_TRASH)) {
+ deleteEntry(request, response, true);
+ }
+ else if (cmd.equals(Constants.RESTORE)) {
+ restoreTrashEntries(request);
+ }
+ }
+ catch (${capFirstModel}ValidateException ssbve) {
+ for (String error : ssbve.getErrors()) {
+ SessionErrors.add(request, error);
+ }
+
+ PortalUtil.copyRequestParameters(request, response);
+ response.setRenderParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/crud");
+ hideDefaultSuccessMessage(request);
+ }
+ catch (Exception t) {
+ _log.error(t.getLocalizedMessage(), t);
+ SessionErrors.add(request, PortalException.class);
+ hideDefaultSuccessMessage(request);
+ }
+
+ //For access from Asset Publisher
+ String redirect = ParamUtil.getString(request, "redirect");
+ Boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+
+ if (Validator.isNotNull(redirect) && (true == fromAsset)) {
+ sendRedirect(request, response, redirect);
+ }
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}LocalService(
+ ${capFirstModel}LocalService ${uncapFirstModel}LocalService) {
+
+ _${uncapFirstModel}LocalService = ${uncapFirstModel}LocalService;
+ }
+
+ @Reference(unbind = "-")
+ protected void set${capFirstModel}Service(${capFirstModel}Service ${uncapFirstModel}Service) {
+ _${uncapFirstModel}Service = ${uncapFirstModel}Service;
+ }
+
+ private static Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}CrudMVCActionCommand.class);
+
+ @Reference
+ private AssetDisplayPageEntryFormProcessor
+ _assetDisplayPageEntryFormProcessor;
+
+ private ${capFirstModel}LocalService _${uncapFirstModel}LocalService;
+ private ${capFirstModel}Service _${uncapFirstModel}Service;
+
+ @Reference
+ private TrashEntryService _trashEntryService;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCRenderCommand.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCRenderCommand.java.ftl
new file mode 100644
index 0000000..d7f8f62
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_CrudMVCRenderCommand.java.ftl
@@ -0,0 +1,248 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}CrudMVCRenderCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCRenderCommand;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.exception.${capFirstModel}ValidateException;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}Service;
+import ${packageName}.web.constants.${capFirstModel}WebKeys;
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}EntryPermission;
+import ${packageName}.web.upload.${capFirstModel}ItemSelectorHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalService;
+import ${packageName}.web.constants.${capFirstValidationModel}WebKeys;
+import ${packageName}.web.util.${capFirstValidationModel}ViewHelper;
+ #if>
+#list>
+// //
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * CRUD Render
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "mvc.command.name=/${lowercaseModel}/crud"
+ },
+ service = MVCRenderCommand.class
+)
+public class ${capFirstModel}CrudMVCRenderCommand implements MVCRenderCommand {
+
+ /**
+ * Edit Page JSP file
+ */
+ public String getEditPageJSP() {
+ return ${capFirstModel}WebKeys.EDIT_JSP;
+ }
+
+ /**
+ * View Page JSP file
+ */
+ public String getViewPageJSP() {
+ return ${capFirstModel}WebKeys.VIEW_JSP;
+ }
+
+ /**
+ * View Record JSP file
+ */
+ public String getViewRecordPageJSP() {
+ return ${capFirstModel}WebKeys.VIEW_RECORD_JSP;
+ }
+
+ @Override
+ public String render(RenderRequest request, RenderResponse response)
+ throws PortletException {
+
+ String renderJSP = getViewPageJSP();
+
+ // Fetch command
+
+ String cmd = ParamUtil.getString(request, Constants.CMD);
+
+ // Fetch primary key
+
+ long primaryKey = ParamUtil.getLong(request, "resourcePrimKey", 0);
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ try {
+ if (cmd.equalsIgnoreCase(Constants.UPDATE)) {
+ renderJSP = update(request, themeDisplay, primaryKey);
+ }
+ else if (cmd.equalsIgnoreCase(Constants.VIEW)) {
+ renderJSP = view(request, themeDisplay, primaryKey);
+ }
+ else {
+ renderJSP = add(request, themeDisplay, primaryKey);
+ }
+ }
+ catch (PortalException pe) {
+ throw new PortletException(pe.getMessage());
+ }
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+
+ request.setAttribute(${capFirstValidationModel}WebKeys.${uppercaseValidationModel}_VIEW_HELPER, _${uncapFirstValidationModel}ViewHelper);
+ request.setAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE, _${uncapFirstValidationModel}LocalService);
+ #if>
+#list>
+// //
+
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_ITEM_SELECTOR_HELPER,
+ _${uncapFirstModel}ItemSelectorHelper);
+
+ return renderJSP;
+ }
+
+ /**
+ * Add record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return JSP file path
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ * @throws PortletException
+ */
+ protected String add(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, PortletException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = null;
+
+ if (Validator.isNull(request.getParameter("addErrors"))) {
+ record = _${uncapFirstModel}Service.getInitialized${capFirstModel}(
+ primaryKey, request);
+ }
+ else {
+ record = _${uncapFirstModel}Service.get${capFirstModel}FromRequest(
+ primaryKey, request);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getEditPageJSP();
+ }
+
+ /**
+ * Update record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return JSP file path to open
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ */
+ protected String update(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = _${uncapFirstModel}Service.get${capFirstModel}(primaryKey);
+
+ if (!${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), record,
+ ActionKeys.UPDATE)) {
+
+ List error = new ArrayList<>();
+ error.add("permission-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getEditPageJSP();
+ }
+
+ /**
+ * View record
+ *
+ * @param request
+ * @param themeDisplay
+ * @param primaryKey
+ * @return
+ * @throws PortalException
+ * @throws ${capFirstModel}ValidateException
+ */
+ protected String view(
+ RenderRequest request, ThemeDisplay themeDisplay, long primaryKey)
+ throws PortalException, ${capFirstModel}ValidateException {
+
+ ${capFirstModel} record = _${uncapFirstModel}Service.get${capFirstModel}(primaryKey);
+
+ if (!${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), record, ActionKeys.VIEW)) {
+
+ List error = new ArrayList<>();
+ error.add("permission-error");
+
+ throw new ${capFirstModel}ValidateException(error);
+ }
+
+ request.setAttribute("${uncapFirstModel}", record);
+
+ return getViewRecordPageJSP();
+ }
+
+ @Reference
+ private ${capFirstModel}Service _${uncapFirstModel}Service;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+
+ @Reference
+ private ${capFirstValidationModel}ViewHelper _${uncapFirstValidationModel}ViewHelper;
+
+ @Reference
+ private ${capFirstValidationModel}LocalService _${uncapFirstValidationModel}LocalService;
+ #if>
+#list>
+// //
+
+ @Reference
+ private ${capFirstModel}ItemSelectorHelper _${uncapFirstModel}ItemSelectorHelper;
+
+}
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_DisplayContext.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_DisplayContext.java.ftl
new file mode 100644
index 0000000..fe3bbae
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_DisplayContext.java.ftl
@@ -0,0 +1,188 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/internal/display/context/${capFirstModel}DisplayContext.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.internal.display.context;
+
+import com.liferay.portal.kernel.dao.search.DisplayTerms;
+import com.liferay.portal.kernel.dao.search.SearchContainer;
+import com.liferay.portal.kernel.dao.search.SearchContainerResults;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
+import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
+import com.liferay.portal.kernel.portlet.PortalPreferences;
+import com.liferay.portal.kernel.portlet.PortletPreferencesFactoryUtil;
+import com.liferay.portal.kernel.portlet.PortletURLUtil;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}EntryPermission;
+import ${packageName}.web.util.${capFirstModel}ViewHelper;
+import com.liferay.trash.TrashHelper;
+
+import java.text.ParseException;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.PortletException;
+import javax.portlet.PortletURL;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ${capFirstModel} Display Context
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}DisplayContext {
+
+ public ${capFirstModel}DisplayContext(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse, TrashHelper trashHelper,
+ ${capFirstModel}ViewHelper ${uncapFirstModel}ViewHelper) {
+
+ _liferayPortletRequest = liferayPortletRequest;
+ _liferayPortletResponse = liferayPortletResponse;
+ _trashHelper = trashHelper;
+
+ _portalPreferences = PortletPreferencesFactoryUtil.getPortalPreferences(
+ liferayPortletRequest);
+
+ _httpServletRequest = _liferayPortletRequest.getHttpServletRequest();
+ _${uncapFirstModel}ViewHelper = ${uncapFirstModel}ViewHelper;
+ }
+
+ public List getAvailableActions(${capFirstModel} entry)
+ throws PortalException {
+
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)_httpServletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ if (${capFirstModel}EntryPermission.contains(
+ themeDisplay.getPermissionChecker(), entry,
+ ActionKeys.DELETE)) {
+
+ return Collections.singletonList("deleteEntries");
+ }
+
+ return Collections.emptyList();
+ }
+
+ public Map getComponentContext() throws PortalException {
+ ThemeDisplay themeDisplay =
+ (ThemeDisplay)_httpServletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+
+ return new HashMap() {
+ {
+ put(
+ "trashEnabled",
+ _trashHelper.isTrashEnabled(
+ themeDisplay.getScopeGroupId()));
+ }
+ };
+ }
+
+ public String getDisplayStyle() {
+ String displayStyle = ParamUtil.getString(
+ _httpServletRequest, "displayStyle");
+
+ if (Validator.isNull(displayStyle)) {
+ return _portalPreferences.getValue(
+ ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN, "entries-display-style",
+ "icon");
+ }
+
+ _portalPreferences.setValue(
+ ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN, "entries-display-style",
+ displayStyle);
+
+ _httpServletRequest.setAttribute(
+ WebKeys.SINGLE_PAGE_APPLICATION_CLEAR_CACHE, Boolean.TRUE);
+
+ return displayStyle;
+ }
+
+ public SearchContainer<${capFirstModel}> getSearchContainer()
+ throws ParseException, PortalException, PortletException {
+
+ PortletURL navigationPortletURL =
+ _liferayPortletResponse.createRenderURL();
+
+ String keywords = ParamUtil.getString(
+ _httpServletRequest, DisplayTerms.KEYWORDS);
+ int cur = ParamUtil.getInteger(
+ _httpServletRequest, SearchContainer.DEFAULT_CUR_PARAM);
+ String orderByCol = ParamUtil.getString(
+ _httpServletRequest, SearchContainer.DEFAULT_ORDER_BY_COL_PARAM,
+ "${lowercaseModel}Id");
+ String orderByType = ParamUtil.getString(
+ _httpServletRequest, SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM,
+ "asc");
+
+ navigationPortletURL.setParameter(DisplayTerms.KEYWORDS, keywords);
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_CUR_PARAM, String.valueOf(cur));
+ navigationPortletURL.setParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/view");
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_COL_PARAM, orderByCol);
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM, orderByType);
+
+ SearchContainer<${capFirstModel}> _searchContainer = new SearchContainer<>(
+ _liferayPortletRequest,
+ PortletURLUtil.clone(navigationPortletURL, _liferayPortletResponse),
+ null, "no-records-were-found");
+
+ _searchContainer.setId("entryList");
+ _searchContainer.setDeltaConfigurable(true);
+
+ _searchContainer.setOrderByCol(orderByCol);
+ _searchContainer.setOrderByType(orderByType);
+
+ SearchContainerResults<${capFirstModel}> searchContainerResults = null;
+
+ if (Validator.isNull(keywords)) {
+ searchContainerResults = _${uncapFirstModel}ViewHelper.getListFromDB(
+ _liferayPortletRequest, _searchContainer,
+ new int[] {WorkflowConstants.STATUS_APPROVED});
+ }
+ else {
+ searchContainerResults = _${uncapFirstModel}ViewHelper.getListFromIndex(
+ _liferayPortletRequest, _searchContainer,
+ WorkflowConstants.STATUS_APPROVED);
+ }
+
+ _searchContainer.setTotal(searchContainerResults.getTotal());
+ _searchContainer.setResults(searchContainerResults.getResults());
+
+ return _searchContainer;
+ }
+
+ private static final Logger _log = LoggerFactory.getLogger(
+ ${capFirstModel}DisplayContext.class);
+
+ private final HttpServletRequest _httpServletRequest;
+ private final LiferayPortletRequest _liferayPortletRequest;
+ private final LiferayPortletResponse _liferayPortletResponse;
+ private final PortalPreferences _portalPreferences;
+ private ${capFirstModel}ViewHelper _${uncapFirstModel}ViewHelper;
+ private final TrashHelper _trashHelper;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_EntryPermission.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_EntryPermission.java.ftl
new file mode 100644
index 0000000..5addb3b
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_EntryPermission.java.ftl
@@ -0,0 +1,63 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/internal/security/permission/resource/${capFirstModel}EntryPermission.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.internal.security.permission.resource;
+
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
+import ${packageName}.model.${capFirstModel};
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * Entry Permission
+ *
+ * @author ${damascus_author}
+ */
+@Component(immediate = true, service = {})
+public class ${capFirstModel}EntryPermission {
+
+ public static boolean contains(
+ PermissionChecker permissionChecker, long entryId, String actionId)
+ throws PortalException {
+
+ return _${uncapFirstModel}ModelResourcePermission.contains(
+ permissionChecker, entryId, actionId);
+ }
+
+ public static boolean contains(
+ PermissionChecker permissionChecker, ${capFirstModel} entry,
+ String actionId)
+ throws PortalException {
+
+ return _${uncapFirstModel}ModelResourcePermission.contains(
+ permissionChecker, entry, actionId);
+ }
+
+ @Reference(
+ policy = ReferencePolicy.DYNAMIC,
+ policyOption = ReferencePolicyOption.GREEDY,
+ target = "(model.class.name=${packageName}.model.${capFirstModel})"
+ )
+ protected void set${capFirstModel}ModelResourcePermission(
+ ModelResourcePermission<${capFirstModel}> modelResourcePermission) {
+
+ _${uncapFirstModel}ModelResourcePermission = modelResourcePermission;
+ }
+
+ protected void unset${capFirstModel}ModelResourcePermission(
+ ModelResourcePermission<${capFirstModel}> modelResourcePermission) {
+ }
+
+ private static ModelResourcePermission<${capFirstModel}>
+ _${uncapFirstModel}ModelResourcePermission;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_ExportMVCResourceCommand.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ExportMVCResourceCommand.java.ftl
new file mode 100644
index 0000000..5e00cce
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ExportMVCResourceCommand.java.ftl
@@ -0,0 +1,193 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}ExportMVCResourceCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.dao.search.DisplayTerms;
+import com.liferay.portal.kernel.dao.search.SearchContainer;
+import com.liferay.portal.kernel.dao.search.SearchContainerResults;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCResourceCommand;
+import com.liferay.portal.kernel.search.SearchException;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ContentTypes;
+import com.liferay.portal.kernel.util.HtmlUtil;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.workflow.WorkflowConstants;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.web.util.${capFirstModel}ViewHelper;
+
+import java.io.IOException;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.portlet.PortletPreferences;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Export Resource Command
+ *
+ * @author Softbless
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN,
+ "mvc.command.name=/${lowercaseModel}/export"
+ },
+ service = MVCResourceCommand.class
+)
+public class ${capFirstModel}ExportMVCResourceCommand implements MVCResourceCommand {
+
+ @Override
+ public boolean serveResource(
+ ResourceRequest resourceRequest, ResourceResponse resourceResponse) {
+
+ String cmd = ParamUtil.getString(resourceRequest, Constants.CMD, "");
+
+// //
+ if (!cmd.equals(Constants.EXPORT)) {
+ return false;
+ }
+
+ ${capFirstModel}Configuration ${uncapFirstModel}Configuration =
+ (${capFirstModel}Configuration)resourceRequest.getAttribute(
+ ${capFirstModel}Configuration.class.getName());
+
+ PortletPreferences portletPreferences =
+ resourceRequest.getPreferences();
+
+ String dateFormatVal = HtmlUtil.escape(
+ portletPreferences.getValue(
+ "dateFormat",
+ Validator.isNull(${uncapFirstModel}Configuration) ? "yyyy/MM/dd" :
+ ${uncapFirstModel}Configuration.dateFormat()));
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatVal);
+
+ String keywords = ParamUtil.getString(
+ resourceRequest, DisplayTerms.KEYWORDS);
+ String orderByCol = ParamUtil.getString(
+ resourceRequest, SearchContainer.DEFAULT_ORDER_BY_COL_PARAM,
+ "${lowercaseModel}Id");
+ String orderByType = ParamUtil.getString(
+ resourceRequest, SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM,
+ "asc");
+
+ String filename = Constants.EXPORT;
+
+ SearchContainerResults<${capFirstModel}> searchContainerResults = null;
+
+ try {
+ if (Validator.isNull(keywords)) {
+ searchContainerResults = _${uncapFirstModel}ViewHelper.getListFromDB(
+ resourceRequest, -1, -1, orderByCol, orderByType,
+ new int[] {WorkflowConstants.STATUS_APPROVED});
+ }
+ else {
+ searchContainerResults = _${uncapFirstModel}ViewHelper.getListFromIndex(
+ resourceRequest, -1, -1, WorkflowConstants.STATUS_APPROVED);
+ }
+ }
+ catch (ParseException | SearchException e) {
+ e.printStackTrace();
+ }
+
+ try (Workbook workbook = new HSSFWorkbook()) {
+ Sheet sheet = workbook.createSheet("data");
+
+ List headers = new LinkedList<>();
+
+ <#list application.fields as field >
+ headers.add("${field.name?cap_first}");
+ #list>
+
+ // Header
+
+ Row headerRow = sheet.createRow(0);
+
+ for (int i = 0; i < headers.size(); i++) {
+ Cell cell = headerRow.createCell(i);
+
+ cell.setCellValue(headers.get(i));
+ }
+
+ if (Validator.isNotNull(searchContainerResults) &&
+ (searchContainerResults.getTotal() > 0)) {
+
+ List<${capFirstModel}> datas = searchContainerResults.getResults();
+
+ for (int i = 0; i < searchContainerResults.getTotal(); i++) {
+ Row row = sheet.createRow(i + 1);
+
+ for (int j = 0; j < headers.size(); j++) {
+ Cell cell = row.createCell(j);
+ switch (j) {
+ <#assign counter = 0>
+ <#list application.fields as field >
+ case ${counter}:
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime"
+ >
+ cell.setCellValue(dateFormat.format(datas.get(i).get${field.name?cap_first}()));
+ <#else>
+ cell.setCellValue(datas.get(i).get${field.name?cap_first}());
+ #if>
+
+ break;
+ <#assign counter += 1>
+ #list>
+ default:
+
+ break;
+ }
+ }
+ }
+ }
+
+ resourceResponse.setContentType(
+ ContentTypes.APPLICATION_VND_MS_EXCEL);
+ resourceResponse.setProperty(
+ "Content-Disposition",
+ "attachment; filename=\"" + filename + ".xls\"");
+ workbook.write(resourceResponse.getPortletOutputStream());
+
+ return true;
+ }
+ catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+// //
+
+ return false;
+ }
+
+ @Reference(unbind = "-")
+ public void setViewHelper(${capFirstModel}ViewHelper ${uncapFirstModel}ViewHelper) {
+ _${uncapFirstModel}ViewHelper = ${uncapFirstModel}ViewHelper;
+ }
+
+ private ${capFirstModel}ViewHelper _${uncapFirstModel}ViewHelper;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_FriendlyURLMapper.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_FriendlyURLMapper.java.ftl
new file mode 100644
index 0000000..7f0700b
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_FriendlyURLMapper.java.ftl
@@ -0,0 +1,39 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/route/${capFirstModel}FriendlyURLMapper.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.route;
+
+import com.liferay.portal.kernel.portlet.DefaultFriendlyURLMapper;
+import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * FriendlyURL Mapper
+ *
+ * This is used to mapping Friendly URL to the portlet. This class is reqired for routing path correctly for Asset Publisher.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ property = {
+ "com.liferay.portlet.friendly-url-routes=META-INF/friendly-url-routes/routes.xml",
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}
+ },
+ service = FriendlyURLMapper.class
+)
+public class ${capFirstModel}FriendlyURLMapper extends DefaultFriendlyURLMapper {
+
+ @Override
+ public String getMapping() {
+ return _MAPPING;
+ }
+
+ private static final String _MAPPING = "${uncapFirstModel}";
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_ItemSelectorHelper.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ItemSelectorHelper.java.ftl
new file mode 100644
index 0000000..ac145cc
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ItemSelectorHelper.java.ftl
@@ -0,0 +1,75 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/upload/${capFirstModel}ItemSelectorHelper.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.upload;
+
+import com.liferay.item.selector.ItemSelector;
+import com.liferay.item.selector.ItemSelectorReturnType;
+import com.liferay.item.selector.criteria.FileEntryItemSelectorReturnType;
+import com.liferay.item.selector.criteria.file.criterion.FileItemSelectorCriterion;
+import com.liferay.portal.kernel.portlet.RequestBackedPortletURLFactory;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.PortletURL;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * Item Selector Helper
+ *
+ * This is used for Documents and Media related operations (such as uploading assets, selecting assets, e.g)
+ *
+ * @author ${damascus_author}
+ */
+@Component(service = ${capFirstModel}ItemSelectorHelper.class)
+public class ${capFirstModel}ItemSelectorHelper {
+
+ public String getItemSelectorURL(
+ RequestBackedPortletURLFactory requestBackedPortletURLFactory,
+ ThemeDisplay themeDisplay, String itemSelectedEventName) {
+
+ List desiredItemSelectorReturnTypes =
+ new ArrayList<>();
+ desiredItemSelectorReturnTypes.add(
+ new FileEntryItemSelectorReturnType());
+
+ FileItemSelectorCriterion fileItemSelectorCriterion =
+ new FileItemSelectorCriterion();
+
+ fileItemSelectorCriterion.setDesiredItemSelectorReturnTypes(
+ desiredItemSelectorReturnTypes);
+
+ PortletURL itemSelectorURL = _itemSelector.getItemSelectorURL(
+ requestBackedPortletURLFactory, itemSelectedEventName,
+ fileItemSelectorCriterion);
+
+ return itemSelectorURL.toString();
+ }
+
+ @Reference(
+ cardinality = ReferenceCardinality.OPTIONAL,
+ policy = ReferencePolicy.DYNAMIC,
+ policyOption = ReferencePolicyOption.GREEDY
+ )
+ public void setItemSelector(ItemSelector itemSelector) {
+ _itemSelector = itemSelector;
+ }
+
+ public void unsetItemSelector(ItemSelector itemSelector) {
+ _itemSelector = null;
+ }
+
+ private ItemSelector _itemSelector;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_Language.properties.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_Language.properties.ftl
new file mode 100644
index 0000000..165b544
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_Language.properties.ftl
@@ -0,0 +1,33 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/content/Language.properties">
+<#assign skipTemplate = !generateWeb>
+# #
+
+# #
+model.resource.${packageName}=${damascus.projectName}
+
+<#list damascus.applications as application>
+javax.portlet.short-title.${application.model?lower_case}web=${camelcaseProjectName}Web
+javax.portlet.title.${application.model?lower_case}web=${camelcaseProjectName}Web
+model.resource.${packageName}.model.${application.model?cap_first}=${application.model?cap_first}
+ <#list application.fields as field >
+${application.model?lower_case}-${field.name?lower_case}=${field.title}
+${field.name?lower_case}=${field.title}
+ <#if field.required?? && field.required == true>
+${application.model?lower_case}-${field.name?lower_case}-required=The field ${field.title} must be filled!
+ #if>
+ #list>
+add-${application.model?lower_case}=Add ${application.model?lower_case}
+${application.model?lower_case}-added-successfully=The data has been added.
+${application.model?lower_case}-updated-successfully=The data has been updated.
+${application.model?lower_case}-deleted-successfully=The data has been deleted.
+#list>
+there-was-an-unexpected-error.-please-refresh-the-current-page=Unexpected error. Please refresh.
+permissions=Permissions
+view=View
+edit=Update
+remove=Delete
+trash=Move to trash
+# #
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_LayoutFinder.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_LayoutFinder.java.ftl
new file mode 100644
index 0000000..447bf6a
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_LayoutFinder.java.ftl
@@ -0,0 +1,30 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}LayoutFinder.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import com.liferay.portal.kernel.portlet.BasePortletLayoutFinder;
+import com.liferay.portal.kernel.portlet.PortletLayoutFinder;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = PortletLayoutFinder.class
+)
+public class ${capFirstModel}LayoutFinder extends BasePortletLayoutFinder {
+
+ @Override
+ protected String[] getPortletIds() {
+ return _PORTLET_IDS;
+ }
+
+ private static final String[] _PORTLET_IDS = {${capFirstModel}PortletKeys.${uppercaseModel}};
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_ManagementToolbarDisplayContext.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ManagementToolbarDisplayContext.java.ftl
new file mode 100644
index 0000000..4dd75dd
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ManagementToolbarDisplayContext.java.ftl
@@ -0,0 +1,346 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/internal/display/context/${capFirstModel}ManagementToolbarDisplayContext.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.internal.display.context;
+
+import com.liferay.frontend.taglib.clay.servlet.taglib.display.context.SearchContainerManagementToolbarDisplayContext;
+import com.liferay.frontend.taglib.clay.servlet.taglib.util.CreationMenu;
+import com.liferay.frontend.taglib.clay.servlet.taglib.util.DropdownItem;
+import com.liferay.frontend.taglib.clay.servlet.taglib.util.DropdownItemList;
+import com.liferay.frontend.taglib.clay.servlet.taglib.util.ViewTypeItem;
+import com.liferay.portal.kernel.dao.search.DisplayTerms;
+import com.liferay.portal.kernel.dao.search.SearchContainer;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.language.LanguageUtil;
+import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
+import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
+import com.liferay.portal.kernel.security.permission.ActionKeys;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.Constants;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.web.internal.security.permission.resource.${capFirstModel}Permission;
+import com.liferay.trash.TrashHelper;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.PortletURL;
+import javax.portlet.ResourceURL;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * ${capFirstModel} Management Toolbar Display Context
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}ManagementToolbarDisplayContext
+ extends SearchContainerManagementToolbarDisplayContext {
+
+ public ${capFirstModel}ManagementToolbarDisplayContext(
+ LiferayPortletRequest liferayPortletRequest,
+ LiferayPortletResponse liferayPortletResponse,
+ HttpServletRequest httpServletRequest,
+ SearchContainer> searchContainer, TrashHelper trashHelper,
+ String displayStyle) {
+
+ super(
+ liferayPortletRequest, liferayPortletResponse, httpServletRequest,
+ searchContainer);
+
+ _trashHelper = trashHelper;
+ _displayStyle = displayStyle;
+
+ _themeDisplay = (ThemeDisplay)httpServletRequest.getAttribute(
+ WebKeys.THEME_DISPLAY);
+ }
+
+ /**
+ * Order Dropdown items
+ *
+ * @return
+ */
+ public List _getOrderByDropdownItems() {
+ return new DropdownItemList() {
+ {
+// //
+<#list application.fields as field >
+ <#if field.primary?? && field.primary == false >
+ add(
+ dropdownItem -> {
+ dropdownItem.setActive(
+ Objects.equals(getOrderByCol(), "${field.name}"));
+ dropdownItem.setHref(
+ _getCurrentSortingURL(), "orderByCol", "${field.name}");
+ dropdownItem.setLabel(
+ LanguageUtil.get(request, "${field.name}"));
+ });
+ #if>
+#list>
+// //
+ }
+ };
+ }
+
+ /**
+ * Action Items
+ */
+ @Override
+ public List getActionDropdownItems() {
+ return new DropdownItemList() {
+ {
+
+ // Delete action
+
+ add(
+ dropdownItem -> {
+ dropdownItem.putData("action", "deleteEntries");
+ dropdownItem.setHref(
+ "javascript:" +
+ liferayPortletResponse.getNamespace() +
+ "deleteEntries();");
+
+ boolean trashEnabled = _trashHelper.isTrashEnabled(
+ _themeDisplay.getScopeGroupId());
+
+ dropdownItem.setIcon(
+ trashEnabled ? "trash" : "times-circle");
+
+ String label = "delete";
+
+ if (trashEnabled) {
+ label = "move-to-recycle-bin";
+ }
+
+ dropdownItem.setLabel(LanguageUtil.get(request, label));
+
+ dropdownItem.setQuickAction(true);
+ });
+// //
+<#if exportExcel>
+ // Export Action
+
+ add(
+ dropdownItem -> {
+ dropdownItem.setHref(_getExportResourceURL());
+
+ dropdownItem.setIcon("download");
+
+ dropdownItem.setLabel(
+ LanguageUtil.get(request, "download"));
+
+ dropdownItem.setQuickAction(true);
+ });
+#if>
+// //
+ }
+ };
+ }
+
+ @Override
+ public String getClearResultsURL() {
+ return getSearchActionURL();
+ }
+
+ public Map getComponentContext() throws PortalException {
+ Map context = new HashMap<>();
+
+ String cmd = Constants.DELETE;
+
+ if (_trashHelper.isTrashEnabled(_themeDisplay.getScopeGroup())) {
+ cmd = Constants.MOVE_TO_TRASH;
+ }
+
+ context.put(Constants.CMD, cmd);
+
+ PortletURL deleteEntriesURL = liferayPortletResponse.createActionURL();
+
+ deleteEntriesURL.setParameter(
+ ActionRequest.ACTION_NAME, "/${lowercaseModel}/crud");
+
+ context.put("deleteEntryIds", deleteEntriesURL.toString());
+
+ context.put(
+ "trashEnabled",
+ _trashHelper.isTrashEnabled(_themeDisplay.getScopeGroupId()));
+
+ return context;
+ }
+
+ @Override
+ public CreationMenu getCreationMenu() {
+ if (!${capFirstModel}Permission.contains(
+ _themeDisplay.getPermissionChecker(),
+ _themeDisplay.getScopeGroupId(), ActionKeys.ADD_ENTRY)) {
+
+ return null;
+ }
+
+ return new CreationMenu() {
+ {
+ addDropdownItem(
+ dropdownItem -> {
+ dropdownItem.setHref(
+ liferayPortletResponse.createRenderURL(),
+ Constants.CMD, Constants.ADD,
+ "mvcRenderCommandName", "/${lowercaseModel}/crud",
+ "redirect", currentURLObj.toString());
+ dropdownItem.setLabel(
+ LanguageUtil.get(request, "add-${lowercaseModel}"));
+ });
+ }
+ };
+ }
+
+ /**
+ * Returns the filter menu options.
+ *
+ * @return menu options list
+ */
+ @Override
+ public List getFilterDropdownItems() {
+ return new DropdownItemList() {
+ {
+ addGroup(
+ dropdownGroupItem -> {
+ dropdownGroupItem.setDropdownItems(
+ _getOrderByDropdownItems());
+ dropdownGroupItem.setLabel(
+ LanguageUtil.get(request, "order-by"));
+ });
+ }
+ };
+ }
+
+ public String getOrderByType() {
+ return searchContainer.getOrderByType();
+ }
+
+ @Override
+ public String getSearchActionURL() {
+ PortletURL searchURL = liferayPortletResponse.createRenderURL();
+
+ searchURL.setParameter("mvcRenderCommandName", "/${lowercaseModel}/view");
+
+ String navigation = ParamUtil.getString(
+ request, "navigation", "entries");
+
+ searchURL.setParameter("navigation", navigation);
+
+ searchURL.setParameter("orderByCol", getOrderByCol());
+ searchURL.setParameter("orderByType", getOrderByType());
+
+ return searchURL.toString();
+ }
+
+ @Override
+ public String getSortingURL() {
+ PortletURL sortingURL = _getCurrentSortingURL();
+
+ sortingURL.setParameter(
+ "orderByType",
+ Objects.equals(getOrderByType(), "asc") ? "desc" : "asc");
+
+ return sortingURL.toString();
+ }
+
+ @Override
+ public List getViewTypeItems() {
+ return null;
+
+ // TODO : Configure if you need to switch view type
+
+ // return new ViewTypeItemList(getPortletURL(), getDisplayStyle()) {
+
+ // {
+ // if (ArrayUtil.contains(getDisplayViews(), "icon")) {
+ // addCardViewTypeItem();
+ // }
+ //
+ // if (ArrayUtil.contains(getDisplayViews(), "descriptive")) {
+ // addListViewTypeItem();
+ // }
+ //
+ // if (ArrayUtil.contains(getDisplayViews(), "list")) {
+ // addTableViewTypeItem();
+ // }
+ // }
+ // };
+
+ }
+
+ /**
+ * Export Resource URL
+ *
+ * @return Export resource URL
+ */
+ protected String _getExportResourceURL() {
+ String keywords = ParamUtil.getString(request, DisplayTerms.KEYWORDS);
+
+ ResourceURL exportResourceURL =
+ liferayPortletResponse.createResourceURL(
+ _themeDisplay.getPortletDisplay(
+ ).getId());
+
+ exportResourceURL.setParameter(Constants.CMD, Constants.EXPORT);
+ exportResourceURL.setParameter(DisplayTerms.KEYWORDS, keywords);
+ exportResourceURL.setResourceID("/${lowercaseModel}/export");
+ exportResourceURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_COL_PARAM,
+ searchContainer.getOrderByCol());
+ exportResourceURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM,
+ searchContainer.getOrderByType());
+
+ return exportResourceURL.toString();
+ }
+
+ /**
+ * Search Sort URL
+ *
+ * @return Search filter URL string
+ */
+ private PortletURL _getCurrentSortingURL() {
+ String keywords = ParamUtil.getString(request, DisplayTerms.KEYWORDS);
+ int cur = ParamUtil.getInteger(
+ request, SearchContainer.DEFAULT_CUR_PARAM);
+ int delta = ParamUtil.getInteger(
+ request, SearchContainer.DEFAULT_DELTA_PARAM);
+ String orderByCol = ParamUtil.getString(
+ request, SearchContainer.DEFAULT_ORDER_BY_COL_PARAM, "${lowercaseModel}Id");
+ String orderByType = ParamUtil.getString(
+ request, SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM, "asc");
+
+ PortletURL navigationPortletURL =
+ liferayPortletResponse.createRenderURL();
+
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_CUR_PARAM, String.valueOf(cur));
+ navigationPortletURL.setParameter(
+ "mvcRenderCommandName", "/${lowercaseModel}/view");
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_COL_PARAM, orderByCol);
+ navigationPortletURL.setParameter(
+ SearchContainer.DEFAULT_ORDER_BY_TYPE_PARAM, orderByType);
+
+ if (Validator.isNotNull(keywords)) {
+ navigationPortletURL.setParameter(DisplayTerms.KEYWORDS, keywords);
+ }
+
+ return navigationPortletURL;
+ }
+
+ private final String _displayStyle;
+ private final ThemeDisplay _themeDisplay;
+ private final TrashHelper _trashHelper;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_PanelApp.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_PanelApp.java.ftl
new file mode 100644
index 0000000..b5eb35b
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_PanelApp.java.ftl
@@ -0,0 +1,50 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}PanelApp.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import com.liferay.application.list.BasePanelApp;
+import com.liferay.application.list.PanelApp;
+import com.liferay.application.list.constants.PanelCategoryKeys;
+import com.liferay.portal.kernel.model.Portlet;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * PanelApp
+ *
+ * This class is used to display a portet in the product menu
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "panel.app.order:Integer=100", //TODO : this number determin the order in the panel
+ "panel.category.key=" + PanelCategoryKeys.SITE_ADMINISTRATION_CONTENT
+ },
+ service = PanelApp.class
+)
+public class ${capFirstModel}PanelApp extends BasePanelApp {
+
+ @Override
+ public String getPortletId() {
+ return ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN;
+ }
+
+ @Override
+ @Reference(
+ target = "(javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel}_ADMIN + ")",
+ unbind = "-"
+ )
+ public void setPortlet(Portlet portlet) {
+ super.setPortlet(portlet);
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_Permission.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_Permission.java.ftl
new file mode 100644
index 0000000..a2bedb0
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_Permission.java.ftl
@@ -0,0 +1,44 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/internal/security/permission/resource/${capFirstModel}Permission.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.internal.security.permission.resource;
+
+import com.liferay.portal.kernel.security.permission.PermissionChecker;
+import com.liferay.portal.kernel.security.permission.resource.PortletResourcePermission;
+import ${packageName}.constants.${capFirstModel}Constants;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Permission
+ *
+ * @author ${damascus_author}
+ */
+@Component(immediate = true, service = {})
+public class ${capFirstModel}Permission {
+
+ public static boolean contains(
+ PermissionChecker permissionChecker, long groupId, String actionId) {
+
+ return _portletResourcePermission.contains(
+ permissionChecker, groupId, actionId);
+ }
+
+ @Reference(
+ target = "(resource.name=" + ${capFirstModel}Constants.RESOURCE_NAME + ")",
+ unbind = "-"
+ )
+ protected void setPortletResourcePermission(
+ PortletResourcePermission portletResourcePermission) {
+
+ _portletResourcePermission = portletResourcePermission;
+ }
+
+ private static PortletResourcePermission _portletResourcePermission;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_Portlet.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_Portlet.java.ftl
new file mode 100644
index 0000000..d7ee64c
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_Portlet.java.ftl
@@ -0,0 +1,108 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}Portlet.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import aQute.bnd.annotation.metatype.Configurable;
+
+import com.liferay.asset.constants.AssetWebKeys;
+import com.liferay.asset.util.AssetHelper;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.web.portlet.action.${capFirstModel}Configuration;
+import com.liferay.trash.TrashHelper;
+import com.liferay.trash.util.TrashWebKeys;
+
+import java.io.IOException;
+
+import java.util.Map;
+
+import javax.portlet.Portlet;
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Modified;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Portlet
+ *
+ * @author yasuflatland
+ */
+@Component(
+ configurationPid = ${capFirstModel}PortletKeys.${uppercaseModel}_CONFIG, immediate = true,
+ property = {
+ "com.liferay.portlet.add-default-resource=true",
+ "com.liferay.portlet.application-type=full-page-application",
+ "com.liferay.portlet.application-type=widget",
+ "com.liferay.portlet.css-class-wrapper=portlet-${lowercaseModel}",
+ "com.liferay.portlet.display-category=category.sample",
+ "com.liferay.portlet.header-portlet-css=/${snakecaseModel}/css/main.css",
+ "com.liferay.portlet.layout-cacheable=true",
+ "com.liferay.portlet.preferences-owned-by-group=true",
+ "com.liferay.portlet.private-request-attributes=false",
+ "com.liferay.portlet.private-session-attributes=false",
+ "com.liferay.portlet.render-weight=50",
+ "com.liferay.portlet.scopeable=true",
+ "com.liferay.portlet.struts-path=${lowercaseModel}",
+ "com.liferay.portlet.use-default-template=true",
+ "javax.portlet.display-name=${capFirstModel}",
+ "javax.portlet.init-param.mvc-command-names-default-views=/${lowercaseModel}/view",
+ "javax.portlet.expiration-cache=0",
+ "javax.portlet.init-param.always-display-default-configuration-icons=true",
+ "javax.portlet.init-param.template-path=/META-INF/resources/",
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "javax.portlet.resource-bundle=content.Language",
+ "javax.portlet.security-role-ref=guest,power-user,user"
+ },
+ service = Portlet.class
+)
+public class ${capFirstModel}Portlet extends MVCPortlet {
+
+ @Override
+ public void render(
+ RenderRequest renderRequest, RenderResponse renderResponse)
+ throws IOException, PortletException {
+
+ renderRequest.setAttribute(AssetWebKeys.ASSET_HELPER, _assetHelper);
+ renderRequest.setAttribute(TrashWebKeys.TRASH_HELPER, _trashHelper);
+ renderRequest.setAttribute(
+ ${capFirstModel}Configuration.class.getName(), _${uncapFirstModel}Configuration);
+
+ super.render(renderRequest, renderResponse);
+ }
+
+ @Activate
+ @Modified
+ protected void activate(Map properties) {
+ _${uncapFirstModel}Configuration = Configurable.createConfigurable(
+ ${capFirstModel}Configuration.class, properties);
+ }
+
+ @Override
+ protected void doDispatch(
+ RenderRequest renderRequest, RenderResponse renderResponse)
+ throws IOException, PortletException {
+
+ renderRequest.setAttribute(
+ ${capFirstModel}Configuration.class.getName(), _${uncapFirstModel}Configuration);
+
+ super.doDispatch(renderRequest, renderResponse);
+ }
+
+ @Reference
+ private AssetHelper _assetHelper;
+
+ private volatile ${capFirstModel}Configuration _${uncapFirstModel}Configuration;
+
+ @Reference
+ private TrashHelper _trashHelper;
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_PortletLayoutFinder.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_PortletLayoutFinder.java.ftl
new file mode 100644
index 0000000..3b6738d
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_PortletLayoutFinder.java.ftl
@@ -0,0 +1,33 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}PortletLayoutFinder.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.portal.kernel.portlet.BasePortletLayoutFinder;
+import com.liferay.portal.kernel.portlet.PortletLayoutFinder;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = PortletLayoutFinder.class
+)
+public class ${capFirstModel}PortletLayoutFinder extends BasePortletLayoutFinder {
+
+ @Override
+ protected String[] getPortletIds() {
+ return _PORTLET_IDS;
+ }
+
+ private static final String[] _PORTLET_IDS = {${capFirstModel}PortletKeys.${uppercaseModel}};
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_PortletProvider.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_PortletProvider.java.ftl
new file mode 100644
index 0000000..f63dc3e
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_PortletProvider.java.ftl
@@ -0,0 +1,43 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/${capFirstModel}PortletProvider.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet;
+
+import com.liferay.portal.kernel.portlet.BasePortletProvider;
+import com.liferay.portal.kernel.portlet.EditPortletProvider;
+import com.liferay.portal.kernel.portlet.ManagePortletProvider;
+import com.liferay.portal.kernel.portlet.ViewPortletProvider;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * Portlet Provider
+ *
+ * This class returns Portlet ID for PortletProviderUtil which is used in TrashHandler.
+ * This Portlet ID is used to create a restore URL.
+ *
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = "model.class.name=${packageName}.model.${capFirstModel}",
+ service = {
+ EditPortletProvider.class, ManagePortletProvider.class,
+ ViewPortletProvider.class
+ }
+)
+public class ${capFirstModel}PortletProvider
+ extends BasePortletProvider
+ implements EditPortletProvider, ManagePortletProvider, ViewPortletProvider {
+
+ @Override
+ public String getPortletName() {
+ return ${capFirstModel}PortletKeys.${uppercaseModel};
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_ViewHelper.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ViewHelper.java.ftl
new file mode 100644
index 0000000..d80a6f2
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ViewHelper.java.ftl
@@ -0,0 +1,282 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/util/${capFirstModel}ViewHelper.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.util;
+
+import com.liferay.portal.kernel.dao.search.DisplayTerms;
+import com.liferay.portal.kernel.dao.search.SearchContainer;
+import com.liferay.portal.kernel.dao.search.SearchContainerResults;
+import com.liferay.portal.kernel.search.Document;
+import com.liferay.portal.kernel.search.Field;
+import com.liferay.portal.kernel.search.Hits;
+import com.liferay.portal.kernel.search.Indexer;
+import com.liferay.portal.kernel.search.IndexerRegistryUtil;
+import com.liferay.portal.kernel.search.SearchContext;
+import com.liferay.portal.kernel.search.SearchContextFactory;
+import com.liferay.portal.kernel.search.SearchException;
+import com.liferay.portal.kernel.theme.ThemeDisplay;
+import com.liferay.portal.kernel.util.GetterUtil;
+import com.liferay.portal.kernel.util.OrderByComparator;
+import com.liferay.portal.kernel.util.OrderByComparatorFactoryUtil;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.kernel.util.PortalUtil;
+import com.liferay.portal.kernel.util.WebKeys;
+import ${packageName}.model.${capFirstModel};
+import ${packageName}.service.${capFirstModel}LocalServiceUtil;
+import ${packageName}.web.portlet.action.${capFirstModel}Configuration;
+
+import java.text.ParseException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.PortletPreferences;
+import javax.portlet.PortletRequest;
+
+import org.osgi.service.component.annotations.Component;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * View Helper
+ *
+ * @author ${damascus_author}
+ */
+@Component(immediate = true, service = ${capFirstModel}ViewHelper.class)
+public class ${capFirstModel}ViewHelper {
+
+ /**
+ * Get Data list from Database
+ *
+ * @param request PortletRequest
+ * @param start int
+ * @param end int
+ * @param orderByCol String
+ * @param orderByType String
+ * @return SearchContainerResults<${capFirstModel}>
+ * @throws ParseException
+ */
+ public SearchContainerResults<${capFirstModel}> getListFromDB(
+ PortletRequest request, int start, int end, String orderByCol,
+ String orderByType, int[] state)
+ throws ParseException {
+
+ ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
+ WebKeys.THEME_DISPLAY);
+ PortletPreferences portletPreferences = request.getPreferences();
+
+ // Filter type
+
+ String prefsViewType = portletPreferences.getValue(
+ ${capFirstModel}Configuration.CONF_PREFS_VIEW_TYPE,
+ ${capFirstModel}Configuration.PREFS_VIEW_TYPE_DEFAULT);
+
+ long groupId = themeDisplay.getScopeGroupId();
+ int containerStart = start;
+ int containerEnd = end;
+
+ List<${capFirstModel}> results = new ArrayList<>();
+
+ int total = 0;
+
+ // Get Order
+
+ OrderByComparator<${capFirstModel}> orderByComparator = getOrderByComparator(
+ orderByCol, orderByType);
+
+ if (prefsViewType.equals(
+ ${capFirstModel}Configuration.PREFS_VIEW_TYPE_DEFAULT)) {
+
+ results = ${capFirstModel}LocalServiceUtil.findAllInGroup(
+ groupId, containerStart, containerEnd, orderByComparator,
+ state);
+ total = ${capFirstModel}LocalServiceUtil.countAllInGroup(groupId, state);
+ }
+ else if (prefsViewType.equals(
+ ${capFirstModel}Configuration.PREFS_VIEW_TYPE_USER)) {
+
+ results = ${capFirstModel}LocalServiceUtil.findAllInUser(
+ themeDisplay.getUserId(), containerStart, containerEnd,
+ orderByComparator, state);
+ total = ${capFirstModel}LocalServiceUtil.countAllInUser(
+ themeDisplay.getUserId(), state);
+ }
+ else {
+ results = ${capFirstModel}LocalServiceUtil.findAllInUserAndGroup(
+ themeDisplay.getUserId(), groupId, containerStart, containerEnd,
+ orderByComparator, state);
+ total = ${capFirstModel}LocalServiceUtil.countAllInUserAndGroup(
+ themeDisplay.getUserId(), groupId, state);
+ }
+
+ return new SearchContainerResults<>(results, total);
+ }
+
+ /**
+ * Get Data list from Database
+ *
+ * @param request PortletRequest
+ * @param searchContainer SearchContainer>
+ * @return SearchContainerResults<${capFirstModel}>
+ * @throws ParseException
+ */
+ public SearchContainerResults<${capFirstModel}> getListFromDB(
+ PortletRequest request, SearchContainer> searchContainer,
+ int[] state)
+ throws ParseException {
+
+ return getListFromDB(
+ request, searchContainer.getStart(), searchContainer.getEnd(),
+ searchContainer.getOrderByCol(), searchContainer.getOrderByType(),
+ state);
+ }
+
+ /**
+ * Get Data list from Index
+ *
+ * @param request PortletRequest
+ * @param start int
+ * @param end int
+ * @throws SearchException
+ */
+ public SearchContainerResults<${capFirstModel}> getListFromIndex(
+ PortletRequest request, int start, int end, int state)
+ throws SearchException {
+
+ // Search Key
+
+ String searchFilter = ParamUtil.getString(
+ request, DisplayTerms.KEYWORDS);
+
+ Indexer<${capFirstModel}> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
+ ${capFirstModel}.class);
+
+ SearchContext searchContext = SearchContextFactory.getInstance(
+ PortalUtil.getHttpServletRequest(request));
+
+ // TODO : When WorkflowConstants.STATUS_ANY, this parameter should be set to
+ // display all records in the list
+ // searchContext.setAndSearch(true);
+
+ searchContext.setAttribute(Field.STATUS, state);
+
+ searchContext.setKeywords(searchFilter);
+ searchContext.setStart(start);
+ searchContext.setEnd(end);
+
+ // Search in index
+
+ Hits results = indexer.search(searchContext);
+
+ // Initialize return values
+
+ int total = results.getLength();
+ List<${capFirstModel}> tempResults = new ArrayList<>();
+
+ for (int i = 0; i < results.getDocs().length; i++) {
+ Document doc = results.doc(i);
+
+ ${capFirstModel} resReg = null;
+
+ // Entry
+
+ long entryId = GetterUtil.getLong(doc.get(Field.ENTRY_CLASS_PK));
+
+ try {
+ resReg = ${capFirstModel}LocalServiceUtil.get${capFirstModel}(entryId);
+
+ resReg = resReg.toEscapedModel();
+
+ tempResults.add(resReg);
+ }
+ catch (Exception e) {
+ if (_log.isWarnEnabled()) {
+ _log.warn(
+ "${capFirstModel} search index is stale and contains entry " +
+ entryId);
+ }
+
+ continue;
+ }
+ }
+
+ return new SearchContainerResults<>(tempResults, total);
+ }
+
+ /**
+ * Get Data list from Index
+ *
+ * @param request PortletRequest
+ * @return searchContainer SearchContainer>
+ * @throws SearchException
+ */
+ public SearchContainerResults<${capFirstModel}> getListFromIndex(
+ PortletRequest request, SearchContainer> searchContainer,
+ int state)
+ throws SearchException {
+
+ return getListFromIndex(
+ request, searchContainer.getStart(), searchContainer.getEnd(),
+ state);
+ }
+
+ /**
+ *
+ * Order Comparetor
+ *
+ * @param searchContainer
+ * @return OrderByComparator
+ */
+ public OrderByComparator<${capFirstModel}> getOrderByComparator(
+ SearchContainer> searchContainer) {
+
+ return getOrderByComparator(
+ searchContainer.getOrderByCol(), searchContainer.getOrderByType());
+ }
+
+ /**
+ *
+ * Order Comparetor
+ *
+ * @param orderByCol
+ * @param orderByType
+ * @return OrderByComparator
+ */
+ public OrderByComparator<${capFirstModel}> getOrderByComparator(
+ String orderByCol, String orderByType) {
+
+ if (_log.isDebugEnabled()) {
+ _log.debug(
+ "searchContainer.getOrderByCol()" +
+ (null != orderByCol ? orderByCol : "null"));
+ _log.debug(
+ "searchContainer.getOrderByType()" +
+ (null != orderByType ? orderByType : "null"));
+ }
+
+ return OrderByComparatorFactoryUtil.create(
+ "${capFirstModel}_${capFirstModel}", orderByCol, getOrder(orderByType));
+ }
+
+ /**
+ * Order string to boolean
+ *
+ * @param order
+ * @return if true if order is "asc" or false
+ */
+ protected boolean getOrder(String order) {
+ if ("asc".equalsIgnoreCase(order)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static Logger _log = LoggerFactory.getLogger(${capFirstModel}ViewHelper.class);
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_ViewMVCRenderCommand.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ViewMVCRenderCommand.java.ftl
new file mode 100644
index 0000000..602d8b5
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_ViewMVCRenderCommand.java.ftl
@@ -0,0 +1,97 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/portlet/action/${capFirstModel}ViewMVCRenderCommand.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.portlet.action;
+
+import com.liferay.asset.util.AssetHelper;
+import com.liferay.portal.kernel.portlet.bridges.mvc.MVCRenderCommand;
+import com.liferay.portal.kernel.util.Portal;
+import ${packageName}.constants.${capFirstModel}PortletKeys;
+import ${packageName}.web.constants.${capFirstModel}WebKeys;
+import ${packageName}.web.internal.display.context.${capFirstModel}DisplayContext;
+import ${packageName}.web.util.${capFirstModel}ViewHelper;
+import com.liferay.trash.TrashHelper;
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+import ${packageName}.service.${capFirstValidationModel}LocalService;
+import ${packageName}.web.constants.${capFirstValidationModel}WebKeys;
+ #if>
+#list>
+// //
+
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * @author ${damascus_author}
+ */
+@Component(
+ immediate = true,
+ property = {
+ "javax.portlet.name=" + ${capFirstModel}PortletKeys.${uppercaseModel},
+ "mvc.command.name=/", "mvc.command.name=/${lowercaseModel}/view"
+ },
+ service = MVCRenderCommand.class
+)
+public class ${capFirstModel}ViewMVCRenderCommand implements MVCRenderCommand {
+
+ @Override
+ public String render(RenderRequest request, RenderResponse response)
+ throws PortletException {
+
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_DISPLAY_CONTEXT,
+ new ${capFirstModel}DisplayContext(
+ _portal.getLiferayPortletRequest(request),
+ _portal.getLiferayPortletResponse(response), _trashHelper,
+ _${uncapFirstModel}ViewHelper));
+
+ request.setAttribute(
+ ${capFirstModel}WebKeys.${uppercaseModel}_VIEW_HELPER, _${uncapFirstModel}ViewHelper);
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+ request.setAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE, _${uncapFirstValidationModel}LocalService);
+ #if>
+#list>
+// //
+
+ return ${capFirstModel}WebKeys.VIEW_JSP;
+ }
+
+ @Reference
+ private AssetHelper _assetHelper;
+
+ @Reference
+ private Portal _portal;
+
+ @Reference
+ private ${capFirstModel}ViewHelper _${uncapFirstModel}ViewHelper;
+
+ @Reference
+ private TrashHelper _trashHelper;
+
+//<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ @Reference
+ private ${capFirstValidationModel}LocalService _${uncapFirstValidationModel}LocalService;
+ #if>
+#list>
+// //
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_WebKeys.java.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_WebKeys.java.ftl
new file mode 100644
index 0000000..1ebb844
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_WebKeys.java.ftl
@@ -0,0 +1,48 @@
+//
+// //
+<#include "./license.ftl">
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/java/${packagePath}/web/constants/${capFirstModel}WebKeys.java">
+<#assign skipTemplate = !generateWeb>
+// //
+package ${packageName}.web.constants;
+
+/**
+ * ${capFirstModel} Web Keys
+ *
+ * @author ${damascus_author}
+ */
+public class ${capFirstModel}WebKeys {
+
+ public static final String ADMIN_EDIT_JSP = "/${snakecaseModel}_admin/edit.jsp";
+
+ public static final String ADMIN_VIEW_JSP = "/${snakecaseModel}_admin/view.jsp";
+
+ public static final String ADMIN_VIEW_RECORD_JSP =
+ "/${snakecaseModel}_admin/view_record.jsp";
+
+ public static final String EDIT_JSP = "/${snakecaseModel}/edit.jsp";
+
+ public static final String ${uppercaseModel}_DISPLAY_CONTEXT =
+ "${uppercaseModel}_DISPLAY_CONTEXT";
+
+ public static final String ${uppercaseModel}_ITEM_SELECTOR_HELPER =
+ "${uppercaseModel}_ITEM_SELECTOR_HELPER";
+
+ public static final String ${uppercaseModel}_VIEW_HELPER = "${uppercaseModel}_VIEW_HELPER";
+
+ public static final String VIEW_JSP = "/${snakecaseModel}/view.jsp";
+
+ public static final String VIEW_RECORD_JSP = "/${snakecaseModel}/view_record.jsp";
+
+// //
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+ public static final String ${uppercaseValidationModel}_LOCAL_SERVICE =
+ "${uppercaseValidationModel}_LOCAL_SERVICE";
+ #if>
+#list>
+// //
+
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_abstract.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_abstract.jsp.ftl
new file mode 100644
index 0000000..cd34b59
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_abstract.jsp.ftl
@@ -0,0 +1,15 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/asset/abstract.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="/${snakecaseModel}/init.jsp" %>
+
+
+
+<%-- --%>
+<#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}() %>
+#if>
+<%-- --%>
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_abstract.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_abstract.jsp.ftl
new file mode 100644
index 0000000..c14f55d
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_abstract.jsp.ftl
@@ -0,0 +1,17 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/asset/abstract.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="../init.jsp" %>
+
+
+
+
+
+<%-- --%>
+<#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}() %>
+#if>
+<%-- --%>
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_edit.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_edit.jsp.ftl
new file mode 100644
index 0000000..857f5e2
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_edit.jsp.ftl
@@ -0,0 +1,360 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/edit.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+PortletURL portletURL = PortletURLUtil.clone(renderResponse.createRenderURL(), liferayPortletResponse);
+boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+String CMD = ParamUtil.getString(request, Constants.CMD, Constants.UPDATE);
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})request.getAttribute("${uncapFirstModel}");
+String redirect = ParamUtil.getString(request, "redirect");
+portletDisplay.setShowBackIcon(true);
+portletDisplay.setURLBack(redirect);
+
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<%-- --%>
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+ #if>
+<%-- --%>
+
+ <%
+ String requiredLabel = "";
+ %>
+
+<%-- --%>
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- primary key check -->
+ <#if field.primary?? && field.primary == true >
+ <#continue>
+ #if>
+ <#if field.required?? && field.required == true>
+ <%
+ requiredLabel = "*";
+ %>
+
+ <#else>
+ <%
+ requiredLabel = "";
+ %>
+ #if>
+
+ <#-- ---------------- -->
+ <#-- Long -->
+ <#-- Varchar -->
+ <#-- Date -->
+ <#-- DateTime -->
+ <#-- Boolean -->
+ <#-- Double -->
+ <#-- Integer -->
+ <#-- Text -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Double" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text"
+ >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+
+ <#assign fieldName = "PrimaryKey">
+ <#if field.validation.fieldName??>
+ <#assign fieldName = "${field.validation.fieldName?cap_first}">
+ #if>
+
+ <#assign orderByField = "PrimaryKey">
+ <#if field.validation.orderByField??>
+ <#assign orderByField = "${field.validation.orderByField?uncap_first}">
+ #if>
+ <%
+ ${capFirstValidationModel}ViewHelper ${uncapFirstValidationModel}ViewHelper = (${capFirstValidationModel}ViewHelper) request
+ .getAttribute(${capFirstValidationModel}WebKeys.${uppercaseValidationModel}_VIEW_HELPER);
+
+ SearchContainerResults<${capFirstValidationModel}> ${uncapFirstValidationModel}Results = ${uncapFirstValidationModel}ViewHelper.getListFromDB(
+ renderRequest, -1, -1, "${orderByField?uncap_first}", "asc", new int[] {WorkflowConstants.STATUS_APPROVED});
+ %>
+
+
+
+ <%=LanguageUtil.get(request, "please-select") %>
+ <% for(${capFirstValidationModel} ${uncapFirstValidationModel} : ${uncapFirstValidationModel}Results.getResults()) { %>
+ <%=${uncapFirstValidationModel}.get${orderByField?cap_first}() %>
+ <% } %>
+
+
+ <#else>
+
+ #if>
+ #if>
+ <#-- ---------------- -->
+ <#-- Document Library -->
+ <#-- ---------------- -->
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+
+ <%
+ String ${field.name}Click = renderResponse.getNamespace() + "dlBrowse('${field.name} Files select','" +
+ renderResponse.getNamespace()+"${field.name}')";
+ %>
+
+
+ #if>
+ <#-- ---------------- -->
+ <#-- RichText -->
+ <#-- ---------------- -->
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ ">
+
+
+
+ #if>
+ #list>
+<%-- --%>
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+
+
+
+
+
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0 && false == fromAsset) {
+ %>
+
+
+
+
+
+
+
+ <%
+ }
+ %>
+
+
+
+ <%
+ String publishButtonLabel = "submit";
+ %>
+
+ <%
+ if (WorkflowDefinitionLinkLocalServiceUtil
+ .hasWorkflowDefinitionLink(themeDisplay.getCompanyId(), scopeGroupId, ${capFirstModel}.class.getName())) {
+
+ publishButtonLabel = "submit-for-publication";
+ }
+ %>
+
+
+
+ <%
+ if (!fromAsset) {
+ %>
+
+ − −
+
+
+ <%
+ }
+ %>
+
+
+
+
+
+
+
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0 && false == fromAsset) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+
+ function init${field.name}Editor() {
+ return '<%=UnicodeFormatter.toString(${uncapFirstModel}.get${field.name?cap_first}())%>';
+ }
+
+ #if>
+#list>
+<%-- --%>
+
+
+ function saveEditors() {
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ document. ${lowercaseModel}Edit. ${field.name}.value =
+ window. ${field.name}Editor.getHTML();
+ #if>
+#list>
+<%-- --%>
+ submitForm(document. ${lowercaseModel}Edit);
+ }
+
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+<%
+${capFirstModel}ItemSelectorHelper ${uncapFirstModel}ItemSelectorHelper = (${capFirstModel}ItemSelectorHelper)request
+ .getAttribute(${capFirstModel}WebKeys.${uppercaseModel}_ITEM_SELECTOR_HELPER);
+RequestBackedPortletURLFactory requestBackedPortletURLFactory = RequestBackedPortletURLFactoryUtil
+ .create(liferayPortletRequest);
+String selectItemName = liferayPortletResponse.getNamespace()
+ + "selectItem";
+%>
+
+
+ function dlBrowse (title, inputField) {
+ var itemSrc = $('#'+inputField);
+ AUI().use(
+ 'liferay-item-selector-dialog',
+ function(A) {
+ var itemSelectorDialog = new A.LiferayItemSelectorDialog(
+ {
+ eventName: '<%= selectItemName %>',
+ on: {
+ selectedItemChange: function(event) {
+ var selectedItem = event.newVal;
+
+ if (selectedItem) {
+ var itemValue = JSON.parse(
+ selectedItem.value
+ );
+ itemSrc.val(itemValue.url);
+ }
+ }
+ },
+ title: title,
+ url: '<%= ${uncapFirstModel}ItemSelectorHelper.getItemSelectorURL(
+ requestBackedPortletURLFactory, themeDisplay, selectItemName) %>'
+ }
+ );
+ itemSelectorDialog.open();
+ }
+ );
+ }
+
+ <#break>
+ #if>
+#list>
+<%-- --%>
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_edit_actions.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_edit_actions.jsp.ftl
new file mode 100644
index 0000000..4ae946b
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_edit_actions.jsp.ftl
@@ -0,0 +1,99 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/edit_actions.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+PortletURL navigationPortletURL = renderResponse.createRenderURL();
+PortletURL portletURL = PortletURLUtil.clone(navigationPortletURL, liferayPortletResponse);
+
+ResultRow row = (ResultRow)request.getAttribute(WebKeys.SEARCH_CONTAINER_RESULT_ROW);
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})row.getObject();
+
+long groupId = ${uncapFirstModel}.getGroupId();
+String name = ${capFirstModel}.class.getName();
+String primKey = String.valueOf(${uncapFirstModel}.getPrimaryKey());
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_full_content.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_full_content.jsp.ftl
new file mode 100644
index 0000000..04f3112
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_full_content.jsp.ftl
@@ -0,0 +1,18 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/asset/full_content.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+
+<%@ include file="../init.jsp" %>
+
+
+
+
+
+<%-- --%>
+<#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}()
+#if>
+<%-- --%>
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_init.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_init.jsp.ftl
new file mode 100644
index 0000000..b9ed51a
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_init.jsp.ftl
@@ -0,0 +1,92 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/init.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
+
+<%@ taglib uri="http://liferay.com/tld/asset" prefix="liferay-asset" %><%@
+taglib uri="http://liferay.com/tld/aui" prefix="aui" %><%@
+taglib uri="http://liferay.com/tld/clay" prefix="clay" %><%@
+taglib uri="http://liferay.com/tld/comment" prefix="liferay-comment" %><%@
+taglib uri="http://liferay.com/tld/frontend" prefix="liferay-frontend" %><%@
+taglib uri="http://liferay.com/tld/item-selector" prefix="liferay-item-selector" %><%@
+taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %><%@
+taglib uri="http://liferay.com/tld/security" prefix="liferay-security" %><%@
+taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %><%@
+taglib uri="http://liferay.com/tld/trash" prefix="liferay-trash" %><%@
+taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %><%@
+taglib uri="http://liferay.com/tld/util" prefix="liferay-util" %>
+
+<%@ page import="com.liferay.asset.constants.AssetWebKeys" %><%@
+page import="com.liferay.asset.util.AssetHelper" %><%@
+page import="com.liferay.portal.kernel.dao.search.*" %><%@
+page import="com.liferay.portal.kernel.language.*" %><%@
+page import="com.liferay.portal.kernel.portlet.*" %><%@
+page import="com.liferay.portal.kernel.security.permission.ActionKeys" %><%@
+page import="com.liferay.portal.kernel.service.WorkflowDefinitionLinkLocalServiceUtil" %><%@
+page import="com.liferay.portal.kernel.util.*" %><%@
+page import="com.liferay.portal.kernel.workflow.*" %><%@
+page import="com.liferay.frontend.taglib.clay.servlet.taglib.util.JSPNavigationItemList" %><%@
+page import="${packageName}.model.${capFirstModel}" %><%@
+page import="${packageName}.web.constants.*" %><%@
+page import="${packageName}.web.constants.${capFirstModel}WebKeys" %><%@
+page import="${packageName}.web.internal.display.context.*" %><%@
+page import="${packageName}.web.internal.security.permission.resource.*" %><%@
+page import="${packageName}.web.portlet.action.${capFirstModel}Configuration" %><%@
+page import="${packageName}.web.upload.${capFirstModel}ItemSelectorHelper" %><%@
+page import="com.liferay.trash.TrashHelper" %><%@
+page import="com.liferay.trash.util.TrashWebKeys" %><%@
+page import="com.liferay.petra.string.StringPool" %>
+
+<%@ page import="javax.portlet.PortletPreferences" %>
+<%@ page import="java.text.SimpleDateFormat" %>
+<%@ page import="java.util.ArrayList" %>
+<%@ page import="java.util.Calendar"%>
+<%@ page import="java.util.Date" %>
+<%@ page import="java.util.List" %>
+<%@ page import="java.util.Map"%>
+
+<%@ page import="javax.portlet.PortletURL" %>
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+<%@page import="${packageName}.model.${field.validation.className}"%>
+<%@page import="${packageName}.web.constants.${field.validation.className}WebKeys"%>
+<%@page import="${packageName}.web.util.${field.validation.className}ViewHelper"%>
+<%@page import="${packageName}.service.${field.validation.className}LocalService"%>
+ #if>
+#list>
+<%-- --%>
+
+
+
+
+
+<%
+AssetHelper assetHelper = (AssetHelper)request.getAttribute(AssetWebKeys.ASSET_HELPER);
+TrashHelper trashHelper = (TrashHelper)request.getAttribute(TrashWebKeys.TRASH_HELPER);
+
+${capFirstModel}Configuration ${uncapFirstModel}Configuration =
+(${capFirstModel}Configuration)
+ renderRequest.getAttribute(${capFirstModel}Configuration.class.getName());
+
+String prefsViewType = StringPool.BLANK;
+String dateFormatVal = StringPool.BLANK;
+String datetimeFormatVal = StringPool.BLANK;
+String datePickerFormatVal = StringPool.BLANK;
+
+if (Validator.isNotNull(${uncapFirstModel}Configuration)) {
+prefsViewType = HtmlUtil.escape(portletPreferences.getValue("prefsViewType", String.valueOf(${uncapFirstModel}Configuration.prefsViewType())));
+
+dateFormatVal = HtmlUtil.escape(portletPreferences.getValue("dateFormat", ${uncapFirstModel}Configuration.dateFormat()));
+
+datetimeFormatVal = HtmlUtil.escape(portletPreferences.getValue("datetimeFormat", ${uncapFirstModel}Configuration.datetimeFormat()));
+
+datePickerFormatVal = HtmlUtil.escape(portletPreferences.getValue("datePickerFormat", ${uncapFirstModel}Configuration.datePickerFormat()));
+}
+%>
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_main.css.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_main.css.ftl
new file mode 100644
index 0000000..b14a30d
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_main.css.ftl
@@ -0,0 +1,6 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/css/main.css">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_view.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_view.jsp.ftl
new file mode 100644
index 0000000..d1bd56b
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_view.jsp.ftl
@@ -0,0 +1,216 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/view.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+String iconChecked = "checked";
+String iconUnchecked = "unchecked";
+SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatVal);
+SimpleDateFormat dateTimeFormat = new SimpleDateFormat(datetimeFormatVal);
+
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+${capFirstValidationModel}LocalService ${uncapFirstValidationModel}LocalService = (${capFirstValidationModel}LocalService) request
+.getAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE);
+ #if>
+#list>
+
+${capFirstModel}DisplayContext ${uncapFirstModel}DisplayContext = (${capFirstModel}DisplayContext)request.getAttribute(${capFirstModel}WebKeys.${uppercaseModel}_DISPLAY_CONTEXT);
+
+String displayStyle = ${uncapFirstModel}DisplayContext.getDisplayStyle();
+SearchContainer entriesSearchContainer = ${uncapFirstModel}DisplayContext.getSearchContainer();
+
+PortletURL portletURL = entriesSearchContainer.getIteratorURL();
+
+${capFirstModel}ManagementToolbarDisplayContext ${uncapFirstModel}ManagementToolbarDisplayContext = new ${capFirstModel}ManagementToolbarDisplayContext(liferayPortletRequest, liferayPortletResponse, request, entriesSearchContainer, trashHelper, displayStyle);
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<%-- --%>
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- ---------------- -->
+ <#-- Long -->
+ <#-- Varchar -->
+ <#-- Boolean -->
+ <#-- Double -->
+ <#-- Document Library -->
+ <#-- Integer -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Double" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer"
+ >
+
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+
+ <#assign fieldName = "PrimaryKey">
+ <#if field.validation.fieldName??>
+ <#assign fieldName = "${field.validation.fieldName?cap_first}">
+ #if>
+
+ <#assign orderByField = "PrimaryKey">
+ <#if field.validation.orderByField??>
+ <#assign orderByField = "${field.validation.orderByField?cap_first}">
+ #if>
+ <%
+ String ${field.name}Text = "";
+ try {
+ ${capFirstValidationModel} ${uncapFirstValidationModel} = ${uncapFirstValidationModel}LocalService.get${capFirstValidationModel}(GetterUtil.getLong(${uncapFirstModel}.get${field.name?cap_first}()));
+ ${field.name}Text = ${uncapFirstValidationModel}.get${orderByField}();
+ } catch(Exception e) {}
+ %>
+
+ <#else>
+
+ #if>
+ #if>
+ <#-- ---------------- -->
+ <#-- Date -->
+ <#-- DateTime -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime"
+ >
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- RichText -->
+ <#-- Text -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.RichText" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text"
+ >
+
+ <%
+ String ${field.name}Icon = iconUnchecked;
+ String ${field.name} = ${uncapFirstModel}.get${field.name?cap_first}();
+ if (!${field.name}.equals("")) {
+ ${field.name}Icon= iconChecked;
+ }
+ %>
+
+
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+<%-- --%>
+
+
+
+
+
+
+
+
+
+
+ function deleteEntries() {
+ if (<%=trashHelper.isTrashEnabled(scopeGroupId) %> || confirm('<%=UnicodeLanguageUtil.get(request, "are-you-sure-you-want-to-delete-the-selected-entries") %>')) {
+ var form = AUI.$(document. fm);
+
+ form.attr('method', 'post');
+ form.fm('<%=Constants.CMD%>').val('<%=trashHelper.isTrashEnabled(scopeGroupId) ? Constants.MOVE_TO_TRASH : Constants.DELETE%>');
+ form.fm('deleteEntryIds').val(Liferay.Util.listCheckedExcept(form, ' allRowIds'));
+
+ submitForm(form, ' ');
+ }
+ }
+
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_view_record.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_view_record.jsp.ftl
new file mode 100644
index 0000000..2666fd2
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_admin_view_record.jsp.ftl
@@ -0,0 +1,91 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}_admin/view_record.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})request.getAttribute("${uncapFirstModel}");
+String redirect = ParamUtil.getString(request, "redirect");
+boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+portletDisplay.setShowBackIcon(true);
+portletDisplay.setURLBack(redirect);
+
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+${capFirstValidationModel}LocalService ${uncapFirstValidationModel}LocalService = (${capFirstValidationModel}LocalService) request
+.getAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE);
+ #if>
+#list>
+%>
+
+
+
+
+
+
+<%-- --%>
+
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop end -->
+ <#-- ---------------- -->
+<%-- --%>
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_bnd.bnd.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_bnd.bnd.ftl
new file mode 100644
index 0000000..8127acf
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_bnd.bnd.ftl
@@ -0,0 +1,26 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/bnd.bnd">
+<#assign skipTemplate = !generateWeb>
+# #
+Bundle-Name: ${dashcaseProjectName}-web
+Bundle-SymbolicName: ${packageName}.web
+Bundle-Version: 1.0.0
+Import-Package:\
+ !com.google.*,\
+ !com.graphbuilder.*,\
+ !com.microsoft.*,\
+ !org.apache.*,\
+ !org.bouncycastle.*,\
+ !org.etsi.uri.*,\
+ !org.openxmlformats.*,\
+ !com.zaxxer.*,\
+ *
+Web-ContextPath: /${dashcaseProjectName}-web
+-dsannotations-options: inherit
+-includeresource:\
+ @poi-*.jar,\
+ @poi-ooxml-*.jar,\
+ @poi-ooxml-schemas-*.jar
+-metatype: *
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_build.gradle.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_build.gradle.ftl
new file mode 100644
index 0000000..92e86ef
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_build.gradle.ftl
@@ -0,0 +1,53 @@
+//
+// //
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/build.gradle">
+<#assign skipTemplate = !generateWeb>
+// //
+apply plugin: 'java'
+apply plugin: 'groovy'
+apply plugin: 'idea'
+apply plugin: 'eclipse'
+
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
+
+//Need for Windows
+def defaultEncoding = 'UTF-8'
+
+dependencies {
+ compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.5.0"
+ compile group: "org.apache.poi", name: "poi"<#if useTP?? && false == useTP>, version: "4.1.2"#if>
+ compile group: "org.apache.poi", name: "poi-ooxml"<#if useTP?? && false == useTP>, version: "4.1.2"#if>
+ compile group: "org.apache.poi", name: "poi-ooxml-schemas"<#if useTP?? && false == useTP>, version: "4.1.2"#if>
+
+ compileOnly group: "com.liferay", name: "com.liferay.application.list.api"<#if useTP?? && false == useTP>, version: "5.1.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.api"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.api"<#if useTP?? && false == useTP>, version: "6.3.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.display.page.item.selector.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.info.display.api"<#if useTP?? && false == useTP>, version: "3.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.asset.taglib"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.comment.taglib"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.clay"<#if useTP?? && false == useTP>, version: "3.5.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.soy"<#if useTP?? && false == useTP>, version: "4.0.0"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib.util"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.info.api"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.api"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.criteria.api"<#if useTP?? && false == useTP>, version: "5.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.item.selector.taglib"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.reflect"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.string"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.petra.function"<#if useTP?? && false == useTP>, version: "4.0.+"#if>
+ compileOnly group: "com.liferay", name: "com.liferay.trash.api"<#if useTP?? && false == useTP>, version: "3.0.+"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"<#if useTP?? && false == useTP>, version: "7.2.0"#if>
+ compileOnly group: "com.liferay.portal", name: "com.liferay.util.taglib"<#if useTP?? && false == useTP>, version: "5.1.0"#if>
+ compileOnly group: "javax.portlet", name: "portlet-api"<#if useTP?? && false == useTP>, version: "3.0.1"#if>
+ compileOnly group: "javax.servlet.jsp", name: "jsp-api"<#if useTP?? && false == useTP>, version: "2.1"#if>
+ compileOnly group: "jstl", name: "jstl"<#if useTP?? && false == useTP>, version: "1.2"#if>
+ compileOnly group: "org.apache.felix", name: "org.apache.felix.http.servlet-api", version: "1.1.+"
+ compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
+ compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.+'
+ compileOnly project(":${dashcaseProjectName}-api")
+ compileOnly project(":${dashcaseProjectName}-service")
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_configuration.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_configuration.jsp.ftl
new file mode 100644
index 0000000..78094b8
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_configuration.jsp.ftl
@@ -0,0 +1,47 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/configuration.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+<%@ page contentType="text/html; charset=UTF-8" %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_default.xml.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_default.xml.ftl
new file mode 100644
index 0000000..ad745b0
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_default.xml.ftl
@@ -0,0 +1,74 @@
+
+
+
+
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/resource-actions/default.xml">
+<#assign skipTemplate = !generateWeb>
+
+
+
+<#list damascus.applications as app >
+
+ ${packageSnake}_web_${app.model?cap_first}Portlet
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ PERMISSIONS
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ VIEW
+
+
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ PERMISSIONS
+
+
+
+
+ ${packageSnake}_web_${app.model?cap_first}AdminPortlet
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ PERMISSIONS
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ VIEW
+
+
+ VIEW
+
+
+ ACCESS_IN_CONTROL_PANEL
+ ADD_TO_PAGE
+ CONFIGURATION
+ ADD_ENTRY
+ PERMISSIONS
+
+
+
+#list>
+
+
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_edit.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_edit.jsp.ftl
new file mode 100644
index 0000000..0334fa6
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_edit.jsp.ftl
@@ -0,0 +1,370 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/edit.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+ PortletURL portletURL = PortletURLUtil.clone(renderResponse.createRenderURL(), liferayPortletResponse);
+ boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+ String CMD = ParamUtil.getString(request, Constants.CMD, Constants.UPDATE);
+ ${capFirstModel} ${uncapFirstModel} = (${capFirstModel})request.getAttribute("${uncapFirstModel}");
+ String redirect = ParamUtil.getString(request, "redirect");
+ portletDisplay.setShowBackIcon(true);
+ portletDisplay.setURLBack(redirect);
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <%
+
+ //This tag is only necessary in Asset publisher
+
+ if (fromAsset) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+
+
+<%--
--%>
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+ #if>
+<%-- --%>
+
+ <%
+ String requiredLabel = "";
+ %>
+<%--
--%>
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- primary key check -->
+ <#if field.primary?? && field.primary == true >
+ <#continue>
+ #if>
+ <#if field.required?? && field.required == true>
+ <%
+ requiredLabel = "*";
+ %>
+
+ <#else>
+ <%
+ requiredLabel = "";
+ %>
+ #if>
+
+ <#-- ---------------- -->
+ <#-- Long -->
+ <#-- Varchar -->
+ <#-- Date -->
+ <#-- DateTime -->
+ <#-- Boolean -->
+ <#-- Double -->
+ <#-- Integer -->
+ <#-- Text -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Double" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text"
+ >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+
+ <#assign fieldName = "PrimaryKey">
+ <#if field.validation.fieldName??>
+ <#assign fieldName = "${field.validation.fieldName?cap_first}">
+ #if>
+
+ <#assign orderByField = "PrimaryKey">
+ <#if field.validation.orderByField??>
+ <#assign orderByField = "${field.validation.orderByField?uncap_first}">
+ #if>
+ <%
+ ${capFirstValidationModel}ViewHelper ${uncapFirstValidationModel}ViewHelper = (${capFirstValidationModel}ViewHelper) request
+ .getAttribute(${capFirstValidationModel}WebKeys.${uppercaseValidationModel}_VIEW_HELPER);
+
+ SearchContainerResults<${capFirstValidationModel}> ${uncapFirstValidationModel}Results = ${uncapFirstValidationModel}ViewHelper.getListFromDB(
+ renderRequest, -1, -1, "${orderByField?uncap_first}", "asc", new int[] {WorkflowConstants.STATUS_APPROVED});
+ %>
+
+
+
+ <%=LanguageUtil.get(request, "please-select") %>
+ <% for(${capFirstValidationModel} ${uncapFirstValidationModel} : ${uncapFirstValidationModel}Results.getResults()) { %>
+ <%=${uncapFirstValidationModel}.get${orderByField?cap_first}() %>
+ <% } %>
+
+
+ <#else>
+
+ #if>
+ #if>
+ <#-- ---------------- -->
+ <#-- Document Library -->
+ <#-- ---------------- -->
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+
+ <%
+ String ${field.name}Click = renderResponse.getNamespace() + "dlBrowse('${field.name} Files select','" +
+ renderResponse.getNamespace()+"${field.name}')";
+ %>
+
+
+ #if>
+ <#-- ---------------- -->
+ <#-- RichText -->
+ <#-- ---------------- -->
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ ">
+
+
+
+ #if>
+ #list>
+<%-- --%>
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+
+
+
+
+
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0 && false == fromAsset) {
+ %>
+
+
+
+
+
+
+
+ <%
+ }
+ %>
+
+ <%
+
+ //This tag is only necessary in Asset publisher
+
+ if (fromAsset) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+ <%
+ String publishButtonLabel = "submit";
+ %>
+
+ <%
+ if (WorkflowDefinitionLinkLocalServiceUtil
+ .hasWorkflowDefinitionLink(themeDisplay.getCompanyId(), scopeGroupId, ${capFirstModel}.class.getName())) {
+
+ publishButtonLabel = "submit-for-publication";
+ }
+ %>
+
+
+
+ <%
+ if (!fromAsset) {
+ %>
+
+ − −
+
+
+ <%
+ }
+ %>
+
+
+
+
+ <%
+ if (${uncapFirstModel}.getPrimaryKey() != 0 && false == fromAsset) {
+ %>
+
+
+
+ <%
+ }
+ %>
+
+
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+
+ function init${field.name}Editor() {
+ return '<%=UnicodeFormatter.toString(${uncapFirstModel}.get${field.name?cap_first}())%>';
+ }
+
+ #if>
+#list>
+<%-- --%>
+
+
+ function saveEditors() {
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.RichText" >
+ document. ${lowercaseModel}Edit. ${field.name}.value =
+ window. ${field.name}Editor.getHTML();
+ #if>
+#list>
+<%-- --%>
+ submitForm(document. ${lowercaseModel}Edit);
+ }
+
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" >
+<%
+${capFirstModel}ItemSelectorHelper ${uncapFirstModel}ItemSelectorHelper = (${capFirstModel}ItemSelectorHelper)request
+ .getAttribute(${capFirstModel}WebKeys.${uppercaseModel}_ITEM_SELECTOR_HELPER);
+RequestBackedPortletURLFactory requestBackedPortletURLFactory = RequestBackedPortletURLFactoryUtil
+ .create(liferayPortletRequest);
+String selectItemName = liferayPortletResponse.getNamespace()
+ + "selectItem";
+%>
+
+
+ function dlBrowse (title, inputField) {
+ var itemSrc = $('#'+inputField);
+ AUI().use(
+ 'liferay-item-selector-dialog',
+ function(A) {
+ var itemSelectorDialog = new A.LiferayItemSelectorDialog(
+ {
+ eventName: '<%= selectItemName %>',
+ on: {
+ selectedItemChange: function(event) {
+ var selectedItem = event.newVal;
+
+ if (selectedItem) {
+ var itemValue = JSON.parse(
+ selectedItem.value
+ );
+ itemSrc.val(itemValue.url);
+ }
+ }
+ },
+ title: title,
+ url: '<%= ${uncapFirstModel}ItemSelectorHelper.getItemSelectorURL(
+ requestBackedPortletURLFactory, themeDisplay, selectItemName) %>'
+ }
+ );
+ itemSelectorDialog.open();
+ }
+ );
+ }
+
+ <#break>
+ #if>
+#list>
+<%-- --%>
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_edit_actions.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_edit_actions.jsp.ftl
new file mode 100644
index 0000000..97bb94d
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_edit_actions.jsp.ftl
@@ -0,0 +1,99 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/edit_actions.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+PortletURL navigationPortletURL = renderResponse.createRenderURL();
+PortletURL portletURL = PortletURLUtil.clone(navigationPortletURL, liferayPortletResponse);
+
+ResultRow row = (ResultRow)request.getAttribute(WebKeys.SEARCH_CONTAINER_RESULT_ROW);
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})row.getObject();
+
+long groupId = ${uncapFirstModel}.getGroupId();
+String name = ${capFirstModel}.class.getName();
+String primKey = String.valueOf(${uncapFirstModel}.getPrimaryKey());
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_full_content.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_full_content.jsp.ftl
new file mode 100644
index 0000000..d074b86
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_full_content.jsp.ftl
@@ -0,0 +1,15 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/asset/full_content.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="/${snakecaseModel}/init.jsp" %>
+
+
+
+<%-- --%>
+<#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}()
+#if>
+<%-- --%>
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_init.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_init.jsp.ftl
new file mode 100644
index 0000000..953f36f
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_init.jsp.ftl
@@ -0,0 +1,91 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/init.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
+
+<%@ taglib uri="http://liferay.com/tld/asset" prefix="liferay-asset" %><%@
+taglib uri="http://liferay.com/tld/aui" prefix="aui" %><%@
+taglib uri="http://liferay.com/tld/clay" prefix="clay" %><%@
+taglib uri="http://liferay.com/tld/comment" prefix="liferay-comment" %><%@
+taglib uri="http://liferay.com/tld/frontend" prefix="liferay-frontend" %><%@
+taglib uri="http://liferay.com/tld/item-selector" prefix="liferay-item-selector" %><%@
+taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %><%@
+taglib uri="http://liferay.com/tld/security" prefix="liferay-security" %><%@
+taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %><%@
+taglib uri="http://liferay.com/tld/trash" prefix="liferay-trash" %><%@
+taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %><%@
+taglib uri="http://liferay.com/tld/util" prefix="liferay-util" %>
+
+<%@ page import="com.liferay.asset.constants.AssetWebKeys" %><%@
+page import="com.liferay.asset.util.AssetHelper" %><%@
+page import="com.liferay.portal.kernel.dao.search.*" %><%@
+page import="com.liferay.portal.kernel.language.*" %><%@
+page import="com.liferay.portal.kernel.portlet.*" %><%@
+page import="com.liferay.portal.kernel.security.permission.ActionKeys" %><%@
+page import="com.liferay.portal.kernel.service.WorkflowDefinitionLinkLocalServiceUtil" %><%@
+page import="com.liferay.portal.kernel.util.*" %><%@
+page import="com.liferay.portal.kernel.workflow.*" %><%@
+page import="${packageName}.model.${capFirstModel}" %><%@
+page import="${packageName}.web.constants.*" %><%@
+page import="${packageName}.web.constants.${capFirstModel}WebKeys" %><%@
+page import="${packageName}.web.internal.display.context.*" %><%@
+page import="${packageName}.web.internal.security.permission.resource.*" %><%@
+page import="${packageName}.web.portlet.action.${capFirstModel}Configuration" %><%@
+page import="${packageName}.web.upload.${capFirstModel}ItemSelectorHelper" %><%@
+page import="com.liferay.trash.TrashHelper" %><%@
+page import="com.liferay.trash.util.TrashWebKeys" %><%@
+page import="com.liferay.petra.string.StringPool" %>
+
+<%@ page import="javax.portlet.PortletPreferences" %>
+<%@ page import="java.text.SimpleDateFormat" %>
+<%@ page import="java.util.ArrayList" %>
+<%@ page import="java.util.Calendar"%>
+<%@ page import="java.util.Date" %>
+<%@ page import="java.util.List" %>
+<%@ page import="java.util.Map"%>
+
+<%@ page import="javax.portlet.PortletURL" %>
+
+<%-- --%>
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+<%@page import="${packageName}.model.${field.validation.className}"%>
+<%@page import="${packageName}.web.constants.${field.validation.className}WebKeys"%>
+<%@page import="${packageName}.web.util.${field.validation.className}ViewHelper"%>
+<%@page import="${packageName}.service.${field.validation.className}LocalService"%>
+ #if>
+#list>
+<%-- --%>
+
+
+
+
+
+<%
+AssetHelper assetHelper = (AssetHelper)request.getAttribute(AssetWebKeys.ASSET_HELPER);
+TrashHelper trashHelper = (TrashHelper)request.getAttribute(TrashWebKeys.TRASH_HELPER);
+
+${capFirstModel}Configuration ${uncapFirstModel}Configuration =
+(${capFirstModel}Configuration)
+ renderRequest.getAttribute(${capFirstModel}Configuration.class.getName());
+
+String prefsViewType = StringPool.BLANK;
+String dateFormatVal = StringPool.BLANK;
+String datetimeFormatVal = StringPool.BLANK;
+String datePickerFormatVal = StringPool.BLANK;
+
+if (Validator.isNotNull(${uncapFirstModel}Configuration)) {
+prefsViewType = HtmlUtil.escape(portletPreferences.getValue("prefsViewType", String.valueOf(${uncapFirstModel}Configuration.prefsViewType())));
+
+dateFormatVal = HtmlUtil.escape(portletPreferences.getValue("dateFormat", ${uncapFirstModel}Configuration.dateFormat()));
+
+datetimeFormatVal = HtmlUtil.escape(portletPreferences.getValue("datetimeFormat", ${uncapFirstModel}Configuration.datetimeFormat()));
+
+datePickerFormatVal = HtmlUtil.escape(portletPreferences.getValue("datePickerFormat", ${uncapFirstModel}Configuration.datePickerFormat()));
+}
+%>
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_main.css.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_main.css.ftl
new file mode 100644
index 0000000..06c9573
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_main.css.ftl
@@ -0,0 +1,6 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/css/main.css">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_portlet.properties.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_portlet.properties.ftl
new file mode 100644
index 0000000..6392dac
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_portlet.properties.ftl
@@ -0,0 +1,15 @@
+#
+# #
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/portlet.properties">
+<#assign skipTemplate = !generateWeb>
+# #
+include-and-override=portlet-ext.properties
+
+language.bundle=content.Language
+
+#
+# Input a list of comma delimited resource action configurations that will be
+# read from the class path.
+#
+resource.actions.configs=resource-actions/default.xml
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_preview.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_preview.jsp.ftl
new file mode 100644
index 0000000..34a96ee
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_preview.jsp.ftl
@@ -0,0 +1,11 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/asset/preview.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="/${snakecaseModel}/init.jsp" %>
+
+
+
+<%= ${uncapFirstModel}.get${application.asset.assetTitleFieldName?cap_first}() %>
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_routes.xml.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_routes.xml.ftl
new file mode 100644
index 0000000..21fcd51
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_routes.xml.ftl
@@ -0,0 +1,54 @@
+
+
+
+
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/friendly-url-routes/routes.xml">
+<#assign skipTemplate = !generateWeb>
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_view.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_view.jsp.ftl
new file mode 100644
index 0000000..81bc20c
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_view.jsp.ftl
@@ -0,0 +1,196 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/view.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+String iconChecked = "checked";
+String iconUnchecked = "unchecked";
+SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatVal);
+SimpleDateFormat dateTimeFormat = new SimpleDateFormat(datetimeFormatVal);
+
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+${capFirstValidationModel}LocalService ${uncapFirstValidationModel}LocalService = (${capFirstValidationModel}LocalService) request
+.getAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE);
+ #if>
+#list>
+
+${capFirstModel}DisplayContext ${uncapFirstModel}DisplayContext = (${capFirstModel}DisplayContext)request.getAttribute(${capFirstModel}WebKeys.${uppercaseModel}_DISPLAY_CONTEXT);
+
+String displayStyle = ${uncapFirstModel}DisplayContext.getDisplayStyle();
+SearchContainer entriesSearchContainer = ${uncapFirstModel}DisplayContext.getSearchContainer();
+
+PortletURL portletURL = entriesSearchContainer.getIteratorURL();
+
+${capFirstModel}ManagementToolbarDisplayContext ${uncapFirstModel}ManagementToolbarDisplayContext = new ${capFirstModel}ManagementToolbarDisplayContext(liferayPortletRequest, liferayPortletResponse, request, entriesSearchContainer, trashHelper, displayStyle);
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<%-- --%>
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+ <#-- ---------------- -->
+ <#-- Long -->
+ <#-- Varchar -->
+ <#-- Boolean -->
+ <#-- Double -->
+ <#-- Document Library -->
+ <#-- Integer -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Long" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Varchar" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Boolean" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Double" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DocumentLibrary" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Integer"
+ >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+
+ <#assign fieldName = "PrimaryKey">
+ <#if field.validation.fieldName??>
+ <#assign fieldName = "${field.validation.fieldName?cap_first}">
+ #if>
+
+ <#assign orderByField = "PrimaryKey">
+ <#if field.validation.orderByField??>
+ <#assign orderByField = "${field.validation.orderByField?cap_first}">
+ #if>
+ <%
+ String ${field.name}Text = "";
+ try {
+ ${capFirstValidationModel} ${uncapFirstValidationModel} = ${uncapFirstValidationModel}LocalService.get${capFirstValidationModel}(GetterUtil.getLong(${uncapFirstModel}.get${field.name?cap_first}()));
+ ${field.name}Text = ${uncapFirstValidationModel}.get${orderByField}();
+ } catch(Exception e) {}
+ %>
+
+ <#else>
+
+ #if>
+ #if>
+ <#-- ---------------- -->
+ <#-- Date -->
+ <#-- DateTime -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.Date" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.DateTime"
+ >
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- RichText -->
+ <#-- Text -->
+ <#-- ---------------- -->
+ <#if
+ field.type?string == "com.liferay.damascus.cli.json.fields.RichText" ||
+ field.type?string == "com.liferay.damascus.cli.json.fields.Text"
+ >
+
+ <%
+ String ${field.name}Icon = iconUnchecked;
+ String ${field.name} = ${uncapFirstModel}.get${field.name?cap_first}();
+ if (!${field.name}.equals("")) {
+ ${field.name}Icon= iconChecked;
+ }
+ %>
+
+
+ #if>
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+<%-- --%>
+
+
+
+
+
+
+
+
+
+ function deleteEntries() {
+ if (<%=trashHelper.isTrashEnabled(scopeGroupId) %> || confirm('<%=UnicodeLanguageUtil.get(request, "are-you-sure-you-want-to-delete-the-selected-entries") %>')) {
+ var form = AUI.$(document. fm);
+
+ form.attr('method', 'post');
+ form.fm('<%=Constants.CMD%>').val('<%=trashHelper.isTrashEnabled(scopeGroupId) ? Constants.MOVE_TO_TRASH : Constants.DELETE%>');
+ form.fm('deleteEntryIds').val(Liferay.Util.listCheckedExcept(form, ' allRowIds'));
+
+ submitForm(form, ' ');
+ }
+ }
+
diff --git a/src/test/resources/templates/7.3/Portlet_XXXXWEB_view_record.jsp.ftl b/src/test/resources/templates/7.3/Portlet_XXXXWEB_view_record.jsp.ftl
new file mode 100644
index 0000000..fc209a5
--- /dev/null
+++ b/src/test/resources/templates/7.3/Portlet_XXXXWEB_view_record.jsp.ftl
@@ -0,0 +1,83 @@
+<%-- --%>
+<%-- --%>
+<#include "./valuables.ftl">
+<#assign createPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}/view_record.jsp">
+<#assign skipTemplate = !generateWeb>
+<%-- --%>
+<%@ include file="./init.jsp" %>
+
+<%
+${capFirstModel} ${uncapFirstModel} = (${capFirstModel})request.getAttribute("${uncapFirstModel}");
+String redirect = ParamUtil.getString(request, "redirect");
+boolean fromAsset = ParamUtil.getBoolean(request, "fromAsset", false);
+portletDisplay.setShowBackIcon(true);
+portletDisplay.setURLBack(redirect);
+
+<#list application.fields as field >
+ <#if field.validation?? && field.validation.className??>
+ <#assign capFirstValidationModel = "${field.validation.className?cap_first}">
+ <#assign uncapFirstValidationModel = "${field.validation.className?uncap_first}">
+ <#assign uppercaseValidationModel = "${field.validation.className?upper_case}">
+${capFirstValidationModel}LocalService ${uncapFirstValidationModel}LocalService = (${capFirstValidationModel}LocalService) request
+.getAttribute(${capFirstModel}WebKeys.${uppercaseValidationModel}_LOCAL_SERVICE);
+ #if>
+#list>
+%>
+
+
+
+<%-- --%>
+ <#-- ---------------- -->
+ <#-- Assets -->
+ <#-- ---------------- -->
+ <#if application.asset.assetTitleFieldName?? && application.asset.assetTitleFieldName != "" >
+
+ #if>
+ <#if application.asset.assetSummaryFieldName?? && application.asset.assetSummaryFieldName != "" >
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list application.fields as field >
+
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop end -->
+ <#-- ---------------- -->
+<%-- --%>
+
+
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/base.json b/src/test/resources/templates/7.3/base.json
new file mode 100644
index 0000000..9cd3602
--- /dev/null
+++ b/src/test/resources/templates/7.3/base.json
@@ -0,0 +1,87 @@
+{
+ "projectName": "${damascus.projectName}",
+ "packageName" : "${damascus.packageName}",
+ "liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
+ "applications": [
+ {
+ "model" : "${damascus.entityName}",
+ "title" : "${damascus.projectName} Test",
+ "web" : "true",
+ "asset": {
+ "assetTitleFieldName": "${damascus.entityNameLower}TitleName",
+ "assetSummaryFieldName": "${damascus.entityNameLower}SummaryName",
+ "categories": "true",
+ "discussion": "true",
+ "ratings": "true",
+ "tags": "true",
+ "relatedAssets": "true",
+ "fullContentFieldName": "${damascus.entityNameLower}fullContent",
+ "workflow": "true",
+ "generateActivity": "true",
+ "trash":"true",
+ "advancedSearch": "true",
+ "exportExcel": "true"
+ },
+ "fields": [
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "primary":true,
+ "name": "${damascus.entityNameLower}Id",
+ "title": "${damascus.projectName} Id",
+ "showFieldInView": "false",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Varchar",
+ "name": "title",
+ "title": "Title",
+ "length": "80",
+ "showFieldInView": "true",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Boolean",
+ "name": "${damascus.entityNameLower}BooleanStat",
+ "title": "${damascus.projectName} Boolean Stat"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.DateTime",
+ "name": "${damascus.entityNameLower}DateTime",
+ "title": "${damascus.projectName} DateTime"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.DocumentLibrary",
+ "name": "${damascus.entityNameLower}DocumentLibrary",
+ "title": "${damascus.projectName} DocumentLibrary"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Double",
+ "name": "${damascus.entityNameLower}Double",
+ "title": "${damascus.projectName} Double"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Integer",
+ "name": "${damascus.entityNameLower}Integer",
+ "title": "${damascus.projectName} Integer"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.RichText",
+ "name": "${damascus.entityNameLower}RichText",
+ "title": "${damascus.projectName} RichText"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Text",
+ "name": "${damascus.entityNameLower}Text",
+ "title": "${damascus.projectName} Text"
+ }
+ ],
+ "customValue" : {
+ "your_own_id" : "your_custom_value_for_template_here"
+ },
+ "replacements" : {
+ "original_string_to_be_replaced" : "replacement_string"
+ }
+ }
+ ]
+}
diff --git a/src/test/resources/templates/7.3/base_relation_fail.json b/src/test/resources/templates/7.3/base_relation_fail.json
new file mode 100644
index 0000000..d6dd339
--- /dev/null
+++ b/src/test/resources/templates/7.3/base_relation_fail.json
@@ -0,0 +1,99 @@
+{
+ "projectName": "Employee",
+ "packageName": "com.liferay.sb.employee",
+ "liferayVersion": "7.1",
+ "useTargetPlatform": "false",
+ "applications": [{
+ "model": "Employee",
+ "title": "Employee Test",
+ "web": "true",
+ "asset": {
+ "assetTitleFieldName": "employeeTitleName",
+ "assetSummaryFieldName": "employeeSummaryName",
+ "categories": "true",
+ "discussion": "true",
+ "ratings": "true",
+ "tags": "true",
+ "relatedAssets": "true",
+ "fullContentFieldName": "employeefullContent",
+ "workflow": "true",
+ "generateActivity": "true",
+ "trash": "true",
+ "advancedSearch": "true",
+ "exportExcel": "true"
+ },
+ "fields": [{
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "primary": true,
+ "name": "employeeId",
+ "title": "Employee Id",
+ "showFieldInView": "false",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Varchar",
+ "name": "name",
+ "title": "Name",
+ "length": "80",
+ "showFieldInView": "true",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "name": "position",
+ "title": "Position",
+ "showFieldInView": "false",
+ "required": "true",
+ "validation": {
+ "className": "Skills",
+ "fieldName": "skillId",
+ "orderByField": "title"
+ }
+ }
+ ],
+ "customValue": {
+ "your_own_id": "your_custom_value_for_template_here"
+ }
+ },
+ {
+ "model": "Position",
+ "title": "Position Test",
+ "web": "true",
+ "asset": {
+ "assetTitleFieldName": "positionTitleName",
+ "assetSummaryFieldName": "positionSummaryName",
+ "categories": "true",
+ "discussion": "true",
+ "ratings": "true",
+ "tags": "true",
+ "relatedAssets": "true",
+ "fullContentFieldName": "positionfullContent",
+ "workflow": "true",
+ "generateActivity": "true",
+ "trash": "true",
+ "advancedSearch": "true",
+ "exportExcel": "true"
+ },
+ "fields": [{
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "primary": true,
+ "name": "positionId",
+ "title": "Position Id",
+ "showFieldInView": "false",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Varchar",
+ "name": "title",
+ "title": "Title",
+ "length": "80",
+ "showFieldInView": "true",
+ "required": "true"
+ }
+ ],
+ "customValue": {
+ "your_own_id": "your_custom_value_for_template_here"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/base_relation_success.json b/src/test/resources/templates/7.3/base_relation_success.json
new file mode 100644
index 0000000..7d36799
--- /dev/null
+++ b/src/test/resources/templates/7.3/base_relation_success.json
@@ -0,0 +1,99 @@
+{
+ "projectName": "Employee",
+ "packageName": "com.liferay.sb.employee",
+ "liferayVersion": "7.1",
+ "useTargetPlatform": "false",
+ "applications": [{
+ "model": "Employee",
+ "title": "Employee Test",
+ "web": "true",
+ "asset": {
+ "assetTitleFieldName": "employeeTitleName",
+ "assetSummaryFieldName": "employeeSummaryName",
+ "categories": "true",
+ "discussion": "true",
+ "ratings": "true",
+ "tags": "true",
+ "relatedAssets": "true",
+ "fullContentFieldName": "employeefullContent",
+ "workflow": "true",
+ "generateActivity": "true",
+ "trash": "true",
+ "advancedSearch": "true",
+ "exportExcel": "true"
+ },
+ "fields": [{
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "primary": true,
+ "name": "employeeId",
+ "title": "Employee Id",
+ "showFieldInView": "false",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Varchar",
+ "name": "name",
+ "title": "Name",
+ "length": "80",
+ "showFieldInView": "true",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "name": "position",
+ "title": "Position",
+ "showFieldInView": "false",
+ "required": "true",
+ "validation": {
+ "className": "Position",
+ "fieldName": "positionId",
+ "orderByField": "title"
+ }
+ }
+ ],
+ "customValue": {
+ "your_own_id": "your_custom_value_for_template_here"
+ }
+ },
+ {
+ "model": "Position",
+ "title": "Position Test",
+ "web": "true",
+ "asset": {
+ "assetTitleFieldName": "positionTitleName",
+ "assetSummaryFieldName": "positionSummaryName",
+ "categories": "true",
+ "discussion": "true",
+ "ratings": "true",
+ "tags": "true",
+ "relatedAssets": "true",
+ "fullContentFieldName": "positionfullContent",
+ "workflow": "true",
+ "generateActivity": "true",
+ "trash": "true",
+ "advancedSearch": "true",
+ "exportExcel": "true"
+ },
+ "fields": [{
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "primary": true,
+ "name": "positionId",
+ "title": "Position Id",
+ "showFieldInView": "false",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Varchar",
+ "name": "title",
+ "title": "Title",
+ "length": "80",
+ "showFieldInView": "true",
+ "required": "true"
+ }
+ ],
+ "customValue": {
+ "your_own_id": "your_custom_value_for_template_here"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/base_tags_false.json b/src/test/resources/templates/7.3/base_tags_false.json
new file mode 100644
index 0000000..41c65ef
--- /dev/null
+++ b/src/test/resources/templates/7.3/base_tags_false.json
@@ -0,0 +1,81 @@
+{
+ "projectName": "${damascus.projectName}",
+ "packageName" : "${damascus.packageName}",
+ "liferayVersion": "${damascus.liferayVersion}",
+ "useTargetPlatform": "false",
+ "applications": [
+ {
+ "model" : "${damascus.projectName}",
+ "title" : "${damascus.projectName} Test",
+ "web" : "true",
+ "asset": {
+ "assetTitleFieldName": "${damascus.entityNameLower}TitleName",
+ "assetSummaryFieldName": "${damascus.entityNameLower}SummaryName",
+ "categories": "true",
+ "discussion": "true",
+ "ratings": "true",
+ "tags": "false",
+ "relatedAssets": "true",
+ "fullContentFieldName": "${damascus.entityNameLower}fullContent",
+ "workflow": "true",
+ "generateActivity": "true",
+ "trash":"true",
+ "advancedSearch": "true",
+ "exportExcel": "true"
+ },
+ "fields": [
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Long",
+ "primary":true,
+ "name": "${damascus.entityNameLower}Id",
+ "title": "${damascus.projectName} Id",
+ "showFieldInView": "false",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Varchar",
+ "name": "title",
+ "title": "Title",
+ "length": "80",
+ "showFieldInView": "true",
+ "required": "true"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Boolean",
+ "name": "${damascus.entityNameLower}BooleanStat",
+ "title": "${damascus.projectName} Boolean Stat"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.DateTime",
+ "name": "${damascus.entityNameLower}DateTime",
+ "title": "${damascus.projectName} DateTime"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.DocumentLibrary",
+ "name": "${damascus.entityNameLower}DocumentLibrary",
+ "title": "${damascus.projectName} DocumentLibrary"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Double",
+ "name": "${damascus.entityNameLower}Double",
+ "title": "${damascus.projectName} Double"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Integer",
+ "name": "${damascus.entityNameLower}Integer",
+ "title": "${damascus.projectName} Integer"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.RichText",
+ "name": "${damascus.entityNameLower}RichText",
+ "title": "${damascus.projectName} RichText"
+ },
+ {
+ "type": "com.liferay.damascus.cli.json.fields.Text",
+ "name": "${damascus.entityNameLower}Text",
+ "title": "${damascus.projectName} Text"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/test/resources/templates/7.3/license.ftl b/src/test/resources/templates/7.3/license.ftl
new file mode 100644
index 0000000..69a69b8
--- /dev/null
+++ b/src/test/resources/templates/7.3/license.ftl
@@ -0,0 +1,13 @@
+/**
+* Copyright (C) ${.now?date?string.yyyy} Yasuyuki Takeo All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*/
diff --git a/src/test/resources/templates/7.3/service.xml b/src/test/resources/templates/7.3/service.xml
new file mode 100644
index 0000000..ae7ca10
--- /dev/null
+++ b/src/test/resources/templates/7.3/service.xml
@@ -0,0 +1,148 @@
+
+
+
+
+<#include "./valuables.ftl">
+<#assign createPath = "${createPath_val}/service.xml">
+
+
+
+ "${damascus_author}"
+ ${camelcaseProjectName}
+
+ <#list damascus.applications as app>
+
+
+
+
+ <#-- ---------------- -->
+ <#-- field loop start -->
+ <#-- ---------------- -->
+ <#list app.fields as field >
+ <#if field.primary?? && field.primary == true >
+
+ #if>
+ primary="true"#if> />
+ #list>
+ <#-- ---------------- -->
+ <#-- field loop ends -->
+ <#-- ---------------- -->
+
+
+
+
+
+
+
+
+
+
+
+ <#-- ---------------- -->
+ <#-- Asset Commons -->
+ <#-- ---------------- -->
+ <#if app.asset?? >
+
+
+
+
+
+ <#-- ---------------- -->
+ <#-- Workflow -->
+ <#-- ---------------- -->
+ <#if app.asset.workflow?? && true == app.asset.workflow >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #if>
+
+ #if>
+
+ <#-- ---------------- -->
+ <#-- Asset related -->
+ <#-- ---------------- -->
+ <#if app.asset?? >
+
+
+
+
+
+
+
+
+ #if>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <#-- ---------------- -->
+ <#-- Fields Finders -->
+ <#-- ---------------- -->
+ <#list app.fields as field >
+
+
+
+ #list>
+
+
+
+
+
+
+
+
+
+
+ #list>
+
+ <#list damascus.applications as app >
+ NoSuch${app.model}
+ ${app.model?cap_first}Validate
+ #list>
+
+
+
+
diff --git a/src/test/resources/templates/7.3/valuables.ftl b/src/test/resources/templates/7.3/valuables.ftl
new file mode 100644
index 0000000..728c8cb
--- /dev/null
+++ b/src/test/resources/templates/7.3/valuables.ftl
@@ -0,0 +1,43 @@
+<#assign void><#-- Just to prevent unexpected whitespace or line breaks -->
+
+<#assign packageName = "${damascus.packageName}">
+<#assign packagePath = "${packageName?replace(\".\", \"/\")}">
+<#assign packageSnake = "${packageName?replace(\".\", \"_\")}">
+<#assign useTP = damascus.isUseTargetPlatform() >
+
+<#assign camelcaseProjectName = "${damascus.projectName?replace(\"-\", \"\")}">
+<#assign dashcaseProjectName = "${caseUtil.camelCaseToDashCase(camelcaseProjectName)}">
+<#assign projectPath = "${createPath_val}/${dashcaseProjectName}">
+<#assign apiModulePath = "${projectPath}/${dashcaseProjectName}-api">
+<#assign serviceModulePath = "${projectPath}/${dashcaseProjectName}-service">
+<#assign webModulePath = "${projectPath}/${dashcaseProjectName}-web">
+
+<#if application?exists>
+<#assign capFirstModel = "${application.model?cap_first}">
+<#assign uncapFirstModel = "${application.model?uncap_first}">
+<#assign lowercaseModel = "${application.model?lower_case}">
+<#assign uppercaseModel = "${application.model?upper_case}">
+<#assign snakecaseModel = "${caseUtil.camelCaseToSnakeCase(application.model)}">
+
+<#assign categories = application.asset?exists && application.asset.categories>
+<#assign discussion = application.asset?exists && application.asset.discussion>
+<#assign advancedSearch = application.asset?exists && application.asset.advancedSearch>
+<#assign exportExcel = application.asset?exists && application.asset.exportExcel>
+<#assign ratings = application.asset?exists && application.asset.ratings>
+<#assign tags = application.asset?exists && application.asset.tags>
+<#assign relatedAssets = application.asset?exists && application.asset.relatedAssets>
+<#assign generateActivity = application.asset?exists && application.asset.generateActivity>
+<#assign generateWeb = application.web?exists && application.web>
+<#assign anyGeneratedWeb = damascus.isWebExist()>
+
+<#assign entityWebResourcesPath = "${webModulePath}/src/main/resources/META-INF/resources/${snakecaseModel}">
+
+<#assign primaryKeyParam = "">
+<#list application.fields as field >
+ <#if field.primary?? && field.primary == true >
+ <#assign primaryKeyParam = "${field.name}">
+ #if>
+#list>
+#if>
+
+#assign>