[ofbiz-framework] branch trunk updated: Improved: Convert ProductContentServices.xml mini lang to groovy (OFBIZ-11436)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[ofbiz-framework] branch trunk updated: Improved: Convert ProductContentServices.xml mini lang to groovy (OFBIZ-11436)

nmalin
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 43b44f5  Improved: Convert ProductContentServices.xml mini lang to groovy (OFBIZ-11436)
43b44f5 is described below

commit 43b44f53e0897935a194db7c1ee56f2ebcbd8300
Author: Nicolas Malin <[hidden email]>
AuthorDate: Tue Mar 10 09:32:37 2020 +0100

    Improved: Convert ProductContentServices.xml mini lang to groovy
    (OFBIZ-11436)
   
    Thanks to Sebastian Berg for providing the patch
---
 .../product/product/ProductContentServices.groovy  | 215 +++++++++++++++++++
 .../product/product/ProductContentServices.xml     | 238 ---------------------
 applications/product/servicedef/services.xml       |  84 ++++----
 3 files changed, 252 insertions(+), 285 deletions(-)

diff --git a/applications/product/groovyScripts/product/product/ProductContentServices.groovy b/applications/product/groovyScripts/product/product/ProductContentServices.groovy
new file mode 100644
index 0000000..ee69514
--- /dev/null
+++ b/applications/product/groovyScripts/product/product/ProductContentServices.groovy
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ */
+
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.service.ServiceUtil
+
+/**
+ * Create Content For Product
+ * @return
+ */
+def createProductContent() {
+    Map result = success()
+    GenericValue newEntity = makeValue("ProductContent", parameters)
+    newEntity.create()
+    run service: "updateContent", with: parameters
+    result.contentId = newEntity.contentId
+    result.productId = newEntity.productId
+    result.productContentTypeId = newEntity.productContentTypeId
+    return result
+}
+
+/**
+ * Update Content For Product
+ * @return
+ */
+def updateProductContent() {
+    GenericValue lookedUpValue = from("ProductContent").where(parameters).queryOne()
+    lookedUpValue.setNonPKFields(parameters)
+    lookedUpValue.store()
+    run service: "updateContent", with: parameters
+    return success()
+}
+
+/**
+ * Create Email Content For Product
+ * @return
+ */
+def createEmailContentForProduct() {
+    Map result = success()
+    Map createProductContent = parameters
+    Map serviceResult = run service: "createEmailContent", with: parameters
+    if (!ServiceUtil.isSuccess(serviceResult)) {
+        return serviceResult
+    }
+    createProductContent.contentId = serviceResult.contentId
+    run service: "createProductContent", with: createProductContent
+    return result
+}
+
+/**
+ * Create Download Content For Product
+ * @return
+ */
+def createDownloadContentForProduct() {
+    Map createProductContent = parameters
+    Map persistContentAndAssoc = parameters
+    persistContentAndAssoc.contentTypeId = "DOCUMENT"
+    persistContentAndAssoc.dataResourceTypeId = "IMAGE_OBJECT"
+    persistContentAndAssoc.contentName = parameters._imageData_fileName
+    persistContentAndAssoc.mimeTypeId = parameters._imageData_contentType
+    
+    Map serviceResult = run service: "persistContentAndAssoc", with: persistContentAndAssoc
+    if (!ServiceUtil.isSuccess(serviceResult)) {
+        return serviceResult
+    }
+    createProductContent.contentId = serviceResult.contentId
+    run service: "createProductContent", with: createProductContent
+    return success()
+}
+
+
+/**
+ * Create Simple Text Content For Product
+ * @return
+ */
+def createSimpleTextContentForProduct() {
+    Map serviceResult = run service: "createSimpleTextContent", with: parameters
+    Map createProductContentMap = parameters
+    createProductContentMap.contentId = serviceResult.contentId
+    run service: "createProductContent", with: createProductContentMap
+    return success()
+}
+
+/**
+ * Create Simple Text Content For Alternate Locale
+ * @return
+ */
+def createSimpleTextContentForAlternateLocale() {
+    Map serviceResult = run service: "createSimpleTextContent", with: parameters
+    Map createContentAssocMap = [contentIdTo: serviceResult.contentId,
+                                 contentId: parameters.mainContentId,
+                                 contentAssocTypeId: "ALTERNATE_LOCALE"]
+    run service: "createContentAssoc", with: createContentAssocMap
+    return success()
+}
+
+/**
+ * Method to upload multiple Additional View images for product
+ * @return
+ */
+def uploadProductAdditionalViewImages() {
+    Map result = success()
+    Map addAdditionalViewForProductMap = [productId: parameters.productId]
+    if (parameters.additionalImageOne) {
+        addAdditionalViewForProductMap.uploadedFile = parameters.additionalImageOne
+        addAdditionalViewForProductMap.productContentTypeId = "ADDITIONAL_IMAGE_1"
+        addAdditionalViewForProductMap._uploadedFile_fileName = parameters._additionalImageOne_contentType
+        run service: "addAdditionalViewForProduct", with: addAdditionalViewForProductMap
+    }
+    if (parameters.additionalImageTwo) {
+        addAdditionalViewForProductMap.uploadedFile = parameters.additionalImageTwo
+        addAdditionalViewForProductMap.productContentTypeId = "ADDITIONAL_IMAGE_2"
+        addAdditionalViewForProductMap._uploadedFile_fileName = parameters._additionalImageTwo_contentType
+        run service: "addAdditionalViewForProduct", with: addAdditionalViewForProductMap
+    }
+    if (parameters.additionalImageThree) {
+        addAdditionalViewForProductMap.uploadedFile = parameters.additionalImageThree
+        addAdditionalViewForProductMap.productContentTypeId = "ADDITIONAL_IMAGE_3"
+        addAdditionalViewForProductMap._uploadedFile_fileName = parameters._additionalImageThree_contentType
+        run service: "addAdditionalViewForProduct", with: addAdditionalViewForProductMap
+    }
+    if (parameters.additionalImageFour) {
+        addAdditionalViewForProductMap.uploadedFile = parameters.additionalImageFour
+        addAdditionalViewForProductMap.productContentTypeId = "ADDITIONAL_IMAGE_4"
+        addAdditionalViewForProductMap._uploadedFile_fileName = parameters._additionalImageFour_contentType
+        run service: "addAdditionalViewForProduct", with: addAdditionalViewForProductMap
+    }
+    result.productId = parameters.productId
+    return result
+}
+
+/**
+ * Update Product SEO
+ * @return
+ */
+def updateContentSEOForProduct() {
+    GenericValue productContent
+    if (parameters.title) {
+        productContent = from("ProductContentAndInfo")
+                .where(productId: parameters.productId,
+                        productContentTypeId: "PAGE_TITLE")
+                .queryFirst()
+        if (productContent) {
+            GenericValue electronicText = from("ElectronicText")
+                    .where(dataResourceId: productContent.dataResourceId)
+                    .queryOne()
+            if (electronicText) {
+                electronicText.textData = parameters.title
+                electronicText.store()
+            }
+        } else {
+            Map createTextContentMap = [productId: parameters.productId,
+                                        productContentTypeId: "PAGE_TITLE",
+                                        text: parameters.title]
+            run service: "createSimpleTextContentForProduct", with: createTextContentMap
+        }
+    }
+    if (parameters.metaKeyword) {
+        productContent = from("ProductContentAndInfo")
+                .where(productId: parameters.productId,
+                        productContentTypeId: "META_KEYWORD")
+                .queryFirst()
+        if (productContent) {
+            GenericValue electronicText = from("ElectronicText")
+                    .where(dataResourceId: productContent.dataResourceId)
+                    .queryOne()
+            if (electronicText) {
+                electronicText.textData = parameters.metaKeyword
+                electronicText.store()
+            }
+        } else {
+            Map createTextContentMap = [productId: parameters.productId,
+                                        productContentTypeId: "META_KEYWORD",
+                                        text: parameters.metaKeyword]
+            run service: "createSimpleTextContentForProduct", with: createTextContentMap
+        }
+    }
+    if (parameters.metaDescription) {
+        productContent = from("ProductContentAndInfo")
+                .where(productId: parameters.productId,
+                        productContentTypeId: "META_DESCRIPTION")
+                .queryFirst()
+        if (productContent) {
+            GenericValue electronicText = from("ElectronicText")
+                    .where(dataResourceId: productContent.dataResourceId)
+                    .queryOne()
+            if (electronicText) {
+                electronicText.textData = parameters.metaDescription
+                electronicText.store()
+            }
+        } else {
+            Map createTextContentMap = [productId: parameters.productId,
+                                        productContentTypeId: "META_DESCRIPTION",
+                                        text: parameters.metaDescription]
+            run service: "createSimpleTextContentForProduct", with: createTextContentMap
+        }
+    }
+    return success()
+}
diff --git a/applications/product/minilang/product/product/ProductContentServices.xml b/applications/product/minilang/product/product/ProductContentServices.xml
deleted file mode 100644
index 141d6c6..0000000
--- a/applications/product/minilang/product/product/ProductContentServices.xml
+++ /dev/null
@@ -1,238 +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">
-    <!-- ProductContent -->
-    <simple-method method-name="createProductContent" short-description="Create Content For Product">
-        <make-value entity-name="ProductContent" value-field="newEntity"/>
-        <set-pk-fields map="parameters" value-field="newEntity"/>
-        <set-nonpk-fields map="parameters" value-field="newEntity"/>
-
-        <if-empty field="newEntity.fromDate">
-            <now-timestamp field="nowTimestamp"/>
-            <set field="newEntity.fromDate" from-field="nowTimestamp"/>
-        </if-empty>
-
-        <create-value value-field="newEntity"/>
-
-        <set-service-fields service-name="updateContent" map="parameters" to-map="updateContent"/>
-        <call-service service-name="updateContent" in-map-name="updateContent"/>
-
-        <field-to-result field="newEntity.contentId" result-name="contentId"/>
-        <field-to-result field="newEntity.productId" result-name="productId"/>
-        <field-to-result field="newEntity.productContentTypeId" result-name="productContentTypeId"/>
-    </simple-method>
-    <simple-method method-name="updateProductContent" short-description="Update Content For Product">
-        <make-value entity-name="ProductContent" value-field="lookupPKMap"/>
-        <set-pk-fields map="parameters" value-field="lookupPKMap"/>
-        <find-by-primary-key map="lookupPKMap" value-field="lookedUpValue"/>
-        <set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
-        <store-value value-field="lookedUpValue"/>
-
-        <set-service-fields service-name="updateContent" map="parameters" to-map="updateContent"/>
-        <call-service service-name="updateContent" in-map-name="updateContent"/>
-    </simple-method>
-    <simple-method method-name="removeProductContent" short-description="Remove Content From Product">
-        <make-value entity-name="ProductContent" value-field="lookupPKMap"/>
-        <set-pk-fields map="parameters" value-field="lookupPKMap"/>
-        <find-by-primary-key map="lookupPKMap" value-field="lookedUpValue"/>
-        <remove-value value-field="lookedUpValue"/>
-    </simple-method>
-
-    <!-- Specialized -->
-    <simple-method method-name="createEmailContentForProduct" short-description="Create Email Content For Product">
-        <set-service-fields service-name="createProductContent" map="parameters" to-map="createProductContent"/>
-        <set-service-fields service-name="createEmailContent" map="parameters" to-map="createEmail"/>
-        <call-service service-name="createEmailContent" in-map-name="createEmail" break-on-error="true" >
-            <result-to-field result-name="contentId" field="createProductContent.contentId"/>
-        </call-service>
-        <call-service service-name="createProductContent" in-map-name="createProductContent"/>
-    </simple-method>
-    <simple-method method-name="updateEmailContentForProduct" short-description="Update Email Content For Product">
-        <set-service-fields service-name="updateProductContent" map="parameters" to-map="updateProductContent"/>
-        <call-service service-name="updateProductContent" in-map-name="updateProductContent"/>
-        <set-service-fields service-name="updateEmailContent" map="parameters" to-map="updateEmail"/>
-        <call-service service-name="updateEmailContent" in-map-name="updateEmail"/>
-    </simple-method>
-
-    <simple-method method-name="createDownloadContentForProduct" short-description="Create Download Content For Product">
-        <set-service-fields service-name="createProductContent" map="parameters" to-map="createProductContent"/>
-        <set-service-fields service-name="persistContentAndAssoc" map="parameters" to-map="persistContentAndAssoc"/>
-        <set field="persistContentAndAssoc.contentTypeId" value="DOCUMENT"/>
-        <set field="persistContentAndAssoc.dataResourceTypeId" value="IMAGE_OBJECT"/>
-        <set field="persistContentAndAssoc.contentName" from-field="parameters._imageData_fileName"/>
-        <set field="persistContentAndAssoc.mimeTypeId" from-field="parameters._imageData_contentType"/>
-        <call-service service-name="persistContentAndAssoc" in-map-name="persistContentAndAssoc" break-on-error="true" >
-            <result-to-field result-name="contentId" field="createProductContent.contentId"/>
-        </call-service>
-        <call-service service-name="createProductContent" in-map-name="createProductContent"/>
-    </simple-method>
-    <simple-method method-name="updateDownloadContentForProduct" short-description="Update Email Content For Product">
-        <set-service-fields service-name="updateProductContent" map="parameters" to-map="updateProductContent"/>
-        <call-service service-name="updateProductContent" in-map-name="updateProductContent"/>
-        <set-service-fields service-name="updateDownloadContent" map="parameters" to-map="updateDownload"/>
-        <call-service service-name="updateDownloadContent" in-map-name="updateDownload"/>
-    </simple-method>
-
-    <simple-method method-name="createSimpleTextContentForProduct" short-description="Create Simple Text Content For Product">
-        <set-service-fields service-name="createProductContent" map="parameters" to-map="createProductContentMap"/>
-        <set-service-fields service-name="createSimpleTextContent" map="parameters" to-map="createSimpleTextMap"/>
-        <call-service service-name="createSimpleTextContent" in-map-name="createSimpleTextMap">
-            <result-to-field result-name="contentId" field="createProductContentMap.contentId"/>
-        </call-service>
-        <call-service service-name="createProductContent" in-map-name="createProductContentMap"/>
-    </simple-method>
-    <simple-method method-name="updateSimpleTextContentForProduct" short-description="Update Simple Text Content For Product">
-        <set-service-fields service-name="updateProductContent" map="parameters" to-map="updateProductContent"/>
-        <call-service service-name="updateProductContent" in-map-name="updateProductContent"/>
-        <set-service-fields service-name="updateSimpleTextContent" map="parameters" to-map="updateSimpleText"/>
-        <call-service service-name="updateSimpleTextContent" in-map-name="updateSimpleText"/>
-    </simple-method>
-    <simple-method method-name="createSimpleTextContentForAlternateLocale" short-description="Create Simple Text Content For Alternate Locale">
-        <set-service-fields service-name="createSimpleTextContent" map="parameters" to-map="createSimpleTextMap"/>
-        <call-service service-name="createSimpleTextContent" in-map-name="createSimpleTextMap">
-            <result-to-field result-name="contentId" field="createContentAssocMap.contentIdTo"/>
-        </call-service>
-        <set field="createContentAssocMap.contentId" from-field="parameters.mainContentId"/>
-        <set field="createContentAssocMap.contentAssocTypeId" value="ALTERNATE_LOCALE"/>
-        <call-service service-name="createContentAssoc" in-map-name="createContentAssocMap"/>
-    </simple-method>
-
-    <simple-method method-name="uploadProductAdditionalViewImages" short-description="Method to upload multiple Additional View images for product">
-        <set-service-fields service-name="addAdditionalViewForProduct" map="parameters" to-map="addAdditionalViewForProductMap"/>
-        <if-not-empty field="parameters.additionalImageOne">
-            <set field="addAdditionalViewForProductMap.productId" from-field="parameters.productId"/>
-            <set field="addAdditionalViewForProductMap.uploadedFile" from-field="parameters.additionalImageOne"/>
-            <set field="addAdditionalViewForProductMap.productContentTypeId" value="ADDITIONAL_IMAGE_1"/>
-            <set field="addAdditionalViewForProductMap._uploadedFile_fileName" from-field="parameters._additionalImageOne_fileName"/>
-            <set field="addAdditionalViewForProductMap._uploadedFile_contentType" from-field="parameters._additionalImageOne_contentType"/>
-            <call-service service-name="addAdditionalViewForProduct" in-map-name="addAdditionalViewForProductMap"/>
-            <clear-field field="addAdditionalViewForProductMap"/>
-        </if-not-empty>
-        <if-not-empty field="parameters.additionalImageTwo">
-            <set field="addAdditionalViewForProductMap.productId" from-field="parameters.productId"/>
-            <set field="addAdditionalViewForProductMap.uploadedFile" from-field="parameters.additionalImageTwo"/>
-            <set field="addAdditionalViewForProductMap.productContentTypeId" value="ADDITIONAL_IMAGE_2"/>
-            <set field="addAdditionalViewForProductMap._uploadedFile_fileName" from-field="parameters._additionalImageTwo_fileName"/>
-            <set field="addAdditionalViewForProductMap._uploadedFile_contentType" from-field="parameters._additionalImageTwo_contentType"/>
-            <call-service service-name="addAdditionalViewForProduct" in-map-name="addAdditionalViewForProductMap"/>
-            <clear-field field="addAdditionalViewForProductMap"/>
-        </if-not-empty>
-        <if-not-empty field="parameters.additionalImageThree">
-            <set field="addAdditionalViewForProductMap.productId" from-field="parameters.productId"/>
-            <set field="addAdditionalViewForProductMap.uploadedFile" from-field="parameters.additionalImageThree"/>
-            <set field="addAdditionalViewForProductMap.productContentTypeId" value="ADDITIONAL_IMAGE_3"/>
-            <set field="addAdditionalViewForProductMap._uploadedFile_fileName" from-field="parameters._additionalImageThree_fileName"/>
-            <set field="addAdditionalViewForProductMap._uploadedFile_contentType" from-field="parameters._additionalImageThree_contentType"/>
-            <call-service service-name="addAdditionalViewForProduct" in-map-name="addAdditionalViewForProductMap"/>
-            <clear-field field="addAdditionalViewForProductMap"/>
-        </if-not-empty>
-        <if-not-empty field="parameters.additionalImageFour">
-            <set field="addAdditionalViewForProductMap.productId" from-field="parameters.productId"/>
-            <set field="addAdditionalViewForProductMap.uploadedFile" from-field="parameters.additionalImageFour"/>
-            <set field="addAdditionalViewForProductMap.productContentTypeId" value="ADDITIONAL_IMAGE_4"/>
-            <set field="addAdditionalViewForProductMap._uploadedFile_fileName" from-field="parameters._additionalImageFour_fileName"/>
-            <set field="addAdditionalViewForProductMap._uploadedFile_contentType" from-field="parameters._additionalImageFour_contentType"/>
-            <call-service service-name="addAdditionalViewForProduct" in-map-name="addAdditionalViewForProductMap"/>
-            <clear-field field="addAdditionalViewForProductMap"/>
-        </if-not-empty>
-        <field-to-result field="parameters.productId" result-name="productId"/>
-    </simple-method>
-
-    <!-- ProductPromoContent -->
-    <simple-method method-name="removeProductPromoContent" short-description="Remove Content From Product Promo">
-        <set-service-fields service-name="updateProductPromoContent" map="parameters" to-map="updateProductPromoContentMap"/>
-        <if-empty field="updateProductPromoContentMap.thruDate">
-            <now-timestamp field="updateProductPromoContentMap.thruDate"/>
-        </if-empty>
-        <call-service service-name="updateProductPromoContent" in-map-name="updateProductPromoContentMap"/>
-    </simple-method>
-
-    <!-- Product Content SEO -->
-    <simple-method method-name="updateContentSEOForProduct" short-description="Update Product SEO">
-        <if-not-empty field="parameters.title">
-            <entity-and entity-name="ProductContentAndInfo" list="productContents">
-                <field-map field-name="productId" from-field="parameters.productId"/>
-                <field-map field-name="productContentTypeId" value="PAGE_TITLE"/>
-            </entity-and>
-            <if-not-empty field="productContents">
-                <first-from-list entry="productContent" list="productContents"/>
-                <entity-one entity-name="ElectronicText" value-field="electronicText">
-                    <field-map field-name="dataResourceId" from-field="productContent.dataResourceId"/>
-                </entity-one>
-                <if-not-empty field="electronicText">
-                    <set field="electronicText.textData" from-field="parameters.title"/>
-                    <store-value value-field="electronicText"/>
-                </if-not-empty>
-            <else>
-                <set field="createTextContentMap.productId" from-field="parameters.productId"/>
-                <set field="createTextContentMap.productContentTypeId" value="PAGE_TITLE"/>
-                <set field="createTextContentMap.text" from-field="parameters.title"/>
-                <call-service service-name="createSimpleTextContentForProduct" in-map-name="createTextContentMap"/>
-            </else>
-            </if-not-empty>
-        </if-not-empty>
-        <if-not-empty field="parameters.metaKeyword">
-            <entity-and entity-name="ProductContentAndInfo" list="productContents">
-                <field-map field-name="productId" from-field="parameters.productId"/>
-                <field-map field-name="productContentTypeId" value="META_KEYWORD"/>
-            </entity-and>
-            <if-not-empty field="productContents">
-                <first-from-list entry="productContent" list="productContents"/>
-                <entity-one entity-name="ElectronicText" value-field="electronicText">
-                    <field-map field-name="dataResourceId" from-field="productContent.dataResourceId"/>
-                </entity-one>
-                <if-not-empty field="electronicText">
-                    <set field="electronicText.textData" from-field="parameters.metaKeyword"/>
-                    <store-value value-field="electronicText"/>
-                </if-not-empty>
-            <else>
-                <set field="createTextContentMap.productId" from-field="parameters.productId"/>
-                <set field="createTextContentMap.productContentTypeId" value="META_KEYWORD"/>
-                <set field="createTextContentMap.text" from-field="parameters.metaKeyword"/>
-                <call-service service-name="createSimpleTextContentForProduct" in-map-name="createTextContentMap"/>
-            </else>
-            </if-not-empty>
-        </if-not-empty>
-        <if-not-empty field="parameters.metaDescription">
-            <entity-and entity-name="ProductContentAndInfo" list="productContents">
-                <field-map field-name="productId" from-field="parameters.productId"/>
-                <field-map field-name="productContentTypeId" value="META_DESCRIPTION"/>
-            </entity-and>
-            <if-not-empty field="productContents">
-                <first-from-list entry="productContent" list="productContents"/>
-                <entity-one entity-name="ElectronicText" value-field="electronicText">
-                    <field-map field-name="dataResourceId" from-field="productContent.dataResourceId"/>
-                </entity-one>
-                <if-not-empty field="electronicText">
-                    <set field="electronicText.textData" from-field="parameters.metaDescription"/>
-                    <store-value value-field="electronicText"/>
-                </if-not-empty>
-            <else>
-                <set field="createTextContentMap.productId" from-field="parameters.productId"/>
-                <set field="createTextContentMap.productContentTypeId" value="META_DESCRIPTION"/>
-                <set field="createTextContentMap.text" from-field="parameters.metaDescription"/>
-                <call-service service-name="createSimpleTextContentForProduct" in-map-name="createTextContentMap"/>
-            </else>
-            </if-not-empty>
-        </if-not-empty>
-    </simple-method>
-</simple-methods>
diff --git a/applications/product/servicedef/services.xml b/applications/product/servicedef/services.xml
index e776379..6015638 100644
--- a/applications/product/servicedef/services.xml
+++ b/applications/product/servicedef/services.xml
@@ -361,30 +361,27 @@ under the License.
     </service>
 
     <!-- Product content services -->
