Author: jleroux
Date: Thu Jun 27 11:49:22 2019
New Revision: 1862206

URL: http://svn.apache.org/viewvc?rev=1862206&view=rev
Log:
Implemented: JSON entity data import and export utility
(OFBIZ-10966)

Currently, we support import/export entity data in XML format.
  Nowadays JSON is widely used in industry, we can have support for JSON format 
  which looks quite similar to XML support.

Here is example of XML data and it's JSON version
<Party partyId="123456" partyTypeId="PERSON" statusId="PARTY_ENABLED"/>
{“Party”: 
{"partyId":"123456","partyTypeId":"PERSON","statusId":"PARTY_ENABLED”}}

Design Proposal

We can write entityImportJson and entityImportDirJson services for importing 
JSON from screen and directory respectively.
And the entityExportAllJson service for exporting entity data in JSON.

Import Design
 The import service will perform following operations:
 1.) Validate the input JSON data
 2.) On successful validation, convert JSON to OFBiz's entity model 
     (GenericValue)
 3.) The GenericValue will be inserted in database by some handler class for 
e.g 
     we can write JsonDataHandler, it will convert given JSON to 
     List<GenericValue>, and finally write it to database 
     (Similar pattern is used in XML import).

Export Design
 Based on existing XML pattern the writeXmlText method of GenericEntity class 
 write the exported data in XML format. 
 In the similar way, we can implement writeJsonText to export data in JSON 
format.

jleroux: I fixed 2 trivials things and at my request in last patch Jayansh 
added 
"JSON Data Export All" and "JSON Data Import Dir

Thanks: Jayansh Shinde 

Added:
    
ofbiz/ofbiz-framework/trunk/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntityJsonReader.java
   (with props)
    
ofbiz/ofbiz-framework/trunk/framework/webtools/groovyScripts/entity/JsonDsDump.groovy
   (with props)
    
ofbiz/ofbiz-framework/trunk/framework/webtools/src/main/java/org/apache/ofbiz/webtools/EntityJsonEvents.java
   (with props)
    
ofbiz/ofbiz-framework/trunk/framework/webtools/src/main/java/org/apache/ofbiz/webtools/EntityJsonHelper.java
   (with props)
    
ofbiz/ofbiz-framework/trunk/framework/webtools/template/entity/EntityExportAllJson.ftl
   (with props)
    
ofbiz/ofbiz-framework/trunk/framework/webtools/template/entity/EntityImportDirJson.ftl
   (with props)
    
ofbiz/ofbiz-framework/trunk/framework/webtools/template/entity/EntityImportJson.ftl
   (with props)
    
ofbiz/ofbiz-framework/trunk/framework/webtools/template/entity/JsonDsDump.ftl   
(with props)
Modified:
    
ofbiz/ofbiz-framework/trunk/applications/commonext/webapp/ofbizsetup/WEB-INF/controller.xml
    
ofbiz/ofbiz-framework/trunk/applications/commonext/widget/ofbizsetup/CommonScreens.xml
    ofbiz/ofbiz-framework/trunk/build.gradle
    ofbiz/ofbiz-framework/trunk/framework/webtools/config/WebtoolsUiLabels.xml
    ofbiz/ofbiz-framework/trunk/framework/webtools/servicedef/services.xml
    
ofbiz/ofbiz-framework/trunk/framework/webtools/src/main/java/org/apache/ofbiz/webtools/WebToolsServices.java
    ofbiz/ofbiz-framework/trunk/framework/webtools/template/Main.ftl
    
ofbiz/ofbiz-framework/trunk/framework/webtools/webapp/webtools/WEB-INF/controller.xml
    ofbiz/ofbiz-framework/trunk/framework/webtools/widget/EntityScreens.xml
    ofbiz/ofbiz-framework/trunk/framework/webtools/widget/Menus.xml

Modified: 
ofbiz/ofbiz-framework/trunk/applications/commonext/webapp/ofbizsetup/WEB-INF/controller.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/commonext/webapp/ofbizsetup/WEB-INF/controller.xml?rev=1862206&r1=1862205&r2=1862206&view=diff
==============================================================================
--- 
ofbiz/ofbiz-framework/trunk/applications/commonext/webapp/ofbizsetup/WEB-INF/controller.xml
 (original)
+++ 
ofbiz/ofbiz-framework/trunk/applications/commonext/webapp/ofbizsetup/WEB-INF/controller.xml
 Thu Jun 27 11:49:22 2019
@@ -58,6 +58,17 @@
         <response name="success" type="view" value="EntityExportAll"/>
         <response name="error" type="view" value="EntityExportAll"/>
     </request-map>
+    <request-map uri="EntityExportAllJson">
+        <security https="true" auth="true"/>
+        <response name="success" type="view" value="EntityExportAllJson"/>
+        <response name="error" type="view" value="EntityExportAllJson"/>
+    </request-map>
+    <request-map uri="entityExportAllJson">
+        <security https="true" auth="true"/>
+        <event type="service" path="" invoke="entityExportAllJson"/>
+        <response name="success" type="view" value="EntityExportAllJson"/>
+        <response name="error" type="view" value="EntityExportAllJson"/>
+    </request-map>
     
     <!-- ================ Product Store Requests ============= -->
     <request-map uri="FindProductStore">
@@ -206,6 +217,7 @@
     <view-map name="EditProductStore" type="screen" 
page="component://commonext/widget/ofbizsetup/SetupScreens.xml#EditProductStore"/>
 
     <view-map name="EntityExportAll" type="screen" 
page="component://commonext/widget/ofbizsetup/CommonScreens.xml#EntityExportAll"/>
+    <view-map name="EntityExportAllJson" type="screen" 
page="component://commonext/widget/ofbizsetup/CommonScreens.xml#EntityExportAllJson"/>
 
     <view-map name="FindWebSite" type="screen" 
page="component://commonext/widget/ofbizsetup/SetupScreens.xml#FindWebSite"/>
     <view-map name="EditWebSite" type="screen" 
page="component://commonext/widget/ofbizsetup/SetupScreens.xml#EditWebSite"/>

Modified: 
ofbiz/ofbiz-framework/trunk/applications/commonext/widget/ofbizsetup/CommonScreens.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/commonext/widget/ofbizsetup/CommonScreens.xml?rev=1862206&r1=1862205&r2=1862206&view=diff
==============================================================================
--- 
ofbiz/ofbiz-framework/trunk/applications/commonext/widget/ofbizsetup/CommonScreens.xml
 (original)
+++ 
ofbiz/ofbiz-framework/trunk/applications/commonext/widget/ofbizsetup/CommonScreens.xml
 Thu Jun 27 11:49:22 2019
@@ -153,4 +153,26 @@
             </widgets>
         </section>
     </screen>
+    <screen name="EntityExportAllJson">
+        <section>
+            <actions>
+                <set field="titleProperty" 
value="PageTitleEntityExportAllJson"/>
+                <set field="tabButtonItem" value="entityExportAllJson"/>
+                <set field="parameters.TRANSACTION_TIMEOUT" value="7200"/>
+                <set field="results" from-field="parameters.results"/>
+                <set field="headerItem" value="export"/>
+            </actions>
+            <widgets>
+                <decorator-screen name="main-decorator" 
location="${parameters.mainDecoratorLocation}">
+                    <decorator-section name="body">
+                        <screenlet 
title="${uiLabelMap.PageTitleEntityExportAllJson}">
+                            <platform-specific>
+                                <html><html-template 
location="component://webtools/template/entity/EntityExportAllJson.ftl"/></html>
+                            </platform-specific>
+                        </screenlet>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
 </screens>

