| //------------------------------------------------------------------------------ |
| // Copyright (c) 2005, 2006 IBM Corporation and others. |
| // 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: |
| // IBM Corporation - initial implementation |
| //------------------------------------------------------------------------------ |
| package org.eclipse.epf.importing.services; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.epf.importing.ImportPlugin; |
| import org.eclipse.epf.library.edit.util.TngUtil; |
| import org.eclipse.epf.uma.Dimension; |
| import org.eclipse.epf.uma.MethodConfiguration; |
| import org.eclipse.epf.uma.MethodElement; |
| import org.eclipse.epf.uma.MethodElementProperty; |
| import org.eclipse.epf.uma.MethodLibrary; |
| import org.eclipse.epf.uma.MethodPackage; |
| import org.eclipse.epf.uma.MethodPlugin; |
| import org.eclipse.epf.uma.Point; |
| |
| |
| /** |
| * Manages the differences between method elements in the current library and |
| * those that will be imported. |
| * |
| * @author Jinhua Xi |
| * @since 1.0 |
| */ |
| public class LibraryDiffManager { |
| |
| private MethodLibrary baseLibrary; |
| |
| private MethodLibrary importLibraty; |
| |
| // Map of uid to ElementDiffTree, the root of the ElementDiffTree is the |
| // library. |
| private Map diffElementMap = new HashMap(); |
| |
| // Map of uid to element for import library configuration. |
| private Map importElementMap = new HashMap(); |
| |
| // id to element map of the current library. |
| private Map currentElementMap = new HashMap(); |
| |
| // The diff tree. |
| ElementDiffTree rootDiffTree = null; |
| |
| private boolean debug = ImportPlugin.getDefault().isDebugging(); |
| |
| /** |
| * Creates a new instance. |
| */ |
| public LibraryDiffManager(MethodLibrary baseLibrary, |
| MethodLibrary importLibraty) { |
| this.baseLibrary = baseLibrary; |
| this.importLibraty = importLibraty; |
| |
| rootDiffTree = new ElementDiffTree(baseLibrary, importLibraty); |
| } |
| |
| /** |
| * Returns the import library. |
| */ |
| public MethodLibrary getImportingLibrary() { |
| return this.importLibraty; |
| } |
| |
| /** |
| * Builds the difference tree. |
| */ |
| public ElementDiffTree buildDiffTree() { |
| // Build the uid to element map for the import library. |
| buildUIDMap(importLibraty.eContents(), importElementMap, true, false); |
| |
| buildUIDMap(baseLibrary.eContents(), currentElementMap, true, true); |
| |
| // Get all the system packages in each plug-in so we can filter out |
| // those packages when comparing the libraries. |
| |
| // Iterate the element in the current library, and build a diff tree by |
| // comparing to the import library. |
| List plugins = baseLibrary.getMethodPlugins(); |
| for (Iterator it = plugins.iterator(); it.hasNext();) { |
| MethodPlugin plugin = (MethodPlugin) it.next(); |
| List systemPackages = TngUtil.getAllSystemPackages(plugin); |
| |
| // content category packages should be included into the diff tree |
| // otherwise the category information will be lost |
| List categoryList = TngUtil.getContentCategoryPackages(plugin); |
| for ( Iterator itc = categoryList.iterator(); itc.hasNext(); ) { |
| Object o = itc.next(); |
| if ( systemPackages.contains(o) ) { |
| systemPackages.remove(o); |
| } |
| } |
| |
| // the root customcategoty package needs to be included into the diff tree |
| int i = 0; |
| while (i < systemPackages.size() ) { |
| MethodPackage pkg = (MethodPackage)systemPackages.get(i); |
| if ( TngUtil.isRootCutomCategoryPackage(pkg) ) { |
| systemPackages.remove(pkg); |
| break; |
| } else { |
| i++; |
| } |
| } |
| |
| // Build the diff tree by iterating the current library. |
| iterateElement(plugin, rootDiffTree, systemPackages); |
| } |
| |
| List configs = baseLibrary.getPredefinedConfigurations(); |
| for (Iterator it = configs.iterator(); it.hasNext();) { |
| MethodConfiguration config = (MethodConfiguration) it.next(); |
| |
| // Build the diff tree by iterating the current library. |
| iterateElement(config, rootDiffTree, new ArrayList()); |
| } |
| |
| // Process the new elements in the import library and add them to the |
| // diff tree. |
| handleNewElements(importLibraty); |
| |
| return rootDiffTree; |
| } |
| |
| /** |
| * Returns the differnece tree. |
| */ |
| public ElementDiffTree getDiffTree() { |
| return rootDiffTree; |
| } |
| |
| /** |
| * Returns the differnece map. |
| */ |
| public Map getDiffTreeMap() { |
| return diffElementMap; |
| } |
| |
| /** |
| * Iterates the element in the current library and build a diff tree by |
| * comparing to the import library. |
| */ |
| private void iterateElement(MethodElement element, |
| ElementDiffTree diffTree, List systemPackages) { |
| if (!selectable(element)) { |
| return; |
| } |
| |
| // Update the diffelement UID map. |
| if (!systemPackages.contains(element) |
| && !(element instanceof MethodLibrary)) { |
| String uid = element.getGuid(); |
| ElementDiffTree diffChild = new ElementDiffTree(element, |
| (MethodElement) importElementMap.get(uid)); |
| diffElementMap.put(uid, diffChild); |
| diffTree.addChild(diffChild); |
| diffTree = diffChild; |
| } |
| |
| // Check with the importing element and create an ElementDiffInfo object |
| EList children = element.eContents(); |
| if (children != null) { |
| for (Iterator it = children.iterator(); it.hasNext();) { |
| Object e = it.next(); |
| if (e instanceof MethodElement) { |
| MethodElement child = (MethodElement) e; |
| if (selectable(child)) { |
| iterateElement(child, diffTree, systemPackages); |
| } |
| } else { |
| if (debug ) { |
| System.out |
| .println("Error! " + e + " is not a MethodElement object"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * If there are newly added elements in the importing library, add the new |
| * elements into the parent |
| */ |
| private void handleNewElements(MethodElement element) { |
| if (!selectable(element)) { |
| return; |
| } |
| |
| if (isNewElement(element)) { |
| // This is a new element, find the parent in the base library. |
| MethodElement parent = (MethodElement) element.eContainer(); |
| while (isNewElement(parent)) { |
| element = parent; |
| parent = (MethodElement) parent.eContainer(); |
| } |
| |
| // Always merge libray plugins even it's from a different library. |
| if (parent instanceof MethodLibrary) { |
| parent = baseLibrary; |
| } |
| |
| // Need to find the parent element in the current library so that we |
| // know where to add the new element. |
| MethodElement lib_parent = (MethodElement) currentElementMap |
| .get(parent.getGuid()); |
| if (lib_parent == null) { |
| lib_parent = baseLibrary; |
| } |
| ElementDiffTree elementDiffTree = new ElementDiffTree(null, |
| element, lib_parent); |
| |
| // Find the parent diff tree. |
| ElementDiffTree parentDiffTree = null; |
| while ((parentDiffTree == null) && (parent != null)) { |
| parentDiffTree = (ElementDiffTree) diffElementMap.get(parent |
| .getGuid()); |
| parent = (MethodElement) parent.eContainer(); |
| } |
| |
| if (parentDiffTree == null) { |
| parentDiffTree = rootDiffTree; |
| } |
| |
| parentDiffTree.addChild(elementDiffTree); |
| } else { |
| // Iterate the children. |
| List children = element.eContents(); |
| for (Iterator itc = children.iterator(); itc.hasNext();) { |
| Object obj = itc.next(); |
| if (obj instanceof MethodElement) { |
| MethodElement e = (MethodElement) obj; |
| handleNewElements(e); |
| } |
| } |
| |
| } |
| } |
| |
| private boolean isNewElement(MethodElement element) { |
| if (element == null || element instanceof MethodLibrary) { |
| return false; |
| } |
| return !currentElementMap.containsKey(element.getGuid()); |
| } |
| |
| private void buildUIDMap(List elements, Map elementUIDMap, boolean recursive, boolean full) { |
| MethodElement element; |
| for (Iterator it = elements.iterator(); it.hasNext();) { |
| Object e = it.next(); |
| if (e instanceof MethodElement) { |
| element = (MethodElement) e; |
| if (selectable(element) || full) { |
| String uid = element.getGuid(); |
| elementUIDMap.put(uid, element); |
| |
| if (recursive) { |
| buildUIDMap(element.eContents(), elementUIDMap, |
| recursive, full); |
| } |
| } |
| } else if ( !(e instanceof Point || e instanceof Dimension || e instanceof MethodElementProperty) ){ |
| ImportPlugin.getDefault().getLogger().logError( |
| "Import error. " + e + " is not a MethodElement object"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| } |
| |
| /** |
| * Checks if the method element is selectable. |
| */ |
| public boolean selectable(MethodElement element) { |
| return (element instanceof MethodLibrary |
| || element instanceof MethodPlugin |
| || element instanceof MethodPackage |
| || element instanceof MethodConfiguration); |
| } |
| |
| /** |
| * Returns the existing method element given by the guid. |
| */ |
| public MethodElement getExistingElement(String guid) { |
| return (MethodElement)currentElementMap.get(guid); |
| } |
| |
| } |