-    <service name="createProductContent" default-entity-name="ProductContent" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="createProductContent" auth="true">
+    <service name="createProductContent" default-entity-name="ProductContent" engine="groovy"
+        location="component://product/groovyScripts/product/product/ProductContentServices.groovy" invoke="createProductContent" auth="true">
         <description>Add Content To Product</description>
         <auto-attributes include="pk" mode="INOUT" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
-        <override name="fromDate" optional="true"/>
-        <!--<override name="contentId" optional="true" mode="INOUT"/>-->
+        <override name="fromDate" default-value="${date:nowTimestamp()}"/>
     </service>
-    <service name="updateProductContent" default-entity-name="ProductContent" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="updateProductContent" auth="true">
+    <service name="updateProductContent" default-entity-name="ProductContent" engine="groovy"
+        location="component://product/groovyScripts/product/product/ProductContentServices.groovy" invoke="updateProductContent" auth="true">
         <description>Update Content To Product</description>
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="removeProductContent" default-entity-name="ProductContent" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="removeProductContent" auth="true">
+    <service name="removeProductContent" default-entity-name="ProductContent" engine="entity-auto" invoke="delete" auth="true">
         <description>Remove Content From Product</description>
         <auto-attributes include="pk" mode="IN" optional="false"/>
-        <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="createEmailContentForProduct" default-entity-name="ProductContent" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="createEmailContentForProduct" auth="true">
+    <service name="createEmailContentForProduct" default-entity-name="ProductContent" engine="groovy"
+        location="component://product/groovyScripts/product/product/ProductContentServices.groovy" invoke="createEmailContentForProduct" auth="true">
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <auto-attributes mode="IN" entity-name="Content" optional="true"/>
@@ -393,20 +390,15 @@ under the License.
         <attribute name="htmlBody" type="String" mode="IN" optional="true" allow-html="safe"/>
         <override name="contentId" optional="true" mode="INOUT"/>
     </service>
