This is an automated email from the ASF dual-hosted git repository.

nmalin pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new eee3a464d0 Improved: Convert PortalPageServices.xml from mini-lang to 
Groovy (OFBIZ-13091)
eee3a464d0 is described below

commit eee3a464d0396b23081d150b940338752619d30c
Author: Nicolas Malin <nicolas.ma...@nereide.fr>
AuthorDate: Tue May 14 16:51:36 2024 +0200

    Improved: Convert PortalPageServices.xml from mini-lang to Groovy 
(OFBIZ-13091)
    
    Convert following services :
        * createPortalPagePortlet
        * deletePortalPagePortlet
        * movePortletToPortalPage
        * deletePortalPage
        * updatePortalPageSeq
        * addPortalPageColumn
        * deletePortalPageColumn
        * updatePortletSeqDragDrop
        * getPortletAttributes
    
    Due to interdependency, introduce new service :
        * duplicatePortalPageDetails
    
    And by the way migrate PortalPageMethods.xml to PortalMethods.groovy
---
 framework/common/minilang/PortalPageMethods.xml    | 159 ---------
 framework/common/minilang/PortalPageServices.xml   | 364 --------------------
 framework/common/servicedef/services.xml           | 115 ++++---
 .../apache/ofbiz/common/PortalPageMethods.groovy   |  65 ++++
 .../apache/ofbiz/common/PortalPageServices.groovy  | 370 +++++++++++++++++++++
 .../common/webcommon/WEB-INF/portal-controller.xml |   4 +-
 6 files changed, 498 insertions(+), 579 deletions(-)

diff --git a/framework/common/minilang/PortalPageMethods.xml 
b/framework/common/minilang/PortalPageMethods.xml
deleted file mode 100644
index 3986dc1f20..0000000000
--- a/framework/common/minilang/PortalPageMethods.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
--->
-
-<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-        xmlns="http://ofbiz.apache.org/Simple-Method"; 
xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method 
http://ofbiz.apache.org/dtds/simple-methods.xsd";>
-
-    <simple-method method-name="setPortalPortletAttributes" 
short-description="Sets a PortalPortlet attributes">
-        <if-not-empty field="parameters">
-            <iterate-map map="parameters" key="attributeKey" 
value="attributeValue">
-                <if>
-                    <condition>
-                        <and>
-                            <if-compare field="attributeKey"  
operator="not-equals" value="portalPageId"/>
-                            <if-compare field="attributeKey"  
operator="not-equals" value="portalPortletId"/>
-                            <if-compare field="attributeKey"  
operator="not-equals" value="portletSeqId"/>
-                        </and>
-                    </condition>
-                    <then>
-                        <log level="info" message="===2==processing: 
${attributeKey}"></log>
-                        <clear-field field="attributeEntityMap"/>
-                        <set-service-fields 
service-name="createPortletAttribute" map="parameters" 
to-map="attributeEntityMap"/>
-                        <set field="attributeEntityMap.attrName"  
from-field="attributeKey"/>
-                        <set field="attributeEntityMap.attrValue" 
from-field="attributeValue"/>
-                        
-                        <entity-one entity-name="PortletAttribute" 
value-field="attributeItem">
-                            <field-map field-name="attrName" 
from-field="attributeEntityMap.attrName"/>
-                        </entity-one>
-                        <if-not-empty field="attributeItem">
-                            <remove-value value-field="attributeItem"/>
-                        </if-not-empty>
-                        <call-service service-name="createPortletAttribute" 
in-map-name="attributeEntityMap"/>
-                        <!-- remove all attributes which were not provided -->
-                        <entity-condition entity-name="PortletAttribute" 
list="attributeList">
-                            <condition-list combine="and">
-                                <condition-expr field-name="portalPageId" 
operator="equals" from-field="parameters.portalPageId"/>                
-                                <condition-expr field-name="portalPortletId" 
operator="equals" from-field="parameters.portalPortletId"/>                
-                                <condition-expr field-name="portletSeqId" 
operator="equals" from-field="parameters.portletSeqId" ignore-if-null="true"/>  
              
