Implemented: Birt Report Builder: an enhancement of the Birt component. Easier user possibility of report creation. (OFBIZ-6919)

The concept, you define a report domain related to an entity or a service through a master content (master report) and a master search form.
When a high level user create a report on a configured domain, OFBiz prepare an instantiation of the master content (flexible report) that permit
to surcharge the search form (recorded dynamically on the content as ElectronicText) and prepare a rptDesign skeleton.
The high level user can download the rptDesign to edit it trhough the birt editor, with all fields that ofbiz will be load as dataset and when is finish upload the result on the content instantiation.
For the end user, he selected the instantiation report, OFBiz display the report search from the content instantiation and the submission call birt with the search parameters and the linked rptDesign.

The rptDesign file is drive by OFBiz to build the data set by two methods :
 * call the performFind if the domain is related to an entity
 * call the a custom service if the domain is related to a service.
For the last case we need two services, a first who prepare and list available fields for search and display. And a second who realize the search.
By convention currently the first service as the same name that the second service suffixed by 'PrepareFields'

This commit contains :
 * useful UI to create a new content instance from a master content. List, edit, remove a content instance and a simple drop-down to list all instance published (ready to use by end user)
 * all services (with the work flexibleReport) to manage a flexible report, prepare the rptDesign skeleton, reanalyze the rptDesign uploaded, prepare the search form
 * Services interface to define you own search custom method
 * Two examples, one on the entity Exemple and one with the service flexibleReportTurnOver. Warning ! there are raw example without a beautiful rptDesign so you need to update the rptDesign with the birt editor to display something.
Thanks: François Wurmser for initialize this improvement, Jacques and Gil for their time to analyze, document and refactor the code


git-svn-id: https://svn.apache.org/repos/asf/ofbiz/trunk@1780683 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/plugins/birt/config/BirtErrorUiLabels.xml b/plugins/birt/config/BirtErrorUiLabels.xml
new file mode 100644
index 0000000..c7734e7
--- /dev/null
+++ b/plugins/birt/config/BirtErrorUiLabels.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+
+<resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-properties.xsd">
+    <property key="BirtErrorCannotDetermineDataSource">
+        <value xml:lang="en">Failed to determine data source for report</value>
+        <value xml:lang="fr">La détermination de la source de données à échoué</value>
+    </property>
+    <property key="BirtErrorCannotFindUploadedFile">
+        <value xml:lang="en">Could not find uploaded file</value>
+        <value xml:lang="fr">Impossible de trouver le fichier uploadé</value>
+    </property>
+    <property key="BirtErrorCannotLocateReportFile">
+        <value xml:lang="en">Report file cannot be located. It does not exist in specified directory.</value>
+        <value xml:lang="fr">Le fichier de rapport n'a pas pu être localisé. Il n'existe pas dans le dossier spécifié.</value>
+    </property>
+    <property key="BirtErrorCannotLocateReportFolder">
+        <value xml:lang="en">Report folder cannot be located. Are you sure you configured correctly birt.properties for the report folder path?</value>
+        <value xml:lang="fr">Le dossier de stockage des rapports n'a pu être localisé. Êtes-vous sûr d'avoir bien configuré birt.properties pour le chemin du dossier ?</value>
+    </property>
+    <property key="BirtErrorConversionFieldToBirtFailed">
+        <value xml:lang="en">Failed to convert fieldType to birtType</value>
+        <value xml:lang="fr">Conversion du type de champ en type birt échouée</value>
+    </property>
+    <property key="BirtErrorCreatingDefaultSearchForm">
+        <value xml:lang="en">An error happened while creating the display of current form.</value>
+        <value xml:lang="fr">Erreur à la création de l'affichage du formulaire actuel</value>
+    </property>
+    <property key="BirtErrorCreatingFlexibleReport">
+        <value xml:lang="en">Error while generating report</value>
+        <value xml:lang="fr">Erreur lors de la création du rapport</value>
+    </property>
+    <property key="BirtErrorEntityViewNotExist">
+        <value xml:lang="en">This entity/view name is not valid</value>
+        <value xml:lang="fr">Ce nom de vue/entité n'est pas valide</value>
+    </property>
+    <property key="BirtErrorEntityViewNotFound">
+        <value xml:lang="en">No view entity name found</value>
+        <value xml:lang="fr">Aucun nom de vue/entité n'a été trouvé</value>
+    </property>
+    <property key="BirtErrorNoAttributeFound">
+        <value xml:lang="en">Master workflow attribute not found</value>
+        <value xml:lang="fr">L'attribut de workflow du master n'as pas pu être trouvé</value>
+    </property>
+    <property key="BirtErrorNoFlexibleReportToDelete">
+        <value xml:lang="en">No report to delete</value>
+        <value xml:lang="fr">Aucun rapport à supprimer</value>
+    </property>
+    <property key="BirtErrorRetrievingTurnOver">
+        <value xml:lang="en">Error while retrieving turnover informations</value>
+        <value xml:lang="fr">Erreur lors de l'accès aux informations liées au chiffre d'affaire</value>
+    </property>
+    <property key="BirtErrorRunningPerformFind">
+        <value xml:lang="en">Error running performFind</value>
+        <value xml:lang="fr">Erreur lors de l'exécution du performFind</value>
+    </property>
+    <property key="BirtErrorUnauthorisedCharacter">
+        <value xml:lang="en">Form refused: unauthorised character detected</value>
+        <value xml:lang="fr">Formulaire refusé : caractère non autorisé</value>
+    </property>
+    <property key="BirtErrorUnexpectedNumberReportToDelete">
+        <value xml:lang="en">Unexpected number of reports selected for deletion</value>
+        <value xml:lang="fr">Tentative de suppression d'un nombre inattendu de rapports</value>
+    </property>
+</resource>
\ No newline at end of file
diff --git a/plugins/birt/config/BirtUiLabels.xml b/plugins/birt/config/BirtUiLabels.xml
index 1dd76bc..1a402e3 100644
--- a/plugins/birt/config/BirtUiLabels.xml
+++ b/plugins/birt/config/BirtUiLabels.xml
@@ -21,6 +21,7 @@
 <resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-properties.xsd">
     <property key="BirtApplication">
         <value xml:lang="en">Eclipse BIRT Application</value>
+        <value xml:lang="fr">Application Eclipse Birt</value>
         <value xml:lang="ja">Eclipse BIRT 業務</value>
         <value xml:lang="th">Eclipse BIRT Application</value>
         <value xml:lang="zh">Eclipse BIRT应用程序</value>
@@ -41,6 +42,22 @@
         <value xml:lang="zh">开源软件OFBiz的组成部分</value>
         <value xml:lang="zh-TW">開源軟體OFBiz的組成部分</value>
     </property>
+    <property key="BirtConfirmDeleteFlexibleReports">
+        <value xml:lang="en">Are you sure you want to delete all reports?</value>
+        <value xml:lang="fr">Voulez-vous vraiment supprimer tous les rapports ?</value>
+    </property>
+    <property key="BirtDeleteFlexibeReports">
+        <value xml:lang="en">Delete all reports</value>
+        <value xml:lang="fr">Supprimer tous les rapports</value>
+    </property>
+    <property key="BirtDownloadRptDesign">
+        <value xml:lang="en">Download rptdesign file</value>
+        <value xml:lang="fr">Télécharger le fichier rptdesign</value>
+    </property>
+    <property key="BirtEditFlexibleReport">
+        <value xml:lang="en">Edit report</value>
+        <value xml:lang="fr">Modification du rapport</value>
+    </property>
     <property key="BirtErrorFOPRenderingAttachmentForEmail">
         <value xml:lang="en">Error FOP rendering ${birtContentType} attachment for email: ${errorString}</value>
     </property>
@@ -88,6 +105,66 @@
         <value xml:lang="fr">Ruptures de stock, pour le nombre de derniers mois : </value>
         <value xml:lang="zh">上月脱销的数量</value>
     </property>
+    <property key="BirtFindCompareOperator">
+        <value xml:lang="en"> - Operator - </value>
+        <value xml:lang="fr"> - Opérateur - </value>
+    </property>
+    <property key="BirtFindFieldOptionValue0">
+        <value xml:lang="en"> - Lower bound or equal - </value>
+        <value xml:lang="fr"> - Borne basse ou égal - </value>
+    </property>
+    <property key="BirtFindFieldOptionValue1">
+        <value xml:lang="en"> - Higher bound  - </value>
+        <value xml:lang="fr"> - Borne haute - </value>
+    </property>
+    <property key="BirtFilteringParameters">
+        <value xml:lang="en">Filtering parameters</value>
+        <value xml:lang="fr">Paramètres de filtrage</value>
+    </property>
+    <property key="BirtFlexibleReport">
+        <value xml:lang="en">Flexible Report</value>
+        <value xml:lang="fr">Rapport configurable</value>
+    </property>
+    <property key="BirtFlexibleReportGeneration">
+        <value xml:lang="en">Generate report</value>
+        <value xml:lang="fr">Générer un rapport</value>
+    </property>
+    <property key="BirtFlexibleReportInformation">
+        <value xml:lang="en">Report information</value>
+        <value xml:lang="fr">Informations du rapport</value>
+    </property>
+    <property key="BirtFlexibleReportManagement">
+        <value xml:lang="en">Reports management</value>
+        <value xml:lang="fr">Gestion des rapports</value>
+    </property>
+    <property key="BirtFlexibleReportSuccessfullyDeleted">
+        <value xml:lang="en">The report has been successfully deleted</value>
+        <value xml:lang="fr">Le rapport a été supprimé avec succès</value>
+    </property>
+    <property key="BirtFlexibleReportsSuccessfullyDeleted">
+        <value xml:lang="en">All reports have been successfully deleted</value>
+        <value xml:lang="fr">Tous les rapports ont été supprimés avec succès</value>
+    </property>
+    <property key="BirtFlexibleReportSuccessfullyGenerated">
+        <value xml:lang="en">Report has been successfully generated under the name: </value>
+        <value xml:lang="fr">Le rapport a été généré avec succès sous le nom : </value>
+    </property>
+    <property key="BirtFlexibleRptDesignSuccessfullyUploaded">
+        <value xml:lang="en">Report file successfully uploaded</value>
+        <value xml:lang="fr">Le fichier de rapport a été uploadé avec succès</value>
+    </property>
+    <property key="BirtGenericReport">
+        <value xml:lang="en">Use a report</value>
+        <value xml:lang="fr">Utiliser un rapport</value>
+    </property>
+    <property key="BirtManageReports">
+        <value xml:lang="en">Manage reports</value>
+        <value xml:lang="fr">Gérer les rapports</value>
+    </property>
+    <property key="BirtNoKnownFlexibleReport">
+        <value xml:lang="en">You have no report yet</value>
+        <value xml:lang="fr">Vous n'avez aucun rapport pour l'instant</value>
+    </property>
     <property key="BirtOrderReportAllOrderItemsWithDiscountCode">
         <value xml:lang="en">All order items with discount code</value>
         <value xml:lang="fr">Tous les lignes de commandes ayant des codes promotionels</value>
@@ -138,6 +215,26 @@
         <value xml:lang="fr">Quatre tableau créés par Birt (Ventes des 3 derniers mois, Ventes, Ventes par codes promotionels, Demandes par produit) nécessitent d'alimenter la base de données d'Inform. décis. (notez aussi la nécessaire màj du fichier bi.properties après septembre 2023). Ensuite seules les commandes nouvellement approuvées seront prises en compte.</value>
         <value xml:lang="zh">4个Birt报告(最近3个月销售、销售、销售订单折扣优惠码、产品需求)要求提供BI数据库(注意:bi.properites文件需要在2023年9月后进行更新)。只会统计新批准的那些订单。</value>
     </property>
+    <property key="BirtPermissionError">
+        <value xml:lang="en">Birt Permission Error</value>
+        <value xml:lang="fr">Erreur d'autorisation sur le composant Birt</value>
+    </property>
+    <property key="BirtSearchFormSuccessfullyOverridde">
+        <value xml:lang="en">The form has been successfully updated</value>
+        <value xml:lang="fr">Le formulaire a bien été mis à jour</value>
+    </property>
+    <property key="BirtSelectFlexibleReport">
+        <value xml:lang="en">Report choice</value>
+        <value xml:lang="fr">Choix du rapport</value>
+    </property>
+    <property key="BirtSelectMasterFlexibleReport">
+        <value xml:lang="en">Choose report topic</value>
+        <value xml:lang="fr">Choix du sujet du rapport</value>
+    </property>
+    <property key="BirtUploadRptDesign">
+        <value xml:lang="en">Upload rptdesign file</value>
+        <value xml:lang="fr">Importer le fichier rptdesign</value>
+    </property>
     <property key="ExampleBirtChartReport">
         <value xml:lang="en">HTML chart report</value>
         <value xml:lang="fr">Graphiques HTML</value>
@@ -154,6 +251,7 @@
     </property>
     <property key="ExampleBirtExamples">
         <value xml:lang="en">BIRT Examples</value>
