org.eclipse.jubula.client.core.businessprocess.ComponentNamesBP.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jubula.client.core.businessprocess.ComponentNamesBP.java

Source

/*******************************************************************************
 * 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.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jubula.client.core.businessprocess.treeoperations.CheckIfComponentNameIsReusedOp;
import org.eclipse.jubula.client.core.businessprocess.treeoperations.FindNodesForComponentNameOp;
import org.eclipse.jubula.client.core.i18n.Messages;
import org.eclipse.jubula.client.core.model.IAUTMainPO;
import org.eclipse.jubula.client.core.model.ICapPO;
import org.eclipse.jubula.client.core.model.IComponentNameData;
import org.eclipse.jubula.client.core.model.IComponentNamePO;
import org.eclipse.jubula.client.core.model.INodePO;
import org.eclipse.jubula.client.core.model.IObjectMappingAssoziationPO;
import org.eclipse.jubula.client.core.model.IProjectPO;
import org.eclipse.jubula.client.core.model.IReusedProjectPO;
import org.eclipse.jubula.client.core.model.ITestSuitePO;
import org.eclipse.jubula.client.core.model.PoMaker;
import org.eclipse.jubula.client.core.persistence.CompNamePM;
import org.eclipse.jubula.client.core.persistence.GeneralStorage;
import org.eclipse.jubula.client.core.persistence.ISpecPersistable;
import org.eclipse.jubula.client.core.persistence.IncompatibleTypeException;
import org.eclipse.jubula.client.core.persistence.PMAlreadyLockedException;
import org.eclipse.jubula.client.core.persistence.PMDirtyVersionException;
import org.eclipse.jubula.client.core.persistence.PMException;
import org.eclipse.jubula.client.core.persistence.PMObjectDeletedException;
import org.eclipse.jubula.client.core.persistence.PersistenceUtil;
import org.eclipse.jubula.client.core.persistence.ProjectPM;
import org.eclipse.jubula.client.core.persistence.locking.LockManager;
import org.eclipse.jubula.client.core.utils.StringHelper;
import org.eclipse.jubula.client.core.utils.TreeTraverser;
import org.eclipse.jubula.toolkit.common.xml.businessprocess.ComponentBuilder;
import org.eclipse.jubula.tools.constants.StringConstants;
import org.eclipse.jubula.tools.exception.Assert;
import org.eclipse.jubula.tools.exception.JBException;
import org.eclipse.jubula.tools.exception.JBFatalException;
import org.eclipse.jubula.tools.messagehandling.MessageIDs;
import org.eclipse.jubula.tools.xml.businessmodell.CompSystem;
import org.eclipse.jubula.tools.xml.businessmodell.Component;
import org.eclipse.osgi.util.NLS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Acts as a Component Name cache for the master session.
 *
 * @author BREDEX GmbH
 * @created Apr 9, 2008
 */
public class ComponentNamesBP extends AbstractNameBP<IComponentNamePO> implements IComponentNameCache {

    /** i18n key for the "unknown" component type */
    public static final String UNKNOWN_COMPONENT_TYPE = "guidancer.abstract.Unknown"; //$NON-NLS-1$

    /**
     * <code>log</code> logger for class
     */
    private static Logger log = LoggerFactory.getLogger(ComponentNamesBP.class);

    /**
     * @author BREDEX GmbH
     * @created Apr 16, 2008
     */
    public enum CompNameCreationContext {
        /** ObjectMapping-Editor context*/
        OBJECT_MAPPING,
        /** Overriden name context */
        OVERRIDDEN_NAME,
        /** Test Step context */
        STEP;

        /** for toString and forName */
        private static final String OBJECT_MAPPING_CTX = "OBJECT_MAPPING"; //$NON-NLS-1$

        /** for toString and forName */
        private static final String OVERRIDDEN_NAME_CTX = "OVERRIDDEN_NAME"; //$NON-NLS-1$

        /** for toString and forName */
        private static final String STEP_CTX = "STEP"; //$NON-NLS-1$

        /**
         * 
         * {@inheritDoc}
         */
        public String toString() {
            switch (this) {
            case OBJECT_MAPPING:
                return OBJECT_MAPPING_CTX;
            case OVERRIDDEN_NAME:
                return OVERRIDDEN_NAME_CTX;
            case STEP:
                return STEP_CTX;
            default:
                // nothing
            }
            Assert.notReached("Missing toString representation for CompNameCreationContext"); //$NON-NLS-1$
            return StringConstants.EMPTY;
        }