-                            </condition-list>
-                        </entity-condition>
-                        <!-- remove all not supplied attributes -->
-                        <iterate list="attributeList" entry="attribute">
-                            <if-empty field="parameters.${attribute.attrName}">
-                                <remove-value value-field="attribute"/>
-                            </if-empty>
-                        </iterate>                        
-                    </then>
-                </if>
-            </iterate-map>
-        </if-not-empty>
-    </simple-method>
-
-    <!--Create simple-method of copyOriginalPage-->
-    <simple-method method-name="copyIfRequiredSystemPage" 
short-description="Check if the page is a system page, then copy before 
allowing the user to edit it">
-        <entity-one entity-name="PortalPage" value-field="portalPage"/>
-        <if-compare field="portalPage.ownerUserLoginId" value="_NA_" 
operator="equals">
-            <!-- check if private page already created -->
-            <entity-and entity-name="PortalPage" list="getPrivatePages">
-                <field-map field-name="originalPortalPageId" 
from-field="parameters.portalPageId"/>
-                <field-map field-name="ownerUserLoginId" 
from-field="userLogin.userLoginId"/>
-            </entity-and>
-            <if-empty field="getPrivatePages">
-
-                <!-- copy the portal page -->
-                <set-service-fields service-name="createPortalPage" 
map="portalPage" to-map="createPage"/>
-                <clear-field field="createPage.portalPageId"/>
-                <set field="createPage.ownerUserLoginId" 
from-field="userLogin.userLoginId"/>
-                <set field="createPage.originalPortalPageId" 
from-field="parameters.portalPageId"/>
-                <call-service service-name="createPortalPage" 
in-map-name="createPage">
-                    <result-to-field result-name="portalPageId"/>
-                </call-service>
-                <field-to-request field="portalPageId" 
request-name="portalPageId"/>
-
-                <call-simple-method method-name="duplicatePortalPageDetails"/>
-
-            </if-empty>
-        </if-compare>
-    </simple-method>
-
-    <!--Duplicate content of portalPage, portalPageColumn, portalPagePortlet, 
portletAttribute,
-         this method should be call with portalpageId and portalPage in 
context-->
-    <simple-method method-name="duplicatePortalPageDetails" 
short-description="Duplicate content of portalPage, portalPageColumn, 
portalPagePortlet, portletAttribute">
-        <log level="info" message="duplicate portalPage detail from 
portalPageId  ${parameters.portalPageId} to new portalPageId=${portalPageId}"/>
-
-        <if-not-empty field="portalPageId">
-          <!-- delete the columns -->
-          <set field="delMap.portalPageId" from-field="portalPageId" />
-          <!--        <remove-by-and entity-name="PortalPageColumn" 
map="delMap"/>-->
-
-          <!-- copy columns -->
-          <entity-and entity-name="PortalPageColumn" use-cache="true" 
list="portalPageColumns">
-            <field-map field-name="portalPageId" 
from-field="parameters.portalPageId" />
-          </entity-and>
-          <set field="first" value="true" type="Boolean" />
-          <iterate list="portalPageColumns" entry="portalPageColumn">
-            <set-service-fields service-name="addPortalPageColumn" 
map="portalPageColumn" to-map="addColumnMap" />
-            <clear-field field="addColumnMap.columnSeqId" />
-            <set field="addColumnMap.portalPageId" from-field="portalPageId" />
-            <call-service service-name="addPortalPageColumn" 
in-map-name="addColumnMap" />
-          </iterate>
-
-          <!-- copy portlets, and portletAttribute -->
-          <entity-and entity-name="PortalPagePortlet" 
list="portalPagePortlets">
-            <field-map field-name="portalPageId" 
from-field="parameters.portalPageId" />
-          </entity-and>
-          <iterate list="portalPagePortlets" entry="portalPagePortlet">
-            <set-service-fields service-name="createPortalPagePortlet" 
map="portalPagePortlet" to-map="createPortLet" />
-            <set field="createPortLet.portalPageId" from-field="portalPageId" 
/>
-            <call-service service-name="createPortalPagePortlet" 
in-map-name="createPortLet" />
-            <!-- copy the attributes -->
-            <entity-and entity-name="PortletAttribute" 
list="portletAttributes">
-              <field-map field-name="portalPageId" 
from-field="parameters.portalPageId" />
-              <field-map field-name="portalPortletId" 
from-field="portalPagePortlet.portalPortletId" />
-              <field-map field-name="portletSeqId" 
from-field="portalPagePortlet.portletSeqId" />
-            </entity-and>
-            <iterate list="portletAttributes" entry="portletAttribute">
-              <set field="portletAttribute.portalPageId" 
from-field="portalPageId" />
-              <create-value value-field="portletAttribute" />
-            </iterate>
-          </iterate>
-        </if-not-empty>
-    </simple-method>
-
-    <!--Duplicate simple-method of copyOriginalPage-->
-    <simple-method method-name="duplicatePortalPage" short-description="Only 
duplicate a portal page, user should put correct owner and securityGroup">
-        <entity-one entity-name="PortalPage" value-field="portalPage"/>
-
-        <!-- copy the portal page -->
-        <set-service-fields service-name="createPortalPage" map="portalPage" 
to-map="createPage"/>
-        <clear-field field="createPage.portalPageId"/>
-        <if-empty field="createPage.originalPortalPageId">
-            <set field="createPage.originalPortalPageId" 
from-field="parameters.portalPageId"/>
-        </if-empty>
-        <call-service service-name="createPortalPage" in-map-name="createPage">
-            <result-to-field result-name="portalPageId"/>
-        </call-service>
-        <field-to-request field="portalPageId" request-name="portalPageId"/>
-        <log level="info" message="new protalPageId=${portalPageId}"/>
-
-        <call-simple-method method-name="duplicatePortalPageDetails"/>
-
-    </simple-method>
-</simple-methods>
diff --git a/framework/common/minilang/PortalPageServices.xml 
b/framework/common/minilang/PortalPageServices.xml
deleted file mode 100644
index 519519cb89..0000000000
--- a/framework/common/minilang/PortalPageServices.xml
+++ /dev/null
@@ -1,364 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
--->
-
-<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-        xmlns="http://ofbiz.apache.org/Simple-Method"; 
xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method 
http://ofbiz.apache.org/dtds/simple-methods.xsd";>
-
-    <simple-method method-name="movePortletToPortalPage" 
short-description="Moves a PortalPortlet from the actual portalPage to a 
different one">
-        <call-simple-method method-name="checkOwnerShip"/>
-        <entity-one entity-name="PortalPagePortlet" value-field="oldEntity"/>
-        <set field="parameters.portalPageId" 
from-field="parameters.newPortalPageId"/>
-        <call-simple-method method-name="copyIfRequiredSystemPage" 
xml-resource="component://common/minilang/PortalPageMethods.xml"/>
-        <set field="parameters.newPortalPageId" from-field="portalPageId"/>
-        <make-value entity-name="PortalPagePortlet" value-field="newEntity"/>
-        <set field="newEntity.portalPortletId" 
from-field="parameters.portalPortletId"/>
-        <set field="newEntity.portalPageId" 
from-field="parameters.newPortalPageId"/>
-        <set field="newEntity.columnNum" value="1"/>
-        <make-next-seq-id value-field="newEntity" 
seq-field-name="portletSeqId"/>
-        <create-value value-field="newEntity"/>
-        <remove-value value-field="oldEntity"/>
-    </simple-method>
-
-    <simple-method method-name="addPortalPageColumn" short-description="Add a 
new Column to a PortalPage">
-        <call-simple-method method-name="checkOwnerShip"/>
-        <make-value entity-name="PortalPageColumn" value-field="newEntity"/>
-        <set-pk-fields map="parameters" value-field="newEntity"/>
-        <if-empty field="parameters.columnSeqId">
-            <make-next-seq-id value-field="newEntity" 
seq-field-name="columnSeqId"/>
-        </if-empty>
-        <field-to-result field="newEntity.columnSeqId" 
result-name="columnSeqId"/>
-        <set-nonpk-fields map="parameters" value-field="newEntity"/>
-        <create-value value-field="newEntity"/>
-    </simple-method>
-
-    <simple-method method-name="deletePortalPageColumn" 
short-description="Delete a Column from a PortalPage">
-        <call-simple-method method-name="checkOwnerShip"/>
-        <entity-one entity-name="PortalPageColumn" value-field="column" 
auto-field-map="true"/>
-        <if-not-empty field="column">
-            <entity-and entity-name="PortalPagePortlet" 
list="portalPortletList">
-                <field-map field-name="portalPageId" 
from-field="column.portalPageId"/>
-                <field-map field-name="columnSeqId"  
from-field="column.columnSeqId"/>
-            </entity-and>
-            <iterate list="portalPortletList" entry="portalPortlet">
-                <set-service-fields service-name="deletePortalPagePortlet" 
map="portalPortlet" to-map="deletePortalPagePortletInMap"/>
-                <call-service service-name="deletePortalPagePortlet" 
in-map-name="deletePortalPagePortletInMap"/>
-            </iterate>
-            <remove-value value-field="column"/>
-        </if-not-empty>
-        <check-errors/>
-    </simple-method>
-
-    <simple-method method-name="createPortalPagePortlet" 
short-description="Add a registered PortalPortlet to a PortalPage">
-        <call-simple-method method-name="checkOwnerShip"/>
-        <make-value entity-name="PortalPagePortlet" value-field="newEntity"/>
-        <set-pk-fields map="parameters" value-field="newEntity"/>
-
-        <entity-condition entity-name="PortalPagePortlet" list="portlets">
-            <condition-expr field-name="portalPageId" operator="equals" 
from-field="parameters.portalPageId"/>
-            <select-field field-name="sequenceNum"/>
-            <order-by field-name="-sequenceNum"/>
-            <limit-range size="1" start="0"/>
-        </entity-condition>
-        <first-from-list list="portlets" entry="portalPagePortlet"/>
-
-        <if-empty field="portalPagePortlet.sequenceNum">
-            <calculate field="newEntity.sequenceNum" type="Long"><number 
value="1"/></calculate>
-            <else>
-                <calculate field="newEntity.sequenceNum" type="Long">
-                    <calcop operator="add" 
field="portalPagePortlet.sequenceNum">
-                        <number value="1"/>
-                    </calcop>
-                </calculate>
-            </else>
-        </if-empty>
-
-        <make-next-seq-id value-field="newEntity" 
seq-field-name="portletSeqId"/>
-        <field-to-result field="newEntity.portletSeqId" 
result-name="portletSeqId"/>
-        <set-nonpk-fields map="parameters" value-field="newEntity"/>
-        <create-value value-field="newEntity"/>
-    </simple-method>
-
-    <simple-method method-name="deletePortalPagePortlet" 
short-description="Delete a PortalPortlet from a PortalPageColumn">
-        <call-simple-method method-name="checkOwnerShip"/>
-        <entity-one entity-name="PortalPagePortlet" value-field="portlet" 
auto-field-map="true"/>
-        <if-not-empty field="portlet">
-            <make-value entity-name="PortletAttribute" 
value-field="newEntity"/>
-            <set field="newEntity.portalPageId" 
from-field="portlet.portalPageId"/>
-            <set field="newEntity.portalPortletId" 
from-field="portlet.portalPortletId"/>
-            <set field="newEntity.portletSeqId" 
from-field="portlet.portletSeqId"/>
-            <remove-by-and entity-name="PortletAttribute" map="newEntity"/>
-            <remove-value value-field="portlet"/>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="getPortletAttributes" short-description="Get 
all attributes of a Portlet either by providing userLogin or portalPageid with 
portalPortletId" login-required="true">
-        <if-empty field="parameters.ownerUserLoginId">
-            <if-empty field="parameters.portalPageId">
-                <log level="error" message="Service getPortletAttributes did 
not receive either ownerUserLoginId OR portalPageId"></log>
-                <string-to-list string="Service getPortletAttributes did not 
receive either ownerUserLoginId OR portalPageId" list="error_list"/>
-            </if-empty>
-        </if-empty>
-        <check-errors/>
-        <!-- if userLogin provided get the portalPageId with the required 
portlet -->
-        <if-not-empty field="parameters.ownerUserLoginId">
-            <entity-and entity-name="PortalPageAndPortlet" list="ppList">
-                <field-map field-name="ownerUserLoginId" 
from-field="parameters.ownerUserLoginId"/>
-                <field-map field-name="portalPortletId"  
from-field="parameters.portalPortletId"/>
-            </entity-and>
-            <first-from-list list="ppList" entry="portalPage"/>
-            <set field="parameters.portalPageId" 
from-field="portalPage.portalPageId"/>
-        </if-not-empty>
-        <entity-condition entity-name="PortletAttribute" list="attributeList">
-            <condition-list combine="and">
-                <condition-expr field-name="portalPageId" operator="equals" 
from-field="parameters.portalPageId"/>
-                <condition-expr field-name="portalPortletId" operator="equals" 
from-field="parameters.portalPortletId"/>
-                <condition-expr field-name="portletSeqId" operator="equals" 
from-field="parameters.portletSeqId" ignore-if-empty="true"/>
-            </condition-list>
-        </entity-condition>
-        <if-not-empty field="attributeList">
-            <iterate list="attributeList" entry="attributeRecord">
-                <set field="attributeMap.${attributeRecord.attrName}" 
from-field="attributeRecord.attrValue"/>
-            </iterate>
-            <field-to-result field="attributeMap" result-name="attributeMap"/>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="createPortalPage" short-description="Create a 
new Portal Page">
-        <if-not-empty field="parameters.portalPageName">
-            <make-value entity-name="PortalPage" value-field="newPortalPage"/>
-            <set-pk-fields map="parameters" value-field="newPortalPage"/>
-            <if-empty field="newPortalPage.portalPageId">
-                <sequenced-id sequence-name="PortalPage" 
field="newPortalPage.portalPageId"/>
-            </if-empty>
-            <set-nonpk-fields map="parameters" value-field="newPortalPage"/>
-            <set field="newPortalPage.ownerUserLoginId" 
from-field="parameters.userLogin.userLoginId"/>
-            <if-empty field="parameters.sequenceNum">
-                <make-next-seq-id value-field="newPortalPage" 
seq-field-name="sequenceNum"/>
-            </if-empty>
-            <create-value value-field="newPortalPage"/>
-            <field-to-result field="newPortalPage.portalPageId" 
result-name="portalPageId"/>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="deletePortalPage" short-description="Delete a 
Portal Page">
-        <entity-one entity-name="PortalPage" value-field="getPortalPage"/>
-        <if-not-empty field="getPortalPage.originalPortalPageId">
-            <entity-one entity-name="PortalPage" 
value-field="getOldSequenceNum">
-                <field-map field-name="portalPageId" 
from-field="getPortalPage.originalPortalPageId"/>
-            </entity-one>
-            <entity-condition entity-name="PortalPage" 
list="checkSequenceNums">
-                <condition-list combine="and">
-                    <condition-expr field-name="sequenceNum" operator="equals" 
from-field="getOldSequenceNum.sequenceNum"/>
-                    <condition-expr field-name="ownerUserLoginId" 
operator="equals" from-field="userLogin.userLoginId"/>
-                    <condition-expr field-name="parentPortalPageId" 
operator="equals" from-field="parameters.parentPortalPageId"/>
-                </condition-list>
-            </entity-condition>
-            <first-from-list list="checkSequenceNums" 
entry="checkSequenceNum"/>
-            <if-not-empty field="checkSequenceNum.portalPageId">
-                <set field="first.portalPageId" 
from-field="checkSequenceNum.portalPageId"/>
-                <set field="first.sequenceNum" 
from-field="getPortalPage.sequenceNum" type="Long"/>
-                <call-service service-name="updatePortalPage" 
in-map-name="first"/>
-            </if-not-empty>
-        </if-not-empty>
-        <call-simple-method method-name="checkOwnerShip"/>
-        <remove-related value-field="portalPage" 
relation-name="PortalPageColumn"/>
-        <remove-related value-field="portalPage" 
relation-name="PortalPagePortlet"/>
-        <remove-value value-field="portalPage"/>
-    </simple-method>
-
-    <simple-method method-name="checkOwnerShip" short-description="Check the 
ownership of a Portal Page">
-        <if-not-empty field="parameters.portalPageId">
-            <entity-one entity-name="PortalPage" value-field="portalPage"/>
-            <if-empty field="portalPage">
-                <add-error>
-                    <fail-property resource="CommonUiLabels" 
property="PortalPageNotFound"/>
-                </add-error>
-            </if-empty>
-            <check-errors/>
-            <if> <!-- only page owner or user with MYPORTALBASE_ADMIN can 
modify the page detail -->
-              <condition>
-                <and>
-                  <if-compare field="portalPage.ownerUserLoginId" 
operator="not-equals" value="${parameters.userLogin.userLoginId}"/>
-                  <not>
-                       <if-has-permission permission="MYPORTALBASE" 
action="_ADMIN"/>
-                  </not>
-                </and>
-              </condition>
-              <then>
-                <add-error>
-                    <fail-property resource="CommonUiLabels" 
property="PortalPageNotOwned"/>
-                </add-error>
-              </then>
-            </if>
-            <check-errors/>
-        </if-not-empty>
-    </simple-method>
-    <simple-method method-name="updatePortalPageSeq" short-description="Update 
the portal page sequence numbers">
-        <call-simple-method method-name="checkOwnerShip"/>
-        <entity-one entity-name="PortalPage" value-field="getSequenceNum"/>
-        <if-compare field="parameters.mode" value="UP" operator="equals">
-            <entity-condition entity-name="PortalPage" list="getDatas">
-                <condition-list combine="and">
-                    <condition-expr field-name="sequenceNum" operator="less" 
from-field="getSequenceNum.sequenceNum"/>
-                    <condition-expr field-name="ownerUserLoginId" 
operator="equals" from-field="userLogin.userLoginId"/>
-                    <condition-list combine="or">
-                        <condition-expr field-name="parentPortalPageId" 
operator="equals" from-field="parameters.parentPortalPageId"/>
-                        <condition-expr field-name="originalPortalPageId" 
operator="equals" from-field="parameters.parentPortalPageId"/>
-                    </condition-list>
-                </condition-list>
-                <order-by field-name="-sequenceNum"/>
-            </entity-condition>
-        </if-compare>
-        <if-compare field="parameters.mode" value="DWN" operator="equals">
-            <entity-condition entity-name="PortalPage" list="getDatas">
-                <condition-list combine="and">
-                    <condition-expr field-name="sequenceNum" 
operator="greater" from-field="getSequenceNum.sequenceNum"/>
-                    <condition-expr field-name="ownerUserLoginId" 
operator="equals" from-field="userLogin.userLoginId"/>
-                    <condition-list combine="or">
-                        <condition-expr field-name="parentPortalPageId" 
operator="equals" from-field="parameters.parentPortalPageId"/>
-                        <condition-expr field-name="originalPortalPageId" 
operator="equals" from-field="parameters.parentPortalPageId"/>
-                    </condition-list>
-                </condition-list>
-                <order-by field-name="sequenceNum"/>
-            </entity-condition>
-        </if-compare>
-        <if-compare field="parameters.mode" value="TOP" operator="equals">
-            <entity-condition entity-name="PortalPage" list="getDatas">
-                <condition-list combine="and">
-                    <condition-expr field-name="sequenceNum" operator="less" 
from-field="getSequenceNum.sequenceNum"/>
-                    <condition-expr field-name="ownerUserLoginId" 
operator="equals" from-field="userLogin.userLoginId"/>
-                    <condition-list combine="or">
-                        <condition-expr field-name="parentPortalPageId" 
operator="equals" from-field="parameters.parentPortalPageId"/>
-                        <condition-expr field-name="originalPortalPageId" 
operator="equals" from-field="parameters.parentPortalPageId"/>
-                    </condition-list>
-                </condition-list>
-                <order-by field-name="sequenceNum"/>
-            </entity-condition>
-        </if-compare>
-        <if-compare field="parameters.mode" value="BOT" operator="equals">
-            <entity-condition entity-name="PortalPage" list="getDatas">
-                <condition-list combine="and">
-                    <condition-expr field-name="sequenceNum" 
operator="greater" from-field="getSequenceNum.sequenceNum"/>
-                    <condition-expr field-name="ownerUserLoginId" 
operator="equals" from-field="userLogin.userLoginId"/>
-                    <condition-list combine="or">
-                        <condition-expr field-name="parentPortalPageId" 
operator="equals" from-field="parameters.parentPortalPageId"/>
-                        <condition-expr field-name="originalPortalPageId" 
operator="equals" from-field="parameters.parentPortalPageId"/>
-                    </condition-list>
-                </condition-list>
-                <order-by field-name="-sequenceNum"/>
-            </entity-condition>
-        </if-compare>
-        <first-from-list list="getDatas" entry="getData"/>
-        <set field="portalPage.sequenceNum" from-field="getData.sequenceNum" 
type="Long"/>
-        <store-value value-field="portalPage"/>
-        <set field="first.portalPageId" from-field="getData.portalPageId"/>
-        <set field="first.sequenceNum" from-field="getSequenceNum.sequenceNum" 
type="Long"/>
-        <call-service service-name="updatePortalPage" in-map-name="first"/>
-    </simple-method>
-
-    <!-- update Portlet Seq with Drag & Drop -->
-    <simple-method method-name="updatePortletSeqDragDrop" 
short-description="Updates a portlet Seq No for the Drag and Drop Feature">
-        <set field="parameters.portalPageId" 
from-field="parameters.o_portalPageId"/>
-        <call-simple-method method-name="checkOwnerShip"/>
-
-        <!-- origin Portlet -->
-        <entity-one entity-name="PortalPagePortlet" value-field="originPp">
-            <field-map field-name="portalPageId" 
from-field="parameters.o_portalPageId"/>
-            <field-map field-name="portalPortletId" 
from-field="parameters.o_portalPortletId"/>
-            <field-map field-name="portletSeqId" 
from-field="parameters.o_portletSeqId"/>
-        </entity-one>
-        <if-empty field="originPp">
-            <return response-code="error"/>
-        </if-empty>
-        <set field="columnSeqId" from-field="parameters.destinationColumn" 
default-value="${originPp.columnSeqId}"/>
-
-        <!-- destination Portlet -->
-        <if-compare field="parameters.mode" operator="contains" 
value="DRAGDROPBEFORE">
-            <entity-one value-field="destiPp" entity-name="PortalPagePortlet">
-                <field-map field-name="portalPageId" 
from-field="parameters.d_portalPageId"/>
-                <field-map field-name="portalPortletId" 
from-field="parameters.d_portalPortletId"/>
-                <field-map field-name="portletSeqId" 
from-field="parameters.d_portletSeqId"/>
-            </entity-one>
-
-            <entity-condition entity-name="PortalPagePortlet" 
list="modifyPpList">
-             <condition-list combine="and">
-                <condition-expr field-name="portalPageId" operator="equals" 
from-field="parameters.portalPageId"/>
-                <condition-expr field-name="columnSeqId" operator="equals" 
from-field="columnSeqId"/>
-                <condition-expr field-name="sequenceNum" 
operator="greater-equals" from-field="destiPp.sequenceNum"/>
-                <condition-expr field-name="sequenceNum" operator="less" 
from-field="originPp.sequenceNum" ignore-if-empty="true"/>
-             </condition-list>
-             <order-by field-name="sequenceNum"/>
-            </entity-condition>
-            <set field="increase" value="1" type="Long"/>
-            <set field="newSequenceNo" from-field="destiPp.sequenceNum"/>
-        </if-compare>
-
-        <if-compare field="parameters.mode" operator="equals" 
value="DRAGDROPAFTER">
-            <entity-one value-field="destiPp" entity-name="PortalPagePortlet">
-                <field-map field-name="portalPageId" 
from-field="parameters.d_portalPageId"/>
-                <field-map field-name="portalPortletId" 
from-field="parameters.d_portalPortletId"/>
-                <field-map field-name="portletSeqId" 
from-field="parameters.d_portletSeqId"/>
-            </entity-one>
-
-            <entity-condition entity-name="PortalPagePortlet" 
list="modifyPpList">
-             <condition-list combine="and">
-                <condition-expr field-name="portalPageId" operator="equals" 
from-field="parameters.portalPageId"/>
-                <condition-expr field-name="columnSeqId" operator="equals" 
from-field="columnSeqId"/>
-                <condition-expr field-name="sequenceNum" operator="greater" 
from-field="originPp.sequenceNum"/>
-                <condition-expr field-name="sequenceNum" 
operator="less-equals" from-field="destiPp.sequenceNum" ignore-if-empty="true"/>
-             </condition-list>
-             <order-by field-name="-sequenceNum"/>
-            </entity-condition>
-            <set field="increase" value="-1" type="Long"/>
-            <set field="newSequenceNo" from-field="destiPp.sequenceNum"/>
-        </if-compare>
-
-        <if-compare field="parameters.mode" operator="contains" value="NEW">
-            <set field="newSequenceNo" value="0"/>
-        </if-compare>
-
-        <!-- Modify the sequence id from the following portlets -->
-        <if-not-empty field="modifyPpList">
-            <iterate list="modifyPpList" entry="modifyPp">
-                <if-empty field="modifyPp.sequenceNum">
-                    <set field="modifyPp.sequenceNum" value="newSequenceNo"/>
-                    <else>
-                        <calculate field="modifyPp.sequenceNum" type="Long">
-                            <calcop operator="add" field="newSequenceNo">
-                                <calcop operator="get" field="increase"/>
-                            </calcop>
-                        </calculate>
-                        <calculate field="increase" type="Long">
-                            <calcop operator="add" field="increase">
-                                <calcop operator="get" field="increase"/>
-                            </calcop>
-                        </calculate>
-                    </else>
-                </if-empty>
-                <store-value value-field="modifyPp"/>
-            </iterate>
-        </if-not-empty>
-        <!-- Create a new db entry for the moved portlet -->
-        <set field="originPp.columnSeqId" from-field="columnSeqId"/>
-        <set field="originPp.sequenceNum" from-field="newSequenceNo" 
type="Long"/>
-        <store-value value-field="originPp"/>
-    </simple-method>
-    <!--  -->
-</simple-methods>
diff --git a/framework/common/servicedef/services.xml 
b/framework/common/servicedef/services.xml
index 50a9724d7f..698610395d 100644
--- a/framework/common/servicedef/services.xml
+++ b/framework/common/servicedef/services.xml
@@ -259,9 +259,9 @@ under the License.
 
     <service name="performFindList" auth="false" engine="java" 