-    <service name="updateEmailContentForProduct" default-entity-name="ProductContent" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="updateEmailContentForProduct" auth="true">
-        <auto-attributes include="pk" mode="IN" optional="false"/>
-        <auto-attributes include="nonpk" mode="IN" optional="true"/>
-        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
-        <attribute name="subjectDataResourceId" type="String" mode="IN" optional="true"/>
-        <attribute name="subject" type="String" mode="IN" optional="true"/>
-        <attribute name="plainBodyDataResourceId" type="String" mode="IN" optional="true"/>
-        <attribute name="plainBody" type="String" mode="IN" optional="true"/>
-        <attribute name="htmlBodyDataResourceId" type="String" mode="IN" optional="true"/>
-        <attribute name="htmlBody" type="String" mode="IN" optional="true" allow-html="safe"/>
+    <service name="updateEmailContentForProduct" default-entity-name="ProductContent" engine="group" auth="true">
+        <description>Update Email Content For Product</description>
+        <group>
+            <invoke name="updateProductContent"/>
+            <invoke name="updateEmailContent"/>
+        </group>
     </service>
-    <service name="createDownloadContentForProduct" default-entity-name="ProductContent" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="createDownloadContentForProduct" auth="true">
+    <service name="createDownloadContentForProduct" default-entity-name="ProductContent" engine="groovy"
+        location="component://product/groovyScripts/product/product/ProductContentServices.groovy" invoke="createDownloadContentForProduct" auth="true">
         <auto-attributes include="pk" mode="IN" optional="true"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <auto-attributes include="nonpk" mode="IN" entity-name="Content" optional="true"/>