        /**
         * 
         * @param name a toString representation of a CompNameCreationContext.
         * @return a CompNameCreationContext
         */
        public static CompNameCreationContext forName(String name) {
            if (OBJECT_MAPPING_CTX.equalsIgnoreCase(name)) {
                return OBJECT_MAPPING;
            }
            if (OVERRIDDEN_NAME_CTX.equalsIgnoreCase(name)) {
                return OVERRIDDEN_NAME;
            }
            if (STEP_CTX.equalsIgnoreCase(name)) {
                return STEP;
            }
            Assert.notReached("No CompNameCreationContext for '" //$NON-NLS-1$
                    + String.valueOf(name) + "'"); //$NON-NLS-1$
            return null;
        }
    }

    /** The singleton instance */
    private static ComponentNamesBP instance = null;

    /**
     * Singleton Constructor.
     */
    private ComponentNamesBP() {
        //

    }

    /**
     * @return The singleton instance.
     */
    public static final ComponentNamesBP getInstance() {
        if (instance == null) {
            instance = new ComponentNamesBP();
        }
        return instance;
    }

    /**
     * Adds the given NAME_PO to the chache.<br>
     * This method is null-safe!
     * @param compName namePO object
     */
    public final void addComponentNamePO(IComponentNamePO compName) {
        addNamePO(compName);
    }

    /**
     * 
     * @param guid a GUID
     */
    public final void removeComponentNamePO(String guid) {
        removeNamePO(guid);
    }

    /**
     * {@inheritDoc}
     */
    public String getGuidForName(String name, Long parentProjectId) {
        for (IComponentNamePO compName : getAllNamePOs()) {
            if (compName.getName().equals(name) && parentProjectId.equals(compName.getParentProjectId())) {
                return compName.getGuid();
            }
        }
        return null;
    }

    /**
     * 
     * @param guid the GUID of the Component Name.
     * @return the display name of the Component Name with the given GUID of 
     * the current Project.
     */
    public final String getName(String guid) {
        return getName(guid, GeneralStorage.getInstance().getProject().getId());
    }

    /**
     * {@inheritDoc}
     */
    public final String getName(String guid, Long rootProjId) {
        // fallback, show uniqueId, if no name for component is available
        String name = guid;
        IComponentNamePO namePO = getNamePO(guid);
        if (namePO == null) {
            // try to get component name from used Projects
            final IProjectPO currProj = GeneralStorage.getInstance().getProject();
            try {
                namePO = getCompNamePoImpl(currProj.getGuid(), guid, null, currProj.getMajorProjectVersion(),
                        currProj.getMinorProjectVersion());
                addComponentNamePO(namePO);
            } catch (JBException e) {
                throw new JBFatalException(e, MessageIDs.E_DATABASE_GENERAL);
            }
        }
        if (namePO != null) {
            if (namePO.getReferencedGuid() != null) {
                return getName(namePO.getReferencedGuid(), rootProjId);
            }
            name = namePO.getName();
        } else {
            // This can happen legally if there is an unused overridden 
            // Component Name which was formerly propagated. 
            if (log.isDebugEnabled()) {
                log.debug(Messages.EmptyComponentName + StringConstants.SPACE + StringConstants.EQUALS_SIGN
                        + StringConstants.SPACE + rootProjId + " uniqueId = " + guid); //$NON-NLS-1$
            }
        }
        return name;
    }

    /**
     * reads all paramNames of the current Project and its reused Projects 
     * from database into names map
     * @throws PMException in case of an (unexpected) DB access problem
     */
    public final void init() throws PMException {
        clearAllNamePOs();
        final IProjectPO currProject = GeneralStorage.getInstance().getProject();
        initCompNamesTransitive(currProject.getId(), new HashSet<Long>());
    }