+        <value xml:lang="fr">Exemples BIRT</value>
         <value xml:lang="ja">BIRT サンプル</value>
         <value xml:lang="th">ตัวอย่าง BIRT</value>
         <value xml:lang="zh">BIRT样例</value>
@@ -161,18 +259,27 @@
     </property>
     <property key="ExampleBirtMail">
         <value xml:lang="en">Send any format through Mail</value>
+        <value xml:lang="fr">Envoyer différents formats par mail</value>
         <value xml:lang="ja">任意の書式をメールで送信する</value>
         <value xml:lang="zh">通过邮件发送任一格式</value>
         <value xml:lang="zh-TW">通過郵件發送任一格式</value>
     </property>
     <property key="ExampleBirtReport">
         <value xml:lang="en">HTML</value>
-        <value xml:lang="zh">HTML</value>
-        <value xml:lang="zh-TW">HTML</value>
     </property>
     <property key="ExampleBirtViewHandler">
         <value xml:lang="en">PDF</value>
-        <value xml:lang="zh">PDF</value>
-        <value xml:lang="zh-TW">PDF</value>
+    </property>
+    <property key="FormFieldTitle_birtContentType">
+        <value xml:lang="en">Birt export format</value>
+        <value xml:lang="fr">Format d'export Birt</value>
+    </property>
+    <property key="FormFieldTitle_reportName">
+        <value xml:lang="en">Report name</value>
+        <value xml:lang="fr">Nom du rapport</value>
+    </property>
+    <property key="FormFieldTitle_writeFilters">
+        <value xml:lang="en">Generate filters in design</value>
+        <value xml:lang="fr">Générer les filtres dans le design</value>
     </property>
 </resource>
diff --git a/plugins/birt/data/BirtMasterData.xml b/plugins/birt/data/BirtMasterData.xml
new file mode 100644
index 0000000..22f28d1
--- /dev/null
+++ b/plugins/birt/data/BirtMasterData.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<entity-engine-xml>
+    <DataResource dataResourceId="DR_MASTER_EXAMPLE" dataResourceTypeId="ELECTRONIC_TEXT" dataTemplateTypeId="FORM_COMBINED" />
+    <ElectronicText dataResourceId="DR_MASTER_EXAMPLE">
+        <textData><![CDATA[<!--default domain form-->
+<form name="${masterContentId}_${contentId}" type="single" extends="${masterContentId}" extends-resource="component://birt/widget/birt/BirtMasterForms.xml">
+</form>]]>
+        </textData>
+    </ElectronicText>
+    <Content contentId="CTNT_MASTER_EXAMPLE" contentTypeId="REPORT_MASTER"  dataResourceId="DR_MASTER_EXAMPLE" statusId="CTNT_PUBLISHED" contentName="Example" description="Master Content for Example" />
+    <!-- Data retrieval will be done using perform find on entity Example-->
+    <ContentAttribute contentId="CTNT_MASTER_EXAMPLE" attrName="Entity" attrValue="Example"/>
+
+    <CustomMethod customMethodId="CM_FB_TURNOVER" customMethodTypeId="FLEXIBLE_BIRT" customMethodName="flexibleReportTurnOver" description="service to resolve invoice for turnover report domain"/>
+    <DataResource dataResourceId="DR_MASTER_TURNOVER" dataResourceTypeId="ELECTRONIC_TEXT" dataTemplateTypeId="FORM_COMBINED" />
+    <ElectronicText dataResourceId="DR_MASTER_TURNOVER">
+        <textData><![CDATA[<!--default domain form-->
+<form name="${masterContentId}_${contentId}" type="single" extends="${masterContentId}" extends-resource="component://birt/widget/birt/BirtMasterForms.xml">
+</form>]]>
+        </textData>
+    </ElectronicText>
+    <Content contentId="CTNT_MASTER_TURNOVER" customMethodId="CM_FB_TURNOVER" contentTypeId="REPORT_MASTER" dataResourceId="DR_MASTER_TURNOVER" statusId="CTNT_PUBLISHED" contentName="Turnover" description="Master Content for TURNOVER domain" />
+    <!-- Data retrieval will be done using two service call. First the contentAttribute Service give the service that will define which data and label will be retrieved,
+    and which filter and label are supported by the report design (default value will call the second service with "prepareField" suffix).
+    Second, the custom method give the service to retrieve all data in the report design.
+    Here : flexibleReportTurnOverPrepareFields (customMethodName + "prepareFields") then flexibleReportTurnOver-->
+    <ContentAttribute contentId="CTNT_MASTER_TURNOVER" attrName="Service" attrValue="default"/>
+
+</entity-engine-xml>
\ No newline at end of file
diff --git a/plugins/birt/data/BirtSecurityGroupDemoData.xml b/plugins/birt/data/BirtSecurityGroupDemoData.xml
new file mode 100644
index 0000000..6268750
--- /dev/null
+++ b/plugins/birt/data/BirtSecurityGroupDemoData.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<entity-engine-xml>
+    <SecurityPermission permissionId="BIRT_ADMIN" description="ALL Birt component operations"/>
+    <SecurityPermission permissionId="BIRT_CREATE" description="Create report from master"/>
+    <SecurityPermission permissionId="BIRT_UPDATE" description="Update operations for reports"/>
+    <SecurityPermission permissionId="BIRT_DELETE" description="Delete reports"/>
+    <SecurityPermission permissionId="BIRT_VIEW" description="View and use all birt reports"/>
+
+    <SecurityGroup groupId="BIRTADMIN" description="Birt - admin"/>
+    <SecurityGroup groupId="BIRTUSER" description="Birt - user"/>
+
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="BIRT_CREATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="BIRT_UPDATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="BIRT_DELETE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="BIRT_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="OFBTOOLS_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_ROLE_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_ROLE_CREATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_CREATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_ROLE_UPDATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_UPDATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_DELETE"/>
+
+    <SecurityGroupPermission groupId="BIRTUSER" permissionId="BIRT_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTUSER" permissionId="OFBTOOLS_VIEW"/>
+
+    <SecurityGroupPermission groupId="FULLADMIN" permissionId="BIRT_CREATE"/>
+    <SecurityGroupPermission groupId="FULLADMIN" permissionId="BIRT_UPDATE"/>
+    <SecurityGroupPermission groupId="FULLADMIN" permissionId="BIRT_DELETE"/>
+    <SecurityGroupPermission groupId="FULLADMIN" permissionId="BIRT_VIEW"/>
+    <SecurityGroupPermission groupId="FLEXADMIN" permissionId="BIRT_CREATE"/>
+    <SecurityGroupPermission groupId="FLEXADMIN" permissionId="BIRT_UPDATE"/>
+    <SecurityGroupPermission groupId="FLEXADMIN" permissionId="BIRT_DELETE"/>
+    <SecurityGroupPermission groupId="FLEXADMIN" permissionId="BIRT_VIEW"/>
+</entity-engine-xml>
\ No newline at end of file
diff --git a/plugins/birt/data/BirtTypeData.xml b/plugins/birt/data/BirtTypeData.xml
new file mode 100644
index 0000000..f290d1c
--- /dev/null
+++ b/plugins/birt/data/BirtTypeData.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<entity-engine-xml>
+    <ContentType contentTypeId="REPORT_MASTER" description="Report Master" />
+    <ContentType contentTypeId="FLEXIBLE_REPORT" description="Report" />
+    <ContentType contentTypeId="RPTDESIGN" description="Birt report (.rptDesign) file" />
+    <DataTemplateType dataTemplateTypeId="FORM_COMBINED" description="Form widget" extension="xml" />
+
+    <CustomMethodType customMethodTypeId="FLEXIBLE_BIRT" description="Service calling from a birt rptDesign file to populate the data source"/>
+    <CustomMethod customMethodId="CM_FB_PERFORM_FIND" customMethodTypeId="FLEXIBLE_BIRT" customMethodName="callPerformFindFromBirt" description="Generic service to call the standard performFind service from birt rptDesign file"/>
+
+    <EnumerationType enumTypeId="FLEXIBLE_BIRT" description="Mime Type Format available for flexible birt system"/>
+
+    <Enumeration enumId="FB_ODS" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.oasis.opendocument.spreadsheet" sequenceId="01" enumCode="LibreOffice Calc (.ods)"/>
+    <Enumeration enumId="FB_ODT" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.oasis.opendocument.text" sequenceId="02" enumCode="LibreOffice Writer (.odt)"/>
+    <Enumeration enumId="FB_ODP" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.oasis.opendocument.presentation" sequenceId="03" enumCode="LibreOffice Impress (.odp)"/>
+    <Enumeration enumId="FB_PDF" enumTypeId="FLEXIBLE_BIRT" description="application/pdf" sequenceId="04" enumCode="Pdf (.pdf)"/>
+    <Enumeration enumId="FB_PS" enumTypeId="FLEXIBLE_BIRT" description="application/postscript" sequenceId="05" enumCode="Postscript (.ps)"/>
+    <Enumeration enumId="FB_HTML" enumTypeId="FLEXIBLE_BIRT" description="text/html" sequenceId="06" enumCode="Text (.html)"/>
+    <Enumeration enumId="FB_XSLX" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" sequenceId="07" enumCode="Excel (.xlsx)"/>
+    <Enumeration enumId="FB_DOCX" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.openxmlformats-officedocument.wordprocessingml.document" sequenceId="08" enumCode="Word (.docx)"/>
+    <Enumeration enumId="FB_PPTX" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.openxmlformats-officedocument.presentationml.presentation" sequenceId="09" enumCode="Powerpoint (.pptx)"/>
+    <Enumeration enumId="FB_XLS" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.ms-excel" sequenceId="10" enumCode="Excel (.xls)"/>
+    <Enumeration enumId="FB_DOC" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.ms-word" sequenceId="11" enumCode="Word (.doc)"/>
+    <Enumeration enumId="FB_PPT" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.ms-powerpoint" sequenceId="12" enumCode="Powerpoint (.ppt)"/>
+</entity-engine-xml>
\ No newline at end of file
diff --git a/plugins/birt/groovyScripts/report/PrepareBirtCall.groovy b/plugins/birt/groovyScripts/report/PrepareBirtCall.groovy
new file mode 100644
index 0000000..040f103
--- /dev/null
+++ b/plugins/birt/groovyScripts/report/PrepareBirtCall.groovy
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+def birtParameters = [:];
+
+birtParameters.parameters = parameters
+birtParameters.modelElementName = parameters.modelElementName
+birtParameters.userLogin = context.userLogin
+birtParameters.locale = locale
+
+request.setAttribute("birtParameters", birtParameters);
+return "success";
diff --git a/plugins/birt/minilang/BirtPermissionServices.xml b/plugins/birt/minilang/BirtPermissionServices.xml
new file mode 100644
index 0000000..9cf7a21
--- /dev/null
+++ b/plugins/birt/minilang/BirtPermissionServices.xml
@@ -0,0 +1,106 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+
+<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd">
+
+    <simple-method method-name="genericBirtPermission" short-description="Generic Service for Birt Permissions">
+        <set field="primaryPermission" value="BIRT"/>
+        <call-simple-method method-name="genericBasePermissionCheck" xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
+
+        <!-- mainAction based call outs -->
+        <if>
+            <condition>
+                <not>
+                    <if-compare field="hasPermission" value="true" type="Boolean" operator="equals"/>
+                </not>
+            </condition>
+            <then>
+                <if>
+                    <!-- view data resource -->
+                    <condition>
+                        <if-compare field="parameters.mainAction" value="VIEW" operator="equals"/>
+                    </condition>
+                    <then>
+                        <call-simple-method method-name="viewBirtPermission"/>
+                    </then>
+                    <else-if>
+                        <!-- create data resource -->
+                        <condition>
+                            <if-compare field="parameters.mainAction" value="CREATE" operator="equals"/>
+                        </condition>
+                        <then>
+                            <call-simple-method method-name="createBirtPermission"/>
+                        </then>
+                    </else-if>
+                    <else-if>
+                        <!-- update data resource -->
+                        <condition>
+                            <if-compare field="parameters.mainAction" value="UPDATE" operator="equals"/>
+                        </condition>
+                        <then>
+                            <call-simple-method method-name="updateBirtPermission"/>
+                        </then>
+                    </else-if>
+                    <!-- all other actions use main base check -->
+                </if>
+            </then>
+            <else>
+                <log level="info" message="Admin permission found: ${primaryPermission}_${mainAction}"/>
+            </else>
+        </if>
+
+        <log level="info" message="Permission service [${mainAction} / ${parameters.contentId}] completed; returning hasPermission = ${hasPermission}"/>
+        <field-to-result field="hasPermission"/>
+    </simple-method>
+
+    <!-- Birt View Permission -->
+    <simple-method method-name="viewBirtPermission" short-description="Check user can view Birt reports">
+        <!-- if called directly check the main permission -->
+        <if-empty field="hasPermission">
+            <set field="primaryPermission" value="BIRT"/>
+            <set field="mainAction" value="VIEW"/>
+            <call-simple-method method-name="genericBasePermissionCheck"
+                                xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
+        </if-empty>
+    </simple-method>
+
+    <!-- Birt Create Permission -->
+    <simple-method method-name="createBirtPermission" short-description="Check user can create new Birt report">
+        <!-- if called directly check the main permission -->
+        <if-empty field="hasPermission">
+            <set field="primaryPermission" value="BIRT"/>
+            <set field="mainAction" value="CREATE"/>
+            <call-simple-method method-name="genericBasePermissionCheck"
+                                xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
+        </if-empty>
+        <!-- this is about the same as the VIEW permission; but left as a unique service for extending purposes -->
+    </simple-method>
+
+    <!-- Birt Update Permission -->
+    <simple-method method-name="updateBirtPermission" short-description="Check user can update existing Birt report">
+        <!-- if called directly check the main permission -->
+        <if-empty field="hasPermission">
+            <set field="primaryPermission" value="BIRT"/>
+            <set field="mainAction" value="UPDATE"/>
+            <call-simple-method method-name="genericBasePermissionCheck"
+                                xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
+        </if-empty>
+    </simple-method>
+</simple-methods>
\ No newline at end of file
diff --git a/plugins/birt/ofbiz-component.xml b/plugins/birt/ofbiz-component.xml
index fc10f9c..92ec10d 100644
--- a/plugins/birt/ofbiz-component.xml
+++ b/plugins/birt/ofbiz-component.xml
@@ -26,7 +26,10 @@
 
     <classpath type="dir" location="config"/>
     <entity-resource type="data" reader-name="seed" loader="main" location="data/BirtHelpData.xml"/>
