Author: nmalin
Date: Sat Nov  8 21:00:55 2014
New Revision: 1637596

URL: http://svn.apache.org/r1637596
Log:
Manage multi pk with sub-sequence on entity-auto (OFBIZ-5800), 

Add the possibility to the entity-auto engine on the create action to manage 
entities with more than 2 primary keys which one is under sub sequence or 
fromDate, like PerfReview (employeePartyId, employeeRoleTypeId, perfReviewId) 
or PartyQual (partyId, partyQualTypeId, fromDate).

Improve return message for the create action if the entity value exist and the 
delete action if the entity value not exist instead of the database message 
error.

Modified:
    ofbiz/trunk/framework/service/config/ServiceErrorUiLabels.xml
    ofbiz/trunk/framework/service/servicedef/services_test_se.xml
    
ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/EntityAutoEngine.java
    
ofbiz/trunk/framework/service/src/org/ofbiz/service/test/ServiceEntityAutoTests.java

Modified: ofbiz/trunk/framework/service/config/ServiceErrorUiLabels.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/config/ServiceErrorUiLabels.xml?rev=1637596&r1=1637595&r2=1637596&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/config/ServiceErrorUiLabels.xml (original)
+++ ofbiz/trunk/framework/service/config/ServiceErrorUiLabels.xml Sat Nov  8 
21:00:55 2014
@@ -272,11 +272,22 @@
         <value xml:lang="zh">缺少参数</value>
         <value xml:lang="zh_TW">缺少參數</value>
     </property>
+    <property key="ServiceValueFound">
+        <value xml:lang="en">Value found (with ids ${pkFields}), cannot create 
a new one</value>
+        <value xml:lang="fr">La valeur a été trouvée (avec les réfs. 
${pkFields}), une nouvelle ne peut donc pas être créée</value>
+        <value xml:lang="it">Valore troavato, non è possibile creare</value>
+    </property>
     <property key="ServiceValueNotFound">
         <value xml:lang="en">Value not found, cannot update</value>
+        <value xml:lang="fr">La valeur n'a pas été trouvée, elle ne peut 
donc pas être mise à jour</value>
         <value xml:lang="it">Valore non troavato, non è possibile 
aggiornare</value>
         <value 
xml:lang="ja">値が見つかりません。更新できません</value>
         <value xml:lang="zh">没有找到值,无法更新</value>
         <value xml:lang="zh_TW">沒有找到值,無法更新</value>
     </property>
+    <property key="ServiceValueNotFoundForRemove">
+        <value xml:lang="en">Value not found, cannot remove</value>
+        <value xml:lang="fr">La valeur n'a pas été trouvée, suppression 
impossible</value>
+        <value xml:lang="it">Valore non troavato, non è possibile 
sopprimere</value>
+    </property>
 </resource>

Modified: ofbiz/trunk/framework/service/servicedef/services_test_se.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/servicedef/services_test_se.xml?rev=1637596&r1=1637595&r2=1637596&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/servicedef/services_test_se.xml (original)
+++ ofbiz/trunk/framework/service/servicedef/services_test_se.xml Sat Nov  8 
21:00:55 2014
@@ -80,7 +80,7 @@ under the License.
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <attribute name="testingId" mode="IN" type="String"/>
         <attribute name="testingNodeId" mode="IN" type="String"/>
-        <attribute name="fromDate" mode="OUT" type="String"/>
+        <attribute name="fromDate" mode="OUT" type="Timestamp"/>
     </service>
     <service name="testEntityAutoUpdateTesting" auth="false"
         engine="entity-auto" default-entity-name="Testing" invoke="update">

Modified: 
ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/EntityAutoEngine.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/EntityAutoEngine.java?rev=1637596&r1=1637595&r2=1637596&view=diff
==============================================================================
--- 
ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/EntityAutoEngine.java
 (original)
+++ 
ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/EntityAutoEngine.java
 Sat Nov  8 21:00:55 2014
@@ -20,6 +20,7 @@ package org.ofbiz.service.engine;
 
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.Locale;
 import java.util.Map;
 
@@ -88,11 +89,16 @@ public final class EntityAutoEngine exte
 
         try {
             boolean allPksInOnly = true;
+            LinkedList<String> pkFieldNameOutOnly = null;
             for (ModelField pkField: modelEntity.getPkFieldsUnmodifiable()) {
                 ModelParam pkParam = modelService.getParam(pkField.getName());
                 if (pkParam.isOut()) {
                     allPksInOnly = false;
                 }
+                if (pkParam.isOut() && !pkParam.isIn()) {
+                    if (pkFieldNameOutOnly == null) pkFieldNameOutOnly = new 
LinkedList();
+                    pkFieldNameOutOnly.add(pkField.getName());
+                }
             }
 
             if ("create".equals(modelService.invoke)) {
@@ -128,7 +134,6 @@ public final class EntityAutoEngine exte
                     }
                 }
 
