/***************************************************************************
 * GanttXMLSaver.java  -  description
 * -------------------
 * begin                : feb 2003
 * copyright            : (C) 2002 by Thomas Alexandre
 * email                : alexthomas(at)ganttproject.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

package net.sourceforge.ganttproject.io;

import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

import net.sourceforge.ganttproject.GanttCalendar;
import net.sourceforge.ganttproject.GanttGraphicArea;
import net.sourceforge.ganttproject.GanttPreviousState;
import net.sourceforge.ganttproject.GanttPreviousStateTask;
import net.sourceforge.ganttproject.GanttProject;
import net.sourceforge.ganttproject.GanttResourcePanel;
import net.sourceforge.ganttproject.GanttTask;
import net.sourceforge.ganttproject.GanttTaskRelationship;
import net.sourceforge.ganttproject.GanttTree2;
import net.sourceforge.ganttproject.GanttTreeTable;
import net.sourceforge.ganttproject.IGanttProject;
import net.sourceforge.ganttproject.Mediator;
import net.sourceforge.ganttproject.calendar.GanttDaysOff;
import net.sourceforge.ganttproject.gui.UIFacade;
import net.sourceforge.ganttproject.resource.HumanResource;
import net.sourceforge.ganttproject.roles.Role;
import net.sourceforge.ganttproject.roles.RoleManager;
import net.sourceforge.ganttproject.roles.RoleSet;
import net.sourceforge.ganttproject.shape.ShapeConstants;
import net.sourceforge.ganttproject.shape.ShapePaint;
import net.sourceforge.ganttproject.task.CustomColumn;
import net.sourceforge.ganttproject.task.CustomColumnsException;
import net.sourceforge.ganttproject.task.CustomColumnsStorage;
import net.sourceforge.ganttproject.task.CustomColumnsValues;
import net.sourceforge.ganttproject.task.ResourceAssignment;
import net.sourceforge.ganttproject.task.BlankLineNode;
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;

/**
 * Classe for save the project in a XML file
 */
public class GanttXMLSaver implements GPSaver {

    private final IGanttProject myProject;

    private final UIFacade myUIFacade;

    private GanttTree2 tree;

    private GanttResourcePanel peop;

    private GanttGraphicArea area;

    private HashMap usersId = new HashMap();

    ArrayList number = new ArrayList();

    // List of tasks
    //ArrayList lot = new ArrayList();
    Task[] lot;
    //ArrayList lots = new ArrayList();

    int cpt;

    String s = "    "; // the marge

    /** The constructor */
    public GanttXMLSaver(IGanttProject project, GanttTree2 tree,
            GanttResourcePanel peop, GanttGraphicArea area, UIFacade uiFacade) {
        this.tree = tree;
        this.peop = peop;
        this.area = area;
        myProject = project;
        myUIFacade = uiFacade;
    }

    /** Replace a part of the string by another one */
    public String replaceAll(String notes, String s1, String s2) {

        return notes.replaceAll(s1, s2);
    }