-    <entity-resource type="data" reader-name="seed" loader="main" location="data/OrderPortletData.xml"/>
+    <entity-resource type="data" reader-name="seed" loader="main" location="data/BirtTypeData.xml"/>
+    <entity-resource type="data" reader-name="demo" loader="main" location="data/BirtSecurityGroupDemoData.xml"/>
+    <entity-resource type="data" reader-name="demo" loader="main" location="data/BirtMasterData.xml"/>
+
     <service-resource type="model" loader="main" location="servicedef/services.xml"/>
    
     <webapp name="accounting"
diff --git a/plugins/birt/servicedef/services.xml b/plugins/birt/servicedef/services.xml
index 0f1c6ad..97df43e 100644
--- a/plugins/birt/servicedef/services.xml
+++ b/plugins/birt/servicedef/services.xml
@@ -35,8 +35,132 @@
         <attribute name="bodyParameters" type="Map" mode="IN" optional="true"/>
         <attribute name="birtParameters" type="Map" mode="IN" optional="true"/>
         <attribute name="birtLocale" type="Locale" mode="IN" optional="true"/>
-        <attribute name="birtContentType" type="String" mode="IN" optional="true"></attribute>
+        <attribute name="birtContentType" type="String" mode="IN" optional="true"/>
         <attribute name="webSiteId" type="String" mode="IN" optional="true"/>
         <attribute name="body" type="String" mode="OUT" optional="false"/>
     </service>
+
+    <!-- SERVICES FOR REPORTS -->
+    <service name="genericBirtPermission" engine="simple" auth="true"
+            location="component://birt/minilang/BirtPermissionServices.xml" invoke="genericBirtPermission">
+        <description>Generic Birt Permission Service; Takes mainAction to determine the mode.</description>
+        <implements service="permissionInterface"/>
+    </service>
+
+    <!-- Interfaces -->
+    <service name="createFlexibleReportFromMasterInterface" engine="interface">
+        <attribute name="reportName" type="String" mode="IN" optional="false" />
+        <attribute name="description" type="String" mode="IN" optional="true" />
+        <attribute name="writeFilters" type="String" mode="IN" optional="true" />
+        <attribute name="masterContentId" type="String" mode="IN" optional="false" />
+        <attribute name="contentId" type="String" mode="OUT" optional="false" />
+    </service>
+    <service name="prepareFieldsForFlexibleReportInterface" engine="interface">
+        <attribute name="dataMap" type="Map" mode="OUT" optional="false" />
+        <attribute name="fieldDisplayLabels" type="Map" mode="OUT" optional="true"/>
+        <attribute name="filterMap" type="Map" mode="OUT" optional="true" />
+        <attribute name="filterDisplayLabels" type="Map" mode="OUT" optional="true"/>
+    </service>
+    <service name="searchRecordsForFlexibleReportInterface" engine="interface">
+        <attribute name="reportContext" type="Object" mode="IN" optional="false" />
+        <attribute name="records" type="List" mode="OUT" />
+    </service>
+
+    <service name="createFlexibleReport" engine="java" auth="true" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFlexibleReport">
+        <description>BIRT report generation</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <attribute name="dataMap" type="Map" mode="IN" optional="false" />
+        <attribute name="fieldDisplayLabels" type="Map" mode="IN" optional="true" />
+        <attribute name="filterMap" type="Map" mode="IN" optional="true" />
+        <attribute name="filterDisplayLabels" type="Map" mode="IN" optional="true" />
+        <attribute name="writeFilters" type="String" mode="IN" optional="true" />
+        <attribute name="serviceName" type="String" mode="IN" optional="false" />
+        <attribute name="rptDesignName" type="String" mode="IN" optional="false" />
+    </service>
+
+    <service name="createFlexibleReportFromMaster" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFlexibleReportFromMaster">
+        <description>Call report generator with appropriate workflow required by the given master report</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <attribute name="contentId" type="String" mode="IN" optional="false" />
+        <attribute name="reportName" type="String" mode="IN" optional="false" />
+        <attribute name="description" type="String" mode="IN" optional="false" />
+        <attribute name="writeFilters" type="String" mode="IN" optional="true" />
+        <attribute name="reportContentId" type="String" mode="OUT" optional="false"/>
+        <attribute name="textForm" type="String" mode="OUT" optional="false" allow-html="any"/>
+    </service>
+    <service name="createFlexibleReportFromMasterEntityWorkflow" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFlexibleReportFromMasterEntityWorkflow">
+        <description>Create and save in db content, a new report design following entity workflow</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <implements service="createFlexibleReportFromMasterInterface"/>
+        <attribute name="entityViewName" type="String" mode="IN" optional="false" />
+    </service>
+    <service name="createFlexibleReportFromMasterServiceWorkflow" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFlexibleReportFromMasterServiceWorkflow">
+        <description>Create and save in db content, a new report following service workflow</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <implements service="createFlexibleReportFromMasterInterface"/>
+        <attribute name="serviceName" type="String" mode="IN" optional="false" />
+    </service>
+    <service name="deleteAllFlexibleReports" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="deleteAllReports">
+        <description>Delete all reports (admin purposes)</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_DELETE"/></required-permissions>
+    </service>
+    <service name="deleteFlexibleReport" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="deleteFlexibleReport">
+        <description>Delete a report</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_DELETE"/></required-permissions>
+        <attribute name="contentId" type="String" mode="IN" optional="false" />
+    </service>
+
+    <service name="prepareFlexibleReportOptionFieldsFromEntity" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="prepareFlexibleReportOptionFieldsFromEntity">
+        <description>Get fields corresponding to an entity or view, including _op _value and so on depending on type.</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <attribute name="entityViewName" type="String" mode="IN" optional="false" />
+        <attribute name="listMultiFields" type="List" mode="OUT" optional="false" />
+    </service>
+    <service name="prepareFlexibleReportFieldsFromEntity" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="prepareFlexibleReportFieldsFromEntity">
+        <description>prepare maps fields for ReportDesignGenerator</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <implements service="prepareFieldsForFlexibleReportInterface"/>
+        <attribute name="modelEntity" mode="IN" type="Object"/>
+    </service>
+
+    <service name="uploadFlexibleReportRptDesign" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="uploadRptDesign">
+        <description>Upload design-modified rptdesign file</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_UPDATE"/></required-permissions>
+        <attribute name="dataResourceIdRpt" type="String" mode="IN" optional="false" />
+        <attribute name="uploadRptDesign" type="java.nio.ByteBuffer" mode="IN" optional="false" />
+    </service>
+
+    <service name="updateFlexibleReportSearchForm" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="overrideReportForm">
+        <description>Override report form</description>
+        <required-permissions join-type="OR">
+            <check-permission permission="BIRT_CREATE"/>
+            <check-permission permission="BIRT_UPDATE"/>
+        </required-permissions>
+        <attribute name="reportContentId" type="String" mode="IN" optional="false" />
+        <attribute name="overrideFilters" type="String" mode="IN" optional="true" allow-html="any"/>
+    </service>
+    <service name="prepareFlexibleReportSearchFormToEdit" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFormForDisplay">
+        <description>Prepare from DB report form for display</description>
+        <required-permissions join-type="OR">
+            <check-permission permission="BIRT_CREATE"/>
+            <check-permission permission="BIRT_UPDATE"/>
+        </required-permissions>
+        <attribute name="reportContentId" type="String" mode="IN" optional="false" />
+        <attribute name="textForm" type="String" mode="OUT" optional="false" allow-html="any"/>
+    </service>
+
+    <!-- Service example for flexible report-->
+    <service name="callPerformFindFromBirt" engine="java" auth="true" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="callPerformFindFromBirt" transaction-timeout="7200">
+        <description>Manages performFind calling from Birt. Flexible Report from entity workflow. (Default search service)</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_VIEW"/></required-permissions>
+        <implements service="searchRecordsForFlexibleReportInterface"/>
+    </service>
+    <service name="flexibleReportTurnOver" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtMasterReportServices" invoke="turnOver">
+        <description>Service getting data for report. Turnover report</description>
+        <implements service="searchRecordsForFlexibleReportInterface"/>
+    </service>
+    <service name="flexibleReportTurnOverPrepareFields" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtMasterReportServices" invoke="turnOverPrepareFields">
+        <description>Service configuring data for report (works in duo!). Turnover report.</description>
+        <implements service="prepareFieldsForFlexibleReportInterface"/>
+    </service>
 </services>
diff --git a/plugins/birt/src/main/java/org/apache/ofbiz/birt/BirtWorker.java b/plugins/birt/src/main/java/org/apache/ofbiz/birt/BirtWorker.java
index aa00e03..4e7d255 100644
--- a/plugins/birt/src/main/java/org/apache/ofbiz/birt/BirtWorker.java
+++ b/plugins/birt/src/main/java/org/apache/ofbiz/birt/BirtWorker.java
@@ -18,8 +18,12 @@
  *******************************************************************************/
 package org.apache.ofbiz.birt;
 
+import java.io.File;
+import java.io.IOException;
 import java.io.OutputStream;
+import java.io.StringWriter;
 import java.sql.SQLException;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
@@ -28,6 +32,21 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.GeneralException;
+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.string.FlexibleStringExpander;
+import org.apache.ofbiz.birt.flexible.BirtUtil;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.entity.condition.EntityCondition;
+import org.apache.ofbiz.service.GenericServiceException;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.service.ServiceUtil;
+import org.apache.ofbiz.webapp.WebAppUtil;
 import org.eclipse.birt.report.engine.api.EXCELRenderOption;
 import org.eclipse.birt.report.engine.api.EngineException;
 import org.eclipse.birt.report.engine.api.HTMLRenderOption;
@@ -38,13 +57,6 @@
 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.apache.ofbiz.base.util.Debug;