invoke="performFindList" location="org.apache.ofbiz.common.FindServices">
         <description>Generic service to return an partial list.  set 
filterByDate to Y to exclude expired records.
-            set noConditionFind to Y to find without conditions. 
-            If used in a form, it is necessary to assign a value (true makes 
sense) to override-list-size attribute so that 
-            FormRenderer.renderItemRows sets the lowIndex correctly, because 
once the results of performFindList are displayed, 
+            set noConditionFind to Y to find without conditions.
+            If used in a form, it is necessary to assign a value (true makes 
sense) to override-list-size attribute so that
+            FormRenderer.renderItemRows sets the lowIndex correctly, because 
once the results of performFindList are displayed,
             otherwise pages > 0 are rendered as empty. see OFBIZ-6422 + 6423 
for details</description>
         <attribute name="entityName" type="String" mode="IN" optional="false"/>
         <attribute name="inputFields" type="java.util.Map" mode="IN" 
optional="false"/>
@@ -340,7 +340,7 @@ under the License.
         <attribute name="conversionParameters" mode="IN" type="Map" 
optional="true"/>
         <attribute name="convertedValue" mode="OUT" type="BigDecimal" 
optional="true"/>
     </service>
-    
+
     <service name="checkUomConversion" engine="groovy" 
default-entity-name="UomConversion"
         
