/* * Copyright 2011 Red Hat, Inc. and/or its affiliates. * * 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.drools.workbench.models.guided.dtable.backend.util; import java.util.ArrayList; import java.util.List; import org.drools.workbench.models.datamodel.rule.FieldConstraint; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; import org.drools.workbench.models.guided.dtable.shared.model.BaseColumn; import org.drools.workbench.models.guided.dtable.shared.model.ConditionCol52; import org.drools.workbench.models.guided.dtable.shared.model.DTCellValue52; /** * Utility class to build Field Constraints for cells with "Otherwise" values */ public class GuidedDTDRLOtherwiseHelper { /** * OtherwiseBuilder for equals operators. This assembles a comma separated * list of non-null values contained in other cells in the column and * constructs a FieldConstraint with operator "not in" and the derived list: * e.g. not in ("a", "b", "c") */ public static class EqualsOtherwiseBuilder extends AbstractOtherwiseBuilder { private EqualsOtherwiseBuilder() { } @Override FieldConstraint constructSingleFieldConstraint( ConditionCol52 c, List<DTCellValue52> columnData ) { SingleFieldConstraint sfc = new SingleFieldConstraint( c.getFactField() ); sfc.setConstraintValueType( c.getConstraintValueType() ); sfc.setFieldType( c.getFieldType() ); sfc.setOperator( "not in" ); List<String> consumedValues = new ArrayList<String>(); StringBuilder value = new StringBuilder(); value.append( "( " ); for ( DTCellValue52 cv : columnData ) { //Skip the "otherwise" cell itself if ( cv.isOtherwise() ) { continue; } //Ensure cell values start and end with quotes String scv = GuidedDTDRLUtilities.convertDTCellValueToString( cv ); if ( scv != null ) { if ( !consumedValues.contains( scv ) ) { value.append( scv ).append( ", " ); } consumedValues.add( scv ); } } value.delete( value.lastIndexOf( "," ), value.length() - 1 ); value.append( ")" ); sfc.setValue( value.toString() ); return sfc; } } /** * OtherwiseBuilder for not-equals operators. This assembles a comma * separated list of non-null values contained in other cells in the column * and constructs a FieldConstraint with operator "in" and the derived list: * e.g. in ("a", "b", "c") */ public static class NotEqualsOtherwiseBuilder extends AbstractOtherwiseBuilder { private NotEqualsOtherwiseBuilder() { } @Override SingleFieldConstraint constructSingleFieldConstraint( ConditionCol52 c, List<DTCellValue52> columnData ) { SingleFieldConstraint sfc = new SingleFieldConstraint( c.getFactField() ); sfc.setConstraintValueType( c.getConstraintValueType() ); sfc.setFieldType( c.getFieldType() ); sfc.setOperator( "in" ); List<String> consumedValues = new ArrayList<String>(); StringBuilder value = new StringBuilder(); value.append( "( " ); for ( DTCellValue52 cv : columnData ) { //Skip the "otherwise" cell itself if ( cv.isOtherwise() ) { continue; } //Ensure cell values start and end with quotes String scv = GuidedDTDRLUtilities.convertDTCellValueToString( cv ); if ( scv != null ) { if ( !consumedValues.contains( scv ) ) { value.append( scv ).append( ", " ); } consumedValues.add( scv ); } } value.delete( value.lastIndexOf( "," ), value.length() - 1 ); value.append( ")" ); sfc.setValue( value.toString() ); return sfc; } } /** * Interface defining a factory method to build a FieldConstraint */ public interface OtherwiseBuilder { /** * Build a Field Constraint * @param c Condition Column that contains the "Otherwise" cell * @param allColumns All Decision Table columns. Decision Tables have an * implied "and" between multiple SingleFieldConstraints for * the same Fact field. OtherwiseBuilders for less-than, * greater-than etc need access to other Condition Columns * bound to the same Fact and Field to construct a * CompositeFieldConstraint. * @param data Decision Table values * @return */ FieldConstraint makeFieldConstraint( ConditionCol52 c, List<BaseColumn> allColumns, List<List<DTCellValue52>> data ); } /** * Base OtherwiseBuilder that extracts a single column of data relating to * the ConditionCol from which the FieldConstraint will be constructed. This * will need to be re-factored if it is agreed that the implementation of * "Otherwise" for certain operators needs to provide * CompositeFieldConstraints. */ static abstract class AbstractOtherwiseBuilder implements OtherwiseBuilder { public FieldConstraint makeFieldConstraint( ConditionCol52 c, List<BaseColumn> allColumns, List<List<DTCellValue52>> data ) { int index = allColumns.indexOf( c ); List<DTCellValue52> columnData = extractColumnData( data, index ); return constructSingleFieldConstraint( c, columnData ); } //Template pattern, provide method for implementations to override abstract FieldConstraint constructSingleFieldConstraint( ConditionCol52 c, List<DTCellValue52> columnData ); } /** * Retrieve the correct OtherwiseBuilder for the given column * @param c * @return */ public static OtherwiseBuilder getBuilder( ConditionCol52 c ) { if ( c.getOperator().equals( "==" ) ) { return new EqualsOtherwiseBuilder(); } else if ( c.getOperator().equals( "!=" ) ) { return new NotEqualsOtherwiseBuilder(); } throw new IllegalArgumentException( "ConditionCol operator does not support Otherwise values" ); } //Extract data relating to a single column private static List<DTCellValue52> extractColumnData( List<List<DTCellValue52>> data, int columnIndex ) { List<DTCellValue52> columnData = new ArrayList<DTCellValue52>(); for ( List<DTCellValue52> row : data ) { columnData.add( row.get( columnIndex ) ); } return columnData; } //Utility factory class, no constructor private GuidedDTDRLOtherwiseHelper() { } }