Modified: ofbiz/ofbiz-framework/trunk/build.gradle
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/build.gradle?rev=1862206&r1=1862205&r2=1862206&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/build.gradle (original)
+++ ofbiz/ofbiz-framework/trunk/build.gradle Thu Jun 27 11:49:22 2019
@@ -209,6 +209,7 @@ dependencies {
     implementation 'wsdl4j:wsdl4j:1.6.3'
     implementation 'org.jsoup:jsoup:1.11.3'
     implementation 'io.jsonwebtoken:jjwt:0.9.1'
+    implementation 'org.json:json:20140107'
     testImplementation 'org.mockito:mockito-core:2.27.0'
     runtimeOnly 'javax.xml.soap:javax.xml.soap-api:1.4.0'
     runtimeOnly 'de.odysseus.juel:juel-spi:2.2.7'

Added: 
ofbiz/ofbiz-framework/trunk/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntityJsonReader.java
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntityJsonReader.java?rev=1862206&view=auto
==============================================================================
--- 
ofbiz/ofbiz-framework/trunk/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntityJsonReader.java
 (added)
+++ 
ofbiz/ofbiz-framework/trunk/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntityJsonReader.java
 Thu Jun 27 11:49:22 2019
@@ -0,0 +1,598 @@
+package org.apache.ofbiz.entity.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ofbiz.base.lang.JSON;
+import org.apache.ofbiz.base.util.Base64;
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.GenericEntityException;
+import org.apache.ofbiz.entity.GenericEntityNotFoundException;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.entity.datasource.GenericHelper;
+import org.apache.ofbiz.entity.eca.EntityEcaHandler;
+import org.apache.ofbiz.entity.model.ModelEntity;
+import org.apache.ofbiz.entity.model.ModelField;
+import org.apache.ofbiz.entity.transaction.GenericTransactionException;
+import org.apache.ofbiz.entity.transaction.TransactionUtil;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+public class EntityJsonReader {
+    public static final String module = EntitySaxReader.class.getName();
+    public static final int DEFAULT_TX_TIMEOUT = 7200;
+    private Delegator delegator;
+    private EntityEcaHandler<?> ecaHandler = null;
+    private long numberRead = 0;
+    private long numberCreated = 0;
+    private long numberUpdated = 0;
+    private long numberReplaced = 0;
+    private long numberDeleted = 0;
+    private long numberSkipped = 0;
+
+    private int valuesPerWrite = 100;
+    private int valuesPerMessage = 1000;
+    private int transactionTimeout = 7200;
+    private boolean useTryInsertMethod = false;
+    private boolean maintainTxStamps = false;
+    private boolean createDummyFks = false;
+    private boolean checkDataOnly = false;
+    private boolean continueOnFail = false;
+
+    private List<Object> messageList = null;
+
+    private List<GenericValue> valuesToCreate = new 
ArrayList<>(valuesPerWrite);
+    private List<GenericValue> valuesToDelete = new 
ArrayList<>(valuesPerWrite);
+    private List<GenericValue> valuesToUpdate = new 
ArrayList<>(valuesPerWrite);
+
+    /**TODO need to evaluate how placeholders are going to be used in json 
data*/
+    private Map<String, Object> placeholderValues = null; //contains map of 
values for corresponding placeholders (eg. ${key}) in the entity xml data file.
+
+    protected EntityJsonReader() {
+    }
+
+    public EntityJsonReader(Delegator delegator, int transactionTimeout) {
+        this.delegator = delegator.cloneDelegator();
+        this.transactionTimeout = transactionTimeout;
+    }
+
+    public EntityJsonReader(Delegator delegator) {
+        this(delegator, DEFAULT_TX_TIMEOUT);
+    }
+
+    public int getTransactionTimeout() {
+        return this.transactionTimeout;
+    }
+
+    public void setUseTryInsertMethod(boolean value) {
+        this.useTryInsertMethod = value;
+    }
+
+    public void setTransactionTimeout(int transactionTimeout) throws 
GenericTransactionException {
+        if (this.transactionTimeout != transactionTimeout) {
+            TransactionUtil.setTransactionTimeout(transactionTimeout);
+            this.transactionTimeout = transactionTimeout;
+        }
+
+    }
+
+    public void setMaintainTxStamps(boolean maintainTxStamps) {
+        this.maintainTxStamps = maintainTxStamps;
+    }
+
+    public void setCreateDummyFks(boolean createDummyFks) {
+        this.createDummyFks = createDummyFks;
+    }
+
+    public void setCheckDataOnly(boolean checkDataOnly) {
+        this.checkDataOnly = checkDataOnly;
+    }
+
+    public void setContinueOnFail(boolean continueOnFail) {
+        this.continueOnFail = continueOnFail;
+    }
+
+    public void setPlaceholderValues(Map<String, Object> placeholderValues) {
+        this.placeholderValues = placeholderValues;
+    }
+
+    public List<Object> getMessageList() {
+        if (this.checkDataOnly && this.messageList == null) {
+            this.messageList = new LinkedList();
+        }
+
+        return this.messageList;
+    }
+
+    public void setDisableEeca(boolean disableEeca) {
+        if (disableEeca) {
+            if (this.ecaHandler == null) {
+                this.ecaHandler = this.delegator.getEntityEcaHandler();
+            }
+
+            this.delegator.setEntityEcaHandler((EntityEcaHandler) null);
+        } else if (this.ecaHandler != null) {
+            this.delegator.setEntityEcaHandler(this.ecaHandler);
+        }
+
+    }
+
+    public long parse(String content) throws IOException {
+        if (content == null) {
+            Debug.logWarning("content was null, doing nothing", module);
+            return 0L;
+        } else {
+            return this.convertJsonAndWriteValues(content);
+        }
+    }
+
+    public long parse(URL location) throws IOException {
+        if (location == null) {
+            Debug.logWarning("location URL was null, doing nothing", module);
+            return 0L;
+        } else {
+            Debug.logImportant("Beginning import from URL: " + 
location.toExternalForm(), module);
+            long numberRead = 0L;
+            InputStream is = location.openStream();
+            numberRead = this.parse(is, location.toString());
+            return numberRead;
+        }
+    }
+
+    private long parse(InputStream is, String docDescription) throws 
IOException {
+        JSON json = JSON.from(is);
+        return this.convertJsonAndWriteValues(json.toString());
+    }
+
+    private long convertJsonAndWriteValues(String jsonString) throws 
IOException {
+        this.numberRead = 0L;
+        String _prefix = "";
+        JSONArray jsonArray = new JSONArray(jsonString);
+        int length = jsonArray.length();
+
+        for (int jsonIndex = 0; jsonIndex < length; ++jsonIndex) {
+            JSONObject jsonObject = jsonArray.getJSONObject(jsonIndex);
+            Map<String, Map<String, Object>> flatJson = new HashMap<String, 
Map<String, Object>>();
+            Iterator iterator = jsonObject.keySet().iterator();
+
+            while (iterator.hasNext()) {
+                String key = iterator.next().toString();
+                /**TODO use something else instead of if-else */
+                if (key.equals("create")) {
+                    action(jsonObject.get(key), "create");
+                } else if (key.equals("create-update")) {
+                    action(jsonObject.get(key), "createUpdate");
+                } else if (key.equals("create-replace")) {
+                    action(jsonObject.get(key), "createReplace");
+                } else if (key.equals("delete")) {
+                    action(jsonObject.get(key), "delete");
+                } else {
+                    /**TODO replace this block with createUpdate method*/
+                    /*Object value = jsonObject.get(key);
+                    if (value != null && !value.equals("null") && value 
instanceof JSONObject) {
+                        flatJson.put(_prefix + key, 
this.iterateJSONObject((JSONObject) value));
+                        ModelEntity modelEntity = 
this.delegator.getModelEntity(key);
+                        GenericValue entityVal = 
GenericValue.create(this.delegator, modelEntity,
+                                this.iterateJSONObject((JSONObject) value));
+                        if (UtilValidate.isNotEmpty(entityVal)) {
+                            this.valuesToCreate.add(entityVal);
+                        }
+                    }*/
+                    createUpdate(jsonObject);
+                }
+            }
+        }
+
+        this.numberRead = this.writeValues();
+        return this.numberRead;
+    }
+
+    private List<Map<String, Object>> iterateJsonEntityData(Object jsonData) {
+        List<Map<String, Object>> genericMapList = new LinkedList<Map<String, 
Object>>();
+        if (jsonData instanceof JSONArray) {
+            JSONArray jsonArray = (JSONArray) jsonData;
+            int length = jsonArray.length();
+            for (int jsonIndex = 0; jsonIndex < length; ++jsonIndex) {
+                JSONObject jsonObject = jsonArray.getJSONObject(jsonIndex);
+                Map<String, Object> genericMap = iterateJSONObject(jsonObject);
+                if (UtilValidate.isNotEmpty(genericMap)) {
+                    genericMapList.add(genericMap);
+                }
+            }
+        } else if (jsonData instanceof JSONObject) {
+            JSONObject jsonObject = (JSONObject) jsonData;
+            Map<String, Object> genericMap = iterateJSONObject(jsonObject);
+            if (UtilValidate.isNotEmpty(genericMap)) {
+                genericMapList.add(genericMap);
+            }
+        }
+        return genericMapList;
+    }
+
+    private Map<String, Object> iterateJSONObject(JSONObject jsonObj) {
+        Map<String, Object> mapObj = new HashMap<String, Object>();
+        Iterator iterator = jsonObj.keySet().iterator();
+        while (iterator.hasNext()) {
+            String keyStr = (String) iterator.next();
+            Object keyvalue = jsonObj.get(keyStr);
+            if (keyvalue instanceof String) {
+                String keyValStr = 
org.apache.commons.text.StringEscapeUtils.unescapeJson((String) keyvalue);
+                mapObj.put(keyStr, keyValStr);
+            } else {
+                mapObj.put(keyStr, keyvalue);
+            }
+        }
+        return mapObj;
+    }
+
+    private long create(JSONObject jsonObject) throws IOException {
+        Iterator iterator = jsonObject.keySet().iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next().toString();
+            Object value = jsonObject.get(key);
+            if (UtilValidate.isNotEmpty(value)) {
+                List<Map<String, Object>> genericMapList = 
this.iterateJsonEntityData(value);
+                for (Map<String, Object> keyValPair : genericMapList) {
+                    try {
+                        ModelEntity modelEntity = 
this.delegator.getModelEntity(key);
+                        GenericValue currentValue = delegator.makeValue(key, 
keyValPair);
+                        if (this.maintainTxStamps) {
+                            currentValue.setIsFromEntitySync(true);
+                        }
+                        GenericHelper helper = 
delegator.getEntityHelper(currentValue.getEntityName());
+                        if (UtilValidate.isNotEmpty(currentValue)) {
+                            boolean exist = true;
+                            if (currentValue.containsPrimaryKey()) {
+                                try {
+                                    
helper.findByPrimaryKey(currentValue.getPrimaryKey());
+                                } catch (GenericEntityNotFoundException e) {
+                                    exist = false;
+                                }
+                            }
+                            if (!exist) {
+                                if (this.useTryInsertMethod && 
!this.checkDataOnly) {
+                                    currentValue.create();
+                                } else {
+                                    this.valuesToCreate.add(currentValue);
+                                }
+                                this.numberCreated++;
+                            }//if pk exist ignore it.
+                        }
+                    } catch (Exception e) {
+                        if (continueOnFail) {
+                            Debug.logError(e, module);
+                        } else {
+                            throw new IOException(e);
+                        }
+                    }
+                }
+            }
+        }
+        return this.numberCreated;
+    }
+
+    private long createUpdate(JSONObject jsonObject) throws IOException {
+        Iterator iterator = jsonObject.keySet().iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next().toString();
+            Object value = jsonObject.get(key);
+            if (UtilValidate.isNotEmpty(value)) {
+                List<Map<String, Object>> genericMapList = 
this.iterateJsonEntityData(value);
+                for (Map<String, Object> keyValPair : genericMapList) {
+                    try {
+                        GenericValue currentValue = delegator.makeValue(key);
+                        if (currentValue != null) {
+                            ModelEntity modelEntity = 
currentValue.getModelEntity();
+                            List<String> pkFields = 
modelEntity.getPkFieldNames();
+                            for (String pkField : pkFields) {
+                                ModelField modelField = 
modelEntity.getField(pkField);
+                                Object pkFieldValue = keyValPair.get(pkField);
+                                String type = modelField.getType();
+                                if (type != null && "blob".equals(type)) {
+                                    byte[] binData = 
Base64.base64Decode((pkFieldValue.toString()).getBytes());
+                                    currentValue.setBytes(pkField, binData);
+                                } else {
+                                    currentValue.setString(pkField, 
pkFieldValue.toString());
+                                }
+                            }
+
+                            GenericHelper helper = 
delegator.getEntityHelper(currentValue.getEntityName());
+
+                            boolean exist = true;
+                            if (currentValue.containsPrimaryKey()) {
+                                try {
+                                    
helper.findByPrimaryKey(currentValue.getPrimaryKey());
+                                } catch (GenericEntityNotFoundException e) {
+                                    exist = false;
+                                }
+                            }
+                            for (Map.Entry<String, Object> entry : 
keyValPair.entrySet()) {
+                                String currentFieldName = entry.getKey();
+                                Object currentFieldValue = entry.getValue();
+                                if (currentFieldName != null && 
!pkFields.contains(currentFieldName)) {
+                                    if 
(currentValue.getModelEntity().isField(currentFieldName)) {
+                                        if 
(UtilValidate.isNotEmpty(currentFieldValue)) {
+                                            ModelField modelField = 
modelEntity.getField(currentFieldName);
+                                            String type = modelField.getType();
+                                            if (type != null && 
"blob".equals(type)) {
+                                                byte[] binData = 
Base64.base64Decode(currentFieldValue.toString().getBytes());
+                                                
currentValue.setBytes(currentFieldName, binData);
+                                            } else {
+                                                
currentValue.setString(currentFieldName, currentFieldValue.toString());
+                                            }
+                                        }
+                                    } else {
+                                        Debug.logWarning("Ignoring invalid 
field name [" + currentFieldName + "] found for the entity: "
+                                                + currentValue.getEntityName() 
+ " with value=" + currentFieldValue.toString(), module);
+                                    }
+                                }
+                            }
+                            if (exist) {
+                                this.valuesToUpdate.add(currentValue);
+                            } else {
+                                // Not sure about this!
+                                //if (this.useTryInsertMethod && 
!this.checkDataOnly) {
+                                //    currentValue.create();
+                                //} else {
+                                this.valuesToCreate.add(currentValue);
+                                //}
+
+                            }
+                            if (this.maintainTxStamps) {
+                                currentValue.setIsFromEntitySync(true);
+                            }
+                            this.numberUpdated++;
+                        }
+                    } catch (Exception e) {
+                        if (continueOnFail) {
+                            Debug.logError(e, module);
+                        } else {
+                            throw new IOException(e);
+                        }
+                    }
+                }
+            }
+        }
+        return this.numberUpdated;
+    }
+
+    private long createReplace(JSONObject jsonObject) throws IOException {
+        Iterator iterator = jsonObject.keySet().iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next().toString();
+            Object value = jsonObject.get(key);
+            if (UtilValidate.isNotEmpty(value)) {
+                List<Map<String, Object>> genericMapList = 
this.iterateJsonEntityData(value);
+                for (Map<String, Object> keyValPair : genericMapList) {
+                    try {
+                        GenericValue currentValue = 
this.delegator.makeValue(key);
+                        if (this.maintainTxStamps) {
+                            currentValue.setIsFromEntitySync(true);
+                        }
+                        ModelEntity modelEntity = 
currentValue.getModelEntity();
+                        List<String> pkFields = modelEntity.getPkFieldNames();
+                        if (currentValue != null) {
+                            for (String pkField : pkFields) {
+                                ModelField modelField = 
modelEntity.getField(pkField);
+                                Object pkFieldValue = keyValPair.get(pkField);
+                                String type = modelField.getType();
+                                if (type != null && "blob".equals(type)) {
+                                    byte[] binData = 
Base64.base64Decode((pkFieldValue.toString()).getBytes());
+                                    currentValue.setBytes(pkField, binData);
+                                } else {
+                                    currentValue.setString(pkField, 
pkFieldValue.toString());
+                                }
+                            }
+
+                            GenericHelper helper = 
delegator.getEntityHelper(currentValue.getEntityName());
+
+                            boolean exist = true;
+                            if (currentValue.containsPrimaryKey()) {
+                                try {
+                                    
helper.findByPrimaryKey(currentValue.getPrimaryKey());
+                                } catch (GenericEntityNotFoundException e) {
+                                    exist = false;
+                                }
+                            } else {
+                                if (modelEntity.getPksSize() == 1) {
+                                    ModelField modelField = 
currentValue.getModelEntity().getOnlyPk();
+                                    String newSeq = 
delegator.getNextSeqId(currentValue.getEntityName());
+                                    
currentValue.setString(modelField.getName(), newSeq);
+                                } else {
+                                    throw new IOException("Cannot store value 
with incomplete primary key with more than 1 primary key field: " + 
currentValue);
+                                }
+                            }
+
+                            ModelEntity currentEntity = 
currentValue.getModelEntity();
+                            List<String> absentFields = 
currentEntity.getNoPkFieldNames();
+                            
absentFields.removeAll(currentEntity.getAutomaticFieldNames());
+
+                            for (Map.Entry<String, Object> entry : 
keyValPair.entrySet()) {
+                                String currentFieldName = entry.getKey();
+                                Object currentFieldValue = entry.getValue();
+                                if (UtilValidate.isNotEmpty(currentFieldName) 
&& !pkFields.contains(currentFieldName)) {
+                                    if (modelEntity.isField(currentFieldName)) 
{
+                                        if 
(UtilValidate.isNotEmpty(currentFieldValue)) {
+                                            ModelField modelField = 
modelEntity.getField(currentFieldName);
+                                            String type = modelField.getType();
+                                            if (type != null && 
"blob".equals(type)) {
+                                                byte[] binData = 
Base64.base64Decode(((String) currentFieldValue).getBytes());
+                                                
currentValue.setBytes(currentFieldName, binData);
+                                            } else {
+                                                
currentValue.setString(currentFieldName, currentFieldValue.toString());
+                                            }
+                                            
absentFields.remove(currentFieldName);
+                                        }
+                                    } else {
+                                        Debug.logWarning("Ignoring invalid 
field name [" + currentFieldName + "] found for the entity: "
+                                                + currentValue.getEntityName() 
+ " with value=" + currentFieldValue.toString(), module);
+                                    }
+                                }
+                            }
+                            if (absentFields != null) {
+                                for (String fieldName : absentFields) {
+                                    currentValue.set(fieldName, null);
+                                }
+                            }
+                            if (exist) {
+                                this.valuesToUpdate.add(currentValue);
+                            } else {
+                                // Not sure about this!
+                                //if (this.useTryInsertMethod && 
!this.checkDataOnly) {
+                                //    currentValue.create();
+                                //} else {
+                                this.valuesToCreate.add(currentValue);
+                                //}
+                            }
+                            if (this.maintainTxStamps) {
+                                currentValue.setIsFromEntitySync(true);
+                            }
+                            this.numberReplaced++;
+                        }
+                    } catch (Exception e) {
+                        if (continueOnFail) {
+                            Debug.logError(e, module);
+                        } else {
+                            throw new IOException(e);
+                        }
+                    }
+                }
+            }
+        }
+        return this.numberReplaced;
+    }
+
+    private long delete(JSONObject jsonObject) throws IOException {
+        Iterator iterator = jsonObject.keySet().iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next().toString();
+            Object value = jsonObject.get(key);
+            if (UtilValidate.isNotEmpty(value)) {
+                List<Map<String, Object>> genericMapList = 
this.iterateJsonEntityData(value);
+                for (Map<String, Object> keyValPair : genericMapList) {
+                    try {
+                        ModelEntity modelEntity = 
this.delegator.getModelEntity(key);
+                        GenericValue currentValue = delegator.makeValue(key, 
keyValPair);
+                        if (this.maintainTxStamps) {
+                            currentValue.setIsFromEntitySync(true);
+                        }
+                        GenericHelper helper = delegator.getEntityHelper(key);
+                        if (currentValue != null) {
+                            boolean exist = true;
+                            if (currentValue.containsPrimaryKey()) {
+                                try {
+                                    
helper.findByPrimaryKey(currentValue.getPrimaryKey());
+                                } catch (GenericEntityNotFoundException e) {
+                                    exist = false;
+                                }
+                            }
+                            if (exist) {
+                                if (this.useTryInsertMethod && 
!this.checkDataOnly) {
+                                    currentValue.remove();
+                                } else {
+                                    this.valuesToDelete.add(currentValue);
+                                }
+                                this.numberDeleted++;
+                            }//if pk exist ignore it.
+                        }
+                    } catch (Exception e) {
+                        if (continueOnFail) {
+                            Debug.logError(e, module);
+                        } else {
+                            throw new IOException(e);
+                        }
+                    }
+                }
+            }
+        }
+        return this.numberDeleted;
+    }
+
+    private long action(Object jsonData, String actionName) throws IOException 
{
+        java.lang.reflect.Method method;
+        try {
+            method = this.getClass().getDeclaredMethod(actionName, 
JSONObject.class);
+            if (jsonData instanceof JSONArray) {
+                JSONArray jsonArray = (JSONArray) jsonData;
+                int length = jsonArray.length();
+                for (int jsonIndex = 0; jsonIndex < length; ++jsonIndex) {
+                    JSONObject jsonObject = jsonArray.getJSONObject(jsonIndex);
+                    method.invoke(this, jsonObject);
+                }
+            } else if (jsonData instanceof JSONObject) {
+                method.invoke(this, (JSONObject) jsonData);
+            }
+        } catch (Exception e) {
+            throw new IOException(e);
+        }
+        return this.numberCreated;
+    }
+
+    private long writeValues() {
+        this.numberRead = 0L;
+
+        try {
+            boolean beganTransaction = false;
+            if (this.transactionTimeout > -1) {
+                beganTransaction = 
TransactionUtil.begin(this.transactionTimeout);
+                Debug.logImportant("Transaction Timeout set to " + 
this.transactionTimeout / 3600 + " hours ("
+                        + this.transactionTimeout + " seconds)", module);
+            }
+
+            try {
+                if (!this.valuesToCreate.isEmpty()) {
+                    this.writeValues(this.valuesToCreate);
+                    numberRead = numberRead + this.valuesToCreate.size();
+                    this.valuesToCreate.clear();
+                }
+
+                if (!this.valuesToDelete.isEmpty()) {
+                    this.delegator.removeAll(this.valuesToDelete);
+                    numberRead = numberRead + this.valuesToDelete.size();
+                    this.valuesToDelete.clear();
+                }
+                if (!this.valuesToUpdate.isEmpty()) {
+                    this.writeValues(this.valuesToUpdate);
+                    numberRead = numberRead + this.valuesToUpdate.size();
+                    this.valuesToUpdate.clear();
+                }
+
+                TransactionUtil.commit(beganTransaction);
+            } catch (IllegalArgumentException | GenericEntityException e1) {
+                String errMsg = "An error occurred saving the data, rolling 
back transaction (" + beganTransaction
+                        + ")";
+                Debug.logError(e1, errMsg, module);
+                TransactionUtil.rollback(beganTransaction, errMsg, e1);
+            }
+        } catch (GenericTransactionException e) {
+            Debug.logError(e, "A transaction error occurred reading data", 
module);
+        }
+
+        if (Debug.verboseOn()) {
+            Debug.logVerbose("  Detail created : " + this.numberCreated + ", 
skipped : " + this.numberSkipped
+                    + ", updated : " + this.numberUpdated + ", replaced : " + 
this.numberReplaced + ", deleted : "
+                    + this.numberDeleted, module);
+        }
+
+        return this.numberRead;
+    }
+
+    private void writeValues(List<GenericValue> valuesToWrite) throws 
GenericEntityException {
+        if (this.checkDataOnly) {
+            EntityDataAssert.checkValueList(valuesToWrite, this.delegator, 
this.getMessageList());
+        } else {
+            this.delegator.storeAll(valuesToWrite, new 
EntityStoreOptions(this.createDummyFks));
+        }
+
+    }
+}