    /**
     * reads all paramNames of the given Project and its reused Projects 
     * from database into names map
     * @param projectID an IProjectPO id
     * @param loadedProjectIds Accumulated IDs of reused projects that have 
     *                         been loaded.
     * @throws PMException in case of an (unexpected) DB access problem
     */
    private void initCompNamesTransitive(Long projectID, Set<Long> loadedProjectIds) throws PMException {

        if (projectID == null) {
            return;
        }
        readCompNamesForProjectID(projectID);
        for (IReusedProjectPO usedProj : ProjectPM.getReusedProjectsForProject(projectID)) {
            final String reusedGuid = usedProj.getProjectGuid();
            final int reuseMajVers = usedProj.getMajorNumber();
            final int reuseMinVers = usedProj.getMinorNumber();
            try {
                final Long usedProjPo = ProjectPM.findProjectIDByGuidAndVersion(reusedGuid, reuseMajVers,
                        reuseMinVers);
                if (usedProjPo != null && loadedProjectIds.add(usedProjPo)) {
                    initCompNamesTransitive(usedProjPo, loadedProjectIds);
                }
            } catch (JBException e) {
                // Continue! Maybe the Project is not present in DB.
            }
        }
    }

    /**
     * reads all paramNames of the Project with the given ID from database 
     * into names map
     * @param projId the Project ID.
     * @throws PMException PMException in case of any db problem
     */
    private void readCompNamesForProjectID(Long projId) throws PMException {
        List<IComponentNamePO> names = CompNamePM.readAllCompNames(projId);
        for (IComponentNamePO compNamePO : names) {
            addNamePO(compNamePO);
        }
    }

    /**
     * reads all paramNames of the Project with the given ID from database 
     * into names map
     * @param projId projId the Project ID.
     * @throws PMException PMException PMException in case of any db problem
     */
    public final void refreshNames(Long projId) throws PMException {
        readCompNamesForProjectID(projId);
    }

    /**
     * 
     * @return all IComponentNamePOs of the current project and its reused 
     * Projects.
     */
    public final Collection<IComponentNamePO> getAllComponentNamePOs() {
        return getAllNamePOs();
    }

    /**
     * @param projId a Project ID
     * @return all IComponentNamePOs of the project with the given Project ID.
     */
    public final Collection<IComponentNamePO> getAllComponentNamePOs(Long projId) throws PMException {

        return CompNamePM.readAllCompNamesRO(projId);
    }

    /**
     * @param projId a Project ID
     * @return all IComponentNamePOs of the project with the given Project ID.
     */
    public final Collection<IComponentNamePO> getAllNonRefCompNamePOs(Long projId) throws PMException {

        Collection<IComponentNamePO> allCompNamePOs = getAllComponentNamePOs(projId);

        CollectionUtils.filter(allCompNamePOs, new Predicate() {

            public boolean evaluate(Object object) {
                if (object instanceof IComponentNamePO) {
                    return ((IComponentNamePO) object).getReferencedGuid() == null;
                }
                return false;
            }

        });

        return allCompNamePOs;
    }

    /**
     * Creates a new IComponentNamePO and puts it in the list of 
     * IComponentNamePO to persist.
     * @param guid a GUID, can be null. If null, a GUID will be created.
     * @param name the name.
     * @param type the type 
     * @param ctx the CompNameCreationContext.
     * @return a new IComponentNamePO.
     * @see #createComponentNamePO(String, String, CompNameCreationContext)
     */
    public final IComponentNamePO createComponentNamePO(String guid, String name, String type,
            CompNameCreationContext ctx) {

        String nameGuid = guid;
        if (guid == null) {
            nameGuid = PersistenceUtil.generateGuid();
        }
        final IComponentNamePO newComponentNamePO = PoMaker.createComponentNamePO(nameGuid, name, type, ctx,
                GeneralStorage.getInstance().getProject().getId());
        addComponentNamePO(newComponentNamePO);
        return newComponentNamePO;
    }

    /**
     * Gets an IComponentNamePO from the database with the help of the given 
     * Parameters.
     * @param compNameGuid The GUID of the IComponentNamePO which is to load.
     * @param compNameParentProjGuid The ParentProjectGUID of the 
     * IComponentNamePO which is to load.
     * @return an IComponentNamePO or null if not found
     * @throws JBException in case of any db problem.
     */
    public final IComponentNamePO getCompNamePo(String compNameGuid, String compNameParentProjGuid)
            throws JBException {

        final IProjectPO currProject = GeneralStorage.getInstance().getProject();
        final String currGuid = currProject.getGuid();
        if (currGuid.equals(compNameParentProjGuid)) {
            return loadCompNamePoImpl(compNameGuid, currGuid, currProject.getMajorProjectVersion(),
                    currProject.getMinorProjectVersion());
        }

        return getCompNamePoImpl(currProject.getGuid(), compNameGuid, compNameParentProjGuid,
                currProject.getMajorProjectVersion(), currProject.getMinorProjectVersion());
    }

