diff options
8 files changed, 182 insertions, 12 deletions
diff --git a/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/businessprocess/CollectAllNodeGuidsOperation.java b/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/businessprocess/CollectAllNodeGuidsOperation.java new file mode 100644 index 000000000..2b241d583 --- /dev/null +++ b/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/businessprocess/CollectAllNodeGuidsOperation.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2017 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.archive.businessprocess; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jubula.client.core.model.INodePO; +import org.eclipse.jubula.client.core.utils.AbstractNonPostOperatingTreeNodeOperation; +import org.eclipse.jubula.client.core.utils.ITreeTraverserContext; + +/** + * Collects all NodePO guids from within a project + * @author BREDEX GmbH + * + */ +public class CollectAllNodeGuidsOperation + extends AbstractNonPostOperatingTreeNodeOperation<INodePO> { + + /** The collected guids */ + private Set<String> m_guids = new HashSet<>(); + + /** {@inheritDoc} */ + public boolean operate(ITreeTraverserContext<INodePO> ctx, INodePO parent, + INodePO node, boolean alreadyVisited) { + if (alreadyVisited) { + return false; + } + m_guids.add(node.getGuid()); + return true; + } + + /** + * @return the collected guids + */ + public Set<String> getGuids() { + return m_guids; + } + +} diff --git a/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/businessprocess/FileStorageBP.java b/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/businessprocess/FileStorageBP.java index fb4be5ccf..bff7127a0 100644 --- a/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/businessprocess/FileStorageBP.java +++ b/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/businessprocess/FileStorageBP.java @@ -60,6 +60,7 @@ import org.eclipse.jubula.client.core.persistence.PMSaveException; import org.eclipse.jubula.client.core.persistence.Persistor; import org.eclipse.jubula.client.core.persistence.ProjectPM; import org.eclipse.jubula.client.core.progress.IProgressConsole; +import org.eclipse.jubula.client.core.utils.TreeTraverser; import org.eclipse.jubula.toolkit.common.exception.ToolkitPluginException; import org.eclipse.jubula.tools.internal.constants.StringConstants; import org.eclipse.jubula.tools.internal.exception.ConfigXmlException; @@ -378,6 +379,8 @@ public class FileStorageBP { if (checkNameGuidConflict(guidToNameMap)) { return true; } + checkNodePOGuidConflict(); + // check for reusable project problems (circular dependencies) if (checkCircularDependencies(circularDependencyCheckSess)) { @@ -805,7 +808,87 @@ public class FileStorageBP { MessageIDs.E_PROJ_GUID_CONFLICT, new String [0], new String [] {importName, existingName}); } - + + /** + * Shows an error message + * @param msgId the MessageID to use, we assume that + * there are no details and params. + */ + private void showError(Integer msgId) { + Status s = new Status(IStatus.ERROR, Activator.PLUGIN_ID, + MessageIDs.getMessageString(msgId, null)); + m_console.writeStatus(s); + ErrorMessagePresenter.getPresenter().showErrorMessage( + msgId, null, null); + } + + /** + * @return whether there is any NodePO guid conflict + */ + private boolean checkNodePOGuidConflict() { + Map<String, String> importMap = new HashMap<>(); + boolean error = false; + for (IProjectPO proj : m_projectToCompCacheMap.keySet()) { + CollectAllNodeGuidsOperation op = + new CollectAllNodeGuidsOperation(); + TreeTraverser trav = new TreeTraverser(proj, op, true, true); + trav.setTraverseReused(false); + trav.traverse(true); + for (String guid : op.getGuids()) { + String prev = importMap.put(guid, proj.getGuid()); + if (prev != null && !prev.equals(proj.getGuid())) { + error = true; + writeGUIDDuplicationStatus(prev); + } + } + } + if (error) { + showError(MessageIDs.E_GUID_DUPLICATION_IMP); + return true; + } + Map<String, String> databaseMap = NodePM.getGuidToProjGuidMap( + importMap.keySet(), + GeneralStorage.getInstance().getMasterSession()); + return compareMaps(databaseMap, importMap, + MessageIDs.E_GUID_DUPLICATION_DB); + } + + /** + * Utility method for comparing two guid-to-project guid maps + * @param map1 the first map + * @param map2 the second map + * @param messId the error message ID to show + * @return whether there were any problems + */ + private boolean compareMaps(Map<String, String> map1, + Map<String, String> map2, Integer messId) { + boolean error = false; + for (String guid : map1.keySet()) { + String str1 = map1.get(guid); + String str2 = map2.get(guid); + if (str1 != null && str2 != null + && !str1.equals(str2)) { + error = true; + writeGUIDDuplicationStatus(guid); + } + } + if (error) { + showError(messId); + return true; + } + return false; + } + + /** + * write an warning to the console that UIDs are doubled + * @param uuid the identifier + */ + private void writeGUIDDuplicationStatus(String uuid) { + m_console.writeStatus(new Status(IStatus.WARNING, + "org.eclipse.jubula.client.archive", //$NON-NLS-1$ + NLS.bind(Messages.GuidUsedMultiple, uuid))); + } + /** * Checks whether the currently imported project already exists in the * database. diff --git a/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/i18n/Messages.java b/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/i18n/Messages.java index d556b72e9..045cbf162 100644 --- a/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/i18n/Messages.java +++ b/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/i18n/Messages.java @@ -42,7 +42,9 @@ public class Messages extends NLS { public static String ExportProjectInfo; public static String Failed; public static String File; + public static String GatheringProjectData; public static String GeneralIoExeption; + public static String GuidUsedMultiple; public static String ImportEmptyName; public static String ImportFailed; public static String ImportFileActionDoubleProjName; @@ -110,7 +112,7 @@ public class Messages extends NLS { public static String XmlImporterToolkitVersionConflict3a; public static String XmlImporterToolkitVersionConflict3b; public static String XmlImporterToolkitVersionConversion; - public static String GatheringProjectData; + static { // initialize resource bundle diff --git a/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/i18n/messages.properties b/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/i18n/messages.properties index 45d4d4153..3c9a709a4 100644 --- a/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/i18n/messages.properties +++ b/org.eclipse.jubula.client.archive/src/org/eclipse/jubula/client/archive/i18n/messages.properties @@ -29,6 +29,7 @@ ExportProjectInfo=Project information Failed=failed\! File=File GeneralIoExeption=General IO exception +GuidUsedMultiple=UID {0} is used in multiple projects ImportEmptyName=Import of project with an empty name not allowed. ImportFailed=\: Import failed\! ImportFileActionDoubleProjName=The Project name already exists in the Database. Please type another one. diff --git a/org.eclipse.jubula.client.core/src/org/eclipse/jubula/client/core/persistence/CompNamePM.java b/org.eclipse.jubula.client.core/src/org/eclipse/jubula/client/core/persistence/CompNamePM.java index 7397f1215..33c30636c 100644 --- a/org.eclipse.jubula.client.core/src/org/eclipse/jubula/client/core/persistence/CompNamePM.java +++ b/org.eclipse.jubula.client.core/src/org/eclipse/jubula/client/core/persistence/CompNamePM.java @@ -308,15 +308,6 @@ public class CompNamePM extends AbstractNamePM { } /** - * Releases the lock of the ComponentNames Table in database. - */ - private static final void unlockComponentNames() { - if (lockObj != null) { - LockManager.instance().unlockPO(lockObj); - } - } - - /** * Initializes the locking of the CompNames table */ private static void loadLockedObj() { diff --git a/org.eclipse.jubula.client.core/src/org/eclipse/jubula/client/core/persistence/NodePM.java b/org.eclipse.jubula.client.core/src/org/eclipse/jubula/client/core/persistence/NodePM.java index 7309320cc..4151a84bd 100644 --- a/org.eclipse.jubula.client.core/src/org/eclipse/jubula/client/core/persistence/NodePM.java +++ b/org.eclipse.jubula.client.core/src/org/eclipse/jubula/client/core/persistence/NodePM.java @@ -23,6 +23,7 @@ import javax.persistence.EntityTransaction; import javax.persistence.NoResultException; import javax.persistence.PersistenceException; import javax.persistence.Query; +import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; @@ -1206,4 +1207,27 @@ public class NodePM extends PersistenceManager { } return null; } + + /** + * Returns the CompNamePO -> parent projectPO map for the given NodePO guids + * Without GUID duplication, all nodes which have the same GUID should also have the + * same ParentProject GUID. + * @param guids the NodePO guids + * @param sess the session to use + * @return the resulting map + */ + public static Map<String, String> getGuidToProjGuidMap( + Set<String> guids, EntityManager sess) { + TypedQuery<Object[]> q = sess.createQuery("select node.guid, proj.guid from " //$NON-NLS-1$ + + "NodePO node, ProjectPO proj " //$NON-NLS-1$ + + "where node.hbmParentProjectId = proj.id and " //$NON-NLS-1$ + + "node.guid in :nodeGuids", Object[].class); //$NON-NLS-1$ + q.setParameter("nodeGuids", guids); //$NON-NLS-1$ + Map<String, String> result = new HashMap<>(); + for (Object[] entry : q.getResultList()) { + // we assume that the DB is consistent, and doesn't already contain duplicated GUIDs + result.put((String) entry[0], (String) entry[1]); + } + return result; + } } diff --git a/org.eclipse.jubula.tools/src/org/eclipse/jubula/tools/internal/i18n/jubulaI18n.properties b/org.eclipse.jubula.tools/src/org/eclipse/jubula/tools/internal/i18n/jubulaI18n.properties index 527c4d298..a1cf6c402 100644 --- a/org.eclipse.jubula.tools/src/org/eclipse/jubula/tools/internal/i18n/jubulaI18n.properties +++ b/org.eclipse.jubula.tools/src/org/eclipse/jubula/tools/internal/i18n/jubulaI18n.properties @@ -156,6 +156,8 @@ ErrorMessage.COMMAND_NOT_CREATED=Creating a command for AUT Agent failed. ErrorMessage.COMMIT_FAILED=Final save to storage failed. ErrorMessage.COMMIT_PROJECT=Cannot commit deleted Project. ErrorMessage.COMMUNICATOR_CONNECTION=An error has occurred while connecting to the AUT Agent. +ErrorMessage.GUID_DUPLICATION_IMP=Two of the imported projects have a GUID conflict.\nThis may cause unexpected problems. +ErrorMessage.GUID_DUPLICATION_DB=An imported project has a GUID conflict with a project in the Database.\nThis may cause unexpected problems. ErrorMessage.COMP_TYPE_INCOMPATIBLE=Incompatible type of Component Name "{0}"\:\n "{1}" -> "{2}".\nPlease choose a compatible Component Name. ErrorMessage.COMPONENT_ID_CREATION=Problem with component id creation. ErrorMessage.COMPONENT_NOT_FOUND=Component not found. @@ -289,6 +291,7 @@ ErrorMessage.PARAMETER_ERROR=Parameter Error. ErrorMessage.PARSE_NAME_ERROR=Names may only contain letters, digits or underscore. ErrorMessage.PO_NOT_FOUND=Class not found. ErrorMessage.PROBLEM_VIEW_REFRESH=Problem with refreshing Problem View occurred\! +ErrorMessage.PROJ_CIRC_DEPEND=Importing project "{0}" would result in a circular dependency of reused projects. ErrorMessage.PROJ_GUID_CONFLICT=There is a name conflict. No projects will be imported. ErrorMessage.PROJ_NAME_CONFLICT=There is a name conflict. No projects will be imported. ErrorMessage.PROJECT_NOT_FOUND=Project not found\! diff --git a/org.eclipse.jubula.tools/src/org/eclipse/jubula/tools/internal/messagehandling/MessageIDs.java b/org.eclipse.jubula.tools/src/org/eclipse/jubula/tools/internal/messagehandling/MessageIDs.java index 342a98d90..76c291264 100644 --- a/org.eclipse.jubula.tools/src/org/eclipse/jubula/tools/internal/messagehandling/MessageIDs.java +++ b/org.eclipse.jubula.tools/src/org/eclipse/jubula/tools/internal/messagehandling/MessageIDs.java @@ -331,6 +331,13 @@ public class MessageIDs { public static final Integer E_NO_FUNCTION = new Integer(4056); /** If test data is missing during test execution */ public static final Integer E_MISSING_DATA = new Integer(4057); + /** If two imported projects have guid conflicts */ + public static final Integer E_GUID_DUPLICATION_IMP = + new Integer(4058); + /** If an imported project has a guid conflict with a project in DB*/ + public static final Integer E_GUID_DUPLICATION_DB = + new Integer(4059); + // -- CONNECTION ERROR IDs --------------------------------------------- /** if problem occurred, during AUT connection initialization */ public static final Integer E_AUT_CONNECTION_INIT = new Integer(5000); @@ -778,7 +785,8 @@ public class MessageIDs { messageMap.put(E_CONVERSION_ABORTED_ERROR, e, "ErrorMessage.CONVERSION_ABORTED_ERROR", null); //$NON-NLS-1$ messageMap.put(E_UNSUPPORTED_TOOLKIT, e, "ErrorMessage.UNSUPPORTED_TOOLKIT", null); //$NON-NLS-1$ messageMap.put(E_MISSING_DATA, e, "ErrorMessage.MISSING_DATA", null); //$NON-NLS-1$ - + messageMap.put(E_GUID_DUPLICATION_IMP, e, "ErrorMessage.GUID_DUPLICATION_IMP", null); //$NON-NLS-1$ + messageMap.put(E_GUID_DUPLICATION_DB, e, "ErrorMessage.GUID_DUPLICATION_DB", null); //$NON-NLS-1$ } /** @@ -1072,6 +1080,16 @@ public class MessageIDs { initErrorMap(); return messageMap; } + + /** + * @param id the message id + * @param params the parameters + * @return the message string + */ + public static String getMessageString(Integer id, Object[] params) { + Message msg = getMessageMap().get(id); + return msg.getMessage(params); + } /** * MessageMap for ITE messages. |