blob: 389cd7d56ce5a9b7a9260fb13d00e8c72e8c9ec2 [file] [log] [blame]
//------------------------------------------------------------------------------
// 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.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();) {
MethodElement e = (MethodElement) itc.next();
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) ){
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);
}
}