    /**
     * Gets an IComponentNamePO with the given Parameters.
     * @param projToSearchGuid The GUID of the Project to search for the 
     * IComponentNamePO
     * @param compNameGuid The GUID of the IComponentNamePO which is to load.
     * @param compNameParentProjGuid The ParentProjectGUID of the 
     * IComponentNamePO which is to load.
     * Can be null. If it is null, the search for the IComponentNamePO begins
     * in the used Projects of the Project with the given projToSearchGuid and 
     * projMajVers and projMinVers. Otherwise the search start in the given
     * Project itself.
     * @param projMajVers the Major Version of the ParentProject of the wanted 
     * IComponentNamePO.
     * @param projMinVers the Minor Version of the ParentProject of the wanted 
     * IComponentNamePO.
     * @return an IComponentNamePO or null if not found.
     * @throws JBException in case of any db problem.
     */
    private IComponentNamePO getCompNamePoImpl(String projToSearchGuid, String compNameGuid,
            String compNameParentProjGuid, Integer projMajVers, Integer projMinVers) throws JBException {

        if (compNameParentProjGuid != null) {
            IComponentNamePO compNamePo = loadCompNamePoImpl(compNameGuid, compNameParentProjGuid, projMajVers,
                    projMinVers);
            if (compNamePo != null) {
                return compNamePo;
            }
        }

        List<IReusedProjectPO> reusedProjList = ProjectPM.loadReusedProjectsRO(projToSearchGuid, projMajVers,
                projMinVers);
        for (IReusedProjectPO reusedProj : reusedProjList) {
            final Integer reusedMajVers = reusedProj.getMajorNumber();
            final Integer reusedMinVers = reusedProj.getMinorNumber();
            final String reusedGuid = reusedProj.getProjectGuid();
            IComponentNamePO compNamePo = null;
            if (StringUtils.equals(compNameParentProjGuid, reusedGuid)) {
                compNamePo = loadCompNamePoImpl(compNameGuid, reusedGuid, reusedMajVers, reusedMinVers);
                if (compNamePo != null) {
                    return compNamePo;
                }
            }
            compNamePo = getCompNamePoImpl(reusedGuid, compNameGuid, reusedGuid, reusedMajVers, reusedMinVers);
            if (compNamePo != null) {
                return compNamePo;
            }
        }
        return null;
    }

    /**
     * Loads an IComponentNamePO
     * @param compNameGuid The GUID of the IComponentNamePO which is to load.
     * @param compNameParentProjGuid The ParentProjectGUID of the 
     * IComponentNamePO which is to load.
     * @param projMajVers the Major Version of the ParentProject of the wanted 
     * IComponentNamePO.
     * @param projMinVers the Minor Version of the ParentProject of the wanted 
     * IComponentNamePO.
     * @return an IComponentNamePO or null if not found.
     * @throws JBException in case of any db problem.
     */
    private IComponentNamePO loadCompNamePoImpl(String compNameGuid, String compNameParentProjGuid,
            Integer projMajVers, Integer projMinVers) throws JBException {

        IComponentNamePO compNamePO = null;
        final Long projId = ProjectPM.findProjectId(compNameParentProjGuid, projMajVers, projMinVers);
        if (projId != null) {
            compNamePO = CompNamePM.loadCompName(compNameGuid, projId);
        }
        return compNamePO;
    }

    /**
     * 
     * {@inheritDoc}
     */
    public final IComponentNamePO getCompNamePo(String guid) {
        return getCompNamePo(guid, true);
    }

    /**
     * 
     * {@inheritDoc}
     */
    public final IComponentNamePO getCompNamePo(String guid, boolean resolveRefs) {

        IComponentNamePO compNamePO = getNamePO(guid);
        if (compNamePO != null) {
            if (resolveRefs && compNamePO.getReferencedGuid() != null) {
                return getCompNamePo(compNamePO.getReferencedGuid(), resolveRefs);
            }
            return compNamePO;

        }
        return null;
    }

