blob: b385aa2ebc6b47ce6e2869eb072f701436d83859 [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.persistence.migration.internal;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.xmi.IllegalValueException;
import org.eclipse.emf.ecore.xmi.XMLHelper;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.eclipse.emf.mapping.ecore2xml.Ecore2XMLPackage;
import org.eclipse.emf.mapping.ecore2xml.Ecore2XMLRegistry;
import org.eclipse.emf.mapping.ecore2xml.impl.Ecore2XMLRegistryImpl;
import org.eclipse.emf.mapping.ecore2xml.util.Ecore2XMLExtendedMetaData;
import org.eclipse.epf.persistence.MultiFileResourceSetImpl;
import org.eclipse.epf.persistence.MultiFileURIConverter;
import org.eclipse.epf.persistence.MultiFileXMIHelperImpl;
import org.eclipse.epf.persistence.MultiFileXMIResourceImpl;
import org.eclipse.epf.persistence.migration.UMA2UMAResourceHandler;
import org.eclipse.epf.persistence.util.PersistenceResources;
import org.eclipse.epf.persistence.util.PersistenceUtil;
import org.eclipse.epf.resourcemanager.ResourceDescriptor;
import org.eclipse.epf.resourcemanager.ResourceManager;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.Guideline;
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.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.util.ContentDescriptionFactory;
import org.eclipse.epf.uma.util.UmaUtil;
/**
* Migrates one version of UMA library to another using the provided Ecore2XML
* mapping files and UMA2UMAResourceHandler. The Ecore2XML mapping files
* specifies the name changes of classes/attributes while UMA2UMAResourceHandler
* handles the data moving.
*
* @author Phong Nguyen Le
* @since 1.0
*/
public class Migrator {
private static final String[] NS_URIs = { Migrator.OLD_UMA_NS_URI,
Migrator.OLD_UMA_NS_URI, Migrator.UMA_NS_URI };
private static final URI[] ECORE2XML_URIs = {
URI
.createURI("platform:/plugin/com.ibm.rpm.library.persistence/migration/uma.ecore2xml") //$NON-NLS-1$
,
URI
.createURI("platform:/plugin/com.ibm.rpm.library.persistence/migration/uma2.ecore2xml") //$NON-NLS-1$
,
URI
.createURI("platform:/plugin/com.ibm.rpm.library.persistence/migration/uma3.ecore2xml") //$NON-NLS-1$
};
public static final String OLD_UMA_NS_URI = "http:///com/ibm/uma.ecore"; //$NON-NLS-1$
public static final String UMA_NS_URI = "http://www.ibm.com/uma/1.0.2/uma.ecore"; //$NON-NLS-1$
private ExtendedMetaData[] extendedMetaDatas;
private UMA2UMAResourceHandler0 resourceHandler;
public HashMap oldPathToNewURIMap = new HashMap();
public Collection anyTypeFeatureValues = new ArrayList();
private static final ExtendedMetaData getExtendedMetaData(String oldNsURI,
URI ecore2XMLURI) {
EPackage.Registry ePackageRegistry = new EPackageRegistryImpl(
EPackage.Registry.INSTANCE);
ePackageRegistry.put(oldNsURI, UmaPackage.eINSTANCE);
Ecore2XMLRegistry ecore2xmlRegistry = new Ecore2XMLRegistryImpl(
Ecore2XMLRegistry.INSTANCE);
ecore2xmlRegistry
.put(oldNsURI, EcoreUtil.getObjectByType(new ResourceSetImpl()
.getResource(ecore2XMLURI, true).getContents(),
Ecore2XMLPackage.eINSTANCE.getXMLMap()));
return new Ecore2XMLExtendedMetaData(ePackageRegistry,
ecore2xmlRegistry) {
public EClassifier getType(EPackage ePackage, String name) {
EClassifier type = super.getType(ePackage, name);
if (type == null) {
// try to get type from the package with the given name
//
List eClassifiers = ePackage.getEClassifiers();
for (int i = 0, size = eClassifiers.size(); i < size; ++i) {
EClassifier eClassifier = (EClassifier) eClassifiers
.get(i);
if (name.equals(eClassifier.getName())) {
return eClassifier;
}
}
}
return type;
}
};
}
public Migrator() {
this(NS_URIs, ECORE2XML_URIs);
}
public Migrator(String[] nsURIs, URI[] ecore2XMLURIs) {
int size = ecore2XMLURIs.length;
extendedMetaDatas = new ExtendedMetaData[size];
for (int i = 0; i < ecore2XMLURIs.length; i++) {
extendedMetaDatas[i] = getExtendedMetaData(nsURIs[i],
ecore2XMLURIs[i]);
}
this.resourceHandler = new UMA2UMAResourceHandler0();
}
private static void updateStatus(IProgressMonitor monitor, String msg) {
if (monitor != null) {
monitor.setTaskName(msg);
} else {
System.out.println(msg);
}
}
private static class AnyTypeFeatureValue {
String ownerId;
EObject owner;
EStructuralFeature feature;
String valueId;
AnyType value;
int index;
}
class MigratorURIConverter extends MultiFileURIConverter {
private ResourceManager oldResMgr;
/**
* @param resourceSet
*/
public MigratorURIConverter(MultiFileResourceSetImpl resourceSet) {
super(resourceSet);
}
/*
* (non-Javadoc)
*
* @see com.ibm.uma.persistence.MultiFileURIConverter#normalize(org.eclipse.emf.common.util.URI)
*/
public URI normalize(URI uri) {
URI normalized = super.normalize(uri);
if (normalized == null && SCHEME.equalsIgnoreCase(uri.scheme())) {
if (oldResMgr != null) {
String id = uri.authority();
normalized = getURIFromOldResourceManager(id);
if (normalized != null) {
if (uri.hasFragment()) {
normalized = normalized.appendFragment(uri
.fragment());
} else {
normalized = normalized.appendFragment(id);
}
}
}
}
return normalized;
}
public URI getURIFromOldResourceManager(String id) {
if (oldResMgr == null)
return null;
ResourceDescriptor desc = oldResMgr.getResourceDescriptor(id);
if (desc != null) {
URI normalized = desc.getResolvedURI();
URI newURI = (URI) oldPathToNewURIMap.get(normalized
.toFileString());
if (newURI != null) {
normalized = newURI;
}
return normalized;
}
return null;
}
/*
* (non-Javadoc)
*
* @see com.ibm.uma.persistence.MultiFileURIConverter#dispose()
*/
public void dispose() {
if (oldResMgr != null) {
oldResMgr.dispose();
oldResMgr = null;
}
super.dispose();
}
/**
* @param resMgr2
*/
public void setOldResourceManager(ResourceManager resMgr) {
oldResMgr = resMgr;
}
public ResourceManager getOldResourceManager() {
return oldResMgr;
}
/*
* (non-Javadoc)
*
* @see com.ibm.uma.persistence.MultiFileURIConverter#setURIMapping(org.eclipse.emf.ecore.EObject,
* org.eclipse.emf.common.util.URI, java.util.Set)
*/
public void setURIMapping(EObject e, URI uri, Set modifiedResources) {
// code to support migration from older version
//
if (e instanceof MethodElement) {
MigratorURIConverter uriConverter = (MigratorURIConverter) ((MultiFileResourceSetImpl) e
.eResource().getResourceSet()).getURIConverter();
ResourceManager oldResMgr = uriConverter
.getOldResourceManager();
if (oldResMgr != null) {
ResourceDescriptor desc = oldResMgr
.getResourceDescriptor(((MethodElement) e)
.getGuid());
if (desc != null) {
oldPathToNewURIMap.put(desc.getResolvedURI()
.toFileString(), uri);
}
}
}
super.setURIMapping(e, uri, modifiedResources);
}
}
class MigratorResourceSet extends MultiFileResourceSetImpl {
/*
* (non-Javadoc)
*
* @see com.ibm.uma.persistence.MultiFileResourceSetImpl#getURIConverter()
*/
public URIConverter getURIConverter() {
if (uriConverter == null) {
uriConverter = new MigratorURIConverter(this);
}
return uriConverter;
}
private void loadOldResourceManager(String libPath) throws IOException {
// trying to load the resource descriptors file
//
String libDir = new File(libPath).getParent() + File.separator;
File file = new File(libDir, RESMGR_XMI);
ResourceManager resMgr = null;
MultiFileURIConverter multiFileURIConverter = (MultiFileURIConverter) getURIConverter();
if (file.exists()) {
Resource resMgrRes = new XMIResourceImpl(URI.createFileURI(file
.getAbsolutePath())); // super.getResource(URI.createFileURI(file.getAbsolutePath()),
// true);
resMgrRes.load(null);
if (!resMgrRes.getContents().isEmpty()) {
Object obj = resMgrRes.getContents().get(0);
if (obj instanceof ResourceManager) {
resMgr = (ResourceManager) obj;
// resMgr.resolve();
} else {
System.err
.println("Invalid ResourceManager file: " + file); //$NON-NLS-1$
}
}
}
((MigratorURIConverter) multiFileURIConverter)
.setOldResourceManager(resMgr);
}
public MethodLibrary loadLibrary(String path) throws Exception {
loadOldResourceManager(path);
return loadLibraryWithoutReset(path);
}
/*
* (non-Javadoc)
*
* @see com.ibm.uma.persistence.MultiFileResourceSetImpl#findEObjectInUnloadedResources(java.lang.String)
*/
protected EObject findEObjectInUnloadedResources(String id) {
Object object = null;
if (getResourceManager() != null) {
object = super.findEObjectInUnloadedResources(id);
}
if (object == null) {
URI uri = ((MigratorURIConverter) getURIConverter())
.getURIFromOldResourceManager(id);
Resource resource = super.getResource(uri, true);
return resource.getEObject(id);
}
return null;
}
/*
* (non-Javadoc)
*
* @see com.ibm.uma.persistence.MultiFileResourceSetImpl#getEObject(org.eclipse.emf.common.util.URI,
* boolean)
*/
public EObject getEObject(URI uri, boolean loadOnDemand) {
// EObject eObj = superGetEObject(uri, loadOnDemand);
EObject eObj = super.getEObject(uri, loadOnDemand);
if (eObj == null
&& MigratorURIConverter.SCHEME.equalsIgnoreCase(uri
.scheme()) && !uri.hasFragment()) {
eObj = super.getEObject(uri.authority());
}
// if(uri.authority().equals("{11B60A4B-A0C7-4D5C-891A-346E8652A4EB}"))
// {
// System.out.println("MigratorResourceSet.getEObject(): eObj = " +
// eObj);
// }
if (eObj == null || eObj.eIsProxy()) {
throw new RuntimeException(
"Could not load object with URI '" + uri + "' (normalized URI: '" + getURIConverter().normalize(uri) + "').\nPlease see log file for more details."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return eObj;
}
public EObject superGetEObject(URI uri, boolean loadOnDemand) {
try {
URI normalized = getURIConverter().normalize(uri);
if (normalized == null) {
return null;
}
Resource resource = null;
resource = getResource(normalized.trimFragment(), loadOnDemand);
if (resource != null) {
String fragment = normalized.fragment();
if (fragment == null || fragment.length() == 0) {
return PersistenceUtil.getMethodElement(resource);
}
try {
return resource.getEObject(fragment);
} catch (NullPointerException e) {
throw e;
}
} else {
return null;
}
} catch (RuntimeException e) {
//
}
return null;
}
/*
* (non-Javadoc)
*
* @see com.ibm.uma.persistence.MultiFileResourceSetImpl#createResource(org.eclipse.emf.common.util.URI)
*/
public Resource createResource(URI uri) {
Resource result = new MultiFileXMIResourceImpl(uri) {
protected XMLHelper createXMLHelper() {
return new MultiFileXMIHelperImpl(this) {
public void setValue(EObject object,
EStructuralFeature feature, Object value,
int position) {
boolean old = logError;
try {
logError = false;
super
.setValue(object, feature, value,
position);
} catch (RuntimeException e) {
if (value instanceof AnyType
&& object instanceof MethodElement
// && object instanceof WorkBreakdownElement
// && feature ==
// UmaPackage.eINSTANCE.getWorkBreakdownElement_LinkToPredecessor()
) {
AnyTypeFeatureValue fvalue = new AnyTypeFeatureValue();
// fvalue.owner = object;
fvalue.ownerId = ((MethodElement) object)
.getGuid();
fvalue.feature = feature;
// fvalue.value = (AnyType) value;
fvalue.valueId = (String) UMA2UMAResourceHandler
.getSingleValue(((AnyType) value)
.getAnyAttribute(), "guid"); //$NON-NLS-1$
fvalue.index = position;
anyTypeFeatureValues.add(fvalue);
} else {
throw e;
}
} finally {
logError = old;
}
}
public List setManyReference(
org.eclipse.emf.ecore.xmi.XMLHelper.ManyReference reference,
String location) {
List exceptions = super.setManyReference(reference,
location);
if (exceptions == null)
return null;
for (Iterator iter = exceptions.iterator(); iter
.hasNext();) {
Object ex = iter.next();
if (ex instanceof IllegalValueException) {
IllegalValueException ive = (IllegalValueException) ex;
if (ive.getValue() instanceof AnyType
&& ive.getObject() instanceof MethodElement) {
AnyTypeFeatureValue fvalue = new AnyTypeFeatureValue();
fvalue.ownerId = ((MethodElement) ive
.getObject()).getGuid();
fvalue.feature = ive.getFeature();
fvalue.valueId = (String) UMA2UMAResourceHandler
.getSingleValue(((AnyType) ive
.getValue())
.getAnyAttribute(),
"guid"); //$NON-NLS-1$
fvalue.index = -1;
anyTypeFeatureValues.add(fvalue);
iter.remove();
}
}
}
if (exceptions.isEmpty()) {
return null;
}
return exceptions;
}
};
}
};
result.setTrackingModification(true);
getResources().add(result);
return result;
}
}
public void migrate(String libPath, IProgressMonitor monitor)
throws Exception {
Set classNames = new HashSet();
classNames.add("Technique"); //$NON-NLS-1$
MultiFileResourceSetImpl resourceSet = new MigratorResourceSet();
// ResourceManager oldResMgr = null;
for (int i = 0; i < extendedMetaDatas.length; i++) {
resourceSet.getLoadOptions().put(
XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.TRUE);
if (i < 2) {
resourceSet.getLoadOptions().put(
XMLResource.OPTION_RESOURCE_HANDLER, resourceHandler);
}
resourceSet.getLoadOptions()
.put(XMLResource.OPTION_EXTENDED_META_DATA,
extendedMetaDatas[i]);
if (i == 0) {
resourceHandler.savePresentationURIFor(classNames);
} else {
resourceHandler.savePresentationURIFor(null);
}
updateStatus(monitor, PersistenceResources.loadLibraryTask_name);
// if(oldResMgr != null) {
// ((MigratorURIConverter)resourceSet.getURIConverter()).setOldResourceManager(oldResMgr);
// resourceSet.loadLibraryWithoutReset(libPath);
// }
// else {
resourceSet.loadLibrary(libPath);
// }
MethodLibrary lib = resourceSet.getMethodLibrary();
if (lib == null)
return;
// load all the resources in memory
//
updateStatus(monitor, PersistenceResources.loadResourcesTask_name);
for (Iterator iter = lib.eAllContents(); iter.hasNext();) {
EObject element = (EObject) iter.next();
if (element instanceof Guideline && i > 0) {
// hack to restore the right presentation for old Technique
//
Guideline guideline = (Guideline) element;
URI uri = resourceHandler.getPresentationURI(guideline
.getGuid());
if (uri != null) {
ContentDescription presentation = (ContentDescription) resourceSet
.getEObject(uri, true);
guideline.setPresentation(presentation);
}
}
if (element instanceof MethodElement) {
try {
for (Iterator iterator = element.eCrossReferences()
.iterator(); iterator.hasNext();) {
iterator.next();
}
} catch (Exception e) {
CommonPlugin.INSTANCE.log(e);
System.err
.println("Error iterate thru cross references of element: " + element); //$NON-NLS-1$
}
}
}
if (i == 0) {
// oldResMgr =
// ((MigratorURIConverter)resourceSet.getURIConverter()).getOldResourceManager();
migrateProcessContentDescriptions(monitor, lib);
updateStatus(monitor, PersistenceResources.moveDataTask_name);
}
if (i < 2) {
resourceHandler.moveData();
resourceHandler.clearMoveInfos();
}
if (i == extendedMetaDatas.length - 1) {
migrateProcesses(monitor, lib);
restoreReferences(resourceSet);
}
updateStatus(monitor, PersistenceResources.saveLibraryTask_name);
resourceSet.save(null, true);
resourceSet.reset();
}
// delete old resmgr.xmi
//
try {
File resMgrFile = new File(new File(libPath).getParentFile(),
MultiFileResourceSetImpl.RESMGR_XMI);
if (resMgrFile.exists()) {
resMgrFile.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void restoreReferences(MultiFileResourceSetImpl resourceSet) {
for (Iterator iter = anyTypeFeatureValues.iterator(); iter.hasNext();) {
AnyTypeFeatureValue element = (AnyTypeFeatureValue) iter.next();
if (element.ownerId != null && element.valueId != null) {
EObject owner = resourceSet.getEObject(element.ownerId);
Object value = resourceSet.getEObject(element.valueId);
UMA2UMAResourceHandler.setValue(owner, element.feature, value);
}
}
anyTypeFeatureValues.clear();
}
private static void migrateProcesses(IProgressMonitor monitor,
MethodLibrary lib) {
updateStatus(monitor, PersistenceResources.fixPresentationNameTask_name);
String[][] procPkgPaths = MultiFileResourceSetImpl.PROCESS_PACKAGE_PATHS;
for (Iterator iter = lib.getMethodPlugins().iterator(); iter.hasNext();) {
MethodPlugin plugin = (MethodPlugin) iter.next();
ArrayList procPkgs = new ArrayList();
for (int j = 0; j < procPkgPaths.length; j++) {
MethodPackage pkg = UmaUtil.findMethodPackage(plugin,
procPkgPaths[j]);
if (pkg != null) {
procPkgs.add(pkg);
}
}
for (Iterator iterator = procPkgs.iterator(); iterator.hasNext();) {
ProcessPackage pkg = (ProcessPackage) iterator.next();
for (Iterator iterator1 = pkg.getChildPackages().iterator(); iterator1
.hasNext();) {
EObject childPkg = (EObject) iterator1.next();
if (childPkg instanceof ProcessComponent) {
org.eclipse.epf.uma.Process proc = ((ProcessComponent) childPkg)
.getProcess();
if (proc != null) {
try {
fixPresentationName(proc);
} catch (RuntimeException e) {
throw e;
}
} else {
String msg = Migrator.class.getName()
+ ": invalid ProcessComponent (with no Process): " + childPkg //$NON-NLS-1$
+ "\n ProcessComponent's resource URI: " + (childPkg.eResource() != null ? childPkg.eResource().getURI() : null) //$NON-NLS-1$
+ "\n Parent package: " + pkg //$NON-NLS-1$
+ "\n Parent package's resource URI: " + (pkg.eResource() != null ? pkg.eResource().getURI() : null) //$NON-NLS-1$
;
CommonPlugin.INSTANCE.log(msg);
System.err.println(msg);
}
}
}
}
}
}
private static void migrateProcessContentDescriptions(
IProgressMonitor monitor, MethodLibrary lib) {
updateStatus(monitor,
PersistenceResources.migrateContentDescriptionsTask_name);
String[][] procPkgPaths = MultiFileResourceSetImpl.PROCESS_PACKAGE_PATHS;
for (Iterator iter = lib.getMethodPlugins().iterator(); iter.hasNext();) {
MethodPlugin plugin = (MethodPlugin) iter.next();
ArrayList procPkgs = new ArrayList();
for (int j = 0; j < procPkgPaths.length; j++) {
MethodPackage pkg = UmaUtil.findMethodPackage(plugin,
procPkgPaths[j]);
if (pkg != null) {
procPkgs.add(pkg);
}
}
for (Iterator iterator = procPkgs.iterator(); iterator.hasNext();) {
ProcessPackage pkg = (ProcessPackage) iterator.next();
for (Iterator iterator1 = pkg.getChildPackages().iterator(); iterator1
.hasNext();) {
Object childPkg = (Object) iterator1.next();
if (childPkg instanceof ProcessComponent) {
org.eclipse.epf.uma.Process proc = ((ProcessComponent) childPkg)
.getProcess();
migrateContentDescription(proc);
}
}
}
}
}
private static void migrateContentDescription(BreakdownElement e) {
if (ContentDescriptionFactory.hasPresentation(e)) {
ContentDescription content = e.getPresentation();
EClass eCls = ContentDescriptionFactory
.getContentDescriptionEClass(e);
if (eCls != content) {
ContentDescription newContent = ContentDescriptionFactory
.createContentDescription(e);
newContent.setMainDescription(content.getMainDescription());
newContent.setKeyConsiderations(content.getKeyConsiderations());
newContent.getSections().addAll(content.getSections());
e.setPresentation(newContent);
}
}
if (e instanceof Activity) {
for (Iterator iter = ((Activity) e).getBreakdownElements()
.iterator(); iter.hasNext();) {
migrateContentDescription((BreakdownElement) iter.next());
}
}
}
private static void fixPresentationName(BreakdownElement e) {
if (e.getPresentationName() == null
|| e.getPresentationName().trim().length() == 0) {
e.setPresentationName(e.getName());
}
if (e instanceof Activity) {
for (Iterator iter = ((Activity) e).getBreakdownElements()
.iterator(); iter.hasNext();) {
fixPresentationName((BreakdownElement) iter.next());
}
}
}
}