blob: 55c02fa19ad08c8872adfc8cc8535a0ff0bd8c01 [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*
*
* This copyright notice shows up in the generated Java code
*
*/
package org.eclipse.osbp.xtext.reportdsl.jvmmodel
import com.google.inject.Inject
import com.ibm.icu.util.ULocale
import com.vaadin.data.Container.Filter
import com.vaadin.server.Sizeable.Unit
import com.vaadin.server.StreamResource
import com.vaadin.ui.AbstractComponent
import com.vaadin.ui.BrowserFrame
import com.vaadin.ui.Button
import com.vaadin.ui.HorizontalLayout
import java.io.ByteArrayOutputStream
import java.io.PrintStream
import java.util.ArrayList
import java.util.Locale
import java.util.UUID
import org.eclipse.birt.report.model.api.IDesignEngine
import org.eclipse.birt.report.model.api.OdaDataSetHandle
import org.eclipse.birt.report.model.api.StructureFactory
import org.eclipse.birt.report.model.api.command.ContentException
import org.eclipse.birt.report.model.api.command.CustomMsgException
import org.eclipse.birt.report.model.api.core.IModuleModel
import org.eclipse.birt.report.model.api.elements.structures.CachedMetaData
import org.eclipse.birt.report.model.api.elements.structures.ComputedColumn
import org.eclipse.birt.report.model.api.elements.structures.OdaResultSetColumn
import org.eclipse.birt.report.model.api.metadata.DimensionValue
import org.eclipse.birt.report.model.elements.interfaces.IDataSetModel
import org.eclipse.e4.core.di.extensions.EventUtils
import org.eclipse.e4.core.services.events.IEventBroker
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.osbp.dsl.entity.xtext.extensions.NamingExtensions
import org.eclipse.osbp.dsl.semantic.common.types.LPackage
import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute
import org.eclipse.osbp.eventbroker.EventBrokerMsg
import org.eclipse.osbp.ui.api.report.IReportProvider
import org.eclipse.osbp.utils.entityhelper.DataType
import org.eclipse.osbp.utils.vaadin.ViewLayoutManager
import org.eclipse.osbp.xtext.action.common.IToolbarAction
import org.eclipse.osbp.xtext.basic.generator.BasicDslGeneratorUtils
import org.eclipse.osbp.xtext.datamartdsl.DatamartCube
import org.eclipse.osbp.xtext.datamartdsl.DatamartDefinition
import org.eclipse.osbp.xtext.datamartdsl.DatamartEntity
import org.eclipse.osbp.xtext.datamartdsl.DatamartProperty
import org.eclipse.osbp.xtext.datamartdsl.DatamartRole
import org.eclipse.osbp.xtext.datamartdsl.DatamartTask
import org.eclipse.osbp.xtext.datamartdsl.jvmmodel.DatamartDSLJvmModelInferrer
import org.eclipse.osbp.xtext.i18n.DSLOutputConfigurationProvider
import org.eclipse.osbp.xtext.i18n.I18NKeyGenerator
import org.eclipse.osbp.xtext.i18n.I18NModelGenerator
import org.eclipse.osbp.xtext.reportdsl.AutoText
import org.eclipse.osbp.xtext.reportdsl.DatamartTable
import org.eclipse.osbp.xtext.reportdsl.DatamartTableProperty
import org.eclipse.osbp.xtext.reportdsl.Element
import org.eclipse.osbp.xtext.reportdsl.Grid
import org.eclipse.osbp.xtext.reportdsl.Image
import org.eclipse.osbp.xtext.reportdsl.Label
import org.eclipse.osbp.xtext.reportdsl.PageFooter
import org.eclipse.osbp.xtext.reportdsl.PageHeader
import org.eclipse.osbp.xtext.reportdsl.PageTemplate
import org.eclipse.osbp.xtext.reportdsl.Report
import org.eclipse.osbp.xtext.reportdsl.ReportDesignTemplate
import org.eclipse.osbp.xtext.reportdsl.ReportModel
import org.eclipse.osbp.xtext.reportdsl.ReportPackage
import org.eclipse.osbp.xtext.reportdsl.Style
import org.eclipse.osbp.xtext.reportdsl.SubSubTitle
import org.eclipse.osbp.xtext.reportdsl.SubTitle
import org.eclipse.osbp.xtext.reportdsl.Text
import org.eclipse.osbp.xtext.reportdsl.Title
import org.eclipse.osbp.xtext.reportdsl.common.BaseReport
import org.eclipse.osbp.xtext.reportdsl.common.BirtEngine
import org.eclipse.osbp.xtext.reportdsl.common.DataTypes
import org.eclipse.osbp.xtext.reportdsl.common.OdaConnProperties
import org.eclipse.osbp.xtext.reportdsl.common.attribute.Attribute
import org.eclipse.osbp.xtext.reportdsl.common.attribute.Width
import org.eclipse.osbp.xtext.reportdsl.common.item.BodyItem
import org.eclipse.osbp.xtext.reportdsl.common.item.ContainerItem
import org.eclipse.osbp.xtext.reportdsl.common.item.GridItem
import org.eclipse.osbp.xtext.reportdsl.common.item.ImageItem
import org.eclipse.osbp.xtext.reportdsl.common.item.PageFooterItem
import org.eclipse.osbp.xtext.reportdsl.common.item.PageHeaderItem
import org.eclipse.xtext.generator.IFileSystemAccess
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.xbase.compiler.GeneratorConfig
import org.eclipse.xtext.xbase.compiler.ImportManager
import org.osgi.service.event.Event
import org.osgi.service.event.EventHandler
class ReportModelGenerator extends I18NModelGenerator {
@Inject extension IQualifiedNameProvider
@Inject extension DatamartDSLJvmModelInferrer datamartInferrer
@Inject extension NamingExtensions
@Inject extension BasicDslGeneratorUtils
@Inject
@Extension
private DataType dtType;
static var designEngine = null
override void doGenerate(Resource input, IFileSystemAccess fsa) {
addTranslatables('''«BaseReport.CAPTION_I18NKEY_SAVE_PDF»,«BaseReport.CAPTION_I18NKEY_PRINT_PDF»''')
super.doGenerate(input, fsa)
}
def dispatch void internalDoGenerate(ReportModel orgModel, IFileSystemAccess fsa) {
designEngine = BirtEngine.createDesignEngine()
for (pkg:orgModel.pckg) {
for (report : pkg.reports) {
try {
generateReportFile(pkg, report, fsa)
}
catch (Exception e) {
e.printStackTrace
}
}
}
}
private def void generateReportFile(ReportPackage pckg, Report report, IFileSystemAccess fsa) {
if (report.design instanceof ReportDesignTemplate) {
generateReportRoleFile(pckg, report, null, fsa)
for(role : report.datamartRef.roles) {
generateReportRoleFile(pckg, report, role, fsa)
}
}
}
private def void generateReportRoleFile(ReportPackage pckg, Report report, DatamartRole role, IFileSystemAccess fsa) {
var workSet = new ReportGeneratorWorkSet()
workSet.generator = this
workSet.report = report
workSet.role = role
// --- generate full path name to the report design file to be generated ---
var template = report.design as ReportDesignTemplate
var pckgName = pckg.fullyQualifiedName.toString
var pckgNamePath = pckgName.replaceAll("\\.","/")
var filename = '''«report.name»«IF role!=null»«role.assignedRole.name»«ENDIF».rptdesign'''
var fullpath = '''«pckgNamePath»/«filename»'''
// --- get managing BIRT instances ---
var session = (designEngine as IDesignEngine).newSessionHandle(ULocale.forLocale(Locale.getDefault()))
// --- Create a new report design ---
workSet.design = session.createDesign()
// --- The element factory creates instances of the various BIRT elements ---
workSet.factory = workSet.design.getElementFactory()
// set the i18n property resources
workSet.design.setIncludeResource("i18n/I18N")
// set the requested media for this report
workSet.requestedMedia = report.media
// --- generate a master page ---
generateMasterPage(report.datamartRef, workSet, report.pageTemplate, template.header, template.footer)
// --- add the master datamart ---
// if (report.datamartRef != null) {
addDatamartSourceAndSet(report.datamartRef, workSet, null, null)
// }
var body = new BodyItem(workSet)
generateItems(report.datamartRef, workSet, body, template.detail.elements)
// --- generate an output stream to receive the BIRT generated report design ---
var baos = new ByteArrayOutputStream()
try {
workSet.design.getModule().prepareToSave();
workSet.design.getModule().getWriter().write(baos);
workSet.design.getModule().onSave();
}
catch (Exception e) {
baos = new ByteArrayOutputStream()
e.printStackTrace(new PrintStream(baos))
}
// --- generated output stream to the file ---
fsa.generateFile(fullpath, DSLOutputConfigurationProvider.DEFAULT_REPORT_OUTPUT, baos.toString())
}
// def SessionHandle newSessionHandle(IDesignEngine engine, ULocale locale) {
// return engine.newSessionHandle(locale)
// }
private def generateMasterPage(DatamartDefinition datamart, ReportGeneratorWorkSet workSet, PageTemplate pageTemplate, PageHeader pageHeader, PageFooter pageFooter) {
// Note: The report will fail to load in the BIRT designer unless you create a master page.
var header = pageHeader
var footer = pageFooter
if (header == null) {
header = pageTemplate.header
}
if (footer == null) {
footer = pageTemplate.footer
}
var masterPage = workSet.factory.newSimpleMasterPage(pageTemplate.name); //$NON-NLS-1$
masterPage.setPageType(pageTemplate.size.name().toLowerCase);
masterPage.setOrientation(pageTemplate.orientation.name().toLowerCase)
masterPage.topMargin.setValue(new DimensionValue(pageTemplate.topMarginValue, pageTemplate.topMarginUnit.name().toLowerCase))
masterPage.leftMargin.setValue(new DimensionValue(pageTemplate.leftMarginValue, pageTemplate.leftMarginUnit.name().toLowerCase))
masterPage.bottomMargin.setValue(new DimensionValue(pageTemplate.bottomMarginValue, pageTemplate.bottomMarginUnit.name().toLowerCase))
masterPage.rightMargin.setValue(new DimensionValue(pageTemplate.rightMarginValue, pageTemplate.rightMarginUnit.name().toLowerCase))
if (header != null) {
masterPage.setShowHeaderOnFirst(header.showOnFirst)
masterPage.headerHeight.setValue(new DimensionValue(header.heightValue, header.heightUnit.name().toLowerCase))
generateItems(datamart, workSet, new PageHeaderItem(workSet, masterPage), header.elements)
}
if (footer != null) {
masterPage.setShowFooterOnLast(footer.showOnLast)
masterPage.footerHeight.setValue(new DimensionValue(footer.heightValue, footer.heightUnit.name().toLowerCase))
generateItems(datamart, workSet, new PageFooterItem(workSet, masterPage), footer.elements)
}
workSet.design.getMasterPages().add(masterPage);
}
private def addDatamartSourceAndSet(DatamartDefinition datamart, ReportGeneratorWorkSet workSet, String alias, DatamartProperty[] hiddens) {
// --- generate the Data Source ---
var dataSourceName = Utilities.getDataSourceName(alias, datamart).toString
var odsourceh = workSet.factory.newOdaDataSource(dataSourceName, BaseReport.DATASOURCE_EXTENSION_ID);
odsourceh.getElement().setID(workSet.design.getModule().getNextID());
workSet.design.getModule().addElementID(odsourceh.getElement());
workSet.design.getModule().add(odsourceh.getElement(), IModuleModel.DATA_SOURCE_SLOT);
// --- generate the Data Set connected to the Data Source ---
var dataSetName = Utilities.getDataSetName(alias, datamart).toString
var odseth = workSet.factory.newOdaDataSet(dataSetName, BaseReport.DATASOURCE_EXTENSION_ID.concat(".dataSet"));
workSet.dataSets.put(dataSetName, odseth)
odseth.getElement().setID(workSet.design.getModule().getNextID());
odseth.setProperty(OdaConnProperties.DATAMART_BUNDLENAME, Utilities.getBundleName(datamart));
odseth.setProperty(OdaConnProperties.DATAMART_CLASSNAME, getDatamartClassName(alias, datamart));
odseth.setProperty(OdaConnProperties.DATAMART_DATASOURCE, odsourceh.getElement().getName());
odseth.setProperty(OdaConnProperties.DATAMART_DATASOURCENAME, dataSourceName);
odseth.setProperty(OdaConnProperties.DATAMART_DATASETNAME, dataSetName);
// --- add additional informations to the Data Set ---
switch (datamart.source) {
DatamartCube:
addDatamartCubeResultSet(workSet, odseth, dataSetName, datamart)
DatamartEntity:
addDatamartEntityResultSet(workSet, odseth, dataSetName, datamart)
DatamartTask:
System.err.println("DatamartTask ... todo")
}
workSet.design.getModule().addElementID(odseth.getElement());
workSet.design.getModule().add(odseth.getElement(), IModuleModel.DATA_SET_SLOT);
}
private def addDatamartCubeResultSet(ReportGeneratorWorkSet workSet, OdaDataSetHandle odseth, String dataSetName, DatamartDefinition datamart) {
System.err.println("DatamartCube ... todo")
var cube = datamart.source as DatamartCube;
var selectColumns = ""
var cmd = new CachedMetaData()
var sd = new ArrayList<OdaResultSetColumn>()
var cc = new ArrayList<ComputedColumn>()
// var position = 0
// // --- at first all navigations ---
// for (navigation : entity.navigations) {
// for (property : navigation.datamartEntity.properties) {
// if ((hiddens == null) || !hiddens.contains(property)) {
// position = position+1
// addDatamartProperty(sd, cc, property, position)
// }
// }
// }
// // --- at last the "pure" data properties ---
// for (property : entity.properties) {
// if ((hiddens == null) || !hiddens.contains(property)) {
// position = position+1
// addDatamartProperty(sd, cc, property, position)
// }
// }
// workSet.putResultSetColumns(dataSetName, sd)
// workSet.putComputedColumns(dataSetName, cc)
// for (cc1 : cc) {
// if (selectColumns.empty) {
// selectColumns = cc1.getName();
// }
// else {
// selectColumns = selectColumns+","+cc1.getName();
// }
// }
odseth.setProperty("queryText", ('''select «selectColumns» from «datamart.name»''').toString())
cmd.setProperty(IDataSetModel.RESULT_SET_PROP, sd)
odseth.setProperty(IDataSetModel.CACHED_METADATA_PROP, cmd)
odseth.getElement().setProperty(IDataSetModel.RESULT_SET_PROP, sd)
}
private def addAllDatamartProperties(ReportGeneratorWorkSet workSet, ArrayList<OdaResultSetColumn> sd, ArrayList<ComputedColumn> cc, EObject container) {
switch container {
DatamartEntity: {
// --- at first all navigations ---
for (navigation : container.navigations) {
navigation.eAllContents.forEach[element |
addAllDatamartProperties(workSet, sd, cc, element)
]
}
// --- if no explicit properties are set ---
if (container.properties.isEmpty) {
for (attribute : container.entityRef.allAttributes) {
if (!attribute.isId && !attribute.isUuid) {
if (datamartInferrer.isAuthorized(workSet.role, container.entityRef, attribute.name)) {
addDatamartProperty(workSet, sd, cc, attribute)
}
}
}
}
// --- at last the "pure" data properties ---
else {
for (property : container.properties) {
if (datamartInferrer.isAuthorized(workSet.role, container.entityRef, property.propertyRef.name)) {
addDatamartProperty(workSet, sd, cc, property)
}
}
}
}
}
}
private def addDatamartEntityResultSet(ReportGeneratorWorkSet workSet, OdaDataSetHandle odseth, String dataSetName, DatamartDefinition datamart) {
var selectColumns = ""
var cmd = new CachedMetaData()
var sd = new ArrayList<OdaResultSetColumn>()
var cc = new ArrayList<ComputedColumn>()
workSet.fPosition = 0
addAllDatamartProperties(workSet, sd, cc, datamart.source)
workSet.putResultSetColumns(dataSetName, sd)
workSet.putComputedColumns(dataSetName, cc)
for (cc1 : cc) {
if (selectColumns.empty) {
selectColumns = cc1.getName();
}
else {
selectColumns = selectColumns.concat(",").concat(cc1.getName());
}
}
odseth.setProperty("queryText", ('''select «selectColumns» from «datamart.name»''').toString())
cmd.setProperty(IDataSetModel.RESULT_SET_PROP, sd)
odseth.setProperty(IDataSetModel.CACHED_METADATA_PROP, cmd)
odseth.getElement().setProperty(IDataSetModel.RESULT_SET_PROP, sd)
}
private def addDatamartProperty(ReportGeneratorWorkSet workSet, ArrayList<OdaResultSetColumn> sd, ArrayList<ComputedColumn> cc, DatamartProperty property) {
addDatamartProperty(workSet, sd, cc, property.propertyRef)
}
private def addDatamartProperty(ReportGeneratorWorkSet workSet, ArrayList<OdaResultSetColumn> sd, ArrayList<ComputedColumn> cc, LEntityAttribute attribute) {
// --- general information about the column ---
var etype = dtType.getBasicType(attribute)
var dataType = DataTypes.typeFor(etype)
if (dataType == DataTypes.ANY) {
dataType = DataTypes.typeFor(attribute.type) // ??? warum ANY ???
}
// see also DatamartDSLJvmInferrer
var name = attribute.toColumnName.toLowerCase
// --- check for already found column ---
for (column : sd) {
if (column.columnName.equalsIgnoreCase(name)) {
return
}
}
// --- information needed to access via oda ---
var st = new OdaResultSetColumn()
st.setColumnName(name)
st.setProperty("name", name)
st.setNativeDataType(dataType.getNativeOdaDataTypeId())
st.setNativeName(name)
workSet.fPosition = workSet.fPosition+1
st.setPosition(workSet.fPosition)
st.setDataType(dataType.getNativeOdaDataTypeName())
sd.add(st)
// --- information needed to access via table ---
var cs1 = StructureFactory.createComputedColumn()
cs1.setName(name)
cs1.setDisplayName(name);
cs1.setExpression("dataSetRow[\"".concat(name).concat("\"]"))
cs1.setDataType(dataType.getNativeOdaDataTypeName())
cc.add(cs1)
}
private def getDatamartClassName(String alias, DatamartDefinition datamart) {
'''«(datamart.eContainer as LPackage).fullyQualifiedName».«datamart.name»Class'''
}
public def generateItems(DatamartDefinition datamart, ReportGeneratorWorkSet workSet, ContainerItem container, Element[] elements) {
if (elements != null) {
for (element : elements) {
try {
switch (element) {
Title:
container.addHeader(1, I18NKeyGenerator.key(element.text), element.text.replace("\"",""), element.style)
SubTitle:
container.addHeader(2, I18NKeyGenerator.key(element.text), element.text.replace("\"",""), element.style)
SubSubTitle:
container.addHeader(3, I18NKeyGenerator.key(element.text), element.text.replace("\"",""), element.style)
Label:
container.addLabel(I18NKeyGenerator.key(element.text), element.text.replace("\"",""), element.style)
Text:
container.addText (I18NKeyGenerator.key(element.text), element.text.replace("\"",""), element.style)
AutoText:
container.addAutoText (element.type.toString, element.style)
DatamartTableProperty:
container.addData (element, element.style)
Image:
addImage(
workSet, container, element, null
)
DatamartTable:
addDatamartTable(datamart,
workSet, container, element,
new Width("100%")
)
Grid:
addGrid(datamart,
workSet, container, element, null,
new Width("100%")
)
// TableDsl:
// addTable(
// workSet, container, element,
// new Width("100%")
// )
// ChartDsl:
// System.err.println("ChartDsl ... todo")
}
}
catch (ContentException ce) {
System.err.println('''«ce.class.simpleName»: «ce.localizedMessage»''')
}
catch (Exception e) {
e.printStackTrace
}
}
}
}
private def addDatamartTable(DatamartDefinition datamart, ReportGeneratorWorkSet workSet, ContainerItem container, DatamartTable datamartTable, Attribute... attributes) {
// var datamart = datamartTable.datamartRef
var hiddens = new ArrayList<DatamartProperty>
for (columnFormatter : datamartTable.detail.columnFormatters) {
// if (columnFormatter.hiddens) {
// var column = columnFormatter.column
// switch (column) {
// TableProperty: hiddens.add(column.valueRef)
// }
// }
}
var alias = datamartTable.name
var dataSetName = Utilities.getDataSetName(alias, datamart).toString
var dataSet = workSet.dataSets.get(dataSetName)
if (dataSet == null) {
addDatamartSourceAndSet(datamart, workSet, alias, hiddens)
dataSet = workSet.dataSets.get(dataSetName)
}
container.addTable(dataSet, datamartTable, workSet.getComputedColumns(dataSetName), datamartTable.groups, datamartTable.detail.style, datamartTable.detail.columnFormatters, datamartTable.style, attributes)
}
// def addTable(ReportGeneratorWorkSet workSet, Container container, TableDsl tableDsl, Attribute... attributes) {
// var datamart = tableDsl.tableRef.source.datamartRef
// var hiddens = null as DatamartProperty[]//tableItem.hiddens
// var alias = tableDsl.name
// var dataSetName = Utilities.getDataSetName(alias, datamart).toString
// var dataSet = workSet.dataSets.get(dataSetName)
// if (dataSet == null) {
// addDatamart(workSet, alias, datamart, hiddens)
// dataSet = workSet.dataSets.get(dataSetName)
// }
// var propertyLookups = new PropertyLookups
// var tableInferrer = new TableDSLJvmModelInferrer
// tableInferrer.extractPropertyLookups(tableDsl.tableRef, propertyLookups)
// container.addTable(dataSet, workSet.getComputedColumns(dataSetName), propertyLookups, attributes)
// }
private def addImage(ReportGeneratorWorkSet workSet, ContainerItem container, Image imageData, Style style, Attribute... attributes) {
var image = new ImageItem(
workSet,
null,
imageData.size.literal,
imageData.scale,
imageData.sourceType.literal,
imageData.filename
)
container.add(image, style, attributes)
}
private def addGrid(DatamartDefinition datamart, ReportGeneratorWorkSet workSet, ContainerItem container, Grid grid, Style style, Attribute... attributes) {
var rowCount = grid.rows.length
var columnCount = 0
for (row : grid.rows) {
columnCount = Math.max(columnCount, row.cells.length)
}
var gridItem = new GridItem(
workSet,
columnCount,
rowCount
);
var rowNo = 0
for (row : grid.rows) {
var columnNo = 0
for (cell : row.cells) {
generateItems(datamart, workSet, gridItem.getCell(columnNo, rowNo).setColumnSpan(cell.columnspan), cell.elements)
columnNo = columnNo+1
}
if (row.style != null) {
gridItem.applyStyle(rowNo, row.style)
}
rowNo = rowNo+1
}
container.add(gridItem, style, attributes)
}
override createAppendable(EObject context, ImportManager importManager, GeneratorConfig config) {
// required to initialize the needed builder to avoid deprecated methods
builder = context.eResource
// ---------
addImportFor(importManager, _typeReferenceBuilder
, ReportGeneratorWorkSet
, HorizontalLayout
, ViewLayoutManager
, BrowserFrame
, StreamResource
, Unit
, Button
, com.vaadin.ui.Label
, IEventBroker
, EventHandler
, Event
, EventUtils
, EventBrokerMsg
, CustomMsgException
, IReportProvider.Rendering
, AbstractComponent
, UUID
, Filter
, IToolbarAction)
super.createAppendable(context, importManager, config)
}
}