/**
* Copyright 2010 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.client.decisiontable;
import java.util.ArrayList;
import java.util.List;
import org.drools.ide.common.client.modeldriven.dt.ActionCol;
import org.drools.ide.common.client.modeldriven.dt.AttributeCol;
import org.drools.ide.common.client.modeldriven.dt.ConditionCol;
import org.drools.ide.common.client.modeldriven.dt.GuidedDecisionTable;
import org.drools.ide.common.client.modeldriven.dt.MetadataCol;
/**
* Helps to move rows and columns in Decision Table.
*
* @author Toni Rikkola
*
*/
public class DecisionTableHandler {
// counter and description data
private static int COUNTER_AND_DESCRIPTION = 2;
private static int ARROW = 1;
enum DTColumnConfigType {
METADATA, ATTRIBUTE, CONDITION, ACTION
}
/**
* Checks if old and new column have the same type.
*
* @param dt
* @param oldIndex
* @param newIndex
* @return
*/
public static boolean validateMove(GuidedDecisionTable dt,
int oldIndex,
int newIndex) {
DTColumnConfigType oldType = DecisionTableHandler.getType( dt,
oldIndex );
DTColumnConfigType newType = DecisionTableHandler.getType( dt,
newIndex );
return oldType.equals( newType );
}
/**
* Moves the column if the old and new index columns have the same type.
*
* @param dt
* @param oldIndex
* @param newIndex
*/
public static void moveColumn(GuidedDecisionTable dt,
int oldIndex,
int newIndex) {
if ( !validateMove( dt,
oldIndex,
newIndex ) ) {
return;
}
DTColumnConfigType type = getType( dt,
newIndex );
// Move headers.
// its +2 as we have counter and description data
int add = COUNTER_AND_DESCRIPTION;
switch ( type ) {
case METADATA :
dt.setMetadataCols( moveColumnHeader( dt.getMetadataCols(),
oldIndex - add,
newIndex - add ) );
break;
case ATTRIBUTE :
add = COUNTER_AND_DESCRIPTION + dt.getMetadataCols().size();
dt.setAttributeCols( moveColumnHeader( dt.getAttributeCols(),
oldIndex - add,
newIndex - add ) );
break;
case CONDITION :
add = COUNTER_AND_DESCRIPTION + dt.getMetadataCols().size() + dt.getAttributeCols().size();
dt.setConditionCols( moveColumnHeader( dt.getConditionCols(),
oldIndex - add,
newIndex - add ) );
break;
case ACTION :
// +1 as we have an arrow between conditions and actions.
add = COUNTER_AND_DESCRIPTION + dt.getMetadataCols().size() + dt.getAttributeCols().size() + ARROW + dt.getConditionCols().size();
dt.setActionCols( moveColumnHeader( dt.getActionCols(),
oldIndex - add,
newIndex - add ) );
break;
default :
break;
}
// Move data.
switch ( type ) {
case ACTION :
// If we are moving action parts we need to jump over the arrow separator.
moveData( dt.getData(),
oldIndex - 1,
newIndex - 1 );
break;
default :
moveData( dt.getData(),
oldIndex,
newIndex );
break;
}
}
public static DTColumnConfigType getType(GuidedDecisionTable dt,
int index) {
if ( index < (COUNTER_AND_DESCRIPTION + dt.getMetadataCols().size()) ) {
return DTColumnConfigType.METADATA;
} else if ( index < (COUNTER_AND_DESCRIPTION + dt.getMetadataCols().size() + dt.getAttributeCols().size()) ) {
return DTColumnConfigType.ATTRIBUTE;
} else if ( index < (COUNTER_AND_DESCRIPTION + dt.getMetadataCols().size() + dt.getAttributeCols().size() + dt.getConditionCols().size() + ARROW) ) {
return DTColumnConfigType.CONDITION;
} else {
return DTColumnConfigType.ACTION;
}
}
public static void moveData(String[][] data,
int oldIndex,
int newIndex) {
if ( newIndex > oldIndex ) {
moveDataRight( data,
oldIndex,
newIndex );
} else {
moveDataLeft( data,
oldIndex,
newIndex );
}
}
public static void moveDataRight(String[][] data,
int oldIndex,
int newIndex) {
for ( int i = 0; i < data.length; i++ ) {
String[] row = data[i];
// Get the value that needs to be moved.
String value = row[oldIndex];
for ( int j = oldIndex; j <= newIndex; j++ ) {
if ( j < newIndex && j >= oldIndex ) {
// Move everything between to the left.
row[j] = row[j + 1];
} else if ( j == newIndex ) {
row[j] = value;
}
}
}
}
public static void moveDataLeft(String[][] data,
int oldIndex,
int newIndex) {
for ( int i = 0; i < data.length; i++ ) {
String[] row = data[i];
// Get the value that needs to be moved.
String value = row[oldIndex];
for ( int j = oldIndex; j >= newIndex; j-- ) {
if ( j > newIndex && j <= oldIndex ) {
// Move everything between to the left.
row[j] = row[j - 1];
} else if ( j == newIndex ) {
row[j] = value;
}
}
}
}
public static <T> List <T>moveColumnHeader(List<T> list,
int oldIndex,
int newIndex) {
T from = list.get( oldIndex );
T to = list.get( newIndex );
// Create new list.
List<T> newList = new ArrayList<T>();
for ( T item : list ) {
if ( item.equals( to ) ) {
if ( newIndex > oldIndex ) {
newList.add( item );
newList.add( from );
} else {
newList.add( from );
newList.add( item );
}
} else if ( !item.equals( from ) ) {
newList.add( item );
}
}
return newList;
}
}