com.projity.server.data.mspdi.ModifiedMSPDIWriter.java Source code

Java tutorial

Introduction

Here is the source code for com.projity.server.data.mspdi.ModifiedMSPDIWriter.java

Source

/*
 * file:       MSPDIFile.java
 * author:     Jon Iles
 * copyright:  (c) Tapster Rock Limited 2002-2003
 * date:       20/02/2003
 */

/*
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

package com.projity.server.data.mspdi;

import java.math.BigInteger;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.sf.mpxj.ProjectCalendar;
import net.sf.mpxj.ProjectFile;
import net.sf.mpxj.Resource;
import net.sf.mpxj.ResourceAssignment;
import net.sf.mpxj.Task;
import net.sf.mpxj.mspdi.DatatypeConverter;
import net.sf.mpxj.mspdi.MSPDIWriter;
import net.sf.mpxj.mspdi.schema.ObjectFactory;
import net.sf.mpxj.mspdi.schema.Project;
import net.sf.mpxj.mspdi.schema.ProjectType;
import net.sf.mpxj.mspdi.schema.TimephasedDataType;

import com.projity.association.AssociationList;
import com.projity.configuration.Settings;
import com.projity.exchange.ImportedCalendarService;
import com.projity.pm.assignment.Assignment;
import com.projity.pm.calendar.CalendarService;
import com.projity.pm.resource.EnterpriseResource;
import com.projity.pm.resource.ResourceImpl;
import com.projity.pm.snapshot.Snapshottable;
import com.projity.pm.task.NormalTask;
import com.projity.pm.task.TaskSnapshot;
import com.projity.server.data.MPXConverter;
import com.projity.util.DateTime;
import com.projity.util.Environment;

/**
 * This class is used to represent a Microsoft Project Data Interchange (MSPDI)
 * XML file. This implementation allows the file to be read, and the data it
 * contains exported as a set of MPX objects. These objects can be interrogated
 * to retrieve any required data, or stored as an MPX file.
 */
public class ModifiedMSPDIWriter extends MSPDIWriter {
    //static Log logg=LogFactory.getLog(ModifiedMSPDIFile.class);
    /**
     * This constructor allows a new MSPDI file to be created from scratch.
     */
    public ModifiedMSPDIWriter() {
        super();
    }

    protected Boolean formatOutput() {
        return Boolean.FALSE;
    }

    public void setProjectFile(ProjectFile pf) {
        m_projectFile = pf;
    }

    private Resource unassignedResource() {
        // add the unassigned resource
        if (UNASSIGNED == null) {
            UNASSIGNED = m_projectFile.addResource();
            UNASSIGNED.setUniqueID(EnterpriseResource.UNASSIGNED_ID);
        }
        return UNASSIGNED;

    }

    protected void writeProjectCalendar(Project project) {
        // projity addition
        int id = 1; // if not found below, use the default standard calendar
        ProjectCalendar cal = ImportedCalendarService.getInstance().findExportedCalendar(
                CalendarService.findBaseCalendar(m_projectFile.getProjectHeader().getCalendarName()));
        if (cal != null) {
            id = cal.getUniqueID();
        } else {
            log.warn("EXPORT: Could not export project calendar: Project: "
                    + m_projectFile.getProjectHeader().getName() + " calendar "
                    + m_projectFile.getProjectHeader().getCalendarName());
        }
        project.setCalendarUID(BigInteger.valueOf(id));

    }