location="component://common/src/main/groovy/org/apache/ofbiz/common/CommonServicesScript.groovy"
 invoke="checkUomConversion">
         <description>Returns true if an UomConversion record 
exists</description>
@@ -348,7 +348,7 @@ under the License.
         <auto-attributes include="pk" mode="IN"/>
         <attribute name="exist" mode="OUT" type="Boolean"/>
     </service>
-    
+
     <service name="checkUomConversionDated" engine="groovy" 
default-entity-name="UomConversionDated"
         
location="component://common/src/main/groovy/org/apache/ofbiz/common/CommonServicesScript.groovy"
 invoke="checkUomConversionDated">
         <description>Returns true if an UomConversionDated record 
exists</description>
@@ -356,8 +356,8 @@ under the License.
         <auto-attributes include="pk" mode="IN"/>
         <attribute name="exist" mode="OUT" type="Boolean"/>
     </service>
-    
-    
+
+
     <service name="getFileUploadProgressStatus" engine="groovy" 
location="component://common/src/main/groovy/org/apache/ofbiz/common/CommonServicesScript.groovy"
 invoke="getFileUploadProgressStatus" auth="false">
         <description>Look up progress made in File Upload process</description>
         <attribute name="uploadProgressListener" mode="IN" 
type="org.apache.ofbiz.webapp.event.FileUploadProgressListener" 
optional="true"/>
@@ -513,7 +513,7 @@ under the License.
         <attribute name="userPrefTypeId" type="String" mode="IN" 
