/*
 * This file is part of NavalPlan
 *
 * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
 *                    Desenvolvemento Tecnolóxico de Galicia
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.navalplanner.web.calendars;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.zkoss.zul.SimpleTreeModel;
import org.zkoss.zul.SimpleTreeNode;

/**
 * Model for the {@link BaseCalendar} tree.
 *
 * @author Manuel Rego Casasnovas <mrego@igalia.com>
 */
public class BaseCalendarsTreeModel extends SimpleTreeModel {

    private static Map<BaseCalendar, List<BaseCalendar>> relationParentChildren = new HashMap<BaseCalendar, List<BaseCalendar>>();

    public BaseCalendarsTreeModel(BaseCalendarTreeRoot root) {
        super(createRootNodeAndDescendants(root, root.getRootCalendars(), root
                .getDerivedCalendars()));
    }

    private static SimpleTreeNode createRootNodeAndDescendants(
            BaseCalendarTreeRoot root, List<BaseCalendar> rootCalendars,
            List<BaseCalendar> derivedCalendars) {

        fillHashParentChildren(rootCalendars, derivedCalendars);

        return new SimpleTreeNode(root, asNodes(rootCalendars));
    }

    private static List<SimpleTreeNode> asNodes(List<BaseCalendar> baseCalendars) {
        if (baseCalendars == null) {
            return new ArrayList<SimpleTreeNode>();
        }

        ArrayList<SimpleTreeNode> result = new ArrayList<SimpleTreeNode>();
        for (BaseCalendar baseCalendar : baseCalendars) {
            result.add(asNode(baseCalendar));
        }

        return result;
    }

    private static SimpleTreeNode asNode(BaseCalendar baseCalendar) {
        List<BaseCalendar> children = relationParentChildren.get(baseCalendar);
        return new SimpleTreeNode(baseCalendar, asNodes(children));
    }

    private static void fillHashParentChildren(
            List<BaseCalendar> rootCalendars,
            List<BaseCalendar> derivedCalendars) {
        for (BaseCalendar root : rootCalendars) {
            relationParentChildren.put(root, new ArrayList<BaseCalendar>());
        }

        for (BaseCalendar derived : derivedCalendars) {
            BaseCalendar parent = derived.getParent();
            List<BaseCalendar> siblings = relationParentChildren.get(parent);

            if (siblings == null) {
                siblings = new ArrayList<BaseCalendar>();
                siblings.add(derived);
                relationParentChildren.put(parent, siblings);
            } else {
                siblings.add(derived);
            }
        }
    }

    @Override
    public boolean isLeaf(Object node) {
        if (node == null) {
            return true;
        }

        SimpleTreeNode simpleTreeNode = (SimpleTreeNode) node;
        BaseCalendar baseCalendar = (BaseCalendar) simpleTreeNode.getData();

        List<BaseCalendar> children = relationParentChildren.get(baseCalendar);
        if (children == null) {
            return true;
        }

        return children.isEmpty();
    }

}

@@ -1299,140 +1299,8 @@
  %7B%0A%0A
-    private static Map%3CBaseCalendar, List%3CBaseCalendar%3E%3E relationParentChildren = new HashMap%3CBaseCalendar, List%3CBaseCalendar%3E%3E();%0A%0A
     
@@ -1683,39 +1683,125 @@
         
-fillHashParentChildren(
+Map%3CBaseCalendar, List%3CBaseCalendar%3E%3E parentChildren = createRelationParentChildren(%0A                        
 rootCale
@@ -1826,17 +1826,16 @@
 ndars);%0A
-%0A
         
@@ -1874,16 +1874,32 @@
 asNodes(
+parentChildren, 
 rootCale
@@ -1962,16 +1962,103 @@
 asNodes(
+%0A            Map%3CBaseCalendar, List%3CBaseCalendar%3E%3E relationParentChildren,%0A            
 List%3CBas
@@ -2345,24 +2345,48 @@
 .add(asNode(
+relationParentChildren, 
 baseCalendar
@@ -2471,16 +2471,103 @@
  asNode(
+%0A            Map%3CBaseCalendar, List%3CBaseCalendar%3E%3E relationParentChildren,%0A            
 BaseCale
@@ -2727,59 +2727,138 @@
 des(
-children));%0A    %7D%0A%0A    private static void fillHash
+relationParentChildren,%0A                children));%0A    %7D%0A%0A    private static Map%3CBaseCalendar, List%3CBaseCalendar%3E%3E createRelation
 Pare
@@ -2958,32 +2958,136 @@
 vedCalendars) %7B%0A
+        Map%3CBaseCalendar, List%3CBaseCalendar%3E%3E result = new HashMap%3CBaseCalendar, List%3CBaseCalendar%3E%3E();%0A
         for (Bas
@@ -3134,36 +3134,20 @@
       re
-lationParentChildren
+sult
 .put(roo
@@ -3347,36 +3347,20 @@
 ngs = re
-lationParentChildren
+sult
 .get(par
@@ -3517,36 +3517,20 @@
       re
-lationParentChildren
+sult
 .put(par
@@ -3637,452 +3637,25 @@
     
-%7D%0A%0A    @Override%0A    public boolean isLeaf(Object node) %7B%0A        if (node == null) %7B%0A            return true;%0A        %7D%0A%0A        SimpleTreeNode simpleTreeNode = (SimpleTreeNode) node;%0A        BaseCalendar baseCalendar = (BaseCalendar) simpleTreeNode.getData();%0A%0A        List%3CBaseCalendar%3E children = relationParentChildren.get(baseCalendar);%0A        if (children == null) %7B%0A            return true;%0A        %7D%0A%0A        return children.isEmpty()
+    return result
 ;%0A  

Remove the static variable so previous listings can't affect the current one