/******************************************************************************* | |
* 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.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.EntityQuery; | |
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 org.w3c.dom.Document; | |
import org.xml.sax.SAXException; | |
import com.ibm.icu.util.ULocale; | |
/** | |
* 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"; | |
/** | |
* Instantiate 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 = EntityQuery.use(delegator).from("ContentAttribute").where(entityCondition).queryFirst(); | |
} 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 = EntityQuery.use(delegator).from("Content").where("contentId", reportContentId).queryOne(); | |
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 = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne(); | |
String customMethodId = content.getString("customMethodId"); | |
if (UtilValidate.isEmpty(customMethodId)) customMethodId = "CM_FB_PERFORM_FIND"; | |
GenericValue customMethod = EntityQuery.use(delegator).from("CustomMethod").where("customMethodId", customMethodId).cache().queryOne(); | |
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 = EntityQuery.use(delegator).from("Content").where("contentId", masterContentId).cache().queryOne(); | |
String customMethodId = masterContent.getString("customMethodId"); | |
if (UtilValidate.isEmpty(customMethodId)) { | |
throw new GeneralException("The master content " + masterContentId + " haven't a customMethod"); | |
} | |
GenericValue customMethod = EntityQuery.use(delegator).from("CustomMethod").where("customMethodId", customMethodId).cache().queryOne(); | |
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 = EntityQuery.use(delegator).from("Content").where("contentId", reportContentId).cache().queryOne(); | |
String dataResourceId = content.getString("dataResourceId"); | |
GenericValue electronicText = EntityQuery.use(delegator).from("ElectronicText").where("dataResourceId", dataResourceId).cache().queryOne(); | |
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, "$", "$"); | |
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 = EntityQuery.use(delegator).from("Content").where(entityConditionContent).select("contentId").queryList(); | |
} 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 = EntityQuery.use(delegator).from("ContentAssoc").where("contentId", contentId).select("contentIdTo").queryList(); | |
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 = EntityQuery.use(delegator).from("ContentDataResourceView").where(ecl).select("drObjectInfo").queryList(); | |
} 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 = EntityQuery.use(delegator).from("DataResource").where("dataResourceId", dataResourceId).queryOne(); | |
} 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; | |
} | |
} |