/* GanttProject is an opensource project management tool. License: GPL3 Copyright (C) 2004-2012 Thomas Alexandre, GanttProject Team 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 biz.ganttproject.impex.csv; import biz.ganttproject.core.model.task.TaskDefaultColumn; import biz.ganttproject.core.option.BooleanOption; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.base.Strings; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import net.sourceforge.ganttproject.CustomProperty; import net.sourceforge.ganttproject.CustomPropertyDefinition; import net.sourceforge.ganttproject.CustomPropertyManager; import net.sourceforge.ganttproject.GanttTask; import net.sourceforge.ganttproject.IGanttProject; import net.sourceforge.ganttproject.ResourceDefaultColumn; import net.sourceforge.ganttproject.io.CSVOptions; import net.sourceforge.ganttproject.language.GanttLanguage; import net.sourceforge.ganttproject.resource.HumanResource; import net.sourceforge.ganttproject.resource.HumanResourceManager; import net.sourceforge.ganttproject.roles.Role; import net.sourceforge.ganttproject.roles.RoleManager; import net.sourceforge.ganttproject.task.ResourceAssignment; import net.sourceforge.ganttproject.task.Task; import net.sourceforge.ganttproject.task.TaskManager; import net.sourceforge.ganttproject.task.TaskProperties; import net.sourceforge.ganttproject.util.StringUtils; import org.apache.commons.csv.CSVFormat; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; /** * Class to export the project in CSV text format * * @author athomas */ public class GanttCSVExport { private static final Predicate<ResourceAssignment> COORDINATOR_PREDICATE = arg -> arg.isCoordinator(); private CSVOptions myCsvOptions; private final TaskManager myTaskManager; private final CustomPropertyManager myTaskCustomPropertyManager; private final HumanResourceManager myHumanResourceManager; private final CustomPropertyManager myHumanResourceCustomPropertyManager; private final RoleManager myRoleManager; public GanttCSVExport(IGanttProject project, CSVOptions csvOptions) { this(project.getTaskManager(), project.getHumanResourceManager(), project.getRoleManager(), csvOptions); } GanttCSVExport(TaskManager taskManager, HumanResourceManager resourceManager, RoleManager roleManager, CSVOptions csvOptions) { myTaskManager = Preconditions.checkNotNull(taskManager); myTaskCustomPropertyManager = Preconditions.checkNotNull(taskManager.getCustomPropertyManager()); myHumanResourceManager = Preconditions.checkNotNull(resourceManager); myHumanResourceCustomPropertyManager = Preconditions.checkNotNull(resourceManager.getCustomPropertyManager()); myRoleManager = Preconditions.checkNotNull(roleManager); myCsvOptions = Preconditions.checkNotNull(csvOptions); } private CSVFormat getCSVFormat() { CSVFormat format = CSVFormat.DEFAULT.withEscape('\\'); if (myCsvOptions.sSeparatedChar.length() == 1) { format = format.withDelimiter(myCsvOptions.sSeparatedChar.charAt(0)); } if (myCsvOptions.sSeparatedTextChar.length() == 1) { format = format.withQuote(myCsvOptions.sSeparatedTextChar.charAt(0)); } return format; } public SpreadsheetWriter createWriter(OutputStream stream, SpreadsheetFormat format) throws IOException { format = Preconditions.checkNotNull(format); switch (format) { case CSV: return getCsvWriter(stream); case XLS: return getXlsWriter(stream); default: throw new IllegalArgumentException("Unsupported format == " + format + "!"); } } private SpreadsheetWriter getCsvWriter(OutputStream stream) throws IOException { return new CsvWriterImpl(stream, getCSVFormat()); } private SpreadsheetWriter getXlsWriter(OutputStream stream) { return new XlsWriterImpl(stream); } public void save(SpreadsheetWriter writer) throws IOException { writeTasks(writer); if (myHumanResourceManager.getResources().size() > 0) { writer.println(); writer.println(); writeResources(writer); } } private List<CustomPropertyDefinition> writeTaskHeaders(SpreadsheetWriter writer) throws IOException { List<CustomPropertyDefinition> defs = myTaskCustomPropertyManager.getDefinitions(); for (Map.Entry<String, BooleanOption> entry : myCsvOptions.getTaskOptions().entrySet()) { TaskDefaultColumn defaultColumn = TaskDefaultColumn.find(entry.getKey()); if (!entry.getValue().isChecked()) { continue; } if (defaultColumn == null) { writer.print(i18n(entry.getKey())); } else { writer.print(defaultColumn.getName()); } } for (CustomPropertyDefinition def : defs) { writer.print(def.getName()); } writer.println(); return defs; } private String i18n(String key) { return GanttLanguage.getInstance().getText(key); } private void writeTasks(SpreadsheetWriter writer) throws IOException { List<CustomPropertyDefinition> customFields = writeTaskHeaders(writer); for (Task task : myTaskManager.getTasks()) { for (Map.Entry<String, BooleanOption> entry : myCsvOptions.getTaskOptions().entrySet()) { if (!entry.getValue().isChecked()) { continue; } TaskDefaultColumn defaultColumn = TaskDefaultColumn.find(entry.getKey()); if (defaultColumn == null) { if ("webLink".equals(entry.getKey())) { writer.print(getWebLink((GanttTask) task)); continue; } if ("notes".equals(entry.getKey())) { writer.print(task.getNotes()); continue; } } else { switch (defaultColumn) { case ID: writer.print(String.valueOf(task.getTaskID())); break; case NAME: writer.print(getName(task)); break; case BEGIN_DATE: writer.print(task.getStart().toString()); break; case END_DATE: writer.print(task.getDisplayEnd().toString()); break; case DURATION: writer.print(String.valueOf(task.getDuration().getLength())); break; case COMPLETION: writer.print(String.valueOf(task.getCompletionPercentage())); break; case OUTLINE_NUMBER: List<Integer> outlinePath = task.getManager().getTaskHierarchy().getOutlinePath(task); writer.print(Joiner.on('.').join(outlinePath)); break; case COORDINATOR: ResourceAssignment coordinator = Iterables.tryFind(Arrays.asList(task.getAssignments()), COORDINATOR_PREDICATE).orNull(); writer.print(coordinator == null ? "" : coordinator.getResource().getName()); break; case PREDECESSORS: writer.print(TaskProperties.formatPredecessors(task, ";", true)); break; case RESOURCES: writer.print(getAssignments(task)); break; case COST: writer.print(task.getCost().getValue().toPlainString()); break; case INFO: case PRIORITY: case TYPE: break; } } } writeCustomPropertyValues(writer, customFields, task.getCustomValues().getCustomProperties()); } } private List<CustomPropertyDefinition> writeResourceHeaders(SpreadsheetWriter writer) throws IOException { for (Map.Entry<String, BooleanOption> entry : myCsvOptions.getResourceOptions().entrySet()) { ResourceDefaultColumn defaultColumn = ResourceDefaultColumn.find(entry.getKey()); if (!entry.getValue().isChecked()) { continue; } if (defaultColumn == null) { if ("id".equals(entry.getKey())) { writer.print(i18n("tableColID")); } else { writer.print(i18n(entry.getKey())); } } else { writer.print(defaultColumn.getName()); } } List<CustomPropertyDefinition> customFieldDefs = myHumanResourceCustomPropertyManager.getDefinitions(); for (CustomPropertyDefinition nextDef : customFieldDefs) { writer.print(nextDef.getName()); } writer.println(); return customFieldDefs; } private void writeResources(SpreadsheetWriter writer) throws IOException { Set<Role> projectRoles = Sets.newHashSet(myRoleManager.getProjectLevelRoles()); List<CustomPropertyDefinition> customPropDefs = writeResourceHeaders(writer); // parse all resources for (HumanResource p : myHumanResourceManager.getResources()) { for (Map.Entry<String, BooleanOption> entry : myCsvOptions.getResourceOptions().entrySet()) { if (!entry.getValue().isChecked()) { continue; } ResourceDefaultColumn defaultColumn = ResourceDefaultColumn.find(entry.getKey()); if (defaultColumn == null) { if ("id".equals(entry.getKey())) { writer.print(String.valueOf(p.getId())); continue; } } else { switch (defaultColumn) { case NAME: writer.print(p.getName()); break; case EMAIL: writer.print(p.getMail()); break; case PHONE: writer.print(p.getPhone()); break; case ROLE: Role role = p.getRole(); final String sRoleID; if (role == null) { sRoleID = "0"; } else if (projectRoles.contains(role)) { sRoleID = role.getName(); } else { sRoleID = role.getPersistentID(); } writer.print(sRoleID); break; case ROLE_IN_TASK: writer.print(""); break; case STANDARD_RATE: writer.print(p.getStandardPayRate().toPlainString()); break; case TOTAL_COST: writer.print(p.getTotalCost().toPlainString()); break; } } } writeCustomPropertyValues(writer, customPropDefs, p.getCustomProperties()); } } private void writeCustomPropertyValues(SpreadsheetWriter writer, List<CustomPropertyDefinition> defs, List<CustomProperty> values) throws IOException { Map<String, CustomProperty> definedProps = Maps.newHashMap(); for (CustomProperty prop : values) { definedProps.put(prop.getDefinition().getID(), prop); } for (CustomPropertyDefinition def : defs) { CustomProperty value = definedProps.get(def.getID()); String valueAsString = value == null ? null : Strings.nullToEmpty(value.getValueAsString()); writer.print(valueAsString); } writer.println(); } /** * @return the name of task with the correct level. */ private String getName(Task task) { if (myCsvOptions.bFixedSize) { return task.getName(); } int depth = task.getManager().getTaskHierarchy().getDepth(task) - 1; return StringUtils.padLeft(task.getName(), depth * 2); } /** * @return the link of the task. */ private String getWebLink(GanttTask task) { return (task.getWebLink() == null || task.getWebLink().equals("http://") ? "" : task.getWebLink()); } /** * @return the list of the assignment for the resources. */ private String getAssignments(Task task) { StringBuilder res = new StringBuilder(); ResourceAssignment[] assignment = task.getAssignments(); for (int i = 0; i < assignment.length; i++) { String assignmentDelimiter = i == assignment.length - 1 ? "" : myCsvOptions.sSeparatedChar.equals(";") ? "," : ";"; res.append(assignment[i].getResource()).append(assignmentDelimiter); } return res.toString(); } }