org.eclipse.epf.export.msp.ExportMSPXMLService.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.epf.export.msp.ExportMSPXMLService.java

Source

//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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.export.msp;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.edit.provider.AdapterFactoryTreeIterator;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.configuration.ProcessConfigurator;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.process.ActivityWrapperItemProvider;
import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.process.IBSItemProvider;
import org.eclipse.epf.library.edit.process.RoleDescriptorWrapperItemProvider;
import org.eclipse.epf.library.edit.process.TaskDescriptorWrapperItemProvider;
import org.eclipse.epf.library.edit.realization.IRealizationManager;
import org.eclipse.epf.library.edit.ui.UIHelper;
import org.eclipse.epf.library.edit.util.ConfigurableComposedAdapterFactory;
import org.eclipse.epf.library.edit.util.PredecessorList;
import org.eclipse.epf.library.edit.util.ProcessScopeUtil;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.library.util.LibraryUtil.ConfigAndPlugin;
import org.eclipse.epf.msproject.Assignment;
import org.eclipse.epf.msproject.DocumentRoot;
import org.eclipse.epf.msproject.MsprojectFactory;
import org.eclipse.epf.msproject.PredecessorLink;
import org.eclipse.epf.msproject.Project;
import org.eclipse.epf.msproject.Resource;
import org.eclipse.epf.msproject.Task;
import org.eclipse.epf.msproject.util.MsprojectResourceImpl;
import org.eclipse.epf.publishing.services.PublishHTMLOptions;
import org.eclipse.epf.publishing.services.PublishManager;
import org.eclipse.epf.publishing.services.PublishOptions;
import org.eclipse.epf.publishing.ui.wizards.PublishProgressMonitorDialog;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.CapabilityPattern;
import org.eclipse.epf.uma.DeliveryProcess;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.Milestone;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.WorkOrderType;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.util.Scope;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.swt.widgets.Display;

/**
 * The default Export Microsoft Project Plan Service implementation.
 * 
 * @author Bingxue Xu
 * @author Kelvin Low
 * @since 1.0
 * 
 * Bugs fixed: https://bugs.eclipse.org/bugs/show_bug.cgi?id=155089
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=155086
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=155095
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=157265
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=155155
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=156959
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=157321
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=159230
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=162336
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=168801 fix for
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=176951
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=177428
 */
public class ExportMSPXMLService {

    // If true, generate debug traces.
    private static boolean debug = ExportMSPPlugin.getDefault().isDebugging();

    // All Tasks referenced by the exported Project Template.
    private List referencedTasks = new ArrayList();

    private HashMap rolesToUidMap = new HashMap();

    private HashMap taskUidToWbsWapperPathMap = new HashMap();

    private HashMap wbsWapperPathToLocalPredListMap = new HashMap();

    private HashMap wbsGuidToTaskUidMap = new HashMap();

    private HashMap wbsWrapperPathToPredListMap = new HashMap();

    // The name of the content folder. This will be named after the context.
    private String contentFolderName;

    private String abTargetDir;

    // If true, only export breakdown elements with 'isPlanned' attributes set
    // to true.
    protected boolean exportOnlyPlannedElements;

    private boolean publishContentSite = false;

    private int task_uid = 1;

    private int res_uid = 1;

    private int assign_uid = 1;

    protected MsprojectFactory projectFactory = MsprojectFactory.eINSTANCE;

    // The process to be exported.
    private Process process;
    private MethodConfiguration processConfig;

    private ConfigurableComposedAdapterFactory wbsAdapterFactory;

    // The process configurator for filtering breakdown elements in a
    // configuration.
    private ProcessConfigurator breakdownElementFilter;

    private IStructuredContentProvider wbsContentProvider;

    // Map processes to suppression objects.
    private Map suppressionMap = new HashMap();

    // The suppression object associated with the selected process to be
    // exported.
    private Suppression suppression;

    // The WBS element paths.
    private Stack elementPaths = new Stack();

    private Object currentElement;

    private String currentElementPath;

    private PredecessorList currentPredList;

    private HashMap<Task, WorkBreakdownElement> taskToWbeMap;

    /**
     * Creates a new instance.
     */
    public ExportMSPXMLService() {
        super();
    }

    ConfigAndPlugin tempConfigAndPlugin;

    /**
     * Export a process to a Microsoft Project XML file.
     * 
     * @param process
     *            a capability pattern or delivery process
     * @param exportOptions
     *            a collection of user specified export options
     * @throws ExportMSPServiceException
     *             if an error occurs while executing the operation
     */
    public boolean export(Process process, ExportMSPOptions exportOptions) throws ExportMSPServiceException {

        tempConfigAndPlugin = null;
        boolean result = false;
        try {
            Scope scope = ProcessScopeUtil.getInstance().getScope(process);
            MethodConfiguration config = exportOptions.getMethodConfiguration();
            if (config == scope) {
                List<Process> list = new ArrayList<Process>();
                list.add(process);
                tempConfigAndPlugin = LibraryUtil.addTempConfigAndPluginToCurrentLibrary(list);
                if (tempConfigAndPlugin != null && tempConfigAndPlugin.config != null) {
                    config = tempConfigAndPlugin.config;
                }
            }
            IRealizationManager mgr = ConfigurationHelper.getDelegate().getRealizationManager(config);
            if (mgr != null) {
                mgr.updateProcessModel(process);
            }

            result = export_(process, exportOptions, config);
        } finally {
            LibraryUtil.removeTempConfigAndPluginFromCurrentLibrary(tempConfigAndPlugin);
            tempConfigAndPlugin = null;
        }

        return result;
    }