    /** Simple write information of tasks */
    public void writeTask(Writer fout, DefaultMutableTreeNode node, String space) {
        String space2 = s + space;
        try {

            if (node instanceof BlankLineNode) {
                fout.write(space + "<blankline />\n");
                return;
            }

            GanttTask task = (GanttTask) node.getUserObject();

            if (task.getTaskID() == -1)
                throw new RuntimeException(
                        "A task can not has a number equal to -1");

            int id = task.getTaskID();

            /*
             * if (id >= lot.size()) { return; }
             */

            boolean haschild = false;

            ArrayList child = tree.getAllChildTask(node);
            if (child.size() != 0) {
                haschild = true;

            }

            number.add(new Integer(id));
            cpt++;

            // Writes data of task
            fout.write(space + "<task id=\"" + task.getTaskID() + // lots.indexOf(task.toString())
                    // + //By CL
                    "\" ");
            fout.write("name=\"" + correct(task.getName()) + "\" ");

            if (task.colorDefined()) {
                /*
                 * fout.write("color=\"#"); if (task.getColor().getRed() <= 15) {
                 * fout.write("0"); }
                 * fout.write(Integer.toHexString(task.getColor().getRed())); if
                 * (task.getColor().getGreen() <= 15) { fout.write("0"); }
                 * fout.write(Integer.toHexString(task.getColor().getGreen()));
                 * if (task.getColor().getBlue() <= 15) { fout.write("0"); }
                 * fout.write(Integer.toHexString(task.getColor().getBlue()));
                 * fout.write("\" ");
                 */
                fout.write("color=\""
                        + ColorConvertion.getColor(task.getColor()) + "\" ");
            }

            if (task.shapeDefined()
                    && task.getShape() != new ShapePaint(
                            ShapeConstants.BACKSLASH, task.getColor(), task
                                    .getColor())) {
                fout.write("shape=\"" + task.getShape().getArray() + "\" ");
            }

            fout.write("meeting=\"" + ((task.isMilestone()) ? "true" : "false")
                    + "\" ");
            if (task.isProjectTask())
                fout.write("project=\"true\" ");
            fout.write("start=\"" + task.getStart().toXMLString() + "\" ");
            fout.write("duration=\"" + task.getLength() + "\" ");
            fout.write("complete=\"" + task.getCompletionPercentage() + "\" ");
//            fout.write("fixed-start=\""
//                    + (task.isStartFixed() ? "true" : "false") + "\" ");

            if (task.getThird() != null) {
                fout.write("thirdDate=\"" + task.getThird().toXMLString()
                        + "\" ");
                fout.write("thirdDate-constraint=\""
                        + task.getThirdDateConstraint() + "\" ");
            }

            fout.write("priority=\"" + task.getPriority() + "\"");

            // write the web link of the task
            String sWebLink = task.getWebLink();
            if (sWebLink != null && !sWebLink.equals("")
                    && !sWebLink.equals("http://"))
                fout.write(" webLink=\""
                        + URLEncoder.encode(sWebLink, "ISO-8859-1") + "\"");

            // write if the task is expand or collapse
            fout.write(" expand=\"" + task.getExpand() + "\"");

            fout.write(">\n");
            if (task.getNotes() != null && task.getNotes().length() > 0) {
                fout.write(space2 + "<notes>");
                fout.write("\n"
                        + space2
                        + s
                        + correct(replaceAll(task.getNotes(), "\n", "\n"
                                + space2 + s)));
                fout.write("\n" + space2 + "</notes>\n");
            }

            // Write the depends of the task
            /*
             * if (task.getDepend().size() != 0) { //fout.writeBytes(space2+"<depends>\n");
             * for (int i = 0; i < task.getDepend().size(); i++) {
             * fout.write(space2 + "<depend id=\"" + tree.getTask( (String)
             * task.getDepend().get(i)).getTaskID() + // changed By CL
             * //lots.indexOf( (String) task.getDepend().get(i)) + "\"/>\n");
             * //fout.writeBytes(space2+"</depends>\n"); } }
             */

            // use successors to write depends information
            TaskDependency[] depsAsDependee = task.getDependenciesAsDependee().toArray();
            for (int i = 0; i < depsAsDependee.length; i++) {
            	TaskDependency next = depsAsDependee[i];
                fout.write(space2 /* +s */+ "<depend id=\""
                        + next.getDependant().getTaskID() + "\"" + " type=\""
                        + next.getConstraint().getID()
                        + "\" difference=\"" + next.getDifference()
                        + "\" hardness=\""+next.getHardness().getIdentifier()
                        + "\"/>\n");
            }

            CustomColumnsValues ccv = task.getCustomValues();
            CustomColumnsStorage ccs = Mediator.getCustomColumnsStorage();
            List names = ccs.getCustomColumnsNames();
            Iterator it = names.iterator();
            while (it.hasNext()) {
                String name, idc, value;
                name = null;
                idc = null;
                value = null;
                try {
                    name = (String) it.next();
                    idc = ccs.getIdFromName(name);
                    value = ccv.getValue(name).toString();
                    CustomColumn cc = ccs.getCustomColumn(name);
                    if (GregorianCalendar.class.isAssignableFrom(cc.getType()))
                        value = DateParser.getIsoDate(((GanttCalendar) ccv
                                .getValue(name)).getTime());
                    fout.write(s + s + s + "<customproperty taskproperty-id=\""
                            + idc + "\" value=\"" + value + "\" />\n");
                } catch (NullPointerException e) {
                    System.out.println(name + ", " + idc + ", " + value);
                    e.printStackTrace();
                }
            }

            // Write the child of the task
            if (haschild) {
                for (int i = 0; i < child.size(); i++) {
                    Task task2 = (Task) ((DefaultMutableTreeNode) child.get(i))
                            .getUserObject();
                    int newid = -1; // lot.lastIndexOf(task2);

                    for (int j = 0; j < lot.length; j++) {
                        String a = task2.getName();
                        if (a == null)
                            System.out.println("nul");
                        String b = lot[j].getName();

                        if (a.equals(b)) {
                            newid = j;
                        }
                    }
                    writeTask(fout, (DefaultMutableTreeNode) child.get(i),
                            space + s);
                }

            }

            // end of task section
            fout.write(space + "</task>\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void writeTaskProperties(Writer fout, CustomColumnsStorage customCol) {
        try {

            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd0\" name=\"type\" type=\"default\" valuetype=\"icon\" />\n");
            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd1\" name=\"priority\" type=\"default\" valuetype=\"icon\" />\n");
            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd2\" name=\"info\" type=\"default\" valuetype=\"icon\" />\n");
            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd3\" name=\"name\" type=\"default\" valuetype=\"text\" />\n");
            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd4\" name=\"begindate\" type=\"default\" valuetype=\"date\" />\n");
            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd5\" name=\"enddate\" type=\"default\" valuetype=\"date\" />\n");
            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd6\" name=\"duration\" type=\"default\" valuetype=\"int\" />\n");
            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd7\" name=\"completion\" type=\"default\" valuetype=\"int\" />\n");
            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd8\" name=\"coordinator\" type=\"default\" valuetype=\"text\" />\n");
            fout
                    .write(s
                            + s
                            + s
                            + "<taskproperty id=\"tpd9\" name=\"predecessors\" type=\"default\" valuetype=\"text\" />\n");

            Iterator it = customCol.getCustomColumnsNames().iterator();
            while (it.hasNext()) {
                String colName = (String) it.next();
                try {
                    CustomColumn cc = customCol.getCustomColumn(colName);
                    Object defVal = cc.getDefaultValue();
                    String valueType = null;
                    Class cla = cc.getType();
                    if (cla.equals(String.class))
                        valueType = "text";
                    else if (cla.equals(Boolean.class))
                        valueType = "boolean";
                    else if (cla.equals(Integer.class))
                        valueType = "int";
                    else if (cla.equals(Double.class))
                        valueType = "double";
                    else if (cla.isAssignableFrom(GregorianCalendar.class)) // TODO
                    // to
                    // be
                    // tested
                    {
                        valueType = "date";
                        defVal = DateParser.getIsoDate(((GanttCalendar) cc
                                .getDefaultValue()).getTime());
                    }

                    String idcStr = Mediator.getCustomColumnsStorage()
                            .getIdFromName(cc.getName());

                    fout.write(s + s + s + "<taskproperty id=\"" + idcStr
                            + "\" name=\"" + cc.getName()
                            + "\" type=\"custom\" valuetype=\"" + valueType
                            + "\" defaultvalue=\"" + defVal.toString()
                            + "\" />\n");
                } catch (CustomColumnsException e1) {
                    e1.printStackTrace();
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void writeTaskDisplayColumns(Writer fout) {
        List displayedColumns = tree.getTreeTable().getDisplayColumns();
        if (displayedColumns != null) {
            Iterator it = displayedColumns.iterator();
            while (it.hasNext()) {
                GanttTreeTable.DisplayedColumn dc = (GanttTreeTable.DisplayedColumn) it
                        .next();
                if (dc.isDisplayed())
                    try {
                        fout.write(s + s + "<displaycolumn property-id=\""
                                + dc.getID() + "\" order=\"" + dc.getOrder()
                                + "\" width=\"" + dc.getWidth() + "\" />\n");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }
        }
    }

    /** Write the resources on the file */
    public void writeResources(Writer fout) {
        try {
            List resources = peop.getPeople();
            int cpt_resources = 1;
            for (int i = 0; i < resources.size(); i++, cpt_resources++) {
                HumanResource p = (HumanResource) resources.get(i);
                String string = p.getName();
                byte[] btf8 = string.getBytes("UTF-8");

                fout.write(s + s + "<resource id=\"" + p.getId() + "\" name=\""
                        + (p.getName() != null ? correct(p.getName()) : "")
                        + "\" function=\"" + p.getRole().getPersistentID()
                        + "\" contacts=\""
                        + (p.getMail() != null ? correct(p.getMail()) : "")
                        + "\" phone=\""
                        + (p.getPhone() != null ? correct(p.getPhone()) : "")
                        + "\" />\n");
                usersId.put(p.getName(), new Integer(cpt_resources));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** Write the vacations on the file */
    public void writeVacations(Writer fout) {
        try {
            List resources = peop.getPeople();
            int cpt_resources = 1;
            for (int i = 0; i < resources.size(); i++, cpt_resources++) {
                HumanResource p = (HumanResource) resources.get(i);
                if (p.getDaysOff() != null)
                    for (int j = 0; j < p.getDaysOff().size(); j++) {
                        GanttDaysOff gdo = (GanttDaysOff) p.getDaysOff()
                                .getElementAt(j);
                        fout.write(s + s + "<vacation start=\""
                                + gdo.getStart().toXMLString() + "\" end=\""
                                + gdo.getFinish().toXMLString()
                                + "\" resourceid=\"" + p.getId() + "\"/>\n");
                    }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Write all previous states of the project.
     * 
     * @throws IOException
     */
    public void writePreviousStateTasks(Writer fout) throws IOException {
        ArrayList previousStates = ((GanttProject) myProject)
                .getPreviouStates();
        for (int i = 0; i < previousStates.size(); i++) {
            ArrayList list = null;
            try {
                list = ((GanttPreviousState) previousStates.get(i)).load();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            // ArrayList list =
            // ((GanttPreviousState)previous.get(i)).getTasks();
            fout.write(s + s + "<previous-tasks name=\""
                    + ((GanttPreviousState) previousStates.get(i)).getName()
                    + "\">\n");
            for (int j = 0; j < list.size(); j++) {
                GanttPreviousStateTask task = (GanttPreviousStateTask) list
                        .get(j);

                fout.write(s + s + s + "<previous-task id=\"" + task.getId()
                        + "\"");
                fout.write(" start=\"" + task.getStart().toXMLString() + "\"");
                fout.write(" duration=\"" + task.getDuration() + "\"");
                fout.write(" meeting=\"" + task.isMilestone() + "\"");
                fout.write(" super=\"" + task.hasNested() + "\"");
                fout.write("/>\n");

            }
            fout.write(s + s + "</previous-tasks>\n");
        }

    }

    /** Write the assignement between tasks and users */
    public void writeAllocations(Writer fout) {
        try {

            for (int i = 0; i < lot.length; i++) {
                Task task = lot[i];
                // ArrayList users = task.getUsersList();
                ResourceAssignment[] assignments = task.getAssignments();
                for (int j = 0; j < assignments.length; j++) {
                    int task_id = task.getTaskID();// (i-1);
                    ResourceAssignment next = assignments[j];

                    Role roleForAssignment = next.getRoleForAssignment();
                    if (roleForAssignment == null)
                        if (next.getResource() instanceof HumanResource)
                            roleForAssignment = ((HumanResource) next
                                    .getResource()).getRole();

                    fout.write(s + s + "<allocation task-id=\"" + task_id
                            + "\" resource-id=\"" + next.getResource().getId()
                            + "\" function=\""
                            + roleForAssignment.getPersistentID()
                            + "\" responsible=\"" + next.isCoordinator()
                            + "\" load=\"" + next.getLoad() + "\"/>\n");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** Write all roles of the project. */
    public void writeRoles(Writer fout) {
        try {
            // int id=RoleManager.Access.getInstance().DEFAULT_ROLES_NUMBER;
            // String []roles=RoleManager.Access.getInstance().getRolesShort();
            Role[] projectRoles = RoleManager.Access.getInstance()
                    .getProjectLevelRoles();
            for (int i = 0; i < projectRoles.length; i++) {
                Role next = projectRoles[i];
                fout.write(s + s + "<role id=\"" + (next.getPersistentID())
                        + "\" name=\"" + correct(next.getName()) + "\"/>\n");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** Correct the charcters to be compatible with xml format */
    public String correct(String s) {
        String res;
        if (s != null) {
            res = s.replaceAll("&", "&#38;");
            res = res.replaceAll("<", "&#60;");
            res = res.replaceAll(">", "&#62;");
            res = res.replaceAll("/", "&#47;");
            res = res.replaceAll("\"", "&#34;");
        } else
            res = s;
        return res;
    }

    public void save(OutputStream stream) {
        save(stream, "1.12");
    }

    /** Save the project as XML on a stream (including the XML-prolog) */
    public void save(OutputStream stream, String version) {
        try {
            OutputStreamWriter fout = new OutputStreamWriter(stream, "UTF-8");
            save(fout, version, true);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(e);
            // System.out.println("Error in saving the file");
        } catch (TransformerFactoryConfigurationError e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TransformerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private void startElement(String name, AttributesImpl attrs,
            TransformerHandler handler) throws SAXException {
        handler.startElement("", name, name, attrs);
        attrs.clear();
    }

    private void endElement(String name, TransformerHandler handler)
            throws SAXException {
        handler.endElement("", name, name);
    }

    private void addAttribute(String name, String value, AttributesImpl attrs) {
        attrs.addAttribute("", name, name, "CDATA", value);
    }

    private void emptyElement(String name, AttributesImpl attrs,
            TransformerHandler handler) throws SAXException {
        startElement(name, attrs, handler);
        endElement(name, handler);
        attrs.clear();
    }

    private void emptyComment(TransformerHandler handler) throws SAXException {
        handler.comment(new char[] { ' ' }, 0, 1);

    }

    public void save(OutputStreamWriter _fout, String version,
            boolean includeProlog) throws IOException,
            TransformerFactoryConfigurationError, TransformerException,
            SAXException {
        try {
            AttributesImpl attrs = new AttributesImpl();
            StreamResult result = new StreamResult(_fout);
            SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory
                    .newInstance();
            TransformerHandler handler = factory.newTransformerHandler();
            Transformer serializer = handler.getTransformer();
            serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.setOutputProperty(
                    "{http://xml.apache.org/xslt}indent-amount", "4");
            handler.setResult(result);
            handler.startDocument();
            addAttribute("name", getProject().getProjectName(), attrs);
            addAttribute("company", getProject().getOrganization(), attrs);
            addAttribute("webLink", getProject().getWebLink(), attrs);
            addAttribute("view-date", new GanttCalendar(area.getViewState()
                    .getStartDate()).toXMLString(), attrs);
            addAttribute("view-index", "" + myUIFacade.getViewIndex(), attrs);
            //TODO for GP 2.0: move view configurations into <view> tag (see ViewSaver) 
            addAttribute("gantt-divider-location", ""
                    + myUIFacade.getGanttDividerLocation(), attrs);
            addAttribute("resource-divider-location", ""
                    + myUIFacade.getResourceDividerLocation(), attrs);
            addAttribute("version", version, attrs);
            startElement("project", attrs, handler);
            saveViews(handler);
            emptyComment(handler);
            saveCalendar(handler);
            _save(_fout, version);

            saveRoles(handler);
            endElement("project", handler);
            handler.endDocument();

            _fout.close();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    private void saveViews(TransformerHandler handler) throws SAXException {
        new ViewSaver().save(getUIFacade(), handler);
    }

    private void saveCalendar(TransformerHandler handler) throws SAXException {
        new CalendarSaver().save(getProject(), handler);
    }

    private void saveRoles(TransformerHandler handler) throws SAXException {
        AttributesImpl attrs = new AttributesImpl();
        RoleManager roleManager = getProject().getRoleManager();
        RoleSet[] roleSets = roleManager.getRoleSets();
        for (int i = 0; i < roleSets.length; i++) {
            RoleSet next = roleSets[i];
            if (next.isEnabled()) {
                addAttribute("roleset-name", next.getName(), attrs);
                emptyElement("roles", attrs, handler);
            }
        }
        //
        RoleSet projectRoleSet = roleManager.getProjectRoleSet();
        if (!projectRoleSet.isEmpty()) {
            startElement("roles", attrs, handler);
            Role[] projectRoles = projectRoleSet.getRoles();
            for (int i = 0; i < projectRoles.length; i++) {
                Role next = projectRoles[i];
                addAttribute("id", next.getPersistentID(), attrs);
                addAttribute("name", next.getName(), attrs);
                emptyElement("role", attrs, handler);
            }
            endElement("roles", handler);
        }
    }

    /**
     * Save the project as XML on a writer
     * 
     * @throws TransformerFactoryConfigurationError
     * @throws TransformerFactoryConfigurationError
     * @throws TransformerException
     * @throws SAXException
     */
    public void _save(OutputStreamWriter fout, String version) throws IOException,
            TransformerFactoryConfigurationError, TransformerException,
            SAXException {
        // String space=" ";
        number.clear();

        fout.write(s + "<description>");
        if (!getProject().getDescription().equals("")) {
            fout.write("\n"
                    + s
                    + s
                    + correct(replaceAll(getProject().getDescription(), "\n",
                            "\n" + s + s)) + "\n");
        }
        fout.write(s + "</description>\n\n");

        lot = this.myProject.getTaskManager().getTasks();

        // begin of tasks
        // fout.write(s + "<tasks>\n");

        // begin of tasks
        fout.write(s + "<tasks ");
        Color taskColor = area.getTaskColor();
        if (taskColor!=null) {
            fout.write("color=\"" + ColorConvertion.getColor(taskColor)
                    + "\"");
        }
        fout.write(">\n");

        fout.write(s + s + "<taskproperties>\n");
        writeTaskProperties(fout, Mediator.getCustomColumnsStorage());
        fout.write(s + s + "</taskproperties>\n");

        cpt = 1;
        Enumeration children = ((DefaultMutableTreeNode) tree.getJTree()
                .getModel().getRoot()).children();
        while (children.hasMoreElements()) {
            DefaultMutableTreeNode element = (DefaultMutableTreeNode) children
                    .nextElement();
            writeTask(fout, /* lot.indexOf(element) */element, s + s);
        }

        // end of tasks
        fout.write(s + "</tasks>\n\n");

        // write the resources
        fout.write(s + "<resources>\n");
        writeResources(fout);
        fout.write(s + "</resources>\n\n");

        // write the assign task to user
        fout.write(s + "<allocations>\n");
        writeAllocations(fout);
        fout.write(s + "</allocations>\n\n");

        fout.write(s + "<vacations>\n");
        writeVacations(fout);
        fout.write(s + "</vacations>\n\n");

        fout.write(s + "<taskdisplaycolumns>\n");
        writeTaskDisplayColumns(fout);
        fout.write(s + "</taskdisplaycolumns>\n\n");

        fout.write(s + "<previous>\n");
        writePreviousStateTasks(fout);
        fout.write(s + "</previous>\n\n");

        // write the assign task to user

        // end of project
        // fout.write("</project>\n");

        // fout.close();
        //

    }

    IGanttProject getProject() {
        return myProject;
    }

    UIFacade getUIFacade() {
        return myUIFacade;
    }
}