@@ -415,17 +407,16 @@ under the License.
         <attribute mode="IN" name="_imageData_fileName" optional="true" type="String"/>
         <override name="productContentTypeId" optional="false"/>
     </service>
-    <service name="updateDownloadContentForProduct" default-entity-name="ProductContent" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="updateDownloadContentForProduct" auth="true">
-        <auto-attributes include="pk" mode="IN" optional="false"/>
-        <auto-attributes include="nonpk" mode="IN" optional="true"/>
-        <auto-attributes mode="IN" entity-name="Content" optional="true"/>
-        <attribute name="fileDataResourceId" type="String" mode="IN" optional="true"/>
-        <attribute name="file" type="String" mode="IN" optional="true"/>
+    <service name="updateDownloadContentForProduct" default-entity-name="ProductContent" engine="group" auth="true">
+        <description>Update Download Content For Product</description>
+        <group>
+            <invoke name="updateProductContent"/>
+            <invoke name="updateDownloadContent"/>
+        </group>
     </service>
 
-    <service name="createSimpleTextContentForProduct" default-entity-name="ProductContent" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="createSimpleTextContentForProduct" auth="true">
+    <service name="createSimpleTextContentForProduct" default-entity-name="ProductContent" engine="groovy"
+        location="component://product/groovyScripts/product/product/ProductContentServices.groovy" invoke="createSimpleTextContentForProduct" auth="true">
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
@@ -433,16 +424,16 @@ under the License.
         <override name="contentId" optional="true"/>
         <override name="fromDate" optional="true"/>
     </service>