Propchange: 
ofbiz/ofbiz-framework/trunk/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntityJsonReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
ofbiz/ofbiz-framework/trunk/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntityJsonReader.java
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: 
ofbiz/ofbiz-framework/trunk/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntityJsonReader.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: 
ofbiz/ofbiz-framework/trunk/framework/webtools/config/WebtoolsUiLabels.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webtools/config/WebtoolsUiLabels.xml?rev=1862206&r1=1862205&r2=1862206&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webtools/config/WebtoolsUiLabels.xml 
(original)
+++ ofbiz/ofbiz-framework/trunk/framework/webtools/config/WebtoolsUiLabels.xml 
Thu Jun 27 11:49:22 2019
@@ -98,6 +98,15 @@
         <value 
xml:lang="zh">没有指定的文件名/网址或完整的XML文档,什么也不做。</value>
         <value 
xml:lang="zh-TW">沒有指定的檔案名/網址或完整的XML檔,什麼也不做.</value>
     </property>
+    <property key="EntityImportNoJsonFileSpecified">
+        <value xml:lang="en">No filename/URL or complete JSON document 
specified, doing nothing.</value>
+        <value xml:lang="fr">Pas de fichier, URL ou flux JSON fournit, aucune 
action réalisée.</value>
+        <value xml:lang="it">Nessun nome file/URL o documento JSON completo 
specificato, nientre verrà fatto.</value>
+        <value xml:lang="ja">ファイル名/URLまたは完å…
¨ãªJSON文書が指定されていません。処理を行いません。</value>
+        <value xml:lang="vi">Không Tập tin/URL hoặc tài liệu JSON hoà
n chỉnh nào được xác định nên hệ thống sẽ không làm gì 
cả.</value>
+        <value 
xml:lang="zh">没有指定的文件名/网址或完整的JSON文档,什么也不做。</value>
+        <value 
xml:lang="zh-TW">沒有指定的檔案名/網址或完整的JSON檔,什麼也不做.</value>
+    </property>
     <property key="EntityImportNumberOfEntityToBeProcessed">
         <value xml:lang="en">Got ${numberRead} entities from 