-import org.apache.ofbiz.base.util.GeneralException;
-import org.apache.ofbiz.base.util.UtilGenerics;
-import org.apache.ofbiz.base.util.UtilValidate;
-import org.apache.ofbiz.entity.Delegator;
-import org.apache.ofbiz.security.Security;
-import org.apache.ofbiz.service.LocalDispatcher;
 
 public final class BirtWorker {
 
@@ -55,10 +67,11 @@
     private final static String BIRT_IMAGE_DIRECTORY = "birtImageDirectory";
     private final static String BIRT_CONTENT_TYPE = "birtContentType";
     private final static String BIRT_OUTPUT_FILE_NAME = "birtOutputFileName";
+    private static final String resourceError = "BirtErrorUiLabels";
 
     private final static HTMLServerImageHandler imageHandler = new HTMLServerImageHandler();
 
-    private BirtWorker () {}
+    private BirtWorker() {}
 
     /**
      * export report
@@ -71,16 +84,18 @@
      * @throws SQLException
      */
     public static void exportReport(IReportRunnable design, Map<String, ? extends Object> context, String contentType, OutputStream output)
-        throws EngineException, GeneralException, SQLException {
+            throws EngineException, GeneralException, SQLException {
 
-        Locale birtLocale = (Locale)context.get(BIRT_LOCALE);
-        String birtImageDirectory = (String)context.get(BIRT_IMAGE_DIRECTORY);
+        Locale birtLocale = (Locale) context.get(BIRT_LOCALE);
+        String birtImageDirectory = (String) context.get(BIRT_IMAGE_DIRECTORY);
 
         if (contentType == null) {
             contentType = "text/html";
+        } else {
+            contentType = contentType.toLowerCase();
         }
         if (birtImageDirectory == null) {
-             birtImageDirectory = "/";
+            birtImageDirectory = "/";
         }
         Debug.logInfo("Get report engine", module);
         IReportEngine engine = BirtFactory.getReportEngine();
@@ -92,107 +107,65 @@
         }
 
         // set parameters if exists
-        Map<String, Object> parameters = UtilGenerics.cast(context.get(BirtWorker.BIRT_PARAMETERS));
+        Map<String, Object> parameters = UtilGenerics.cast(context.get(BirtWorker.getBirtParameters()));
         if (parameters != null) {
-            Debug.logInfo("Set BIRT parameters:" + parameters, module);
+            //Debug.logInfo("Set BIRT parameters:" + parameters, module);
             task.setParameterValues(parameters);
         }
 
         // set output options
+        if (! BirtUtil.isSupportedMimeType(contentType)) {
+            throw new GeneralException("Unknown content type : " + contentType);
+        }
         RenderOption options = new RenderOption();
-        if ("text/html".equalsIgnoreCase(contentType)) { // HTML
-            options.setOutputFormat(RenderOption.OUTPUT_FORMAT_HTML);
+        options.setOutputFormat(BirtUtil.getMimeTypeOutputFormat(contentType));
+
+        //specific process for mimetype
+        if ("text/html".equals(contentType)) { // HTML
             HTMLRenderOption htmlOptions = new HTMLRenderOption(options);
             htmlOptions.setImageDirectory(birtImageDirectory);
             htmlOptions.setBaseImageURL(birtImageDirectory);
             options.setImageHandler(imageHandler);
-        } else if ("application/postscript".equalsIgnoreCase(contentType)) { // Post Script
-            options.setOutputFormat("postscript");
-        } else if ("application/pdf".equalsIgnoreCase(contentType)) { // PDF
-            options.setOutputFormat(RenderOption.OUTPUT_FORMAT_PDF);
+        } else if ("application/pdf".equals(contentType)) { // PDF
             PDFRenderOption pdfOptions = new PDFRenderOption(options);
-            pdfOptions.setOption(IPDFRenderOption.PAGE_OVERFLOW, Boolean.TRUE );
-        } else if ("application/vnd.ms-word".equalsIgnoreCase(contentType)) { // MS Word
-            options.setOutputFormat("doc");
-        }  else if ("application/vnd.ms-excel".equalsIgnoreCase(contentType)) { // MS Excel
-            options.setOutputFormat("xls");
+            pdfOptions.setOption(IPDFRenderOption.PAGE_OVERFLOW, Boolean.TRUE);
+        } else if ("application/vnd.ms-excel".equals(contentType)) { // MS Excel
             new EXCELRenderOption(options);
-        } else if ("application/vnd.ms-powerpoint".equalsIgnoreCase(contentType)) { // MS Power Point
-            options.setOutputFormat("ppt");
-        } else if ("application/vnd.oasis.opendocument.text".equalsIgnoreCase(contentType)) { // Open Document Text
-            options.setOutputFormat("odt");
-        } else if ("application/vnd.oasis.opendocument.spreadsheet".equalsIgnoreCase(contentType)) { // Open Document Spreadsheet
-            options.setOutputFormat("ods");
-        } else if ("application/vnd.oasis.opendocument.presentation".equalsIgnoreCase(contentType)) { // Open Document Presentation
-            options.setOutputFormat("odp");
-        } else if ("application/vnd.openxmlformats-officedocument.wordprocessingml.document".equalsIgnoreCase(contentType)) { // MS Word 2007
-            options.setOutputFormat("docx");
-        } else if ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equalsIgnoreCase(contentType)) { // MS Excel 2007
-            options.setOutputFormat("xlsx");
-        } else if ("application/vnd.openxmlformats-officedocument.presentationml.presentation".equalsIgnoreCase(contentType)) { // MS Word 2007
-            options.setOutputFormat("pptx");
-        } else {
-            throw new GeneralException("Unknown content type : " + contentType);
         }
 
         options.setOutputStream(output);
         task.setRenderOption(options);
 
         // run report
-        Debug.logInfo("BIRT's locale is: " + task.getLocale(), module);
-        Debug.logInfo("Run report's task", module);
+        if (Debug.infoOn()) {
+            Debug.logInfo("BIRT's locale is: " + task.getLocale(), module);
+            Debug.logInfo("Run report's task", module);
+        }
         task.run();
         task.close();
     }
-    
+
     /**
      * set web context objects
      * @param appContext
      * @param request
      * @param response
      */
-    public static void setWebContextObjects(Map<String, Object> appContext, HttpServletRequest request, HttpServletResponse response) {
+    public static void setWebContextObjects(Map<String, Object> appContext, HttpServletRequest request, HttpServletResponse response)
+    throws GeneralException {
         HttpSession session = request.getSession();
         ServletContext servletContext = session.getServletContext();
-        
-        // set delegator
-        Delegator delegator = (Delegator) session.getAttribute("delegator");
-        if (UtilValidate.isEmpty(delegator)) {
-            delegator = (Delegator) servletContext.getAttribute("delegator");
-        }
-        if (UtilValidate.isEmpty(delegator)) {
-            delegator = (Delegator) request.getAttribute("delegator");
-        }
-        if (UtilValidate.isNotEmpty(delegator)) {
-            appContext.put("delegator", delegator);
+
+        if (appContext == null || servletContext == null) {
+            throw new GeneralException("The context reporting is empty, check your configuration");
         }
 
-        // set JDBC connection
-        //appContext.put("OdaJDBCDriverPassInConnection", connection);
-
-        // set dispatcher
-        LocalDispatcher dispatcher = (LocalDispatcher) session.getAttribute("dispatcher");
-        if (UtilValidate.isEmpty(dispatcher)) {
-            dispatcher = (LocalDispatcher) servletContext.getAttribute("dispatcher");
-        }
-        if (UtilValidate.isEmpty(dispatcher)) {
-            dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
-        }
-        if (UtilValidate.isNotEmpty(dispatcher)) {
-            appContext.put("dispatcher", dispatcher);
-        }
-
-        // set security
-        Security security = (Security) session.getAttribute("security");
-        if (UtilValidate.isEmpty(security)) {
-            security = (Security) servletContext.getAttribute("security");
-        }
-        if (UtilValidate.isEmpty(security)) {
-            security = (Security) request.getAttribute("security");
-        }
-        if (UtilValidate.isNotEmpty(security)) {
-            appContext.put("security", security);
-        }
+        // initialize the delegator
+        appContext.put("delegator", WebAppUtil.getDelegator(servletContext));
+        // initialize security
+        appContext.put("security", WebAppUtil.getSecurity(servletContext));
+        // initialize the services dispatcher
+        appContext.put("dispatcher", WebAppUtil.getDispatcher(servletContext));
     }
 
     public static String getBirtParameters () {
@@ -214,4 +187,93 @@
     public static String getBirtOutputFileName () {
         return BIRT_OUTPUT_FILE_NAME;
     }
+
+    //TODO documentation
+    public static String recordReportContent(Delegator delegator, LocalDispatcher dispatcher, Map<String, Object> context) throws GeneralException {
+        Locale locale = (Locale) context.get("locale");
+        String description = (String) context.get("description");
+        String reportName = (String) context.get("reportName");
+        String writeFilters = (String) context.get("writeFilters");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        String entityViewName = (String) context.get("entityViewName");
+        String serviceName = (String) context.get("serviceName");
+        String masterContentId = (String) context.get("masterContentId");
+        String dataResourceId = delegator.getNextSeqId("DataResource");
+        String contentId = delegator.getNextSeqId("Content");
+        context.put("contentId", contentId);
+
+        if (UtilValidate.isEmpty(serviceName) && UtilValidate.isEmpty(entityViewName)) {
+            throw new GenericServiceException("Service and entity name cannot be both empty");
+        }
+
+        String modelType = null;
+        String modelElementName = null;
+        String workflowType = null;
+        if (UtilValidate.isEmpty(serviceName)) {
+            modelElementName = entityViewName;
+            workflowType = "Entity";
+        } else {
+            modelElementName = serviceName;
+            workflowType = "Service";
+        }
+
+        //resolve the path location to store the RptDesign file, check if the file already exists under this name and increment index name if needed
+        List<GenericValue> listRptDesigns = null;
+        EntityCondition entityConditionRpt = EntityCondition.makeCondition("contentTypeId", "RPTDESIGN");
+        String templatePathLocation = BirtUtil.resolveTemplatePathLocation();
+        File templatePathLocationDir = new File(templatePathLocation);
+            if (!templatePathLocationDir.exists()) {
+                boolean created = templatePathLocationDir.mkdirs();
+                if (!created) {
+                    new GeneralException(UtilProperties.getMessage(resourceError, "BirtErrorCannotLocateReportFolder", locale));
+                }
+            }
+        int i = 0;
+        String templateFileLocation = null;
+        EntityCondition ecl = null;
+        do {
+            StringBuffer rptDesignNameSb = new StringBuffer(templatePathLocation);
+            rptDesignNameSb.append(BirtUtil.encodeReportName(reportName));
+            rptDesignNameSb.append("_").append(i);
+            rptDesignNameSb.append(".rptdesign");
+            templateFileLocation = rptDesignNameSb.toString();
+            EntityCondition entityConditionOnName = EntityCondition.makeCondition("drObjectInfo", templateFileLocation);
+            ecl = EntityCondition.makeCondition(UtilMisc.toList(entityConditionRpt, entityConditionOnName));
+            i++;
+        } while (delegator.findCountByCondition("ContentDataResourceView", ecl, null, null) > 0);
+
+        //resolve the initial form structure from master content
+        Map<String, Object> resultElectronicText = dispatcher.runSync("getElectronicText", UtilMisc.toMap("contentId", masterContentId, "locale", locale, "userLogin", userLogin));
+        if (ServiceUtil.isError(resultElectronicText)) {
+            new GeneralException(ServiceUtil.getErrorMessage(resultElectronicText));
+        }
+        String reportForm = (String) resultElectronicText.get("textData");
+        if (! reportForm.startsWith("<?xml")) {
+            StringBuffer xmlHeaderForm = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+            xmlHeaderForm.append("<forms xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://ofbiz.apache.org/dtds/widget-form.xsd\">");
+            xmlHeaderForm.append(reportForm);
+            xmlHeaderForm.append("</forms>");
+            reportForm = xmlHeaderForm.toString();
+        }
+        FlexibleStringExpander reportFormExpd = FlexibleStringExpander.getInstance(reportForm);
+        reportForm = reportFormExpd.expandString(context);
+
+        //create content and dataressource strucutre
+        dispatcher.runSync("createDataResource", UtilMisc.toMap("dataResourceId", dataResourceId, "dataResourceTypeId", "ELECTRONIC_TEXT", "dataTemplateTypeId", "FORM_COMBINED", "userLogin", userLogin));
+        dispatcher.runSync("createElectronicTextForm", UtilMisc.toMap("dataResourceId", dataResourceId, "textData", reportForm, "userLogin", userLogin));
+        dispatcher.runSync("createContent", UtilMisc.toMap("contentId", contentId, "contentTypeId", "FLEXIBLE_REPORT", "dataResourceId", dataResourceId, "statusId", "CTNT_IN_PROGRESS", "contentName", reportName, "description", description, "userLogin", userLogin));
+        String dataResourceIdRpt = delegator.getNextSeqId("DataResource");
+        String contentIdRpt = delegator.getNextSeqId("Content");
+        String rptDesignName = BirtUtil.encodeReportName(reportName);
+        if (! rptDesignName.endsWith(".rptdesign")) {
+            rptDesignName = rptDesignName.concat(".rptdesign");
+        }
+        dispatcher.runSync("createDataResource", UtilMisc.toMap("dataResourceId", dataResourceIdRpt, "dataResourceTypeId", "LOCAL_FILE", "mimeTypeId", "text/rptdesign", "dataResourceName", rptDesignName, "objectInfo", templateFileLocation, "userLogin", userLogin));
+        dispatcher.runSync("createContent", UtilMisc.toMap("contentId", contentIdRpt, "contentTypeId", "RPTDESIGN", "dataResourceId", dataResourceIdRpt, "statusId", "CTNT_PUBLISHED", "contentName", reportName, "description", description + " (.rptDesign file)", "userLogin", userLogin));
+        dispatcher.runSync("createContentAssoc", UtilMisc.toMap("contentId", masterContentId, "contentIdTo", contentId, "contentAssocTypeId", "SUB_CONTENT", "userLogin", userLogin));
+        dispatcher.runSync("createContentAssoc", UtilMisc.toMap("contentId", contentId, "contentIdTo", contentIdRpt, "contentAssocTypeId", "SUB_CONTENT", "userLogin", userLogin));
+        dispatcher.runSync("createContentAttribute", UtilMisc.toMap("contentId", contentId, "attrName", workflowType, "attrValue", modelElementName, "userLogin", userLogin));
+        return contentId;
+    }
+
 }
diff --git a/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtMasterReportServices.java b/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtMasterReportServices.java
new file mode 100644
index 0000000..e0ec7fb
--- /dev/null
+++ b/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtMasterReportServices.java
@@ -0,0 +1,294 @@
+package org.apache.ofbiz.birt.flexible;
+
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ofbiz.base.util.UtilDateTime;
+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.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.EntityExpr;
+import org.apache.ofbiz.entity.condition.EntityOperator;
+import org.apache.ofbiz.entity.util.EntityUtil;
+import org.apache.ofbiz.party.party.PartyHelper;
+import org.apache.ofbiz.service.DispatchContext;
+import org.apache.ofbiz.service.ServiceUtil;
+import org.eclipse.birt.report.engine.api.script.IReportContext;
+
+public class BirtMasterReportServices {
+
+    public static final String module = BirtServices.class.getName();
+    public static final String resource = "BirtUiLabels";
+    public static final String resource_error = "BirtErrorUiLabels";
+
+    // The following funtion are flexible service as example for reporting
+    public static Map<String, Object> workEffortPerPersonPrepareDate(DispatchContext dctx, Map<String, Object> context) {
+        Map<String, String> dataMap = UtilMisc.toMap("lastName", "name", "firstName", "name", "hours", "floating-point", "fromDate", "date-time", "thruDate", "date-time");
+        LinkedHashMap<String, String> filterMap = new LinkedHashMap<String, String>();
+        filterMap.put("firstName", "name");
+        filterMap.put("lastName", "name");
+        filterMap.put("fromDate", "date-time");
+        filterMap.put("thruDate", "date-time");
+        Map<String, String> fieldDisplayLabels = UtilMisc.toMap("lastName", "Last name", "firstName", "First name", "hours", "Hours", "fromDate", "From date", "thruDate", "Thru date");
+        LinkedHashMap<String, String> filterDisplayLabels = new LinkedHashMap<String, String>();
+        filterDisplayLabels.put("firstName", "First name");
+        filterDisplayLabels.put("lastName", "Last name");
+        filterDisplayLabels.put("fromDate", "From date");
+        filterDisplayLabels.put("thruDate", "Thru date");
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        result.put("dataMap", dataMap);
+        result.put("filterMap", filterMap);
+        result.put("fieldDisplayLabels", fieldDisplayLabels);
+        result.put("filterDisplayLabels", filterDisplayLabels);
+        return result;
+    }
+
+    public static Map<String, Object> workEffortPerPerson(DispatchContext dctx, Map<String, Object> context) {
+        Delegator delegator = (Delegator) dctx.getDelegator();
+        IReportContext reportContext = (IReportContext) context.get("reportContext");
+        Map<String, Object> parameters = (Map<String, Object>) reportContext.getParameterValue("parameters");
+        List<GenericValue> listWorkEffortTime = null;
+
+        if (UtilValidate.isEmpty(parameters.get("firstName")) && UtilValidate.isEmpty(parameters.get("lastName"))) {
+            return ServiceUtil.returnError("First and last name can not be both empty");
+        }
+        List<GenericValue> listPersons = null;
+        try {
+            // TODO: translate labels
+            List<EntityExpr> listConditions = new ArrayList<EntityExpr>();
+            if (UtilValidate.isNotEmpty(parameters.get("firstName"))) {
+                EntityExpr conditionFirstName = EntityCondition.makeCondition("firstName", parameters.get("firstName"));
+                listConditions.add(conditionFirstName);
+            }
+            if (UtilValidate.isNotEmpty(parameters.get("lastName"))) {
+                EntityExpr conditionLastName = EntityCondition.makeCondition("lastName", parameters.get("lastName"));
+                listConditions.add(conditionLastName);
+            }
+            EntityCondition ecl = EntityCondition.makeCondition(listConditions, EntityOperator.AND);
+            listPersons = delegator.findList("Person", ecl, UtilMisc.toSet("partyId", "firstName", "lastName"), null, null, true);
+            GenericValue person = null;
+            if (listPersons.size() > 1) {
+                return ServiceUtil.returnError("Your criteria match with several people");
+            } else if (listPersons.size() == 1) {
+                person = listPersons.get(0);
+            } else {
+                return ServiceUtil.returnError("Could not find this person");
+            }
+            String partyId = person.getString("partyId");
+
+            List<EntityExpr> listConditionsWorkEffort = new ArrayList<EntityExpr>();
+            Timestamp thruDate = null;
+            Timestamp fromDate = null;
+            if (UtilValidate.isEmpty(parameters.get("fromDate"))) {
+                return ServiceUtil.returnError("The starting date is mandatory");
+            } else {
+                fromDate = Timestamp.valueOf((String) parameters.get("fromDate"));
+                EntityExpr conditionFromDate = EntityCondition.makeCondition("fromDate", EntityOperator.GREATER_THAN_EQUAL_TO, fromDate);
+                listConditionsWorkEffort.add(conditionFromDate);
+            }
+            if (UtilValidate.isEmpty(parameters.get("thruDate"))) {
+                thruDate = UtilDateTime.nowTimestamp();
+            } else {
+                thruDate = Timestamp.valueOf((String) parameters.get("thruDate"));
+            }
+            EntityExpr conditionThruDate = EntityCondition.makeCondition("thruDate", EntityOperator.LESS_THAN_EQUAL_TO, thruDate);
+            listConditionsWorkEffort.add(conditionThruDate);
+            EntityExpr conditionParty = EntityCondition.makeCondition("partyId", partyId);
+            listConditionsWorkEffort.add(conditionParty);
+            ecl = EntityCondition.makeCondition(listConditionsWorkEffort, EntityOperator.AND);
+            listWorkEffortTime = delegator.findList("WorkEffortAndTimeEntry", ecl, UtilMisc.toSet("hours", "fromDate", "thruDate"), null, null, true);
+        } catch (GenericEntityException e) {
+            e.printStackTrace();
+            ServiceUtil.returnError("Error getting party from person name.");
+        }
+        List<GenericValue> listCompiled = new ArrayList<GenericValue>();
+        if (UtilValidate.isNotEmpty(listWorkEffortTime)) listCompiled.addAll(listWorkEffortTime);
+        if (UtilValidate.isNotEmpty(listPersons)) listCompiled.addAll(listPersons);
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        result.put("records", listCompiled);
+        return result;
+    }
+
+    public static Map<String, Object> turnOverPrepareFields(DispatchContext dctx, Map<String, Object> context) {
+        Map<String, String> dataMap = UtilMisc.toMap("invoiceTypeId", "short-varchar", "invoicePartyId", "short-varchar", "statusId", "short-varchar", "invoiceDate", "date", "dueDate", "date", "currencyUomId", "short-varchar", "invoiceItemTypeId", "short-varchar", "invoiceItemSeqId", "short-varchar", "productId", "short-varchar", "partyId", "short-varchar", "partyName", "short-varchar", "primaryProductCategoryId", "short-varchar", "quantity", "numeric", "amount", "currency-amount", "productStoreId", "short-varchar", "storeName", "short-varchar");
+        Map<String, String> fieldDisplayLabels = UtilMisc.toMap("invoiceTypeId", "invoice Type", "invoicePartyId", "Invoice", "statusId", "Status", "invoiceDate", "Date", "dueDate", "Due date ", "currencyUomId", "Currency", "invoiceItemTypeId", "Invoice type line", "invoiceItemSeqId", "Invoice line", "productId", "Product", "partyId", "Customer", "partyName", "Customer name", "primaryProductCategoryId", "Product category", "quantity", "Qty", "amount", "Montant", "productStoreId", "Product Store", "storeName", "Product store name");
+        LinkedHashMap<String, String> filterMap = new LinkedHashMap<String, String>(); 
+        filterMap.put("productCategoryId", "short-varchar");
+        filterMap.put("productStoreId", "short-varchar");
+        filterMap.put("fromDate", "date");
+        filterMap.put("thruDate", "date");
+        LinkedHashMap<String, String> filterDisplayLabels = new LinkedHashMap<String, String>();
+        //it's better to use Label Map, maybe an improvement point !
+        filterDisplayLabels.put("productCategoryId", "product Category");
+        filterDisplayLabels.put("productStoreId", "product Store");
+        filterDisplayLabels.put("fromDate", "from Date");
+        filterDisplayLabels.put("thruDate", "through Date");
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        result.put("dataMap", dataMap);
+        result.put("filterMap", filterMap);
+        result.put("fieldDisplayLabels", fieldDisplayLabels);
+        result.put("filterDisplayLabels", filterDisplayLabels);
+        return result;
+    }
+
+    public static Map<String, Object> turnOver(DispatchContext dctx, Map<String, Object> context) {
+        Delegator delegator = (Delegator) dctx.getDelegator();
+        Locale locale = (Locale) context.get("locale");
+        IReportContext reportContext = (IReportContext) context.get("reportContext");
+        Map<String, Object> parameters = (Map<String, Object>) reportContext.getParameterValue("parameters");
+
+        List<GenericValue> listTurnOver = null;
+        List<Map<String, Object>> listInvoiceEditable = new ArrayList<Map<String, Object>>();
+        List<EntityCondition> listAllConditions = new ArrayList<EntityCondition>();
+        try {
+            // treating fromDate field condition
+            if (UtilValidate.isNotEmpty(parameters.get("fromDate"))) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                String fromDateString = (String) parameters.get("fromDate");
+                Timestamp fromDate = new Timestamp(sdf.parse(fromDateString).getTime());
+                EntityExpr conditionFromDate = EntityCondition.makeCondition("invoiceDate", EntityOperator.GREATER_THAN_EQUAL_TO, fromDate);
+                listAllConditions.add(conditionFromDate);
+            }
+
+            // treating throughDate field condition
+            if (UtilValidate.isNotEmpty(parameters.get("throughDate"))) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                String throughDateString = (String) parameters.get("throughDate");
+                Timestamp throughDate = new Timestamp(sdf.parse(throughDateString).getTime());
+                EntityExpr conditionThroughDate = EntityCondition.makeCondition("invoiceDate", EntityOperator.LESS_THAN_EQUAL_TO, throughDate);
+                listAllConditions.add(conditionThroughDate);
+            }
+
+            // product category field condition
+            if (UtilValidate.isNotEmpty(parameters.get("productCategoryId"))) {
+                List<String> productCategoryList = new ArrayList<String>();
+                if (parameters.get("productCategoryId") instanceof String) {
+                    String productCategoryId = (String) parameters.get("productCategoryId");
+                    productCategoryList.add(productCategoryId);
+                } else {
+                    productCategoryList = (List<String>) parameters.get("productCategoryId");
+                }
+                // getting productIds in these categories
+                EntityExpr conditionProductCategory = EntityCondition.makeCondition("primaryProductCategoryId", EntityOperator.IN, productCategoryList);
+                EntityExpr conditionFromDate = EntityCondition.makeCondition("fromDate", EntityOperator.GREATER_THAN_EQUAL_TO, UtilDateTime.nowTimestamp());
+                EntityExpr conditionBeforeDate = EntityCondition.makeCondition("thruDate", EntityOperator.LESS_THAN_EQUAL_TO, UtilDateTime.nowTimestamp());
+                EntityExpr conditionNull = EntityCondition.makeCondition("thruDate", null);
+                EntityCondition conditionThroughDate = EntityCondition.makeCondition(EntityOperator.OR, UtilMisc.toList(conditionBeforeDate, conditionNull));
+                List<GenericValue> listProductIds = delegator.findList("ProductCategoryMember", EntityCondition.makeCondition(UtilMisc.toList(conditionProductCategory, conditionFromDate, conditionThroughDate)), UtilMisc.toSet("productId"), null, null, true);
+                List<String> listProductIdsString = EntityUtil.getFieldListFromEntityList(listProductIds, "productId", true);
+
+                EntityExpr conditionProductCat = EntityCondition.makeCondition("productId", EntityOperator.IN, listProductIdsString);
+                listAllConditions.add(conditionProductCat);
+            }
+
+            // productStoreId condition
+            List<String> productStoreList = new ArrayList<String>();
+            if (UtilValidate.isNotEmpty(parameters.get("productStoreId"))) {
+                if (parameters.get("productStoreId") instanceof String) {
+                    String productStoreId = (String) parameters.get("productStoreId");
+                    productStoreList.add(productStoreId);
+                } else {
+                    productStoreList = (List<String>) parameters.get("productStoreId");
+                }
+                // getting list of invoice Ids linked to these productStore
+                EntityExpr conditionProductStoreId = EntityCondition.makeCondition("productStoreId", EntityOperator.IN, productStoreList);
+                List<GenericValue> listOrderAndProductStores = delegator.findList("OrderAndProductStore", conditionProductStoreId, UtilMisc.toSet("orderId"), null, null, true);
+                List<String> listOrderIds = EntityUtil.getFieldListFromEntityList(listOrderAndProductStores, "orderId", true);
+                EntityExpr conditionOrderId = EntityCondition.makeCondition("orderId", EntityOperator.IN, listOrderIds);
+                List<GenericValue> listInvoices = delegator.findList("OrderItemBilling", conditionOrderId, UtilMisc.toSet("invoiceId"), null, null, false);
+                List<String> listInvoiceString = EntityUtil.getFieldListFromEntityList(listInvoices, "invoiceId", true);
+
+                EntityExpr conditionInvoiceIdProductStore = EntityCondition.makeCondition("invoiceId", EntityOperator.IN, listInvoiceString);
+                listAllConditions.add(conditionInvoiceIdProductStore);
+            }
+
+            // adding mandatory conditions
+            // condition on invoice item type
+            List<String> listInvoiceItemType = UtilMisc.toList("ITM_PROMOTION_ADJ", "INV_PROD_ITEM", "INV_FPROD_ITEM", "INV_DPROD_ITEM", "INV_FDPROD_ITEM", "INV_PROD_FEATR_ITEM");
+            listInvoiceItemType.add("ITM_DISCOUNT_ADJ");
+            listInvoiceItemType.add("CRT_FPROD_ITEM");
+            listInvoiceItemType.add("CRT_DPROD_ITEM");
+            listInvoiceItemType.add("CRT_FDPROD_ITEM");
+            listInvoiceItemType.add("CRT_SPROD_ITEM");
+            listInvoiceItemType.add("CRT_PROMOTION_ADJ");
+            listInvoiceItemType.add("CRT_DISCOUNT_ADJ");
+            listInvoiceItemType.add("CRT_MAN_ADJ");
+            listInvoiceItemType.add("INV_SPROD_ITEM");
+            EntityExpr conditionInvoiceItemType = EntityCondition.makeCondition("invoiceItemTypeId", EntityOperator.IN, listInvoiceItemType);
+            listAllConditions.add(conditionInvoiceItemType);
+
+            // condition on invoice ((not cancelled) or null)
+            EntityExpr conditionStatusNotCancelled = EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "INVOICE_CANCELLED");
+            EntityExpr conditionStatusNull = EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, null);
+            EntityCondition conditionStatus = EntityCondition.makeCondition(UtilMisc.toList(conditionStatusNotCancelled, conditionStatusNull), EntityOperator.OR);
+            listAllConditions.add(conditionStatus);
+
+            // condition sales invoice or customer return invoice
+            EntityExpr conditionSalesInvoice = EntityCondition.makeCondition("invoiceTypeId", EntityOperator.IN, UtilMisc.toList("SALES_INVOICE", "CUST_RTN_INVOICE"));
+            listAllConditions.add(conditionSalesInvoice);
+
+            // retrieving all invoices
+            Set<String> fieldsToSelect = UtilMisc.toSet("invoiceId");
+            fieldsToSelect.add("invoiceTypeId");
+            fieldsToSelect.add("invoicePartyId");
+            fieldsToSelect.add("statusId");
+            fieldsToSelect.add("invoiceDate");
+            fieldsToSelect.add("dueDate");
+            fieldsToSelect.add("currencyUomId");
+            fieldsToSelect.add("invoiceItemTypeId");
+            fieldsToSelect.add("invoiceItemSeqId");
+            fieldsToSelect.add("quantity");
+            fieldsToSelect.add("amount");
+            fieldsToSelect.add("productId");
+            fieldsToSelect.add("partyId");
+            fieldsToSelect.add("primaryProductCategoryId");
+            listTurnOver = delegator.findList("InvoiceItemProductAndParty", EntityCondition.makeCondition(listAllConditions), fieldsToSelect, null, null, true);
+
+            // adding missing fields
+            for (GenericValue invoice : listTurnOver) {
+                Map<String, Object> invoiceEditableTemp = (Map<String, Object>) invoice.clone();
+                invoiceEditableTemp.remove("GenericEntity");
+                Map<String, Object> invoiceEditable = new HashMap<String, Object>();
+                invoiceEditable.putAll(invoiceEditableTemp);
+                invoiceEditable.put("partyName", PartyHelper.getPartyName(delegator, invoice.getString("partyId"), false));
+
+                // adding productStoreId and productStoreName
+                EntityExpr conditionInvoiceId = EntityCondition.makeCondition("invoiceId", invoice.getString("invoiceId"));
+//                EntityExpr conditionInvoiceItemSeqId = EntityCondition.makeCondition("invoiceItemSeqId", invoice.getString("invoiceItemSeqId"));
+//                List<GenericValue> listOrderBilling = delegator.findList("OrderItemBilling", EntityCondition.makeCondition(UtilMisc.toList(conditionInvoiceId, conditionInvoiceItemSeqId)), UtilMisc.toSet("orderId"), null, null, false);
+                List<GenericValue> listOrderBilling = delegator.findList("OrderItemBilling", conditionInvoiceId, UtilMisc.toSet("orderId"), null, null, false);
+                if (UtilValidate.isNotEmpty(listOrderBilling)) {
+                    GenericValue orderBilling = EntityUtil.getFirst(listOrderBilling);
+                    EntityExpr conditionOrderId = EntityCondition.makeCondition("orderId", orderBilling.getString("orderId"));
+                    List<GenericValue> listProductStore = delegator.findList("OrderAndProductStore", conditionOrderId, null, null, null, true);
+                    GenericValue productStore = EntityUtil.getFirst(listProductStore);
+                    if (UtilValidate.isNotEmpty(productStoreList) && ! productStoreList.contains(productStore.getString("productStoreId"))) {
+                        continue; // pretty ugly... but had problems with the rare case where an invoice matches with several orders with more than one productStore
+                    }
+                    invoiceEditable.put("productStoreId", productStore.getString("productStoreId"));
+                    invoiceEditable.put("storeName", productStore.getString("storeName"));
+                } else {
+                    invoiceEditable.put("productStoreId", "_NA_");
+                    invoiceEditable.put("storeName", "_NA_");
+                }
+                listInvoiceEditable.add(invoiceEditable);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "BirtErrorRetrievingTurnOver", locale));
+        }
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        result.put("records", listInvoiceEditable);
+        return result;
+    }
+}
diff --git a/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtServices.java b/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtServices.java
new file mode 100644
index 0000000..7ba0305
--- /dev/null
+++ b/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtServices.java
@@ -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
diff --git a/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtUtil.java b/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtUtil.java
new file mode 100644
index 0000000..c5ffc77
--- /dev/null
+++ b/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtUtil.java
@@ -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
diff --git a/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/ReportDesignGenerator.java b/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/ReportDesignGenerator.java
new file mode 100644
index 0000000..57071f0
--- /dev/null
+++ b/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/ReportDesignGenerator.java
@@ -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);
+    }
+}
diff --git a/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtEngineServlet.java b/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtEngineServlet.java
index 1939839..9aafe40 100644
--- a/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtEngineServlet.java
+++ b/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtEngineServlet.java
@@ -23,6 +23,7 @@
 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 @@
 
     @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);
     }
