svn commit: r1780683 [2/3] - in /ofbiz/trunk/plugins/birt: ./ config/ data/ groovyScripts/report/ minilang/ servicedef/ src/main/java/org/apache/ofbiz/birt/ src/main/java/org/apache/ofbiz/birt/flexible/ src/main/java/org/apache/ofbiz/birt/report/servle...

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

svn commit: r1780683 [2/3] - in /ofbiz/trunk/plugins/birt: ./ config/ data/ groovyScripts/report/ minilang/ servicedef/ src/main/java/org/apache/ofbiz/birt/ src/main/java/org/apache/ofbiz/birt/flexible/ src/main/java/org/apache/ofbiz/birt/report/servle...

nmalin
Added: ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtServices.java?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtServices.java (added)
+++ ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtServices.java Sat Jan 28 13:22:55 2017
@@ -0,0 +1,823 @@
+/*******************************************************************************
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.apache.ofbiz.birt.flexible;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+import org.xml.sax.SAXException;
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.GeneralException;
+import org.apache.ofbiz.base.util.StringUtil;
+import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilProperties;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.base.util.UtilXml;
+import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
+import org.apache.ofbiz.birt.BirtWorker;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.GenericEntityException;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.entity.condition.EntityCondition;
+import org.apache.ofbiz.entity.condition.EntityConditionList;
+import org.apache.ofbiz.entity.condition.EntityExpr;
+import org.apache.ofbiz.entity.condition.EntityOperator;
+import org.apache.ofbiz.entity.model.ModelEntity;
+import org.apache.ofbiz.entity.model.ModelField;
+import org.apache.ofbiz.entity.util.EntityListIterator;
+import org.apache.ofbiz.entity.util.EntityUtil;
+import org.apache.ofbiz.service.DispatchContext;
+import org.apache.ofbiz.service.GenericServiceException;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.service.ModelService;
+import org.apache.ofbiz.service.ServiceUtil;
+import org.eclipse.birt.core.exception.BirtException;
+import org.eclipse.birt.core.framework.Platform;
+import org.eclipse.birt.report.engine.api.script.IReportContext;
+import org.eclipse.birt.report.model.api.DesignConfig;
+import org.eclipse.birt.report.model.api.DesignElementHandle;
+import org.eclipse.birt.report.model.api.DesignFileException;
+import org.eclipse.birt.report.model.api.IDesignEngine;
+import org.eclipse.birt.report.model.api.IDesignEngineFactory;
+import org.eclipse.birt.report.model.api.ReportDesignHandle;
+import org.eclipse.birt.report.model.api.SessionHandle;
+import org.eclipse.birt.report.model.api.SimpleMasterPageHandle;
+import org.eclipse.birt.report.model.api.SlotHandle;
+import org.eclipse.birt.report.model.api.VariableElementHandle;
+import org.eclipse.birt.report.model.api.activity.SemanticException;
+import org.eclipse.birt.report.model.elements.SimpleMasterPage;
+
+import com.ibm.icu.util.ULocale;
+import org.w3c.dom.Document;
+
+
+/**
+ * Birt Services
+ */
+
+public class BirtServices {
+
+    public static final String module = BirtServices.class.getName();
+    public static final String resource = "BirtUiLabels";
+    public static final String resource_error = "BirtErrorUiLabels";
+    public static final String resourceProduct = "BirtUiLabels";
+
+    /**
+     * Instanciate a new Flexible report, using the data given in parameters and <code>ReportDesignGenerator</code> class.
+     */
+    public static Map<String, Object> createFlexibleReport(DispatchContext dctx, Map<String, Object> context) {
+        ReportDesignGenerator rptGenerator;
+        try {
+            rptGenerator = new ReportDesignGenerator(context, dctx);
+        } catch (Exception e1) {
+            e1.printStackTrace();
+            return ServiceUtil.returnError(e1.getMessage());
+        }
+        try {
+            rptGenerator.buildReport();
+        } catch (Exception e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        return ServiceUtil.returnSuccess();
+    }
+
+    @Deprecated
+    public static Map<String, Object> prepareFlexibleReportOptionFieldsFromEntity(DispatchContext dctx, Map<String, Object> context) {
+        String entityViewName = (String) context.get("entityViewName");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        List<String> listMultiFields = new ArrayList<String>();
+        Delegator delegator = dctx.getDelegator();
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        Map<String, Object> result = new HashMap<String, Object>();
+        Locale locale = (Locale) context.get("locale");
+
+        ModelEntity modelEntity = delegator.getModelEntity(entityViewName);
+        List<String> listFieldsEntity = modelEntity.getAllFieldNames();
+
+        for (String field : listFieldsEntity) {
+            listMultiFields.add(field);
+            ModelField mField = modelEntity.getField(field);
+            String fieldType = mField.getType();
+            String birtType = null;
+            try {
+                Map<String, Object> convertRes = dispatcher.runSync("convertFieldTypeToBirtType", UtilMisc.toMap("fieldType", fieldType, "userLogin", userLogin));
+                birtType = (String) convertRes.get("birtType");
+                if (UtilValidate.isEmpty(birtType)) {
+                    return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorConversionFieldToBirtFailed", locale));
+                }
+            } catch (GenericServiceException e) {
+                e.printStackTrace();
+            }
+            // make more general when report forms have been made so too.
+            if (birtType.equalsIgnoreCase("date-time") || birtType.equalsIgnoreCase("date") || birtType.equalsIgnoreCase("time")) {
+                listMultiFields.add(field + "_fld0_op");
+                listMultiFields.add(field + "_fld0_value");
+                listMultiFields.add(field + "_fld1_op");
+                listMultiFields.add(field + "_fld1_value");
+            }
+        }
+        result.put("listMultiFields", listMultiFields);
+        return result;
+    }
+
+    /**
+     * Perform find data on given view/entity and return these into birt compatible format.
+     * This service is meant to be used as default for View/entity report design
+     *
+     */
+    public static Map<String, Object> callPerformFindFromBirt(DispatchContext dctx, Map<String, Object> context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        IReportContext reportContext = (IReportContext) context.get("reportContext");
+        Locale locale = (Locale) context.get("locale");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        String entityViewName = (String) reportContext.getParameterValue("modelElementName");
+        Map<String, Object> inputFields = (Map<String, Object>) reportContext.getParameterValue("parameters");
+        Map<String, Object> resultPerformFind = new HashMap<String, Object>();
+        Map<String, Object> resultToBirt = null;
+        List<GenericValue> list = null;
+
+        if (UtilValidate.isEmpty(entityViewName)) {
+            entityViewName = (String) inputFields.get("modelElementName");
+            if (UtilValidate.isEmpty(entityViewName)) {
+                return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorEntityViewNotFound", locale));
+            }
+        }
+
+        try {
+            resultPerformFind = dispatcher.runSync("performFind", UtilMisc.<String, Object>toMap("entityName", entityViewName, "inputFields", inputFields, "userLogin", userLogin, "noConditionFind", "Y", "locale", locale));
+            if (ServiceUtil.isError(resultPerformFind)) {
+                return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorRunningPerformFind", locale));
+            }
+        } catch (GenericServiceException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        EntityListIterator listIt = (EntityListIterator) resultPerformFind.get("listIt");
+        try {
+            if (UtilValidate.isNotEmpty(listIt)) {
+                list = listIt.getCompleteList();
+                listIt.close();
+            } else {
+                return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorRunningPerformFind", locale));
+            }
+        } catch (GenericEntityException e) {
+            e.printStackTrace();
+        }
+        resultToBirt = ServiceUtil.returnSuccess();
+        resultToBirt.put("records", list);
+        return resultToBirt;
+    }
+
+    /**
+     * Analyse given master and create report design from its data
+     * Two cases are implemented :
+     * <ul>
+     *     <li>Entity : data retieval is based on a simple view/entity</li>
+     *     <li>Service : data retrieval is based on service</li>
+     * </ul>
+     */
+    public static Map<String, Object> createFlexibleReportFromMaster(DispatchContext dctx, Map<String, Object> context) {
+        Delegator delegator = dctx.getDelegator();
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        Locale locale = (Locale) context.get("locale");
+
+        String reportName = (String) context.get("reportName");
+        String masterContentId = (String) context.get("contentId");
+        String description = (String) context.get("description");
+        String writeFilters = (String) context.get("writeFilters");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+
+        GenericValue masterContentAttribute = null;
+        try {
+            EntityCondition entityCondition = EntityCondition.makeCondition("contentId", masterContentId);
+            masterContentAttribute = EntityUtil.getFirst(delegator.findList("ContentAttribute", entityCondition, null, null, null, false));
+        } catch (GenericEntityException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        if (masterContentAttribute == null) {
+            return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorNoAttributeFound", locale));
+        }
+        String attrName = masterContentAttribute.getString("attrName");
+        String reportContentId;
+        if (attrName.equalsIgnoreCase("Entity")) {
+            String entityViewName = masterContentAttribute.getString("attrValue");
+                ModelEntity modelEntity = delegator.getModelEntity(entityViewName);
+                if (modelEntity == null) {
+                    return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorEntityViewNotExist", locale) + " " + entityViewName);
+                }
+            try {
+                Map<String, Object> resultContent = dispatcher.runSync("createFlexibleReportFromMasterEntityWorkflow", UtilMisc.toMap("entityViewName", entityViewName, "reportName", reportName, "description", description, "writeFilters", writeFilters, "masterContentId", masterContentId, "userLogin", userLogin, "locale", locale));
+                if(ServiceUtil.isError(resultContent)) {
+                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultContent));
+                }
+                reportContentId = (String) resultContent.get("contentId");
+            } catch (GenericServiceException e) {
+                e.printStackTrace();
+                return ServiceUtil.returnError(e.getMessage());
+            }
+        } else if (attrName.equalsIgnoreCase("Service")) {
+            String serviceName = masterContentAttribute.getString("attrValue");
+            try {
+                Map<String, Object> resultContent = dispatcher.runSync("createFlexibleReportFromMasterServiceWorkflow", UtilMisc.toMap("serviceName", serviceName, "reportName", reportName, "description", description, "writeFilters", writeFilters, "masterContentId", masterContentId, "userLogin", userLogin, "locale", locale));
+                if (ServiceUtil.isError(resultContent)) {
+                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultContent));
+                }
+                reportContentId = (String) resultContent.get("contentId");
+            } catch (GenericServiceException e) {
+                e.printStackTrace();
+                return ServiceUtil.returnError(e.getMessage());
+            }
+        } else {
+            // could create other workflows. WebService? Does it need to be independent from Service workflow?
+            return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorCannotDetermineDataSource", locale));
+        }
+
+        // prepare report form to display to allow override
+        String textForm;
+        Map<String, Object> resultFormDisplay;
+        try {
+            resultFormDisplay = dispatcher.runSync("prepareFlexibleReportSearchFormToEdit", UtilMisc.toMap("reportContentId", reportContentId, "userLogin", userLogin, "locale", locale));
+            textForm = (String) resultFormDisplay.get("textForm");
+        } catch (GenericServiceException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorCreatingDefaultSearchForm", locale).concat(": ").concat(e.getMessage()));
+        }
+
+        Map<String, Object> result = ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, "BirtFlexibleReportSuccessfullyGenerated", locale).concat(" ").concat(reportName));
+        result.put("textForm", textForm);
+        result.put("reportContentId", reportContentId);
+        return result;
+    }
+
+    // I'm not a big fan of how I did the createFormForDisplay / overrideReportForm. Could probably be improved using a proper formForReport object or something similar.
+
+    /**
+     * Update search form of a report design
+     */
+    public static Map<String, Object> overrideReportForm(DispatchContext dctx, Map<String, Object> context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        Delegator delegator = dctx.getDelegator();
+        Locale locale = (Locale) context.get("locale");
+        String reportContentId = (String) context.get("reportContentId");
+        String overrideFilters = (String) context.get("overrideFilters");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+
+        // safety check : do not accept "${groovy", "${bsh" and "javascript"
+        String overideFiltersNoWhiteSpace = overrideFilters.replaceAll("\\s", "");
+        if (overideFiltersNoWhiteSpace.contains("${groovy:") || overideFiltersNoWhiteSpace.contains("${bsh:") || overideFiltersNoWhiteSpace.contains("javascript:")) {
+            return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorUnauthorisedCharacter", locale));
+        }
+
+        try {
+            GenericValue content = delegator.findOne("Content", true, UtilMisc.toMap("contentId", reportContentId));
+            String dataResourceId = content.getString("dataResourceId");
+            StringBuffer newForm = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?> <forms xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://ofbiz.apache.org/dtds/widget-form.xsd\">");
+            newForm.append(overrideFilters);
+            newForm.append("</forms>");
+            Document xmlForm = UtilXml.readXmlDocument(newForm.toString());
+            dispatcher.runSync("updateElectronicTextForm", UtilMisc.toMap("dataResourceId", dataResourceId, "textData", UtilXml.writeXmlDocument(xmlForm), "userLogin", userLogin, "locale", locale));
+        } catch (GeneralException | SAXException | ParserConfigurationException | IOException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        return ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, "BirtSearchFormSuccessfullyOverridde", locale));
+    }
+
+    /**
+     * Create report design from View/Entity master report
+     */
+    public static Map<String, Object> createFlexibleReportFromMasterEntityWorkflow(DispatchContext dctx, Map<String, Object> context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        Delegator delegator = dctx.getDelegator();
+        Locale locale = (Locale) context.get("locale");
+        String writeFilters = (String) context.get("writeFilters");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        String entityViewName = (String) context.get("entityViewName");
+
+        ModelEntity modelEntity = delegator.getModelEntity(entityViewName);
+        String contentId = null;
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        try {
+            Map<String, Object> resultMapsForGeneration = dispatcher.runSync("prepareFlexibleReportFieldsFromEntity", UtilMisc.toMap("modelEntity", modelEntity, "userLogin", userLogin, "locale", locale));
+            if (ServiceUtil.isError(resultMapsForGeneration)) {
+                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultMapsForGeneration));
+            }
+            Map<String, String> dataMap = (Map<String, String>) resultMapsForGeneration.get("dataMap");
+            Map<String, String> fieldDisplayLabels = null;
+            if (UtilValidate.isNotEmpty(resultMapsForGeneration.get("fieldDisplayLabels"))) {
+                fieldDisplayLabels = (Map<String, String>) resultMapsForGeneration.get("fieldDisplayLabels");
+            }
+            Map<String, String> filterMap = null;
+            if (UtilValidate.isNotEmpty(resultMapsForGeneration.get("filterMap"))) {
+                filterMap = (Map<String, String>) resultMapsForGeneration.get("filterMap");
+            }
+            Map<String, String> filterDisplayLabels = null;
+            if (UtilValidate.isNotEmpty(resultMapsForGeneration.get("filterDisplayLabels"))) {
+                filterDisplayLabels = (Map<String, String>) resultMapsForGeneration.get("filterDisplayLabels");
+            }
+            contentId = BirtWorker.recordReportContent(delegator, dispatcher, context);
+            // callPerformFindFromBirt is the customMethod for Entity workflow
+            String rptDesignFileName = BirtUtil.resolveRptDesignFilePathFromContent(delegator, contentId);
+            GenericValue content = delegator.findOne("Content", true, "contentId", contentId);
+            String customMethodId = content.getString("customMethodId");
+            if (UtilValidate.isEmpty(customMethodId)) customMethodId = "CM_FB_PERFORM_FIND";
+            GenericValue customMethod = delegator.findOne("CustomMethod", true, "customMethodId", customMethodId);
+            if (customMethod == null) {
+                return ServiceUtil.returnError("CustomMethod not exist : " + customMethodId); //todo labelise
+            }
+            result = dispatcher.runSync("createFlexibleReport", UtilMisc.toMap(
+                    "locale", locale,
+                    "dataMap", dataMap,
+                    "userLogin", userLogin,
+                    "filterMap", filterMap,
+                    "serviceName", customMethod.get("customMethodName"),
+                    "writeFilters", writeFilters,
+                    "rptDesignName", rptDesignFileName,
+                    "fieldDisplayLabels", fieldDisplayLabels,
+                    "filterDisplayLabels", filterDisplayLabels));
+            if (ServiceUtil.isError(result)) {
+                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
+            }
+        } catch (GeneralException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        result.put("contentId", contentId);
+        return result;
+    }
+
+    /**
+     * Create report design from service master report
+     */
+    public static Map<String, Object> createFlexibleReportFromMasterServiceWorkflow(DispatchContext dctx, Map<String, Object> context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        Delegator delegator = dctx.getDelegator();
+        Locale locale = (Locale) context.get("locale");
+        String writeFilters = (String) context.get("writeFilters");
+        String serviceName = (String) context.get("serviceName");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        String masterContentId = (String) context.get("masterContentId");
+        String contentId = null;
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+
+        try {
+            GenericValue masterContent = delegator.findOne("Content", true, "contentId", masterContentId);
+            String customMethodId = masterContent.getString("customMethodId");
+            if (UtilValidate.isEmpty(customMethodId)) {
+                throw new GeneralException("The master content " + masterContentId + " haven't a customMethod");
+            }
+            GenericValue customMethod = delegator.findOne("CustomMethod", true, "customMethodId", customMethodId);
+            if (customMethod == null) {
+                return ServiceUtil.returnError("CustomMethod not exist : " + customMethodId); //todo labelise
+            }
+            String customMethodName = (String) customMethod.getString("customMethodName");
+            if ("default".equalsIgnoreCase(serviceName)) {
+                serviceName = customMethodName + "PrepareFields";
+            }
+            try {
+                ModelService modelService = dctx.getModelService(serviceName);
+            } catch (GenericServiceException e) {
+                return ServiceUtil.returnError("No service define with name " + serviceName); //TODO labelise
+            }
+            contentId = BirtWorker.recordReportContent(delegator, dispatcher, context);
+            String rptDesignFileName = BirtUtil.resolveRptDesignFilePathFromContent(delegator, contentId);
+            Map<String, Object> resultService = dispatcher.runSync(serviceName, UtilMisc.toMap("locale", locale, "userLogin", userLogin));
+            Map<String, String> dataMap = (Map<String, String>) resultService.get("dataMap");
+            Map<String, String> filterMap = (Map<String, String>) resultService.get("filterMap");
+            Map<String, String> fieldDisplayLabels = (Map<String, String>) resultService.get("fieldDisplayLabels");
+            Map<String, String> filterDisplayLabels = (Map<String, String>) resultService.get("filterDisplayLabels");
+            Map<String, Object> resultGeneration = dispatcher.runSync("createFlexibleReport", UtilMisc.toMap(
+                    "locale", locale,
+                    "dataMap", dataMap,
+                    "userLogin", userLogin,
+                    "filterMap", filterMap,
+                    "serviceName", customMethodName,
+                    "writeFilters", writeFilters,
+                    "rptDesignName", rptDesignFileName,
+                    "fieldDisplayLabels", fieldDisplayLabels,
+                    "filterDisplayLabels", filterDisplayLabels));
+            if (ServiceUtil.isError(resultGeneration)) {
+                return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorCreatingFlexibleReport", locale));
+            }
+        } catch (GeneralException e) {
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        result.put("contentId", contentId);
+        return result;
+    }
+
+    /**
+     * Define which data fields and its label, filter fields and label that will be supported by the View/Entity report design
+     */
+    public static Map<String, Object> prepareFlexibleReportFieldsFromEntity(DispatchContext dctx, Map<String, Object> context) {
+        Locale locale = (Locale) context.get("locale");
+        ModelEntity modelEntity = (ModelEntity) context.get("modelEntity");
+
+        Map<String, String> dataMap = new HashMap<String, String>();
+        Map<String, String> fieldDisplayLabels = new HashMap<String, String>();
+        LinkedHashMap<String, String> filterMap = new LinkedHashMap<String, String>();
+        LinkedHashMap<String, String> filterDisplayLabels = new LinkedHashMap<String, String>();
+
+        List<String> listEntityFields = modelEntity.getAllFieldNames();
+        Map<Object, Object> uiLabelMap = new HashMap<Object, Object>();
+        final String[] resourceGlob = {"OrderUiLabels", "ProductUiLabels", "PartyUiLabels", "ContentUiLabels", "AccountingUiLabels", "CommonUiLabels", "BirtUiLabels"};
+        for (String res : resourceGlob) {
+            uiLabelMap.putAll(UtilProperties.getProperties(res, locale));
+        }
+
+        List<String> excludeFields = modelEntity.getAutomaticFieldNames();
+        for (String field : listEntityFields) {
+            ModelField mField = modelEntity.getField(field);
+            //ignore stamps fields
+            if (excludeFields.contains(mField.getName())) continue;
+            dataMap.put(field, mField.getType());
+
+            String localizedName = null;
+            String interpretedFieldName = null;
+            FlexibleStringExpander.getInstance(mField.getDescription()).expandString(context);
+            String titleFieldName = "FormFieldTitle_".concat(field);
+            localizedName = (String) uiLabelMap.get(titleFieldName);
+            if (UtilValidate.isEmpty(localizedName) || localizedName.equals(titleFieldName)) {
+                interpretedFieldName = FlexibleStringExpander.getInstance(field).expandString(context);
+                fieldDisplayLabels.put(field, interpretedFieldName);
+            } else {
+                fieldDisplayLabels.put(field, localizedName);
+            }
+
+            List<String> fieldTypeWithRangeList = UtilMisc.toList("date", "date-time", "time", "floating-point", "currency-amount", "numeric");
+            if (fieldTypeWithRangeList.contains(mField.getType())) {
+                filterMap.put(field.concat("_fld0_value"), mField.getType());
+                filterMap.put(field.concat("_fld0_op"), "short-varchar");
+                filterMap.put(field.concat("_fld1_value"), mField.getType());
+                filterMap.put(field.concat("_fld1_op"), "short-varchar");
+                filterDisplayLabels.put(field.concat("_fld0_value"), fieldDisplayLabels.get(field).concat(UtilProperties.getMessage(resource, "BirtFindFieldOptionValue0", locale)));
+                filterDisplayLabels.put(field.concat("_fld0_op"), fieldDisplayLabels.get(field).concat(UtilProperties.getMessage(resource, "BirtFindFieldOptionValue0", locale).concat(UtilProperties.getMessage(resource, "BirtFindCompareOperator", locale))));
+                filterDisplayLabels.put(field.concat("_fld1_value"), fieldDisplayLabels.get(field).concat(UtilProperties.getMessage(resource, "BirtFindFieldOptionValue1", locale)));
+                filterDisplayLabels.put(field.concat("_fld1_op"), fieldDisplayLabels.get(field).concat(UtilProperties.getMessage(resource, "BirtFindFieldOptionValue1", locale).concat(UtilProperties.getMessage(resource, "BirtFindCompareOperator", locale))));
+            } else { // remaining types need 4 fields (fld0-1_op-value)
+                filterMap.put(field, mField.getType());
+                filterMap.put(field.concat("_op"), "short-varchar");
+                filterDisplayLabels.put(field, fieldDisplayLabels.get(field));
+                filterDisplayLabels.put(field.concat("_op"), fieldDisplayLabels.get(field).concat(UtilProperties.getMessage(resource, "BirtFindCompareOperator", locale)));
+            }
+        }
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        result.put("dataMap", dataMap);
+        if (UtilValidate.isNotEmpty(fieldDisplayLabels)) {
+            result.put("fieldDisplayLabels", fieldDisplayLabels);
+        }
+        if (UtilValidate.isNotEmpty(filterMap)) {
+            result.put("filterMap", filterMap);
+        }
+        if (UtilValidate.isNotEmpty(filterDisplayLabels)) {
+            result.put("filterDisplayLabels", filterDisplayLabels);
+        }
+        return result;
+    }
+
+    /**
+     * Prepare and return search form of a report design
+     */
+    public static Map<String, Object> createFormForDisplay(DispatchContext dctx, Map<String, Object> context) {
+        String reportContentId = (String) context.get("reportContentId");
+        Delegator delegator = dctx.getDelegator();
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+
+        String textData = null;
+        try {
+            GenericValue content = delegator.findOne("Content", true, "contentId", reportContentId);
+            String dataResourceId = content.getString("dataResourceId");
+            GenericValue electronicText = delegator.findOne("ElectronicText", true, "dataResourceId", dataResourceId);
+            textData = electronicText.getString("textData");
+        } catch (GenericEntityException e) {
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        if (Debug.infoOn()) Debug.logInfo(textData, module);
+        textData = textData.substring(textData.indexOf("<form "), textData.length());
+        if (textData.contains("</form>")) {
+            textData = textData.substring(0, textData.indexOf("</form>") + 7);
+        } else {
+            textData = textData.substring(0, textData.indexOf("/>") + 2);
+        }
+        textData = StringUtil.replaceString(textData, "$", "&#36;");
+        result.put("textForm", textData);
+        return result;
+    }
+
+    /**
+     * delete all non-master report design
+     */
+    public static Map<String, Object> deleteAllReports(DispatchContext dctx, Map<String, Object> context) {
+        Delegator delegator = dctx.getDelegator();
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        Locale locale = (Locale) context.get("locale");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+
+        List<String> listContentId = null;
+        List<GenericValue> listContent = null;
+        EntityCondition entityConditionContent = EntityCondition.makeCondition("contentTypeId", "FLEXIBLE_REPORT");
+        try {
+            listContent = delegator.findList("Content", entityConditionContent, UtilMisc.toSet("contentId"), null, null, false);
+        } catch (GenericEntityException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        if (UtilValidate.isEmpty(listContent)) {
+            return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorNoFlexibleReportToDelete", locale));
+        }
+        listContentId = EntityUtil.getFieldListFromEntityList(listContent, "contentId", true);
+
+        try {
+            for (String contentId : listContentId) {
+                Map<String, Object> returnMap = dispatcher.runSync("deleteFlexibleReport", UtilMisc.toMap("contentId", contentId, "userLogin", userLogin, "locale", locale));
+                ServiceUtil.isError(returnMap);
+            }
+        } catch (GenericServiceException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        return ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, "BirtFlexibleReportsSuccessfullyDeleted", locale));
+    }
+
+    /**
+     * Delete a flexible report design
+     */
+    public static Map<String, Object> deleteFlexibleReport(DispatchContext dctx, Map<String, Object> context) {
+        Delegator delegator = dctx.getDelegator();
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        Locale locale = (Locale) context.get("locale");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        String contentId = (String) context.get("contentId");
+
+        List<GenericValue> listContentRpt = null;
+        List<GenericValue> listRptDesignFileGV = null;
+        String contentIdRpt;
+        try {
+            listContentRpt = delegator.findList("ContentAssoc", EntityCondition.makeCondition("contentId", EntityOperator.EQUALS, contentId), UtilMisc.toSet("contentIdTo"), null, null, false);
+            contentIdRpt = listContentRpt.get(0).getString("contentIdTo");
+            List<EntityExpr> listConditions = UtilMisc.toList(EntityCondition.makeCondition("contentTypeId", EntityOperator.EQUALS, "RPTDESIGN"), EntityCondition.makeCondition("contentId", EntityOperator.EQUALS, contentIdRpt));
+            EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(listConditions, EntityOperator.AND);
+            listRptDesignFileGV = delegator.findList("ContentDataResourceView", ecl, UtilMisc.toSet("drObjectInfo"), null, null, false);
+        } catch (GenericEntityException e1) {
+            e1.printStackTrace();
+            return ServiceUtil.returnError(e1.getMessage());
+        }
+        if (listRptDesignFileGV.size() > 1) {
+            return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorUnexpectedNumberReportToDelete", locale));
+        }
+        List<String> listRptDesignFile = EntityUtil.getFieldListFromEntityList(listRptDesignFileGV, "drObjectInfo", false);
+        String rptfileName = listRptDesignFile.get(0);
+        Path path = Paths.get(rptfileName);
+        try {
+            if (! Files.deleteIfExists(path)) {
+                ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorCannotLocateReportFile", locale));
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        try {
+            delegator.removeByAnd("ContentAttribute", UtilMisc.toMap("contentId", contentId));
+            dispatcher.runSync("removeContentAndRelated", UtilMisc.toMap("contentId", contentId, "userLogin", userLogin, "locale", locale));
+            dispatcher.runSync("removeContentAndRelated", UtilMisc.toMap("contentId", contentIdRpt, "userLogin", userLogin, "locale", locale));
+        } catch (GenericServiceException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        } catch (GenericEntityException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        return ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, "BirtFlexibleReportSuccessfullyDeleted", locale));
+    }
+
+    /**
+     * Update birt rptdesign file from uploaded one.
+     * <p>This will update only STYLES, BODY, MASTERPAGE AND CUBES from existing rptdesign with uploaded ones.</p>
+     *
+     */
+    public static Map<String, Object> uploadRptDesign(DispatchContext dctx, Map<String, Object> context) {
+        String dataResourceId = (String) context.get("dataResourceIdRpt");
+        Locale locale = (Locale) context.get("locale");
+        Delegator delegator = dctx.getDelegator();
+        Map<String, Object> result = null;
+        List<String> listSuccessMessage = new ArrayList<String>();
+
+        // the idea is to allow only design to be uploaded. We use the stored file and add the new design from the uploaded file within.
+        DesignConfig config = new DesignConfig();
+        IDesignEngine engine = null;
+        try {
+            Platform.startup();
+            IDesignEngineFactory factory = (IDesignEngineFactory) Platform.createFactoryObject(IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY);
+            engine = factory.createDesignEngine(config);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        SessionHandle session = engine.newSessionHandle(ULocale.forLocale(locale));
+
+        // get old file to restore dataset and datasource
+        ByteBuffer newRptDesignBytes = (ByteBuffer) context.get("uploadRptDesign");
+        if (newRptDesignBytes == null) {
+            return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, "BirtErrorCannotFindUploadedFile", locale));
+        }
+
+        GenericValue dataResource = null;
+        try {
+            dataResource = delegator.findOne("DataResource", false, "dataResourceId", dataResourceId);
+        } catch (GenericEntityException e1) {
+            e1.printStackTrace();
+            return ServiceUtil.returnError(e1.getMessage());
+        }
+        String rptDesignName = dataResource.getString("objectInfo");
+        // start Birt API platfrom
+        try {
+            Platform.startup();
+        } catch (BirtException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError("Cannot start Birt platform");
+        }
+
+        // get database design
+        ReportDesignHandle designStored;
+        try {
+            designStored = session.openDesign(rptDesignName);
+        } catch (DesignFileException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        // check if design stored already has a body and delete it to avoid conflicts (taking into account only newly designed body)
+        if (UtilValidate.isNotEmpty(designStored.getBody())) {
+            SlotHandle bodyStored = designStored.getBody();
+
+            Iterator<DesignElementHandle> iter = bodyStored.iterator();
+            while (iter.hasNext()) {
+                try {
+                    iter.remove();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return ServiceUtil.returnError(e.getMessage());
+                }
+            }
+        }
+
+        // NEED TO COPY STYLES, BODY, MASTERPAGE AND CUBES; existing elements (in case I missed one):
+        //[styles, parameters, dataSources, dataSets, pageSetup, components, body, scratchPad, templateParameterDefinitions, cubes, themes]
+        // get user design
+        String nameTempRpt = rptDesignName.substring(0, rptDesignName.lastIndexOf('.')).concat("_TEMP_.rptdesign");
+        File file = new File(nameTempRpt);
+        RandomAccessFile out;
+        ReportDesignHandle designFromUser;
+        try {
+            out = new RandomAccessFile(file, "rw");
+            out.write(newRptDesignBytes.array());
+            out.close();
+            designFromUser = session.openDesign(nameTempRpt);
+            // user file is deleted straight away to prevent the use of the report as script entry (security)
+            Path path = Paths.get(nameTempRpt);
+            Files.deleteIfExists(path);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        //copy cube
+        SlotHandle cubesFromUser = designFromUser.getCubes();
+        Iterator<DesignElementHandle> iterCube = cubesFromUser.iterator();
+
+        while (iterCube.hasNext()) {
+            DesignElementHandle item = (DesignElementHandle) iterCube.next();
+            DesignElementHandle copy = item.copy().getHandle(item.getModule());
+            try {
+                designStored.getCubes().add(copy);
+            } catch (Exception e) {
+                e.printStackTrace();
+                return ServiceUtil.returnError(e.getMessage());
+            }
+        }
+
+        // copy body
+        SlotHandle bodyFromUser = designFromUser.getBody();
+        Iterator<DesignElementHandle> iter = bodyFromUser.iterator();
+
+        while (iter.hasNext()) {
+            DesignElementHandle item = (DesignElementHandle) iter.next();
+            DesignElementHandle copy = item.copy().getHandle(item.getModule());
+            try {
+                designStored.getBody().add(copy);
+            } catch (Exception e) {
+                e.printStackTrace();
+                return ServiceUtil.returnError(e.getMessage());
+            }
+        }
+
+        // deleting simple master page from design stored
+        try {
+            List<DesignElementHandle> listMasterPagesStored = designStored.getMasterPages().getContents();
+            for (Object masterPage : listMasterPagesStored) {
+                if (masterPage instanceof SimpleMasterPageHandle) {
+                    designStored.getMasterPages().drop((DesignElementHandle) masterPage);
+                }
+            }
+
+            // adding simple master page => tous ces casts et autres instanceof... c'est laid, mais c'est tellement galère que quand je trouve une solution qui marche... :s
+            List<DesignElementHandle> listMasterPages = designFromUser.getMasterPages().getContents();
+            for (DesignElementHandle masterPage : listMasterPages) {
+                if (masterPage instanceof SimpleMasterPageHandle) {
+                    designStored.getMasterPages().add((SimpleMasterPage) ((SimpleMasterPageHandle) masterPage).copy());
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        // page variables
+        List<VariableElementHandle> pageVariablesUser = designFromUser.getPageVariables();
+        for (VariableElementHandle pageVariable : pageVariablesUser) {
+            try {
+                designStored.setPageVariable(pageVariable.getName(), pageVariable.getPropertyBindingExpression(pageVariable.getName()));
+            } catch (SemanticException e) {
+                e.printStackTrace();
+                return ServiceUtil.returnError(e.getMessage());
+            }
+        }
+
+        // copy styles
+        SlotHandle stylesFromUser = designFromUser.getStyles();
+        SlotHandle stylesStored = designStored.getStyles();
+
+        // getting style names from stored report
+        List<String> listStyleNames = new ArrayList<String>();
+        Iterator<DesignElementHandle> iterStored = stylesStored.iterator();
+        while (iterStored.hasNext()) {
+            DesignElementHandle item = (DesignElementHandle) iterStored.next();
+            listStyleNames.add(item.getName());
+        }
+
+        Iterator<DesignElementHandle> iterUser = stylesFromUser.iterator();
+
+        // adding to styles those which are not already present
+        while (iterUser.hasNext()) {
+            DesignElementHandle item = (DesignElementHandle) iterUser.next();
+            if (! listStyleNames.contains(item.getName())) {
+                DesignElementHandle copy = item.copy().getHandle(item.getModule());
+                try {
+                    designStored.getStyles().add(copy);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return ServiceUtil.returnError(e.getMessage());
+                }
+            }
+        }
+
+        try {
+            designStored.saveAs(rptDesignName);
+        } catch (IOException e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        designFromUser.close();
+        designStored.close();
+        if (Debug.infoOn()) Debug.logInfo("####### Design uploaded: ".concat(rptDesignName), module);
+
+        // should we as a secondary safety precaution delete any file finishing with _TEMP_.rptdesign?
+        listSuccessMessage.add(UtilProperties.getMessage(resource, "BirtFlexibleRptDesignSuccessfullyUploaded", locale));
+        result = ServiceUtil.returnSuccess(listSuccessMessage);
+        return result;
+    }
+
+}
\ No newline at end of file

Added: ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtUtil.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtUtil.java?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtUtil.java (added)
+++ ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtUtil.java Sat Jan 28 13:22:55 2017
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.apache.ofbiz.birt.flexible;
+
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.GeneralException;
+import org.apache.ofbiz.base.util.StringUtil;
+import org.apache.ofbiz.base.util.UtilGenerics;
+import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilProperties;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.base.util.template.FreeMarkerWorker;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.GenericEntityException;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.entity.condition.EntityCondition;
+import org.apache.ofbiz.entity.condition.EntityConditionList;
+import org.apache.ofbiz.entity.condition.EntityExpr;
+import org.apache.ofbiz.entity.util.EntityUtil;
+import org.apache.ofbiz.security.Security;
+import org.apache.ofbiz.service.GenericServiceException;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.eclipse.birt.report.engine.api.EXCELRenderOption;
+import org.eclipse.birt.report.engine.api.EngineException;
+import org.eclipse.birt.report.engine.api.HTMLRenderOption;
+import org.eclipse.birt.report.engine.api.HTMLServerImageHandler;
+import org.eclipse.birt.report.engine.api.IPDFRenderOption;
+import org.eclipse.birt.report.engine.api.IReportEngine;
+import org.eclipse.birt.report.engine.api.IReportRunnable;
+import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
+import org.eclipse.birt.report.engine.api.PDFRenderOption;
+import org.eclipse.birt.report.engine.api.RenderOption;
+import org.eclipse.birt.report.model.api.elements.DesignChoiceConstants;
+
+public final class BirtUtil {
+
+    public final static String module = BirtUtil.class.getName();
+
+    private final static HTMLServerImageHandler imageHandler = new HTMLServerImageHandler();
+    private final static Map<String, String> entityFieldTypeBirtTypeMap = MapUtils.unmodifiableMap(UtilMisc.toMap(
+            "id", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "url", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "name", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "id-ne", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "value", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "email", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "comment", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "id-long",DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "id-vlong", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "very-long", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "indicator", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "very-short", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "tel-number", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "id-long-ne", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "id-vlong-ne", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "description", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "long-varchar", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "short-varchar", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "credit-card-date", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "credit-card-number", DesignChoiceConstants.COLUMN_DATA_TYPE_STRING,
+            "date-time", DesignChoiceConstants.COLUMN_DATA_TYPE_DATETIME,
+            "date", DesignChoiceConstants.COLUMN_DATA_TYPE_DATE,
+            "time", DesignChoiceConstants.COLUMN_DATA_TYPE_TIME,
+            "currency-amount", DesignChoiceConstants.COLUMN_DATA_TYPE_DECIMAL,
+            "currency-precise", DesignChoiceConstants.COLUMN_DATA_TYPE_DECIMAL,
+            "fixed-point", DesignChoiceConstants.COLUMN_DATA_TYPE_DECIMAL,
+            "floating-point", DesignChoiceConstants.COLUMN_DATA_TYPE_DECIMAL,
+            "numeric", DesignChoiceConstants.COLUMN_DATA_TYPE_INTEGER,
+            "object", DesignChoiceConstants.COLUMN_DATA_TYPE_JAVA_OBJECT,
+            "blob", DesignChoiceConstants.COLUMN_DATA_TYPE_BLOB));
+
+    private final static Map<String, String> entityFieldTypeBirtParameterTypeMap = MapUtils.unmodifiableMap(UtilMisc.toMap(
+            "id", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "url", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "name", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "id-ne", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "value", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "email", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "comment", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "id-long",DesignChoiceConstants.PARAM_TYPE_STRING,
+            "id-vlong", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "very-long", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "indicator", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "very-short", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "tel-number", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "id-long-ne", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "id-vlong-ne", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "description", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "long-varchar", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "short-varchar", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "credit-card-date", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "credit-card-number", DesignChoiceConstants.PARAM_TYPE_STRING,
+            "date-time", DesignChoiceConstants.PARAM_TYPE_DATETIME,
+            "date", DesignChoiceConstants.PARAM_TYPE_DATE,
+            "time", DesignChoiceConstants.PARAM_TYPE_TIME,
+            "currency-amount", DesignChoiceConstants.PARAM_TYPE_DECIMAL,
+            "currency-precise", DesignChoiceConstants.PARAM_TYPE_DECIMAL,
+            "fixed-point", DesignChoiceConstants.PARAM_TYPE_DECIMAL,
+            "floating-point", DesignChoiceConstants.PARAM_TYPE_DECIMAL,
+            "numeric", DesignChoiceConstants.PARAM_TYPE_INTEGER,
+            "object", DesignChoiceConstants.PARAM_TYPE_JAVA_OBJECT,
+            "blob", DesignChoiceConstants.PARAM_TYPE_JAVA_OBJECT));
+
+    private final static Map<String, String> mimeTypeOutputFormatMap = UtilMisc.toMap(
+            "text/html", RenderOption.OUTPUT_FORMAT_HTML,
+            "application/pdf", RenderOption.OUTPUT_FORMAT_PDF,
+            "application/postscript", "postscript",
+            "application/vnd.ms-word", "doc",
+            "application/vnd.ms-excel", "xls",
+            "application/vnd.ms-powerpoint", "ppt",
+            "application/vnd.oasis.opendocument.text", "odt",
+            "application/vnd.oasis.opendocument.spreadsheet", "ods",
+            "application/vnd.oasis.opendocument.presentation", "odp",
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx",
+            "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx",
+            "application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx");
+
+    private BirtUtil() {}
+
+    /**
+     * Return birt field type corresponding to given entity field type
+     * @param entityFieldType
+     * @return
+     * @throws GeneralException
+     */
+    public static String convertFieldTypeToBirtType(String entityFieldType) {
+        if (UtilValidate.isEmpty(entityFieldType)) {
+            return null;
+        }
+        return entityFieldTypeBirtTypeMap.get(entityFieldType.toLowerCase());
+    }
+
+    /**
+     * Return birt parameter type corresponding to given entity field type
+     * @param entityFieldType
+     * @return
+     * @throws GeneralException
+     */
+    public static String convertFieldTypeToBirtParameterType(String entityFieldType) {
+        if (UtilValidate.isEmpty(entityFieldType)) {
+            return null;
+        }
+        return entityFieldTypeBirtParameterTypeMap.get(entityFieldType.toLowerCase());
+    }
+
+    /**
+     * Return true if mime type related to a contentType is supported by Birt
+     * @param contentType
+     * @return
+     * @throws GeneralException
+     */
+    public static boolean isSupportedMimeType(String contentType) {
+        return mimeTypeOutputFormatMap.containsKey(contentType);
+    }
+
+    /**
+     * Return mime type related to a contentType supported by Birt
+     * @param contentType
+     * @return
+     * @throws GeneralException
+     */
+    public static String getMimeTypeOutputFormat(String contentType) throws GeneralException {
+        if (isSupportedMimeType(contentType)) {
+            return mimeTypeOutputFormatMap.get(contentType);
+        }
+        throw new GeneralException("Unknown content type : " + contentType);
+    }
+
+    /**
+     * return extension file related to a contentType supported by Birt
+     * @param contentType
+     * @return
+     * @throws GeneralException
+     */
+    public static String getMimeTypeFileExtension(String contentType) throws GeneralException {
+        return ".".concat(getMimeTypeOutputFormat(contentType));
+    }
+
+    /**
+     * Resolve the template path location where rptDesign file are stored,
+     * first try the resolution from birt.properties with rptDesign.output.path
+     * second from content.properties content.upload.path.prefix
+     * and add birtReptDesign directory
+     * default OFBIZ_HOME/runtime/uploads/birtRptDesign/
+     * @return
+     */
+    public static String resolveTemplatePathLocation() {
+        String templatePathLocation = UtilProperties.getPropertyValue("birt", "rptDesign.output.path");
+        if (UtilValidate.isEmpty(templatePathLocation)) {
+            templatePathLocation = UtilProperties.getPropertyValue("content", "content.upload.path.prefix", "runtime/uploads");
+        }
+        if (! templatePathLocation.endsWith("/")) {
+            templatePathLocation = templatePathLocation.concat("/");
+        }
+        if (! templatePathLocation.endsWith("/birtRptDesign/")) {
+            templatePathLocation = templatePathLocation.concat("birtRptDesign/");
+        }
+        if (! templatePathLocation.startsWith("/")) templatePathLocation = System.getProperty("ofbiz.home").concat("/").concat(templatePathLocation);
+        return templatePathLocation;
+    }
+
+    /**
+     * With the reporting contentId element resolve the path to rptDesign linked
+     * @param delegator
+     * @param contentId
+     * @return
+     * @throws GenericEntityException
+     */
+    public static String resolveRptDesignFilePathFromContent(Delegator delegator, String contentId) throws GenericEntityException {
+        List<GenericValue> listContentRpt = delegator.findList("ContentAssoc", EntityCondition.makeCondition("contentId", contentId), UtilMisc.toSet("contentIdTo"), null, null, true);
+        if (UtilValidate.isNotEmpty(listContentRpt)) {
+            String contentIdRpt = EntityUtil.getFirst(listContentRpt).getString("contentIdTo");
+            List<EntityExpr> listConditions = UtilMisc.toList(
+                    EntityCondition.makeCondition("contentTypeId", "RPTDESIGN"),
+                    EntityCondition.makeCondition("contentId", contentIdRpt));
+            EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(listConditions);
+            List<GenericValue> listDataRessouceRptDesignFile = delegator.findList("ContentDataResourceView", ecl, UtilMisc.toSet("drObjectInfo"), null, null, true);
+            if (UtilValidate.isNotEmpty(listDataRessouceRptDesignFile)) {
+                return EntityUtil.getFirst(listDataRessouceRptDesignFile).getString("drObjectInfo");
+            }
+        }
+        return "";
+    }
+
+    /**
+     * remove all non unicode alphanumeric and replace space by _
+     * @param reportName
+     * @return
+     */
+    public static String encodeReportName(String reportName) {
+        if (UtilValidate.isEmpty(reportName)) return "";
+        return StringUtil.replaceString(StringUtil.removeRegex(reportName.trim(), "[^\\p{L}\\s]"), " ", "_");
+    }
+}
\ No newline at end of file

Added: ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/ReportDesignGenerator.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/ReportDesignGenerator.java?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/ReportDesignGenerator.java (added)
+++ ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/ReportDesignGenerator.java Sat Jan 28 13:22:55 2017
@@ -0,0 +1,344 @@
+package org.apache.ofbiz.birt.flexible;
+
+import com.ibm.icu.util.ULocale;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.GeneralException;
+import org.apache.ofbiz.base.util.UtilProperties;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.service.DispatchContext;
+import org.apache.ofbiz.service.GenericServiceException;
+import org.eclipse.birt.core.framework.Platform;
+import org.eclipse.birt.report.model.api.CachedMetaDataHandle;
+import org.eclipse.birt.report.model.api.CellHandle;
+import org.eclipse.birt.report.model.api.DataItemHandle;
+import org.eclipse.birt.report.model.api.DesignConfig;
+import org.eclipse.birt.report.model.api.DesignElementHandle;
+import org.eclipse.birt.report.model.api.ElementFactory;
+import org.eclipse.birt.report.model.api.GridHandle;
+import org.eclipse.birt.report.model.api.IDesignEngine;
+import org.eclipse.birt.report.model.api.IDesignEngineFactory;
+import org.eclipse.birt.report.model.api.LabelHandle;
+import org.eclipse.birt.report.model.api.PropertyHandle;
+import org.eclipse.birt.report.model.api.ReportDesignHandle;
+import org.eclipse.birt.report.model.api.RowHandle;
+import org.eclipse.birt.report.model.api.ScalarParameterHandle;
+import org.eclipse.birt.report.model.api.ScriptDataSetHandle;
+import org.eclipse.birt.report.model.api.ScriptDataSourceHandle;
+import org.eclipse.birt.report.model.api.SessionHandle;
+import org.eclipse.birt.report.model.api.StructureFactory;
+import org.eclipse.birt.report.model.api.activity.SemanticException;
+import org.eclipse.birt.report.model.api.elements.DesignChoiceConstants;
+import org.eclipse.birt.report.model.api.elements.structures.CachedMetaData;
+import org.eclipse.birt.report.model.api.elements.structures.ColumnHint;
+import org.eclipse.birt.report.model.api.elements.structures.ComputedColumn;
+import org.eclipse.birt.report.model.api.elements.structures.HideRule;
+import org.eclipse.birt.report.model.api.elements.structures.ResultSetColumn;
+import org.eclipse.birt.report.model.elements.ReportItem;
+
+/**
+ * Report Design Generator Object - Handles flexible report design Generation from Master.
+ */
+
+public class ReportDesignGenerator {
+
+    private static final String module = ReportDesignGenerator.class.getName();
+    private Locale locale;
+    private ElementFactory factory;
+    /** The generated design */
+    private ReportDesignHandle design;
+    private Map<String, String> dataMap;
+    /** Map of all filter supported by the report design */
+    private Map<String, String> filterMap;
+    /** Service name to populate dataset of the report design*/
+    private String serviceName;
+    private Map<String, String> fieldDisplayLabels;
+    private Map<String, String> filterDisplayLabels;
+    private String rptDesignName;
+    private boolean generateFilters = false;
+    private GenericValue userLogin;
+
+    public static final String resource_error = "BirtErrorUiLabels";
+
+    public ReportDesignGenerator(Map<String, Object> context, DispatchContext dctx) throws GeneralException, SemanticException {
+        locale = (Locale) context.get("locale");
+        dataMap = (Map<String, String>) context.get("dataMap");
+        filterMap = (LinkedHashMap<String, String>) context.get("filterMap");
+        serviceName = (String) context.get("serviceName");
+        fieldDisplayLabels = (Map<String, String>) context.get("fieldDisplayLabels");
+        filterDisplayLabels = (LinkedHashMap<String, String>) context.get("filterDisplayLabels");
+        rptDesignName = (String) context.get("rptDesignName");
+        String writeFilters = (String) context.get("writeFilters");
+        userLogin = (GenericValue) context.get("userLogin");
+        if (UtilValidate.isEmpty(dataMap)) {
+            throw new GeneralException("Report design generator failed. Entry data map not found.");
+        }
+        if ("Y".equals(writeFilters)) {
+            generateFilters = true;
+        }
+    }
+
+    /**
+     * Generate report design (rtdesign file).
+     * @throws IOException
+     * @throws SemanticException
+     * @throws GeneralException
+     */
+    public void buildReport() throws IOException, SemanticException, GeneralException {
+        DesignConfig config = new DesignConfig();
+        IDesignEngine engine = null;
+
+        try {
+            Platform.startup();
+            IDesignEngineFactory factory = (IDesignEngineFactory) Platform.createFactoryObject(IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY);
+            engine = factory.createDesignEngine(config);
+        } catch (Exception e) {
+            throw new GeneralException(e.getMessage());
+        }
+
+        // creating main design elements
+        SessionHandle session = engine.newSessionHandle(ULocale.forLocale(locale));
+        design = session.createDesign();
+
+        factory = design.getElementFactory();
+
+        DesignElementHandle element = factory.newSimpleMasterPage("Page Master");
+        design.getMasterPages().add(element);
+
+        // create DataSource call
+        createScriptedDataSource();
+
+        // create DataSet call
+        try {
+            createScriptedDataset();
+        } catch (SemanticException se) {
+            throw se;
+        } catch (GenericServiceException gse) {
+            throw gse;
+        }
+
+        // General design parameters
+        design.setLayoutPreference(DesignChoiceConstants.REPORT_LAYOUT_PREFERENCE_AUTO_LAYOUT);
+        design.setBidiOrientation(DesignChoiceConstants.BIDI_DIRECTION_LTR);
+        design.setDefaultUnits(DesignChoiceConstants.UNITS_IN);
+        design.setCreatedBy(design.getVersion());
+        design.setImageDPI(96);
+
+        // adding filters as parameters to make them available for design
+        // first adding parameters to the design itself
+        if (UtilValidate.isNotEmpty(filterMap)) {
+            // adding filters within reportDesign if generateFilters is set to true
+            GridHandle grid = null;
+            int i = 0;
+            if (generateFilters) {
+                grid = factory.newGridItem(null, 2, filterMap.size());
+                design.getBody().add(grid);
+                grid.setWidth("100%");
+            }
+
+            for (String filter : filterMap.keySet()) {
+                String birtType = BirtUtil.convertFieldTypeToBirtParameterType(filterMap.get(filter));
+                if (birtType == null) {
+                    throw new GeneralException(UtilProperties.getMessage(resource_error, "BirtErrorConversionFieldToBirtFailed", locale));
+                }
+                // get label
+                String displayFilterName;
+                if (UtilValidate.isNotEmpty(filterDisplayLabels)) {
+                    displayFilterName = filterDisplayLabels.get(filter);
+                } else {
+                    displayFilterName = filter;
+                }
+                ScalarParameterHandle scalParam = factory.newScalarParameter(filter);
+//                scalParam.setDisplayName(displayFilterName); // has no incidence at all right now, is only displayed when using birt's report parameter system. Not our case. I leave it here if any idea arise of how to translate these.
+                scalParam.setPromptText(displayFilterName);
+                if ("javaObject".equals(birtType)) { //Fields of type='blob' are rejected by Birt: org.eclipse.birt.report.model.api.metadata.PropertyValueException: The choice value "javaObject" is not allowed.
+                    throw new GeneralException("Fields of type='blob' are rejected by Birt. Create a view entity, based on the requested entity, where you exclude the field of type='blob'");
+                } else {
+                    scalParam.setDataType(birtType);
+                }
+                scalParam.setIsRequired(false);
+                design.getParameters().add(scalParam);
+
+                if (generateFilters) {
+                    RowHandle row = (RowHandle) grid.getRows().get(i);
+                    CellHandle cellLabel = (CellHandle) row.getCells().get(0);
+                    CellHandle cellFilter = (CellHandle) row.getCells().get(1);
+                    LabelHandle label = factory.newLabel(null);
+                    label.setText(displayFilterName);
+                    cellLabel.getContent().add(label);
+
+                    // 1. create computed column and add it to grid column bindings
+                    ComputedColumn computedCol = StructureFactory.createComputedColumn();
+                    PropertyHandle computedSet = grid.getColumnBindings();
+                    computedCol.setName(displayFilterName);
+                    StringBuffer expression = new StringBuffer("params[\"");
+                    expression.append(filter);
+                    expression.append("\"]");
+                    computedCol.setExpression(expression.toString());
+                    computedSet.addItem(computedCol);
+
+                    // 2. create data and add computed column to it
+                    DataItemHandle data = factory.newDataItem(null);
+                    data.setResultSetColumn(computedCol.getName());
+                    cellFilter.getContent().add(data);
+
+                    // add visibility rule on row
+                    HideRule hideRule = StructureFactory.createHideRule();
+                    StringBuffer expressionHide = new StringBuffer(expression);
+                    expressionHide.append(".value == null || ");
+                    expressionHide.append(expression);
+                    expressionHide.append(".value == \"\"");
+                    hideRule.setExpression(expressionHide.toString());
+                    PropertyHandle propVisHandle = row.getPropertyHandle(ReportItem.VISIBILITY_PROP);
+                    propVisHandle.addItem(hideRule);
+                    i++;
+                }
+            }
+            // second adding script within beforeFactory filling the parameters with values from inputFields
+            createScriptedBeforeFactory();
+        }
+
+        // ################ CODE HERE IF YOU WANT TO ADD GENERATED DESIGN / MAY BE WORTH USING RPTTEMPLATE AND-OR RPTLIBRARY ###################
+
+        //GridHandle grid = factory.newGridItem(null, 7, 3);
+//        design.getBody().add(grid);
+
+//        grid.setWidth("100%");
+
+//        RowHandle row = (RowHandle) grid.getRows().get(0);
+
+//        ImageHandle image = factory.newImage(null);
+
+//        CellHandle cell = (CellHandle) row.getCells().get(0);
+//        cell.getContent().add(image);
+//        image.setURL("http://ofbiz.apache.org/images/ofbiz_logo.gif");
+
+//        LabelHandle label = factory.newLabel(null);
+//        cell = (CellHandle) row.getCells().get(1);
+//        cell.getContent().add(label);
+//        label.setText("Dat is dat test !");
+        // #####################
+        design.saveAs(rptDesignName);
+        design.close();
+        if (Debug.infoOn())Debug.logInfo("####### Design generated: " + rptDesignName, module);
+        session.closeAll(false);
+        Platform.shutdown();
+    }
+
+    /**
+     * Create the script that will be called within "Before Factory" step in Birt Report rendering process.
+     * <p>This script is used to populate Birt design parameters from input</p>
+     */
+    private void createScriptedBeforeFactory() {
+        StringBuffer beforeFactoryScript = new StringBuffer("Debug.logInfo(\"###### In beforeFactory\", module);\n");
+        beforeFactoryScript.append("var inputFields = reportContext.getParameterValue(\"parameters\");\n");
+        beforeFactoryScript.append("//get a list of all report parameters\n");
+        beforeFactoryScript.append("var parameters = reportContext.getDesignHandle().getAllParameters();\n");
+        beforeFactoryScript.append("for (var i = 0; i < parameters.size(); i++) {\n");
+        beforeFactoryScript.append("    var currentParam = parameters.get(i);\n");
+        beforeFactoryScript.append("    var parametersName = currentParam.getName();\n");
+        beforeFactoryScript.append("    params[parametersName].value = inputFields.get(parametersName);\n");
+        beforeFactoryScript.append("}");
+        design.setBeforeFactory(beforeFactoryScript.toString());
+    }
+
+    /**
+     * Create the script that will define the OFBiz dataset in Birt Report design.
+     * <p>This dataset will populate the OFBiz datasource of the design
+     * with <code>records</code> returned by <code>serviceName</code> service</p>
+     * @throws SemanticException
+     * @throws GeneralException
+     */
+    private void createScriptedDataset() throws SemanticException, GeneralException {
+        ScriptDataSetHandle dataSetHandle = factory.newScriptDataSet("Data Set");
+        dataSetHandle.setDataSource("OFBiz");
+
+        // set Initialize Birt script
+        StringBuffer dataSetInitializeScript = new StringBuffer();
+        dataSetInitializeScript.append("importPackage(Packages.org.eclipse.birt.report.engine.api);\n");
+        dataSetInitializeScript.append("importPackage(Packages.org.apache.ofbiz.entity);\n");
+        dataSetInitializeScript.append("importPackage(Packages.org.apache.ofbiz.service);\n");
+        dataSetInitializeScript.append("importPackage(Packages.org.apache.ofbiz.base.util);\n");
+        dataSetInitializeScript.append("importPackage(java.util);\n");
+        dataSetInitializeScript.append("module = \"" + rptDesignName + "\";");
+        dataSetInitializeScript.append("Debug.logInfo(\"###### In initialize \", module);");
+        design.setInitialize(dataSetInitializeScript.toString());
+
+        // set open Birt script
+        StringBuffer dataSetOpenScript = new StringBuffer("importPackage(Packages.org.apache.ofbiz.birt);\n");
+        dataSetOpenScript.append("Debug.logInfo(\"#### In open\", module)\n");
+        dataSetOpenScript.append("try {\n");
+        dataSetOpenScript.append("    listRes = dispatcher.runSync(\"" + serviceName + "\", UtilMisc.toMap(\"userLogin\", reportContext.getParameterValue(\"userLogin\"), \"locale\", reportContext.getParameterValue(\"locale\"), \"reportContext\", reportContext));\n");
+        dataSetOpenScript.append("    if (ServiceUtil.isError(listRes)) {\n");
+        dataSetOpenScript.append("         Debug.logError(ServiceUtil.getErrorMessage(listRes));\n");
+        dataSetOpenScript.append("    }\n");
+        dataSetOpenScript.append("}\n");
+        dataSetOpenScript.append("catch (e) { Debug.logError(e, module); }\n");
+        dataSetOpenScript.append("records = listRes.get(\"records\");\n");
+        dataSetOpenScript.append("countOfRow = 0;\n");
+        dataSetOpenScript.append("totalRow = records.size();\n");
+        dataSetHandle.setOpen(dataSetOpenScript.toString());
+
+        // set fetch Birt script
+        StringBuffer dataSetFetchScript = new StringBuffer("if (countOfRow == totalRow) return false;\n");
+        dataSetFetchScript.append("line = records.get(countOfRow);\n");
+        for (String field : dataMap.keySet()) {
+            dataSetFetchScript.append(field);
+            dataSetFetchScript.append(" = line.get(\"");
+            dataSetFetchScript.append(field);
+            dataSetFetchScript.append("\"); row[\"");
+            dataSetFetchScript.append(field);
+            dataSetFetchScript.append("\"] = ");
+            dataSetFetchScript.append(field);
+            dataSetFetchScript.append(";\n");
+        }
+
+        dataSetFetchScript.append("countOfRow ++;\n");
+        dataSetFetchScript.append("return true;");
+        dataSetHandle.setFetch(dataSetFetchScript.toString());
+
+        // #### define dataSet
+        CachedMetaData cmd = StructureFactory.createCachedMetaData();
+        CachedMetaDataHandle cachedMetaDataHandle = dataSetHandle.setCachedMetaData(cmd);
+        PropertyHandle columnHintsSet = dataSetHandle.getPropertyHandle(ScriptDataSetHandle.COLUMN_HINTS_PROP);
+
+        int i = 1;
+        for (String field : dataMap.keySet()) {
+            ResultSetColumn resultSetCol = StructureFactory.createResultSetColumn();
+            resultSetCol.setColumnName(field);
+            String birtType = BirtUtil.convertFieldTypeToBirtType(dataMap.get(field));
+            if (birtType == null) {
+                 throw new GeneralException(UtilProperties.getMessage(resource_error, "BirtErrorConversionFieldToBirtFailed", locale));
+            }
+            resultSetCol.setPosition(i);
+            resultSetCol.setDataType(birtType);
+
+            ColumnHint columnHint = StructureFactory.createColumnHint();
+            columnHint.setProperty("columnName", field);
+            columnHint.setProperty("analysis", "dimension");
+            columnHint.setProperty("heading", field);
+            // get label
+            String displayName = null;
+            if (UtilValidate.isNotEmpty(fieldDisplayLabels)) {
+                displayName = fieldDisplayLabels.get(field);
+            } else {
+                displayName = field;
+            }
+            columnHint.setProperty("displayName", displayName);
+            cachedMetaDataHandle.getResultSet().addItem(resultSetCol);
+            columnHintsSet.addItem(columnHint);
+            i++;
+        }
+        design.getDataSets().add(dataSetHandle);
+    }
+
+    /** Create new dataSource named OFBiz */
+    private void createScriptedDataSource() throws SemanticException {
+        ScriptDataSourceHandle dataSource = factory.newScriptDataSource("OFBiz");
+        design.getDataSources().add(dataSource);
+    }
+}

Modified: ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtEngineServlet.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtEngineServlet.java?rev=1780683&r1=1780682&r2=1780683&view=diff
==============================================================================
--- ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtEngineServlet.java (original)
+++ ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtEngineServlet.java Sat Jan 28 13:22:55 2017
@@ -23,6 +23,7 @@ import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.ofbiz.base.util.GeneralException;
 import org.eclipse.birt.core.exception.BirtException;
 import org.eclipse.birt.report.context.BirtContext;
 import org.eclipse.birt.report.context.IContext;
@@ -39,12 +40,15 @@ public class BirtEngineServlet extends o
 
     @Override
     protected IContext __getContext(HttpServletRequest request, HttpServletResponse response) throws BirtException {
-        BirtReportServiceFactory.getReportService().setContext(getServletContext( ), null);
+        BirtReportServiceFactory.getReportService().setContext(getServletContext(), null);
         
         // set app context
         Map<String, Object> appContext = UtilGenerics.cast(ReportEngineService.getInstance().getEngineConfig().getAppContext());
-        BirtWorker.setWebContextObjects(appContext, request, response);
-        
+        try {
+            BirtWorker.setWebContextObjects(appContext, request, response);
+        } catch (GeneralException e) {
+            throw new BirtException(e.getMessage());
+        }
         return new BirtContext(new ViewerServletRequest(ParameterAccessor.getParameter(request, ParameterAccessor.PARAM_REPORT)
                         , request), response);
     }

Modified: ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtViewerServlet.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtViewerServlet.java?rev=1780683&r1=1780682&r2=1780683&view=diff
==============================================================================
--- ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtViewerServlet.java (original)
+++ ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtViewerServlet.java Sat Jan 28 13:22:55 2017
@@ -23,6 +23,7 @@ import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.ofbiz.base.util.GeneralException;
 import org.eclipse.birt.core.exception.BirtException;
 import org.eclipse.birt.report.context.BirtContext;
 import org.eclipse.birt.report.context.IContext;
@@ -40,11 +41,15 @@ public class BirtViewerServlet extends V
 
     @Override
     protected IContext __getContext(HttpServletRequest request, HttpServletResponse response) throws BirtException {
-        BirtReportServiceFactory.getReportService().setContext(getServletContext( ), null);
+        BirtReportServiceFactory.getReportService().setContext(getServletContext(), null);
         
         // set app context
         Map<String, Object> appContext = UtilGenerics.cast(ReportEngineService.getInstance().getEngineConfig().getAppContext());
-        BirtWorker.setWebContextObjects(appContext, request, response);
+        try {
+            BirtWorker.setWebContextObjects(appContext, request, response);
+        } catch (GeneralException e) {
+            throw new BirtException(e.getMessage());
+        }
         
         return new BirtContext(new ViewerServletRequest(ParameterAccessor.getParameter(request, ParameterAccessor.PARAM_REPORT)
                         , request), response);

Modified: ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/webapp/view/BirtViewHandler.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/webapp/view/BirtViewHandler.java?rev=1780683&r1=1780682&r2=1780683&view=diff
==============================================================================
--- ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/webapp/view/BirtViewHandler.java (original)
+++ ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/webapp/view/BirtViewHandler.java Sat Jan 28 13:22:55 2017
@@ -40,6 +40,7 @@ import org.apache.ofbiz.base.util.UtilHt
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.birt.BirtFactory;
 import org.apache.ofbiz.birt.BirtWorker;
+import org.apache.ofbiz.birt.flexible.BirtUtil;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.GenericEntityException;
 import org.apache.ofbiz.entity.util.EntityUtilProperties;
@@ -75,11 +76,17 @@ public class BirtViewHandler implements
             IReportEngine engine = org.apache.ofbiz.birt.BirtFactory.getReportEngine();
             // open report design
             IReportRunnable design = null;
+
+            // add dynamic parameter for page
+            if (UtilValidate.isEmpty(page) || page.equals("ExecuteFlexibleReport")) {
+                page = (String) request.getParameter("rptDesignFile");
+            }
+
             if (page.startsWith("component://")) {
                 InputStream reportInputStream = BirtFactory.getReportInputStreamFromLocation(page);
                 design = engine.openReportDesign(reportInputStream);
             } else {
-                design = engine.openReportDesign(servletContext.getRealPath(page));
+                design = engine.openReportDesign(page);
             }
             
             Map<String, Object> appContext = UtilGenerics.cast(engine.getConfig().getAppContext());
@@ -99,18 +106,29 @@ public class BirtViewHandler implements
                 locale = UtilHttp.getLocale(request);
             }
             
-            // set output file name
-            String outputFileName = (String) request.getAttribute(BirtWorker.getBirtOutputFileName());
-            if (UtilValidate.isNotEmpty(outputFileName)) {
-                UtilHttp.setContentDisposition(response, outputFileName);
-            }
-            
             // set override content type
-            String overrideContentType = (String) request.getAttribute(BirtWorker.getBirtContentType());
+            String overrideContentType = (String) request.getParameter(BirtWorker.getBirtContentType());
             if (UtilValidate.isNotEmpty(overrideContentType)) {
                 contentType = overrideContentType;
             }
             
+            // set output file name to get also file extension
+            String outputFileName = (String) request.getParameter(BirtWorker.getBirtOutputFileName());
+            if (UtilValidate.isNotEmpty(outputFileName)) {
+                outputFileName = BirtUtil.encodeReportName(outputFileName);
+                String format = BirtUtil.getMimeTypeFileExtension(contentType);
+                if (! outputFileName.endsWith(format)) {
+                    outputFileName = outputFileName.concat(format);
+                }
+                outputFileName = UtilHttp.canonicalizeParameter(outputFileName);
+                response.setHeader("Content-Disposition", "attachment; filename=" + outputFileName);
+            }
+
+            // checking consistency between Birt content type and response content type
+            if (! contentType.equals(response.getContentType())) {
+                response.setContentType(contentType);
+            }
+
             context.put(BirtWorker.getBirtLocale(), locale);
             Delegator delegator = (Delegator) request.getAttribute("delegator");
             String birtImageDirectory = EntityUtilProperties.getPropertyValue("birt", "birt.html.image.directory", delegator);