optional="false"/>
         <attribute name="userPrefLoginId" type="String" mode="IN" 
optional="true"/>
     </service>
-    
+
     <service name="setUserPreferenceGroup" engine="java"
             location="org.apache.ofbiz.common.preferences.PreferenceServices" 
invoke="setUserPreferenceGroup" auth="true">
         <description>Sets a group of user preferences.</description>
@@ -633,87 +633,94 @@ under the License.
     </service>
 
     <!-- Portal Page Portlet services -->
-    <service name="createPortalPagePortlet" 
default-entity-name="PortalPagePortlet" engine="simple" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="createPortalPagePortlet">
+    <service name="createPortalPagePortlet" 
default-entity-name="PortalPagePortlet" engine="groovy" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="createPortalPagePortlet">
         <description>Add a registered PortalPortlet to a 
PortalPage</description>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <override name="portletSeqId" mode="OUT" optional="true"/>
     </service>
     <service name="updatePortalPagePortlet" 
default-entity-name="PortalPagePortlet" engine="entity-auto" invoke="update" 
auth="true">
         <description>Update a PortalPortlet</description>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="deletePortalPagePortlet" 
default-entity-name="PortalPagePortlet" engine="simple" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="deletePortalPagePortlet">
+    <service name="deletePortalPagePortlet" 
default-entity-name="PortalPagePortlet" engine="groovy" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="deletePortalPagePortlet">
         <description>Delete a PortalPortlet from a PortalPage</description>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
     </service>
 
-    <service name="movePortletToPortalPage" 
default-entity-name="PortalPagePortlet" engine="simple" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="movePortletToPortalPage">
+    <service name="movePortletToPortalPage" 
default-entity-name="PortalPagePortlet" engine="groovy" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="movePortletToPortalPage">
+        <description>Move a PortalPortlet from the actual portalPage to a 
different one</description>
+        <attribute name="portalPageId" type="String" mode="IN"/>
+        <attribute name="portalPortletId" type="String" mode="IN"/>
+        <attribute name="portletSeqId" type="String" mode="IN"/>
+        <attribute name="newPortalPageId" type="String" mode="IN"/>
+    </service>
+    <service name="duplicatePortalPageDetails" engine="groovy" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="duplicatePortalPageDetails">
         <description>Move a PortalPortlet from the actual portalPage to a 
different one</description>
-        <attribute name="portalPageId" type="String" mode="IN" 
optional="false"/>
-        <attribute name="portalPortletId" type="String" mode="IN" 
optional="false"/>
-        <attribute name="portletSeqId" type="String" mode="IN" 
optional="false"/>
-        <attribute name="newPortalPageId" type="String" mode="IN" 
optional="false"/>
+        <attribute name="fromPortalPageId" type="String" mode="IN"/>
+        <attribute name="toPortalPageId" type="String" mode="IN"/>
     </service>
 
     <!-- Portal Page services -->
-    <service name="createPortalPage" default-entity-name="PortalPage" 
engine="simple" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="createPortalPage">
+    <service name="createPortalPage" default-entity-name="PortalPage" 
engine="entity-auto" auth="true" invoke="create">
         <description>Create a new Portal Page</description>
-        <auto-attributes include="pk" mode="INOUT" optional="true"/>
+        <auto-attributes include="pk" mode="IN" optional="true"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
+        <override name="portalPageName" mode="IN"/>
+        <override name="portalPageId" mode="OUT"/>
     </service>
     <service name="updatePortalPage" default-entity-name="PortalPage" 
engine="entity-auto" invoke="update" auth="true">
         <description>Update a Portal Page</description>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="deletePortalPage" default-entity-name="PortalPage" 
engine="simple" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="deletePortalPage">
+    <service name="deletePortalPage" default-entity-name="PortalPage" 
engine="groovy" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="deletePortalPage">
         <description>Delete a Portal Page, related colums and used 
portlets</description>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="updatePortalPageSeq" engine="simple" 
default-entity-name="PortalPage" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="updatePortalPageSeq">
+    <service name="updatePortalPageSeq" engine="groovy" 
default-entity-name="PortalPage" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="updatePortalPageSeq">
         <auto-attributes mode="IN" include="pk"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <attribute name="mode" type="String" mode="IN"/><!-- possible values: 
TOP, BOTTOM, UP, DOWN -->
     </service>
 
     <!-- PortalPageColumn services -->
-    <service name="addPortalPageColumn" default-entity-name="PortalPageColumn" 
engine="simple" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="addPortalPageColumn">
+    <service name="addPortalPageColumn" default-entity-name="PortalPageColumn" 
engine="groovy" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="addPortalPageColumn">
         <description>Add a new Column to a PortalPage</description>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <override name="columnSeqId" mode="INOUT" optional="true"/>
     </service>
     <service name="updatePortalPageColumn" 
default-entity-name="PortalPageColumn" engine="entity-auto" invoke="update" 
auth="true">
         <description>Update a Portal Page Column</description>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="deletePortalPageColumn" 
default-entity-name="PortalPageColumn" engine="simple" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="deletePortalPageColumn">
+    <service name="deletePortalPageColumn" 
default-entity-name="PortalPageColumn" engine="groovy" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="deletePortalPageColumn">
         <description>Delete a Column from a PortalPage</description>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
     </service>
 
     <!-- update Sequence No for Drag and Drop -->