diff --git a/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtViewerServlet.java b/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtViewerServlet.java
index dc733ec..88cc1d9 100644
--- a/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtViewerServlet.java
+++ b/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtViewerServlet.java
@@ -23,6 +23,7 @@
 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 @@
 
     @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);
diff --git a/plugins/birt/src/main/java/org/apache/ofbiz/birt/webapp/view/BirtViewHandler.java b/plugins/birt/src/main/java/org/apache/ofbiz/birt/webapp/view/BirtViewHandler.java
index a0ca302..62d367f 100644
--- a/plugins/birt/src/main/java/org/apache/ofbiz/birt/webapp/view/BirtViewHandler.java
+++ b/plugins/birt/src/main/java/org/apache/ofbiz/birt/webapp/view/BirtViewHandler.java
@@ -40,6 +40,7 @@
 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 @@
             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 @@
                 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);
diff --git a/plugins/birt/webapp/birt/WEB-INF/controller.xml b/plugins/birt/webapp/birt/WEB-INF/controller.xml
index 1093d36..9772ddb 100644
--- a/plugins/birt/webapp/birt/WEB-INF/controller.xml
+++ b/plugins/birt/webapp/birt/WEB-INF/controller.xml
@@ -28,6 +28,7 @@
     <description>BIRT Component Site Configuration File</description>

 

     <handler name="birt" type="view" class="org.apache.ofbiz.birt.webapp.view.BirtViewHandler"/>

