org.pentaho.di.ui.trans.steps.annotation.ModelAnnotationActionPropertiesDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.ui.trans.steps.annotation.ModelAnnotationActionPropertiesDialog.java

Source

/*! ******************************************************************************
 *
 * Pentaho Community Edition Project: data-refinery-pdi-plugin
 *
 * Copyright (C) 2002-2015 by Pentaho : http://www.pentaho.com
 *
 * *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ********************************************************************************/

package org.pentaho.di.ui.trans.steps.annotation;

import org.apache.commons.lang.StringUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableItem;
import org.pentaho.agilebi.modeler.ModelerException;
import org.pentaho.agilebi.modeler.models.annotations.AnnotationType;
import org.pentaho.agilebi.modeler.models.annotations.BlankAnnotation;
import org.pentaho.agilebi.modeler.models.annotations.CreateAttribute;
import org.pentaho.agilebi.modeler.models.annotations.CreateCalculatedMember;
import org.pentaho.agilebi.modeler.models.annotations.CreateDimensionKey;
import org.pentaho.agilebi.modeler.models.annotations.CreateMeasure;
import org.pentaho.agilebi.modeler.models.annotations.LinkDimension;
import org.pentaho.agilebi.modeler.models.annotations.ModelAnnotation;
import org.pentaho.agilebi.modeler.models.annotations.ModelAnnotationManager;
import org.pentaho.agilebi.modeler.models.annotations.ModelProperty;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.steps.annotation.ModelAnnotationMeta;
import org.pentaho.di.ui.core.PropsUI;
import org.pentaho.di.ui.core.widget.ColumnInfo;
import org.pentaho.di.ui.core.widget.ComboValuesSelectionListener;
import org.pentaho.di.ui.core.widget.TableView;
import org.pentaho.metadata.model.concept.types.AggregationType;
import org.pentaho.metastore.api.IMetaStore;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;

/**
 * @author Rowell Belen
 */
public class ModelAnnotationActionPropertiesDialog extends ModelAnnotationActionDialog {

    protected Composite contentPanel;

    private Label wField;
    private CCombo wActionList;
    private ColumnInfo[] ciFields;
    private ComboValuesSelectionListener comboValuesSelectionListener;
    private TableView wProperties;

    private AnnotationType annotationType;
    private OptionsResolver optionsResolver;

    public ModelAnnotationActionPropertiesDialog(Shell parent, ModelAnnotationMeta baseStepMeta,
            TransMeta transMeta, String stepname, IMetaStore metaStore) {
        super(parent, baseStepMeta, transMeta, stepname, metaStore);
        optionsResolver = new OptionsResolver();
    }