    /**
     * Gets the IComponentNamePO of the given name
     * @param name a name
     * @return an IComponentNamePO or null if not found.
     */
    public final IComponentNamePO getCompNamePoByName(String name) {
        for (IComponentNamePO compNamePO : getAllComponentNamePOs()) {
            if (name.equals(compNamePO.getName())) {
                return compNamePO;
            }
        }
        return null;
    }

    /**
     * Updates the Component Type of the IComponentNamePO with the given guid.
     * @param guid the GUID of the IComponentNamePO to update.
     * @param componentType the Component Type.
     */
    public void updateType(String guid, String componentType) {
        final IComponentNamePO compNamePo = getCompNamePo(guid);
        compNamePo.setComponentType(componentType);
    }

    /**
     * @param componentName The name of the Component Name for which the
     *                      the type should be computed. This is used to 
     *                      determine if a default mapping exists and
     *                      should be used.
     * @param types The Component Types to be included in the computation.
     * @return The most concrete visible type of the given types, 
     *         or <code>null</code> if the types are incompatible.
     */
    public String computeComponentType(String componentName, Set<String> types) {

        if (types.contains(null) || types.contains(StringConstants.EMPTY)) {
            // Used types contains at least one invalid entry
            return UNKNOWN_COMPONENT_TYPE;
        }

        CompSystem compSystem = ComponentBuilder.getInstance().getCompSystem();
        Set<Component> components = new HashSet<Component>();
        for (String compType : types) {
            Component comp = compSystem.findComponent(compType);
            comp = getMostConcreteVisibleAncestor(comp, compSystem);
            components.add(comp);
        }
        if (components.isEmpty()) {
            components.add(compSystem.getMostAbstractComponent());
        }
        Component mostConcreteComponent = compSystem
                .getMostConcrete(components.toArray(new Component[components.size()]));
        if (mostConcreteComponent == null) {
            return null;
        }

        String compType = mostConcreteComponent.getType();

        mostConcreteComponent = getMostConcreteVisibleAncestor(mostConcreteComponent, compSystem);

        // Use the most concrete visible type, if one is available
        if (mostConcreteComponent != null) {
            compType = mostConcreteComponent.getType();
        }

        return compType;
    }

    /**
     * Find the most concrete visible ancestor of the given component.
     * 
     * @param component The component for which to find the most concrete
     *                  visible ancestor.
     * @param compSystem The component system to use to perform the search.
     * @return the most concrete, visible ancestor of <code>component</code>, 
     *         which may be <code>component</code> itself. 
     *         Returns <code>null</code> if <code>component</code> and
     *         its ancestors are all invisible.
     */
    @SuppressWarnings("unchecked")
    private Component getMostConcreteVisibleAncestor(Component component, CompSystem compSystem) {

        Component comp = component;
        while (comp != null && !comp.isVisible()) {
            Set<Component> realized = comp.getAllRealized();
            comp = compSystem.getMostConcrete(realized.toArray(new Component[realized.size()]));
        }
        return comp;
    }