+    <handler name="simplecontent" type="view" class="org.apache.ofbiz.content.view.SimpleContentViewHandler"/>

 

     <!-- Events to run on every request before security (chains exempt) -->

     <!--

@@ -80,6 +81,59 @@
         <response name="success" type="view" value="chartViewHandler"/>

     </request-map>

 

+    <!--Flexible Report Request-->

+    <request-map uri="UseFlexibleReport"><security https="true" auth="true" /><response name="success" type="view" value="UseFlexibleReport"/></request-map>

+    <request-map uri="ListFlexibleReport"><security https="true" auth="true" /><response name="success" type="view" value="ListFlexibleReport" /></request-map>

+    <request-map uri="SelectMasterFlexibleReport"><security https="true" auth="true" /><response name="success" type="view" value="CreateFlexibleReport" /></request-map>

+    <request-map uri="EditFlexibleReport"><security https="true" auth="true" /><response name="success" type="view" value="EditFlexibleReport" /></request-map>

+    <request-map uri="PreviewReportSearchForm"><security https="true" auth="true" /><response name="success" type="view" value="PreviewReportSearchForm" /></request-map>

+    <request-map uri="DisplayFlexibleReportSearchForm"><security https="true" auth="true" /><response name="success" type="view" value="DisplayFlexibleReportSearchForm" /></request-map>

+    <request-map uri="ViewBinaryDataResource"><security auth="true" https="true" /><response name="success" type="view" value="ViewBinaryDataResource" /></request-map>

+

+    <request-map uri="ExecuteFlexibleReport">

+        <security https="true" auth="true" />

+        <event type="groovy" path="component://birt/groovyScripts/report/PrepareBirtCall.groovy" />

+        <response name="success" type="view" value="ExecuteFlexibleReport" />

+        <response name="error" type="request" value="viewLast" />

+    </request-map>

+    <request-map uri="CreateFlexibleReport">

+        <security https="true" auth="true" />

+        <event type="service" invoke="createFlexibleReportFromMaster" />

+        <response name="error" type="view" value="CreateFlexibleReport" />

+        <response name="success" type="view" value="EditFlexibleReport" />

+    </request-map>

+    <request-map uri="EditFlexibleReportSearchForm">

+        <security https="true" auth="true" />

+        <event type="service" invoke="updateFlexibleReportSearchForm" />

+        <response name="error" type="view" value="DisplayFlexibleReportSearchForm" />

+        <response name="success" type="view" value="DisplayFlexibleReportSearchForm" />

+    </request-map>

+

+    <request-map uri="DeleteAllFlexibleReports">

+        <security https="true" auth="true" />

+        <event type="service" invoke="deleteAllFlexibleReports" />

+        <response name="success" type="view" value="main" />

+        <response name="error" type="view" value="main" />

+    </request-map>

+    <request-map uri="DeleteFlexibleReport">

+        <security https="true" auth="true" />

+        <event type="service" invoke="deleteFlexibleReport" />

+        <response name="success" type="view" value="ListFlexibleReport" />

+        <response name="error" type="view" value="ListFlexibleReport" />

+    </request-map>

+

+    <request-map uri="UpdateFlexibleReport">

+        <security https="true" auth="true" />

+        <event type="service" invoke="updateContent" />

+        <response name="success" type="view" value="ListFlexibleReport" />

+        <response name="error" type="view" value="ListFlexibleReport" />

+    </request-map>

+    <request-map uri="UploadRptDesign">

+        <security https="true" auth="true" />

+        <event type="service" invoke="uploadFlexibleReportRptDesign" />

+        <response name="success" type="view" value="EditFlexibleReport" />

+        <response name="error" type="view" value="EditFlexibleReport" />

+    </request-map>

     <!-- end of request mappings -->

 

     <!-- View Mappings -->

@@ -105,5 +159,14 @@
      -->

     <view-map name="ViewHandler" type="birt" page="component://birt/webapp/birt/report/example.rptdesign" content-type="application/pdf"/>

     <view-map name="chartViewHandler" type="birt" page="component://birt/webapp/birt/report/chart.rptdesign" content-type="application/pdf"/>

+    <view-map name="UseFlexibleReport" type="screen" page="component://birt/widget/birt/BirtScreens.xml#UseFlexibleReport"/>

+    <view-map name="EditFlexibleReportSearchForm" type="screen" page="component://birt/widget/birt/BirtScreens.xml#EditFlexibleReportSearchForm"/>

+    <view-map name="CreateFlexibleReport" type="screen" page="component://birt/widget/birt/BirtScreens.xml#CreateFlexibleReport"/>

+    <view-map name="DisplayFlexibleReportSearchForm" type="screen" page="component://birt/widget/birt/BirtScreens.xml#DisplayFlexibleReportSearchForm"/>

+    <view-map name="ListFlexibleReport" type="screen" page="component://birt/widget/birt/BirtScreens.xml#ListFlexibleReport"/>