-
                 if (isSinglePk && isSinglePkOut && !isSinglePkIn) {
                     /*
                      **** primary sequenced primary key ****
@@ -145,7 +150,6 @@ public final class EntityAutoEngine exte
 
                     String sequencedId = 
dctx.getDelegator().getNextSeqId(modelEntity.getEntityName());
                     newEntity.set(singlePkModeField.getName(), sequencedId);
-                    result.put(singlePkModelParam.name, sequencedId);
                 } else if (isSinglePk && isSinglePkOut && isSinglePkIn) {
                     /*
                      **** primary sequenced key with optional override passed 
in ****
@@ -181,7 +185,6 @@ public final class EntityAutoEngine exte
                         }
                     }
                     newEntity.set(singlePkModeField.getName(), pkValue);
-                    result.put(singlePkModelParam.name, pkValue);
                 } else if (isDoublePk && doublePkPrimaryInParam != null && 
doublePkSecondaryOutParam != null) {
                     /*
                      **** secondary sequenced primary key ****
@@ -199,7 +202,6 @@ public final class EntityAutoEngine exte
 
                     newEntity.setPKFields(parameters, true);
                     dctx.getDelegator().setNextSubSeqId(newEntity, 
doublePkSecondaryOutField.getName(), 5, 1);
-                    result.put(doublePkSecondaryOutParam.name, 
newEntity.get(doublePkSecondaryOutField.getName()));
                 } else if (allPksInOnly) {
                     /*
                      **** plain specified primary key ****
@@ -213,24 +215,46 @@ public final class EntityAutoEngine exte
                      *
                      */
                     newEntity.setPKFields(parameters, true);
+                    //with all pks present on parameters, check if the entity 
is not already exists.
+                    GenericValue lookedUpValue = 
PrimaryKeyFinder.runFind(modelEntity, parameters, dctx.getDelegator(), false, 
true, null, null);
+                    if (lookedUpValue != null) {
+                        return 
ServiceUtil.returnError(UtilProperties.getMessage(resource, 
"ServiceValueFound", UtilMisc.toMap("pkFields", 
newEntity.getPkShortValueString()), locale));
+                    }
                 } else {
-                    throw new GenericServiceException("In Service [" + 
modelService.name + "] which uses the entity-auto engine with the create invoke 
option: " +
-                            "could not find a valid combination of primary key 
settings to do a known create operation; options include: " +
-                            "1. a single OUT pk for primary auto-sequencing, " 
+
-                            "2. a single INOUT pk for primary auto-sequencing 
with optional override, " +
-                            "3. a 2-part pk with one part IN (existing primary 
pk) and one part OUT (the secdonary pk to sub-sequence, " +
-                            "4. all pk fields are IN for a manually specified 
primary key");
+                    /* We haven't all Pk and their are 3 or more, now check if 
isn't a associate entity with own sequence
+                    <set-pk-fields map="parameters" value-field="newEntity"/>
+                    <sequenced-id sequence-name="ExempleItemAssoc" 
field="newEntity.exempleItemAssocId"/>
+                    <create-value value-field="newEntity"/>
+                     */
+                    if (pkFieldNameOutOnly != null && 
pkFieldNameOutOnly.size() == 1) {
+                        newEntity.setPKFields(parameters, true);
+                        String pkFieldName = pkFieldNameOutOnly.getFirst();
+                        //if it's a fromDate, don't update it now, it's will 
be done next step
+                        if (! "fromDate".equals(pkFieldName)) { 
+                            String pkValue = 
dctx.getDelegator().getNextSeqId(modelEntity.getEntityName());
+                            newEntity.set(pkFieldName, pkValue);
+                        }
+                    } else {
+                        throw new GenericServiceException("In Service [" + 
modelService.name + "] which uses the entity-auto engine with the create invoke 
option: " +
+                                "could not find a valid combination of primary 
key settings to do a known create operation; options include: " +
+                                "1. a single OUT pk for primary 
auto-sequencing, " +
+                                "2. a single INOUT pk for primary 
auto-sequencing with optional override, " +
+                                "3. a 2-part pk with one part IN (existing 
primary pk) and one part OUT (the secondary pk to sub-sequence), " +
+                                "4. a N-part pk with N-1 part IN and one party 
OUT only (missing pk is a sub-sequence mainly for entity assoc), " +
+                                "5. all pk fields are IN for a manually 
specified primary key");
+                    }
                 }
 
                 // handle the case where there is a fromDate in the pk of the 
entity, and it is optional or undefined in the service def, populate 
automatically
                 ModelField fromDateField = modelEntity.getField("fromDate");
                 if (fromDateField != null && fromDateField.getIsPk()) {
                     ModelParam fromDateParam = 
modelService.getParam("fromDate");
-                    if (fromDateParam == null || (fromDateParam.isOptional() 
&& parameters.get("fromDate") == null)) {
+                    if (fromDateParam == null || parameters.get("fromDate") == 
null) {
                         newEntity.set("fromDate", UtilDateTime.nowTimestamp());
                     }
                 }
 
+                newEntity.setNonPKFields(parameters, true);
                 if (modelEntity.getField("createdDate") != null) {
                     newEntity.set("createdDate", UtilDateTime.nowTimestamp());
                     if (modelEntity.getField("createdByUserLogin") != null) {
@@ -246,8 +270,8 @@ public final class EntityAutoEngine exte
                         newEntity.set("lastModifiedDate", 
UtilDateTime.nowTimestamp());
                     }
                 }
-                newEntity.setNonPKFields(parameters, true);
                 newEntity.create();
+                result.putAll(modelService.makeValid(newEntity, "OUT"));
             } else if ("update".equals(modelService.invoke)) {
                 /*
                 <auto-attributes include="pk" mode="IN" optional="false"/>
@@ -313,9 +337,9 @@ public final class EntityAutoEngine exte
                         }
                     }
                 }
-
                 // NOTE: nothing here to maintain the status history, that 
should be done with a custom service called by SECA rule
 
+                lookedUpValue.setNonPKFields(parameters, true);
                 if (modelEntity.getField("lastModifiedDate") != null) {
                     lookedUpValue.set("lastModifiedDate", 
UtilDateTime.nowTimestamp());
                     if (modelEntity.getField("lastModifiedByUserLogin") != 
null) {
@@ -325,8 +349,6 @@ public final class EntityAutoEngine exte
                         }
                     }
                 }
-
-                lookedUpValue.setNonPKFields(parameters, true);
                 lookedUpValue.store();
             } else if ("delete".equals(modelService.invoke)) {
                 /*
@@ -344,6 +366,8 @@ public final class EntityAutoEngine exte
                 GenericValue lookedUpValue = 
PrimaryKeyFinder.runFind(modelEntity, parameters, dctx.getDelegator(), false, 
true, null, null);
                 if (lookedUpValue != null) {
                     lookedUpValue.remove();
+                } else {
+                    return 
ServiceUtil.returnError(UtilProperties.getMessage(resource, 
"ServiceValueNotFoundForRemove", locale));
                 }
             }
         } catch (GeneralException e) {

Modified: 
ofbiz/trunk/framework/service/src/org/ofbiz/service/test/ServiceEntityAutoTests.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/test/ServiceEntityAutoTests.java?rev=1637596&r1=1637595&r2=1637596&view=diff
==============================================================================
--- 
ofbiz/trunk/framework/service/src/org/ofbiz/service/test/ServiceEntityAutoTests.java
 (original)
+++ 
ofbiz/trunk/framework/service/src/org/ofbiz/service/test/ServiceEntityAutoTests.java
 Sat Nov  8 21:00:55 2014
@@ -104,11 +104,10 @@ public class ServiceEntityAutoTests exte
         testingNodeMember.remove();
 
         //test create auto sub-sequence
-        //test missing pk
+        //test missing pk fromDate
         Map<String, Object> testingNodeMemberPkMissingMap = 
UtilMisc.toMap("testingId", "TESTING_3", "testingNodeId", "NODE_1");
         results = 
dispatcher.runSync("testEntityAutoCreateTestingNodeMemberPkMissing", 
testingNodeMemberPkMissingMap, 10, true);
-        assertTrue(ServiceUtil.isError(results));
-        assertTrue(ServiceUtil.getErrorMessage(results).contains("1. a single 
OUT pk for primary auto-sequencing"));
+        assertTrue(ServiceUtil.isSuccess(results));
     }
 
     public void testEntityAutoUpdateEntity() throws Exception {
@@ -141,7 +140,7 @@ public class ServiceEntityAutoTests exte
         //test create with bad pk
         Map<String, Object> testingDeleteFailedMap = 
UtilMisc.toMap("testingId", "TESTING_5_FAILED");
         results = dispatcher.runSync("testEntityAutoRemoveTesting", 
testingDeleteFailedMap);
-        assertTrue(ServiceUtil.isSuccess(results));
-        //assertEquals(UtilProperties.getMessage("ServiceErrorUiLabels", 
"ServiceValueNotFound", Locale.ENGLISH), ServiceUtil.getErrorMessage(results));
+        assertTrue(ServiceUtil.isError(results));
+        assertEquals(UtilProperties.getMessage("ServiceErrorUiLabels", 
"ServiceValueNotFoundForRemove", Locale.ENGLISH), 
ServiceUtil.getErrorMessage(results));
     }
 }


Reply via email to