//------------------------------------------------------------------------------
// 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.MultiFileSaveUtil;
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.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 MultiFileSaveUtil.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());
			}
		}
	}

}