+    <view-map name="EditFlexibleReport" type="screen" page="component://birt/widget/birt/BirtScreens.xml#EditFlexibleReport"/>

+    <view-map name="PreviewReportSearchForm" type="screen" page="component://birt/widget/birt/BirtScreens.xml#PreviewReportSearchForm"/>

+    <view-map name="ExecuteFlexibleReport" type="birt" />

+    <view-map name="ViewBinaryDataResource" page="" type="simplecontent"/>

     <!-- end of view mappings -->

 </site-conf>

diff --git a/plugins/birt/widget/birt/BirtForms.xml b/plugins/birt/widget/birt/BirtForms.xml
index 1cae7f8..7a3f48f 100644
--- a/plugins/birt/widget/birt/BirtForms.xml
+++ b/plugins/birt/widget/birt/BirtForms.xml
@@ -25,21 +25,121 @@
         <field name="sendFrom"><text/></field>
         <field name="sendTo"><text/></field>
         <field name="subject"><text/></field>
-        <field name="birtReportLocation" tooltip="Example is component://birt/webapp/birt/report/example.rptdesign" required-field="true"><text/></field>
         <field name="birtContentType">
             <drop-down>
-                <option key="text/html" description="text/html"/>
-                <option key="application/pdf" description="application/pdf"/>
-                <option key="application/postscript" description="application/postscript"/>
-                <option key="application/vnd.ms-excel" description="application/vnd.ms-excel"/>
-                <option key="application/vnd.ms-word" description="application/vnd.ms-word"/>
-                <option key="application/vnd.ms-powerpoint" description="application/vnd.ms-powerpoint"/>
-                <option key="application/vnd.oasis.opendocument.text" description="application/vnd.oasis.opendocument.text"/>
-                <option key="application/vnd.oasis.opendocument.spreadsheet" description="application/vnd.oasis.opendocument.spreadsheet"/>
-                <option key="application/vnd.oasis.opendocument.presentation" description="application/vnd.oasis.opendocument.presentation"/>
+                <entity-options entity-name="Enumeration" description="${enumCode}" key-field-name="description">
+                    <entity-constraint name="enumTypeId" value="FLEXIBLE_BIRT"/>
+                    <entity-order-by field-name="sequenceId"/>
+                </entity-options>
             </drop-down>
         </field>
         <field name="attachmentName" required-field="true"><text/></field>
-        <field name="sendButton" widget-style="smallSubmit"><submit button-type="button"/></field>
+        <field name="birtReportLocation" tooltip="Example is component://birt/webapp/birt/report/example.rptdesign" required-field="true"><text/></field>
+        <field name="sendButton"><submit/></field>
     </form>
+
+    <!-- Flexible Report Form -->
+    <form name="CreateFlexibleReport" type="single" target="CreateFlexibleReport">
+        <field name="contentId" title="${uiLabelMap.BirtSelectMasterFlexibleReport}" >
+            <drop-down>
+                <entity-options description="${description}" entity-name="Content" key-field-name="contentId">
+                    <entity-constraint name="contentTypeId" value="REPORT_MASTER" />
+                </entity-options>
+            </drop-down>
+        </field>
+        <field name="reportName" required-field="true"><text/></field>
+        <field name="description" required-field="true"><text /></field>
+        <field name="writeFilters"><check/></field>
+        <field name="sendButton"><submit/></field>
+    </form>
+    <form name="ListPublishFlexibleReport" type="single" target="DisplayFlexibleReportSearchForm">
+        <field name="contentId" title="${uiLabelMap.BirtSelectFlexibleReport}" >
+            <drop-down>
+                <entity-options description="[${contentName}] ${description}" entity-name="ContentAssocViewTo" key-field-name="contentId">
+                    <entity-constraint name="contentTypeId" value="FLEXIBLE_REPORT" />
+                    <entity-constraint name="statusId" value="CTNT_PUBLISHED"/>
+                </entity-options>
+            </drop-down>
+        </field>
+        <field name="sendButton"><submit /></field>
+    </form>
+
+    <form name="EditFlexibleReport" type="single" target="UpdateFlexibleReport" default-map-name="content">
+        <field name="contentId"><hidden/></field>
+        <field name="contentName" title="${uiLabelMap.FormFieldTitle_reportName}"><display/></field>
+        <field name="description"><text/></field>
+        <field name="statusId">
+            <drop-down>
+                <entity-options description="${description}" entity-name="StatusItem">
+                    <entity-constraint name="statusId" operator="in" value="CTNT_PUBLISHED,CTNT_IN_PROGRESS"/>
+                </entity-options>
+            </drop-down>
+        </field>
+        <field name="submit" title="${uiLabelMap.CommonSubmit}"><submit/></field>
+    </form>
+    <form name="UploadRptDesign" type="upload" target="UploadRptDesign">
+        <actions>
+            <entity-and entity-name="ContentAssoc" use-cache="true" list="contentAssocs">
+                <field-map field-name="contentId" from-field="content.contentId"/>
+            </entity-and>
+            <set field="contentAssoc" from-field="contentAssocs[0]" type="Object"/>
+            <entity-one entity-name="Content" value-field="contentRpt">
+                <field-map from-field="contentAssoc.contentIdTo" field-name="contentId"/>
+            </entity-one>
+        </actions>
+        <field name="contentId"><hidden value="${content.contentId}"/></field>
+        <field name="dataResourceIdRpt"><hidden value="${contentRpt.dataResourceId}"/></field>
+        <field name="downloadRptDesignLink" title=" " widget-style="buttontext">
+            <hyperlink also-hidden="false" description="${uiLabelMap.BirtDownloadRptDesign}" target="ViewBinaryDataResource" target-window="_blank">
+                <parameter param-name="dataResourceId" from-field="contentRpt.dataResourceId"/>
+            </hyperlink>
+        </field>
+        <field name="uploadRptDesign" title=" "><file/></field>
+        <field name="upload" title="${uiLabelMap.CommonUpload}" position="2"><submit/></field>
+    </form>
+
+    <form name="EditFlexibleReportSearchForm" type="single" target="EditFlexibleReportSearchForm">
+        <actions>
+            <set field="statusId" from-field="content.statusId"/>
+            <set field="reportContentId" from-field="content.contentId"/>
+            <entity-and entity-name="ContentAssoc" list="masterContent">
+                <field-map field-name="contentIdTo" from-field="contentId"/>
+                <field-map field-name="contentAssocTypeId" value="SUB_CONTENT"/>
+            </entity-and>
+            <service service-name="prepareFlexibleReportSearchFormToEdit" auto-field-map="true" result-map="displayFormMap"/>
+        </actions>
+        <field name="overrideFilters" title=" "><textarea cols="90" rows="20" default-value="${displayFormMap.textForm}"/></field>
+        <field name="reportContentId"><hidden/></field>
+        <field name="previewButton" title="${uiLabelMap.CommonSave}"><submit/></field>
+        <on-event-update-area event-type="submit" area-id="preview-column" area-target="PreviewReportSearchForm">
+            <parameter param-name="contentId" value="${contentId}"/>
+        </on-event-update-area>
+    </form>
+
+    <form name="ListFlexibleReport" type="list" target="" odd-row-style="alternate-row" list-name="contentTypeReport" header-row-style="header-row-2" default-table-style="basic-table hover-bar">
+        <row-actions>
+            <entity-one entity-name="Content" value-field="content" />
+            <set field="contentId" from-field="content.contentId"/>
+            <entity-and entity-name="ContentAssoc" use-cache="true" list="contentAssocs">
+                <field-map field-name="contentId"/>
+            </entity-and>
+            <set field="contentAssoc" from-field="contentAssocs[0]" type="Object"/>
+            <entity-one entity-name="Content" value-field="contentRpt">
+                <field-map from-field="contentAssoc.contentIdTo" field-name="contentId"/>
+            </entity-one>
+            <entity-and entity-name="ContentAssoc" use-cache="true" list="masterContentAssocs">
+                <field-map field-name="contentIdTo" from-field="contentId"/>
+            </entity-and>
+            <set field="masterContentAssoc" from-field="masterContentAssocs[0]" type="Object"/>
+            <entity-one entity-name="Content" value-field="masterContent">
+                <field-map from-field="masterContentAssoc.contentId" field-name="contentId"/>
+            </entity-one>
+        </row-actions>
+        <field name="contentName" sort-field="true"><display/></field>
+        <field name="masterContentName" sort-field="true" map-name="masterContent" entry-name="contentName"><display /></field>
+        <field name="statusId" sort-field="true"><display-entity entity-name="StatusItem" /></field>
+        <field name="description" sort-field="true"><display/></field>
+        <field name="manageLink"><include-menu name="ListFlexibleBirtAction" location="component://birt/widget/birt/BirtMenus.xml"/></field>
+  </form>
+
 </forms>
diff --git a/plugins/birt/widget/birt/BirtMasterForms.xml b/plugins/birt/widget/birt/BirtMasterForms.xml
new file mode 100644
index 0000000..a17277c
--- /dev/null
+++ b/plugins/birt/widget/birt/BirtMasterForms.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<forms xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://ofbiz.apache.org/Widget-Form"
+       xsi:schemaLocation="http://ofbiz.apache.org/Widget-Form http://ofbiz.apache.org/dtds/widget-form.xsd">
+
+    <!--This form present std field for the flexible birt engine, you need to heritate it for each domain
+        with an auto attribute or something like that to use cache system
+    -->
+    <form name="AbstractFlexibleReportSearchForm" type="single" target="ExecuteFlexibleReport">
+        <actions>
+            <entity-one entity-name="Content" value-field="content"/>
+            <entity-condition entity-name="ContentAttribute" list="contentAttrs">
+                <condition-list>
+                    <condition-expr field-name="contentId" from-field="content.contentId"/>
+                    <condition-list combine="or">
+                        <condition-expr field-name="attrName" value="Service"/>
+                        <condition-expr field-name="attrName" value="Entity"/>
+                    </condition-list>
+                </condition-list>
+            </entity-condition>
+            <set field="rptDesignFile" value="${groovy: org.apache.ofbiz.birt.flexible.BirtUtil.resolveRptDesignFilePathFromContent(delegator, content.contentId)}"/>
+        </actions>
+        <field name="birtContentType">
+            <drop-down>
+                <entity-options entity-name="Enumeration" description="${enumCode}" key-field-name="description">
+                    <entity-constraint name="enumTypeId" value="FLEXIBLE_BIRT"/>
+                    <entity-order-by field-name="sequenceId"/>
+                </entity-options>
+            </drop-down>
+        </field>
+        <field name="rptDesignFile"><hidden/></field>
+        <field name="birtOutputFileName"><hidden value="${content.contentName}"/></field>
+        <field name="modelElementName"><hidden value="${contentAttrs[0].attrValue}"/></field>
+        <field name="sendButton"><submit/></field>
+        <sort-order>
+            <last-field name="birtContentType"/>
+            <last-field name="sendButton"/>
+        </sort-order>
+    </form>
+
+    <form name="CTNT_MASTER_EXAMPLE" type="single" extends="AbstractFlexibleReportSearchForm">
+        <auto-fields-entity entity-name="Example" default-field-type="find"/>
+    </form>
+    <form name="CTNT_MASTER_TURNOVER" type="single" extends="AbstractFlexibleReportSearchForm">
+        <field name="fromDate"><date-time type="date"/></field>
+        <field name="thruDate"><date-time type="date"/></field>
+        <field name="productCategoryId"><lookup target-form-name="LookupProductCategory"/></field>
+        <field name="productStoreId"><lookup target-form-name="LookupProductStore"/></field>
+    </form>
+
+</forms>
\ No newline at end of file
diff --git a/plugins/birt/widget/birt/BirtMenus.xml b/plugins/birt/widget/birt/BirtMenus.xml
index aa68856..b249dba 100644
--- a/plugins/birt/widget/birt/BirtMenus.xml
+++ b/plugins/birt/widget/birt/BirtMenus.xml
@@ -22,6 +22,9 @@
        xmlns="http://ofbiz.apache.org/Widget-Menu" xsi:schemaLocation="http://ofbiz.apache.org/Widget-Menu http://ofbiz.apache.org/dtds/widget-menu.xsd">
 
     <menu name="BirtAppBar" title="${uiLabelMap.BirtApplication}" extends="CommonAppBarMenu" extends-resource="component://common/widget/CommonMenus.xml">
+        <menu-item name="FlexibleReport" title="${uiLabelMap.BirtFlexibleReport}">
+            <link target="ListFlexibleReport" />
+        </menu-item>
     </menu>
     <menu name="BirtTabBar" extends="CommonTabBarMenu" extends-resource="component://common/widget/CommonMenus.xml">
         <menu-item name="Report" title="${uiLabelMap.ExampleBirtReport}"><link target="Report"/></menu-item>
@@ -31,4 +34,57 @@
         <menu-item name="chartReport" title="${uiLabelMap.ExampleBirtChartReport}"><link target="chartReport"/></menu-item>
         <menu-item name="chartExport" title="${uiLabelMap.ExampleBirtChartViewHandler}"><link target="chartViewHandler" target-window="_BLANK"/></menu-item>
     </menu>
