/*
* Copyright 2011 JBoss Inc
*
* 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.guvnor.models.guided.dtable.backend.util;
import org.drools.guvnor.models.commons.shared.oracle.DataType;
import org.drools.guvnor.models.commons.backend.IUpgradeHelper;
import org.drools.guvnor.models.guided.dtable.shared.model.ActionCol52;
import org.drools.guvnor.models.guided.dtable.shared.model.ActionInsertFactCol52;
import org.drools.guvnor.models.guided.dtable.shared.model.ActionRetractFactCol52;
import org.drools.guvnor.models.guided.dtable.shared.model.ActionSetFieldCol52;
import org.drools.guvnor.models.guided.dtable.shared.model.AttributeCol52;
import org.drools.guvnor.models.guided.dtable.shared.model.ConditionCol52;
import org.drools.guvnor.models.guided.dtable.shared.model.DTCellValue52;
import org.drools.guvnor.models.guided.dtable.shared.model.DescriptionCol52;
import org.drools.guvnor.models.guided.dtable.shared.model.GuidedDecisionTable52;
import org.drools.guvnor.models.guided.dtable.shared.model.MetadataCol52;
import org.drools.guvnor.models.guided.dtable.shared.model.Pattern52;
import org.drools.guvnor.models.guided.dtable.shared.model.RowNumberCol52;
import org.drools.guvnor.models.guided.dtable.shared.model.legacy.ActionCol;
import org.drools.guvnor.models.guided.dtable.shared.model.legacy.ActionInsertFactCol;
import org.drools.guvnor.models.guided.dtable.shared.model.legacy.ActionRetractFactCol;
import org.drools.guvnor.models.guided.dtable.shared.model.legacy.ActionSetFieldCol;
import org.drools.guvnor.models.guided.dtable.shared.model.legacy.AttributeCol;
import org.drools.guvnor.models.guided.dtable.shared.model.legacy.ConditionCol;
import org.drools.guvnor.models.guided.dtable.shared.model.legacy.GuidedDecisionTable;
import org.drools.guvnor.models.guided.dtable.shared.model.legacy.MetadataCol;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* Helper class to upgrade model used for Guided Decision Table. This
* implementation converts legacy GuidedDecisionTable objects to
* GuidedDecisionTable52 objects used from Guvnor 5.2 onwards.
*/
@SuppressWarnings("deprecation")
public class GuidedDecisionTableUpgradeHelper1
implements
IUpgradeHelper<GuidedDecisionTable52, GuidedDecisionTable> {
/**
* Convert the legacy Decision Table model to the new
* @param legacyDTModel
* @return The new DTModel
*/
public GuidedDecisionTable52 upgrade( GuidedDecisionTable legacyDTModel ) {
assertConditionColumnPatternGrouping( legacyDTModel );
GuidedDecisionTable52 newDTModel = new GuidedDecisionTable52();
newDTModel.setTableFormat( GuidedDecisionTable52.TableFormat.EXTENDED_ENTRY );
newDTModel.setTableName( legacyDTModel.tableName );
newDTModel.setParentName( legacyDTModel.parentName );
newDTModel.setRowNumberCol( new RowNumberCol52() );
newDTModel.setDescriptionCol( new DescriptionCol52() );
//Metadata columns' data-type is implicitly defined in the metadata value. For example
//a String metadata attribute is: "value", a numerical: 1. No conversion action required
if ( legacyDTModel.metadataCols != null ) {
for ( MetadataCol c : legacyDTModel.metadataCols ) {
newDTModel.getMetadataCols().add( makeNewColumn( c ) );
}
}
//Attribute columns' data-type is based upon the attribute name
if ( legacyDTModel.attributeCols != null ) {
for ( AttributeCol c : legacyDTModel.attributeCols ) {
newDTModel.getAttributeCols().add( makeNewColumn( c ) );
}
}
//Legacy decision tables did not have Condition field data-types. Set all Condition
//fields to a *sensible* default of String (as this matches legacy behaviour).
List<Pattern52> patterns = new ArrayList<Pattern52>();
Map<String, Pattern52> uniquePatterns = new HashMap<String, Pattern52>();
if ( legacyDTModel.conditionCols != null ) {
for ( int i = 0; i < legacyDTModel.conditionCols.size(); i++ ) {
ConditionCol c = legacyDTModel.conditionCols.get( i );
String boundName = c.boundName;
Pattern52 p = uniquePatterns.get( boundName );
if ( p == null ) {
p = new Pattern52();
p.setBoundName( boundName );
p.setFactType( c.factType );
patterns.add( p );
uniquePatterns.put( boundName,
p );
}
if ( p.getFactType() != null && !p.getFactType().equals( c.factType ) ) {
throw new IllegalArgumentException( "Inconsistent FactTypes for ConditionCols bound to '" + boundName + "' detected." );
}
p.getChildColumns().add( makeNewColumn( c ) );
}
for ( Pattern52 p : patterns ) {
newDTModel.getConditions().add( p );
}
}
//Action columns have a discrete data-type. No conversion action required.
if ( legacyDTModel.actionCols != null ) {
for ( ActionCol c : legacyDTModel.actionCols ) {
newDTModel.getActionCols().add( makeNewColumn( c ) );
}
}
//Copy across data
newDTModel.setData( DataUtilities.makeDataLists( legacyDTModel.data ) );
//Copy the boundName for ActionRetractFactCol into the data of the new Guided Decision Table model
if ( legacyDTModel.actionCols != null ) {
final int metaDataColCount = ( legacyDTModel.metadataCols == null ? 0 : legacyDTModel.metadataCols.size() );
final int attributeColCount = ( legacyDTModel.attributeCols == null ? 0 : legacyDTModel.attributeCols.size() );
final int conditionColCount = ( legacyDTModel.conditionCols == null ? 0 : legacyDTModel.conditionCols.size() );
final int DATA_COLUMN_OFFSET = metaDataColCount + attributeColCount + conditionColCount + GuidedDecisionTable.INTERNAL_ELEMENTS;
for ( int iCol = 0; iCol < legacyDTModel.actionCols.size(); iCol++ ) {
ActionCol lc = legacyDTModel.actionCols.get( iCol );
if ( lc instanceof ActionRetractFactCol) {
String boundName = ( (ActionRetractFactCol) lc ).boundName;
for ( List<DTCellValue52> row : newDTModel.getData() ) {
row.get( DATA_COLUMN_OFFSET + iCol ).setStringValue( boundName );
}
}
}
}
return newDTModel;
}
// Ensure Condition columns are grouped by pattern (as we merge equal
// patterns in the UI). This operates on the original Model data and
// therefore should be called before the Decision Table's internal data
// representation (i.e. DynamicData, DynamicDataRow and CellValue) is
// populated
private void assertConditionColumnPatternGrouping( GuidedDecisionTable model ) {
class ConditionColData {
ConditionCol col;
String[] data;
}
// Offset into Model's data array
final int metaDataColCount = ( model.metadataCols == null ? 0 : model.metadataCols.size() );
final int attributeColCount = ( model.attributeCols == null ? 0 : model.attributeCols.size() );
final int DATA_COLUMN_OFFSET = metaDataColCount + attributeColCount + GuidedDecisionTable.INTERNAL_ELEMENTS;
Map<String, List<ConditionColData>> uniqueGroups = new TreeMap<String, List<ConditionColData>>();
List<List<ConditionColData>> groups = new ArrayList<List<ConditionColData>>();
final int DATA_ROWS = model.data.length;
// Copy conditions and related data into temporary groups
for ( int iCol = 0; iCol < model.conditionCols.size(); iCol++ ) {
ConditionCol col = model.conditionCols.get( iCol );
String pattern = col.boundName + "";
List<ConditionColData> groupCols = uniqueGroups.get( pattern );
if ( groupCols == null ) {
groupCols = new ArrayList<ConditionColData>();
groups.add( groupCols );
uniqueGroups.put( pattern,
groupCols );
}
// Make a ConditionColData object
ConditionColData ccd = new ConditionColData();
int colIndex = DATA_COLUMN_OFFSET + iCol;
ccd.data = new String[ DATA_ROWS ];
for ( int iRow = 0; iRow < DATA_ROWS; iRow++ ) {
String[] row = model.data[ iRow ];
ccd.data[ iRow ] = row[ colIndex ];
}
ccd.col = col;
groupCols.add( ccd );
}
// Copy temporary groups back into the model
int iCol = 0;
model.conditionCols.clear();
for ( List<ConditionColData> me : groups ) {
for ( ConditionColData ccd : me ) {
model.conditionCols.add( ccd.col );
int colIndex = DATA_COLUMN_OFFSET + iCol;
for ( int iRow = 0; iRow < DATA_ROWS; iRow++ ) {
String[] row = model.data[ iRow ];
row[ colIndex ] = ccd.data[ iRow ];
}
iCol++;
}
}
}
private AttributeCol52 makeNewColumn( AttributeCol c ) {
AttributeCol52 nc = new AttributeCol52();
nc.setAttribute( c.attr );
nc.setDefaultValue( new DTCellValue52( c.defaultValue ) );
nc.setHideColumn( c.hideColumn );
nc.setReverseOrder( c.reverseOrder );
nc.setUseRowNumber( c.useRowNumber );
nc.setWidth( c.width );
return nc;
}
private MetadataCol52 makeNewColumn( MetadataCol c ) {
MetadataCol52 nc = new MetadataCol52();
nc.setDefaultValue( new DTCellValue52( c.defaultValue ) );
nc.setHideColumn( c.hideColumn );
nc.setMetadata( c.attr );
nc.setWidth( c.width );
return nc;
}
private ConditionCol52 makeNewColumn( ConditionCol c ) {
ConditionCol52 nc = new ConditionCol52();
nc.setConstraintValueType( c.constraintValueType );
nc.setDefaultValue( new DTCellValue52( c.defaultValue ) );
nc.setFactField( c.factField );
nc.setFieldType( DataType.TYPE_STRING );
nc.setHeader( c.header );
nc.setHideColumn( c.hideColumn );
nc.setOperator( c.operator );
nc.setValueList( c.valueList );
nc.setWidth( c.width );
return nc;
}
private ActionCol52 makeNewColumn( ActionCol c ) {
if ( c instanceof ActionInsertFactCol) {
return makeNewColumn( (ActionInsertFactCol) c );
} else if ( c instanceof ActionRetractFactCol ) {
return makeNewColumn( (ActionRetractFactCol) c );
} else if ( c instanceof ActionSetFieldCol) {
return makeNewColumn( (ActionSetFieldCol) c );
}
ActionCol52 nc = new ActionCol52();
nc.setDefaultValue( new DTCellValue52( c.defaultValue ) );
nc.setHeader( c.header );
nc.setHideColumn( c.hideColumn );
nc.setWidth( c.width );
return nc;
}
private ActionInsertFactCol52 makeNewColumn( ActionInsertFactCol c ) {
ActionInsertFactCol52 nc = new ActionInsertFactCol52();
nc.setBoundName( c.boundName );
nc.setDefaultValue( new DTCellValue52( c.defaultValue ) );
nc.setFactField( c.factField );
nc.setFactType( c.factType );
nc.setHeader( c.header );
nc.setHideColumn( c.hideColumn );
nc.setType( c.type );
nc.setValueList( c.valueList );
nc.setWidth( c.width );
return nc;
}
private ActionRetractFactCol52 makeNewColumn( ActionRetractFactCol c ) {
ActionRetractFactCol52 nc = new ActionRetractFactCol52();
nc.setDefaultValue( new DTCellValue52( c.defaultValue ) );
nc.setHeader( c.header );
nc.setHideColumn( c.hideColumn );
nc.setWidth( c.width );
return nc;
}
private ActionSetFieldCol52 makeNewColumn( ActionSetFieldCol c ) {
ActionSetFieldCol52 nc = new ActionSetFieldCol52();
nc.setBoundName( c.boundName );
nc.setDefaultValue( new DTCellValue52( c.defaultValue ) );
nc.setFactField( c.factField );
nc.setHeader( c.header );
nc.setHideColumn( c.hideColumn );
nc.setType( c.type );
nc.setUpdate( c.update );
nc.setValueList( c.valueList );
nc.setWidth( c.width );
return nc;
}
}