-    <service name="updateSimpleTextContentForProduct" default-entity-name="ProductContent" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="updateSimpleTextContentForProduct" auth="true">
-        <auto-attributes include="pk" mode="IN" optional="false"/>
-        <auto-attributes include="nonpk" mode="IN" optional="true"/>
-        <auto-attributes mode="IN" entity-name="Content" optional="true"/>
-        <attribute name="textDataResourceId" type="String" mode="IN" optional="true"/>
-        <attribute name="text" type="String" mode="IN" optional="true" allow-html="safe"/>
+    <service name="updateSimpleTextContentForProduct" default-entity-name="ProductContent" engine="group" auth="true">
+        <description>Update Simple Text Content For Product</description>
+        <group>
+            <invoke name="updateProductContent"/>
+            <invoke name="updateSimpleTextContent"/>
+        </group>
     </service>
 
-    <service name="createSimpleTextContentForAlternateLocale" engine="simple" location="component://product/minilang/product/product/ProductContentServices.xml" invoke="createSimpleTextContentForAlternateLocale">
+    <service name="createSimpleTextContentForAlternateLocale" engine="groovy"
+        location="component://product/groovyScripts/product/product/ProductContentServices.groovy" invoke="createSimpleTextContentForAlternateLocale">
         <auto-attributes mode="IN" entity-name="Content" optional="true"/>
         <attribute name="mainContentId" type="String" mode="IN" optional="false"/>
         <attribute name="text" type="String" mode="IN" optional="false" allow-html="safe"/>
