blob: 9303462ccd087a27c0e5dc1059f10634d9504b9d [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 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*
*
* This copyright notice shows up in the generated Java code
*
*/
package org.eclipse.osbp.xtext.chart.jvmmodel
import com.ejt.vaadin.sizereporter.ComponentResizeListener
import com.ejt.vaadin.sizereporter.SizeReporter
import com.vaadin.server.StreamResource
import com.vaadin.shared.ui.JavaScriptComponentState
import com.vaadin.ui.AbstractJavaScriptComponent
import com.vaadin.ui.Component
import com.vaadin.ui.VerticalLayout
import elemental.json.JsonException
import java.util.ArrayList
import java.util.HashMap
import java.util.HashSet
import java.util.List
import java.util.Locale
import java.util.Set
import javax.annotation.PostConstruct
import javax.annotation.PreDestroy
import javax.inject.Inject
import org.dussan.vaadin.dcharts.DCharts
import org.eclipse.e4.core.contexts.IEclipseContext
import org.eclipse.e4.ui.di.Focus
import org.eclipse.e4.ui.model.application.MApplication
import org.eclipse.e4.ui.workbench.IPresentationEngine
import org.eclipse.emf.common.notify.Adapter
import org.eclipse.osbp.dsl.semantic.common.types.LAttribute
import org.eclipse.osbp.dsl.semantic.entity.LEntity
import org.eclipse.osbp.osgi.hybrid.api.AbstractHybridVaaclipseView
import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent
import org.eclipse.osbp.runtime.common.event.IEventDispatcher
import org.eclipse.osbp.ui.api.datamart.DatamartFilter
import org.eclipse.osbp.ui.api.datamart.IDatamartFilterGenerator
import org.eclipse.osbp.ui.api.e4.IE4Focusable
import org.eclipse.osbp.ui.api.layout.IViewLayoutManager
import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService
import org.eclipse.osbp.ui.api.themes.EnumCssClass
import org.eclipse.osbp.ui.api.themes.IThemeResourceService
import org.eclipse.osbp.ui.api.user.IUser
import org.eclipse.osbp.xtext.action.ActionPackage
import org.eclipse.osbp.xtext.chart.Chart
import org.eclipse.osbp.xtext.chart.ChartAxis
import org.eclipse.osbp.xtext.chart.ChartBar
import org.eclipse.osbp.xtext.chart.ChartBubble
import org.eclipse.osbp.xtext.chart.ChartDatamart
import org.eclipse.osbp.xtext.chart.ChartDonut
import org.eclipse.osbp.xtext.chart.ChartGauge
import org.eclipse.osbp.xtext.chart.ChartHighlighter
import org.eclipse.osbp.xtext.chart.ChartLegend
import org.eclipse.osbp.xtext.chart.ChartLine
import org.eclipse.osbp.xtext.chart.ChartNumberInterval
import org.eclipse.osbp.xtext.chart.ChartPackage
import org.eclipse.osbp.xtext.chart.ChartPie
import org.eclipse.osbp.xtext.chart.ChartSegmentColor
import org.eclipse.osbp.xtext.chart.ChartTree
import org.eclipse.osbp.xtext.cubedsl.CubeLevel
import org.eclipse.osbp.xtext.datamart.common.olap.DerivedCellSet
import org.eclipse.osbp.xtext.datamartdsl.DatamartAttribute
import org.eclipse.osbp.xtext.datamartdsl.DatamartCube
import org.eclipse.osbp.xtext.datamartdsl.DatamartCubeAxis
import org.eclipse.osbp.xtext.datamartdsl.DatamartDerivedMeasure
import org.eclipse.osbp.xtext.datamartdsl.DatamartEntity
import org.eclipse.osbp.xtext.datamartdsl.DatamartMeasure
import org.eclipse.osbp.xtext.datamartdsl.DatamartMember
import org.eclipse.osbp.xtext.datamartdsl.DatamartOwner
import org.eclipse.osbp.xtext.datamartdsl.DatamartPackage
import org.eclipse.osbp.xtext.datamartdsl.ValueScaleEnum
import org.eclipse.osbp.xtext.datamartdsl.jvmmodel.DatamartDSLJvmModelInferrer
import org.eclipse.osbp.xtext.table.common.PropertyLookup
import org.eclipse.xtext.common.types.JvmAnnotationReference
import org.eclipse.xtext.common.types.JvmConstructor
import org.eclipse.xtext.common.types.JvmDeclaredType
import org.eclipse.xtext.common.types.JvmField
import org.eclipse.xtext.common.types.JvmOperation
import org.eclipse.xtext.common.types.JvmStringAnnotationValue
import org.eclipse.xtext.common.types.JvmVisibility
import org.eclipse.xtext.common.types.TypesFactory
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.osgi.service.event.EventHandler
import org.slf4j.Logger
import com.vaadin.annotations.JavaScript
import java.util.stream.Collectors
import org.eclipse.osbp.xtext.chart.CanvasFontFamilyEnum
/**
* <p>
* This inferrer infers models of extension .chart and generates code to be used by a e4 application as view. Underlying components
* are from the vaadin component repository and especially the vaadin addon dChart.
* </p>
*
* @author Joerg Riegel
*/
/**
* <p>Infers a JVM model from the source model.</p>
*
* <p>The JVM model should contain all elements that would appear in the Java code
* which is generated from the source model. Other models link against the JVM model rather than the source model.</p>
*/
class ChartDSLJvmModelInferrer extends AbstractModelInferrer {
@Inject extension JvmTypesBuilder
@Inject extension IQualifiedNameProvider
@Inject extension DatamartDSLJvmModelInferrer datamartInferrer
@Inject extension D3JsJavaUtil
@Inject private TypesFactory typesFactory
/**
* <p>infer method dispatches the necessary routines to build fields, setter, getter, constructors and methods of the generated code.</p>
*
*/
def dispatch void infer(ChartPackage pckg, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
for (chart:pckg.charts) {
var cls = chart.toClass(pckg.fullyQualifiedName+"."+chart.name+"Chart")
cls.superTypes.add(_typeReferenceBuilder.typeRef(AbstractHybridVaaclipseView))
cls.superTypes.add(_typeReferenceBuilder.typeRef(IUser.UserLocaleListener))
cls.superTypes.add(_typeReferenceBuilder.typeRef(IDatamartFilterGenerator.FilterChangeListener))
cls.superTypes.add(_typeReferenceBuilder.typeRef(IEventDispatcher.Receiver))
cls.superTypes.add(_typeReferenceBuilder.typeRef(IE4Focusable))
acceptor.accept(cls,
[
it.fileHeader = pckg.documentation
it.toFields(chart)
it.toConstructor(chart)
it.toGetterSetter(chart)
it.toOperations(chart)
])
if ((chart.charttype instanceof ChartTree)) {
chart.createJsJavaComponent(acceptor)
}
}
}
/**
* <p>build the constructors to be used by an e4 application.</p>
*
*/
def void toConstructor(JvmDeclaredType type, Chart chart) {
type.members += chart.toConstructor([
annotations += _annotationTypesBuilder.annotationRef(Inject)
parameters += chart.toParameter("parent", _typeReferenceBuilder.typeRef(VerticalLayout))
parameters += chart.toParameter("context", _typeReferenceBuilder.typeRef(IEclipseContext))
parameters += chart.toParameter("app", _typeReferenceBuilder.typeRef(MApplication))
body = [ append(
'''
super(parent,context,app);''')]
])
}
/**
* <p>build the class variables.</p>
*
*/
def void toFields(JvmDeclaredType type, Chart chart) {
var JvmField field = null
// create logger
field = chart.toField("log", _typeReferenceBuilder.typeRef(Logger))[setInitializer([append('''org.slf4j.LoggerFactory.getLogger("charts")''')])]
field.static = true
field.visibility = JvmVisibility::PRIVATE
type.members += field
field = chart.toField("user", _typeReferenceBuilder.typeRef(IUser)) [annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = chart.toField("eclipseContext", _typeReferenceBuilder.typeRef(IEclipseContext)) [annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = chart.toField("coordinateSystem", _typeReferenceBuilder.typeRef(ArrayList, _typeReferenceBuilder.typeRef(Integer)))
type.members += field
field = chart.toField("filterGenerator", _typeReferenceBuilder.typeRef(IDatamartFilterGenerator))
type.members += field
field = chart.toField("layoutManager", _typeReferenceBuilder.typeRef(IViewLayoutManager))
type.members += field
// the package name of the referenced datamart
if (getSourceDataMartRefName(chart) !== null) {
var packageName = (chart.source.datamartRef.eContainer as DatamartPackage).fullyQualifiedName.toString
field = chart.toField("datamartInstance", _typeReferenceBuilder.typeRef('''«packageName».«chart.source.datamartRef.name.toString»Datamart'''))
type.members += field
}
field = chart.toField("dataComponent", _typeReferenceBuilder.typeRef(Component))
type.members += field
field = chart.toField("attributeLookupMap", _typeReferenceBuilder.typeRef(HashMap, _typeReferenceBuilder.typeRef(String), _typeReferenceBuilder.typeRef(PropertyLookup)))
type.members += field
field = chart.toField("charts", _typeReferenceBuilder.typeRef(ArrayList, _typeReferenceBuilder.typeRef(DCharts)))
type.members += field
field = chart.toField("refreshView", _typeReferenceBuilder.typeRef(EventHandler))
type.members += field
field = chart.toField("dslMetadataService", _typeReferenceBuilder.typeRef(IDSLMetadataService)) [annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = chart.toField("eventDispatcher", _typeReferenceBuilder.typeRef(IEventDispatcher))[annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = chart.toField("renderingEngine", _typeReferenceBuilder.typeRef(IPresentationEngine))[annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = chart.toField("themeResourceService", _typeReferenceBuilder.typeRef(IThemeResourceService))[annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
if (chart.toolbar !== null && chart.toolbar.eContainer !== null) {
var packageName = (chart.toolbar.eContainer as ActionPackage).fullyQualifiedName.toString
field = chart.toField("toolbarUUID", _typeReferenceBuilder.typeRef(String))
type.members += field
field = chart.toField("toolbarClass", _typeReferenceBuilder.typeRef('''«packageName».«chart.toolbar.name.toString.toFirstUpper»Toolbar'''))
type.members += field
}
field = chart.toField("panelWidth", _typeReferenceBuilder.typeRef(int))
type.members += field
field = chart.toField("panelHeight", _typeReferenceBuilder.typeRef(int))
type.members += field
field = chart.toField("splitAdapter", _typeReferenceBuilder.typeRef(Adapter.Internal))
type.members += field
field = chart.toField("resizeListener", _typeReferenceBuilder.typeRef(ComponentResizeListener))
type.members += field
field = chart.toField("sizeReporter", _typeReferenceBuilder.typeRef(SizeReporter));
type.members += field
}
/**
* <p>build the getters and setters from class variables.</p>
*
*/
def void toGetterSetter(JvmDeclaredType type, Chart chart) {
var JvmOperation operation = null
operation = chart.toGetter("coordinateSystem", _typeReferenceBuilder.typeRef(ArrayList, _typeReferenceBuilder.typeRef(Integer)))
operation.visibility = JvmVisibility::PUBLIC
type.members += operation
}
/**
* <p>build the methods.</p>
*
*/
def void toOperations(JvmDeclaredType type, Chart chart) {
// activate
type.members += chart.toMethod("activate", _typeReferenceBuilder.typeRef(Void::TYPE),
[
annotations += _annotationTypesBuilder.annotationRef(PostConstruct)
body = [append(
'''
super.initView();
user.addUserLocaleListener(this);
filterGenerator.addFilterChangeListener(this);
// to resize the chart according to split positions of partsashcontainer - setContainerData is tracked
((EObject)getPart()).eAdapters().add(splitAdapter);
sizeReporter.addResizeListener(resizeListener);
eventDispatcher.addEventReceiver(this);''')]
])
// deactivate
type.members += chart.toMethod("deactivate", _typeReferenceBuilder.typeRef(Void::TYPE),
[
annotations += _annotationTypesBuilder.annotationRef(PreDestroy)
body = [append(
'''
user.removeUserLocaleListener(this);
filterGenerator.removeFilterChangeListener(this);
((EObject)getPart()).eAdapters().remove(splitAdapter);
sizeReporter.removeResizeListener(resizeListener);
eventDispatcher.removeEventReceiver(this);
super.destroyView();''')]
])
// create view
type.members += chart.toMethod("createView", _typeReferenceBuilder.typeRef(Void::TYPE), [
parameters += chart.toParameter("parent", _typeReferenceBuilder.typeRef(VerticalLayout))
body = [ append('''«chart.createView»''')]
])
// create components
type.members += chart.toMethod("createComponents", _typeReferenceBuilder.typeRef(Void::TYPE), [
body = [ append('''«chart.createComponents»''')]
])
// create tab
type.members += chart.toMethod("createTabSheet", _typeReferenceBuilder.typeRef(Component), [
parameters += chart.toParameter("cellSet", _typeReferenceBuilder.typeRef(DerivedCellSet))
parameters += chart.toParameter("axisNo", _typeReferenceBuilder.typeRef(Integer))
body = [ append('''«chart.createTabSheet»''')]
])
// create chart
if (!((chart.charttype instanceof ChartTree))) {
type.members += chart.toMethod("createChart", _typeReferenceBuilder.typeRef(Component), [
parameters += chart.toParameter("cellSet", _typeReferenceBuilder.typeRef(DerivedCellSet))
body = [ append('''«chart.createChart»''')]
])
}
// create D3 chart
if ((chart.charttype instanceof ChartTree)) {
type.members += chart.toMethod("createD3Chart", _typeReferenceBuilder.typeRef(Component), [
exceptions += _typeReferenceBuilder.typeRef(JsonException)
parameters += chart.toParameter("cxCellSet", _typeReferenceBuilder.typeRef(DerivedCellSet))
body = [ append('''«chart.createD3Chart»''')]
])
}
// focus
type.members += chart.toMethod("setFocus", _typeReferenceBuilder.typeRef(Void::TYPE),
[
annotations += _annotationTypesBuilder.annotationRef(Focus)
body = [append(
'''
Component parent = getParent();
while(!(parent instanceof Panel) && parent != null) {
parent = parent.getParent();
}
if(parent != null) {
((Panel)parent).focus();
}''')]
])
// locale notification
type.members += chart.toMethod("localeChanged", _typeReferenceBuilder.typeRef(Void::TYPE), [
visibility = JvmVisibility.PUBLIC
annotations += _annotationTypesBuilder.annotationRef(Override)
parameters += chart.toParameter("locale", _typeReferenceBuilder.typeRef(Locale))
body = [append('''«chart.localeChanged»''')]
])
// filter notification
type.members += chart.toMethod("filterChanged", _typeReferenceBuilder.typeRef(Void::TYPE),
[
parameters += chart.toParameter("changedFilter", _typeReferenceBuilder.typeRef(DatamartFilter))
visibility = JvmVisibility.PUBLIC
annotations += _annotationTypesBuilder.annotationRef(Override)
body = [append('''renderData();''')]
])
// event notification
type.members += chart.toMethod("receiveEvent", _typeReferenceBuilder.typeRef(Void::TYPE),
[
visibility = JvmVisibility.PUBLIC
annotations += _annotationTypesBuilder.annotationRef(Override)
parameters += chart.toParameter("event", _typeReferenceBuilder.typeRef(EventDispatcherEvent))
body = [append('''«chart.receiveEvent»''')]
])
// getChartResource
type.members += chart.toMethod("getChartResource", _typeReferenceBuilder.typeRef(StreamResource),
[
visibility = JvmVisibility.PRIVATE
parameters += chart.toParameter("chart", _typeReferenceBuilder.typeRef(DCharts))
parameters += chart.toParameter("layoutManager", _typeReferenceBuilder.typeRef(IViewLayoutManager))
body = [append('''«chart.chartResource»''')]
])
}
def String getSourceDataMartRefName(Chart chart) {
if (chart.source !== null && chart.source.datamartRef !== null && chart.source.datamartRef.name !== null) {
return chart.source.datamartRef.name.toString
}
else {
return null;
}
}
/**
* <p>build the main method to be called from e4.</p>
*
*/
def String createView(Chart chart) {
var body =
'''
eclipseContext.set(IE4Focusable.class, this);
charts = new ArrayList<DCharts>();
coordinateSystem = new ArrayList<Integer>();
parent.setPrimaryStyleName("osbp"); // <== is THIS necessary any more???
parent.addStyleName("«EnumCssClass.VIEW.styleName»");
parent.addStyleName("«EnumCssClass.CHART_VIEW.styleName»");
parent.setSizeFull();
layoutManager = new ViewLayoutManager();
layoutManager.init(parent);
splitAdapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification notification) {
if (notification.getEventType()==Notification.SET &&
notification.getFeatureID(UIElementImpl.class) == UiPackageImpl.UI_ELEMENT__CONTAINER_DATA)
{
log.debug("render due to split position changed");
renderData();
}
}
};
sizeReporter = new SizeReporter(layoutManager.getDataArea());
resizeListener = new ComponentResizeListener() {
@Override
public void sizeChanged(ComponentResizeEvent event) {
boolean changed = false;
if (panelWidth != event.getWidth()) {
changed = true;
panelWidth = event.getWidth();
}
if (panelHeight != event.getHeight()) {
changed = true;
panelHeight = event.getHeight();
}
if (changed) {
log.debug("Panel size changed : " + event.getWidth() + " x " + event.getHeight());
renderData();
}
}
};
datamartInstance = new «getSourceDataMartRefName(chart)»Datamart();
datamartInstance.setUser(user);
filterGenerator = new DatamartFilterGenerator(datamartInstance, eclipseContext, «chart.source.datamartRef.showCaption.booleanValue», «Integer.max(10,chart.source.datamartRef.numMultiRows)»);
filterGenerator.createUIFilters(layoutManager);
attributeLookupMap = new HashMap<String,PropertyLookup>();
'''
if (chart.toolbar !== null) {
body = '''
«body»
toolbarUUID = UUID.randomUUID().toString();
toolbarClass = new «chart.toolbar.name.toString.toFirstUpper»Toolbar();
toolbarClass.createToolbar(eclipseContext, renderingEngine, themeResourceService, toolbarUUID);'''
}
body = '''
«body»
refreshView = «chart.refreshView»
'''
return body
}
/**
* <p>create a handler for external triggered refresh requests.</p>
*
*/
def String refreshView(Chart chart) {
var body = ""
body = '''
«body»
new EventHandler() {
@Override
public void handleEvent(Event event) {
renderData();
}
};
'''
return body
}
/**
* <p>build the data components.</p>
*
*/
def String createComponents(Chart chart) {
var body = ""
if (chart.source !== null) {
var isCube = ((chart.source as ChartDatamart).datamartRef.source instanceof DatamartCube)
body = '''
«body»// get the results
if (panelWidth == 0 && panelHeight == 0) {
return;
}
final DerivedCellSet cellSet = datamartInstance.getResults(«IF !isCube»false, getTaskOperativeDtoClass(), getTaskInitialOperativeDtos()«ENDIF»);
getCoordinateSystem().clear();
charts.clear();
if (cellSet == null) {
promptSecurityMessage(dslMetadataService.translate(user.getLocale().toLanguageTag(), "securityMessage"), layoutManager.getDataArea());
return;
} else {
layoutManager.getDataArea().removeAllComponents();
}
// generate a new result component
if (cellSet != null) {
// create a multidimensional coordinate system against the cellSet
for (int axis = 0; axis < cellSet.getAxes().size(); axis++) {
getCoordinateSystem().add(0);
}
// remove any previous component
if (dataComponent != null) {
layoutManager.getDataArea().removeComponent(dataComponent);
dataComponent = null;
}
if (cellSet.getAxes().size() < 2) {
log.error("at least 2 axes from referenced datamart «chart.source.datamartRef.name» are needed to render «chart.name»");
} else {
dataComponent = createTabSheet(cellSet, cellSet.getAxes().size());
if(dataComponent != null) {
dataComponent.setSizeFull();
dataComponent.setId("dataComponent");
dataComponent.addStyleName("«EnumCssClass.DATA_COMPONENT.styleName»");
layoutManager.getDataArea().addComponent(dataComponent);
layoutManager.getDataArea().setExpandRatio(dataComponent, 1);
}
}
getParent().markAsDirtyRecursive();
}
else {
log.error("referenced datamart «chart.source.datamartRef.name» generates no results");
}
'''
} else {
body = '''
«body»
// generate a new result component
try {
// remove any previous component
if (dataComponent != null) {
layoutManager.getDataArea().removeComponent(dataComponent);
dataComponent = null;
}
dataComponent = createTabSheet(null, 2);
dataComponent.setSizeFull();
dataComponent.setId("dataComponent");
dataComponent.addStyleName("«EnumCssClass.DATA_COMPONENT.styleName»");
layoutManager.getDataArea().addComponent(dataComponent);
layoutManager.getDataArea().setExpandRatio(dataComponent, 1);
} catch (DerivedOlapException e) {
log.error(e.getLocalizedMessage());
}
'''
}
return body
}
/**
* <p>if more than 2 axes (dimensions) are found in the cellSet, build recursive tabsheets as long as the remaining axes are more than 2.</p>
*
*/
def String createTabSheet(Chart chart) {
var body =
'''
// either create a recursive tabsheet or a chart
Component component = null;
if (axisNo == 2) {
'''
if ((chart.charttype instanceof ChartTree)) {
body = '''
«body»
try {
component = createD3Chart(cellSet);
} catch (JsonException e) {
log.error(e.getLocalizedMessage());
}
'''
}
else {
body = '''
«body»
component = createChart(cellSet);
'''
}
body = '''
«body»
}
else {
Integer axis = axisNo-1;
TabSheet tabsheet = new TabSheet();
tabsheet.setSizeFull();
DerivedAxis tabAxis = cellSet.getAxes().get(axis);
// create a tab page for all tab axis members
int tabNo = 0;
for (DerivedPosition column : tabAxis.getPositions()) {
// create the title for the axis
String title = null;
for (DerivedMember member : column.getMembers()) {
if (title == null) {
title = dslMetadataService.translate(user.getLocale().toLanguageTag(), member.getCaption());
}
else {
title += " / "+dslMetadataService.translate(user.getLocale().toLanguageTag(), member.getCaption());
}
}
// position the data to this coordinate
getCoordinateSystem().set(axis, tabNo);
component = createTabSheet(cellSet, axis);
// set the caption
if (component != null) {
component.setCaption(title);
// add the component as a tab page
tabsheet.addComponent(component);
}
tabNo++;
}
component = tabsheet;
}
return component;'''
return body
}
/**
* <p>build the chart components.</p>
*
*/
def String createChart(Chart chart) {
var body = ""
var postfix = ""
var chartType = ""
var hasAxis = true
var multipleAxes = <String, String>newHashMap
var ChartAxis category_axis = null
var ChartAxis data_axis = null
var ChartAxis inner_axis = null
var ChartAxis outer_axis = null
var axisSwitch = false;
var axisPrefix = 'XY'
var CanvasFontFamilyEnum fontFamily = (chart.eContainer as ChartPackage).defaultFontFamily
if (chart.charttype instanceof ChartBar) {
if ((chart.charttype as ChartBar).swapped) {
axisPrefix = 'YX'
axisSwitch = true;
}
}
for (element : chart.source.elements) {
if (element instanceof ChartAxis) {
var axis = element as ChartAxis
if (axis.axis.name.getName.equals('COLUMNS') || axis.axis.name.getName.equals('ROWS')) {
if ((axis.renderType.getName.equals("LOG") || axis.renderType.getName.equals("LINEAR") || axis.renderType.getName.equals("PYRAMID"))) {
data_axis = axis
}
if ((axis.renderType.getName.equals("CATEGORY") || axis.renderType.getName.equals("DATE"))) {
category_axis = axis
}
}
}
}
if (chart.charttype instanceof ChartBar) {
chartType = "BAR"
postfix = '''_«chartType»'''
inner_axis = category_axis
outer_axis = data_axis
}
else if (chart.charttype instanceof ChartBubble) {
chartType = "BUBBLE"
postfix = '''_«chartType»'''
hasAxis = true
inner_axis = data_axis
outer_axis = category_axis
}
else if (chart.charttype instanceof ChartDonut) {
chartType = "DONUT"
hasAxis = false
inner_axis = category_axis
outer_axis = data_axis
}
else if (chart.charttype instanceof ChartLine) {
chartType = "LINE"
inner_axis = category_axis
outer_axis = data_axis
}
else if (chart.charttype instanceof ChartPie) {
chartType = "PIE"
hasAxis = false
inner_axis = data_axis
outer_axis = category_axis
}
else if (chart.charttype instanceof ChartGauge) {
chartType = "METER_GAUGE"
hasAxis = false
inner_axis = data_axis
outer_axis = category_axis
}
body =
'''
List<Integer> coordinate = new ArrayList<Integer>(getCoordinateSystem());
'''
body = '''
«body»// create a label series
List<String> «data_axis.axis.name.literal»TitlesArray = new ArrayList<String>();
for (DerivedPosition pos : cellSet.getAxes().get(«data_axis.axis.name.value»).getPositions()) {
'''
body = '''
«body»
String title = null;
for (DerivedMember member : pos.getMembers()) {
if(member.getType() == MemberType.MEASURE || member.getType() == MemberType.FORMULA) {
if (title == null) {
title = dslMetadataService.translate(user.getLocale().toLanguageTag(), member.getCaption());
}
else {
title += " "+dslMetadataService.translate(user.getLocale().toLanguageTag(), member.getCaption());
}
}
}
if(title != null) {
«data_axis.axis.name.literal»TitlesArray.add(title);
}
}
'''
if (hasAxis) {
body = '''
«body»Series «data_axis.axis.name.literal»Series = new Series();
'''
body = '''
«body»if («data_axis.axis.name.literal»TitlesArray.size() > 0) {
'''
// evaluate multiple scales
var showMarker = false
if (chart.charttype instanceof ChartLine) {
showMarker = (chart.charttype as ChartLine).showMarker
}
body = '''«body»«chart.createLabelSeries(data_axis, multipleAxes, axisPrefix, showMarker)»'''
body = '''
«body»}
'''
}
body = '''
«body»// create the data series ticks
String «category_axis.axis.name.literal»AxisLabel = "";
Boolean «category_axis.axis.name.literal»AxisLabelSet = false;
List<String> «category_axis.axis.name.literal»TitlesArray = new ArrayList<String>();
for (DerivedPosition pos : cellSet.getAxes().get(«category_axis.axis.name.value»).getPositions()) {
String title = "";
for (DerivedMember member : pos.getMembers()) {
if(member.getType() == MemberType.REGULAR) {
String[] tokens = member.getUniqueName().split("\\]\\.\\[");
if (!«category_axis.axis.name.literal»AxisLabelSet) {
if («category_axis.axis.name.literal»AxisLabel.length() > 0) {
«category_axis.axis.name.literal»AxisLabel += " / ";
}
«category_axis.axis.name.literal»AxisLabel += dslMetadataService.translate(user.getLocale().toLanguageTag(), member.getLevel().getName());
}
int start = 1;
// if shortlabel is configured, use only last level name
if («category_axis.shortLabel.booleanValue») {
start = tokens.length-1;
}
for (int token = start; token < tokens.length; token++) {
title += dslMetadataService.translate(user.getLocale().toLanguageTag(), tokens[token])+" ";
}
}
}
if(title != null) {
«category_axis.axis.name.literal»AxisLabelSet = true;
«category_axis.axis.name.literal»TitlesArray.add(title.trim().replace("[", "").replace("]", ""));
}
}
'''
if (hasAxis) {
body = '''
«body»Ticks «category_axis.axis.name.literal»Ticks = new Ticks();
«category_axis.axis.name.literal»Ticks.add(«category_axis.axis.name.literal»TitlesArray.toArray());
'''
}
body = '''
«body»
if(«category_axis.axis.name.literal»TitlesArray.isEmpty()) {
return null;
}
// copy cellset data to data series
DataSeries dataSeries = new DataSeries();
'''
if (chart.charttype instanceof ChartBubble) {
body = '''
«body»dataSeries.newSeries();
'''
}
body = '''
«body»int «outer_axis.axis.name.literal»No = 0;
'''
body = '''
«body»for (DerivedPosition «outer_axis.axis.name.literal»Pos : cellSet.getAxes().get(«outer_axis.axis.name.value»).getPositions()) {
'''
body = '''
«body» coordinate.set(«outer_axis.axis.name.value», «outer_axis.axis.name.literal»No);
'''
if (chart.charttype instanceof ChartDonut) {
body = '''
«body» dataSeries.newSeries();
'''
}
if (!(chart.charttype instanceof ChartPie) && !(chart.charttype instanceof ChartDonut)) {
body = '''
«body» ArrayList<Object> «inner_axis.axis.name.literal»DataSeries = new ArrayList<Object>();
'''
}
if(outer_axis == data_axis) {
body = '''
«body» if(«outer_axis.axis.name.literal»Pos.getMembers().get(0).getType() == MemberType.MEASURE || «outer_axis.axis.name.literal»Pos.getMembers().get(0).getType() == MemberType.FORMULA) {
'''
} else {
body = '''
«body» if(«outer_axis.axis.name.literal»Pos.getMembers().get(0).getType() == MemberType.REGULAR) {
'''
}
body = '''
«body» int «inner_axis.axis.name.literal»No = 0;
'''
body = '''
«body» for (DerivedPosition «inner_axis.axis.name.literal»Pos : cellSet.getAxes().get(«inner_axis.axis.name.value»).getPositions()) {
'''
if(inner_axis == data_axis) {
body = '''
«body» if(«inner_axis.axis.name.literal»Pos.getMembers().get(0).getType() == MemberType.MEASURE || «inner_axis.axis.name.literal»Pos.getMembers().get(0).getType() == MemberType.FORMULA) {
'''
} else {
body = '''
«body» if(«inner_axis.axis.name.literal»Pos.getMembers().get(0).getType() == MemberType.REGULAR) {
'''
}
if (chart.charttype instanceof ChartPie) {
body = '''
«body» dataSeries.newSeries();
'''
}
body = '''
«body» coordinate.set(«inner_axis.axis.name.value», «inner_axis.axis.name.literal»No);
'''
body = '''
«body»
Object value = null;
DerivedCell cell = cellSet.getCell(coordinate);
if (cell != null) {
value = cell.getValue();
}
'''
if (chart.charttype instanceof ChartPie || chart.charttype instanceof ChartDonut) {
body = '''
«body» dataSeries.add(«outer_axis.axis.name.literal»TitlesArray.get(«outer_axis.axis.name.literal»No),(value == null ? 0.0 : value));
'''
}
else {
body = '''
«body» «inner_axis.axis.name.literal»DataSeries.add(value == null ? 0.0 : value);
'''
}
body = '''
«body» «inner_axis.axis.name.literal»No ++;
}
}
'''
if (!(chart.charttype instanceof ChartPie) && !(chart.charttype instanceof ChartDonut)) {
if (chart.charttype instanceof ChartBubble) {
body = '''
«body» «inner_axis.axis.name.literal»DataSeries.add(«outer_axis.axis.name.literal»TitlesArray.get(«outer_axis.axis.name.literal»No));
'''
}
body = '''
«body» dataSeries.add(«inner_axis.axis.name.literal»DataSeries.toArray());
'''
}
body = '''
«body» }
«outer_axis.axis.name.literal»No ++;
}
'''
body = '''
«body»SeriesDefaults seriesDefaults = new SeriesDefaults()
.setRenderer(SeriesRenderers.«chartType»);
'''
if (chart.charttype instanceof ChartLine) {
body = '''
«body»seriesDefaults.setFillToZero(«(chart.charttype as ChartLine).fillToZero.booleanValue.toString»).setFill(«(chart.charttype as ChartLine).fillArea.toString»);
'''
if ((chart.charttype as ChartLine).trendLine) {
body = '''
«body»seriesDefaults.setTrendline(
new Trendline().setShow(true).setLineWidth(1));
'''
}
}
// options
body = '''
«body»Options options = new Options()
.setSeriesDefaults(seriesDefaults);
'''
if (chart.charttype instanceof ChartPie) {
body = '''
«body»seriesDefaults.setRendererOptions(new PieRenderer()
.setShowDataLabels(true).setFill(«(!(chart.charttype as ChartPie).empty).toString»));
'''
}
else if (chart.charttype instanceof ChartDonut) {
body = '''
«body»seriesDefaults.setRendererOptions(new DonutRenderer()
.setShowDataLabels(true)
.setStartAngle(-90)
.setSliceMargin(3));
'''
}
else if (chart.charttype instanceof ChartBubble) {
body = '''
«body»seriesDefaults.setRendererOptions(new BubbleRenderer()
.setVaryBubbleColors(true)
«IF (chart.charttype as ChartBubble).multiplier».setAutoscaleMultiplier(«(chart.charttype as ChartBubble).multiplierValue»f)«ENDIF»
«IF (chart.charttype as ChartBubble).transparent».setHighlightAlpha(0.8f).setBubbleAlpha(0.6f)«ENDIF»
«IF (chart.charttype as ChartBubble).gradient».setBubbleGradients(true)«ENDIF»
.setShowLabels(false)
.setAutoscaleBubbles(true));
'''
}
else if (chart.charttype instanceof ChartGauge) {
var intervalValues = ""
var intervalColors = ""
if ((chart.charttype as ChartGauge).hasIntervals) {
for (interval : (chart.charttype as ChartGauge).intervals) {
if (interval instanceof ChartNumberInterval) {
intervalValues = '''«intervalValues»«IF intervalValues.length>0»,«ENDIF»«(interval as ChartNumberInterval).numberIntervalValue»f'''
if ((interval as ChartNumberInterval).numberRange instanceof ChartSegmentColor) {
intervalColors = '''«intervalColors»«IF intervalColors.length>0»,«ENDIF»"«((interval as ChartNumberInterval).numberRange as ChartSegmentColor).rgb.toHex»"'''
}
}
}
}
body = '''
«body»seriesDefaults.setRendererOptions(new MeterGaugeRenderer()
.setShowTickLabels(«(chart.charttype as ChartGauge).hasTicks.toString»)
«IF (chart.charttype as ChartGauge).labeled».setLabel("«(chart.charttype as ChartGauge).labelValue»")«ENDIF»
«IF (chart.charttype as ChartGauge).hasIntervals».setIntervals(«intervalValues»)«ENDIF»
«IF (chart.charttype as ChartGauge).hasIntervals».setIntervalColors(«intervalColors»)«ENDIF»);
'''
}
else if (chart.charttype instanceof ChartBar) {
body = '''
«body»seriesDefaults.setFillToZero(true);
seriesDefaults.setRendererOptions(new BarRenderer()
«IF axisSwitch».setBarDirection(BarDirections.HOTIZONTAL));«ELSE».setBarDirection(BarDirections.VERTICAL));«ENDIF»
'''
if ((chart.charttype as ChartBar).stacked) {
body = '''
«body»options.setStackSeries(true);
'''
}
if ((chart.charttype as ChartBar).shadow) {
body = '''
«body»seriesDefaults.setShadow(true).setShadowAlpha(0.05f);
'''
}
if ((chart.charttype as ChartBar).animated) {
body = '''
«body»options.setAnimate(true);
'''
}
}
if((chart.eContainer as ChartPackage).hasColors) {
body = '''
«body»
String[] seriesColors = «(chart.eContainer as ChartPackage).colors.stream.map['''"«it.rgb.toHex»"'''].collect(Collectors.joining(",", "{", "}"))»;
options.setSeriesColors(seriesColors);
'''
}
if (hasAxis) {
// axes
body = '''
«body»Axes axes = new Axes();
'''
if (chart.charttype instanceof ChartBubble) {
// x
body = '''
«body»
«data_axis.canvasAxisRenderer("x", "Tick", fontFamily)»
«data_axis.canvasAxisRenderer("x", "Label", fontFamily)»
if («data_axis.axis.name.literal»TitlesArray.size() > 0) {
axes.addAxis(new XYaxis(XYaxes.«axisPrefix.charAt(0)»).setLabel(«data_axis.axis.name.literal»TitlesArray.get(0)).setTickOptions(xTickRenderer).setLabelOptions(xLabelRenderer));
axes.addAxis(new XYaxis(XYaxes.«axisPrefix.charAt(1)»).setLabel(«data_axis.axis.name.literal»TitlesArray.get(1)).setTickOptions(xTickRenderer).setLabelOptions(xLabelRenderer));
axes.addAxis(new XYaxis(XYaxes.«axisPrefix.charAt(1)»2).setLabel(«data_axis.axis.name.literal»TitlesArray.get(2)).setTickOptions(xTickRenderer).setLabelOptions(xLabelRenderer));
}
'''
}
else {
// x
body = '''
«body»
«category_axis.canvasAxisRenderer("x", "Tick", fontFamily)»
«category_axis.canvasAxisRenderer("x", "Label", fontFamily)»
axes.addAxis(new XYaxis(XYaxes.«axisPrefix.charAt(0)»)
.setRenderer(AxisRenderers.«category_axis.renderType.name().toString»)
.setLabel(«category_axis.axis.name.literal»AxisLabel)
.setTicks(«category_axis.axis.name.literal»Ticks)
.setTickOptions(xTickRenderer)
.setLabelOptions(xLabelRenderer));
'''
// y .. y9
body = '''
«body»
«data_axis.canvasAxisRenderer("y", "Tick", fontFamily)»
axes.addAxis(new XYaxis(XYaxes.«axisPrefix.charAt(1)»)
.setPad(1.05f)
.setTickOptions(yTickRenderer));
'''
// additional axes
for (axisKey : multipleAxes.keySet) {
if (!axisKey.equals("1")) {
body = '''«body»«multipleAxes.get(axisKey)»'''
}
}
if (multipleAxes.keySet.size > 0) {
body = '''
«body»LinearAxisRenderer linearAxisRenderer = new LinearAxisRenderer();
linearAxisRenderer.setAlignTicks(true);
AxesDefaults axesDefaults = new AxesDefaults()
.setUseSeriesColor(true)
.setBorderWidth(3)
.setRendererOptions(linearAxisRenderer);
options.setAxesDefaults(axesDefaults);
'''
}
}
body = '''
«body»options.setAxes(axes);
'''
}
// legend
var hadLegend = false
for (element : chart.source.elements) {
if (element instanceof ChartLegend) {
var legend = element as ChartLegend
if(legend.noLegend) {
hadLegend = true
} else {
hadLegend = true
body = '''
«body»
Legend legend = new Legend().setShow(«(legend !== null).booleanValue.toString»);
legend.setPlacement(LegendPlacements.«legend.placement.name()»);
'''
if (legend.toggle) {
body = '''
«body»
EnhancedLegendRenderer renderer = new EnhancedLegendRenderer();
renderer.setSeriesToggle(SeriesToggles.«legend.toggleType.getName»);
renderer.setSeriesToggleReplot(«legend.replot.booleanValue.toString»);
legend.setRendererOptions(renderer);
«IF legend.textColor !== null»legend.setTextColor("«legend.textColor.toHex»");«ENDIF»
«IF legend.fontSize !== 0»legend.setFontSize("«legend.fontSize»pt");«ENDIF»
«IF !fontFamily.equals(CanvasFontFamilyEnum.DEFAULT)»legend.setFontFamily("«fontFamily.literal»");«ENDIF»
'''
}
body = '''
«body»options.setLegend(legend);
'''
}
}
}
if(!hadLegend) {
body = '''
«body»
Legend legend = new Legend().setShow(true);
legend.setPlacement(LegendPlacements.OUTSIDE_GRID);
EnhancedLegendRenderer renderer = new EnhancedLegendRenderer();
renderer.setSeriesToggle(SeriesToggles.FAST);
renderer.setSeriesToggleReplot(true);
legend.setRendererOptions(renderer);
«IF !fontFamily.equals(CanvasFontFamilyEnum.DEFAULT)»legend.setFontFamily("«fontFamily.literal»");«ENDIF»
options.setLegend(legend);
'''
}
// highlighter
var hadHighlighter = false
for (element : chart.source.elements) {
if (element instanceof ChartHighlighter) {
hadHighlighter = true
var highlighter = element as ChartHighlighter
body = '''
«body»
Highlighter highlighter = new Highlighter().setShow(«(highlighter !== null).booleanValue.toString»);
highlighter.setShowTooltip(true)
.setTooltipAlwaysVisible(«highlighter.tooltipAlways.booleanValue.toString»)
.setKeepTooltipInsideChart(«highlighter.insideChart.booleanValue.toString»)
.setTooltipLocation(TooltipLocations.«highlighter.location.name()»)
.setBringSeriesToFront(true)
.setFadeTooltip(true)
.setShowMarker(true);
highlighter.setTooltipAxes(TooltipAxes.«axisPrefix»«postfix»);
options.setHighlighter(highlighter);
'''
}
}
if(!hadHighlighter) {
body = '''
«body»
Highlighter highlighter = new Highlighter().setShow(true);
highlighter.setShowTooltip(true)
.setTooltipAlwaysVisible(true)
.setKeepTooltipInsideChart(true)
.setTooltipLocation(TooltipLocations.NORTH_EAST)
.setBringSeriesToFront(true)
.setFadeTooltip(true)
.setShowMarker(true);
highlighter.setTooltipAxes(TooltipAxes.«axisPrefix»«postfix»);
options.setHighlighter(highlighter);
'''
}
// cursor
if (chart.charttype instanceof ChartLine) {
if ((chart.charttype as ChartLine).cursor) {
body = '''
«body»Cursor cursor = new Cursor()
.setShow(true)
.setZoom(«(chart.charttype as ChartLine).zoom.toString»)
.setShowTooltip(«(chart.charttype as ChartLine).tooltip.toString»);
options.setCursor(cursor);
'''
}
if ((chart.charttype as ChartLine).animated) {
body = '''
«body»options.setAnimate(true);
'''
}
}
if (hasAxis) {
// series
body = '''
«body»options.setSeries(«data_axis.axis.name.literal»Series);
'''
}
body = '''
«body»DCharts chart = new DCharts();
chart.setDataSeries(dataSeries);
chart.setOptions(options);
chart.setEnableChartImageChangeEvent(true);
'''
body = '''
«body»chart.setId("chart");
chart.setImmediate(true);
chart.show();
charts.add(chart);
'''
if (chart.toolbar !== null && chart.toolbar.eContainer !== null) {
body = '''
«body»
for (MToolBarElement element : toolbarClass.getToolBar().getChildren()) {
Object widget = element.getWidget();
if (widget instanceof Button) {
List<String> tags = element.getTags();
if (tags.contains(ChartActionEnum.CHART_ACTION_DOWNLOAD.getLiteral())) {
FileDownloader fileDownloader = new FileDownloader(getChartResource(chart, layoutManager));
fileDownloader.extend((Button) widget);
}
}
}'''
}
body = '''
«body»return chart;'''
return body
}
def canvasAxisRenderer(ChartAxis axis, String axisName, String typeName, CanvasFontFamilyEnum fontFamily)
'''
CanvasAxis«typeName»Renderer «axisName»«typeName»Renderer = new CanvasAxis«typeName»Renderer();
«IF "Tick".equals(typeName)»
«axisName»«typeName»Renderer.setTextColor(«IF axis.tickTextColor !== null»"«axis.tickTextColor.toHex»"«ELSE»"#202020"«ENDIF»);
«IF axis.tickFontSize !== 0»«axisName»«typeName»Renderer.setFontSize("«axis.tickFontSize»pt");«ENDIF»
«IF axis.tickAngle!=0»«axisName»«typeName»Renderer.setAngle(«axis.tickAngle»);«ENDIF»
«ELSE»
«axisName»«typeName»Renderer.setTextColor(«IF axis.labelTextColor !== null»"«axis.labelTextColor.toHex»"«ELSE»"#202020"«ENDIF»);
«IF axis.labelFontSize !== 0»«axisName»«typeName»Renderer.setFontSize("«axis.labelFontSize»pt");«ENDIF»
«IF axis.labelAngle!=0»«axisName»«typeName»Renderer.setAngle(«axis.labelAngle»);«ENDIF»
«ENDIF»
«IF !fontFamily.equals(CanvasFontFamilyEnum.DEFAULT)»
«axisName»«typeName»Renderer.setEnableFontSupport(true);
«axisName»«typeName»Renderer.setFontFamily("«fontFamily.literal»");
«ENDIF»
'''
/**
* <p>helper method to convert a rgb string to a hex string.</p>
*
*/
def String toHex(String rgb) {
var colorHex = "#"
for (color : rgb.split(",")) {
var i = new Integer(color);
colorHex = '''«colorHex»«String::format("%02x", i)»'''
}
return colorHex
}
/**
* <p>build the label series. Create multiple y-axes when the underlying datamart presents different scales.</p>
*
* <p>scales are used to display line charts together for comparison reason but they are of different scalings.</p>
*/
def String createLabelSeries(Chart chart, ChartAxis data_axis, HashMap<String,String>multipleAxes, String axisPrefix, boolean showMarker) {
var body = ""
var msrCnt = 0
// find multiple axes defined in datamart
if ((chart.source as ChartDatamart).datamartRef.source instanceof DatamartCube) {
for (axisOrSlicer : ((chart.source as ChartDatamart).datamartRef.source as DatamartCube).axisslicer) {
if (axisOrSlicer instanceof DatamartCubeAxis) {
for (element : (axisOrSlicer as DatamartCubeAxis).elements) {
if (element instanceof DatamartDerivedMeasure) {
if ((element as DatamartDerivedMeasure).scaled) {
body = '''«body»«(element as DatamartDerivedMeasure).scale.createScale(data_axis, multipleAxes, msrCnt, axisPrefix, showMarker)»'''
msrCnt = msrCnt + 1
}
}
if (element instanceof DatamartMeasure) {
if ((element as DatamartMeasure).scaled) {
body = '''«body»«(element as DatamartMeasure).scale.createScale(data_axis, multipleAxes, msrCnt, axisPrefix, showMarker)»'''
msrCnt = msrCnt + 1
}
}
}
}
}
}
else if ((chart.source as ChartDatamart).datamartRef.source instanceof DatamartEntity) {
var entity = ((chart.source as ChartDatamart).datamartRef.source as DatamartEntity)
body = '''«body»«entity.entityScale(data_axis, multipleAxes, msrCnt, axisPrefix, showMarker)»'''
}
// no multiple axes defined in datamart
if (multipleAxes.keySet.size == 0) {
body = '''
«body» for (String title : «data_axis.axis.name.literal»TitlesArray) {
«data_axis.axis.name.literal»Series.addSeries(new XYseries().setLabel(title).setShowMarker(«showMarker.toString»));
}
'''
}
return body
}
/**
* <p>helper method for scales coming from datamart entities not from cubes.</p>
*
*/
def String entityScale(DatamartEntity entity, ChartAxis data_axis, HashMap<String,String> multipleAxes, int msrCnt, String axisPrefix, boolean showMarker) {
var counter = msrCnt
var body = ""
for (attribute : entity.attributes) {
if (attribute instanceof DatamartAttribute) {
if (attribute.scaled) {
body = '''«body»«attribute.scale.createScale(data_axis, multipleAxes, counter, axisPrefix, showMarker)»'''
counter = counter + 1
}
}
}
for (navigation : entity.navigations) {
if (navigation instanceof DatamartMember) {
body = '''«body»«(navigation as DatamartMember).datamartEntity.entityScale(data_axis, multipleAxes, counter, axisPrefix, showMarker)»'''
}
if (navigation instanceof DatamartOwner) {
body = '''«body»«(navigation as DatamartOwner).datamartEntity.entityScale(data_axis, multipleAxes, counter, axisPrefix, showMarker)»'''
}
}
return body
}
/**
* <p>helper method for scales.</p>
*
*/
def String createScale(ValueScaleEnum scale, ChartAxis data_axis, HashMap<String,String> multipleAxes, int msrCnt, String axisPrefix, boolean showMarker) {
var multipleBody = ""
var body = ""
var scaleOrdinal = scale.ordinal
var scaleName = scale.toString
body = '''
«body»
«data_axis.axis.name.literal»Series.addSeries(new XYseries(«axisPrefix.charAt(1)»axes.«axisPrefix.charAt(1)»«IF scaleOrdinal != 0»«(scaleOrdinal+1)»«ENDIF»).setLabel(«data_axis.axis.name.literal»TitlesArray.get(«msrCnt»)).setShowMarker(«showMarker.toString»));
'''
if (!multipleAxes.keySet.contains(scaleName)) {
// axis 1 is never expressed, but 2..9
multipleBody =
'''axes.addAxis(new XYaxis(XYaxes.«axisPrefix.charAt(1)»«IF scaleOrdinal != 0»«(scaleOrdinal+1)»«ENDIF»).setTickOptions(yTickRenderer«IF data_axis.tickAngle!=0».setAngle(«data_axis.tickAngle»)«ENDIF»));
'''
multipleAxes.put(scaleName, multipleBody)
}
return body
}
/**
* <p>helper method to get a attribute name or its alias if present of a entity's attribute object.</p>
*
*/
def String getAttributeName(DatamartAttribute attribute) {
return (attribute.attributeRef as LAttribute).name.toUpperCase
}
/**
* <p>helper method to get a level name of a hierarchy's level object.</p>
*
*/
def String getLevelName(CubeLevel level) {
return level.name
}
def String filterChanged(Chart chart) {
var body = ""
body = '''
«body»
if(changedFilter != null) {
MPerspective perspective = getContext().get(MPerspective.class);
EventDispatcherEvent evnt = new EventDispatcherEvent(perspective, EventDispatcherCommand.SELECT, changedFilter.getName(), "«chart.name»");
evnt.addData(changedFilter.getSelectedData());
eventDispatcher.sendEvent(evnt);
}
renderData();
'''
return body
}
def Set<LEntity> findRequestedEntities(Chart chart) {
var entities = new HashSet<LEntity>()
entities.addAll((chart.source as ChartDatamart).datamartRef.findAllEntities())
return entities
}
def String receiveEvent(Chart chart) {
var body = ""
body = '''
«body»
switch(event.getCommand()) {
case SELECT:
MPerspective perspective = getContext().get(MPerspective.class);
if(event.getPerspective() == null || (perspective != null && event.getPerspective().equals(perspective))){
if(!event.getSender().equals("«chart.fullyQualifiedName»")) {
if(filterGenerator.selectItem(event, «chart.selectById.booleanValue»)) {
renderData();
}
}
}
break;
case SAVE:
case DELETE:
if(!event.getSender().equals("«chart.fullyQualifiedName»")) {
«FOR e:findRequestedEntities(chart)»
if(event.getTopic().equals("«e.fullyQualifiedName»")){
datamartInstance.clearCache();
renderData();
}
«ENDFOR»
}
break;
case REFRESH:
if(!event.getSender().equals("«chart.fullyQualifiedName»")) {
«FOR e:findRequestedEntities(chart)»
if(event.getTopic().equals("«e.fullyQualifiedName»")){
datamartInstance.clearCache();
renderData();
}
«ENDFOR»
}
/* must be activated if sure that the filter is to be refreshed
if (filterGenerator != null) {
filterGenerator.updateFilter();
}*/
break;
}
'''
return body
}
def localeChanged(Chart chart)
'''
if(charts != null) {
for(DCharts chart:charts) {
chart.setLocale(locale);
«IF chart.source.datamartRef.description &&
chart.source.datamartRef.descriptionValue !== null»
chart.setDescription(dslMetadataService.translate(locale.toLanguageTag(), "«chart.source.datamartRef.descriptionValue»"));
««« chart.setDownloadButtonCaption(dslMetadataService.translate(locale.toLanguageTag(), "download"));
«ENDIF»
}
}
if(layoutManager != null) {
layoutManager.setLabelValue(dslMetadataService.translate(locale.toLanguageTag(), "«chart.name»"));
}
'''
def chartResource(Chart chart)
'''
return new StreamResource(new StreamSource() {
private static final long serialVersionUID = -6463786579404065302L;
@Override
public InputStream getStream() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(chart.getChartImage(), chart.getChartImageFormat()
.getFormat(), bos);
return new ByteArrayInputStream(bos.toByteArray());
} catch (Exception e) {
return new ByteArrayInputStream("".getBytes());
}
}
}, layoutManager.getCaption() + chart.getChartImageFormat().getFormatExtension());
'''
def void createJsJavaComponent(Chart chart, IJvmDeclaredTypeAcceptor acceptor){
val stateClassName = chart.createStateFilename
var chart_cls = chart.toClass(chart.createfullyQualifiedChartFilename)
// JavaScript-Java-State-Component creation
var state_cls = chart.toClass(chart.createfullyQualifiedStateFilename)
if (chart.charttype instanceof ChartTree){
val ChartTree chartTree = chart.charttype as ChartTree
// JavaScript-Java-Component creation
acceptor.accept(chart_cls)
.initializeLater([
superTypes += _typeReferenceBuilder.typeRef(AbstractJavaScriptComponent)
var JvmAnnotationReference jsAnnotationRef = chartTree.toAnnotation(typeof(JavaScript))
var jsAnnotationList = newArrayList(
"theme://plugin/org.eclipse.osbp.utils.js/org/eclipse/osbp/utils/js/d3.js",
"theme://plugin/org.eclipse.osbp.utils.js/org/eclipse/osbp/utils/js/d3-scale-chromatic.js",
chart.createChartJsFilename
)
jsAnnotationRef.addStringValuesToAnnotation(jsAnnotationList)
annotations += jsAnnotationRef
if (chartTree.map){
it.toTreeMapConstructor(chart)
} else if (chartTree.collapsible) {
it.toChartConstructor(chart)
}
it.toChartOperations(chart, stateClassName)
])
// JavaScript-Java-State-Component creation
acceptor.accept(state_cls)
.initializeLater([
superTypes += _typeReferenceBuilder.typeRef(JavaScriptComponentState)
if (chartTree.map){
it.toTreeMapStateFields(chart)
} else if (chartTree.collapsible) {
it.toChartStateFields(chart)
}
])
}
}
def void toChartOperations(JvmDeclaredType type, Chart chart, String stateClassName){
// create view
type.members += chart.toMethod("getState", _typeReferenceBuilder.typeRef(stateClassName), [
body = [ append('''return («stateClassName») super.getState();''')]
])
}
def getD3StateVars()
'''
getState().jsonData = _jsonData;
getState().htmlTagId=_htmlTagId;
getState().panelWidth = new Integer(width).toString();
getState().panelHeight = new Integer(height).toString();
'''
def JvmConstructor getChartConstructor(JvmDeclaredType type, Chart chart) {
return chart.toConstructor([
parameters += chart.toParameter("_htmlTagId", _typeReferenceBuilder.typeRef(String))
parameters += chart.toParameter("_jsonData", _typeReferenceBuilder.typeRef(String))
parameters += chart.toParameter("width", _typeReferenceBuilder.typeRef(int))
parameters += chart.toParameter("height", _typeReferenceBuilder.typeRef(int))
body = [ append(getD3StateVars)]
])
}
def void toTreeMapConstructor(JvmDeclaredType type, Chart chart) {
var JvmConstructor constructor = type.getChartConstructor(chart)
constructor.parameters += chart.toParameter("dataColumns", _typeReferenceBuilder.typeRef(List, _typeReferenceBuilder.typeRef(String)))
constructor.body = [ append(
'''
«d3StateVars»
getState().dataColumnList = dataColumns;''')]
type.members += constructor
}
def void toChartConstructor(JvmDeclaredType type, Chart chart) {
var JvmConstructor constructor = type.getChartConstructor(chart)
type.members += constructor
}
def void addStringValuesToAnnotation(JvmAnnotationReference annotationRef, ArrayList<String> annotationStringList){
var JvmStringAnnotationValue value = typesFactory.createJvmStringAnnotationValue
for (annotationString : annotationStringList){
value.values += annotationString
}
annotationRef.explicitValues += value
}
def void toTreeMapStateFields(JvmDeclaredType type, Chart chart){
type.toChartStateFields(chart)
type.members += chart.toField("dataColumnList", _typeReferenceBuilder.typeRef(List, _typeReferenceBuilder.typeRef(String)))[
visibility = JvmVisibility::PUBLIC
setInitializer([append('''new ArrayList<String>()''')])]
}
def void toChartStateFields(JvmDeclaredType type, Chart chart){
type.members += chart.toField("jsonData", _typeReferenceBuilder.typeRef(String))[
visibility = JvmVisibility::PUBLIC
setInitializer([append('''""''')])]
type.members += chart.toField("htmlTagId", _typeReferenceBuilder.typeRef(String))[
visibility = JvmVisibility::PUBLIC
setInitializer([append('''""''')])]
type.members += chart.toField("panelWidth", _typeReferenceBuilder.typeRef(String)) [
visibility = JvmVisibility::PUBLIC
setInitializer([append('''""''')])
]
type.members += chart.toField("panelHeight", _typeReferenceBuilder.typeRef(String)) [
visibility = JvmVisibility::PUBLIC
setInitializer([append('''""''')])
]
type.members += chart.toField("inputValue", _typeReferenceBuilder.typeRef(String))[
visibility = JvmVisibility::PUBLIC
setInitializer([append('''""''')])]
}
def createD3Chart(Chart chart)
'''
CellSetToD3JsonConverter jsonConverter = new CellSetToD3JsonConverter();
return new «val d3ChartFileName = chart.createChartFilename»«d3ChartFileName»("«d3ChartFileName»", jsonConverter.getD3JsonString(cxCellSet, «IF chart.charttype instanceof ChartTree && (chart.charttype as ChartTree).collapsible»true«ELSE»false«ENDIF»), panelWidth, panelHeight«IF chart.treeMap», jsonConverter.getDataColumnNameList(cxCellSet)«ENDIF»);'''
}