/* * Copyright 2012 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.screens.dtablexls.backend.server.conversion.builders; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.drools.decisiontable.parser.ActionType.Code; import org.drools.decisiontable.parser.RuleSheetParserUtil; import org.drools.template.model.SnippetBuilder; import org.drools.template.model.SnippetBuilder.SnippetType; import org.drools.template.parser.DecisionTableParseException; import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.guided.dtable.shared.conversion.ConversionMessageType; import org.drools.workbench.models.guided.dtable.shared.conversion.ConversionResult; import org.drools.workbench.models.guided.dtable.shared.model.BRLActionVariableColumn; import org.drools.workbench.models.guided.dtable.shared.model.BRLVariableColumn; /** * Builder for Action columns */ public class GuidedDecisionTableRHSBuilder implements HasColumnHeadings, GuidedDecisionTableSourceBuilderIndirect { private final int headerRow; private final int headerCol; private final String variable; private final List<String> drlFragments = new ArrayList<String>(); //Map of column headers, keyed on XLS column index private final Map<Integer, String> columnHeaders = new HashMap<Integer, String>(); //Map of column value parsers, keyed on XLS column index private final Map<Integer, ParameterizedValueBuilder> valueBuilders = new HashMap<Integer, ParameterizedValueBuilder>(); private List<GuidedDecisionTableSourceBuilder> sourceBuilders; //Utility class to convert XLS parameters to BRLFragment Template keys private final ParameterUtilities parameterUtilities; private ConversionResult conversionResult; public GuidedDecisionTableRHSBuilder( final int row, final int column, final String boundVariable, final List<GuidedDecisionTableSourceBuilder> sourceBuilders, final ParameterUtilities parameterUtilities, final ConversionResult conversionResult ) { this.headerRow = row; this.headerCol = column; this.variable = boundVariable == null ? "" : boundVariable.trim(); this.sourceBuilders = sourceBuilders; this.parameterUtilities = parameterUtilities; this.conversionResult = conversionResult; } @Override public List<BRLVariableColumn> getVariableColumns() { //Sort column builders by column index to ensure columns are added in the correct sequence final Set<Integer> sortedIndexes = new TreeSet<Integer>( this.valueBuilders.keySet() ); final List<BRLVariableColumn> variableColumns = new ArrayList<BRLVariableColumn>(); for ( Integer index : sortedIndexes ) { final ParameterizedValueBuilder vb = this.valueBuilders.get( index ); final List<BRLVariableColumn> vbVariableColumns = addColumn( vb ); for ( BRLVariableColumn vbVariableColumn : vbVariableColumns ) { ( (BRLActionVariableColumn) vbVariableColumn ).setHeader( this.columnHeaders.get( index ) ); } variableColumns.addAll( vbVariableColumns ); } return variableColumns; } @Override public Map<Integer, ParameterizedValueBuilder> getValueBuilders() { return this.valueBuilders; } private List<BRLVariableColumn> addColumn( final ParameterizedValueBuilder vb ) { if ( vb instanceof LiteralValueBuilder ) { return addLiteralColumn( (LiteralValueBuilder) vb ); } else { return addBRLFragmentColumn( vb ); } } private List<BRLVariableColumn> addLiteralColumn( final LiteralValueBuilder vb ) { final List<BRLVariableColumn> variableColumns = new ArrayList<BRLVariableColumn>(); final BRLActionVariableColumn parameterColumn = new BRLActionVariableColumn( "", DataType.TYPE_BOOLEAN ); variableColumns.add( parameterColumn ); //Store DRL fragment for use by GuidedDecisionTableRHSBuilder drlFragments.add( vb.getTemplate() ); return variableColumns; } private List<BRLVariableColumn> addBRLFragmentColumn( final ParameterizedValueBuilder vb ) { final List<BRLVariableColumn> variableColumns = new ArrayList<BRLVariableColumn>(); for ( String parameter : vb.getParameters() ) { final BRLActionVariableColumn parameterColumn = new BRLActionVariableColumn( parameter, DataType.TYPE_OBJECT ); variableColumns.add( parameterColumn ); } //Store DRL fragment for use by GuidedDecisionTableRHSBuilder drlFragments.add( vb.getTemplate() ); return variableColumns; } @Override public void addTemplate( final int row, final int column, final String content ) { //Validate column template if ( valueBuilders.containsKey( column ) ) { final String message = "Internal error: Can't have a code snippet added twice to one spreadsheet column."; this.conversionResult.addMessage( message, ConversionMessageType.ERROR ); return; } //Add new template String template = content.trim(); if ( isBoundVar() ) { template = variable + "." + template; } if ( !template.endsWith( ";" ) ) { template = template + ";"; } try { this.valueBuilders.put( column, getValueBuilder( template ) ); } catch ( DecisionTableParseException pe ) { this.conversionResult.addMessage( pe.getMessage(), ConversionMessageType.WARNING ); } } private boolean isBoundVar() { return !( "".equals( variable ) ); } @Override public void setColumnHeader( final int column, final String value ) { this.columnHeaders.put( column, value.trim() ); } private ParameterizedValueBuilder getValueBuilder( final String template ) { final SnippetType type = SnippetBuilder.getType( template ); switch ( type ) { case INDEXED: return new IndexedParametersValueBuilder( template, parameterUtilities, ParameterizedValueBuilder.Part.RHS ); case PARAM: return new SingleParameterValueBuilder( template, parameterUtilities, ParameterizedValueBuilder.Part.RHS ); case SINGLE: return new LiteralValueBuilder( template ); } throw new DecisionTableParseException( "SnippetBuilder.SnippetType '" + type.toString() + "' is not supported. The column will not be added." ); } @Override public void addCellValue( final int row, final int column, final String value ) { //Add new row to column data final ParameterizedValueBuilder vb = this.valueBuilders.get( column ); if ( vb == null ) { final String message = "No code snippet for ACTION, above cell " + RuleSheetParserUtil.rc2name( this.headerRow + 2, this.headerCol ); this.conversionResult.addMessage( message, ConversionMessageType.ERROR ); return; } vb.addCellValue( row, column, value ); } @Override public String getResult() { final StringBuilder sb = new StringBuilder(); for ( String drlFragment : drlFragments ) { sb.append( drlFragment ).append( "\n" ); } return sb.toString(); } @Override public Code getActionTypeCode() { return Code.ACTION; } @Override public void clearValues() { throw new UnsupportedOperationException(); } @Override public boolean hasValues() { throw new UnsupportedOperationException(); } @Override public int getRowCount() { int maxRowCount = 0; for ( ParameterizedValueBuilder pvb : valueBuilders.values() ) { maxRowCount = Math.max( maxRowCount, pvb.getColumnData().size() ); } return maxRowCount; } }