    /**
     * This method writes resource data to an MSPDI file.
     *
     * @param factory
     *            ObjectFactory instance
     * @param project
     *            Root node of the MSPDI file
     * @throws JAXBException
     *             on xml creation errors
     */
    protected void writeResources(ObjectFactory factory, Project project) throws JAXBException {
        Project.Resources resources = factory.createProjectTypeResources(); //this ok?
        project.setResources(resources);
        List list = resources.getResource();

        Iterator iter = m_projectFile.getAllResources().iterator();
        Resource resource;
        while (iter.hasNext()) {
            resource = (Resource) iter.next();
            if (resource.getUniqueID() == EnterpriseResource.UNASSIGNED_ID) // don't
                continue;
            //DEF167699    projity: Export  -> mspdi cannot have ',' or msp complains.
            if (Environment.isNoPodServer()) {
                String name = resource.getName();
                if (name.contains(",")) {
                    //Fannon, Tommy -> Tommy Fannon
                    String fname = name.substring(name.indexOf(',') + 2);
                    //fname = fname.replace(" ", "");
                    String lname = name.substring(0, name.indexOf(','));
                    name = fname + " " + lname;
                    //name = name.replace(",", " ");
                    resource.setName(name);
                }
            }

            list.add(writeResource(factory, resource));
        }
    }

    /**
     * This method writes data for a single task to an MSPDI file.
     *
     * @param factory
     *            ObjectFactory instance
     * @param mpx
     *            Task data
     * @return new task instance
     * @throws JAXBException
     *             on xml creation errors
     */
    protected Project.TasksType.TaskType writeTask(ObjectFactory factory, Task mpx) throws JAXBException {

        /* DEF167859:  Projity: MS Project Export not working
           mpxj doesn't handle NaN.  this would be better fixed in mpxj code itself in the DatatypeConverter, but
           it would be a pain to setup the development environment to build this... so we will hack this for now
           --TAF2009-07-29
         */
        if (Double.isNaN(mpx.getFixedCost().doubleValue()))
            mpx.setFixedCost(null);

        Project.TasksType.TaskType xml = super.writeTask(factory, mpx);
        if (!mpx.getNull())
            writeTaskBaselinesAndTimephased(factory, xml, mpx);
        return xml;
    }

    /**
     * This method writes data for a single assignment to an MSPDI file.
     *
     * @param factory
     *            ObjectFactory instance
     * @param mpx
     *            Resource assignment data
     * @param uid
     *            Unique ID for the new assignment
     * @return New MSPDI assignment instance
     * @throws JAXBException
     *             on xml creation errors
     */
    protected Project.AssignmentsType.AssignmentType writeAssignment(ObjectFactory factory, ResourceAssignment mpx,
            int uid) throws JAXBException {
        Project.AssignmentsType.AssignmentType xml = super.writeAssignment(factory, mpx, uid);

        //Microsoft Project does something strange: The unassigned resource has a 0 id for the resource, but assignments use the (short)-1 value.
        if (mpx.getResourceID() == 0)
            xml.setResourceUID(BigInteger.valueOf(EnterpriseResource.UNASSIGNED_ID));

        Assignment projityAssignment = (Assignment) projityAssignmentMap.get(mpx);
        Calendar stop = DateTime.calendarInstance();
        stop.setTimeInMillis(projityAssignment.getStop());
        xml.setStop(stop);
        Calendar resume = DateTime.calendarInstance();
        resume.setTimeInMillis(projityAssignment.getResume());
        xml.setResume(resume);
        writeAssigmentBaselinesAndTimephased(factory, xml, mpx, uid);

        return (xml);
    }

    // Projity specific stuff below

    static Log log = LogFactory.getLog(ModifiedMSPDIWriter.class);
    protected com.projity.pm.task.Project projityProject;
    protected Map projityTaskMap = new HashMap();
    protected Map projityAssignmentMap = new HashMap();
    protected Map projitySnapshotIdMap = new HashMap();
    protected Map timephasedMap = new HashMap();
    private static Resource UNASSIGNED = null;

    public void setProjityProject(com.projity.pm.task.Project projityProject) {
        this.projityProject = projityProject;
    }

    public void putProjityTaskMap(Object mpx, Object projity) {
        projityTaskMap.put(mpx, projity);
    }

    public void putProjityAssignmentMap(Object mpx, Object projity) {
        projityAssignmentMap.put(mpx, projity);
    }

    public void putProjitySnapshotIdMap(Object mpx, Object projity) {
        projitySnapshotIdMap.put(mpx, projity);
    }

