You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ha...@apache.org on 2012/12/26 05:19:34 UTC

svn commit: r1425813 - in /ofbiz/trunk: framework/entity/src/org/ofbiz/entity/model/ModelEntity.java framework/entity/src/org/ofbiz/entity/util/EntitySaxReader.java specialpurpose/example/data/ExampleDemoData.xml

Author: hansbak
Date: Wed Dec 26 04:19:34 2012
New Revision: 1425813

URL: http://svn.apache.org/viewvc?rev=1425813&view=rev
Log:
Nice contribution from Nicolas, now be able to modify and delete database records using the framework import function: https://issues.apache.org/jira/browse/OFBIZ-4949

Modified:
    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/model/ModelEntity.java
    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntitySaxReader.java
    ofbiz/trunk/specialpurpose/example/data/ExampleDemoData.xml

Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/model/ModelEntity.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/model/ModelEntity.java?rev=1425813&r1=1425812&r2=1425813&view=diff
==============================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/model/ModelEntity.java (original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/model/ModelEntity.java Wed Dec 26 04:19:34 2012
@@ -694,6 +694,20 @@ public class ModelEntity extends ModelIn
         return nameList;
     }
 
+    /**
+     * @return field names list, managed by entity-engine
+     */
+    public List<String> getAutomaticFieldNames() {
+        List<String> nameList = FastList.newInstance();
+        if (! this.noAutoStamp) {
+            nameList.add(STAMP_FIELD);
+            nameList.add(STAMP_TX_FIELD);
+            nameList.add(CREATE_STAMP_FIELD);
+            nameList.add(CREATE_STAMP_TX_FIELD);
+        }
+        return nameList;
+    }
+
     public int getRelationsSize() {
         return this.relations.size();
     }

Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntitySaxReader.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntitySaxReader.java?rev=1425813&r1=1425812&r2=1425813&view=diff
==============================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntitySaxReader.java (original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntitySaxReader.java Wed Dec 26 04:19:34 2012
@@ -40,12 +40,15 @@ import javolution.xml.sax.XMLReaderImpl;
 import org.ofbiz.base.location.FlexibleLocation;
 import org.ofbiz.base.util.Base64;
 import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilMisc;
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.base.util.UtilXml;
 import org.ofbiz.base.util.template.FreeMarkerWorker;
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.GenericEntityNotFoundException;
 import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.datasource.GenericHelper;
 import org.ofbiz.entity.eca.EntityEcaHandler;
 import org.ofbiz.entity.model.ModelEntity;
 import org.ofbiz.entity.model.ModelField;
@@ -78,6 +81,11 @@ public class EntitySaxReader implements 
     protected CharSequence currentFieldName = null;
     protected CharSequence currentFieldValue = null;
     protected long numberRead = 0;
+    protected long numberCreated = 0;
+    protected long numberUpdated = 0;
+    protected long numberReplaced = 0;
+    protected long numberDeleted = 0;
+    protected long numberSkipped = 0;
 
     protected int valuesPerWrite = 100;
     protected int valuesPerMessage = 1000;
@@ -88,9 +96,13 @@ public class EntitySaxReader implements 
     protected boolean checkDataOnly = false;
     protected boolean doCacheClear = true;
     protected boolean disableEeca = false;
+    protected enum Action {CREATE, CREATE_UPDATE, CREATE_REPLACE, DELETE}; 
+    protected List<String> actionTags = UtilMisc.toList("create", "create-update", "create-replace", "delete");
+    protected Action currentAction = Action.CREATE_UPDATE;
     protected List<Object> messageList = null;
 
     protected List<GenericValue> valuesToWrite = new ArrayList<GenericValue>(valuesPerWrite);
+    protected List<GenericValue> valuesToDelete = new ArrayList<GenericValue>(valuesPerWrite);
 
     protected boolean isParseForTemplate = false;
     protected CharSequence templatePath = null;
@@ -202,6 +214,14 @@ public class EntitySaxReader implements 
         }
     }
 
