/*******************************************************************************
* 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.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.eclipse.jubula.client.core.businessprocess.importfilter.DataTable;
import org.eclipse.jubula.client.core.businessprocess.importfilter.ExcelImportFilter;
import org.eclipse.jubula.client.core.businessprocess.importfilter.IDataImportFilter;
import org.eclipse.jubula.client.core.businessprocess.importfilter.exceptions.DataReadException;
import org.eclipse.jubula.client.core.i18n.Messages;
import org.eclipse.jubula.client.core.model.IParamDescriptionPO;
import org.eclipse.jubula.client.core.model.IParamNodePO;
import org.eclipse.jubula.client.core.model.IParameterInterfacePO;
import org.eclipse.jubula.client.core.model.ITDManager;
import org.eclipse.jubula.client.core.model.PoMaker;
import org.eclipse.jubula.tools.internal.constants.StringConstants;
import org.eclipse.jubula.tools.internal.exception.IncompleteDataException;
import org.eclipse.jubula.tools.internal.exception.JBException;
import org.eclipse.jubula.tools.internal.messagehandling.MessageIDs;
import org.eclipse.osgi.util.NLS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Business class for handling with external data sources (e.g. Excel files)
*
* @author BREDEX GmbH
* @created Nov 3, 2005
*/
public class ExternalTestDataBP {
/** the logger */
private static final Logger LOG =
LoggerFactory.getLogger(ExternalTestDataBP.class);
/** this is where the datafile are stored */
private static File globalDataDir = new File(StringConstants.DOT);
/** import fiter*/
private List <IDataImportFilter> m_filter;
/**
* Cache for the read in data file
* Key = file name
* Value = DataTable
*/
private Map<File, DataTable> m_dataTableCache =
new HashMap<File, DataTable>();
/**
* Cache for ITDmanagerPOs
* Key = IParamNodePO
* Value = ITDManager
*/
private Map<IParamNodePO, ITDManager> m_tdManagerCache =
new HashMap<IParamNodePO, ITDManager>();
/**
* Constructor
*
*/
public ExternalTestDataBP() {
m_filter = new ArrayList <IDataImportFilter> ();
m_filter.add(new ExcelImportFilter());
}
/**
* Creates a new ITDManager for the given IParamNodePO filled with
* the data of the given file or gets the ITDManager from the cache.
* @param dataDir
* directory for data files
* @param file data source File
* @param node ParamNode
* @throws JBException error occured while reading data source
* @return filled TestDataManager
*/
private ITDManager createFilledTDManager(File dataDir, String file,
IParamNodePO node)
throws JBException {
ITDManager tdManager = m_tdManagerCache.get(node);
if (tdManager != null) {
return tdManager;
}
tdManager = PoMaker.createTDManagerPO(node);
// clear TDManager first
node.clearTestData();
// fill it again
DataTable dataTable = createDataTable(dataDir, file);
tdManager = parseTable(dataTable, node);
m_tdManagerCache.put(node, tdManager);
return tdManager;
}
/**
* Creates and returns a Data Manager populated with test data corresponding
* to the given arguments.
*
* @param referencedDataCube
* The cube from which test data will be retrieved.
* @param node
* The node containing the parameters that will use the generated
* data.
* @return the created Test Data Manager.
*/
private ITDManager createFilledTDManager(
IParameterInterfacePO referencedDataCube, IParamNodePO node) {
ITDManager tdManager = m_tdManagerCache.get(node);
if (tdManager != null) {
return tdManager;
}
tdManager = referencedDataCube.getDataManager();
m_tdManagerCache.put(node, tdManager);
return tdManager;
}
/**
* Creates a DataTable of the given file name with the given Locale or
* gets it from the cache if available.
* @param dataDir
* directory for data files
* @param filePath the path of the data source
* @return a DataTable
* @throws JBException id data source is not supported
*/
public DataTable createDataTable(File dataDir, String filePath)
throws JBException {
File dataFile = new File(filePath);
if (!dataFile.isAbsolute()) {
dataFile = new File(dataDir, filePath);
}
DataTable dataTable = m_dataTableCache.get(dataFile);
if (dataTable != null) {
return dataTable;
}
String dataFileName = String.valueOf(dataFile);
try {
IDataImportFilter filter = getFilterFromFileType(filePath);
if (filter != null) {
dataTable = filter.parse(dataDir, filePath);
m_dataTableCache.put(dataFile, dataTable);
return dataTable;
}
LOG.error(Messages.DataSource + StringConstants.COLON
+ StringConstants.SPACE + StringConstants.APOSTROPHE
+ dataFileName + StringConstants.APOSTROPHE
+ StringConstants.SPACE + Messages.NotSupported);
throw new JBException(
NLS.bind(Messages.ErrorMessageNOT_SUPP_DATASOURCE,
dataFileName),
MessageIDs.E_NOT_SUPP_DATASOURCE);
} catch (IOException e) {
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.ErrorReadingFile + StringConstants.COLON
+ StringConstants.SPACE + dataFileName, e);
}
throw new JBException(NLS.bind(
Messages.ErrorMessageNOT_SUPP_DATASOURCE,
dataFileName),
MessageIDs.E_DATASOURCE_FILE_IO);
} catch (DataReadException e) {
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.ErrorReadingFile + StringConstants.COLON
+ StringConstants.SPACE + dataFileName, e);
}
throw new JBException(NLS.bind(
Messages.ErrorMessageDATASOURCE_READ_ERROR,
dataFileName),
MessageIDs.E_DATASOURCE_READ_ERROR);
}
}
/**
* @param file file we will use as data source or null if file type is not
* supported.
* @return the filter type
*/
private IDataImportFilter getFilterFromFileType(String file) {
for (IDataImportFilter filter : m_filter) {
String[] extensions = filter.getFileExtensions();
for (String extension : extensions) {
if (extension != null && extension.length() > 0) {
if (file.endsWith(extension)) { // NOPMD by al on 3/19/07 1:22 PM
return filter;
}
}
}
}
return null;
}
/**
* update a given TestDataManager with data
*
* @param filledTable
* data extracted from File
* @param paramPo
* Parameter po we would like to update
* @return
* filled TestDataManager with new data
* @throws JBException
* error occurred while reading data source
*/
private ITDManager parseTable(DataTable filledTable,
IParameterInterfacePO paramPo) throws JBException {
return parseTable(filledTable, paramPo, false);
}
/**
* update a given TestDataManager with data
*
* @param filledTable
* data extracted from File
* @param paramPo
* Parameter po we would like to update
* @param useParamInterfaceTDMan
* true to use the original td manager of the passed param po;
* falso to create a new one
* @return filled TestDataManager with new data
* @throws JBException
* error occured while reading data source
*/
public ITDManager parseTable(DataTable filledTable,
IParameterInterfacePO paramPo, boolean useParamInterfaceTDMan)
throws JBException {
ITDManager tdMan;
if (useParamInterfaceTDMan) {
tdMan = paramPo.getDataManager();
} else {
tdMan = PoMaker.createTDManagerPO(paramPo);
}
// iterate over rows
List<String> paramNamesExcel =
new ArrayList<String>();
List <IParamDescriptionPO> paramNamesNode =
paramPo.getParameterList();
final int rowCount = filledTable.getRowCount();
for (int row = 0; row < rowCount; row++) {
final int columnCount = filledTable.getColumnCount();
for (int cellNr = 0; cellNr < columnCount; cellNr++) {
final String cellString = getTestDataForTDManager(filledTable,
row, cellNr);
if (row == 0) {
paramNamesExcel.add(cellString);
} else {
IParamDescriptionPO desc = paramPo
.getParameterForName(paramNamesExcel.get(cellNr));
if (desc != null) {
int dataSetNo = row - 1;
tdMan.updateCell(cellString,
dataSetNo, desc.getUniqueId());
}
}
}
}
for (IParamDescriptionPO desc : paramNamesNode) {
if (!paramNamesExcel.contains(desc.getName())) {
throw new JBException(NLS.bind(
Messages.ErrorMessageDATASOURCE_MISSING_PARAMETER,
new Object[] { desc.getName(),
paramPo.getName(),
paramPo.getDataFile()}),
MessageIDs.E_DATASOURCE_MISSING_PARAMETER);
}
}
if (rowCount == 1) {
throw new JBException(
Messages.ErrorMessageDATASOURCE_MISSING_VALUES,
MessageIDs.E_DATASOURCE_MISSING_VALUES);
}
return tdMan;
}
/**
* Gets the value for the TestDataManager from the given DataTable.
* Any internal Jubula-Symbols (References, Variables, etc.) will be
* converted into the right format.
* @param filledTable The DataTable of the Excel-file
* @param row the row number
* @param column the column number
* @return the value for the TDManager
* @throws IncompleteDataException if data are incomplete
*/
private String getTestDataForTDManager(DataTable filledTable,
int row, int column) throws IncompleteDataException {
String cellString = filledTable.getData(row, column);
if (cellString == null || cellString.length() == 0) {
MessageIDs.getMessageObject(
MessageIDs.E_DATASOURCE_CONTAIN_EMPTY_DATA).setDetails(
new String[] {});
throw new IncompleteDataException(MessageIDs.getMessage(
MessageIDs.E_DATASOURCE_CONTAIN_EMPTY_DATA)
+ StringConstants.NEWLINE
+ NLS.bind(Messages
.ErrorDetailDATASOURCE_CONTAIN_EMPTY_DATA,
new Object[] {row + 1, column + 1}),
MessageIDs.E_DATASOURCE_CONTAIN_EMPTY_DATA);
}
return cellString;
}
/**
* Gets the ITDManager for the given IParamNodePO which has a file as
* data source.<br>
* If the given IParamNodePO has regular data,its ITDManager
* will be returned.
* @param paramNode ParamNode
* @return the usable TDManager
* @throws JBException
* occurring Exception while creating TDManager
*/
public ITDManager getExternalCheckedTDManager(IParamNodePO paramNode)
throws JBException {
boolean isTestRunning =
TestExecution.getInstance().getStartedTestSuite() != null
&& TestExecution.getInstance().getStartedTestSuite().isStarted()
&& TestExecution.getInstance().getConnectedAut() != null;
return getExternalCheckedTDManager(paramNode, isTestRunning);
}
/**
* Retrieves or generates a Test Data Manager for the given arguments. If
* the provided <code>paramNode</code> manages its own data, then its
* Test Data Manager is retrieved and returned. Otherwise, a Test Data
* Manager corresponding to:
* <ul>
* <li>the external data referenced by <code>paramNode</code></li>
* <li>the provided locale</li>
* </ul>
* is generated and returned.
*
* @param paramNode
* The node for which to retrieve / generate a Data Manager.
* Must not be <code>null</code>.
* @param retrieveExternalData
* Flag for forcing retrieval of external test data. If the
* provided node requires external data and this flag is set to
* <code>false</code>, then an empty Data Manager will be
* returned.
*
* @return the retrieved or generated Test Data Manager.
* @throws JBException
* if an error occurs while reading an external data source.
*/
public ITDManager getExternalCheckedTDManager(
IParamNodePO paramNode,
boolean retrieveExternalData) throws JBException {
Validate.notNull(paramNode);
boolean usesExternalDataFile =
StringUtils.isNotEmpty(paramNode.getDataFile());
boolean usesReferencedDataCube =
paramNode.getReferencedDataCube() != null;
if (!usesExternalDataFile && !usesReferencedDataCube) {
return paramNode.getDataManager();
}
if (!retrieveExternalData) {
ITDManager tdManager = PoMaker.createTDManagerPO(paramNode);
return tdManager;
}
if (usesExternalDataFile) {
return createFilledTDManager(globalDataDir, paramNode.getDataFile(),
paramNode);
} else if (usesReferencedDataCube) {
return createFilledTDManager(
paramNode.getReferencedDataCube(), paramNode);
}
LOG.error(Messages.UnknownSourceType + StringConstants.COLON
+ StringConstants.SPACE + paramNode.getName());
return null;
}
/**
* Clears this ExternalTestDataBP (e.g. the caches) after TestExecution
* has finished.
*/
public void clearExternalData() {
m_dataTableCache.clear();
m_tdManagerCache.clear();
}
/**
* @return the dataDir
*/
public static File getDataDir() {
return globalDataDir;
}
/**
* @param dataDir the dataDir to set
*/
public static void setDataDir(File dataDir) {
globalDataDir = dataDir;
}
}