    /**
     * Checks whether the given checkable name is compatible with the 
     * given component type. Returns <code>null</code> if the types are 
     * compatible.
     * @param originalCompType The component type that determines the 
     *                         compatibility.
     * @param checkableName The component name for which to check the 
     *                      compatibility.
     * @param compNameMapper The mapper to use for Component Name information.
     * @param projectId The ID of the Project to be searched. May be 
     *                  <code>null</code>. If this value is not 
     *                  <code>null</code>, only Component Names belonging to 
     *                  the Project with the given ID will be examined. 
     * @param isSimpleMatch if <code>true</code> only the check for checkable
     *                  is compatible with original is done      
     * @return appropriate error message if <code>checkableName</code> is a 
     *         reserved name or if <code>checkableName</code> is found in the 
     *         component names list and the component represented by 
     *         <code>checkableName</code> is incompatible with 
     *         <code>originalCompType</code>. Otherwise, <code>null</code>.
     */
    public String isCompatible(String originalCompType, String checkableName, IComponentNameMapper compNameMapper,
            Long projectId, boolean isSimpleMatch) {

        IComponentNameCache compNameCache = compNameMapper.getCompNameCache();

        Set<IComponentNameData> componentNameDataSet = compNameCache.getComponentNameData();

        IComponentNameData compNameData = null;
        for (IComponentNameData cnd : componentNameDataSet) {
            if ((projectId == null || cnd.getParentProjectId() == null
                    || cnd.getParentProjectId().equals(projectId)) && cnd.getName().equals(checkableName)) {

                compNameData = cnd;
                break;
            }
        }

        if (compNameData == null) {
            return null;
        }

        Set<String> usedTypes = compNameMapper.getUsedTypes(compNameData.getGuid());

        final String computedType = ComponentNamesBP.getInstance().computeComponentType(checkableName, usedTypes);
        Component originalComponent = getComponent(originalCompType);
        Component checkableComponent = getComponent(computedType);
        if (checkableComponent.isCompatibleWith(originalComponent.getType())) {
            return null;
        }
        if (isSimpleMatch) {
            return NLS.bind(Messages.CompNameIncompatibleTypeDetail,
                    new Object[] { checkableName,
                            StringHelper.getInstance().get(checkableComponent.getType(), true),
                            StringHelper.getInstance().get(originalComponent.getType(), true) });
        }

        String compNameGuid = compNameCache.getGuidForName(checkableName);
        final IComponentNamePO namePO = compNameCache.getCompNamePo(compNameGuid);
        final boolean currProj = namePO == null ? false
                : namePO.getParentProjectId() == null
                        || GeneralStorage.getInstance().getProject().getId().equals(namePO.getParentProjectId());

        if (currProj && originalComponent.isCompatibleWith(checkableComponent.getType())) {

            return null;
        }
        if (UNKNOWN_COMPONENT_TYPE.equals(computedType)) {
            // Computed component type is "unknown"
            return NLS.bind(Messages.CompNameUnknownTypeDetail, namePO != null ? namePO.getName() : checkableName);
        }
        return NLS.bind(Messages.CompNameIncompatibleTypeDetail,
                new Object[] { namePO != null ? namePO.getName() : checkableName,
                        StringHelper.getInstance().get(checkableComponent.getType(), true),
                        StringHelper.getInstance().get(originalComponent.getType(), true) });
    }

    /**
     * Checks whether the given checkable name is compatible with the 
     * given component type. Returns <code>null</code> if the types are 
     * compatible.
     * @param originalCompType The component type that determines the 
     *                         compatibility.
     * @param checkableName The component name for which to check the 
     *                      compatibility.
     * @param compNameMapper The mapper to use for Component Name information.
     * @param projectId The ID of the Project to be searched. May be 
     *                  <code>null</code>. If this value is not 
     *                  <code>null</code>, only Component Names belonging to 
     *                  the Project with the given ID will be examined. 
     * @return appropriate error message if <code>checkableName</code> is a 
     *         reserved name or if <code>checkableName</code> is found in the 
     *         component names list and the component represented by 
     *         <code>checkableName</code> is incompatible with 
     *         <code>originalCompType</code>. Otherwise, <code>null</code>.
     */
    public String isCompatible(String originalCompType, String checkableName, IComponentNameMapper compNameMapper,
            Long projectId) {
        return isCompatible(originalCompType, checkableName, compNameMapper, projectId, false);

    }

    /**
     * Gets the Component with the given typeName.
     * @param typeName a type of a Component.
     * @return the Component with the given typeName.
     */
    private Component getComponent(String typeName) {
        final CompSystem compSystem = ComponentBuilder.getInstance().getCompSystem();
        if (typeName == null) {
            return compSystem.getMostAbstractComponent();
        }
        return compSystem.findComponent(typeName);
    }