@@ -460,8 +451,8 @@ under the License.
         <override name="productId" optional="false"/>
     </service>
 
-    <service name="uploadProductAdditionalViewImages" engine="simple"
-        location="component://product/minilang/product/product/ProductContentServices.xml" invoke="uploadProductAdditionalViewImages" auth="true">
+    <service name="uploadProductAdditionalViewImages" engine="groovy"
+        location="component://product/groovyScripts/product/product/ProductContentServices.groovy" invoke="uploadProductAdditionalViewImages" auth="true">
         <description>Upload Additional View Images For Product</description>
         <permission-service service-name="genericContentPermission" main-action="UPDATE"/>
         <attribute name="productId" type="String" mode="INOUT" optional="false"/>
@@ -479,8 +470,8 @@ under the License.
         <attribute name="_additionalImageFour_contentType" type="String" mode="IN" optional="true"/>
     </service>
 
-    <service name="updateContentSEOForProduct" engine="simple"
-            location="component://product/minilang/product/product/ProductContentServices.xml" invoke="updateContentSEOForProduct" auth="true">
+    <service name="updateContentSEOForProduct" engine="groovy"
+            location="component://product/groovyScripts/product/product/ProductContentServices.groovy" invoke="updateContentSEOForProduct" auth="true">
         <description>Update Product SEO</description>
         <attribute name="productId" mode="IN" type="String" optional="false"/>
         <attribute name="title" mode="IN" type="String" optional="true"/>
@@ -1362,8 +1353,7 @@ under the License.
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="removeProductPromoContent" default-entity-name="ProductPromoContent" engine="simple"
-            location="component://product/minilang/product/product/ProductContentServices.xml" invoke="removeProductPromoContent" auth="true">
+    <service name="removeProductPromoContent" default-entity-name="ProductPromoContent" engine="entity-auto" invoke="expire" auth="true">
         <description>Cancel by the thru date a Product Promo Content</description>
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>