${fileName}</value>
         <value xml:lang="fr">Chargement de ${numberRead} entités depuis 
${fileName}</value>
@@ -116,6 +125,15 @@
         <value 
xml:lang="zh">解析实体XML文件时出错:${errorString}</value>
         <value 
xml:lang="zh-TW">解析資料實體XML檔時出錯:${errorString}</value>
     </property>
+    <property key="EntityImportJsonParsingError">
+        <value xml:lang="en">ERROR parsing Entity Json file: 
${errorString}</value>
+        <value xml:lang="fr">ERREUR dans l'analyse de l'JSON : 
${errorString}</value>
+        <value xml:lang="it">ERRORE di parsing file entità JSON: 
${errorString}</value>
+        <value 
xml:lang="ja">エンティティJSONファイルパース時にエラー: 
${errorString}</value>
+        <value xml:lang="vi">LỖI khi phân tích tập tin JSON Thực 
thể: ${errorString}</value>
+        <value 
xml:lang="zh">解析实体JSON文件时出错:${errorString}</value>
+        <value 
xml:lang="zh-TW">解析資料實體JSON檔時出錯:${errorString}</value>
+    </property>
     <property key="EntityImportPassedFile">
         <value xml:lang="en">Pass ${passes} complete</value>
         <value xml:lang="fr">Passe ${passes} complete</value>
@@ -513,6 +531,32 @@
         <value xml:lang="zh">XML数据导出全部</value>
         <value xml:lang="zh-TW">XML資料匯出全部</value>
     </property>
+    <property key="PageTitleEntityExportJson">
+        <value xml:lang="de">JSON-Daten exportieren</value>
+        <value xml:lang="en">JSON Data Export</value>
+        <value xml:lang="fr">Export de données JSON</value>
+        <value xml:lang="it">Esporta dati in JSON</value>
+        <value xml:lang="ja">JSONデータエクスポート</value>
+        <value xml:lang="pt">Exportação de dados JSON</value>
+        <value xml:lang="ro">Exporta Date in JSON</value>
+        <value xml:lang="th">ส่งออกข้อมูล json</value>
+        <value xml:lang="vi">Kết xuất dữ liệu JSON</value>
+        <value xml:lang="zh">JSON数据导出</value>
+        <value xml:lang="zh-TW">JSON資料匯出</value>
+    </property>
+    <property key="PageTitleEntityExportAllJson">
+        <value xml:lang="de">Alle JSON-Daten exportieren</value>
+        <value xml:lang="en">JSON Data Export All</value>
+        <value xml:lang="fr">Exporter toutes les données JSON</value>
+        <value xml:lang="it">Esporta tutti i dati in JSON</value>
+        <value 
xml:lang="ja">JSONデータをすべてエクスポート</value>
+        <value xml:lang="pt">Exportação de todos os dados JSON</value>
+        <value xml:lang="ro">Exporta Toate Datele in JSON</value>
+        <value xml:lang="th">ส่งออกข้อมูล JSON 
ทั้งหมด</value>
+        <value xml:lang="vi">Kết xuất tất cả dữ liệu JSON</value>
+        <value xml:lang="zh">JSON数据导出全部</value>
+        <value xml:lang="zh-TW">JSON資料匯出全部</value>
+    </property>
     <property key="PageTitleEntityImport">
         <value xml:lang="de">XML-Daten importieren</value>
         <value xml:lang="en">XML Data Import</value>
@@ -539,6 +583,32 @@
         <value xml:lang="zh">XML数据导入目录 </value>
         <value xml:lang="zh-TW">XML資料匯入目錄 </value>
     </property>
+    <property key="PageTitleEntityImportJson">
+        <value xml:lang="de">JSON-Daten importieren</value>
+        <value xml:lang="en">JSON Data Import</value>
+        <value xml:lang="fr">Import de données JSON</value>
+        <value xml:lang="it">Importa dati da JSON</value>
+        <value xml:lang="ja">JSONデータインポート</value>
+        <value xml:lang="pt">Importar dados JSON</value>
+        <value xml:lang="ro">Importa Datele din JSON</value>
+        <value xml:lang="th">นำเข้าข้อมูล json</value>
+        <value xml:lang="vi">Nhập khẩu dữ liệu JSON</value>
+        <value xml:lang="zh">JSON数据导入</value>
+        <value xml:lang="zh-TW">JSON資料匯入</value>
+    </property>
+    <property key="PageTitleEntityImportDirJson">
+        <value xml:lang="de">JSON Datenimport aus Verzeichnis</value>
+        <value xml:lang="en">JSON Data Import Dir</value>
+        <value xml:lang="fr">Import de données JSON depuis un 
répertoire</value>
+        <value xml:lang="it">Importa dati JSON in directory</value>
+        <value 
xml:lang="ja">JSONデータインポートディレクトリ</value>
+        <value xml:lang="pt">Importar dados JSON em diretório</value>
+        <value xml:lang="ro">Importa Datele din JSON in Directory</value>
+        <value xml:lang="th">นำเข้าข้อมูล json ใน 
Directory</value>
+        <value xml:lang="vi">Thư mục nhập khẩu JSON</value>
+        <value xml:lang="zh">JSON数据导入目录 </value>
+        <value xml:lang="zh-TW">JSON資料匯入目錄 </value>
+    </property>
     <property key="PageTitleEntityImportReaders">
         <value xml:lang="de">Leser für XML Datenimport</value>
         <value xml:lang="en">XML Data Import Readers</value>