    /**
     * Sets the Component Name for the given Test Step.
     * 
     * @param capPo The Test Step for which to set the Component Name.
     * @param compName The name of the Component Name to use.
     * @param ctx The creation context of the Component Name.
     * @param compMapper The Component Name mapper responsible for the given 
     *                   Test Step.
     * @throws IncompatibleTypeException if the Component Type for the 
     *                                   Component Name to use is incompatible
     *                                   with the Component Type of the given
     *                                   Test Step.
     * @throws PMException if a database error occurs. 
     */
    public void setCompName(ICapPO capPo, String compName, CompNameCreationContext ctx,
            IWritableComponentNameMapper compMapper) throws IncompatibleTypeException, PMException {

        String oldName = capPo.getComponentName();
        String oldGuid = compMapper.getCompNameCache().getGuidForName(oldName);

        if (StringUtils.isBlank(compName)) {
            compMapper.changeReuse(capPo, oldGuid, null);
        } else {
            String guidToSet = compMapper.getCompNameCache().getGuidForName(compName,
                    GeneralStorage.getInstance().getProject().getId());
            if (guidToSet == null) {
                final IComponentNamePO newComponentNamePO = compMapper.getCompNameCache()
                        .createComponentNamePO(compName, capPo.getComponentType(), ctx);
                if (capPo.getParentProjectId() != null) {
                    newComponentNamePO.setParentProjectId(capPo.getParentProjectId());
                }
                guidToSet = newComponentNamePO.getGuid();
            }

            compMapper.changeReuse(capPo, oldGuid, guidToSet);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void clear() {
        clearAllNamePOs();
    }

    /**
     * {@inheritDoc}
     */
    public Set<IComponentNameData> getComponentNameData() {
        Set<IComponentNameData> retVal = new HashSet<IComponentNameData>();
        retVal.addAll(getAllComponentNamePOs());
        return retVal;
    }

    /**
     * {@inheritDoc}
     */
    public Set<IComponentNameData> getLocalComponentNameData() {
        return Collections.emptySet();
    }

    /**
     * {@inheritDoc}
     */
    public void updateStandardMapperAndCleanup(Long activeProjectId) {
        // This is the standard mapper, so do nothing.
    }

    /**
     * Finds all instances of reuse of a Component Name within the given 
     * objects.
     * 
     * @param specsToSearch The Test Cases and Categories to search 
     *                      (recursively).
     * @param suitesToSearch The Test Suites to search.
     * @param autsToSearch The AUTs for which to search through the 
     *                     Object Mapping.
     * @param compNameGuid The GUID of the Component Name for which to find the
     *                    instances of reuse.
     * @return <code>true</code> if the Component Name with GUID 
     *         <code>compNameGuid</code> is used within 
     *         <code>specsToSearch</code> and/or <code>autsToSearch</code>.
     *         Otherwise, <code>false</code>.
     */
    public boolean isCompNameReused(Collection<ISpecPersistable> specsToSearch,
            Collection<ITestSuitePO> suitesToSearch, Collection<IAUTMainPO> autsToSearch, String compNameGuid) {

        return !findAssocsOfReuse(autsToSearch, compNameGuid).isEmpty()
                || isCompNameReused(specsToSearch, suitesToSearch, compNameGuid);
    }

    /**
     * 
     * @param specsToSearch The Test Cases and Categories to search 
     *                      (recursively).
     * @param suitesToSearch The Test Suites to search.
     * @param compNameGuid The GUID of the Component Name for which to find 
     *                     whether it is reused.
     * @return <code>true</code> if the Component Name with GUID 
     *         <code>compNameGuid</code> is reused within 
     *         <code>specsToSearch</code>.
     */
    public boolean isCompNameReused(Collection<ISpecPersistable> specsToSearch,
            Collection<ITestSuitePO> suitesToSearch, String compNameGuid) {

        for (ISpecPersistable node : specsToSearch) {
            CheckIfComponentNameIsReusedOp op = new CheckIfComponentNameIsReusedOp(compNameGuid);
            TreeTraverser traverser = new TreeTraverser(node, op);
            traverser.traverse(true);
            if (op.hasFoundReuse()) {
                return true;
            }
        }

        for (ITestSuitePO ts : suitesToSearch) {
            CheckIfComponentNameIsReusedOp op = new CheckIfComponentNameIsReusedOp(compNameGuid);
            TreeTraverser traverser = new TreeTraverser(ts, op);
            traverser.traverse(true);
            if (op.hasFoundReuse()) {
                return true;
            }
        }

        return false;
    }

    /**
     * Finds all instances of reuse of a Component Name within the given 
     * objects.
     * 
     * @param specsToSearch The Test Cases and Categories to search 
     *                      (recursively).
     * @param suitesToSearch The Test Suites to search.
     * @param compNameGuid The GUID of the Component Name for which to find the
     *                    instances of reuse.
     * @param monitor The progress monitor for this operation.
     * @return all instances of reuse of the Component Name with GUID 
     *         <code>compNameGuid</code> within <code>specsToSearch</code> and
     *         <code>autsToSearch</code>.
     */
    public Set<INodePO> findNodesOfReuse(Collection<ISpecPersistable> specsToSearch,
            Collection<ITestSuitePO> suitesToSearch, String compNameGuid, IProgressMonitor monitor) {

        Set<INodePO> reuse = new HashSet<INodePO>();

        monitor.beginTask(Messages.ShowWhereUsedSearching, specsToSearch.size() + suitesToSearch.size());

        for (ISpecPersistable node : specsToSearch) {
            FindNodesForComponentNameOp op = new FindNodesForComponentNameOp(compNameGuid);
            TreeTraverser traverser = new TreeTraverser(node, op);
            traverser.traverse(true);
            reuse.addAll(op.getNodes());

            monitor.worked(1);
        }

        for (ITestSuitePO ts : suitesToSearch) {
            FindNodesForComponentNameOp op = new FindNodesForComponentNameOp(compNameGuid);
            TreeTraverser traverser = new TreeTraverser(ts, op);
            traverser.traverse(true);
            reuse.addAll(op.getNodes());

            monitor.worked(1);
        }

        return reuse;
    }

    /**
     * Finds all instances of reuse of a Component Name within the given 
     * objects.
     * 
     * @param autsToSearch The AUTs for which to search through the 
     *                     Object Mapping.
     * @param compNameGuid The GUID of the Component Name for which to find the
     *                    instances of reuse.
     * @return all instances of reuse of the Component Name with GUID 
     *         <code>compNameGuid</code> within <code>autsToSearch</code>.
     */
    public Set<IObjectMappingAssoziationPO> findAssocsOfReuse(Collection<IAUTMainPO> autsToSearch,
            String compNameGuid) {
        Set<IObjectMappingAssoziationPO> reuse = new HashSet<IObjectMappingAssoziationPO>();

        for (IAUTMainPO aut : autsToSearch) {
            for (IObjectMappingAssoziationPO assoc : aut.getObjMap().getMappings()) {

                if (assoc.getTechnicalName() != null && assoc.getLogicalNames().contains(compNameGuid)) {
                    reuse.add(assoc);
                }
            }
        }

        return reuse;
    }

    /**
     * Lock the TC if it is reused for the first time. This prevents deletion of
     * the TC while the editor is not saved.
     * 
     * @param sess
     *            DB session for locking purposes
     * @param refCompName
     *            Component Name to be used as a reference.
     * @param isReferencedByThisAction
     *            tells if there was a reference created by the current action,
     *            i.e. there is one references even if no other TC in the db
     *            references this one.
     * @throws PMAlreadyLockedException
     *             if the TC is locked by someone else
     * @throws PMDirtyVersionException
     *             if the TC was modified outside this instance of the
     *             application.
     * @throws PMObjectDeletedException
     *             if the po as deleted by another concurrently working user
     */
    public static void handleFirstReference(EntityManager sess, IComponentNamePO refCompName,
            boolean isReferencedByThisAction)
            throws PMDirtyVersionException, PMObjectDeletedException, PMAlreadyLockedException {

        IComponentNamePO name = refCompName;
        if (name.getId() != null) {
            int minSize = 0;
            if (isReferencedByThisAction) {
                minSize = 1;
            }

            if (CompNamePM.getNumReuseInstances(sess, GeneralStorage.getInstance().getProject().getId(),
                    name.getGuid()) <= minSize) {

                final EntityManager lockSession = sess;
                // make sure there is no old version
                // in the session cache
                try {
                    lockSession.detach(refCompName);
                    name = lockSession.find(name.getClass(), name.getId());
                } catch (PersistenceException he) {
                    // Continue since we are just refreshing the cache
                    log.error(Messages.StrayPersistenceException + StringConstants.DOT + StringConstants.DOT, he);
                }
                if (!LockManager.instance().lockPO(lockSession, name, false)) {
                    throw new PMAlreadyLockedException(name, Messages.OrginalTestcaseLocked + StringConstants.DOT,
                            MessageIDs.E_OBJECT_IN_USE);
                }
            }
        }
    }

}