-    <service name="updatePortletSeqDragDrop" engine="simple" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="updatePortletSeqDragDrop">
-        <attribute name="o_portalPageId" mode="IN" type="String" ></attribute>
-        <attribute name="o_portalPortletId" mode="IN" 
type="String"></attribute>
-        <attribute name="o_portletSeqId" mode="IN" type="String"></attribute>
+    <service name="updatePortletSeqDragDrop" engine="groovy" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="updatePortletSeqDragDrop">
+        <attribute name="o_portalPageId" mode="IN" type="String"/>
+        <attribute name="o_portalPortletId" mode="IN" type="String"/>
+        <attribute name="o_portletSeqId" mode="IN" type="String"/>
 
-        <attribute name="d_portalPageId" mode="IN" type="String" 
optional="true"></attribute>
-        <attribute name="d_portalPortletId" mode="IN" type="String" 
optional="true"></attribute>
-        <attribute name="d_portletSeqId" mode="IN" type="String" 
optional="true"></attribute>
+        <attribute name="d_portalPageId" mode="IN" type="String" 
optional="true"/>
+        <attribute name="d_portalPortletId" mode="IN" type="String" 
optional="true"/>
+        <attribute name="d_portletSeqId" mode="IN" type="String" 
optional="true"/>
 
         <attribute name="destinationColumn" mode="IN" optional="true" 
type="String"/>
         <attribute name="mode" type="String" mode="IN"/>
@@ -722,15 +729,15 @@ under the License.
     <!-- PortletAttribute services -->
     <service name="createPortletAttribute" 
default-entity-name="PortletAttribute" engine="entity-auto" invoke="create" 
auth="true">
         <description>Create a new Portlet Attribute</description>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="getPortletAttributes" engine="simple" auth="true"
-        location="component://common/minilang/PortalPageServices.xml" 
invoke="getPortletAttributes">
+    <service name="getPortletAttributes" engine="groovy" auth="true"
+        
location="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy"
 invoke="getPortletAttributes">
         <description>Get all attributes of a Portlet</description>
         <attribute name="portalPageId" type="String" mode="IN" 
optional="true"/>
         <attribute name="ownerUserLoginId" type="String" mode="IN" 
optional="true"/>
-        <attribute name="portalPortletId" type="String" mode="IN" 
optional="false"/>
+        <attribute name="portalPortletId" type="String" mode="IN"/>
         <attribute name="portletSeqId" type="String" mode="IN" 
optional="true"/>
         <attribute name="attributeMap" type="Map" mode="OUT" optional="true"/>
     </service>
@@ -785,7 +792,7 @@ under the License.
         <attribute name="listOrderBy" mode="IN" type="String" optional="true"/>
         <attribute name="stateList" mode="OUT" type="java.util.List"/>
     </service>
-    
+
     <!-- GeoPoint services -->
     <service name="createGeoPoint" default-entity-name="GeoPoint" 
engine="entity-auto" invoke="create" auth="true">
         <description>Create a GeoPoint</description>
@@ -810,22 +817,22 @@ under the License.
         <permission-service service-name="commonGenericPermission" 
main-action="DELETE"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
     </service>
-    
+
     <service name="getServerTimestamp" engine="groovy" auth="false"
         
location="component://common/src/main/groovy/org/apache/ofbiz/common/CommonServicesScript.groovy"
 invoke="getServerTimestamp">
         <attribute name="serverTimestamp" mode="OUT" type="Timestamp"/>
     </service>
-    
+
     <service name="getServerTimeZone" engine="groovy" auth="false"
         
location="component://common/src/main/groovy/org/apache/ofbiz/common/CommonServicesScript.groovy"
 invoke="getServerTimeZone">
         <attribute name="serverTimeZone" mode="OUT" type="String"/>
     </service>
-    
+
     <service name="getServerTimestampAsLong" engine="groovy" auth="false"
         
location="component://common/src/main/groovy/org/apache/ofbiz/common/CommonServicesScript.groovy"
 invoke="getServerTimestampAsLong">
         <attribute name="serverTimestamp" mode="OUT" type="Long"/>
     </service>
-    
+
     <service name="createJsLanguageFileMapping" engine="java" auth="false" 
use-transaction="false"
         location="org.apache.ofbiz.common.JsLanguageFileMappingCreator" 
invoke="createJsLanguageFileMapping">
         <description>Create or update the JsLanguageFilesMapping.java. You 
still need to compile thereafter</description>
diff --git 
a/framework/common/src/main/groovy/org/apache/ofbiz/common/PortalPageMethods.groovy
 
b/framework/common/src/main/groovy/org/apache/ofbiz/common/PortalPageMethods.groovy
new file mode 100644
index 0000000000..8a57d83f11
--- /dev/null
+++ 
b/framework/common/src/main/groovy/org/apache/ofbiz/common/PortalPageMethods.groovy
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*/
+package org.apache.ofbiz.common
+
+import org.apache.ofbiz.entity.GenericValue
+
+/** Duplicate content of portalPage, portalPageColumn, portalPagePortlet, 
portletAttribute,
+ *        this method should be call with portalpageId and portalPage in 
context-->
+ */
+String duplicatePortalPage() {
+    GenericValue portalPage = from('PortalPage').where(parameters).queryOne()
+    Map serviceResult = run service: 'createPortalPage', with: [*: 
portalPage.getAllFields(),
+                                                                portalPageId: 
null,
+                                                                
originalPortalPageId: parameters.portalPageId]
+    run service: 'duplicatePortalPageDetails', with: [fromPortalPageId: 
parameters.portalPageId,
+                                                      toPortalPageId: 
serviceResult.portalPageId]
+    request.setAttribute('portalPageId', serviceResult.portalPageId)
+    return success()
+}
+
+/**
+ * Sets a PortalPortlet attributes
+ */
+String setPortalPortletAttributes() {
+    if (parameters) {
+        delegator.removeByAnd('PortletAttribute', [portalPageId: 
parameters.portalPageId,
+                                                   portalPortletId: 
parameters.portalPortletId,
+                                                   portletSeqId: 
parameters.portletSeqId])
+        List skipField = ['portalPageId', 'portalPortletId', 'portletSeqId']
+        parameters.each {
+            if (skipField.contains(it.key)) {
+                return
+            }
+            GenericValue porletAttr = from('PortletAttribute')
+                    .where(portalPageId: parameters.portalPageId,
+                            portalPortletId: parameters.portalPortletId,
+                            portletSeqId: parameters.portletSeqId,
+                            attrName: it.key)
+                    .queryOne()
+            if (porletAttr) {
+                porletAttr.remove()
+            }
+            run service: 'createPortletAttribute', [*: parameters,
+                                                    attrName: it.key,
+                                                    attrValue: it.value]
+        }
+    }
+    return success()
+}
diff --git 
a/framework/common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy
 
