/* GanttProject is an opensource project management tool. Copyright (C) 2011 Dmitry Barashev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package net.sourceforge.ganttproject.io; import biz.ganttproject.core.time.GanttCalendar; import com.google.common.base.Charsets; import net.sourceforge.ganttproject.CustomPropertyDefinition; import net.sourceforge.ganttproject.CustomPropertyManager; import net.sourceforge.ganttproject.GanttTask; import net.sourceforge.ganttproject.IGanttProject; import net.sourceforge.ganttproject.task.CustomColumnsValues; import net.sourceforge.ganttproject.task.Task; import net.sourceforge.ganttproject.task.dependency.TaskDependency; import net.sourceforge.ganttproject.util.ColorConvertion; import org.w3c.util.DateParser; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import javax.xml.transform.sax.TransformerHandler; import java.io.IOException; import java.math.BigDecimal; import java.net.URLEncoder; import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; import java.util.Map; class TaskSaver extends SaverBase { void save(IGanttProject project, TransformerHandler handler) throws SAXException, IOException { AttributesImpl attrs = new AttributesImpl(); if (project.getTaskManager().isZeroMilestones() != null) { addAttribute("empty-milestones", project.getTaskManager().isZeroMilestones(), attrs); } startElement("tasks", attrs, handler); startElement("taskproperties", handler); writeTaskProperties(handler, project.getTaskCustomColumnManager()); endElement("taskproperties", handler); Task rootTask = project.getTaskManager().getTaskHierarchy().getRootTask(); Task[] tasks = project.getTaskManager().getTaskHierarchy().getNestedTasks(rootTask); for (int i = 0; i < tasks.length; i++) { writeTask(handler, (GanttTask) tasks[i], project.getTaskCustomColumnManager()); } endElement("tasks", handler); } private void writeTask(TransformerHandler handler, GanttTask task, CustomPropertyManager customPropertyManager) throws SAXException, IOException { if (task.getTaskID() == -1) { throw new IllegalArgumentException("Is it a fake root task? Task=" + task); } AttributesImpl attrs = new AttributesImpl(); addAttribute("id", String.valueOf(task.getTaskID()), attrs); addAttribute("name", task.getName(), attrs); if (task.colorDefined()) { addAttribute("color", ColorConvertion.getColor(task.getColor()), attrs); } if (task.shapeDefined()) { addAttribute("shape", task.getShape().getArray(), attrs); } addAttribute("meeting", Boolean.valueOf(task.isLegacyMilestone()).toString(), attrs); if (task.isProjectTask()) { addAttribute("project", Boolean.TRUE.toString(), attrs); } addAttribute("start", task.getStart().toXMLString(), attrs); addAttribute("duration", String.valueOf(task.getLength()), attrs); addAttribute("complete", String.valueOf(task.getCompletionPercentage()), attrs); if (task.getThird() != null) { addAttribute("thirdDate", task.getThird().toXMLString(), attrs); addAttribute("thirdDate-constraint", String.valueOf(task.getThirdDateConstraint()), attrs); } if (task.getPriority() != Task.DEFAULT_PRIORITY) { addAttribute("priority", task.getPriority().getPersistentValue(), attrs); } final String sWebLink = task.getWebLink(); if (sWebLink != null && !sWebLink.equals("") && !sWebLink.equals("http://")) { addAttribute("webLink", URLEncoder.encode(sWebLink, Charsets.UTF_8.name()), attrs); } addAttribute("expand", String.valueOf(task.getExpand()), attrs); if (!(task.getCost().isCalculated() && task.getCost().getManualValue() == BigDecimal.ZERO)) { addAttribute("cost-manual-value", task.getCost().getManualValue().toPlainString(), attrs); addAttribute("cost-calculated", task.getCost().isCalculated(), attrs); } startElement("task", attrs, handler); if (task.getNotes() != null && task.getNotes().length() > 0) { cdataElement("notes", task.getNotes(), attrs, handler); // fout.write(space2 + "<notes>"); // fout.write("\n" // + space2 // + s // + correct(replaceAll(task.getNotes(), "\n", "\n" // + space2 + s))); // fout.write("\n" + space2 + "</notes>\n"); } // use successors to write depends information final TaskDependency[] depsAsDependee = task.getDependenciesAsDependee().toArray(); for (int i = 0; i < depsAsDependee.length; i++) { TaskDependency next = depsAsDependee[i]; addAttribute("id", String.valueOf(next.getDependant().getTaskID()), attrs); addAttribute("type", next.getConstraint().getType().getPersistentValue(), attrs); addAttribute("difference", String.valueOf(next.getDifference()), attrs); addAttribute("hardness", next.getHardness().getIdentifier(), attrs); emptyElement("depend", attrs, handler); } CustomColumnsValues ccv = task.getCustomValues(); for (CustomPropertyDefinition def : customPropertyManager.getDefinitions()) { final String idc = def.getID(); if (ccv.hasOwnValue(def)) { Object value = ccv.getValue(def); if (GregorianCalendar.class.isAssignableFrom(def.getType()) && value != null) { value = DateParser.getIsoDate(((GanttCalendar) value).getTime()); } addAttribute("taskproperty-id", idc, attrs); addAttribute("value", value == null ? null : String.valueOf(value), attrs); emptyElement("customproperty", attrs, handler); } } // Write the child of the task if (task.getManager().getTaskHierarchy().hasNestedTasks(task)) { Task[] nestedTasks = task.getManager().getTaskHierarchy().getNestedTasks(task); for (int i = 0; i < nestedTasks.length; i++) { writeTask(handler, (GanttTask) nestedTasks[i], customPropertyManager); } } // end of task section endElement("task", handler); } private void writeTaskProperty(TransformerHandler handler, String id, String name, String type, String valueType) throws SAXException { writeTaskProperty(handler, id, name, type, valueType, null, Collections.<String,String>emptyMap()); } private void writeTaskProperty(TransformerHandler handler, String id, String name, String type, String valueType, String defaultValue, Map<String, String> attributes) throws SAXException { AttributesImpl attrs = new AttributesImpl(); addAttribute("id", id, attrs); addAttribute("name", name, attrs); addAttribute("type", type, attrs); addAttribute("valuetype", valueType, attrs); if (defaultValue != null) { addAttribute("defaultvalue", defaultValue, attrs); } for (Map.Entry<String,String> kv : attributes.entrySet()) { addAttribute(kv.getKey(), kv.getValue(), attrs); } emptyElement("taskproperty", attrs, handler); } private void writeTaskProperties(TransformerHandler handler, CustomPropertyManager customPropertyManager) throws SAXException { writeTaskProperty(handler, "tpd0", "type", "default", "icon"); writeTaskProperty(handler, "tpd1", "priority", "default", "icon"); writeTaskProperty(handler, "tpd2", "info", "default", "icon"); writeTaskProperty(handler, "tpd3", "name", "default", "text"); writeTaskProperty(handler, "tpd4", "begindate", "default", "date"); writeTaskProperty(handler, "tpd5", "enddate", "default", "date"); writeTaskProperty(handler, "tpd6", "duration", "default", "int"); writeTaskProperty(handler, "tpd7", "completion", "default", "int"); writeTaskProperty(handler, "tpd8", "coordinator", "default", "text"); writeTaskProperty(handler, "tpd9", "predecessorsr", "default", "text"); for (CustomPropertyDefinition cc : customPropertyManager.getDefinitions()) { Object defVal = cc.getDefaultValue(); final Class<?> cla = cc.getType(); final String valueType = encodeFieldType(cla); if (valueType == null) { continue; } if ("date".equals(valueType) && defVal != null) { if (defVal instanceof GanttCalendar) { defVal = DateParser.getIsoDate(((GanttCalendar) defVal).getTime()); } else if (defVal instanceof Date) { defVal = DateParser.getIsoDate((Date) defVal); } else { assert false : "Default value is expected to be either GanttCalendar or Date instance, while it is " + defVal.getClass(); } } String idcStr = cc.getID(); writeTaskProperty(handler, idcStr, cc.getName(), "custom", valueType, defVal == null ? null : String.valueOf(defVal), cc.getAttributes()); } } static String encodeFieldType(Class<?> fieldType) { return CustomPropertyManager.PropertyTypeEncoder.encodeFieldType(fieldType); } }