/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.client.core.businessprocess;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jubula.client.core.model.ICapPO;
import org.eclipse.jubula.client.core.model.IDataSetPO;
import org.eclipse.jubula.client.core.model.IExecTestCasePO;
import org.eclipse.jubula.client.core.model.IModifiableParameterInterfacePO;
import org.eclipse.jubula.client.core.model.INodePO;
import org.eclipse.jubula.client.core.model.IParamDescriptionPO;
import org.eclipse.jubula.client.core.model.IParameterInterfacePO;
import org.eclipse.jubula.client.core.model.ISpecTestCasePO;
import org.eclipse.jubula.client.core.model.ITDManager;
import org.eclipse.jubula.client.core.model.PoMaker;
import org.eclipse.jubula.client.core.utils.ComboParamValidator;
import org.eclipse.jubula.client.core.utils.GuiParamValueConverter;
import org.eclipse.jubula.client.core.utils.IParamValueValidator;
import org.eclipse.jubula.client.core.utils.IntegerParamValueValidator;
import org.eclipse.jubula.client.core.utils.ModelParamValueConverter;
import org.eclipse.jubula.client.core.utils.NullValidator;
import org.eclipse.jubula.client.core.utils.ParamValueConverter;
import org.eclipse.jubula.client.core.utils.VariableParamValueValidator;
import org.eclipse.jubula.tools.internal.constants.StringConstants;
import org.eclipse.jubula.tools.internal.constants.TestDataConstants;
import org.eclipse.jubula.tools.internal.xml.businessmodell.Param;
/**
* @author BREDEX GmbH
* @created Jul 13, 2010
* @param <T>
* parameterized type
*/
public abstract class AbstractParamInterfaceBP<T> {
/**
* Adds a new data set into the given row of the given IParameterInterface
*
* @param obj
* the IParameterInterface object
* @param row
* the row to insert
*/
public void addDataSet(IParameterInterfacePO obj, int row) {
ISpecTestCasePO spec = null;
ITDManager dataManager = null;
List<String> list = new ArrayList<String>();
if (obj instanceof IExecTestCasePO) {
IExecTestCasePO exec = (IExecTestCasePO) obj;
spec = exec.getSpecTestCase();
dataManager = exec.getDataManager();
} else if (obj instanceof ISpecTestCasePO) {
spec = (ISpecTestCasePO) obj;
dataManager = spec.getDataManager();
}
if (dataManager != null && spec != null) {
List<String> uniqueIds = dataManager.getUniqueIds();
for (int i = 0; i < uniqueIds.size(); i++) {
String uuid = uniqueIds.get(i);
IParamDescriptionPO uniqueID = obj
.getParameterForUniqueId(uuid);
String value = getValueForSpecNodeWithParamDesc(uniqueID, spec);
list.add(value);
}
}
if (list.size() > 0) {
IDataSetPO dataSet = PoMaker.createListWrapperPO(list);
obj.getDataManager().insertDataSet(dataSet, row);
} else {
obj.getDataManager().insertDataSet(row);
}
}
/**
* Removes a test data row in the test data manager of the passed node.
*
* @param paramNode
* The parameter node
* @param row
* The row to remove
* @param mapper
* mapper to resolve param names
*/
public void removeDataSet(IParameterInterfacePO paramNode, int row,
IParamNameMapper mapper) {
int colCount = paramNode.getDataManager().getColumnCount();
for (int i = 0; i < colCount; i++) {
final String uniqueId = paramNode.getDataManager().getUniqueIds()
.get(i);
final IParamDescriptionPO desc = paramNode
.getParameterForUniqueId(uniqueId);
if (desc != null) {
GuiParamValueConverter conv = new GuiParamValueConverter(null,
paramNode, desc, AbstractParamInterfaceBP
.createParamValueValidator(
desc.getType(), false));
startParameterUpdate(conv, row, mapper);
}
}
paramNode.getDataManager().removeDataSet(row);
}
/**
* Updates the specified cell (row, column) in the test data manager of the
* passed parameter object.
*
* @param conv
* converter contains value to update
* @param row
* The test data row
* @param mapper
* mapper to resolve param names
*/
public void startParameterUpdate(GuiParamValueConverter conv,
int row, IParamNameMapper mapper) {
IParameterInterfacePO paramNode = conv.getCurrentNode();
IParamDescriptionPO paramDescription = conv.getDesc();
String paramGuid = paramDescription.getUniqueId();
if (paramNode.getParameterList().contains(conv.getDesc())
&& !paramNode.getDataManager().getUniqueIds().contains(
paramGuid)) {
// This prevents the scenario where a (new) parameter exists in
// the node's parameter list, but not in its data manager.
paramNode.getDataManager().addUniqueId(paramGuid);
}
try {
// do nothing, if parameter value is unchanged
String value =
paramNode.getDataManager().getCell(row, paramDescription);
final String modelString = conv.getModelString();
if (modelString != null && modelString.equals(value)) {
return;
}
} catch (IndexOutOfBoundsException e) { // NOPMD
// nothing
}
updateParam(conv, mapper, row);
}
/**
* get the gui representation for parameter value of given param description for first dataset
* @param node current node
* @param desc param description belonging to searched param value
* @param rowCount datasetNumber - 1
* @return gui representation of parameter value for given parameter description
*/
public static String getGuiStringForParamValue(
final IParameterInterfacePO node, final IParamDescriptionPO desc,
int rowCount) {
String result = StringConstants.EMPTY;
IParameterInterfacePO srcNode = node;
IParamDescriptionPO srcDesc = desc;
while (srcNode.getReferencedDataCube() != null) {
srcNode = srcNode.getReferencedDataCube();
srcDesc = srcNode.getParameterForName(srcDesc.getName());
// Existence and type compatibility check
if (srcDesc == null || !desc.getType().equals(srcDesc.getType())) {
return result;
}
}
if (srcDesc == null) {
// Parameter is not present in the referenced data source.
// Return empty test data.
return result;
}
int col = srcNode.getDataManager().findColumnForParam(
srcDesc.getUniqueId());
boolean colNotExistend = false;
boolean foundCol = false;
int dataSetCount = srcNode.getDataManager().getDataSetCount();
if (col > -1 && dataSetCount > rowCount) {
IDataSetPO row = srcNode.getDataManager().getDataSet(rowCount);
try {
String td = row.getValueAt(col);
ParamValueConverter conv =
new ModelParamValueConverter(td,
srcNode, srcDesc);
result = conv.getGuiString();
foundCol = true;
} catch (IndexOutOfBoundsException e) {
// do nothing
colNotExistend = true;
}
}
if (col == -1 || colNotExistend
|| (dataSetCount <= srcNode.getParameterListSize()
&& StringUtils.isBlank(result) && !foundCol)) {
if (srcNode instanceof IExecTestCasePO) {
INodePO specNode = srcNode.getSpecificationUser();
specNode = ((IExecTestCasePO) srcNode).getSpecTestCase();
if (specNode instanceof ISpecTestCasePO) {
result = getValueForSpecNodeWithParamDesc(
srcDesc, (ISpecTestCasePO) specNode);
}
}
}
return result;
}
/**
* Gets the value (including default value if there is a cap in the spec)
* @param srcDesc the {@link IParamDescriptionPO} of the parameter to get the value for
* @param specNode the spec node to check
* @return the value for a combination of {@link ISpecTestCasePO} column and {@link IParamDescriptionPO}
*/
public static String getValueForSpecNodeWithParamDesc(
IParamDescriptionPO srcDesc, ISpecTestCasePO specNode) {
List<INodePO> list = specNode.getUnmodifiableNodeList();
if (list.size() == 1) {
INodePO possibleCap = list.get(0);
if (possibleCap instanceof ICapPO) {
ICapPO cap = (ICapPO) possibleCap;
List<IDataSetPO> datasets = cap.getDataManager().getDataSets();
if (datasets.size() == 1) {
IDataSetPO set = datasets.get(0);
int i = 0;
for (String string : set.getColumnStringValues()) {
if (StringUtils.contains(string,
srcDesc.getUniqueId())) {
return getDefaultValue(cap, i);
}
i++;
}
}
}
}
return null;
}
/**
* gets the default value for a index from a action
* @param cap the cap to get the default value from
* @param index the index
* @return the default value for the index or <code>null</code>
* if no default value is set
*/
private static String getDefaultValue(ICapPO cap, int index) {
List<Param> paramList = cap.getMetaAction().getParams();
if (paramList.size() > index) {
String defaultValue = paramList.get(index).getDefaultValue();
if (StringUtils.isNotBlank(defaultValue)) {
return defaultValue;
}
}
return null;
}
/**
* adds new parameter(s) to the parent, if the current node contains new
* references. This method doesn't validate, if it's allowed to change the interface.
* This validation has to run before.
* Updates the parametervalue of current node in model
* hint: if the user has removed a reference in current parameter value, the
* corresponding parameter of parent won't be deleted. A removal of parameters
* is only allowed, when the user calls the change parameters dialog.
*
* @param conv converter containing parameter value to update
* @param mapper mapper to resolve param names will be added
* @param row current dataset number
*/
protected abstract void updateParam(GuiParamValueConverter conv,
IParamNameMapper mapper, int row);
/**
* Updates the test data manager of the passed node by writing the
* value contained in converter into the appropriate cell.
*
* @param conv converter contains parameter value to write
* @param dataSetRow The row of the test data manager
*/
protected void writeTestDataEntry(GuiParamValueConverter conv,
int dataSetRow) {
String oldTd = null;
final IParamDescriptionPO desc = conv.getDesc();
IParameterInterfacePO currentNode = conv.getCurrentNode();
ITDManager dataManager = currentNode.getDataManager();
try {
oldTd = dataManager.getCell(dataSetRow,
desc);
} catch (IndexOutOfBoundsException e) { // NOPMD by al on 3/19/07 1:23 PM
// Nothing to be done
}
String td = createOrUpdateTestData(oldTd, conv);
if (dataManager.getDataSetCount() <= dataSetRow) {
addDataSet(currentNode, dataSetRow);
}
dataManager.updateCell(td, dataSetRow,
desc.getUniqueId());
}
/**
* Creates a new test data instance, if the passed test data is
* <code>null</code>, or updates the passed one with the given value.
*
* @param testData The existing test data or <code>null</code>
* @param conv converter with value to update
* @return The (new) test data instance.
* If the creation of the Test Data fails
*/
private String createOrUpdateTestData(String testData,
GuiParamValueConverter conv) {
// A new converter is instantiated and used here in order to cover
// the corner case described in bug http://eclip.se/370718.
GuiParamValueConverter newConv = new GuiParamValueConverter(
conv.getGuiString(), conv.getCurrentNode(),
conv.getDesc(),
AbstractParamInterfaceBP.createParamValueValidator(
TestDataConstants.STR, false));
return newConv.getModelString();
}
/**
* @param name
* the new name of the parameter
* @param type
* the type of the parameter
* @param obj
* the object to add the parameter for
* @param mapper
* the mapper to resolve param names
*/
public void addParameter(String name, String type,
IModifiableParameterInterfacePO obj, IParamNameMapper mapper) {
obj.addParameter(type, name, mapper);
}
/**
* @param desc
* the param to remove
* @param paramIntObj
* the object to remove the param from
*/
public abstract void removeParameter(IParamDescriptionPO desc,
T paramIntObj);
/**
* @param paramIntObj
* The object to change the parameter usage at.
* @param desc
* The old parameter for changing the usage at.
* @param guid
* The GUID of the new parameter usage.
* @param mapper The parameter name mapping.
*/
public abstract void changeUsageParameter(T paramIntObj,
IParamDescriptionPO desc, String guid,
ParamNameBPDecorator mapper);
/**
* @param desc
* the param to rename
* @param newName
* the new name
* @param mapper
* the mapper to use
*/
public void renameParameters(IParamDescriptionPO desc,
String newName, ParamNameBPDecorator mapper) {
mapper.addNameToUpdate(desc.getUniqueId(), newName);
}
/**
* @param type type of parameter
* @param valuesAreCombinable
* whether combinations of the supplied values are allowed
* @param values list of possible values for a parameter
* @return validator fit to given type
*/
public static IParamValueValidator createParamValueValidator(
String type, boolean valuesAreCombinable, String... values) {
if (TestDataConstants.INTEGER.equals(type)) {
return new IntegerParamValueValidator(Integer.MIN_VALUE,
Integer.MAX_VALUE, values);
}
if (values.length > 0) {
return new ComboParamValidator(values, valuesAreCombinable);
}
if (TestDataConstants.VARIABLE.equals(type)) {
return new VariableParamValueValidator();
}
return new NullValidator();
}
}