/*
GanttProject is an opensource project management tool.
Copyright (C) 2005-2011 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 org.ganttproject.impex.htmlpdf;
import java.net.URI;
import java.net.URLDecoder;
import java.util.List;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamSource;
import net.sourceforge.ganttproject.CustomProperty;
import net.sourceforge.ganttproject.CustomPropertyDefinition;
import net.sourceforge.ganttproject.document.Document;
import net.sourceforge.ganttproject.export.ExportException;
import net.sourceforge.ganttproject.export.TaskVisitor;
import net.sourceforge.ganttproject.gui.UIFacade;
import net.sourceforge.ganttproject.io.SaverBase;
import net.sourceforge.ganttproject.language.GanttLanguage;
import net.sourceforge.ganttproject.resource.HumanResource;
import net.sourceforge.ganttproject.resource.HumanResourceManager;
import net.sourceforge.ganttproject.task.CustomColumnsValues;
import net.sourceforge.ganttproject.task.ResourceAssignment;
import net.sourceforge.ganttproject.task.Task;
import net.sourceforge.ganttproject.task.TaskManager;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import biz.ganttproject.core.table.ColumnList;
/**
* Serializes project data into XML for GanttProject's HTML/FOP stylesheets.
*
* @author dbarashev (Dmitry Barashev)
*/
public class XmlSerializer extends SaverBase {
private final SAXTransformerFactory myFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
protected void startPrefixedElement(String name, AttributesImpl attrs, TransformerHandler handler)
throws SAXException {
handler.startElement("http://ganttproject.sf.net/", name, "ganttproject:" + name, attrs);
attrs.clear();
}
protected void endPrefixedElement(String name, TransformerHandler handler) throws SAXException {
handler.endElement("http://ganttproject.sf.net/", name, "ganttproject:" + name);
}
protected void textElement(String name, AttributesImpl attrs, String text, TransformerHandler handler)
throws SAXException {
if (text != null) {
startElement(name, attrs, handler);
handler.startCDATA();
handler.characters(text.toCharArray(), 0, text.length());
handler.endCDATA();
endElement(name, handler);
attrs.clear();
}
}
protected SAXTransformerFactory getTransformerFactory() {
return myFactory;
}
protected TransformerHandler createHandler(String xsltPath) throws TransformerConfigurationException {
TransformerHandler result = getTransformerFactory().newTransformerHandler(new StreamSource(xsltPath));
Transformer transformer = result.getTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
return result;
}
protected String i18n(String key) {
String text = GanttLanguage.getInstance().getText(key);
return GanttLanguage.getInstance().correctLabel(text);
}
protected void writeColumns(ColumnList visibleFields, TransformerHandler handler) throws SAXException {
AttributesImpl attrs = new AttributesImpl();
int totalWidth = 0;
for (int i = 0; i < visibleFields.getSize(); i++) {
if (visibleFields.getField(i).isVisible()) {
totalWidth += visibleFields.getField(i).getWidth();
}
}
for (int i = 0; i < visibleFields.getSize(); i++) {
ColumnList.Column field = visibleFields.getField(i);
if (field.isVisible()) {
addAttribute("id", field.getID(), attrs);
addAttribute("name", field.getName(), attrs);
addAttribute("width", field.getWidth() * 100 / totalWidth, attrs);
emptyElement("field", attrs, handler);
}
}
}
protected void writeViews(UIFacade facade, TransformerHandler handler) throws SAXException {
AttributesImpl attrs = new AttributesImpl();
addAttribute("id", "task-table", attrs);
startElement("view", attrs, handler);
writeColumns(facade.getTaskTree().getVisibleFields(), handler);
endElement("view", handler);
addAttribute("id", "resource-table", attrs);
startElement("view", attrs, handler);
writeColumns(facade.getResourceTree().getVisibleFields(), handler);
endElement("view", handler);
}
protected void writeTasks(final TaskManager taskManager, final TransformerHandler handler) throws ExportException,
SAXException {
AttributesImpl attrs = new AttributesImpl();
addAttribute("xslfo-path", "", attrs);
addAttribute("title", i18n("tasksList"), attrs);
addAttribute("name", i18n("name"), attrs);
addAttribute("begin", i18n("start"), attrs);
addAttribute("end", i18n("end"), attrs);
addAttribute("milestone", i18n("meetingPoint"), attrs);
addAttribute("progress", "%", attrs);
addAttribute("assigned-to", i18n("human"), attrs);
addAttribute("notes", i18n("notes"), attrs);
addAttribute("duration", i18n("duration"), attrs);
startPrefixedElement("tasks", attrs, handler);
TaskVisitor visitor = new TaskVisitor() {
AttributesImpl myAttrs = new AttributesImpl();
@Override
protected String serializeTask(Task t, int depth) throws Exception {
addAttribute("depth", depth, myAttrs);
startPrefixedElement("task", myAttrs, handler);
{
addAttribute("id", "tpd1", myAttrs);
textElement("priority", myAttrs, i18n(t.getPriority().getI18nKey()), handler);
}
addAttribute("id", "tpd3", myAttrs);
textElement("name", myAttrs, t.getName(), handler);
addAttribute("id", "tpd4", myAttrs);
textElement("begin", myAttrs, t.getStart().toString(), handler);
addAttribute("id", "tpd5", myAttrs);
textElement("end", myAttrs, t.getDisplayEnd().toString(), handler);
textElement("milestone", myAttrs, Boolean.valueOf(t.isMilestone()).toString(), handler);
addAttribute("id", "tpd7", myAttrs);
textElement("progress", myAttrs, String.valueOf(t.getCompletionPercentage()), handler);
addAttribute("id", "tpd6", myAttrs);
textElement("duration", myAttrs, String.valueOf(t.getDuration().getLength()), handler);
final List<Document> attachments = t.getAttachments();
for (int i = 0; i < attachments.size(); i++) {
Document nextAttachment = attachments.get(i);
URI nextUri = nextAttachment.getURI();
if (nextUri != null) {
String strUri = URLDecoder.decode(nextUri.toString(), "utf-8");
if (strUri.startsWith("file:")) {
if (strUri.endsWith("/")) {
strUri = strUri.replaceAll("/+$", "");
}
int lastSlash = strUri.lastIndexOf('/');
if (lastSlash >= 0) {
addAttribute("display-name", strUri.substring(lastSlash + 1), myAttrs);
}
}
textElement("attachment", myAttrs, strUri, handler);
} else {
textElement("attachment", myAttrs, nextAttachment.getPath(), handler);
}
}
{
HumanResource coordinator = t.getAssignmentCollection().getCoordinator();
if (coordinator != null) {
addAttribute("id", "tpd8", myAttrs);
textElement("coordinator", myAttrs, coordinator.getName(), handler);
}
}
StringBuffer usersS = new StringBuffer();
ResourceAssignment[] assignments = t.getAssignments();
if (assignments.length > 0) {
for (int j = 0; j < assignments.length; j++) {
addAttribute("resource-id", assignments[j].getResource().getId(), myAttrs);
emptyElement("assigned-resource", myAttrs, handler);
usersS.append(assignments[j].getResource().getName());
if (j < assignments.length - 1) {
usersS.append(getAssignedResourcesDelimiter());
}
}
}
addAttribute("id", "tpdResources", myAttrs);
textElement("assigned-to", myAttrs, usersS.toString(), handler);
if (t.getNotes() != null && t.getNotes().length() > 0) {
textElement("notes", myAttrs, t.getNotes(), handler);
}
if (t.getColor() != null) {
textElement("color", myAttrs, getHexaColor(t.getColor()), handler);
}
{
AttributesImpl attrs = new AttributesImpl();
CustomColumnsValues customValues = t.getCustomValues();
for (CustomPropertyDefinition def : taskManager.getCustomPropertyManager().getDefinitions()) {
Object value = customValues.getValue(def);
String valueAsString = value == null ? "" : value.toString();
addAttribute("id", def.getID(), attrs);
textElement("custom-field", attrs, valueAsString, handler);
}
}
endPrefixedElement("task", handler);
return "";
}
};
try {
visitor.visit(taskManager);
} catch (Exception e) {
throw new ExportException("Failed to write tasks", e);
}
endPrefixedElement("tasks", handler);
}
protected String getAssignedResourcesDelimiter() {
return " ";
}
protected void writeResources(HumanResourceManager resourceManager, TransformerHandler handler) throws SAXException {
AttributesImpl attrs = new AttributesImpl();
addAttribute("title", i18n("resourcesList"), attrs);
addAttribute("name", i18n("colName"), attrs);
addAttribute("role", i18n("colRole"), attrs);
addAttribute("mail", i18n("colMail"), attrs);
addAttribute("phone", i18n("colPhone"), attrs);
addAttribute("rate", i18n("colStandardRate"), attrs);
addAttribute("totalCost", i18n("colTotalCost"), attrs);
startPrefixedElement("resources", attrs, handler);
{
List<HumanResource> resources = resourceManager.getResources();
// String[] function =
// RoleManager.Access.getInstance().getRoleNames();
for (int i = 0; i < resources.size(); i++) {
HumanResource p = resources.get(i);
addAttribute("id", p.getId(), attrs);
startPrefixedElement("resource", attrs, handler);
addAttribute("id", "0", attrs);
textElement("name", attrs, p.getName(), handler);
addAttribute("id", "1", attrs);
textElement("role", attrs, p.getRole().getName(), handler);
addAttribute("id", "2", attrs);
textElement("mail", attrs, p.getMail(), handler);
addAttribute("id", "3", attrs);
textElement("phone", attrs, p.getPhone(), handler);
addAttribute("id", "5", attrs);
textElement("rate", attrs, p.getStandardPayRate().toPlainString(), handler);
addAttribute("id", "6", attrs);
textElement("totalCost", attrs, p.getTotalCost().toPlainString(), handler);
List<CustomProperty> customFields = p.getCustomProperties();
for (int j = 0; j < customFields.size(); j++) {
CustomProperty nextProperty = customFields.get(j);
addAttribute("id", nextProperty.getDefinition().getID(), attrs);
String value = nextProperty.getValueAsString();
textElement("custom-field", attrs, value, handler);
}
endPrefixedElement("resource", handler);
}
}
endPrefixedElement("resources", handler);
}
protected static String getHexaColor(java.awt.Color color) {
StringBuffer out = new StringBuffer();
out.append("#");
if (color.getRed() <= 15) {
out.append("0");
}
out.append(Integer.toHexString(color.getRed()));
if (color.getGreen() <= 15) {
out.append("0");
}
out.append(Integer.toHexString(color.getGreen()));
if (color.getBlue() <= 15) {
out.append("0");
}
out.append(Integer.toHexString(color.getBlue()));
return out.toString();
}
}