    @Override
    protected void initializeListeners() {

        super.initializeListeners();

        comboValuesSelectionListener = new ComboValuesSelectionListener() {
            @Override
            public String[] getComboValues(TableItem tableItem, int rowNr, int colNr) {
                try {

                    String name = tableItem.getText(1);

                    if (StringUtils.isNotBlank(name)) {

                        // Use currently loaded model in the table
                        final AnnotationType at = annotationType;
                        final Class propertyClassType = at.getModelPropertyNameClassType(name);

                        // Parent options
                        if (name.equals(CreateAttribute.PARENT_ATTRIBUTE_NAME)) {
                            List<String> names = new ArrayList<String>();
                            for (ModelAnnotation m : getModifiedModelAnnotations()) {
                                if (ModelAnnotation.Type.CREATE_ATTRIBUTE.equals(m.getType())) {
                                    if (StringUtils.isNotBlank(m.getAnnotation().getName())) {
                                        // Do not include self
                                        if (!StringUtils.equals(at.getName(), m.getAnnotation().getName())) {
                                            names.add(m.getAnnotation().getName()); // return display names
                                        }
                                    }
                                }
                            }
                            return names.toArray(new String[names.size()]);
                        }

                        // Dimension options
                        if (name.equals(CreateAttribute.DIMENSION_NAME)) {
                            LinkedHashSet<String> names = new LinkedHashSet<String>();
                            for (ModelAnnotation<?> m : getModifiedModelAnnotations()) {
                                // Do not include self
                                if (m.getAnnotation() != null && StringUtils.isNotBlank(m.getAnnotation().getName())
                                        && !at.equals(m.getAnnotation())) {
                                    // return dimension names
                                    if (ModelAnnotation.Type.CREATE_ATTRIBUTE.equals(m.getType())) {
                                        names.add(((CreateAttribute) m.getAnnotation()).getDimension());
                                    } else if (ModelAnnotation.Type.CREATE_DIMENSION_KEY.equals(m.getType())) {
                                        names.add(((CreateDimensionKey) m.getAnnotation()).getDimension());
                                    }
                                }
                            }
                            return names.toArray(new String[names.size()]);
                        }

                        // Hierarchy options
                        if (name.equals(CreateAttribute.HIERARCHY_NAME)) {
                            LinkedHashSet<String> names = new LinkedHashSet<String>();
                            for (ModelAnnotation m : getModifiedModelAnnotations()) {
                                if (ModelAnnotation.Type.CREATE_ATTRIBUTE.equals(m.getType())) {
                                    if (StringUtils.isNotBlank(m.getAnnotation().getName())) {
                                        // Do not include self
                                        if (!StringUtils.equals(at.getName(), m.getAnnotation().getName())) {
                                            String hierarchy = ((CreateAttribute) m.getAnnotation()).getHierarchy();
                                            if (StringUtils.isNotBlank(hierarchy)) {
                                                names.add(hierarchy);
                                            }
                                        }
                                    }
                                }
                            }
                            return names.toArray(new String[names.size()]);
                        }

                        // Time Type options
                        if (name.equals(CreateAttribute.TIME_TYPE_NAME) && (propertyClassType != null)
                                && propertyClassType.equals(ModelAnnotation.TimeType.class)) {
                            return ModelAnnotation.TimeType.names();
                        }

                        // GeoType options
                        if (name.equals(CreateAttribute.GEO_TYPE_NAME) && (propertyClassType != null)
                                && propertyClassType.equals(ModelAnnotation.GeoType.class)) {
                            return ModelAnnotation.GeoType.names();
                        }

                        // Time Format String options
                        if (name.equals(CreateAttribute.TIME_FORMAT_NAME)) {
                            String timeType = StringUtils
                                    .defaultIfBlank(findTableItemValue(CreateAttribute.TIME_TYPE_NAME), "");
                            return optionsResolver.resolveTimeSourceFormatOptions(timeType);
                        }

                        // Ordinal Field options
                        if (name.equals(CreateAttribute.ORDINAL_FIELD_NAME)) {
                            return optionsResolver.resolveOrdinalFieldOptions(transMeta, stepname,
                                    getModelAnnotation());
                        }

                        // Measure Format String options
                        if (name.equals(CreateMeasure.FORMAT_STRING_NAME)) {
                            return optionsResolver.resolveMeasureFormatOptions();
                        }

                        // AggregationType options
                        if (name.equals(CreateMeasure.AGGREGATE_TYPE_NAME) && (propertyClassType != null)
                                && propertyClassType.equals(AggregationType.class)) {
                            return optionsResolver.resolveAggregationTypeOptions(getValueMeta(), at);
                        }

                        // Boolean Type options
                        if (propertyClassType != null && (propertyClassType.equals(Boolean.class)
                                || propertyClassType.equals(boolean.class))) {
                            return optionsResolver.resolveBooleanOptions();
                        }

                        if (name.equals(LinkDimension.SHARED_DIMENSION_NAME)) {
                            return optionsResolver.resolveSharedDimensions(new ModelAnnotationManager(true),
                                    getMetaStore());
                        }
                    }

                } catch (Exception e) {
                    logError(e.getMessage());
                }

                return new String[0];
            }
        };
    }

    private void createContentPanel(Composite parent) {
        contentPanel = new Composite(parent, SWT.NULL);
        FormData fd = new FormData();
        fd.top = new FormAttachment(0, 0);
        fd.left = new FormAttachment(0, 0);
        fd.right = new FormAttachment(100, 0);
        fd.bottom = new FormAttachment(wBottomHorizontalSeparator, 0);
        contentPanel.setLayoutData(fd);
        contentPanel.setLayout(new FormLayout());
        PropsUI.getInstance().setLook(contentPanel);
    }

    protected Composite getMainComposite() {
        return shell;
    }