@@ -1220,6 +1290,19 @@
         <value xml:lang="zh">完成XML文档 (根标签: 
entity-engine-xml)</value>
         <value xml:lang="zh-TW">完成XML檔 (根標簽: 
entity-engine-xml)</value>
     </property>
+    <property key="WebtoolsCompleteJsonData">
+        <value xml:lang="de">Vollständiges JSON dokument</value>
+        <value xml:lang="en">Complete JSON data</value>
+        <value xml:lang="fr">Compléter le data JSON</value>
+        <value xml:lang="it">Documento JSON</value>
+        <value xml:lang="ja">JSONドキュメントを完了する</value>
+        <value xml:lang="pt">Documento JSON completo</value>
+        <value xml:lang="ro">Completeaza documentul JSON</value>
+        <value xml:lang="th">เอกสาร JSON 
เสร็จเรียบร้อยแล้ว</value>
+        <value xml:lang="vi">Hoàn thành tài liệu JSON</value>
+        <value xml:lang="zh">完成JSON文档</value>
+        <value xml:lang="zh-TW">完成JSON檔</value>
+    </property>
     <property key="WebtoolsComponentsLoaded">
         <value xml:lang="de">Komponenten geladen</value>
         <value xml:lang="en">Loaded Components</value>
@@ -1997,6 +2080,18 @@
         <value xml:lang="zh">实体XML工具</value>
         <value xml:lang="zh-TW">資料實體XML工具</value>
     </property>
+    <property key="WebtoolsEntityJSONTools">
+        <value xml:lang="de">Entität JSON Tools</value>
+        <value xml:lang="en">Entity JSON Tools</value>
+        <value xml:lang="fr">Outils JSON d'entité</value>
+        <value xml:lang="it">Strumenti JSON per entità</value>
+        <value xml:lang="ja">エンティティJSONツール</value>
+        <value xml:lang="ro">Instrumente pentru Entitatea JSON</value>
+        <value xml:lang="th">เครื่องมือ Entity JSON 
</value>
+        <value xml:lang="vi">Công cụ JSON Thực thể</value>
+        <value xml:lang="zh">实体JSON工具</value>
+        <value xml:lang="zh-TW">資料實體XML工具</value>
+    </property>
     <property key="WebtoolsEnvName">
         <value xml:lang="de">Umgebungsname</value>
         <value xml:lang="en">Env Name</value>
@@ -2186,6 +2281,19 @@
         <value xml:lang="zh">从数据源导出XML</value>
         <value xml:lang="zh-TW">從資料源匯出XML</value>
     </property>
+    <property key="WebtoolsExportJSONFromDataSource">
+        <value xml:lang="de">JSON Export aus der Datenquelle</value>
+        <value xml:lang="en">JSON Export from DataSource(s)</value>
+        <value xml:lang="fr">Export JSON depuis les sources de données</value>
+        <value xml:lang="it">Esportazione JSON da Datasource</value>
+        <value 
xml:lang="ja">データソースからJSONをエクスポート</value>
+        <value xml:lang="pt">Exportar de JSON DataSource(s)</value>
+        <value xml:lang="ro">Exporta Sursa Date in JSON</value>
+        <value xml:lang="th">JSON 
ที่มาจากแหล่งข้อมูล</value>
+        <value xml:lang="vi">Kết xuất JSON từ nguồn dữ liệu</value>
+        <value xml:lang="zh">从数据源导出JSON</value>
+        <value xml:lang="zh-TW">從資料源匯出JSON</value>
+    </property>
     <property key="WebtoolsExportable">
         <value xml:lang="de">Exportierbar</value>
         <value xml:lang="en">Exportable</value>
@@ -2640,6 +2748,19 @@
         <value xml:lang="zh">把XML导入到数据源</value>
         <value xml:lang="zh-TW">把XML匯入到資料源</value>
     </property>
+    <property key="WebtoolsJsonImportToDataSource">
+        <value xml:lang="de">JSON-Import in DataSource(n)</value>
+        <value xml:lang="en">JSON Import to DataSource(s)</value>
+        <value xml:lang="fr">Import JSON vers la source de données</value>
+        <value xml:lang="it">Importazione JSON in Datasource</value>
+        <value 
xml:lang="ja">データソースにJSONをインポート</value>
+        <value xml:lang="pt">Importar JSON para DataSource(s)</value>
+        <value xml:lang="ro">Importa Sursa de Date din JSON</value>
+        <value xml:lang="th">นำเข้า JSON 
ไปยังแหล่งข้อมูล</value>
+        <value xml:lang="vi">Nhập khẩu JSON từ nguồn dữ 
liệu</value>
+        <value xml:lang="zh">把JSON导入到数据源</value>
+        <value xml:lang="zh-TW">把JSON匯入到資料源</value>
+    </property>
     <property key="WebtoolsImportantLogLevel">
         <value xml:lang="de">Wichtig</value>
         <value xml:lang="en">Important</value>
@@ -5942,7 +6063,7 @@
     <property key="WebtoolsXMLExportInfo">
         <value xml:lang="de">Hier Seite können Daten aus der Datenbank 
exportiert werden. Die exportierten Dokumente werden in einem XML-root-tag 
"&lt;entity-engine-xml&gt;" enthalten sein. Es wird für jede Entität in dem 
für diese webapp konfigurierten Delegator eine eigene Datei erstellt.</value>
         <value xml:lang="en">This page can be used to export data from the 
database. The exported documents will have a root tag of 
"&lt;entity-engine-xml&gt;". There will be one file for each Entity in the 
configured delegator for this webapp.</value>
-        <value xml:lang="fr">Cette page peut être utilisée pour exporter des 
données depuis la base. Les documents exportés auront une balise de racine de 
"&lt;entity-engine-xml&gt;". Il y aura un dossier pour chaque entité dans le 
delegator configuré pour cette webapp.</value>
+        <value xml:lang="fr">Cette page peut être utilisée pour exporter des 
données depuis la base. Les documents exportés auront une balise de racine de 
"&lt;entity-engine-xml&gt;". Il y aura un fichier créé pour chaque entité 
dans le delegator configuré pour cette webapp.</value>
         <value xml:lang="it">Questa pagina può essere usata per esportare i 
dati dal database. I documenti esportati avranno un root tag 
"&lt;entity-engine-xml&gt;". C'è un file per ogni Entità nel delegator 
configurato per questa applicazione web.</value>
         <value 
xml:lang="ja">このページでデータベースからデータをエクスポートすることができます。エクスポートするドキュメントには"&lt;entity-engine-xml&gt;"ルートタグがあります。Webアプリケーションに設定されたデリゲータの中のそれぞれのエンティティに対して1つのファイルが作成されます。</value>
         <value xml:lang="pt">Esta página pode ser utilizado para exportar 
dados do banco de dados. Os documentos de exportação terão uma tag 
raiz de " &lt;entity-engine-xml&gt;". Haverá um arquivo para cada entidade 
do delegator configurado para essa webapp.</value>
@@ -5952,6 +6073,43 @@
         <value xml:lang="zh">本页面用于从数据库导出数据 
导出的文档会有一个"&lt;entity-engine-xml&gt;"的根æ 
‡ç­¾åœ¨ä¸ºè¿™ä¸ªåº”用é…
ç½®çš„代表中,会对每个实体有一个文件。</value>
         <value xml:lang="zh-TW">本頁面用於從資料庫匯出資料 
匯出的檔會有一個"&lt;entity-engine-xml&gt;"的æ 
¹æ¨™ç°½åœ¨ç‚ºé€™å€‹æ‡‰ç”¨é…
ç½®çš„代表中,會對每個資料實體有一個檔.&lt;/entity-engine-xml&gt;</value>
     </property>