+    <menu name="FlexibleBirtTabBar" extends="CommonTabBarMenu" extends-resource="component://common/widget/CommonMenus.xml">
+        <menu-item name="ListFlexibleReport" title="${uiLabelMap.BirtManageReports}">
+            <condition>
+                <if-has-permission permission="BIRT_UPDATE"/>
+            </condition>
+            <link target="ListFlexibleReport"/>
+        </menu-item>
+        <menu-item name="UseFlexibleReport" title="${uiLabelMap.BirtGenericReport}"><link target="UseFlexibleReport"/></menu-item>
+        <!-- enable this onl for test
+        <menu-item name="deleteReports" title="${uiLabelMap.BirtDeleteFlexibeReports}">
+            <condition>
+                <if-has-permission permission="BIRT_DELETE"/>
+            </condition>
+            <link target="DeleteAllFlexibleReports" confirmation-message="${uiLabelMap.BirtConfirmDeleteFlexibleReports}" request-confirmation="true"/>
+        </menu-item>
+        -->
+    </menu>
+    <menu name="ListFlexibleBirtAction" extends="CommonInlineBarMenu" extends-resource="component://common/widget/CommonMenus.xml">
+        <menu-item name="publishLink" title="${uiLabelMap.CommonPublish}">
+            <condition>
+                <if-compare field="content.statusId" operator="not-equals" value="CTNT_PUBLISHED"/>
+            </condition>
+            <link target="UpdateFlexibleReport">
+                <parameter param-name="contentId" from-field="content.contentId"/>
+                <parameter param-name="statusId" value="CTNT_PUBLISHED"/>
+            </link>
+        </menu-item>
+        <menu-item name="updateLink" title="${uiLabelMap.CommonOpen}">
+            <condition>
+                <if-compare field="content.statusId" operator="not-equals" value="CTNT_IN_PROGRESS"/>
+            </condition>
+            <link target="UpdateFlexibleReport">
+                <parameter param-name="statusId" value="CTNT_IN_PROGRESS"/>
+                <parameter param-name="contentId" from-field="content.contentId"/>
+            </link>
+        </menu-item>
+        <menu-item name="editLink" title="${uiLabelMap.CommonEdit}">
+            <condition>
+                <if-compare field="content.statusId" operator="equals" value="CTNT_IN_PROGRESS"/>
+            </condition>
+            <link target="EditFlexibleReport">
+                <parameter param-name="contentId" from-field="content.contentId"/>
+            </link>
+        </menu-item>
+        <menu-item name="deleteLink" title="${uiLabelMap.CommonDelete}">
+            <condition>
+                <if-compare field="content.statusId" operator="equals" value="CTNT_IN_PROGRESS"/>
+            </condition>
+            <link target="DeleteFlexibleReport">
+                <parameter param-name="contentId" from-field="content.contentId"/>
+            </link>
+        </menu-item>
+    </menu>
 </menus>
diff --git a/plugins/birt/widget/birt/BirtScreens.xml b/plugins/birt/widget/birt/BirtScreens.xml
index 51c9074..00525ac 100644
--- a/plugins/birt/widget/birt/BirtScreens.xml
+++ b/plugins/birt/widget/birt/BirtScreens.xml
@@ -53,6 +53,8 @@
         <section>
             <actions>
                 <set field="headerItem" value="Birt"/>
+                <set field="subcomponentMenuName" from-field="subcomponentMenuName" default-value="BirtTabBar" />
+                <set field="subcomponentMenuLocation" from-field="subcomponentMenuLocation" default-value="component://birt/widget/birt/BirtMenus.xml" />
             </actions>
             <widgets>
                 <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
@@ -63,7 +65,7 @@
                                 <if-has-permission permission="ENTITY_MAINT"/>
                             </condition>
                             <widgets>
-                                <include-menu name="BirtTabBar" location="component://birt/widget/birt/BirtMenus.xml"/>
+                                <include-menu name="${subcomponentMenuName}" location="${subcomponentMenuLocation}"/>
                             </widgets>
                         </section>
                     </decorator-section>
@@ -86,6 +88,17 @@
             </widgets>
         </section>
     </screen>
+    <screen name="CommonBirtMinimalDecorator">
+        <section>
+            <actions>
+                <property-map resource="BirtUiLabels" map-name="uiLabelMap" global="true"/>
+                <property-map resource="CommonUiLabels" map-name="uiLabelMap" global="true"/>
+            </actions>
+            <widgets>
+                <decorator-section-include name="body"/>
+            </widgets>
+        </section>
+    </screen>
 
     <screen name="main">
         <section>
@@ -176,4 +189,229 @@
             </widgets>
         </section>
     </screen>
+
+    <!--=========================-->
+    <!--  Flexible Birt Screen   -->
+    <!--=========================-->
+    <screen name="CommonFlexibleBirtDecorator">
+        <section>
+            <actions>
+                <set field="subcomponentMenuLocation" value="component://birt/widget/birt/BirtMenus.xml"/>
+                <set field="subcomponentMenuName" value="FlexibleBirtTabBar"/>
+            </actions>
+            <widgets>
+                <decorator-screen name="CommonBirtDecorator" location="${parameters.mainDecoratorLocation}">
+                    <decorator-section name="body">
+                        <decorator-section-include name="body"/>
+                    </decorator-section>
+                </decorator-screen>
+
+            </widgets>
+        </section>
+    </screen>
+    <screen name="UseFlexibleReport">
+        <section>
+            <actions>
+               <set field="tabButtonItem" value="UseFlexibleReport" />
+            </actions>
+            <widgets>
+                <decorator-screen name="CommonFlexibleBirtDecorator">
+                    <decorator-section name="body">
+                        <section>
+                            <condition>
+                                <if-has-permission permission="BIRT" action="_VIEW"/>
+                            </condition>
+                            <widgets>
+                                <include-screen name="SelectFlexibleReport"/>
+                            </widgets>
+                            <fail-widgets>
+                                <label style="h3">${uiLabelMap.BirtPermissionError}</label>
+                            </fail-widgets>
+                        </section>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
+
+    <screen name="SelectFlexibleReport">
+        <section>
+            <condition>
+                <if-has-permission permission="BIRT" action="_VIEW"/>
+<!--                 <if-service-permission service-name="genericBirtPermission" main-action="VIEW"/> -->
+            </condition>
+            <actions>
+                <property-map resource="BirtUiLabels" map-name="uiLabelMap" global="true" />
+                <set field="contentEntityNameView" from-field="contentEntityNameView" default-value=""/>
+            </actions>
+            <widgets>
+                <screenlet title="${uiLabelMap.BirtSelectFlexibleReport}">
+                    <include-form location="component://birt/widget/birt/BirtForms.xml" name="ListPublishFlexibleReport" />
+                </screenlet>
+            </widgets>
+            <fail-widgets>
+                <label style="h3">${uiLabelMap.BirtPermissionError}</label>
+            </fail-widgets>
+        </section>
+    </screen>
+
+    <screen name="ListFlexibleReport">
+        <section>
+            <actions>
+                <set field="tabButtonItem" value="ListFlexibleReport" />
+                <set field="sortField" from-field="parameters.sortField" default-value="contentName"/>
+                <entity-and entity-name="Content" use-cache="true" list="contentTypeReport">
+                    <field-map field-name="contentTypeId" value="FLEXIBLE_REPORT"/>
+                    <order-by field-name="${sortField}"/>
+                </entity-and>
+                <service service-name="genericBirtPermission" result-map="permCreateResult">
+                    <field-map field-name="mainAction" value="CREATE"/>
+                </service>
+                <set field="hasCreatePermission" from-field="permCreateResult.hasPermission"/>
+    
+                <service service-name="genericBirtPermission" result-map="permDeleteResult">
+                    <field-map field-name="mainAction" value="DELETE"/>
+                </service>
+                <set field="hasDeletePermission" from-field="permDeleteResult.hasPermission"/>
+    
+                <service service-name="genericBirtPermission" result-map="permUpdateResult">
+                    <field-map field-name="mainAction" value="UPDATE"/>
+                </service>
+                <set field="hasUpdatePermission" from-field="permUpdateResult.hasPermission"/>
+            </actions>
+            <widgets>
+                <decorator-screen name="CommonFlexibleBirtDecorator">
+                    <decorator-section name="body">
+                        <section>
+                            <condition>
+                                <or>
+                                    <if-has-permission permission="BIRT" action="_DELETE"/>
+                                    <if-has-permission permission="BIRT" action="_CREATE"/>
+                                    <if-has-permission permission="BIRT" action="_UPDATE"/>
+                                </or>
+                            </condition>
+                            <widgets>
+                                <container style="button-bar">
+                                    <link target="SelectMasterFlexibleReport" text="${uiLabelMap.BirtFlexibleReportGeneration}" style="buttontext create"/>
+                                </container>
+                                <screenlet title="${uiLabelMap.BirtFlexibleReportManagement}">
+                                    <section>
+                                        <condition>
+                                            <not><if-empty field="contentTypeReport"/></not>
+                                        </condition>
+                                        <widgets>
+                                            <include-form location="component://birt/widget/birt/BirtForms.xml" name="ListFlexibleReport" />
+                                        </widgets>
+                                        <fail-widgets>
+                                            <label text="${uiLabelMap.BirtNoKnownFlexibleReport}"/>
+                                        </fail-widgets>
+                                    </section>
+                                </screenlet>
+                            </widgets>
+                            <fail-widgets>
+                                <label style="h3">${uiLabelMap.BirtPermissionError}</label>
+                            </fail-widgets>
+                        </section>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
+
+    <screen name="CreateFlexibleReport">
+        <section>
+            <actions>
+                <set field="tabButtonItem" value="SelectMasterFlexibleReport" />
+            </actions>
+            <widgets>
+                <decorator-screen name="CommonFlexibleBirtDecorator">
+                    <decorator-section name="body">
+                        <section>
+                            <condition>
+                                <if-has-permission permission="BIRT" action="_CREATE"/>
+                            </condition>
+                            <widgets>
+                                <screenlet title="${uiLabelMap.BirtSelectMasterFlexibleReport}">
+                                    <include-form location="component://birt/widget/birt/BirtForms.xml" name="CreateFlexibleReport" />
+                                </screenlet>
+                            </widgets>
+                            <fail-widgets>
+                                <label style="h3">${uiLabelMap.BirtPermissionError}</label>
+                            </fail-widgets>
+                        </section>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
+    <screen name="EditFlexibleReport">
+        <section>
+            <actions>
+                <set field="tabButtonItem" value="manageReport" />
+                <set field="contentId" from-field="parameters.reportContentId" default-value="${parameters.contentId}"/>
+                <entity-one entity-name="Content" value-field="content"/>
+            </actions>
+            <widgets>
+                <decorator-screen name="CommonFlexibleBirtDecorator">
+                    <decorator-section name="body">
+                        <section>
+                            <condition>
+                                <or>
+                                    <if-has-permission permission="BIRT" action="_CREATE"/>
+                                    <if-has-permission permission="BIRT" action="_UPDATE"/>
+                                </or>
+                            </condition>
+                            <widgets>
+                                <container id="edit-column" style="lefthalf">
+                                    <screenlet title="${uiLabelMap.BirtEditFlexibleReport}">
+                                        <label style="h2">${uiLabelMap.BirtFlexibleReportInformation}</label>
+                                        <include-form name="EditFlexibleReport" location="component://birt/widget/birt/BirtForms.xml"/>
+                                        <label style="h2">${uiLabelMap.BirtUploadRptDesign}</label>
+                                        <include-form name="UploadRptDesign" location="component://birt/widget/birt/BirtForms.xml" />
+                                        <label style="h2">${uiLabelMap.overrideFilters}</label>
+                                        <include-form name="EditFlexibleReportSearchForm" location="component://birt/widget/birt/BirtForms.xml"/>
+                                    </screenlet>
+                                </container>
+                                <container id="preview-column" style="righthalf">
+                                    <include-screen name="PreviewReportSearchForm"/>
+                                </container>
+                            </widgets>
+                            <fail-widgets>
+                                <label style="h3">${uiLabelMap.BirtPermissionError}</label>
+                            </fail-widgets>
+                        </section>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
+
+    <screen name="DisplayFlexibleReportSearchForm">
+        <section>
+            <widgets>
+                <decorator-screen name="CommonFlexibleBirtDecorator">
+                    <decorator-section name="body">
+                        <include-screen name="PreviewReportSearchForm"/>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
+
+    <screen name="PreviewReportSearchForm">
+        <section>
+            <actions>
+                <entity-one entity-name="Content" value-field="content" use-cache="true"/>
+            </actions>
+            <widgets>
+                <decorator-screen name="CommonBirtMinimalDecorator" location="${parameters.mainDecoratorLocation}">
+                    <decorator-section name="body">
+                        <screenlet title="${uiLabelMap.CommonPreview}" id="content-form-preview">
+                            <content content-id="${content.contentId}"/>
+                        </screenlet>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
 </screens>