    public void createWidgets() {

        createContentPanel(getMainComposite());

        // Create Annotate Field label
        Label wlField = new Label(contentPanel, SWT.LEFT);
        wlField.setText(
                BaseMessages.getString(PKG, "ModelAnnotation.ModelAnnotationActionDialog.AnnotateField.Label"));
        props.setLook(wlField);
        FormData fdlField = new FormData();
        fdlField.left = new FormAttachment(0, LEFT_MARGIN_OFFSET);
        fdlField.top = new FormAttachment(0, margin);
        wlField.setLayoutData(fdlField);

        // Create Annotate Field
        wField = new Label(contentPanel, SWT.LEFT);
        props.setLook(wField);
        FormData fdwField = new FormData();
        fdwField.width = SHELL_MIN_WIDTH;
        fdwField.left = new FormAttachment(0, LEFT_MARGIN_OFFSET);
        fdwField.top = new FormAttachment(wlField, margin);
        wField.setLayoutData(fdwField);

        // ActionList Label
        Label wlActionList = new Label(contentPanel, SWT.RIGHT);
        wlActionList
                .setText(BaseMessages.getString(PKG, "ModelAnnotation.ModelAnnotationActionDialog.Actions.Label"));
        props.setLook(wlActionList);
        FormData fdlActionList = new FormData();
        fdlActionList.left = new FormAttachment(0, LEFT_MARGIN_OFFSET);
        fdlActionList.top = new FormAttachment(wField, margin);
        wlActionList.setLayoutData(fdlActionList);

        // Create Action List
        wActionList = new CCombo(contentPanel, SWT.LEFT | SWT.BORDER);
        wActionList.setText(ModelAnnotation.Type.CREATE_ATTRIBUTE.description()); // default
        wActionList.setToolTipText(
                BaseMessages.getString(PKG, "ModelAnnotation.ModelAnnotationActionDialog.Actions.Label"));
        props.setLook(wActionList);
        FormData fdActionList = new FormData();
        fdActionList.left = new FormAttachment(0, LEFT_MARGIN_OFFSET);
        fdActionList.top = new FormAttachment(wlActionList, margin);
        wActionList.setLayoutData(fdActionList);

        // Create Properties Table
        createPropertiesTable(wActionList);

        // Add Listeners
        wActionList.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(ModifyEvent modifyEvent) {

                if (StringUtils.isBlank(wActionList.getText())) {
                    return;
                }

                if (getModelAnnotation().getAnnotation() != null && getModelAnnotation().getAnnotation().getType()
                        .description().equals(wActionList.getText())) {
                    loadAnnotationProperties(getModelAnnotation().getAnnotation());
                } else {
                    AnnotationType annotationType = createAnnotationType();
                    if (annotationType != null) {
                        loadAnnotationProperties(annotationType);
                    }
                }
            }
        });
    }

    private void createPropertiesTable(Control topWidget) {

        int tableCols = 2;
        int rowCount = 0; // TODO

        ciFields = new ColumnInfo[tableCols];
        ciFields[0] = new ColumnInfo(
                BaseMessages.getString(PKG,
                        "ModelAnnotation.ModelAnnotationActionDialog.PropertiesTable.Column.Name"),
                ColumnInfo.COLUMN_TYPE_TEXT, new String[] { "" }, true);
        ciFields[1] = new ColumnInfo(
                BaseMessages.getString(PKG,
                        "ModelAnnotation.ModelAnnotationActionDialog.PropertiesTable.Column.Value"),
                ColumnInfo.COLUMN_TYPE_CCOMBO, new String[] { "" }, false);

        // Add combo values listener
        ciFields[1].setComboValuesSelectionListener(comboValuesSelectionListener);

        // Annotations Table
        wProperties = new TableView(transMeta, contentPanel,
                SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL, ciFields, rowCount,
                lsMod, props);
        FormData fdProperties = new FormData();
        fdProperties.top = new FormAttachment(topWidget, margin + 10);
        fdProperties.left = new FormAttachment(0, LEFT_MARGIN_OFFSET + 2);
        fdProperties.right = new FormAttachment(100, RIGHT_MARGIN_OFFSET);
        fdProperties.bottom = new FormAttachment(100, -10);
        wProperties.setLayoutData(fdProperties);

        // Try to set initial size of the columns
        wProperties.getTable().setSize(SHELL_MIN_WIDTH, SHELL_MIN_HEIGHT);
        int width = (SHELL_MIN_WIDTH - wProperties.getTable().getColumn(0).getWidth()) / 2;
        wProperties.getTable().getColumn(0).setWidth(0); // hide numbers column
        wProperties.getTable().getColumn(1).setWidth(width - 10);
        wProperties.getTable().getColumn(2).setWidth(width - 10);
    }

    private void populateActionList() {
        wActionList.removeAll();
        for (ModelAnnotation.Type annotationType : getAnnotationTypes()) {
            wActionList.add(annotationType.description());
            wActionList.setData(annotationType.description(), annotationType);
        }
    }

    public void populateDialog() {
        populateActionList();
        if (getModelAnnotation() == null) {
            return;
        }

        wField.setText(StringUtils.defaultIfBlank(getModelAnnotation().getField(), ""));

        if (getModelAnnotation().getAnnotation() != null) {
            wActionList.setText(getModelAnnotation().getAnnotation().getType().description());
            if (wActionList.getData(wActionList.getText()) == null) {
                // invalid action
                wActionList.setText("");
            }
        } else {
            wActionList.setText("");
        }

        loadAnnotationProperties(getModelAnnotation().getAnnotation());
    }

    private void loadAnnotationProperties(AnnotationType annotationType) {

        wProperties.clearAll();

        if (annotationType == null) {
            return;
        }

        this.annotationType = annotationType;
        for (ModelProperty prop : annotationType.getModelProperties()) {
            String name = prop.name();
            TableItem item = new TableItem(wProperties.table, SWT.NONE);
            if (getModelAnnotation() != null && !prop.hideUI()) {
                item.setText(1, name);
                try {
                    Object object = annotationType.getModelPropertyValueByName(name);
                    if (object != null) {
                        String value = object.toString();
                        if (StringUtils.equals(name, CreateAttribute.UNIQUE_NAME)
                                || StringUtils.equals(name, CreateAttribute.HIDDEN_NAME)
                                || StringUtils.equals(name, CreateMeasure.HIDDEN_NAME)) {
                            value = StringUtils.capitalize(value);
                        }
                        item.setText(2, value);
                    }
                } catch (Exception e) {
                    logError(e.getMessage());
                }
            }
        }

        wProperties.removeEmptyRows();
        wProperties.setRowNums();
    }

    protected AnnotationType createAnnotationType() {

        if (StringUtils.isBlank(wActionList.getText())) {
            BlankAnnotation blankAnnotation = new BlankAnnotation();
            blankAnnotation.setField(getModelAnnotation().getField());
            return blankAnnotation;
        }

        switch ((ModelAnnotation.Type) wActionList.getData(wActionList.getText())) {
        case CREATE_MEASURE:
            CreateMeasure cm = new CreateMeasure();
            cm.setField(getModelAnnotation().getField());
            cm.setName(getModelAnnotation().getField());
            ValueMetaInterface vmi = getValueMeta();
            if (vmi != null && !vmi.isNumeric()) {
                cm.setAggregateType(AggregationType.COUNT); // change default for non-numeric fields
            }
            return cm;
        case CREATE_ATTRIBUTE:
            CreateAttribute createAttribute = new CreateAttribute();
            createAttribute.setField(getModelAnnotation().getField());
            createAttribute.setName(getModelAnnotation().getField());
            return createAttribute;
        case CREATE_DIMENSION_KEY:
            CreateDimensionKey createKey = new CreateDimensionKey();
            createKey.setField(getModelAnnotation().getField());
            createKey.setName(wField.getText());
            return createKey;
        case LINK_DIMENSION:
            LinkDimension linkDimension = new LinkDimension();
            linkDimension.setField(getModelAnnotation().getField());
            return linkDimension;
        case CREATE_CALCULATED_MEMBER:
            CreateCalculatedMember createCalculatedMember = new CreateCalculatedMember();
            return createCalculatedMember;
        }

        return null;
    }

    protected void persistAnnotationProperties() throws ModelerException {

        if (getModelAnnotation() == null) {
            return;
        }

        AnnotationType annotationType = createAnnotationType();
        getModelAnnotation().setAnnotation(annotationType); // always override existing type
        for (int i = 0; i < wProperties.getItemCount(); i++) {
            String name = wProperties.getItem(i, 1);
            String value = wProperties.getItem(i, 2);
            if (value.equals("")) {
                value = null;
            }
            try {
                getModelAnnotation().getAnnotation().setModelPropertyByName(name, value);
            } catch (Exception e) {
                logError(e.getMessage());
            }
        }

        if (annotationType != null) {
            annotationType.validate(); // may throw ModelerException
            if (!getModifiedModelAnnotations().contains(getModelAnnotation())) {
                getModifiedModelAnnotations().add(getModelAnnotation());
            }
        }
    }

    private Iterable<ModelAnnotation.Type> getAnnotationTypes() {
        List<ModelAnnotation.Type> types = new ArrayList<ModelAnnotation.Type>();
        for (ModelAnnotation.Type type : ModelAnnotation.Type.values()) {
            if (type.isApplicable(getModelAnnotations(), getModelAnnotation(), getValueMeta())) {
                types.add(type);
            }
        }
        return types;
    }

    private ValueMetaInterface getValueMeta() {
        if (StringUtils.isNotBlank(getModelAnnotation().getField())) {
            try {
                RowMetaInterface rowMeta = transMeta.getPrevStepFields(stepname);
                for (ValueMetaInterface valueMeta : rowMeta.getValueMetaList()) {
                    if (getModelAnnotation().getField().equals(valueMeta.getName())) {
                        return valueMeta;
                    }
                }
            } catch (KettleStepException e) {
                log.logError(e.getLocalizedMessage());
            }
        }
        return null;
    }

    private String findTableItemValue(final String propertyName) {

        if (StringUtils.isNotBlank(propertyName) && (wProperties.getTable() != null)) {
            for (int i = 0; i < wProperties.getTable().getItemCount(); i++) {
                TableItem item = wProperties.getTable().getItem(i);
                if (item != null) {
                    if (StringUtils.equals(propertyName, item.getText(1))) {
                        return item.getText(2);
                    }
                }
            }
        }

        return null;
    }
}