+    <property key="WebtoolsWroteNRecordsToJSONFile">
+        <value xml:lang="de">Es wurden ${numberWritten} Datensätze in die 
Datei ${parameters.filename} geschrieben.</value>
+        <value xml:lang="en">Wrote ${numberWritten} records to JSON file 
${parameters.filename}.</value>
+        <value xml:lang="fr">Ecrire ${numberWritten} les enregistrements dans 
le fichier JSON ${parameters.filename}.</value>
+        <value xml:lang="it">Scritti ${numberWritten} records su file JSON 
${parameters.filename}.</value>
+        <value xml:lang="ja">${numberWritten} 
レコードを、JSONファイル ${parameters.filename} 
に書き出しました。</value>
+        <value xml:lang="pt">Escreveu  ${numberWritten} registros para o 
arquivo JSON ${parameters.filename}.</value>
+        <value xml:lang="th">เขียน ${numberWritten} 
บันทึกมูล XML ไฟล์ ${parameters.filename}.</value>
+        <value xml:lang="vi">Đã ghi ${numberWritten} bản ghi tới tập 
tin JSON ${parameters.filename}.</value>
+        <value 
xml:lang="zh">把${numberWritten}个记录写到JSON文件${parameters.filename}。</value>
+        <value 
xml:lang="zh-TW">把${numberWritten}個記錄寫到JSON檔${parameters.filename}.</value>
+    </property>
+    <property key="WebtoolsWroteJSONForAllDataIn">
+        <value xml:lang="de">Es wurde JSON für alle Daten in 
${numberofEntities} Entitäten geschrieben.</value>
+        <value xml:lang="en">Wrote JSON for all data in ${numberOfEntities} 
entities.</value>
+        <value xml:lang="fr">Ecrire JSON pour toute les donnée inclues 
${numberOfEntities} Entités.</value>
+        <value xml:lang="it">Scritti JSON per tutti i dati in 
${numberOfEntities} entità.</value>
+        <value xml:lang="ja">${numberOfEntities} 
エンティティのすべてのデータをXMLファイルに書き出しました。</value>
+        <value xml:lang="pt">Escreveu JSON para todos os dados em 
${numberOfEntities} entidades.</value>
+        <value xml:lang="th">เขียน JSON 
สำหรับข้อมูลทั้งหมดใน 
${numberOfEntities} entities.</value>
+        <value xml:lang="vi">Đã ghi JSON cho tất cả dữ liệu trong 
${numberOfEntities} Thực thể.</value>
+        <value xml:lang="zh">为${numberOfEntities}个实体中的å…
¨éƒ¨æ•°æ®å†™åˆ°JSON。</value>
+        <value xml:lang="zh-TW">為${numberOfEntities}個資料實體中的å…
¨éƒ¨è³‡æ–™å¯«åˆ°JSON.</value>
+    </property>
+    <property key="WebtoolsJSONExportInfo">
+        <value xml:lang="de">Hier Seite können Daten aus der Datenbank 
exportiert werden. Es wird für jede Entität in dem für diese webapp 
konfigurierten Delegator eine eigene Datei erstellt.</value>
+        <value xml:lang="en">This page can be used to export data from the 
database. There will be one file for each Entity in the configured delegator 
for this webapp.</value>
+        <value xml:lang="fr">Cette page peut être utilisée pour exporter des 
données depuis la base. Il y aura un fichier créé pour chaque entité dans 
le delegator configuré pour cette webapp.</value>
+        <value xml:lang="it">Questa pagina può essere usata per esportare i 
dati dal database. C'è un file per ogni Entità nel delegator configurato per 
questa applicazione web.</value>
+        <value 
xml:lang="ja">このページでデータベースからデータをエクスポートすることができます。Webアプリケーションに設定されたデリゲータの中のそれぞれのエンティティに対して1つのファイルが作成されます。</value>
+        <value xml:lang="pt">Esta página pode ser utilizado para exportar 
dados do banco de dados. Haverá um arquivo para cada entidade do delegator 
configurado para essa webapp.</value>
+        <value xml:lang="ro">Aceasta pagina poate fi folosita pentru 
exportarea datelor din  database. Exista un file pentru orice Entitate din 
delegatorul configurat pentru aceasta aplicatie web.</value>
+        <value 
xml:lang="th">หน้านี้ใช้การส่งออกข้อมูลจากฐานข้อมูลการส่
 มี 1 ไฟล์สำหรับตัวอย่าง Entity 
ในการสร้างตัวแทนสำหรับโปรแกรมประยุกต์นี้</value>
+        <value xml:lang="vi">Giao diện bạn đang sử dụng cung cấp 
chức năng Kết xuất dữ liệu từ Cơ sở dữ liệu.( có 01 Tập 
tin với mỗi Thực thể của Ứng dụng này)</value>
+        <value xml:lang="zh">本页面用于从数据库导出数据 的根æ 
‡ç­¾åœ¨ä¸ºè¿™ä¸ªåº”用é…
ç½®çš„代表中,会对每个实体有一个文件。</value>
+        <value xml:lang="zh-TW">本頁面用於從資料庫匯出資料 的æ 
¹æ¨™ç°½åœ¨ç‚ºé€™å€‹æ‡‰ç”¨é…
ç½®çš„代表中,會對每個資料實體有一個檔.</value>
+    </property>
     <property key="WebtoolsXMLImportInfo">
         <value xml:lang="de">Hier können zuvor exportierte Entitäten XML 
Dateien wieder in die Datenbank importiert werden. Diese Dokumente haben eine 
XML-root-tag "&lt;entity-engine-xml&gt;".</value>
         <value xml:lang="en">This page can be used to import exported Entity 
Engine XML documents. These documents all have a root tag of 
"&lt;entity-engine-xml&gt;".</value>
@@ -5965,6 +6123,19 @@
         <value xml:lang="zh">本页面用于导å…
¥å¯¼å‡ºçš„实体引擎XML文档。这些文档都有一个根标签 
"&lt;entity-engine-xml&gt;".</value>
         <value xml:lang="zh-TW">本頁面用於匯å…
¥åŒ¯å‡ºçš„資料實體引擎XML檔.這些檔都有一個根標簽 
"&lt;entity-engine-xml&gt;".&lt;/entity-engine-xml&gt;</value>
     </property>
+    <property key="WebtoolsJSONImportInfo">
+        <value xml:lang="de">Hier können zuvor exportierte Entitäten JSON 
Dateien wieder in die Datenbank importiert werden.</value>
+        <value xml:lang="en">This page can be used to import exported Entity 
Engine JSON data.</value>
+        <value xml:lang="fr">Cette page peut être utilisée pour importer des 
documents JSON exportés par le moteur d'entité.".</value>
+        <value xml:lang="it">Questa pagina può essere usata per importare 
documenti JSON contenenti export di Entita'.</value>
+        <value 
xml:lang="ja">このページでエクスポートされたエンティティエンジンJSONドキュメントをインポートすることができます。</value>
+        <value xml:lang="pt">Esta página pode ser utilizado para 
importação e exportação de documentos JSON do Engine de 
Entidades.</value>
+        <value xml:lang="ro">Aceasta pagina nu poate fi folosita pentru 
importarea exportarea documentelor JSON de Entity Engine.</value>
+        <value 
xml:lang="th">หน้านี้ใช้การนำเข้าข้อมูลที่มีการส่งออกเอนติตี้เอนจินเอกสาร
 JSON โดยใช้คำสั่ง</value>
+        <value xml:lang="vi">Giao diện bạn đang sử dụng cung cấp 
chức năng Nhập khẩu dữ liệu từ các Tài liệu Thực thể 
JSON.</value>
+        <value xml:lang="zh">本页面用于导å…
¥å¯¼å‡ºçš„实体引擎JSON文档。</value>
+        <value xml:lang="zh-TW">本頁面用於匯å…
¥åŒ¯å‡ºçš„資料實體引擎JSON檔</value>
+    </property>
     <property key="WebtoolsYouMayCreateAnEntity">
         <value xml:lang="de">You may create an Entity ${entityName} by 
entering the values you want, and clicking Create.</value>
         <value xml:lang="en">You may create an Entity ${entityName} by 
entering the values you want, and clicking Create.</value>

Added: 
ofbiz/ofbiz-framework/trunk/framework/webtools/groovyScripts/entity/JsonDsDump.groovy
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webtools/groovyScripts/entity/JsonDsDump.groovy?rev=1862206&view=auto
==============================================================================
--- 
ofbiz/ofbiz-framework/trunk/framework/webtools/groovyScripts/entity/JsonDsDump.groovy
 (added)
+++ 
ofbiz/ofbiz-framework/trunk/framework/webtools/groovyScripts/entity/JsonDsDump.groovy
 Thu Jun 27 11:49:22 2019
