/******************************************************************************* * Copyright (c) 2005, 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.model; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import javax.persistence.CascadeType; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Query; import javax.persistence.Transient; import org.apache.commons.lang.StringUtils; import org.eclipse.jubula.client.core.businessprocess.AbstractParamInterfaceBP; import org.eclipse.jubula.client.core.businessprocess.ParamNameBP; import org.eclipse.jubula.client.core.businessprocess.TestDataBP; import org.eclipse.jubula.client.core.utils.ModelParamValueConverter; import org.eclipse.jubula.client.core.utils.ParamValueConverter; import org.eclipse.jubula.client.core.utils.RefToken; /** * base class for all nodes with parameters * @created 06.06.2005 */ @Entity @DiscriminatorValue(value = "A") abstract class ParamNodePO extends NodePO implements IParamNodePO { /** * delegate for managing the parameter interface and test data for * this node */ private TestDataCubePO m_parameterInterface; /** * @param name name of node * @param isGenerated indicates whether this node has been generated */ public ParamNodePO(String name, boolean isGenerated) { super(name, isGenerated); setParameterInterface(new TestDataCubePO(null)); } /** * @param name name of node * @param guid The GUID of the param node. * @param isGenerated indicates whether this node has been generated */ public ParamNodePO(String name, String guid, boolean isGenerated) { super(name, guid, isGenerated); setParameterInterface(new TestDataCubePO(null)); } /** * only for Persistence (JPA / EclipseLink) */ ParamNodePO() { // only for Persistence (JPA / EclipseLink) } /** * * @return the object responsible for maintaining the receiver's parameter * interface as well as test data. */ @OneToOne(cascade = CascadeType.ALL, targetEntity = TestDataCubePO.class, orphanRemoval = true, fetch = FetchType.EAGER) @JoinColumn(name = "FK_PARAM_INTERFACE", unique = true) // Do not use Batch fetching here this might lead to duplicate data // <and> problems that are caused by that fact see e.g. http://eclip.se/489220 private TestDataCubePO getParameterInterface() { return m_parameterInterface; } /** * Removes the associated TestDataCube from the DB * @param sess the session */ private void removeParamInterface(EntityManager sess) { m_parameterInterface.goingToBeDeleted(sess); Query q = sess.createNativeQuery("update NODE set FK_PARAM_INTERFACE = null where ID = ?1"); //$NON-NLS-1$ q.setParameter(1, getId()); q.executeUpdate(); q = sess.createNativeQuery("delete from PARAM_INTERFACE where ID = ?1"); //$NON-NLS-1$ q.setParameter(1, m_parameterInterface.getId()); q.executeUpdate(); } /** * * @param parameterInterface The new parameter interface for the receiver. */ private void setParameterInterface(TestDataCubePO parameterInterface) { m_parameterInterface = parameterInterface; } /** * * {@inheritDoc} */ @Transient public String getDataFile() { return getParameterInterface().getDataFile(); } /** * * {@inheritDoc} */ @Transient public ITDManager getDataManager() { return getParameterInterface().getDataManager(); } /** * * @return the data manager. */ @Transient protected ITDManager getHbmDataManager() { return getParameterInterface().getHbmDataManager(); } /** * Clears the parameter list. */ protected final void clearParameterList() { getParameterInterface().clearParameterList(); } /** * Add a parameter description to the list of descriptions * @param p <code>ParamDescriptionPO</code> to be added */ protected void addParameter(IParamDescriptionPO p) { getParameterInterface().addParameter(p); } /** * * @return parameters instance */ @Transient protected List<IParamDescriptionPO> getHbmParameterList() { return getParameterInterface().getHbmParameterList(); } /** * Remove a parameter description from the list of descriptions. This * is a method used by derived classes to work with the list. * @param p <code>ParamDescriptionPO</code> to be removed */ protected void removeParameter(IParamDescriptionPO p) { getParameterInterface().removeParameter(p); } /** * * {@inheritDoc} */ public IParamDescriptionPO getParameterForName(String paramName) { return getParameterInterface().getParameterForName(paramName); } /** * * {@inheritDoc} */ public IParamDescriptionPO getParameterForUniqueId(String uniqueId) { return getParameterInterface().getParameterForUniqueId(uniqueId); } /** * * {@inheritDoc} */ @Transient public List<IParamDescriptionPO> getParameterList() { return getParameterInterface().getParameterList(); } /** * * {@inheritDoc} */ @Transient public ListIterator<IParamDescriptionPO> getParameterListIter() { return getParameterInterface().getParameterListIter(); } /** * * {@inheritDoc} */ @Transient public int getParameterListSize() { return getParameterInterface().getParameterListSize(); } /** * * {@inheritDoc} */ @Transient public List<String> getParamNames() { return getParameterInterface().getParamNames(); } /** * * {@inheritDoc} */ @Transient public IParameterInterfacePO getReferencedDataCube() { return getParameterInterface().getReferencedDataCube(); } /** * * {@inheritDoc} */ public void setDataFile(String pathToExternalDataFile) { getParameterInterface().setDataFile(pathToExternalDataFile); } /** * * {@inheritDoc} */ public void setDataManager(ITDManager dataManager) { getParameterInterface().setDataManager(dataManager); } /** * * {@inheritDoc} */ public void setReferencedDataCube(IParameterInterfacePO dataCube) { getParameterInterface().setReferencedDataCube(dataCube); } /** {@inheritDoc} */ public boolean isTestDataComplete() { if (StringUtils.isEmpty(getDataFile())) { // Excel files are ignored. Other data is checked. final int paramListSize = getParameterListSize(); ITDManager testDataManager = getDataManager(); List<IParamDescriptionPO> requiredParameters = new ArrayList<IParamDescriptionPO>(getParameterList()); IParameterInterfacePO refDataCube = getReferencedDataCube(); for (int i = 0; i < testDataManager.getDataSetCount(); i++) { for (IParamDescriptionPO paramDesc : requiredParameters) { int column = testDataManager.findColumnForParam( paramDesc.getUniqueId()); if (refDataCube != null) { IParamDescriptionPO dataCubeParam = refDataCube.getParameterForName( paramDesc.getName()); if (dataCubeParam != null) { column = testDataManager.findColumnForParam( dataCubeParam.getUniqueId()); } } String value = TestDataBP.getTestData( this, testDataManager, paramDesc, i); if (StringUtils.isBlank(value) && column >= -1) { if (this instanceof IExecTestCasePO) { IExecTestCasePO exec = (IExecTestCasePO) this; String result = AbstractParamInterfaceBP .getValueForSpecNodeWithParamDesc(paramDesc, exec.getSpecTestCase()); if (value == null && StringUtils.isNotBlank(result)) { value = result; } if (StringUtils.isBlank(result)) { return false; } } } if (StringUtils.isNotEmpty(value)) { ModelParamValueConverter mpvc = new ModelParamValueConverter( value, this, paramDesc); List<RefToken> referenceTokens = mpvc.getRefTokens(); String uiValue = mpvc.getGuiString(); for (RefToken token : referenceTokens) { if (uiValue.contains(token.getModelString())) { return false; } } } else { if (this instanceof ICapPO) { ICapPO cap = (ICapPO) this; if (!ParamNameBP.isOptionalParameter( cap, paramDesc.getUniqueId())) { return false; } } else { return false; } } } } if ((testDataManager.getDataSetCount() == 0) && (paramListSize > 0)) { // this is needed if a Spec is the data holder return checkSpecForIncompleteData(); } } return true; } /** * checks if the instance of a spec is having default values * for all parameters * @return if the test data is complete */ private boolean checkSpecForIncompleteData() { ISpecTestCasePO thisSpec = null; if (this instanceof ISpecTestCasePO) { thisSpec = (ISpecTestCasePO) this; } else if (this instanceof IExecTestCasePO) { thisSpec = ((IExecTestCasePO)this).getSpecTestCase(); } if (thisSpec != null) { List<IParamDescriptionPO> specParameters = thisSpec.getParameterList(); boolean isComplete = true; for (IParamDescriptionPO paramDesc : specParameters) { String result = AbstractParamInterfaceBP .getValueForSpecNodeWithParamDesc( paramDesc, thisSpec); if (StringUtils.isBlank(result)) { isComplete = false; } } return isComplete; } return false; } /** * * {@inheritDoc} */ public Iterator<TDCell> getParamReferencesIterator() { List <TDCell> references = new ArrayList <TDCell> (); int row = 0; for (IDataSetPO dataSet : getDataManager().getDataSets()) { addParamReferences(references, dataSet, row); row++; } return references.iterator(); } /** {@inheritDoc} */ public Iterator<TDCell> getParamReferencesIterator( int dataSetRow) { IDataSetPO row = getDataManager().getDataSet(dataSetRow); List <TDCell> references = new ArrayList <TDCell> (); addParamReferences(references, row, dataSetRow); return references.iterator(); } /** * @param references * The references * @param row * The row representation * @param dataSetRow * The row index */ private void addParamReferences(List <TDCell> references, IDataSetPO row, int dataSetRow) { for (int col = 0; col < row.getColumnCount(); col++) { String testData = row.getValueAt(col); String uniqueId = getDataManager().getUniqueIds().get(col); IParamDescriptionPO desc = getParameterForUniqueId(uniqueId); ParamValueConverter conv = new ModelParamValueConverter( testData, this, desc); if (conv.containsReferences()) { references.add(new TDCell(testData, dataSetRow, col)); } } } /** * {@inheritDoc} */ public void setParentProjectId(Long projectId) { super.setParentProjectId(projectId); getDataManager().setParentProjectId(projectId); if (getParameterInterface() != null) { getParameterInterface().setParentProjectId(projectId); } } /** * {@inheritDoc} */ @Transient public INodePO getSpecificationUser() { return getSpecAncestor(); } /** * {@inheritDoc} */ public void clearTestData() { if (!hasReferencedTestData()) { getDataManager().clear(); } } /** * * @return <code>true</code> if the receiver references Test Data (for * example, by referencing a Central Test Data instance), rather * than having Test Data of its own. */ public boolean hasReferencedTestData() { return getReferencedDataCube() != null; } /** {@inheritDoc} */ public void goingToBeDeleted(EntityManager sess) { super.goingToBeDeleted(sess); removeParamInterface(sess); } }