    private boolean export_(Process process, ExportMSPOptions exportOptions, MethodConfiguration config)
            throws ExportMSPServiceException {
        String msprojectName = exportOptions.getMSProjectName();
        File exportDir = exportOptions.getExportDir();
        publishContentSite = exportOptions.getPublishWebSite();
        PublishOptions publishingOptions = exportOptions.getPublishingOptions();
        processConfig = config;
        if (debug) {
            System.out.println("$$$ exporting to Microsoft Project!"); //$NON-NLS-1$
            System.out.println("$$$ process          = " + process); //$NON-NLS-1$
            System.out.println("$$$ configuration    = " + processConfig); //$NON-NLS-1$
            System.out.println("$$$ msprojectName    = " //$NON-NLS-1$
                    + msprojectName);
            System.out.println("$$$ targetDir                 = " + exportDir.getAbsolutePath()); //$NON-NLS-1$
            System.out.println("$$$ exportOnlyPlannedElements = " //$NON-NLS-1$
                    + exportOnlyPlannedElements);
            System.out.println("$$$ publishConfigOptions      = " //$NON-NLS-1$
                    + publishingOptions);
        }

        // construct the export target xml file path
        if (!exportDir.exists()) {
            exportDir.mkdirs();
        }
        abTargetDir = exportDir.getAbsolutePath();
        Path exportPath = new Path(abTargetDir);
        boolean endWithXmlExt = msprojectName.toLowerCase().endsWith(".xml"); //$NON-NLS-1$
        String exportPathStr = (exportPath.append(endWithXmlExt ? msprojectName : (msprojectName + ".xml"))) //$NON-NLS-1$
                .toOSString();
        if (debug)
            System.out.println("$$$ exportPathStr                 = " //$NON-NLS-1$
                    + exportPathStr);

        // construct the empty MS project xml template file path
        String emptyTemplateFile = ExportMSPPlugin.getDefault().getInstallPath() + "template" //$NON-NLS-1$
                + File.separator + "msproject_2003_template.xml"; //$NON-NLS-1$
        if (debug)
            System.out.println("$$$ emptyTemplateFile             = " //$NON-NLS-1$
                    + emptyTemplateFile);

        // copy the empty template MS project xml file to the export target
        try {
            File src = new File(emptyTemplateFile);
            File dst = new File(exportPathStr);
            FileUtil.copyFile(src, dst);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Project project = null;
        URI fileURI = URI.createFileURI(exportPathStr);

        try {

            XMLResource res = new MsprojectResourceImpl(fileURI);
            res.getDefaultSaveOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
            res.getDefaultLoadOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
            res.getDefaultSaveOptions().put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
            res.getDefaultSaveOptions().put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.TRUE);
            res.getDefaultLoadOptions().put(XMLResource.OPTION_USE_LEXICAL_HANDLER, Boolean.TRUE);
            res.load(null);

            DocumentRoot docRoot = (DocumentRoot) res.getEObject("/"); //$NON-NLS-1$
            project = (Project) docRoot.getProject();

            taskToWbeMap = new HashMap<Task, WorkBreakdownElement>();
            if (!generateMSProject(process, project, exportOptions)) {
                return false;
            }

            res.save(null);

            if (debug) {
                printMSProject(project);
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new ExportMSPException(e);
        }

        return true;
    }

    /**
     * Exports a capability pattern or delivery process to a Microsoft Project
     * XML file.
     * 
     * @param process
     *            a capability pattern or delivery process
     * @param project
     *            a Microsoft Project object
     * @param exportOptions
     *            a collection of user specified export options
     * @throws ExportMSPServiceException
     *             if an error occurs while executing the operation
     */
    public boolean generateMSProject(Process process, Project project, ExportMSPOptions exportOptions)
            throws Exception {
        if (process == null || project == null) {
            throw new IllegalArgumentException();
        }

        try {
            MethodConfiguration config = tempConfigAndPlugin == null ? exportOptions.getMethodConfiguration()
                    : tempConfigAndPlugin.config;
            if (config == null) {
                // Get the default method configuration associated with the
                // process.
                if (process instanceof DeliveryProcess) {
                    config = ((DeliveryProcess) process).getDefaultContext();
                } else if (process instanceof CapabilityPattern) {
                    config = ((CapabilityPattern) process).getDefaultContext();
                } else {
                    throw new IllegalArgumentException();
                }
            }

            // Create the sub folder to store the published HTML content files.
            contentFolderName = config.getName();

            PublishOptions publishingOptions = exportOptions.getPublishingOptions();
            if (publishContentSite && publishingOptions != null) {
                File contentDir = new File(exportOptions.getExportDir(), contentFolderName);
                if (!contentDir.exists()) {
                    contentDir.mkdirs();
                }
                if (debug) {
                    System.out.println("$$$ vieBuilder methodConfig = " //$NON-NLS-1$
                            + config);
                    System.out.println("$$$ vieBuilder publishConfigOptions = " //$NON-NLS-1$
                            + publishingOptions);
                }

                // Publish the associated configuration.
                if (!publishConfiguration(contentDir.getAbsolutePath(), config, publishingOptions)) {
                    return false;
                }
            }

            exportOnlyPlannedElements = exportOptions.getExportOnlyPlannedWBSElements();

            // Generate the Microsoft Project XML file.
            // populate the project's attributes
            project.setName(process.getName());
            project.setStartDate(new Date());
            project.setCreationDate(new Date());
            project.setLastSaved(new Date());
            project.setFinishDate(new Date());

            setProjectExtendedAttributes(project);

            generateOperatonRun(process, project, config);

            return true;
        } catch (Exception e) {
            throw e;
        }
    }

    private void generateOperatonRun(Process process, Project project, MethodConfiguration config)
            throws InvocationTargetException, InterruptedException {
        final Process fprocess = process;
        final Project fproject = project;
        final MethodConfiguration fconfig = config;

        IRunnableWithProgress op = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) throws InvocationTargetException {
                try {
                    monitor.beginTask(ExportMSPResources.exportMSPWizard_title, IProgressMonitor.UNKNOWN);

                    generate(fprocess, fproject, fconfig);
                } catch (Exception e) {
                    throw new InvocationTargetException(e);
                } finally {
                    monitor.done();
                }
            }
        };
        ProgressMonitorDialog pmDialog = new ProgressMonitorDialog(Display.getCurrent().getActiveShell());
        pmDialog.run(true, false, op);
    }

    private void generate(Process process, Project project, MethodConfiguration config) throws Exception {
        generateProjectResources(process, config, project);
        generateProjectTasks(process, config, project);
        generateLinks(process, project);
        generateWPDs(config);
    }

    /**
     * Sets the export options.
     * 
     * @param exportOptions
     *            a collection of user specified export options
     */
    protected void setExportOptions(ExportOptions exportOptions) {
        Boolean exportOnlyPlannedElements = (Boolean) exportOptions.get(ExportOptions.EXPORT_ONLY_PLANNED_ELEMENTS);
        this.exportOnlyPlannedElements = exportOnlyPlannedElements.booleanValue();
    }

    /**
     * Generates the project resources for all the task descriptors in the
     * process.
     * 
     * @param process
     *            a process
     * @param config
     *            a method configuration used to filter the work breakdown
     *            elements in the process
     * @param project
     *            an object to store the generated Microsoft Project WBS
     * @throws Exception
     *             if an error occurs while generating the Microsoft Project WBS
     */
    protected void generateProjectResources(Process process, MethodConfiguration config, Project project)
            throws Exception {
        ComposedAdapterFactory adapterFactory = null;
        try {
            adapterFactory = TngAdapterFactory.INSTANCE.createTBSComposedAdapterFactory();
            if (adapterFactory instanceof ConfigurableComposedAdapterFactory) {
                ((ConfigurableComposedAdapterFactory) adapterFactory).setFilter(new ProcessConfigurator(config));
            }
            IStructuredContentProvider contentProvider = new AdapterFactoryContentProvider(adapterFactory);

            List elements = process.getBreakdownElements();
            if (elements.size() > 0) {
                generateProjectResource(contentProvider, (BreakdownElement) process, project);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (adapterFactory != null) {
                adapterFactory.dispose();
            }
        }
    }

    /**
     * Generates the project resources for all the role descriptors in the
     * process.
     */
    protected void generateProjectResource(IStructuredContentProvider contentProvider,
            BreakdownElement breakdownElement, Project project) throws Exception {
        if (breakdownElement instanceof WorkProductDescriptor || breakdownElement.getSuppressed().booleanValue()
                || (exportOnlyPlannedElements && !breakdownElement.getIsPlanned().booleanValue())) {
            return;
        }

        if (breakdownElement instanceof RoleDescriptor) {
            addResource(breakdownElement, project);
            return;
        }

        if (contentProvider != null) {
            Object[] elements = contentProvider.getElements(breakdownElement);
            for (int i = 0; i < elements.length; i++) {
                Object element = elements[i];
                if (element instanceof RoleDescriptorWrapperItemProvider) {
                    RoleDescriptorWrapperItemProvider provider = (RoleDescriptorWrapperItemProvider) element;
                    Object value = provider.getValue();
                    if (value instanceof RoleDescriptor) {
                        addResource((BreakdownElement) value, project);
                    }
                } else if (element instanceof RoleDescriptor) {
                    addResource((BreakdownElement) element, project);
                } else if (element instanceof BreakdownElementWrapperItemProvider) {
                    BreakdownElementWrapperItemProvider provider = (BreakdownElementWrapperItemProvider) element;
                    Object value = provider.getValue();
                    if (value instanceof WorkBreakdownElement) {
                        generateProjectResource(contentProvider, (WorkBreakdownElement) value, project);
                    }
                } else if (element instanceof WorkBreakdownElement) {
                    generateProjectResource(contentProvider, (WorkBreakdownElement) element, project);
                }
            }
        }

    }

    // for each RoleDescriptor, create a MS Project resource
    // for the RoleDescriptor and its underlying role, remember the assigned
    // res_uid
    protected void addResource(BreakdownElement breakdownElement, Project proj) throws Exception {
        if (!(breakdownElement instanceof RoleDescriptor)) {
            return;
        }

        // check the existence of the underlying role of this roleDescriptor
        // and skip the creation if a resource for the role already exists
        RoleDescriptor roleDescriptor = (RoleDescriptor) breakdownElement;
        if (debug)
            System.out.println("$$$ handle RoleDescriptor = " + roleDescriptor); //$NON-NLS-1$
        Role ref_edRole = roleDescriptor.getRole();
        if (debug)
            System.out.println("$$$ handle Ref-ed Role = " + ref_edRole); //$NON-NLS-1$

        // check the need to add a new resource based on RoleDescriptor's disply
        // name
        boolean newRDResource = true;
        String rdResourceName = getDisplayName(roleDescriptor);
        if (rolesToUidMap.get(rdResourceName) != null) {
            newRDResource = false;
        }

        // check the need to add a new resource based on associated role's
        // disply name
        boolean newRoleReource = false;
        String roleResourceName = null;
        if (ref_edRole != null && rolesToUidMap.get((roleResourceName = getDisplayName(ref_edRole))) == null
                && !roleResourceName.equalsIgnoreCase(rdResourceName)) {
            newRoleReource = true;
        }

        // create a resource for the RoleDescriptor
        if (newRDResource) {
            Resource aRes = projectFactory.createResource();

            aRes.setUID(BigInteger.valueOf(res_uid));
            aRes.setID(BigInteger.valueOf(res_uid));
            aRes.setName(rdResourceName);
            proj.getResources().getResource().add(aRes);

            rolesToUidMap.put(rdResourceName, BigInteger.valueOf(res_uid));
            res_uid++;
        }

        // create a resource for the underlying associated role too
        if (newRoleReource) {
            Resource aRes = projectFactory.createResource();

            aRes.setUID(BigInteger.valueOf(res_uid));
            aRes.setID(BigInteger.valueOf(res_uid));
            aRes.setName(roleResourceName);
            proj.getResources().getResource().add(aRes);

            rolesToUidMap.put(roleResourceName, BigInteger.valueOf(res_uid));
            res_uid++;
        }
    }

    /**
     * Generates the MS Project WBS for a capability pattern or delivery
     * process.
     * 
     * @param process
     *            a process
     * @param config
     *            a method configuration used to filter the work breakdown
     *            elements in the process
     * @param project
     *            an object to store the generated Microsoft Project WBS
     * @throws Exception
     *             if an error occurs while generating the Microsoft Project WBS
     */
    protected void generateProjectTasks(Process process, MethodConfiguration config, Project project)
            throws Exception {
        // Save the reference to the exported process.
        this.process = process;

        wbsAdapterFactory = null;
        try {
            // Add the suppression object associated with the process to be
            // exported
            // to the suppression map.
            suppression = new Suppression(process);
            suppressionMap.put(process, suppression);

            wbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
                    .createWBSComposedAdapterFactory();
            breakdownElementFilter = new ProcessConfigurator(config);
            wbsAdapterFactory.setFilter(breakdownElementFilter);

            wbsContentProvider = new AdapterFactoryContentProvider(wbsAdapterFactory);

            // test
            // enumerateProcessPredecessorLists();

            currentElement = process;
            if (process instanceof CapabilityPattern) {
                generateProjectTask(wbsContentProvider, (BreakdownElement) process, 1, project);
            } else {
                //            List breakdownElements = process.getBreakdownElements();
                //            if (breakdownElements.size() > 0) {
                generateProjectTask(wbsContentProvider, (BreakdownElement) process, 1, project);
                //            }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (wbsAdapterFactory != null) {
                wbsAdapterFactory.dispose();
            }
            if (suppressionMap != null) {
                suppressionMap.clear();
                suppressionMap = null;
            }
            if (wbsContentProvider != null) {
                wbsContentProvider.dispose();
            }
        }
    }

    private void enumerateProcessPredecessorLists() {
        // WBS tree
        Iterator wbsTreeIterator = new AdapterFactoryTreeIterator(wbsAdapterFactory, process);
        Object obj;
        while (wbsTreeIterator.hasNext()) {
            obj = wbsTreeIterator.next();
            System.out.println("treeIterator: " + obj); //$NON-NLS-1$
            IBSItemProvider adapter = (IBSItemProvider) wbsAdapterFactory.adapt(obj,
                    ITreeItemContentProvider.class);
            PredecessorList predList = adapter.getPredecessors();
            for (Iterator iter = predList.iterator(); iter.hasNext();) {
                IBSItemProvider e = (IBSItemProvider) iter.next();
                System.out.println("    predList: " + e); //$NON-NLS-1$
                if (e instanceof ItemProviderAdapter) {
                    System.out.println("    unwrappedPredList: " //$NON-NLS-1$
                            + ((ItemProviderAdapter) e).getTarget());
                }
            }
        }
    }

    /**
     * Generates the Microsft Project task for a breakdown element.
     * 
     * @param contentProvider
     *            a content provider
     * @param breakdownElement
     *            a breakdown element
     * @param strBuf
     *            a <code>StringBuffer</code> to store the generated XML
     */
    protected void generateProjectTask(IStructuredContentProvider contentProvider, Object elementOrWrapper,
            int taskOLevel, Project proj) throws Exception {

        WorkBreakdownElement breakdownElement = (WorkBreakdownElement) TngUtil.unwrap(elementOrWrapper);

        // not really neccessary here
        if (breakdownElement instanceof WorkProductDescriptor || breakdownElement instanceof RoleDescriptor
                || breakdownElement.getSuppressed().booleanValue()
                || (exportOnlyPlannedElements && !breakdownElement.getIsPlanned().booleanValue())) {
            return;
        }

        boolean isSubTasksPlanned = false;
        if (exportOnlyPlannedElements && breakdownElement instanceof Activity && contentProvider != null) {
            Object[] elements = contentProvider.getElements(elementOrWrapper);
            for (int i = 0; i < elements.length; i++) {
                Object element = elements[i];
                if (element instanceof Activity) {
                    if (!exportOnlyPlannedElements || ((Activity) element).getIsPlanned().booleanValue()) {
                        isSubTasksPlanned = true;
                        break;
                    }
                } else if (element instanceof ActivityWrapperItemProvider) {
                    Object wrappedElement = TngUtil.unwrap(element);
                    if (wrappedElement instanceof Activity) {
                        if (!exportOnlyPlannedElements
                                || ((Activity) wrappedElement).getIsPlanned().booleanValue()) {
                            isSubTasksPlanned = true;
                            break;
                        }
                    }
                } else if (element instanceof TaskDescriptor) {
                    TaskDescriptor descriptor = (TaskDescriptor) element;
                    if (!exportOnlyPlannedElements || descriptor.getIsPlanned().booleanValue()) {
                        isSubTasksPlanned = true;
                        break;
                    }
                } else if (element instanceof TaskDescriptorWrapperItemProvider) {
                    Object wrappedElement = TngUtil.unwrap(element);
                    if (wrappedElement instanceof TaskDescriptor) {
                        TaskDescriptor descriptor = (TaskDescriptor) wrappedElement;
                        if (!exportOnlyPlannedElements || descriptor.getIsPlanned().booleanValue()) {
                            isSubTasksPlanned = true;
                            break;
                        }
                    }
                }
            }
        }

        // create a task for the WorkBreakdownElement
        // decided just to check the isPlanned flag on the WBS
        boolean isPlannedTask = breakdownElement.getIsPlanned().booleanValue();
        Task newTask = null;
        if (!exportOnlyPlannedElements || exportOnlyPlannedElements && isPlannedTask) {
            boolean suppressed = isSuppressed(breakdownElement);
            if (!suppressed) {
                newTask = addTask(elementOrWrapper, taskOLevel, proj);
            }
        }

        // if export planned only wbs, then we need to do the role rollup
        // calculation
        if (exportOnlyPlannedElements && newTask != null && breakdownElement instanceof Activity
                && contentProvider != null && !isSubTasksPlanned) {
            ArrayList rollupRoles = new ArrayList();
            boolean rb = calculateRollupRoles(contentProvider, breakdownElement, rollupRoles);
            // if the whole subtree of the breakdownElemnt is not planned
            // then roll up all the roles
            if (!rb) {
                HashSet rolesSet = new HashSet(rollupRoles);
                for (Iterator iter = rolesSet.iterator(); iter.hasNext();) {
                    String roleName = (String) iter.next();
                    addAssignment(roleName, newTask.getUID().intValue(), proj);
                }
            }
        }

        // export the next level wbs
        if (contentProvider != null) {
            boolean suppressed = isSuppressed(breakdownElement);
            if (!suppressed) {
                elementPaths.push(breakdownElement.getGuid());
                Object[] elements = contentProvider.getElements(elementOrWrapper);
                for (int i = 0; i < elements.length; i++) {
                    Object element = elements[i];

                    // get the current elementOrWrapper and the hierarcal guid
                    // path to it
                    currentElement = element;
                    String[] paths = new String[elementPaths.size()];
                    elementPaths.toArray(paths);
                    StringBuffer pathStr = new StringBuffer();
                    for (int j = 0; j < paths.length; j++) {
                        pathStr.append(paths[j] + "."); //$NON-NLS-1$
                    }
                    if (currentElement instanceof BreakdownElementWrapperItemProvider) {
                        Object wrapped = TngUtil.unwrap(element);
                        pathStr.append(((BreakdownElement) wrapped).getGuid());
                    } else {
                        pathStr.append(((BreakdownElement) currentElement).getGuid());
                    }
                    currentElementPath = pathStr.toString();
                    // if (debug) System.out.println(" path: " +
                    // currentElementPath);

                    generateProjectTask(contentProvider, element, taskOLevel + 1, proj);
                }
                generateLinks(process, proj);
                elementPaths.pop();
            }
        }

    }

    /**
     * Checks whether the given object is a suppressed work breakdown element in
     * its owning process.
     * 
     * @param object
     *            an object
     * @return <ocde>true</code> if the object is a suppressed work breakdown
     *         element in its owning process.
     */
    protected boolean isSuppressed(Object object) {
        if (object != null) {
            if (object instanceof Descriptor) {
                if (debug)
                    System.out.println("Descriptor = " //$NON-NLS-1$
                            + ((Descriptor) object).getName());
            }
            Process owningProcess = TngUtil.getOwningProcess(object);
            Suppression owningProcessSuppression = (Suppression) suppressionMap.get(owningProcess);
            if (owningProcessSuppression == null) {
                owningProcessSuppression = new Suppression(owningProcess);
                suppressionMap.put(owningProcess, owningProcessSuppression);
            }
            if (owningProcessSuppression.isSuppressed(object)) {
                return true;
            }
            if (owningProcess != process && object instanceof WorkBreakdownElement) {
                elementPaths.push(((WorkBreakdownElement) object).getGuid());
                String[] paths = new String[elementPaths.size()];
                elementPaths.toArray(paths);
                Object wrapper = suppression.getObjectByPath(paths, wbsAdapterFactory);
                elementPaths.pop();
                return suppression.isSuppressed(wrapper);
            }
        }
        return false;
    }

    /**
     * Adds a task to a Microsoft Project.
     * 
     * @param element
     *            a work breakdown element
     * @param taskOLevel
     *            the outline level
     * @param project
     *            a Microsoft Project object
     * @return the newly added task
     * @throws Exception
     *             if an error occurrs while performing the operation
     */
    protected Task addTask(Object elementOrWrapper, int taskOLevel, Project project) throws Exception {
        Task task = addTask_(elementOrWrapper, taskOLevel, project);
        if (task != null) {
            WorkBreakdownElement element = (WorkBreakdownElement) TngUtil.unwrap(elementOrWrapper);
            taskToWbeMap.put(task, element);
        }
        return task;
    }

    private Task addTask_(Object elementOrWrapper, int taskOLevel, Project project) throws Exception {

        if (elementOrWrapper == null) {
            return null;
        }

        WorkBreakdownElement element = (WorkBreakdownElement) TngUtil.unwrap(elementOrWrapper);

        Task task = projectFactory.createTask();
        task.setName(getDisplayName(element));
        task.setOutlineLevel(BigInteger.valueOf(taskOLevel));
        task.setUID(BigInteger.valueOf(task_uid));
        task.setID(BigInteger.valueOf(task_uid));
        task.setType(BigInteger.valueOf(0));

        GregorianCalendar gcDate = new GregorianCalendar();
        // gcDate.add(GregorianCalendar.DATE, 80);
        Date startDate = gcDate.getTime();
        task.setStart(startDate);
        // task.setDuration("PT20H0M0S");

        String notes = getBriefDescription(element);
        if (notes != null && notes.trim().length() > 0) {
            task.setNotes(notes);
        }

        if (element instanceof Milestone) {
            task.setMilestone(true);
            task.setDurationFormat(BigInteger.valueOf(7));
            task.setDuration("PT0H0M0S");
        } else {
            task.setMilestone(false);
        }

        // Assign the task to all the associated roles.
        List rolesList = null;
        if (element instanceof TaskDescriptor) {
            rolesList = getRolesForTaskD((TaskDescriptor) element);
        } else if (element instanceof org.eclipse.epf.uma.Task) {
            rolesList = getRolesForTask((org.eclipse.epf.uma.Task) element);
        }
        if (rolesList != null) {
            for (Iterator iter = rolesList.iterator(); iter.hasNext();) {
                String roleName = (String) iter.next();
                addAssignment(roleName, task_uid, project);
            }
        }

        // Add the generated URL link to the task.
        if (publishContentSite) {
            String linkURL = getElementURL(element);
            if (element instanceof TaskDescriptor) {
                TaskDescriptor taskDescriptor = (TaskDescriptor) element;
                org.eclipse.epf.uma.Task ref_edTask = taskDescriptor.getTask();
                referencedTasks.add(ref_edTask);
            }
            task.setHyperlinkAddress(linkURL);
        }

        // aTask.setType(new BigInteger("1"));
        // aTask.setStart(new Date());
        // aTask.setSummary(false);
        // aTask.setConstraintType(new BigInteger("2"));

        // Add the task to the Microsoft Project object.
        project.getTasks().getTask().add(task);

        if (debug) {
            System.out.println("$$$ theCurrent element: taskUid=" + task_uid //$NON-NLS-1$
                    + ", " + currentElement); //$NON-NLS-1$
            System.out.println("                  path: " + currentElementPath); //$NON-NLS-1$
        }

        // Store the task's local predecessors.
        storeTaskPredecessors(element);

        taskUidToWbsWapperPathMap.put(BigInteger.valueOf(task_uid), currentElementPath);
        wbsGuidToTaskUidMap.put(element.getGuid(), BigInteger.valueOf(task_uid));

        // get predecessors of a work breakdown element
        IBSItemProvider adapter = (IBSItemProvider) wbsAdapterFactory.adapt(elementOrWrapper,
                ITreeItemContentProvider.class);
        PredecessorList currentPredList = adapter.getPredecessors();
        List<MethodElement> guidPredList = new ArrayList<MethodElement>();
        for (Iterator iter = currentPredList.iterator(); iter.hasNext();) {
            Object e = (Object) iter.next();
            if (debug)
                System.out.println("    wrapperPredListMember: " + e); //$NON-NLS-1$
            Object unwrappedE = TngUtil.unwrap(e);
            if (unwrappedE instanceof WorkBreakdownElement) {
                //guidPredList.add(((WorkBreakdownElement) unwrappedE).getGuid());
                guidPredList.add((WorkBreakdownElement) unwrappedE);
                if (debug)
                    System.out.println("    unwrappedPredListMember: " //$NON-NLS-1$
                            + unwrappedE);
            }
            if (e instanceof ItemProviderAdapter) {
                unwrappedE = ((ItemProviderAdapter) e).getTarget();
                //guidPredList.add(((BreakdownElement) unwrappedE).getGuid());
                guidPredList.add((BreakdownElement) unwrappedE);
                if (debug)
                    System.out.println("    unwrappedPredListMember: " //$NON-NLS-1$
                            + unwrappedE);
            }
        }
        wbsWrapperPathToPredListMap.put(currentElementPath, guidPredList);
        if (debug)
            System.out.println("    __wrapperPredList: " + guidPredList); //$NON-NLS-1$

        task_uid++;

        return task;
    }

    private String getBriefDescription(WorkBreakdownElement element) {
        if (element == null)
            return null;

        String briefDesc = element.getBriefDescription();
        if ((briefDesc == null || briefDesc.trim().length() <= 0)) {
            if (element instanceof TaskDescriptor) {
                TaskDescriptor taskDescriptor = (TaskDescriptor) element;
                org.eclipse.epf.uma.Task ref_edTask = taskDescriptor.getTask();
                if (ref_edTask != null) {
                    MethodElement realizedElement = ConfigurationHelper.getCalculatedElement(ref_edTask,
                            processConfig);
                    if (debug)
                        System.out.println("$$$ realizedElement = " + realizedElement); //$NON-NLS-1$
                    if (realizedElement != null) {
                        EAttribute attribute = UmaPackage.eINSTANCE.getMethodElement_BriefDescription();
                        Object briefDescObj = ConfigurationHelper.calcAttributeFeatureValue(realizedElement,
                                attribute, processConfig);
                        briefDesc = briefDescObj.toString();
                        if (debug)
                            System.out.println("$$$ realized brief desc = " + briefDesc); //$NON-NLS-1$
                    }
                }
            }
        }

        return briefDesc;
    }

    private void addAssignment(String resName, int taskUid, Project proj) {
        Assignment assignment = projectFactory.createAssignment();

        assignment.setUID(BigInteger.valueOf(assign_uid));
        assignment.setTaskUID(BigInteger.valueOf(taskUid));
        BigInteger resID = (BigInteger) rolesToUidMap.get(resName);
        assignment.setResourceUID(resID);

        proj.getAssignments().getAssignment().add(assignment);

        assign_uid++;
    }

    private List getRolesForTaskD(TaskDescriptor taskDescriptor) {
        ArrayList rolesList = new ArrayList();

        for (RoleDescriptor rd : taskDescriptor.getPerformedPrimarilyBy()) {

            // RoleDescriptor roleDescrp =
            // taskDescriptor.getPerformedPrimarilyBy();
            RoleDescriptor roleDescrp = (RoleDescriptor) ConfigurationHelper.getCalculatedElement(rd,
                    breakdownElementFilter.getMethodConfiguration());

            if (roleDescrp != null) {
                rolesList.add(getDisplayName(roleDescrp));
            }
        }

        // List roleDescrpList =
        // taskDescriptor.getAdditionallyPerformedBy();
        List roleDescrpList = ConfigurationHelper.getCalculatedElements(taskDescriptor.getAdditionallyPerformedBy(),
                breakdownElementFilter.getMethodConfiguration());

        for (Iterator iter = roleDescrpList.iterator(); iter.hasNext();) {
            RoleDescriptor roleDescrp = (RoleDescriptor) iter.next();
            rolesList.add(getDisplayName(roleDescrp));
        }

        return rolesList;
    }

    private List getRolesForTask(org.eclipse.epf.uma.Task umaTask) {
        ArrayList rolesList = new ArrayList();

        for (Role role : umaTask.getPerformedBy()) {
            if (role != null) {
                rolesList.add(getDisplayName(role));
            }
        }

        List list = umaTask.getAdditionallyPerformedBy();
        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Role role = (Role) iter.next();
            rolesList.add(getDisplayName(role));
        }

        return rolesList;
    }

    private boolean calculateRollupRoles(IStructuredContentProvider contentProvider,
            BreakdownElement breakdownElement, List rollupRoles) {

        boolean isAnySubTaskPlanned = false;

        Object[] elements = contentProvider.getElements(breakdownElement);
        for (int i = 0; i < elements.length; i++) {
            Object element = elements[i];
            if (element instanceof Activity) {
                if (!exportOnlyPlannedElements || ((Activity) element).getIsPlanned().booleanValue()) {
                    isAnySubTaskPlanned = true;
                } else {
                    isAnySubTaskPlanned = calculateRollupRoles(contentProvider, (BreakdownElement) element,
                            rollupRoles);
                }
            } else if (element instanceof ActivityWrapperItemProvider) {
                Object wrappedElement = TngUtil.unwrap(element);
                if (wrappedElement instanceof Activity) {
                    if (!exportOnlyPlannedElements || ((Activity) wrappedElement).getIsPlanned().booleanValue()) {
                        isAnySubTaskPlanned = true;
                    } else {
                        isAnySubTaskPlanned = calculateRollupRoles(contentProvider,
                                (BreakdownElement) wrappedElement, rollupRoles);
                    }
                }
            } else if (element instanceof TaskDescriptor) {
                TaskDescriptor descriptor = (TaskDescriptor) element;
                if (!exportOnlyPlannedElements || descriptor.getIsPlanned().booleanValue()) {
                    isAnySubTaskPlanned = true;
                } else {
                    rollupRoles.addAll(getRolesForTaskD((TaskDescriptor) element));
                }
            } else if (element instanceof TaskDescriptorWrapperItemProvider) {
                Object wrappedElement = TngUtil.unwrap(element);
                if (wrappedElement instanceof TaskDescriptor) {
                    TaskDescriptor descriptor = (TaskDescriptor) wrappedElement;
                    if (!exportOnlyPlannedElements || descriptor.getIsPlanned().booleanValue()) {
                        isAnySubTaskPlanned = true;
                    } else {
                        rollupRoles.addAll(getRolesForTaskD((TaskDescriptor) wrappedElement));
                    }
                }
            }
        }

        return isAnySubTaskPlanned;
    }

    /**
     * Retrieves a work breakdown element's predecessors, stores them in an
     * <ocde>ArrayList</code>, and put it into a map.
     * 
     * @param element
     *            a work breakdown element
     */
    private void storeTaskPredecessors(WorkBreakdownElement element) {
        if (element == null) {
            return;
        }

        List predecessors = element.getLinkToPredecessor();
        List predList = new ArrayList();
        if (predecessors != null && predecessors.size() > 0) {
            for (Iterator i = predecessors.iterator(); i.hasNext();) {
                WorkOrder workOrder = (WorkOrder) i.next();
                BreakdownElement predecessor = workOrder.getPred();
                if (debug) {
                    System.out.println("    localPredListMember: " //$NON-NLS-1$
                            + predecessor);
                }
                if (predecessor != null) {
                    String predGuid = predecessor.getGuid();
                    if (predGuid != null)
                        predList.add(predGuid);
                }
            }
        }
        if (debug) {
            System.out.println("   local predlist for " + element.getName() //$NON-NLS-1$
                    + " = " + predList.toString()); //$NON-NLS-1$
        }

        wbsWapperPathToLocalPredListMap.put(currentElementPath, predList);
    }

    protected void generateLinks(Process process, Project project) throws Exception {
        EList tasks = project.getTasks().getTask();
        for (Iterator iter = tasks.iterator(); iter.hasNext();) {
            Task task = (Task) iter.next();

            BigInteger taskUid = task.getUID();
            // skip the MS project hidden task with uid = 0
            if (taskUid.intValue() == 0)
                continue;

            String wbsPathStr = (String) taskUidToWbsWapperPathMap.get(taskUid);

            HashMap<String, WorkOrder> predGuidToWOMap = getPredGuidToWOMap(taskToWbeMap.get(task));

            // List predList = (ArrayList)
            // wbsWapperPathToLocalPredListMap.get(wbsPathStr);
            List predList = (ArrayList) wbsWrapperPathToPredListMap.get(wbsPathStr);
            if (predList != null) {
                List removeList = new ArrayList();
                for (Iterator iterator = predList.iterator(); iterator.hasNext();) {
                    //String predGuid = (String) iterator.next();
                    MethodElement predElem = (MethodElement) iterator.next();
                    String predGuid = predElem.getGuid();

                    BigInteger predTaskUid = (BigInteger) wbsGuidToTaskUidMap.get(predGuid);

                    if (predTaskUid == null || predTaskUid.intValue() == taskUid.intValue()) {
                        continue;
                    }

                    if (debug) {
                        System.out.println("$$$ taskUid = " + taskUid //$NON-NLS-1$
                                + ", wbsPathStr = " + wbsPathStr); //$NON-NLS-1$
                        System.out.println("    localPredList: " + predList); //$NON-NLS-1$
                        System.out.println("    found pred guid: " + predGuid); //$NON-NLS-1$
                    }

                    //removeList.add(predGuid);
                    removeList.add(predElem);

                    PredecessorLink preLink = projectFactory.createPredecessorLink();
                    task.getPredecessorLink().add(preLink);
                    preLink.setPredecessorUID(predTaskUid);

                    //preLink.setType(new BigInteger("1")); //$NON-NLS-1$
                    BigInteger bigInt = getLinkTypeInt(predGuidToWOMap.get(predGuid));
                    if (bigInt != null) {
                        preLink.setType(bigInt);
                    }

                    preLink.setCrossProject(false);
                    preLink.setLinkLag(new BigInteger("0")); //$NON-NLS-1$
                    preLink.setLagFormat(new BigInteger("7")); //$NON-NLS-1$
                }
                predList.removeAll(removeList);
            }
        }
    }

    private BigInteger getLinkTypeInt(WorkOrder wo) {
        if (wo == null) {
            if (debug) {
                System.out.println("Warning> getLinkTypeInt, wo == null.");//$NON-NLS-1$
            }
            return null;
        }
        WorkOrderType woType = wo.getLinkType();
        if (woType == WorkOrderType.FINISH_TO_START) {
            return new BigInteger("1"); //$NON-NLS-1$
        }
        if (woType == WorkOrderType.START_TO_START) {
            return new BigInteger("3"); //$NON-NLS-1$
        }
        if (woType == WorkOrderType.FINISH_TO_FINISH) {
            return new BigInteger("0"); //$NON-NLS-1$
        }
        if (woType == WorkOrderType.START_TO_FINISH) {
            return new BigInteger("2"); //$NON-NLS-1$
        }
        return null;
    }

    private HashMap<String, WorkOrder> getPredGuidToWOMap(WorkBreakdownElement wbe) {
        HashMap<String, WorkOrder> predGuidToWOMap = new HashMap<String, WorkOrder>();
        if (wbe != null) {
            List<WorkOrder> woList = wbe.getLinkToPredecessor();
            int sz = woList == null ? 0 : woList.size();
            for (int i = 0; i < sz; i++) {
                WorkOrder wo = woList.get(i);
                if (wo == null || wo.getPred() == null) {
                    continue;
                }
                predGuidToWOMap.put(wo.getPred().getGuid(), wo);
            }
        }
        return predGuidToWOMap;
    }

    /**
     * Returns the generated HTML content file URL for a method element.
     * 
     * @param element
     *            a method element
     * @return the URL of the generated HTML content file
     */
    protected String getElementURL(MethodElement element) {
        if (element == null)
            return null;

        String elementPath = null;
        String elementFileName = null;
        try {
            elementPath = ResourceHelper.getElementPath(element);
            elementFileName = ResourceHelper.getFileName(element, ResourceHelper.FILE_EXT_HTML);
        } catch (Exception e) {
            e.printStackTrace();
            return ""; //$NON-NLS-1$
        }
        if (elementPath != null && elementFileName != null) {
            elementPath = elementPath.replace('\\', '/');
            elementFileName = elementFileName.replace('\\', '/');
            String url = contentFolderName + "/" + elementPath + elementFileName; //$NON-NLS-1$
            return abTargetDir + File.separator + url;
        } else {
            return ""; //$NON-NLS-1$
        }
    }

    /**
     * Returns the display name of a method element.
     * 
     * @param element
     *            a method element
     * @return the display name of the given element
     */
    protected String getDisplayName(MethodElement element) {
        String name = null;
        if (element instanceof BreakdownElement) {
            name = ProcessUtil.getPresentationName((BreakdownElement) element);
        } else if (element instanceof DescribableElement) {
            name = ((DescribableElement) element).getPresentationName();
        }
        if (name == null || name.length() == 0) {
            name = element.getName();
        }
        if (name.indexOf("\n") >= 0) {//$NON-NLS-1$
            name = name.replaceAll("\r\n", " ");//$NON-NLS-1$ //$NON-NLS-2$
        }
        return name;

        //This is not needed since EMF would take care of encoding
        //suring save
        //return XMLUtil.escapeAttr(name);
    }

    /**
     * Publishes the selected configuration associated with the exported
     * process.
     * 
     * @param dir
     *            the output directory
     * @param config
     *            the configuration to publish
     * @param publishConfigOptions
     *            the publishing options
     * @return <code>true</code> if the configuration was published
     *         successfully, <code>false</code> otherwise
     * @throws Exception
     *             if an error occurs while publishing the configuration
     */
    protected boolean publishConfiguration(String dir, MethodConfiguration config,
            PublishOptions publishConfigOptions) throws Exception {
        PublishManager publishMgr = null;
        try {
            publishMgr = new PublishManager();
            publishMgr.init(dir, config, new PublishHTMLOptions(publishConfigOptions));

            ExportMSPXMLOperation operation = new ExportMSPXMLOperation(publishMgr);
            PublishProgressMonitorDialog dlg = new PublishProgressMonitorDialog(
                    Display.getCurrent().getActiveShell(), publishMgr.getViewBuilder());
            boolean success = UIHelper.runWithProgress(operation, dlg, true,
                    ExportMSPResources.exportMSPWizard_title);
            if (operation.getException() != null) {
                throw operation.getException();
            }
            return success && !dlg.getProgressMonitor().isCanceled();
        } catch (Exception e) {
            throw e;
        } finally {
            if (publishMgr != null) {
                publishMgr.dispose();
                publishMgr = null;
            }
        }
    }

    /**
     * Prints the trace information for the Microsoft Project.
     */
    private static void printMSProject(Project project) {
        System.out.println("\n$$$ read-in project = " + project); //$NON-NLS-1$

        EList tasks = project.getTasks().getTask();
        for (Iterator iter = tasks.iterator(); iter.hasNext();) {
            Task element = (Task) iter.next();
            System.out.println("$$$ a task = " + element); //$NON-NLS-1$
        }

        EList resources = project.getResources().getResource();
        for (Iterator iter = resources.iterator(); iter.hasNext();) {
            org.eclipse.epf.msproject.Resource element = (org.eclipse.epf.msproject.Resource) iter.next();
            System.out.println("$$$ a resource = " + element); //$NON-NLS-1$
        }

        EList assignments = project.getAssignments().getAssignment();
        for (Iterator iter = assignments.iterator(); iter.hasNext();) {
            Assignment element = (Assignment) iter.next();
            System.out.println("$$$ an assignment = " + element); //$NON-NLS-1$
        }

        System.out.println("$$$===\n"); //$NON-NLS-1$
    }

    protected HashMap<Task, WorkBreakdownElement> getTaskToWbeMap() {
        return taskToWbeMap;
    }

    //To be overriden by subclasses
    protected void setProjectExtendedAttributes(Project project) {
    }

    //To be overriden by subclasses
    protected void generateWPDs(MethodConfiguration config) {
    }

}