    public void putTimephasedList(Object mpx, Object timephasedList) {
        if (mpx == null || timephasedList == null)
            return;
        timephasedMap.put(mpx, timephasedList);
    }

    public List getTimephasedList(Object mpx) {
        return (List) timephasedMap.get(mpx);
    }

    /**
     * overloads default behavior to return the "unassigned" resource
     */
    public Resource getResourceByUniqueID(int id) {
        Resource r;
        if (id == EnterpriseResource.UNASSIGNED_ID)
            r = unassignedResource();
        else
            r = m_projectFile.getResourceByUniqueID(id);
        return r;

    }

    private void writeTaskBaselinesAndTimephased(ObjectFactory factory, final Project.TasksType.TaskType xml,
            Task mpx) throws JAXBException {
        // baselines
        final List baselineList = xml.getBaseline();

        NormalTask projityTask = (NormalTask) projityTaskMap.get(mpx);
        if (projityTask == null)
            return;
        for (int s = 0; s < Settings.numBaselines(); s++) {
            if (s == Snapshottable.CURRENT.intValue())
                continue;
            TaskSnapshot snapshot = (TaskSnapshot) projityTask.getSnapshot(new Integer(s));
            if (snapshot == null)
                continue;
            AssociationList snapshotAssignments = snapshot.getHasAssignments().getAssignments();
            if (snapshotAssignments.size() > 0) {
                for (Iterator j = snapshotAssignments.iterator(); j.hasNext();) {
                    Assignment assignment = (Assignment) j.next();
                    ResourceImpl r = (ResourceImpl) assignment.getResource();
                    if (r.isDefault())
                        continue;

                    ProjectType.AssignmentsType.AssignmentType.BaselineType baseline = factory
                            .createProjectTypeAssignmentsTypeAssignmentTypeBaselineType();
                    // For some silly reason, the baseline fields are all
                    // strings so they need to be converted

                    // baseline duration is missing :(
                    baseline.setNumber(s + "");
                    baseline.setStart(
                            MPXConverter.dateToXMLString(DateTime.fromGmt(projityTask.getBaselineStart(s))));
                    baseline.setFinish(
                            MPXConverter.dateToXMLString(DateTime.fromGmt(projityTask.getBaselineFinish(s))));
                    baseline.setWork(DatatypeConverter.printDuration(this,
                            MPXConverter.toMPXDuration((long) projityTask.getBaselineWork(s))));
                    baselineList.add(baseline);
                }
            }

        }
        // There is no need to write out task timephased info since it is all in assignments
        //      final List timephasedList = xml.getTimephasedData();
        //      TimephasedService.getInstance().consumeTimephased(projityTask, new TimephasedConsumer() {
        //         public void consumeTimephased(Object timephased) {
        //            ((TimephasedDataType) timephased).setUID(xml.getUID());
        //            timephasedList.add(timephased);
        //         }
        //      }, factory);
    }

    private void writeAssigmentBaselinesAndTimephased(ObjectFactory factory,
            final ProjectType.AssignmentsType.AssignmentType xml, ResourceAssignment mpx, int uid)
            throws JAXBException {
        int snapshotId = ((Integer) projitySnapshotIdMap.get(mpx)).intValue();
        final Assignment projityAssignment = (Assignment) projityAssignmentMap.get(mpx);
        // baselines
        final List timephasedList = xml.getTimephasedData();
        TimephasedService.getInstance().consumeTimephased(projityAssignment, new TimephasedConsumer() {
            public void consumeTimephased(Object timephased) {
                TimephasedDataType t = (TimephasedDataType) timephased;
                //if ("PT0H0M0S".equals(t.getValue())) return;
                ((TimephasedDataType) timephased).setUID(xml.getUID());
                timephasedList.add(timephased);
            }

            public boolean acceptValue(double value) { //TODO hack, consumeTimephased shouldn't give PT0H0M0S
                return value != 0.0;
            }
        }, factory);
    }

    public ProjectFile getProjectFile() {
        return m_projectFile;
    }

}