b/framework/common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy
new file mode 100644
index 0000000000..6026ee3b52
--- /dev/null
+++ 
b/framework/common/src/main/groovy/org/apache/ofbiz/common/PortalPageServices.groovy
@@ -0,0 +1,370 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*/
+package org.apache.ofbiz.common
+
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.entity.condition.EntityCondition
+import org.apache.ofbiz.entity.condition.EntityConditionBuilder
+import org.apache.ofbiz.service.ServiceUtil
+
+/**
+ * Moves a PortalPortlet from the actual portalPage to a different one
+ * @return Success response
+ */
+Map movePortletToPortalPage() {
+    Map checkIsOwner = checkOwnerShip()
+    if (ServiceUtil.isError(checkIsOwner)) {
+        return checkIsOwner
+    }
+    GenericValue sourcePortalPagePortlet = 
from('PortalPagePortlet').where(parameters).cache().queryOne()
+    GenericValue targetPortalPortlet = makeValue('PortalPagePortlet', [*: 
parameters,
+                                                                       
portalPageId: copyIfRequiredSystemPage(),
+                                                                       
columnNum: 1])
+    delegator.setNextSubSeqId(targetPortalPortlet, 'portletSeqId', 5, 1)
+    targetPortalPortlet.create()
+    sourcePortalPagePortlet.remove()
+}
+
+/**
+ * Add a new Column to a PortalPage
+ * @return Success response with the columnSeqId created
+ */
+Map addPortalPageColumn() {
+    Map checkIsOwner = checkOwnerShip()
+    if (ServiceUtil.isError(checkIsOwner)) {
+        return checkIsOwner
+    }
+    GenericValue portalPageColumn = makeValue('PortalPageColumn', parameters)
+    if (!portalPageColumn.columnSeqId) {
+        delegator.setNextSubSeqId(portalPageColumn, 'columnSeqId', 5, 1)
+    }
+    portalPageColumn.create()
+    return success([columnSeqId: portalPageColumn.columnSeqId])
+}
+
+/**
+ * Delete a Column from a PortalPage
+ * @return Success response after delete
+ */
+Map deletePortalPageColumn() {
+    Map checkIsOwner = checkOwnerShip()
+    if (ServiceUtil.isError(checkIsOwner)) {
+        return checkIsOwner
+    }
+    GenericValue column = from('PortalPageColumn').where(parameters).queryOne()
+    column.getRelated('PortalPagePortlet', null, null, false).each {
+        run service: 'deletePortalPagePortlet', with: it.getAllFields()
+    }
+    column.remove()
+    return success()
+}
+/**
+ * Add a registered PortalPortlet to a PortalPage
+ * @return Success response with the portletSeqId created
+ */
+Map createPortalPagePortlet() {
+    Map checkIsOwner = checkOwnerShip()
+    if (ServiceUtil.isError(checkIsOwner)) {
+        return checkIsOwner
+    }
+    GenericValue portalPagePortlet = makeValue('PortalPagePortlet', parameters)
+    GenericValue lastPortalPagePortlet = from('PortalPagePortlet')
+            .where(portalPageId: parameters.portalPageId)
+            .orderBy('-sequenceNum')
+            .queryFirst()
+    portalPagePortlet.sequenceNum = lastPortalPagePortlet ? 
lastPortalPagePortlet.sequenceNum + 1 : 1
+    delegator.setNextSubSeqId(portalPagePortlet, 'portletSeqId', 5, 1)
+    portalPagePortlet.create()
+    return success([portletSeqId: portalPagePortlet.portletSeqId])
+}
+
+/**
+ * Delete a PortalPortlet from a PortalPageColumn
+ * @return Success response after delete
+ */
+Map deletePortalPagePortlet() {
+    Map checkIsOwner = checkOwnerShip()
+    if (ServiceUtil.isError(checkIsOwner)) {
+        return checkIsOwner
+    }
+    GenericValue portalPagePortlet = 
from('PortalPagePortlet').where(parameters).queryOne()
+    if (portalPagePortlet) {
+        delegator.removeByAnd('PortletAttribute', [portalPageId: 
portalPagePortlet.portalPageId,
+                                                   portalPortletId: 
portalPagePortlet.portalPortletId,
+                                                   portletSeqId: 
portalPagePortlet.portletSeqId])
+        portalPagePortlet.remove()
+    }
+    return success()
+}
+
+/**
+ * Get all attributes of a Portlet either by providing userLogin or 
portalPageId with portalPortletId
+ * @return Success response with all attributes
+ */
+Map getPortletAttributes() {
+    if (!parameters.ownerUserLoginId && !parameters.portalPageId) {
+        return error('Service getPortletAttributes did not receive either 
ownerUserLoginId OR portalPageId')
+    }
+    if (parameters.ownerUserLoginId) {
+        GenericValue portalPagePortlet = from('PortalPageAndPortlet')
+                .where(ownerUserLoginId: parameters.ownerUserLoginId,
+                        portalPortletId: parameters.portalPortletId)
+                .queryFirst()
+        parameters.portalPageId = portalPagePortlet.portalPageId
+    }
+    EntityCondition condition = new EntityConditionBuilder().AND {
+        EQUALS(portalPageId: parameters.portalPageId)
+        EQUALS(portalPortletId: parameters.portalPortletId)
+        if (parameters.portletSeqId) {
+            EQUALS(portletSeqId: parameters.portletSeqId)
+        }
+    }
+    Map attributeMap = [:]
+    from ('PortletAttribute')
+            .where(condition)
+            .queryList()
+            .each {
+                    attributeMap.(it.attrName) = it.attrValue
+            }
+    return success([attributeMap: attributeMap])
+}
+
+/**
+ * Create a new Portal Page
+ * @return Success response after creation with the portalPageId
+ */
+Map createPortalPage() {
+    GenericValue newPortalPage = makeValue('PortalPage', parameters)
+    newPortalPage.portalPageId = newPortalPage.portalPageId ?: 
delegator.getNextSeqId('PortalPage')
+    newPortalPage.ownerUserLoginId = parameters.userLogin.userLoginId
+    if (! newPortalPage.sequenceNum) {
+        delegator.setNextSubSeqId(newPortalPage, 'sequenceNum', 5, 1)
+    }
+    newPortalPage.create()
+    return success([portalPageId: newPortalPage.portalPageId])
+}
+
+/**
+ * Delete a new Portal Page
+ * @return Success response after delete
+ */
+Map deletePortalPage() {
+    Map checkIsOwner = checkOwnerShip()
+    if (ServiceUtil.isError(checkIsOwner)) {
+        return checkIsOwner
+    }
+    GenericValue portalPage = from('PortalPage').where(parameters).queryOne()
+    if (portalPage.originalPortalPageId) {
+        GenericValue originalPortalPage = 
from('PortalPage').where(portalPageId: 
portalPage.originalPortalPageId).cache().queryOne()
+        GenericValue portalPageToUpdate = from('PortalPage')
+                .where(sequenceNum: originalPortalPage.sequenceNum,
+                        ownerUserLoginId: userLogin.userLoginId,
+                        parentPortalPageId: parameters.parentPortalPageId)
+                .queryFirst()
+        if (portalPageToUpdate) {
+            run service: 'updatePortalPage', with: [*: 
portalPageToUpdate.getAllFields(),
+                                                    portalPageId: 
portalPageToUpdate.portalPageId,
+                                                    sequenceNum: 
portalPage.sequenceNum]
+        }
+    }
+    portalPage.removeRelated('PortalPageColumn')
+    portalPage.removeRelated('PortalPagePortlet')
+    portalPage.remove()
+    return success()
+}
+
+/**
+ * Update the portal page sequence numbers
+ * @return Success response after update
+ */
+Map updatePortalPageSeq() {
+    Map checkIsOwner = checkOwnerShip()
+    if (ServiceUtil.isError(checkIsOwner)) {
+        return checkIsOwner
+    }
+    GenericValue portalPage = from('PortalPage').where(parameters).queryOne()
+    String mode = parameters.mode
+    String orderBy = (['UP', 'BOT'].contains(mode) ? '-' : '') + 'sequenceNum'
+    EntityCondition condition = new EntityConditionBuilder().AND {
+        EQUALS(ownerUserLoginId: userLogin.userLoginId)
+        if (['UP', 'TOP'].contains(mode)) {
+            LESS_THAN(sequenceNum: portalPage.sequenceNum)
+        } else {
+            GREATER_THAN(sequenceNum: portalPage.sequenceNum)
+        }
+        EQUALS(ownerUserLoginId: userLogin.userLoginId)
+        OR {
+            EQUALS(parentPortalPageId: parameters.parentPortalPageId)
+            EQUALS(originalPortalPageId: parameters.parentPortalPageId)
+        }
+    }
+    GenericValue updatePortalPage = 
from('PortalPage').where(condition).orderBy(orderBy).queryFirst()
+
+    if (updatePortalPage) {
+        Long previousSequenceNum = portalPage.sequenceNum
+        portalPage.sequenceNum = updatePortalPage.sequenceNum
+        portalPage.store()
+        run service: 'updatePortalPage', with: [*: 
updatePortalPage.getAllFields(),
+                                                sequenceNum: 
previousSequenceNum]
+    }
+    return success()
+}
+
+/**
+ * Updates a portlet Seq No for the Drag and Drop Feature
+ * @return Success response after move
+ */
+Map updatePortletSeqDragDrop() {
+    Map checkIsOwner = checkOwnerShip()
+    if (ServiceUtil.isError(checkIsOwner)) {
+        return checkIsOwner
+    }
+    // update Portlet Seq with Drag & Drop
+    parameters.portalPageId = parameters.o_portalPageId
+    GenericValue originPp = from('PortalPagePortlet')
+            .where(portalPageId: parameters.o_portalPageId,
+                    portalPortletId: parameters.o_portalPortletId,
+                    portletSeqId: parameters.o_portletSeqId)
+            .queryOne()
+    if (!originPp) {
+        return error('')
+    }
+    String columnSeqId = parameters.destinationColumn ?: originPp.columnSeqId
+    GenericValue destiPp = from('PortalPagePortlet')
+            .where(portalPageId: parameters.d_portalPageId,
+                    portalPortletId: parameters.d_portalPortletId,
+                    portletSeqId: parameters.d_portletSeqId)
+            .queryOne()
+
+    int newSequenceNo = 0
+    if (parameters.mode != 'NEW') {
+        EntityCondition condition = new EntityConditionBuilder().AND {
+            EQUALS(portalPageId: parameters.portalPageId)
+            EQUALS(columnSeqId: columnSeqId)
+            if (parameters.mode == 'DRAGDROPBEFORE') {
+                GREATER_THAN_EQUAL_TO(sequenceNum: destiPp.sequenceNum)
+                if (originPp.sequenceNum) {
+                    LESS_THAN(sequenceNum: originPp.sequenceNum)
+                }
+            } else {
+                GREATER_THAN_EQUAL_TO(sequenceNum: originPp.sequenceNum)
+                if (destiPp.sequenceNum) {
+                    LESS_THAN(sequenceNum: destiPp.sequenceNum)
+                }
+            }
+        }
+
+        newSequenceNo = destiPp.sequenceNum
+        int increase = parameters.mode == 'DRAGDROPBEFORE' ? 1 : -1
+        from('PortalPagePortlet')
+                .where(condition)
+                .orderBy((parameters.mode == 'DRAGDROPBEFORE' ? '' : '-') + 
'sequenceNum')
+                .queryList()
+                .each {
+                    if (it.sequenceNum) {
+                        it.sequenceNum = it.sequenceNum + increase
+                        increase += increase
+                    } else {
+                        it.sequenceNum = newSequenceNo
+                    }
+                    it.store()
+                }
+    }
+    originPp.columnSeqId = columnSeqId
+    originPp.sequenceNum = newSequenceNo
+    originPp.store()
+    return success()
+}
+
+/**
+ * Duplicate content of portalPage, portalPageColumn, portalPagePortlet, 
portletAttribute,
+ * this method should be call with parameters.toPortalPageId and portalPage in 
context
+ * @return Success response
+ */
+Map duplicatePortalPageDetails() {
+    logInfo("duplicate portalPage detail from parameters.toPortalPageId 
${parameters.fromPortalPageId}" +
+            " to new portalPageId=${parameters.toPortalPageId}")
+    if (parameters.toPortalPageId) {
+        from('PortalPageColumn')
+                .where(portalPageId: parameters.fromPortalPageId)
+                .queryList()
+                .each {
+                    run service: 'addPortalPageColumn', with: [*: 
it.getAllFields(),
+                                                               portalPageId: 
parameters.toPortalPageId]
+                }
+        from('PortalPagePortlet')
+                .where(portalPageId: parameters.fromPortalPageId)
+                .queryList()
+                .each {
+                    run service: 'createPortalPagePortlet', with: [*: 
it.getAllFields(),
+                                                                   
portalPageId: parameters.toPortalPageId]
+                    from('PortletAttribute')
+                            .where(portalPageId: parameters.fromPortalPageId,
+                                    portalPortletId: it.portalPortletId,
+                                    portletSeqId: it.portletSeqId)
+                            .queryList()
+                            .each { attr ->
+                                attr.portalPageId = parameters.toPortalPageId
+                                attr.create()
+                            }
+                }
+    }
+    return success()
+}
+
+/**
+ * Check the ownership of a Portal Page
+ */
+private Map checkOwnerShip() {
+    if (!parameters.portalPageId) {
+        return [:]
+    }
+    GenericValue portalPage = 
from('PortalPage').where(parameters).cache().queryOne()
+    if (!portalPage) {
+        return error(label('CommonUiLabels', 'PortalPageNotFound', parameters))
+    }
+
+    // only page owner or user with MYPORTALBASE_ADMIN can modify the page 
detail
+    if (portalPage.ownerUserLoginId != userLogin.userLoginId &&
+            !security.hasPermission('MYPORTALBASE_ADMIN', userLogin)) {
+        return error(label('CommonUiLabels', 'PortalPageNotOwned', portalPage))
+    }
+    return success()
+}
+
+/**
+ * Check if the page is a system page, then copy before allowing
+ */
+private String copyIfRequiredSystemPage() {
+    GenericValue portalPage = 
from('PortalPage').where(parameters).cache().queryOne()
+    Map serviceResult = [:]
+    if (portalPage && portalPage.ownerUserLoginId == '_NA_' && 
from('PortalPage')
+            .where(originalPortalPageId: parameters.portalPageId,
+                    ownerUserLoginId: userLogin.userLoginId)
+            .queryCount() == 0 ) {
+        // copy the portal page
+        serviceResult = run service: 'createPortalPage', with: [*: 
portalPage.getAllFields(),
+                                                                portalPageId: 
null,
+                                                                
originalPortalPageId: portalPage.portalPageId,
+                                                                
ownerUserLoginId: userLogin.userLoginId]
+        run service: 'duplicatePortalPageDetails', with: [fromPortalPageId: 
parameters.portalPageId,
+                                                          toPortalPageId: 
serviceResult.portalPageId]
+    }
+    return serviceResult ? serviceResult.portalPageId : 
portalPage?.portalPageId
+}
diff --git a/framework/common/webcommon/WEB-INF/portal-controller.xml 
b/framework/common/webcommon/WEB-INF/portal-controller.xml
index ee475db2e7..196c5e74ac 100644
--- a/framework/common/webcommon/WEB-INF/portal-controller.xml
+++ b/framework/common/webcommon/WEB-INF/portal-controller.xml
@@ -45,7 +45,7 @@ under the License.
     </request-map>
     <request-map uri="setPortalPortletAttributes">
         <security https="true" auth="true"/>
-        <event type="simple" invoke="setPortalPortletAttributes" 
path="component://common/minilang/PortalPageMethods.xml"/>
+        <event type="groovy" invoke="setPortalPortletAttributes" 
path="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageMethods.groovy"/>
         <response name="success" type="view-last" value="main"/>
         <response name="error" type="request" value="main"/>
     </request-map>
@@ -57,7 +57,7 @@ under the License.
     <!-- Portal page update requests -->
     <request-map uri="ManagePortalPages">
         <security https="true" auth="true"/>
-        <event  type="simple" invoke="copyIfRequiredSystemPage" 
path="component://common/minilang/PortalPageMethods.xml"/>
+        <event  type="groovy" invoke="copyIfRequiredSystemPage" 
path="component://common/src/main/groovy/org/apache/ofbiz/common/PortalPageMethods.groovy"/>
         <response name="success" type="view" value="ManagePortalPages"/>
     </request-map>
     <request-map uri="NewPortalPage">

Reply via email to