Java tutorial
/******************************************************************************* * Copyright (c) 2005 Actuate Corporation. * 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: * Actuate Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.birt.report.designer.data.ui.dataset; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.eclipse.birt.core.data.ExpressionUtil; import org.eclipse.birt.core.data.IColumnBinding; import org.eclipse.birt.core.exception.BirtException; import org.eclipse.birt.data.engine.api.aggregation.AggregationManager; import org.eclipse.birt.data.engine.api.aggregation.IAggrFunction; import org.eclipse.birt.data.engine.api.aggregation.IParameterDefn; import org.eclipse.birt.report.data.adapter.api.DataAdapterUtil; import org.eclipse.birt.report.designer.data.ui.property.AbstractDescriptionPropertyPage; import org.eclipse.birt.report.designer.data.ui.util.ControlProvider; import org.eclipse.birt.report.designer.data.ui.util.DataSetExceptionHandler; import org.eclipse.birt.report.designer.data.ui.util.DataSetExpressionProvider; import org.eclipse.birt.report.designer.data.ui.util.DataSetProvider; import org.eclipse.birt.report.designer.data.ui.util.DataUtil; import org.eclipse.birt.report.designer.data.ui.util.IHelpConstants; import org.eclipse.birt.report.designer.data.ui.util.Utility; import org.eclipse.birt.report.designer.internal.ui.util.ExceptionHandler; import org.eclipse.birt.report.designer.nls.Messages; import org.eclipse.birt.report.designer.ui.ReportPlugin; import org.eclipse.birt.report.designer.ui.dialogs.ExpressionBuilder; import org.eclipse.birt.report.designer.util.DEUtil; import org.eclipse.birt.report.model.api.AggregationArgumentHandle; import org.eclipse.birt.report.model.api.ColumnHintHandle; import org.eclipse.birt.report.model.api.ComputedColumnHandle; import org.eclipse.birt.report.model.api.DataSetHandle; import org.eclipse.birt.report.model.api.DesignElementHandle; import org.eclipse.birt.report.model.api.PropertyHandle; import org.eclipse.birt.report.model.api.StructureFactory; import org.eclipse.birt.report.model.api.activity.SemanticException; import org.eclipse.birt.report.model.api.elements.structures.AggregationArgument; import org.eclipse.birt.report.model.api.elements.structures.ComputedColumn; import org.eclipse.birt.report.model.api.metadata.IChoice; import org.eclipse.birt.report.model.api.metadata.PropertyValueException; import org.eclipse.birt.report.model.core.Structure; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; /** * TODO: Please document * * @version $Revision$ $Date$ */ public class DataSetComputedColumnsPage extends AbstractDescriptionPropertyPage { protected transient PropertyHandle computedColumns = null; protected transient PropertyHandleTableViewer viewer = null; private static final int COLUMN_NAME_INDEX = 0; private static final int DATA_TYPE_INDEX = 1; private static final int EXPRESSION_INDEX = 2; private static final int AGGREGATION_INDEX = 3; // private static final int ARGUMENT_INDEX = 4; private static final int FILTER_INDEX = 5; protected static String[] cellLabels = new String[] { Messages.getString("dataset.editor.title.columnName"), //$NON-NLS-1$ Messages.getString("dataset.editor.title.dataType"), //$NON-NLS-1$ Messages.getString("dataset.editor.title.expression"), //$NON-NLS-1$ Messages.getString("dataset.editor.title.aggrFunc"), //$NON-NLS-1$ Messages.getString("dataset.editor.title.aggrArgu"), //$NON-NLS-1$ Messages.getString("dataset.editor.title.filter") //$NON-NLS-1$ }; protected static String[] cellProperties = new String[] { ComputedColumn.NAME_MEMBER, ComputedColumn.DATA_TYPE_MEMBER, ComputedColumn.EXPRESSION_MEMBER, ComputedColumn.AGGREGATEON_FUNCTION_MEMBER, ComputedColumn.ARGUMENTS_MEMBER, ComputedColumn.FILTER_MEMBER }; protected static IChoice[] dataTypes = DEUtil.getMetaDataDictionary() .getStructure(ComputedColumn.COMPUTED_COLUMN_STRUCT).getMember(ComputedColumn.DATA_TYPE_MEMBER) .getAllowedChoices().getChoices(); protected static String[] dialogLabels = new String[] { Messages.getString("dataset.editor.inputDialog.columnName"), //$NON-NLS-1$ Messages.getString("dataset.editor.inputDialog.dataType"), //$NON-NLS-1$ Messages.getString("dataset.editor.inputDialog.expression"), //$NON-NLS-1$ Messages.getString("dataset.editor.inputDialog.aggrFunc"), //$NON-NLS-1$ Messages.getString("dataset.editor.inputDialog.aggrArgu"), //$NON-NLS-1$ Messages.getString("dataset.editor.inputDialog.filter") //$NON-NLS-1$ }; protected AggregationManager aggregationManager; /** * */ public DataSetComputedColumnsPage() { super(); try { aggregationManager = DataUtil.getAggregationManager().getInstance(); } catch (BirtException e) { e.printStackTrace(); } } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.ui.dialogs.properties.IPropertyPage#createPageControl(org.eclipse.swt.widgets.Composite) */ public Control createContents(Composite parent) { computedColumns = ((DataSetHandle) getContainer().getModel()) .getPropertyHandle(DataSetHandle.COMPUTED_COLUMNS_PROP); ; createTableViewer(parent); addListeners(); setToolTips(); return viewer.getControl(); } protected void createTableViewer(Composite parent) { viewer = new PropertyHandleTableViewer(parent, true, true, true) { protected void doRemove() { int index = viewer.getTable().getSelectionIndex(); PropertyHandle handle = (PropertyHandle) viewer.getInput(); int count = (handle.getListValue() == null) ? 0 : handle.getListValue().size(); if (index > -1 && index < count) { ComputedColumnHandle computedColumn = (ComputedColumnHandle) viewer.getTable().getItems()[index] .getData(); removeColumnHint(computedColumn.getName()); try { handle.removeItem(index); } catch (PropertyValueException e1) { ExceptionHandler.handle(e1); } viewer.refresh(); viewer.getTable().setFocus(); viewer.getTable().select(index); updateButtons(); } } private void removeColumnHint(String columnName) { if (columnName == null) return; PropertyHandle propertyHandle = ((DataSetHandle) getContainer().getModel()) .getPropertyHandle(DataSetHandle.COLUMN_HINTS_PROP); Iterator iter = propertyHandle.iterator(); while (iter.hasNext()) { ColumnHintHandle hint = (ColumnHintHandle) iter.next(); if (columnName.equals(hint.getColumnName())) { try { propertyHandle.removeItem(hint); } catch (PropertyValueException e) { ExceptionHandler.handle(e); } } } } }; TableColumn column = new TableColumn(viewer.getViewer().getTable(), SWT.LEFT); column.setText(cellLabels[COLUMN_NAME_INDEX]); column.setWidth(150); column = new TableColumn(viewer.getViewer().getTable(), SWT.LEFT); column.setText(cellLabels[DATA_TYPE_INDEX]); column.setWidth(200); column = new TableColumn(viewer.getViewer().getTable(), SWT.LEFT); column.setText(cellLabels[EXPRESSION_INDEX]); column.setWidth(200); column = new TableColumn(viewer.getViewer().getTable(), SWT.LEFT); column.setText(cellLabels[AGGREGATION_INDEX]); column.setWidth(200); column = new TableColumn(viewer.getViewer().getTable(), SWT.LEFT); column.setText(cellLabels[FILTER_INDEX]); column.setWidth(200); viewer.getViewer().setContentProvider(new IStructuredContentProvider() { public Object[] getElements(Object inputElement) { ArrayList computedColumnsList = new ArrayList(10); Iterator iter = computedColumns.iterator(); if (iter != null) { while (iter.hasNext()) { computedColumnsList.add(iter.next()); } } return computedColumnsList.toArray(); } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } }); viewer.getViewer().setLabelProvider(new TableProvider()); viewer.getViewer().setInput(computedColumns); } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.ui.dialogs.properties.IPropertyPage#pageActivated() */ public void pageActivated() { try { refreshColumnNames(); getContainer().setMessage(Messages.getString("dataset.editor.computedColumns"), //$NON-NLS-1$ IMessageProvider.NONE); // $-NON-NLS-1 // //$NON-NLS-1$ setPageProperties(); computedColumns = ((DataSetHandle) getContainer().getModel()) .getPropertyHandle(DataSetHandle.COMPUTED_COLUMNS_PROP); ; viewer.getViewer().setInput(computedColumns); viewer.getViewer().getTable().select(0); } catch (BirtException e) { DataSetExceptionHandler.handle(e); } } /** * Refresh columns meta data * @throws BirtException */ private void refreshColumnNames() throws BirtException { ((DataSetEditor) this.getContainer()).getCurrentItemModel(true); } private void addListeners() { viewer.getNewButton().addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { doNew(); } }); viewer.getEditButton().addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { doEdit(); } }); viewer.getViewer().getTable().addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent e) { doEdit(); } }); viewer.getViewer().getTable().addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { } public void keyReleased(KeyEvent e) { if (e.keyCode == SWT.DEL) { setPageProperties(); } } }); addRemoveListeners(); viewer.getViewer().addSelectionChangedListener(new ViewerSelectionListener()); } private void addRemoveListeners() { viewer.getRemoveButton().addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { setPageProperties(); updateColumnsOfDataSetHandle(); } public void widgetDefaultSelected(SelectionEvent e) { } }); viewer.getRemoveMenuItem().addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { setPageProperties(); updateColumnsOfDataSetHandle(); } public void widgetDefaultSelected(SelectionEvent e) { } }); viewer.getRemoveAllMenuItem().addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { setPageProperties(); updateColumnsOfDataSetHandle(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); } private void doNew() { doEdit(new ComputedColumn(), true); } private void doEdit() { int index = viewer.getViewer().getTable().getSelectionIndex(); if (index == -1) return; ComputedColumnHandle handle = (ComputedColumnHandle) viewer.getViewer().getTable().getItem(index).getData(); doEdit(handle, false); } protected void doEdit(Object structureOrHandle, boolean applyAnalysis) { ComputedColumnInputDialog dlg = new ComputedColumnInputDialog(structureOrHandle, applyAnalysis); if (dlg.open() == Window.OK) { updateComputedColumn(structureOrHandle); } } protected void updateComputedColumn(Object structureOrHandle) { if (structureOrHandle instanceof ComputedColumn) { try { computedColumns.addItem((ComputedColumn) structureOrHandle); viewer.getViewer().refresh(); } catch (SemanticException e) { ExceptionHandler.handle(e); } } else { viewer.getViewer().update(structureOrHandle, null); } if (validateAllComputedColumns()) getContainer().setMessage(Messages.getString("dataset.editor.computedColumns"), //$NON-NLS-1$ IMessageProvider.NONE); } protected void updateColumnCache() { try { DataSetUIUtil.updateColumnCache((DataSetHandle) getContainer().getModel()); } catch (SemanticException e) { ExceptionHandler.handle(e); } } protected ComputedColumn getStructure(Object structureOrHandle) { ComputedColumn structure = null; if (structureOrHandle instanceof ComputedColumn) { structure = (ComputedColumn) structureOrHandle; } else { structure = (ComputedColumn) ((ComputedColumnHandle) structureOrHandle).getStructure(); } return structure; } protected final String getTypeName(String typeDisplayName) { for (int i = 0; i < dataTypes.length; i++) { if (dataTypes[i].getDisplayName().equals(typeDisplayName)) return dataTypes[i].getName(); } return dataTypes[0].getName(); } protected final String getTypeDisplayName(String typeName) { for (int i = 0; i < dataTypes.length; i++) { if (dataTypes[i].getName().equals(typeName)) { return dataTypes[i].getDisplayName(); } } return typeName; } private void setToolTips() { viewer.getNewButton().setToolTipText(Messages.getString("DataSetComputedColumnsPage.toolTipText.New"));//$NON-NLS-1$ viewer.getEditButton().setToolTipText(Messages.getString("DataSetComputedColumnsPage.toolTipText.Edit"));//$NON-NLS-1$ viewer.getRemoveButton() .setToolTipText(Messages.getString("DataSetComputedColumnsPage.toolTipText.Remove"));//$NON-NLS-1$ viewer.getUpButton().setToolTipText(Messages.getString("DataSetComputedColumnsPage.toolTipText.Up"));//$NON-NLS-1$ viewer.getDownButton().setToolTipText(Messages.getString("DataSetComputedColumnsPage.toolTipText.Down"));//$NON-NLS-1$ } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.ui.dialogs.properties.AbstractDescriptionPropertyPage#getPageDescription() */ public String getPageDescription() { return Messages.getString("DataSetComputedColumnsPage.description"); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.ui.dialogs.properties.AbstractPropertyPage#performOk() */ public boolean performOk() { if (validateAllComputedColumns()) { return super.performOk(); } return false; } private class TableProvider implements ITableLabelProvider { /* * (non-Javadoc) * * @see * org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java * .lang.Object, int) */ public Image getColumnImage(Object element, int columnIndex) { return null; } /* * (non-Javadoc) * * @see * org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java. * lang.Object, int) */ public String getColumnText(Object element, int columnIndex) { String value = null; ComputedColumn computedColumn = getStructure(element); try { switch (columnIndex) { case 0: { value = computedColumn.getName(); break; } case 1: { value = getTypeDisplayName(computedColumn.getDataType()); break; } case 2: { // fetch the first argument as the expression value for // backward capability ComputedColumnHandle handle = (ComputedColumnHandle) computedColumn.getHandle(computedColumns); Iterator iterator = handle.argumentsIterator(); if (iterator.hasNext()) { AggregationArgumentHandle argHandle = (AggregationArgumentHandle) iterator.next(); value = argHandle.getValue(); } if (value == null) { value = computedColumn.getExpression(); } break; } case 3: { value = computedColumn.getAggregateFunction(); IAggrFunction aggrFunc = aggregationManager.getAggregation(value); value = aggrFunc != null ? aggrFunc.getDisplayName() : value; break; } case 4: { value = computedColumn.getFilterExpression(); break; } } } catch (Exception e) { ExceptionHandler.handle(e); } return (value == null ? "" : value); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see * org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse * .jface.viewers.ILabelProviderListener) */ public void addListener(ILabelProviderListener listener) { } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() */ public void dispose() { } /* * (non-Javadoc) * * @see * org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java * .lang.Object, java.lang.String) */ public boolean isLabelProperty(Object element, String property) { return false; } /* * (non-Javadoc) * * @see * org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse * .jface.viewers.ILabelProviderListener) */ public void removeListener(ILabelProviderListener listener) { } } private class ViewerSelectionListener implements ISelectionChangedListener { /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ public void selectionChanged(SelectionChangedEvent event) { setPageProperties(); } } /** * Depending on the Computed the properties of various controls on this page * are set */ private void setPageProperties() { viewer.updateButtons(); validateAllComputedColumns(); } /** * Update the computed columns after removing an established one and cache * the updated DataSetViewData[] * */ private void updateColumnsOfDataSetHandle() { DataSetHandle dataSet = ((DataSetEditor) getContainer()).getHandle(); DataSetViewData[] items; try { items = DataSetProvider.getCurrentInstance().getColumns(dataSet, false, true); int inexistence = 0; for (int i = 0; i < items.length; i++) { boolean exist = false; if (items[i].isComputedColumn()) { Iterator iter = computedColumns.iterator(); while (iter.hasNext()) { ComputedColumn computedColumn = null; Object obj = iter.next(); if (obj instanceof ComputedColumnHandle) { computedColumn = (ComputedColumn) ((ComputedColumnHandle) obj).getStructure(); } if (computedColumn != null && items[i].getName().equals(computedColumn.getName())) { exist = true; } } if (!exist) { items[i] = null; inexistence++; } } } if (inexistence == 0) return; DataSetViewData[] existItems = new DataSetViewData[items.length - inexistence]; int index = 0; for (int i = 0; i < items.length; i++) { if (items[i] != null) { existItems[index] = items[i]; index++; } } DataSetProvider.getCurrentInstance().updateColumnsOfDataSetHandle(dataSet, existItems); } catch (BirtException e) { DataSetExceptionHandler.handle(e); } } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.ui.dialogs.properties.IPropertyPage#getToolTip() */ public String getToolTip() { return Messages.getString("DataSetComputedColumnsPage.ComputedColumns.Tooltip"); //$NON-NLS-1$ } public boolean canLeave() { if (validateAllComputedColumns()) { updateColumnCache(); return true; } return false; } /* * Exam whether all registered computed columns are valid. Set the message * of dialog as appropriated */ private boolean validateAllComputedColumns() { if (computedColumns != null) { Iterator iter = computedColumns.iterator(); if (iter != null) { while (iter.hasNext()) { Object o = iter.next(); ComputedColumn computedColumn = null; if (o instanceof ComputedColumnHandle) { computedColumn = (ComputedColumn) ((ComputedColumnHandle) o).getStructure(); } else { computedColumn = (ComputedColumn) o; } if (!validateSingleColumn(computedColumn)) return false; } } } return true; } /* * Exam whether one computed column is valid or not. */ private boolean validateSingleColumn(ComputedColumn computedColumn) { if (computedColumn.getName() == null || computedColumn.getName().trim().length() == 0) { getContainer().setMessage(Messages.getFormattedString("dataset.editor.error.missingComputedColumnName", //$NON-NLS-1$ new Object[] { computedColumn.getName() }), IMessageProvider.ERROR); return false; } Iterator iter = ((DataSetHandle) getContainer().getModel()) .getPropertyHandle(DataSetHandle.COLUMN_HINTS_PROP).iterator(); while (iter.hasNext()) { ColumnHintHandle hint = (ColumnHintHandle) iter.next(); if (!computedColumn.getName().equals(hint.getColumnName()) && computedColumn.getName().equals(hint.getAlias())) { getContainer().setMessage( Messages.getFormattedString("dataset.editor.error.computedColumnNameAlreadyUsed", //$NON-NLS-1$ new Object[] { computedColumn.getName() }), IMessageProvider.ERROR); return false; } } return true; } /** * */ protected static class DummyParamDefn implements IParameterDefn { String name; String displayName; String description = "";//$NON-NLS-1$ boolean isDataField; boolean isOptional; /** * * @param name * @param displayName * @param isOptional * @param isDataField */ public DummyParamDefn(String name, String displayName, boolean isOptional, boolean isDataField) { this.name = name; this.displayName = displayName; this.isDataField = isDataField; this.isOptional = isOptional; } /* * (non-Javadoc) * * @see org.eclipse.birt.data.engine.api.aggregation.IParameterDefn#getDescription() */ public String getDescription() { return description; } /* * (non-Javadoc) * * @see org.eclipse.birt.data.engine.api.aggregation.IParameterDefn#getDisplayName() */ public String getDisplayName() { return displayName; } /* * (non-Javadoc) * * @see org.eclipse.birt.data.engine.api.aggregation.IParameterDefn#isDataField() */ public boolean isDataField() { return isDataField; } /* * (non-Javadoc) * * @see org.eclipse.birt.data.engine.api.aggregation.IParameterDefn#isOptional() */ public boolean isOptional() { return isOptional; } /* * (non-Javadoc) * * @see org.eclipse.birt.data.engine.api.aggregation.IParameterDefn#supportDataType(int) */ public boolean supportDataType(int dataType) { return true; } /* * (non-Javadoc) * * @see org.eclipse.birt.data.engine.api.aggregation.IParameterDefn#getName() */ public String getName() { return name; } } protected class ComputedColumnInputDialog extends PropertyHandleInputDialog { private static final String BLANK = "";//$NON-NLS-1$ private Text txtColumnName = null; private Combo cmbDataType = null; private Combo cmbAggregation = null; private Label lblFilter = null; private Text txtFilter = null; private Button btnFilter = null; private String columnName = null; private Text[] txtParams = null; // parameter controls private IAggrFunction[] functions = null; private Composite parameterContainer; private Composite composite; private String lastExpression; private Label firstLabel; private int maxWidth; /** * * @param structureOrHandle */ private ComputedColumnInputDialog(Object structureOrHandle, boolean applyAnalysis) { super(structureOrHandle); populateFunctions(); } public void create() { super.create(); validateSyntax(); } protected void setSystemHelp(Composite composite) { Utility.setSystemHelp(composite, IHelpConstants.CONEXT_ID_DATASET_COMPUTEDCOLUMNS_DIALOG); } /** * */ private void populateFunctions() { List aggrList = aggregationManager.getAggregations(AggregationManager.AGGR_TABULAR); functions = new IAggrFunction[aggrList.size()]; aggrList.toArray(functions); } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.data.ui.dataset.PropertyHandleInputDialog#createCustomControls(org.eclipse.swt.widgets.Composite) */ protected void createCustomControls(Composite parent) { this.composite = parent; createTextCell(parent, COLUMN_NAME_INDEX); createComboBoxCell(parent, DATA_TYPE_INDEX); createAggrListCell(parent, AGGREGATION_INDEX); createParameterContainer(parent); createFilterCell(parent, FILTER_INDEX); handleAggrSelectEvent(getStructureOrHandle() instanceof Structure); createSpaceForResize(parent); } /** * @param parent */ private void createSpaceForResize(Composite parent) { Label space = ControlProvider.createLabel(parent, null); space.setLayoutData(ControlProvider.getGridDataWithHSpan(3)); space = ControlProvider.createLabel(parent, null); space.setLayoutData(ControlProvider.getGridDataWithHSpan(3)); space = ControlProvider.createLabel(parent, null); space.setLayoutData(ControlProvider.getGridDataWithHSpan(3)); space = ControlProvider.createLabel(parent, null); space.setLayoutData(ControlProvider.getGridDataWithHSpan(3)); } /** * * @param parent */ private void createParameterContainer(Composite parent) { parameterContainer = new Composite(parent, SWT.NONE); GridData gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); gridData.horizontalIndent = 0; gridData.horizontalSpan = 3; gridData.exclude = true; parameterContainer.setLayoutData(gridData); GridLayout layout = new GridLayout(); // layout.horizontalSpacing = layout.verticalSpacing = 0; layout.marginWidth = layout.marginHeight = 0; layout.numColumns = 3; parameterContainer.setLayout(layout); } /** * * @param parent * @param index */ private void createTextCell(Composite parent, final int index) { firstLabel = ControlProvider.createLabel(parent, dialogLabels[index]); this.maxWidth = computeMaxWidth(firstLabel); txtColumnName = ControlProvider.createText(parent, (String) getProperty(getStructureOrHandle(), cellProperties[index])); txtColumnName.setLayoutData(ControlProvider.getGridDataWithHSpan(2)); columnName = txtColumnName.getText(); txtColumnName.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { validateSyntax(); } }); } /** * * @param parent * @param index */ private void createComboBoxCell(Composite parent, final int index) { Label label = ControlProvider.createLabel(parent, dialogLabels[index]); this.maxWidth = computeMaxWidth(label); cmbDataType = ControlProvider.createCombo(parent, SWT.READ_ONLY); cmbDataType.setLayoutData(ControlProvider.getGridDataWithHSpan(2)); cmbDataType.setVisibleItemCount(30); populateDataTypeComboItems(); cmbDataType.select(Utility.findIndex(cmbDataType.getItems(), getTypeDisplayName((String) getProperty(getStructureOrHandle(), cellProperties[index])))); cmbDataType.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { validateSyntax(); } }); } /** * */ private void populateDataTypeComboItems() { Map<String, String> indexMap = new HashMap<String, String>(); String[] dataTypeDisplayNames = new String[dataTypes.length]; for (int i = 0; i < dataTypes.length; i++) { dataTypeDisplayNames[i] = dataTypes[i].getDisplayName(); indexMap.put(dataTypeDisplayNames[i], dataTypes[i].getName()); } Arrays.sort(dataTypeDisplayNames); cmbDataType.setItems(dataTypeDisplayNames); for (int i = 0; i < dataTypeDisplayNames.length; i++) { String name = (String) indexMap.get(dataTypeDisplayNames[i]); cmbDataType.setData(name, Integer.valueOf(i)); } } /** * * @param parent * @param index */ private void createAggrListCell(final Composite parent, final int index) { Label label = ControlProvider.createLabel(parent, dialogLabels[index]); this.maxWidth = computeMaxWidth(label); cmbAggregation = ControlProvider.createCombo(parent, SWT.READ_ONLY); cmbAggregation.setLayoutData(ControlProvider.getGridDataWithHSpan(2)); cmbAggregation.setVisibleItemCount(30); cmbAggregation.add(BLANK); cmbAggregation.setData(BLANK, Integer.valueOf(0)); for (int i = 0; i < functions.length; i++) { cmbAggregation.add(functions[i].getDisplayName()); cmbAggregation.setData(functions[i].getName(), Integer.valueOf(i + 1)); } String aggrFuncName = (String) getProperty(getStructureOrHandle(), cellProperties[index]); int selectionIndex = getAggrFuncIndex(aggrFuncName); cmbAggregation.select(selectionIndex); cmbAggregation .setToolTipText(selectionIndex > 0 ? functions[selectionIndex - 1].getDescription() : BLANK); cmbAggregation.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { handleAggrSelectEvent(true); validateSyntax(); updateFilterUIStatus(); } }); } private int computeMaxWidth(Label label) { int widthHint = label.computeSize(-1, -1).x - label.getBorderWidth(); return widthHint > this.maxWidth ? widthHint : this.maxWidth; } /** * */ private void handleAggrSelectEvent(boolean resetDataType) { disposeOldParameterUI(); IAggrFunction function = getSelectedFunction(); IParameterDefn[] params = null; if (function != null) { params = function.getParameterDefn(); } else { params = new IParameterDefn[] { new DummyParamDefn(cellLabels[EXPRESSION_INDEX], dialogLabels[EXPRESSION_INDEX], false, true) }; } if (params.length > 0) { showParameterUISection(); createParameterUISection(params); } else { hideParameterUISection(); } if (resetDataType) updateDataTypeCombo(); parameterContainer.layout(); composite.layout(); } /** * @param params */ private void createParameterUISection(IParameterDefn[] params) { txtParams = new Text[params.length]; for (int i = 0; i < params.length; i++) { IParameterDefn param = params[i]; Label paramLabel = new Label(parameterContainer, SWT.NONE | SWT.WRAP); paramLabel.setText(Utility.getNonNullString(param.getDisplayName())); GridData gd = new GridData(); this.maxWidth = computeMaxWidth(paramLabel); gd.widthHint = this.maxWidth; paramLabel.setLayoutData(gd); Composite composite = ControlProvider.getDefaultComposite(parameterContainer); if (param.isDataField()) { String text = BLANK; if (lastExpression != null) { text = lastExpression; } else { text = (String) getProperty(getStructureOrHandle(), cellProperties[EXPRESSION_INDEX]); } txtParams[i] = ControlProvider.createText(composite, text); final Text txtDataField = txtParams[i]; txtDataField.setLayoutData(ControlProvider.getGridDataWithHSpan(1)); txtDataField.setData(params[i]); txtDataField.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { lastExpression = txtDataField.getText(); validateSyntax(); } }); } else { Text txtArgument = ControlProvider.createText(composite, null); txtArgument.setLayoutData(ControlProvider.getGridDataWithHSpan(1)); txtArgument.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { validateSyntax(); } }); txtParams[i] = txtArgument; } txtParams[i].setToolTipText(param.getDescription()); createExpressionButton(composite, txtParams[i]); } updateLabelWidth(); // update parameters' values from ComputedColumnHandle updateParametersText(params); } private void updateLabelWidth() { GridData gd = new GridData(); gd.widthHint = this.maxWidth; firstLabel.setLayoutData(gd); } /** * */ private void updateDataTypeCombo() { final IAggrFunction aggrFunc = getSelectedFunction(); if (aggrFunc != null) { String dataType = DataAdapterUtil.adapterToModelDataType(aggrFunc.getDataType()); cmbDataType.setText(getTypeDisplayName(dataType)); } } /** * */ private void disposeOldParameterUI() { Control[] children = parameterContainer.getChildren(); for (int i = 0; i < children.length; i++) { children[i].dispose(); } } /** * */ private void hideParameterUISection() { ((GridData) parameterContainer.getLayoutData()).heightHint = 0; } /** * */ private void showParameterUISection() { ((GridData) parameterContainer.getLayoutData()).exclude = false; ((GridData) parameterContainer.getLayoutData()).heightHint = SWT.DEFAULT; } /** * update the arguments' UI elements from the compute column handle. */ private void updateParametersText(IParameterDefn[] params) { if (params.length == 0) return; Object handle = getStructureOrHandle(); if (handle instanceof ComputedColumnHandle) { ComputedColumnHandle cHandle = (ComputedColumnHandle) handle; String expr = cHandle.getExpression(); if (expr != null) { txtParams[0].setText(expr); } else { Iterator itr = cHandle.argumentsIterator(); List argHandles = new ArrayList(); while (itr.hasNext()) { argHandles.add(itr.next()); } int i = 0; if (params[0].isDataField() && lastExpression != null) { txtParams[0].setText(lastExpression); i++; } for (; i < params.length; i++) { AggregationArgumentHandle argHandle = null; if (i < argHandles.size()) { argHandle = (AggregationArgumentHandle) argHandles.get(i); } final String value = argHandle != null ? argHandle.getValue() : null; txtParams[i].setText(value != null ? value : BLANK); } } } } /** * * @param aggrFuncName * @return */ private int getAggrFuncIndex(String aggrFuncName) { Integer selectionIndex = (Integer) cmbAggregation.getData(aggrFuncName != null ? aggrFuncName : BLANK); return selectionIndex != null ? selectionIndex.intValue() : 0; } /** * @return whether filter component should be enabled */ private boolean needFilter() { if (cmbAggregation.getText() != null && cmbAggregation.getText().trim().length() > 0) { return true; } else { return false; } } /** * Update the Filter component status */ private void updateFilterUIStatus() { if (needFilter()) { txtFilter.setEnabled(true); lblFilter.setEnabled(true); btnFilter.setEnabled(true); } else { txtFilter.setText(BLANK); txtFilter.setEnabled(false); lblFilter.setEnabled(false); btnFilter.setEnabled(false); } } /** * * @param parent * @param index */ private void createFilterCell(Composite parent, final int index) { lblFilter = ControlProvider.createLabel(parent, dialogLabels[index]); Composite composite = ControlProvider.getDefaultComposite(parent); Object handle = this.getStructureOrHandle(); if (handle instanceof ComputedColumnHandle) { ComputedColumnHandle cHandle = (ComputedColumnHandle) handle; txtFilter = ControlProvider.createText(composite, cHandle.getFilterExpression()); } else txtFilter = ControlProvider.createText(composite, (String) getProperty(getStructureOrHandle(), cellProperties[index])); txtFilter.setLayoutData(ControlProvider.getGridDataWithHSpan(1)); txtFilter.setEnabled(false); txtFilter.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { validateSyntax(); } }); SelectionAdapter listener = new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { ExpressionBuilder expressionBuilder = new ExpressionBuilder(txtFilter.getText()); expressionBuilder.setExpressionProvier( new DataSetExpressionProvider((DesignElementHandle) getContainer().getModel())); String expression = txtFilter == null ? null : txtFilter.getText(); setExprBuilderDefaultSelection(expressionBuilder, expression); if (expressionBuilder.open() == OK) { txtFilter.setText(expressionBuilder.getResult().trim()); } } }; btnFilter = ControlProvider.createButton(composite, SWT.PUSH, listener); updateFilterUIStatus(); } /** * * @param composite * @param text * @return */ private Button createExpressionButton(Composite composite, final Text text) { SelectionAdapter listener = new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { ExpressionBuilder expressionBuilder = new ExpressionBuilder(text.getText()); expressionBuilder.setExpressionProvier( new DataSetExpressionProvider((DesignElementHandle) getContainer().getModel())); String expression = (txtParams.length > 0 && txtParams[0] != null) ? txtParams[0].getText() : null; setExprBuilderDefaultSelection(expressionBuilder, expression); if (expressionBuilder.open() == OK) { text.setText(expressionBuilder.getResult().trim()); } } }; return ControlProvider.createButton(composite, SWT.PUSH, listener); } /** * Set the default selection in the expression builder * * @param expressionBuilder */ private void setExprBuilderDefaultSelection(ExpressionBuilder expressionBuilder, String expression) { Object[] selection = null; String dataSets = DataSetExpressionProvider.DATASETS; DataSetHandle dsHandle = (DataSetHandle) getContainer().getModel(); Object handle = this.getStructureOrHandle(); if (handle instanceof ComputedColumnHandle) { try { String columnName = ExpressionUtil.getColumnBindingName(expression); DataSetViewData viewData = findDataSetViewData(columnName, dsHandle); selection = new Object[] { dataSets, dsHandle, viewData }; } catch (BirtException e) { selection = new Object[] { dataSets, dsHandle }; } } else { selection = new Object[] { dataSets, dsHandle }; } expressionBuilder.setDefaultSelection(selection); } /** * Finds the DataSetViewData instance according to the given column name * * @param columnName * @param handle * @return */ private DataSetViewData findDataSetViewData(String columnName, DataSetHandle handle) { if (columnName == null || columnName.trim().length() == 0) { return null; } try { DataSetViewData[] items = DataSetProvider.getCurrentInstance().getColumns(handle, false, true); for (int i = 0; i < items.length; i++) { if (columnName.equals(items[i].getName())) { return items[i]; } } } catch (BirtException e) { DataSetExceptionHandler.handle(e); } return null; } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.data.ui.dataset.PropertyHandleInputDialog#validateSemantics(java.lang.Object) */ protected IStatus validateSemantics(Object structureOrHandle) { AggregationArgument aggrArgument = null; String columnName = txtColumnName.getText(); String dataTypeName = getTypeName(cmbDataType.getText()); IAggrFunction aggrFunc = getSelectedFunction(); try { String funcName = aggrFunc != null ? aggrFunc.getName() : BLANK; String filter = this.txtFilter.getText(); if (structureOrHandle instanceof ComputedColumnHandle) { ComputedColumnHandle handle = (ComputedColumnHandle) structureOrHandle; handle.setName(columnName); handle.setDataType(dataTypeName); handle.setAggregateFunction(funcName); if (aggrFunc == null) { handle.setExpression(txtParams[0].getText().trim()); } else { handle.setExpression(BLANK); handle.setFilterExpression(filter); handle.clearArgumentList(); IParameterDefn[] params = aggrFunc.getParameterDefn(); for (int i = 0; i < params.length; i++) { if (txtParams[i].getText().trim().length() == 0) continue; aggrArgument = StructureFactory.createAggregationArgument(); aggrArgument.setName(params[i].getName()); aggrArgument.setValue(txtParams[i].getText().trim()); handle.addArgument(aggrArgument); } } } else if (structureOrHandle instanceof ComputedColumn) { ComputedColumn handle = (ComputedColumn) structureOrHandle; handle.setName(columnName); handle.setDataType(dataTypeName); handle.setAggregateFunction(funcName); if (aggrFunc == null) { handle.setExpression(txtParams[0].getText().trim()); } else { handle.setExpression(BLANK); handle.setFilterExpression(filter); IParameterDefn[] params = aggrFunc.getParameterDefn(); for (int i = 0; i < params.length; i++) { if (txtParams[i].getText().trim().length() == 0) continue; aggrArgument = StructureFactory.createAggregationArgument(); aggrArgument.setName(params[i].getName()); aggrArgument.setValue(txtParams[i].getText().trim()); handle.addArgument(aggrArgument); } } updateComputedColumns(handle); } } catch (Exception e) { Status status = new Status(IStatus.ERROR, ReportPlugin.REPORT_UI, BLANK, e); return status; } return getOKStatus(); } /** * * @return */ private IAggrFunction getSelectedFunction() { int index = cmbAggregation.getSelectionIndex(); return index > 0 ? functions[index - 1] : null; } /** * Update the computed columns after adding a new column and cache the * updated DataSetViewData[] * */ private void updateComputedColumns(ComputedColumn handle) { try { DataSetHandle dataSet = ((DataSetEditor) getContainer()).getHandle(); DataSetViewData[] items = DataSetProvider.getCurrentInstance().getColumns(dataSet, false, true); int count = items.length; DataSetViewData[] newItems = new DataSetViewData[count + 1]; System.arraycopy(items, 0, newItems, 0, count); newItems[count] = new DataSetViewData(); newItems[count].setName(handle.getName()); newItems[count].setDataTypeName(handle.getDataType()); newItems[count].setAlias(handle.getDisplayName()); newItems[count].setComputedColumn(true); newItems[count].setPosition(count + 1); newItems[count].setDataType(DataAdapterUtil.adaptModelDataType(handle.getDataType())); DataSetProvider.getCurrentInstance().updateColumnsOfDataSetHandle(dataSet, newItems); } catch (BirtException e) { DataSetExceptionHandler.handle(e); } } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.data.ui.dataset.PropertyHandleInputDialog#validateSyntax(java.lang.Object) */ protected IStatus validateSyntax(Object structureOrHandle) { try { // duplicated columnName check if (!isUniqueColumnName()) return getMiscStatus(IStatus.ERROR, Messages.getString("DataSetComputedColumnsPage.duplicatedName")); //$NON-NLS-1$ // blankProperty check if (isBlankProperty(txtColumnName.getText())) return getBlankPropertyStatus(dialogLabels[COLUMN_NAME_INDEX]); if (isBlankProperty(cmbDataType.getText())) return getBlankPropertyStatus(dialogLabels[DATA_TYPE_INDEX]); //ColumnName is number if (isNumeric(txtColumnName.getText())) { return getMiscStatus(IStatus.ERROR, Messages.getString("DataSetComputedColumnsPage.numberName")); } // if ( expression!=null && isBlankProperty( expression.getText( ) ) ) // { // String funcName = getSelectedFunction( ).getName( ); // if ( isFunctionCount( funcName ) == false ) // return getBlankPropertyStatus( cellLabels[EXPRESSION_INDEX] ); // } // validate arguments IAggrFunction aggrFunc = getSelectedFunction(); if (aggrFunc != null) { IParameterDefn[] paramDefns = aggrFunc.getParameterDefn(); for (int i = 0; i < paramDefns.length; i++) { if (!paramDefns[i].isOptional() && isBlankProperty(txtParams[i].getText())) { return getBlankPropertyStatus(paramDefns[i].getDisplayName()); } } } else if (txtParams != null && isBlankProperty(txtParams[0].getText())) { return getBlankPropertyStatus(dialogLabels[EXPRESSION_INDEX]); } if (cmbAggregation != null && cmbAggregation.getText().trim().length() > 0 && !checkExpressionBindingFields()) { return getMiscStatus(IStatus.ERROR, Messages.getString( "DataSetComputedColumnsPage.InputDialog.message.error.AggregationExpression")); //$NON-NLS-1$ } } catch (BirtException e) { e.printStackTrace(); } return getOKStatus(); } /** * If text is a decimal presentation of int32 value, then text is index. * In this case return true and make send out error message. Otherwise * return false means the column name is right. */ private boolean isNumeric(String text) { long indexTest = indexFromString(text); if (indexTest >= 0) { return true; } return false; } private long indexFromString(String str) { // The length of the decimal string representation of // Integer.MAX_VALUE, 2147483647 final int MAX_VALUE_LENGTH = 10; int len = str.length(); if (len > 0) { int i = 0; boolean negate = false; int c = str.charAt(0); if (c == '-') { if (len > 1) { c = str.charAt(1); i = 1; negate = true; } } c -= '0'; if (0 <= c && c <= 9 && len <= (negate ? MAX_VALUE_LENGTH + 1 : MAX_VALUE_LENGTH)) { // Use negative numbers to accumulate index to handle // Integer.MIN_VALUE that is greater by 1 in absolute value // then Integer.MAX_VALUE int index = -c; int oldIndex = 0; i++; if (index != 0) { // Note that 00, 01, 000 etc. are not indexes while (i != len && 0 <= (c = str.charAt(i) - '0') && c <= 9) { oldIndex = index; index = 10 * index - c; i++; } } // Make sure all characters were consumed and that it // couldn't // have overflowed. if (i == len && (oldIndex > (Integer.MIN_VALUE / 10) || (oldIndex == (Integer.MIN_VALUE / 10) && c <= (negate ? -(Integer.MIN_VALUE % 10) : (Integer.MAX_VALUE % 10))))) { return 0xFFFFFFFFL & (negate ? index : -index); } } } return -1L; } private boolean checkExpressionBindingFields() throws BirtException { for (int i = 0; i < txtParams.length; i++) { if (txtParams[i].getData() instanceof IParameterDefn) { IParameterDefn paramDefn = (IParameterDefn) txtParams[i].getData(); if (paramDefn.isDataField()) { String expr = txtParams[i].getText(); List columns = ExpressionUtil.extractColumnExpressions(expr, ExpressionUtil.ROW_INDICATOR); columns.addAll(ExpressionUtil.extractColumnExpressions(expr, ExpressionUtil.DATASET_ROW_INDICATOR)); for (int k = 0; k < columns.size(); k++) { String columnName = ((IColumnBinding) columns.get(k)).getResultSetColumnName(); ComputedColumnHandle item = findComputedColumn(columnName); if (item != null && item.getAggregateFunction() != null) { return false; } } } } } return true; } private ComputedColumnHandle findComputedColumn(String name) { if (name == null || name.trim().length() == 0) return null; PropertyHandle properyHandle = ((DataSetEditor) getContainer()).getHandle() .getPropertyHandle(DataSetHandle.COMPUTED_COLUMNS_PROP); if (properyHandle != null) { Iterator iter = properyHandle.iterator(); while (iter.hasNext()) { ComputedColumnHandle computedColumn = (ComputedColumnHandle) iter.next(); if (name.equals(computedColumn.getName())) { return computedColumn; } } } return null; } /** * * @return * @throws BirtException */ private final boolean isUniqueColumnName() throws BirtException { DataSetViewData[] items = DataSetProvider.getCurrentInstance() .getColumns(((DataSetEditor) getContainer()).getHandle(), true); for (int i = 0; i < items.length; i++) { if (!items[i].getName().equals(columnName)) { if (!items[i].isComputedColumn()) { if ((items[i].getAlias() != null && items[i].getAlias().equals(txtColumnName.getText())) || (items[i].getName() != null && items[i].getName().equals(txtColumnName.getText()))) { return false; } } } } Iterator iter = computedColumns.iterator(); if (iter != null) { while (iter.hasNext()) { ComputedColumnHandle handle = (ComputedColumnHandle) iter.next(); if (getStructure(getStructureOrHandle()) != handle.getStructure() && handle.getName().equals(txtColumnName.getText())) { return false; } } } Iterator iter2 = ((DataSetHandle) getContainer().getModel()) .getPropertyHandle(DataSetHandle.COLUMN_HINTS_PROP).iterator(); while (iter2.hasNext()) { ColumnHintHandle hint = (ColumnHintHandle) iter2.next(); if (!hint.getColumnName().equals(columnName)) { if (txtColumnName.getText().equals(hint.getAlias()) || txtColumnName.getText().equals(hint.getColumnName())) { return false; } } } return true; } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.data.ui.dataset.PropertyHandleInputDialog#rollback() */ protected void rollback() { } /* * (non-Javadoc) * * @see org.eclipse.birt.report.designer.data.ui.dataset.PropertyHandleInputDialog#getTitle() */ protected String getTitle() { if (this.getStructureOrHandle() instanceof Structure) { return Messages.getString("DataSetComputedColumnsPage.InputDialog.title.New"); //$NON-NLS-1$ } return Messages.getString("DataSetComputedColumnsPage.InputDialog.title.Edit");//$NON-NLS-1$ } } }