org.talend.dataprep.transformation.actions.common.AbstractCompareAction.java Source code

Java tutorial

Introduction

Here is the source code for org.talend.dataprep.transformation.actions.common.AbstractCompareAction.java

Source

// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// https://github.com/Talend/data-prep/blob/master/LICENSE
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================

package org.talend.dataprep.transformation.actions.common;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nonnull;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.talend.dataprep.api.dataset.ColumnMetadata;
import org.talend.dataprep.api.dataset.RowMetadata;
import org.talend.dataprep.api.dataset.row.DataSetRow;
import org.talend.dataprep.api.type.Type;
import org.talend.dataprep.i18n.ActionsBundle;
import org.talend.dataprep.parameters.Parameter;
import org.talend.dataprep.parameters.ParameterType;
import org.talend.dataprep.parameters.SelectParameter;
import org.talend.dataprep.transformation.api.action.context.ActionContext;

public abstract class AbstractCompareAction extends AbstractActionMetadata
        implements ColumnAction, OtherColumnParameters, CompareAction {

    public static final int ERROR_COMPARE_RESULT = Integer.MIN_VALUE;

    public static final String ERROR_COMPARE_RESULT_LABEL = StringUtils.EMPTY;

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCompareAction.class);

    @Override
    @Nonnull
    public List<Parameter> getParameters() {
        final List<Parameter> parameters = super.getParameters();

        parameters.add(getCompareModeSelectParameter());

        //@formatter:off
        parameters.add(SelectParameter.Builder.builder() //
                .name(MODE_PARAMETER) //
                .item(CONSTANT_MODE, CONSTANT_MODE, getDefaultConstantValue()) //
                .item(OTHER_COLUMN_MODE, OTHER_COLUMN_MODE,
                        new Parameter(SELECTED_COLUMN_PARAMETER, ParameterType.COLUMN, //
                                StringUtils.EMPTY, false, false, //
                                StringUtils.EMPTY)) //
                .defaultValue(CONSTANT_MODE).build());
        //@formatter:on

        return ActionsBundle.attachToAction(parameters, this);
    }

    /**
     * can be overridden as keys can be different (date have different keys/labels)
     *
     * @return {@link SelectParameter}
     */
    protected SelectParameter getCompareModeSelectParameter() {

        //@formatter:off
        return SelectParameter.Builder.builder() //
                .name(CompareAction.COMPARE_MODE) //
                .item(EQ, EQ) //
                .item(NE, NE) //
                .item(GT, GT) //
                .item(GE, GE) //
                .item(LT, LT) //
                .item(LE, LE) //
                .defaultValue(EQ) //
                .build();
        //@formatter:on

    }

    /**
     *
     * @return {@link Parameter} the default value (can be a different type/value)
     */
    protected Parameter getDefaultConstantValue() {
        // olamy no idea why this 2 but was here before so just keep backward compat :-)
        return new Parameter(CONSTANT_VALUE, ParameterType.STRING, "2");
    }

    @Override
    public void compile(ActionContext context) {
        super.compile(context);
        if (context.getActionStatus() == ActionContext.ActionStatus.OK) {
            final String columnId = context.getColumnId();
            final RowMetadata rowMetadata = context.getRowMetadata();
            final Map<String, String> parameters = context.getParameters();
            final ColumnMetadata column = rowMetadata.getById(columnId);
            final String compareMode = getCompareMode(parameters);

            String compareToLabel;
            if (parameters.get(MODE_PARAMETER).equals(CONSTANT_MODE)) {
                compareToLabel = parameters.get(CONSTANT_VALUE);
            } else {
                final ColumnMetadata selectedColumn = rowMetadata
                        .getById(parameters.get(SELECTED_COLUMN_PARAMETER));
                compareToLabel = selectedColumn.getName();
            }

            context.column("result", (r) -> {
                final ColumnMetadata c = ColumnMetadata.Builder //
                        .column() //
                        .name(column.getName() + "_" + compareMode + "_" + compareToLabel + "?") //
                        .type(Type.BOOLEAN) //
                        .build();
                rowMetadata.insertAfter(columnId, c);
                return c;
            });
        }
    }

    /**
     * @see ColumnAction#applyOnColumn(DataSetRow, ActionContext)
     */
    @Override
    public void applyOnColumn(DataSetRow row, ActionContext context) {
        final String columnId = context.getColumnId();
        final Map<String, String> parameters = context.getParameters();
        final String compareMode = getCompareMode(parameters);

        // create new column and append it after current column
        final String newColumnId = context.column("result");

        ComparisonRequest comparisonRequest = new ComparisonRequest() //
                .setMode(compareMode) //
                .setColumnMetadata1(context.getRowMetadata().getById(columnId)) //
                .setValue1(row.get(columnId)) //
                // this can be null when comparing with a constant
                .setColumnMetadata2(getColumnMetadataToCompareWith(parameters, context)) //
                .setValue2(getValueToCompareWith(parameters, context, row));
        row.set(newColumnId, toStringCompareResult(comparisonRequest));
    }

    /**
     * can be overridden as keys can be different (date have different keys/labels)
     *
     * @param parameters
     * @return
     */
    protected String getCompareMode(Map<String, String> parameters) {
        return parameters.get(CompareAction.COMPARE_MODE);
    }

    private String getValueToCompareWith(Map<String, String> parameters, ActionContext context, DataSetRow row) {
        if (parameters.get(MODE_PARAMETER).equals(CONSTANT_MODE)) {
            return parameters.get(CONSTANT_VALUE);
        } else {
            final ColumnMetadata selectedColumn = context.getRowMetadata()
                    .getById(parameters.get(SELECTED_COLUMN_PARAMETER));
            return row.get(selectedColumn.getId());
        }
    }

    private ColumnMetadata getColumnMetadataToCompareWith(Map<String, String> parameters, ActionContext context) {
        if (parameters.get(MODE_PARAMETER).equals(CONSTANT_MODE)) {
            // we return the primary columnMetadata as we do not have an other one.
            return null;
        }
        return context.getRowMetadata().getById(parameters.get(SELECTED_COLUMN_PARAMETER));

    }

    /**
     * do the real comparison
     *
     * @param comparisonRequest
     * @return same result as {@link Comparable#compareTo(Object)} if any type issue or any problem use
     * #ERROR_COMPARE_RESULT
     */
    protected abstract int doCompare(ComparisonRequest comparisonRequest);

    /**
     *
     * @param comparisonRequest
     * @return transforming boolean to <code>true</code> or <code>false</code> as String in case of #doCompare returning
     * #ERROR_COMPARE_RESULT the label #ERROR_COMPARE_RESULT_LABEL is returned
     */
    public String toStringCompareResult(ComparisonRequest comparisonRequest) {
        boolean booleanResult;
        try {

            final int result = doCompare(comparisonRequest);

            if (result == ERROR_COMPARE_RESULT) {
                return ERROR_COMPARE_RESULT_LABEL;
            }

            booleanResult = compareResultToBoolean(result, comparisonRequest.mode);

        } catch (NumberFormatException e) {
            LOGGER.debug("Unable to compare values '{}' ", comparisonRequest, e);
            return ERROR_COMPARE_RESULT_LABEL;
        }

        return BooleanUtils.toString(booleanResult, Boolean.TRUE.toString(), Boolean.FALSE.toString());
    }

    protected boolean compareResultToBoolean(final int result, String mode) {
        switch (mode) {
        case EQ:
            return result == 0;
        case NE:
            return result != 0;
        case GT:
            return result > 0;
        case GE:
            return result >= 0;
        case LT:
            return result < 0;
        case LE:
            return result <= 0;
        default:
            return false;
        }
    }

    @Override
    public Set<Behavior> getBehavior() {
        return Collections.singleton(Behavior.METADATA_CREATE_COLUMNS);
    }

    /**
     * bean to ease passing values to do comparison (easier adding fields than changing method parameters)
     */
    public static class ComparisonRequest {

        public String value1, value2;

        public ColumnMetadata colMetadata1, colMetadata2;

        public String mode;

        public ComparisonRequest setValue1(String value1) {
            this.value1 = value1;
            return this;
        }

        public ComparisonRequest setValue2(String value2) {
            this.value2 = value2;
            return this;
        }

        public ComparisonRequest setColumnMetadata1(ColumnMetadata colMetadata1) {
            this.colMetadata1 = colMetadata1;
            return this;
        }

        public ComparisonRequest setColumnMetadata2(ColumnMetadata colMetadata2) {
            this.colMetadata2 = colMetadata2;
            return this;
        }

        public ComparisonRequest setMode(String mode) {
            this.mode = mode;
            return this;
        }

        @Override
        public String toString() {
            return "ComparisonRequest{" + "colMetadata1=" + colMetadata1 //
                    + ", value1='" + value1 + '\'' //
                    + ", value2='" + value2 + '\'' //
                    + ", colMetadata2=" + colMetadata2 //
                    + ", mode='" + mode + '\'' + '}';
        }
    }

}