+    public void setAction(Action action) {
+        this.currentAction = action;
+    }
+
+    public Action getAction() {
+        return this.currentAction;
+    }
+
     public long parse(String content) throws SAXException, java.io.IOException {
         if (content == null) {
             Debug.logWarning("content was null, doing nothing", module);
@@ -272,10 +292,14 @@ public class EntitySaxReader implements 
             try {
                 parser.parse(is);
                 // make sure all of the values to write got written...
-                if (valuesToWrite.size() > 0) {
+                if (! valuesToWrite.isEmpty()) {
                     writeValues(valuesToWrite);
                     valuesToWrite.clear();
                 }
+                if (! valuesToDelete.isEmpty()) {
+                    delegator.removeAll(valuesToDelete);
+                    valuesToDelete.clear();
+                }
                 TransactionUtil.commit(beganTransaction);
             } catch (Exception e) {
                 String errMsg = "An error occurred saving the data, rolling back transaction (" + beganTransaction + ")";
@@ -287,6 +311,11 @@ public class EntitySaxReader implements 
             throw new SAXException("A transaction error occurred reading data", e);
         }
         Debug.logImportant("Finished " + numberRead + " values from " + docDescription, module);
+        if (Debug.verboseOn()) { 
+            Debug.logVerbose("  Detail created : " + numberCreated + ", skipped : " + numberSkipped +
+                    ", updated : " + numberUpdated + ", replaced : " + numberReplaced +
+                    ", deleted : " + numberDeleted, module);
+        }
         return numberRead;
     }
 
@@ -384,6 +413,12 @@ public class EntitySaxReader implements 
             return;
         }
 
+        //Test if end action tag, set action to default
+        if (actionTags.contains(fullNameString)) {
+            setAction(Action.CREATE_UPDATE);
+            return;
+        }
+
         if (currentValue != null) {
             if (currentFieldName != null) {
                 if (UtilValidate.isNotEmpty(currentFieldValue)) {
@@ -419,22 +454,58 @@ public class EntitySaxReader implements 
                 }
 
                 try {
-                    if (this.useTryInsertMethod && !this.checkDataOnly) {
-                        // this technique is faster for data sets where most, if not all, values do not already exist in the database
-                        try {
-                            currentValue.create();
-                        } catch (GenericEntityException e1) {
-                            // create failed, try a store, if that fails too we have a real error and the catch outside of this should handle it
-                            currentValue.store();
+                    boolean exist = true;
+                    boolean skip = false;
+                    //if verbose on, check if entity exist on database for count each action
+                    //It's necessay to check also for specific action CREATE and DELETE to ensure it's ok
+                    if (Action.CREATE == currentAction || Action.DELETE == currentAction || Debug.verboseOn()) {
+                        GenericHelper helper = delegator.getEntityHelper(currentValue.getEntityName());
+                        if (currentValue.containsPrimaryKey()) {
+                            try {
+                                helper.findByPrimaryKey(currentValue.getPrimaryKey());
+                            } catch (GenericEntityNotFoundException e) {exist = false;}
                         }
-                    } else {
-                        valuesToWrite.add(currentValue);
-                        if (valuesToWrite.size() >= valuesPerWrite) {
-                            writeValues(valuesToWrite);
-                            valuesToWrite.clear();
+                        if (Action.CREATE == currentAction && exist) { skip = true; }
+                        else if (Action.DELETE == currentAction && ! exist) { skip = true; }
+                    }
+                    if (! skip) {
+                        if (this.useTryInsertMethod && !this.checkDataOnly) {
+                            if (Action.CREATE == currentAction) { currentValue.create(); }
+                            else if (Action.DELETE == currentAction) {
+                                try {
+                                    currentValue.remove();
+                                } catch (GenericEntityException e1) {
+                                    String errMsg = "Error deleting value";
+                                    Debug.logError(e1, errMsg, module);
+                                    throw new SAXException(errMsg, e1);
+                                }
+                            } else {
+                                // this technique is faster for data sets where most, if not all, values do not already exist in the database
+                                try {
+                                    currentValue.create();
+                                } catch (GenericEntityException e1) {
+                                    // create failed, try a store, if that fails too we have a real error and the catch outside of this should handle it
+                                    currentValue.store();
+                                }
+                            }
+                        } else {
+                            if (Action.DELETE == currentAction) {
+                                valuesToDelete.add(currentValue);
+                                if (valuesToDelete.size() >= valuesPerWrite) {
+                                    delegator.removeAll(valuesToDelete, doCacheClear);
+                                    valuesToDelete.clear();
+                                }
+                            } else {
+                                valuesToWrite.add(currentValue);
+                                if (valuesToWrite.size() >= valuesPerWrite) {
+                                    writeValues(valuesToWrite);
+                                    valuesToWrite.clear();
+                                }
+                            }
                         }
                     }
                     numberRead++;
+                    if (Debug.verboseOn()) countValue(skip, exist);
                     if ((numberRead % valuesPerMessage) == 0) {
                         Debug.logImportant("Another " + valuesPerMessage + " values imported: now up to " + numberRead, module);
                     }
@@ -448,6 +519,15 @@ public class EntitySaxReader implements 
         }
     }
 
+    //Use for detail the loading entities
+    protected void countValue(boolean skip, boolean exist) {
+        if (skip) numberSkipped++;
+        else if (Action.DELETE == currentAction) numberDeleted++;
+        else if (Action.CREATE == currentAction || ! exist) numberCreated++;
+        else if (Action.CREATE_REPLACE == currentAction) numberReplaced++;
+        else numberUpdated++;
+    }
+
     public void endPrefixMapping(CharArray prefix) throws org.xml.sax.SAXException {}
 
     public void ignorableWhitespace(char[] values, int offset, int count) throws org.xml.sax.SAXException {
@@ -526,6 +606,15 @@ public class EntitySaxReader implements 
             return;
         }
 
+        //Test if action change
+        if (actionTags.contains(fullNameString)) {
+            if ("create".equals(fullNameString)) setAction(Action.CREATE);
+            if ("create-update".equals(fullNameString)) setAction(Action.CREATE_UPDATE);
+            if ("create-replace".equals(fullNameString)) setAction(Action.CREATE_REPLACE);
+            if ("delete".equals(fullNameString)) setAction(Action.DELETE);
+            return;
+        }
+
         if (currentValue != null) {
             // we have a nested value/CDATA element
             currentFieldName = fullName;
@@ -554,6 +643,13 @@ public class EntitySaxReader implements 
 
             if (currentValue != null) {
                 int length = attributes.getLength();
+                List<String> absentFields = null;
+                if (Action.CREATE_REPLACE == currentAction) {
+                    //get all non pk fields
+                    ModelEntity currentEntity = currentValue.getModelEntity();
+                    absentFields = currentEntity.getNoPkFieldNames();
+                    absentFields.removeAll(currentEntity.getAutomaticFieldNames());
+                }
 
                 for (int i = 0; i < length; i++) {
                     CharSequence name = attributes.getLocalName(i);
@@ -567,6 +663,7 @@ public class EntitySaxReader implements 
                         if (UtilValidate.isNotEmpty(value)) {
                             if (currentValue.getModelEntity().isField(name.toString())) {
                                 currentValue.setString(name.toString(), value.toString());
+                                if (Action.CREATE_REPLACE == currentAction && absentFields != null) absentFields.remove(name);
                             } else {
                                 Debug.logWarning("Ignoring invalid field name [" + name + "] found for the entity: " + currentValue.getEntityName() + " with value=" + value, module);
                             }
@@ -575,6 +672,11 @@ public class EntitySaxReader implements 
                         Debug.logWarning(e, "Could not set field " + entityName + "." + name + " to the value " + value, module);
                     }
                 }
+                if (Action.CREATE_REPLACE == currentAction && absentFields != null) {
+                    for (String fieldName : absentFields) {
+                        currentValue.set(fieldName, null);
+                    }
+                }
             }
         }
     }

Modified: ofbiz/trunk/specialpurpose/example/data/ExampleDemoData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/example/data/ExampleDemoData.xml?rev=1425813&r1=1425812&r2=1425813&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/example/data/ExampleDemoData.xml (original)
+++ ofbiz/trunk/specialpurpose/example/data/ExampleDemoData.xml Wed Dec 26 04:19:34 2012
@@ -61,6 +61,20 @@ under the License.
     <Example exampleId="EX08" exampleName="Example 8" exampleTypeId="MADE_UP" statusId="EXST_IN_DESIGN"/>
     <Example exampleId="EX09" exampleName="Example 9" exampleTypeId="MADE_UP" statusId="EXST_IN_DESIGN"/>
     <Example exampleId="EX10" exampleName="Example 10" exampleTypeId="MADE_UP" statusId="EXST_IN_DESIGN"/>
-    <Example exampleId="EX11" exampleName="Example 11" exampleTypeId="INSPIRED" statusId="EXST_IN_DESIGN"/>
-    <Example exampleId="EX12" exampleName="Example 12" exampleTypeId="INSPIRED" statusId="EXST_IN_DESIGN"/>
+    <Example exampleId="EX11" exampleName="Example 11" exampleTypeId="INSPIRED" statusId="EXST_IN_DESIGN" description="mMy inspired example 11 description"/>
+    <Example exampleId="EX12" exampleName="Example 12" exampleTypeId="INSPIRED" statusId="EXST_IN_DESIGN" description="mMy inspired example 12 description"/>
+    <create>
+        <Example exampleId="EX13" exampleName="Example 13" exampleTypeId="INSPIRED" statusId="EXST_IN_DESIGN"/>
+        <Example exampleId="EX14" exampleName="Example 14" exampleTypeId="INSPIRED" statusId="EXST_IN_DESIGN"/>
+    </create>
+    <create-replace>
+        <Example exampleId="EX12" exampleName="Example 12 after replace" exampleTypeId="INSPIRED" statusId="EXST_IN_DESIGN"/>
+    </create-replace>
+    <create-update>
+        <Example exampleId="EX12" exampleName="Example 11 after update" exampleTypeId="INSPIRED" statusId="EXST_IN_DESIGN"/>
+    </create-update>
+    <delete>
+        <Example exampleId="EX09"/>
+    </delete>
+    <Example exampleId="EX10" exampleName="Example 10 after update"/>
 </entity-engine-xml>