@@ -0,0 +1,365 @@
+/*
+ * 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 java.util.*
+import java.io.*
+import org.apache.ofbiz.base.util.*
+import org.apache.ofbiz.entity.model.*
+import org.apache.ofbiz.entity.util.*
+import org.apache.ofbiz.entity.transaction.*
+import org.apache.ofbiz.entity.condition.*
+
+outpath = parameters.outpath
+filename = parameters.filename
+maxRecStr = parameters.maxrecords
+entitySyncId = parameters.entitySyncId
+passedEntityNames = null
+if (parameters.entityName) passedEntityNames = parameters.entityName 
instanceof Collection ? parameters.entityName as TreeSet : 
[parameters.entityName] as TreeSet
+
+// get the max records per file setting and convert to a int
+maxRecordsPerFile = 0
+if (maxRecStr) {
+    try {
+        maxRecordsPerFile = Integer.parseInt(maxRecStr)
+    }
+    catch (Exception e) {
+    }
+}
+
+preConfiguredSetName = parameters.preConfiguredSetName
+if ("Product1".equals(preConfiguredSetName)) {
+    passedEntityNames = new LinkedHashSet()
+    passedEntityNames.add("DataResource")
+    passedEntityNames.add("Facility")
+    passedEntityNames.add("ProdCatalog")
+    passedEntityNames.add("Product")
+    passedEntityNames.add("ProductCategory")
+    passedEntityNames.add("ProductFeatureCategory")
+    passedEntityNames.add("ProductFeatureType")
+    passedEntityNames.add("ProductPriceRule")
+    passedEntityNames.add("ProductPromo")
+} else if ("Product2".equals(preConfiguredSetName)) {
+    passedEntityNames = new LinkedHashSet()
+    passedEntityNames.add("Content")
+    passedEntityNames.add("ElectronicText")
+    passedEntityNames.add("FacilityLocation")
+    passedEntityNames.add("ProdCatalogCategory")
+    passedEntityNames.add("ProdCatalogRole")
+    passedEntityNames.add("ProductAssoc")
+    passedEntityNames.add("ProductAttribute")
+    passedEntityNames.add("ProductCategoryMember")
+    passedEntityNames.add("ProductCategoryRollup")
+    passedEntityNames.add("ProductFacility")
+    passedEntityNames.add("ProductFeature")
+    passedEntityNames.add("ProductFeatureCategoryAppl")
+    passedEntityNames.add("ProductKeyword")
+    passedEntityNames.add("ProductPrice")
+    passedEntityNames.add("ProductPriceAction")
+    passedEntityNames.add("ProductPriceCond")
+    passedEntityNames.add("ProductPromoCode")
+    passedEntityNames.add("ProductPromoCategory")
+    passedEntityNames.add("ProductPromoProduct")
+    passedEntityNames.add("ProductPromoRule")
+} else if ("Product3".equals(preConfiguredSetName)) {
+    passedEntityNames = new LinkedHashSet()
+    passedEntityNames.add("ProdCatalogInvFacility")
+    passedEntityNames.add("ProductContent")
+    passedEntityNames.add("ProductFacilityLocation")
+    passedEntityNames.add("ProductFeatureAppl")
+    passedEntityNames.add("ProductFeatureDataResource")
+    passedEntityNames.add("ProductFeatureGroup")
+    passedEntityNames.add("ProductPriceChange")
+    passedEntityNames.add("ProductPromoAction")
+    passedEntityNames.add("ProductPromoCodeEmail")
+    passedEntityNames.add("ProductPromoCodeParty")
+    passedEntityNames.add("ProductPromoCond")
+} else if ("Product4".equals(preConfiguredSetName)) {
+    passedEntityNames = new LinkedHashSet()
+    passedEntityNames.add("InventoryItem")
+    passedEntityNames.add("ProductFeatureCatGrpAppl")
+    passedEntityNames.add("ProductFeatureGroupAppl")
+} else if ("CatalogExport".equals(preConfiguredSetName)) {
+    passedEntityNames = new LinkedHashSet()
+    passedEntityNames.add("ProdCatalogCategoryType")
+    passedEntityNames.add("ProdCatalog")
+    passedEntityNames.add("ProductCategoryType")
+    passedEntityNames.add("ProductCategory")
+    passedEntityNames.add("ProductCategoryRollup")
+    passedEntityNames.add("ProdCatalogCategory")
+    passedEntityNames.add("ProductFeatureType")
+    passedEntityNames.add("ProductFeatureCategory")
+
+    passedEntityNames.add("DataResource")
+    passedEntityNames.add("Content")
+    passedEntityNames.add("ElectronicText")
+
+    passedEntityNames.add("ProductType")
+    passedEntityNames.add("Product")
+    passedEntityNames.add("ProductAttribute")
+    passedEntityNames.add("GoodIdentificationType")
+    passedEntityNames.add("GoodIdentification")
+    passedEntityNames.add("ProductPriceType")
+    passedEntityNames.add("ProductPrice")
+
+    passedEntityNames.add("ProductPriceRule")
+    passedEntityNames.add("ProductPriceCond")
+    passedEntityNames.add("ProductPriceAction")
+    //passedEntityNames.add("ProductPriceChange")
+
+    passedEntityNames.add("ProductPromo")
+    passedEntityNames.add("ProductPromoCode")
+    passedEntityNames.add("ProductPromoCategory")
+    passedEntityNames.add("ProductPromoProduct")
+    passedEntityNames.add("ProductPromoRule")
+    passedEntityNames.add("ProductPromoAction")
+    passedEntityNames.add("ProductPromoCodeEmail")
+    passedEntityNames.add("ProductPromoCodeParty")
+    passedEntityNames.add("ProductPromoCond")
+
+    passedEntityNames.add("ProductCategoryMember")
+    passedEntityNames.add("ProductAssoc")
+    passedEntityNames.add("ProductContent")
+
+    passedEntityNames.add("ProductFeature")
+    passedEntityNames.add("ProductFeatureCategoryAppl")
+    passedEntityNames.add("ProductFeatureAppl")
+    passedEntityNames.add("ProductFeatureDataResource")
+    passedEntityNames.add("ProductFeatureGroup")
+    passedEntityNames.add("ProductFeatureCatGrpAppl")
+    passedEntityNames.add("ProductFeatureGroupAppl")
+
+    //passedEntityNames.add("ProductKeyword")
+}
+
+if (entitySyncId) {
+    passedEntityNames = 
org.apache.ofbiz.entityext.synchronization.EntitySyncContext.getEntitySyncModelNamesToUse(dispatcher,
 entitySyncId)
+}
+checkAll = "true".equals(parameters.checkAll)
+tobrowser = parameters.tobrowser != null
+context.tobrowser = tobrowser
+
+entityFromCond = null
+entityThruCond = null
+entityDateCond = null
+if (entityFrom) {
+    entityFromCond = EntityCondition.makeCondition("lastUpdatedTxStamp", 
EntityComparisonOperator.GREATER_THAN, entityFrom)
+}
+if (entityThru) {
+    entityThruCond = EntityCondition.makeCondition("lastUpdatedTxStamp", 
EntityComparisonOperator.LESS_THAN, entityThru)
+}
+if (entityFromCond && entityThruCond) {
+    entityDateCond = EntityCondition.makeCondition(entityFromCond, 
EntityJoinOperator.AND, entityThruCond)
+} else if (entityFromCond) {
+    entityDateCond = entityFromCond
+} else if (entityThruCond) {
+    entityDateCond = entityThruCond
+}
+
+reader = delegator.getModelReader()
+modelEntities = reader.getEntityCache().values() as TreeSet
+context.modelEntities = modelEntities
+
+if (passedEntityNames) {
+    if (tobrowser) {
+        session.setAttribute("jsonrawdump_entitylist", passedEntityNames)
+        session.setAttribute("entityDateCond", entityDateCond)
+    } else {
+        efo = new EntityFindOptions(true, 
EntityFindOptions.TYPE_SCROLL_INSENSITIVE, EntityFindOptions.CONCUR_READ_ONLY, 
true)
+        numberOfEntities = passedEntityNames?.size() ?: 0
+        context.numberOfEntities = numberOfEntities
+        numberWritten = 0
+        currentIndexEntity = 0
+
+        // single file
+        if (filename && numberOfEntities) {
+            if (outpath && !(filename.contains("/") && 
filename.contains("\\"))) {
+                filename = outpath + File.separator + filename;
+            }
+            writer = new PrintWriter(new BufferedWriter(new 
OutputStreamWriter(new FileOutputStream(filename), "UTF-8")))
+            writer.println('[')
+
+            passedEntityNames.each { curEntityName ->
+                if (entityFrom) {
+                    curModelEntity = reader.getModelEntity(curEntityName)
+                    if (curModelEntity instanceof ModelViewEntity) {
+                        return
+                    }
+                }
+                currentIndexEntity++;
+                beganTransaction = TransactionUtil.begin(3600)
+                try {
+                    me = reader.getModelEntity(curEntityName)
+                    if (me.getNoAutoStamp() || me instanceof ModelViewEntity) {
+                        values = delegator.find(curEntityName, null, null, 
null, me.getPkFieldNames(), efo)
+                    } else {
+                        values = delegator.find(curEntityName, entityDateCond, 
null, null, UtilMisc.toList("-createdTxStamp"), efo)
+                    }
+
+                    curNumberWritten = 0
+                    writer.print('{');
+                    writer.print('"');
+                    writer.print(curEntityName);
+                    writer.print('"');
+                    writer.print(':');
+                    writer.print('[');
+                    while (value = values.next()) {
+                        
org.apache.ofbiz.webtools.EntityJsonHelper.writeJsonText(writer, value)
+                        numberWritten++
+                        curNumberWritten++
+                        if (curNumberWritten % 500 == 0 || curNumberWritten == 
1) {
+                            Debug.log("Records written [$curEntityName]: 
$curNumberWritten Total: $numberWritten")
+                        }
+                        if(curNumberWritten < 
values.getResultsSizeAfterPartialList()) {
+                            writer.print(",");
+                        }
+                    }
+                    writer.print("]}");
+                    values.close()
+                    Debug.log("Wrote [$curNumberWritten] from entity : 
$curEntityName")
+                    TransactionUtil.commit(beganTransaction)
+                } catch (Exception e) {
+                    errMsg = "Error reading data for JSON export:"
+                    Debug.logError(e, errMsg, "JSP")
+                    TransactionUtil.rollback(beganTransaction, errMsg, e)
+                }
+                if(currentIndexEntity < numberOfEntities) {
+                    writer.println(',');
+                } else {
+                    writer.println('');
+                }
+            }
+            writer.print(']')
+            writer.close()
+            Debug.log("Total records written from all entities: 
$numberWritten")
+            context.numberWritten = numberWritten
+        }
+
+        // multiple files in a directory
+        results = []
+        fileNumber = 1
+        context.results = results
+        if (outpath && !filename) {
+            outdir = new File(outpath)
+            if (!outdir.exists()) {
+                outdir.mkdir()
+            }
+            if (outdir.isDirectory() && outdir.canWrite()) {
+                passedEntityNames.each { curEntityName ->
+                    numberWritten = 0
+                    fileName = preConfiguredSetName ? 
UtilFormatOut.formatPaddedNumber((long) fileNumber, 3) + "_" : ""
+                    fileName = fileName + curEntityName
+
+                    values = null
+                    beganTransaction = false
+                    try {
+                        beganTransaction = TransactionUtil.begin(3600)
+
+                        me = delegator.getModelEntity(curEntityName)
+                        if (me instanceof ModelViewEntity) {
+                            results.add("[$fileNumber] [vvv] $curEntityName 
skipping view entity")
+                            return
+                        }
+                        if (me.getNoAutoStamp() || me instanceof 
ModelViewEntity) {
+                            values = delegator.find(curEntityName, null, null, 
null, me.getPkFieldNames(), efo)
+                        } else {
+                            values = delegator.find(curEntityName, 
entityDateCond, null, null, me.getPkFieldNames(), efo)
+                        }
+                        isFirst = true
+                        writer = null
+                        fileSplitNumber = 1
+                        curValueCount = 0
+                        while (value = values.next()) {
+                            //Don't bother writing the file if there's nothing
+                            //to put into it
+                            if (isFirst) {
+                                writer = new PrintWriter(new 
BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(outdir, 
fileName +".json")), "UTF-8")))
+                                writer.println('[');
+                                writer.print('{');
+                                writer.print('"');
+                                writer.print(curEntityName);
+                                writer.print('"');
+                                writer.print(':');
+                                writer.print('[')
+                                isFirst = false
+                            }
+                            
org.apache.ofbiz.webtools.EntityJsonHelper.writeJsonText(writer, value)
+                            numberWritten++
+                            curValueCount++
+                            if(curValueCount < 
values.getResultsSizeAfterPartialList()) {
+                                writer.println(',')
+                            }
+
+                            // split into small files
+                            if (maxRecordsPerFile > 0 && (numberWritten % 
maxRecordsPerFile == 0)) {
+                                fileSplitNumber++
+                                // close the file
+                                writer.println("]}")
+                                writer.print("]")
+                                writer.close()
+
+                                // create a new file
+                                splitNumStr = 
UtilFormatOut.formatPaddedNumber((long) fileSplitNumber, 3)
+                                writer = new PrintWriter(new 
BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(outdir, 
fileName + "_" + splitNumStr +".json")), "UTF-8")))
+                                writer.println('[');
+                                writer.print('{');
+                                writer.print('"');
+                                writer.print(curEntityName);
+                                writer.print('"');
+                                writer.print(':');
+                                writer.print('[');
+                            }
+
+                            if (numberWritten % 500 == 0 || numberWritten == 
1) {
+                                Debug.log("Records written [$curEntityName]: 
$numberWritten")
+                            }
+
+                        }
+                        if (writer) {
+                            writer.println("]}")
+                            writer.print("]")
+                            writer.close()
+                            String thisResult = "[$fileNumber] 
[$numberWritten] $curEntityName wrote $numberWritten records"
+                            Debug.log(thisResult)
+                            results.add(thisResult)
+                        } else {
+                            thisResult = "[$fileNumber] [---] $curEntityName 
has no records, not writing file"
+                            Debug.log(thisResult)
+                            results.add(thisResult)
+                        }
+                        values.close()
+                    } catch (Exception ex) {
+                        if (values != null) {
+                            values.close()
+                        }
+                        thisResult = "[$fileNumber] [xxx] Error when writing 
$curEntityName: $ex"
+                        Debug.log(thisResult)
+                        results.add(thisResult)
+                        TransactionUtil.rollback(beganTransaction, thisResult, 
ex)
+                    } finally {
+                        // only commit the transaction if we started one... 
this will throw an exception if it fails
+                        TransactionUtil.commit(beganTransaction)
+                    }
+                    fileNumber++
+                }
+            }
+        }
+    }
+} else {
+    context.numberOfEntities = 0
+}

Propchange: 
ofbiz/ofbiz-framework/trunk/framework/webtools/groovyScripts/entity/JsonDsDump.groovy
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
ofbiz/ofbiz-framework/trunk/framework/webtools/groovyScripts/entity/JsonDsDump.groovy
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: 
ofbiz/ofbiz-framework/trunk/framework/webtools/groovyScripts/entity/JsonDsDump.groovy
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/ofbiz-framework/trunk/framework/webtools/servicedef/services.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webtools/servicedef/services.xml?rev=1862206&r1=1862205&r2=1862206&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webtools/servicedef/services.xml 
(original)
+++ ofbiz/ofbiz-framework/trunk/framework/webtools/servicedef/services.xml Thu 
Jun 27 11:49:22 2019
@@ -56,6 +56,36 @@ under the License.
         <attribute name="placeholderValues" type="java.util.Map" mode="IN" 
optional="true"/>
         <attribute name="messages" type="List" mode="OUT" optional="false"/>
     </service>
+    <service name="parseEntityJsonFile" engine="java"
+             location="org.apache.ofbiz.webtools.WebToolsServices" 
invoke="parseEntityJsonFile" auth="true" use-transaction="false">
+        <description>Parses an entity xml file or an entity xml 
text</description>
+        <permission-service service-name="entityMaintPermCheck" 
main-action="VIEW"/>
+        <attribute name="url" type="java.net.URL" mode="IN" optional="true"/>
+        <attribute name="xmltext" type="String" mode="IN" optional="true" 
allow-html="any"/>
+        <attribute name="onlyInserts" type="String" mode="IN" optional="true"/>
+        <attribute name="maintainTimeStamps" type="String" mode="IN" 
optional="true"/>
+        <attribute name="txTimeout" type="Integer" mode="IN" optional="true"/>
+        <attribute name="createDummyFks" type="String" mode="IN" 
optional="true"/>
+        <attribute name="checkDataOnly" type="String" mode="IN" 
optional="true"/>
+        <attribute name="placeholderValues" type="java.util.Map" mode="IN" 
optional="true"/>
+        <attribute name="rowProcessed" type="Long" mode="OUT" 
optional="false"/>
+    </service>
+    <service name="entityImportJson" engine="java"
+             location="org.apache.ofbiz.webtools.WebToolsServices" 
invoke="entityImportJson" auth="true" use-transaction="false">
+        <description>Imports an entity xml file or text string</description>
+        <permission-service service-name="entityMaintPermCheck" 
main-action="VIEW"/>
+        <attribute name="filename" type="String" mode="IN" optional="true" 
allow-html="any"/>
+        <attribute name="fmfilename" type="String" mode="IN" optional="true" 
allow-html="any"/>
+        <attribute name="fulltext" type="String" mode="IN" optional="true" 
allow-html="any"/>
+        <attribute name="isUrl" type="String" mode="IN" optional="true"/>
+        <attribute name="onlyInserts" type="String" mode="IN" optional="true"/>
+        <attribute name="maintainTimeStamps" type="String" mode="IN" 
optional="true"/>
+        <attribute name="createDummyFks" type="String" mode="IN" 
optional="true"/>
+        <attribute name="checkDataOnly" type="String" mode="IN" 
optional="true"/>
+        <attribute name="txTimeout" type="Integer" mode="IN" optional="true"/>
+        <attribute name="placeholderValues" type="java.util.Map" mode="IN" 
optional="true"/>
+        <attribute name="messages" type="List" mode="OUT" optional="false"/>
+    </service>
     <service name="entityImportDir" engine="java"
             location="org.apache.ofbiz.webtools.WebToolsServices" 
invoke="entityImportDir" auth="true" use-transaction="false">
         <description>Imports all entity xml files contained in a 
directory</description>
@@ -71,6 +101,21 @@ under the License.
         <attribute name="placeholderValues" type="java.util.Map" mode="IN" 
optional="true"/>
         <attribute name="messages" type="List" mode="OUT" optional="false"/>
     </service>
+    <service name="entityImportDirJson" engine="java"
+             location="org.apache.ofbiz.webtools.WebToolsServices" 
invoke="entityImportDirJson" auth="true" use-transaction="false">
+        <description>Imports all entity json files contained in a 
directory</description>
+        <permission-service service-name="entityMaintPermCheck" 
main-action="VIEW"/>
+        <attribute name="path" type="String" mode="IN" optional="true"/>
+        <attribute name="onlyInserts" type="String" mode="IN" optional="true"/>
+        <attribute name="maintainTimeStamps" type="String" mode="IN" 
optional="true"/>
+        <attribute name="createDummyFks" type="String" mode="IN" 
optional="true"/>
+        <attribute name="checkDataOnly" type="String" mode="IN" 
optional="true"/>
+        <attribute name="deleteFiles" type="String" mode="IN" optional="true"/>
+        <attribute name="txTimeout" type="Integer" mode="IN" optional="true"/>
+        <attribute name="filePause" type="Long" mode="IN" optional="true"/>
+        <attribute name="placeholderValues" type="java.util.Map" mode="IN" 
optional="true"/>
+        <attribute name="messages" type="List" mode="OUT" optional="false"/>
+    </service>
     <service name="entityImportReaders" engine="java"
         location="org.apache.ofbiz.webtools.WebToolsServices" 
invoke="entityImportReaders" auth="true" use-transaction="false">
         <description>Imports an entity xml file or text string</description>
@@ -91,6 +136,15 @@ under the License.
         <permission-service service-name="entityMaintPermCheck" 
main-action="VIEW"/>
         <attribute name="outpath" type="String" mode="IN" optional="true"/>
         <attribute name="fromDate" type="Timestamp" mode="IN" optional="true"/>
+        <attribute name="txTimeout" type="Integer" mode="IN" optional="true"/>
+        <attribute name="results" type="List" mode="OUT" optional="false"/>
+    </service>
+    <service name="entityExportAllJson" engine="java"
+             location="org.apache.ofbiz.webtools.WebToolsServices" 
invoke="entityExportAllJson" auth="true" use-transaction="false">
+        <description>Exports all entities into json files</description>
+        <permission-service service-name="entityMaintPermCheck" 
main-action="VIEW"/>
+        <attribute name="outpath" type="String" mode="IN" optional="true"/>
+        <attribute name="fromDate" type="Timestamp" mode="IN" optional="true"/>
         <attribute name="txTimeout" type="Integer" mode="IN" optional="true"/>
         <attribute name="results" type="List" mode="OUT" optional="false"/>
     </service>


Reply via email to