/******************************************************************************* * 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.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.eclipse.jubula.client.core.businessprocess.ComponentNamesBP.CompNameCreationContext; import org.eclipse.jubula.client.core.model.ICapPO; import org.eclipse.jubula.client.core.model.ICompNamesPairPO; import org.eclipse.jubula.client.core.model.IComponentNamePO; import org.eclipse.jubula.client.core.model.IExecTestCasePO; import org.eclipse.jubula.client.core.model.INodePO; import org.eclipse.jubula.client.core.model.ISpecTestCasePO; import org.eclipse.jubula.client.core.model.PoMaker; import org.eclipse.jubula.tools.internal.constants.StringConstants; import org.eclipse.jubula.tools.internal.xml.businessmodell.Component; import org.eclipse.jubula.tools.internal.xml.businessmodell.ConcreteComponent; /** * This business process performs the override and propagate operations on * component names on the test execution node level. * * @author BREDEX GmbH * @created 08.09.2005 */ public class CompNamesBP { /** * Adds all propagated component name pairs of the test execution node to * the map <code>pairs</code>. * * @param pairs * The map * @param execNode * The test execution node */ private void addPropagatedPairs(Map<String, ICompNamesPairPO> pairs, IExecTestCasePO execNode) { for (ICompNamesPairPO pair : execNode.getCompNamesPairs()) { if (pair.isPropagated()) { String name = pair.getSecondName(); if (!pairs.containsKey(name)) { pairs.put(name, PoMaker.createCompNamesPairPO(name, StringConstants.EMPTY)); } } } } /** * Adds the component name of the passed test step to the map if the * component is not mapped by default. * * @param pairs * The map * @param capNode * The test step */ private void addCapComponentName(Map<String, ICompNamesPairPO> pairs, ICapPO capNode) { final Component component = capNode.getMetaComponentType(); if (component instanceof ConcreteComponent && ((ConcreteComponent)component).hasDefaultMapping()) { return; } final String name = capNode.getComponentName(); final String type = capNode.getComponentType(); if (!pairs.containsKey(name)) { ICompNamesPairPO pair = PoMaker.createCompNamesPairPO(name, type); pairs.put(name, pair); } } /** * Gets all component name pairs of the passed test execution node. The list * contains all pairs of the passed node itself, and the propagated pairs of * the child test execution nodes, and the component names of the child test * steps. * * @param execNode * The test execution node * @return The list with all component name pairs that (directly or * indirectly) belong to the passed node. The list is ordered by the * first names in ascending order. */ public List<ICompNamesPairPO> getAllCompNamesPairs( IExecTestCasePO execNode) { Map<String, ICompNamesPairPO> pairs = new HashMap<String, ICompNamesPairPO>(); for (ICompNamesPairPO pair : execNode.getCompNamesPairs()) { pairs.put(pair.getFirstName(), pair); } ISpecTestCasePO specNode = execNode.getSpecTestCase(); if (specNode != null) { for (Iterator it = specNode.getAllNodeIter(); it.hasNext();) { INodePO child = (INodePO) it.next(); if (child instanceof IExecTestCasePO) { addPropagatedPairs(pairs, (IExecTestCasePO) child); } else if (child instanceof ICapPO) { addCapComponentName(pairs, (ICapPO) child); } } } List<ICompNamesPairPO> pairList = new ArrayList<ICompNamesPairPO>(pairs.values()); // Sort the list by default Collections.sort(pairList, new Comparator<ICompNamesPairPO>() { public int compare(ICompNamesPairPO o1, ICompNamesPairPO o2) { return o1.getFirstName().compareTo(o2.getFirstName()); } }); return pairList; } /** * Updates the passed component name pair by setting the second name * property (that means, the overriding component name. * * @param execNode The test execution node * @param pair The component name pair * @param secondCompName The second component name * @param cache cache for componentNames. */ public void updateCompNamesPairNew(IExecTestCasePO execNode, ICompNamesPairPO pair, String secondCompName, IWritableComponentNameCache cache) { String secondName = cache.getGuidForName(secondCompName); if (StringUtils.equals(secondName, pair.getSecondName())) { return; } if (secondName == null) { final IComponentNamePO newComponentNamePO = cache.createComponentNamePO(secondCompName, pair.getType(), CompNameCreationContext.OVERRIDDEN_NAME); newComponentNamePO.setParentProjectId( execNode.getParentProjectId()); secondName = newComponentNamePO.getGuid(); } cache.changeReuse(pair, pair.getSecondName(), secondName); if (execNode.getCompNamesPair(pair.getFirstName()) == null) { execNode.addCompNamesPair(pair); } } /** * Finds the component name of the passed test step. The method searches for * the name in the passed tree path, which is exepected to be a top-down * path to the <code>capNode</code>. The <code>capNode</code> itself * may or may not be included as the last element of the list. Usually, the * tree path is determined by calling * {@link org.eclipse.jubula.client.core.utils.ITreeTraverserContext#getCurrentTreePath()}. * The result contains the component name and the node that is responsible * for defining the component name. This is the test step itself or the * execution node with the latest overriding. If a name is propagated * (overriden or not), the parent node is always responsible. * * @param treePath * The tree path * @param compNameDefiner * The node that is using the component name * @param compNameCache * The cache to use in order to resolve Component Name * references. * @param compNameGuid * The GUID of the component name. * @return The result containing the component name and the responsible node */ public CompNameResult findCompName(List<INodePO> treePath, INodePO compNameDefiner, String compNameGuid, IComponentNameCache compNameCache) { String currentName = compNameGuid; IComponentNamePO currentNamePo = compNameCache.getResCompNamePOByGuid(currentName); if (currentNamePo != null) { currentName = currentNamePo.getGuid(); } return findCompName(treePath, compNameCache, currentName, compNameDefiner); } /** * @param treePath * The tree path * @param compNameCache * The cache to use in order to resolve Component Name * references. * @param originalName * The GUID of the component name. * @param originalCompNameDefiner * The node that is using the component name * @return The result containing the component name and the responsible node */ private CompNameResult findCompName(List<INodePO> treePath, IComponentNameCache compNameCache, String originalName, INodePO originalCompNameDefiner) { String currentName = originalName; INodePO compNameDefiner = originalCompNameDefiner; IComponentNamePO currentNamePo; ListIterator<INodePO> it = treePath.listIterator(treePath.size()); while (it.hasPrevious()) { INodePO node = it.previous(); if (node instanceof IExecTestCasePO) { IExecTestCasePO execNode = (IExecTestCasePO)node; ICompNamesPairPO pair = null; if (!StringUtils.isEmpty(currentName)) { pair = execNode.getCompNamesPair(currentName); } if (pair != null) { currentName = pair.getSecondName(); currentNamePo = compNameCache.getResCompNamePOByGuid(currentName); if (currentNamePo != null) { currentName = currentNamePo.getGuid(); } if (pair.isPropagated()) { int index = it.previousIndex(); if (index > -1) { compNameDefiner = treePath.get(index); } } else { compNameDefiner = execNode; break; } } } } return new CompNameResult(currentName, compNameDefiner); } /** * Removes incorrect CompNamePairs from children of the given node. * @param cache the Component Name Cache * @param node CompNamePairs for children of this node will be analyzed. */ public static void removeIncorrectCompNamePairs( IWritableComponentNameCache cache, INodePO node) { if (!(node instanceof ISpecTestCasePO)) { return; } ISpecTestCasePO spec = (ISpecTestCasePO) node; CalcTypes.recalculateCompNamePairs(cache, spec); for (Iterator<INodePO> it = spec.getAllNodeIter(); it.hasNext(); ) { INodePO next = it.next(); if (next instanceof IExecTestCasePO) { IExecTestCasePO exec = (IExecTestCasePO) next; // we need to iterate over a copy of the collection // because we are removing elements during iteration for (ICompNamesPairPO pair : new LinkedList<ICompNamesPairPO>( exec.getCompNamesPairs())) { if (!isValidCompNamePair(pair)) { exec.removeCompNamesPair(pair.getFirstName()); } } } } } /** * @param pair the component name pair to check * @return true if the component name pair is valid */ public static boolean isValidCompNamePair(ICompNamesPairPO pair) { return pair.getType().length() != 0; } }