001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ui.apps;
029
030import org.opencms.ui.apps.CmsWorkplaceAppManager.ConfigurationComparator;
031
032import java.util.Collections;
033import java.util.Iterator;
034import java.util.List;
035
036import com.google.common.collect.Lists;
037
038/**
039 * Tree node representing an app category.<p>
040 *
041 * Contains a list of child nodes and a list of apps, which are the leaves of the tree.
042 * Note that the list of children is not initialized after construction, it has to be filled manually.
043 */
044public class CmsAppCategoryNode implements I_CmsHasOrder {
045
046    /** The category data. */
047    private I_CmsAppCategory m_data;
048
049    /** The child nodes. */
050    private List<CmsAppCategoryNode> m_children = Lists.newArrayList();
051
052    /** The app configurations in the category belonging to this node. */
053    private List<I_CmsWorkplaceAppConfiguration> m_appConfigurations = Lists.newArrayList();
054
055    /** Used to count the apps in the subtree starting with this node. */
056    private int m_appCount;
057
058    /**
059     * Creates a new category node for the given category.
060     *
061     * @param appCategory the category data
062     */
063    public CmsAppCategoryNode(I_CmsAppCategory appCategory) {
064
065        m_data = appCategory;
066    }
067
068    /**
069     * Creates a new root node.<p>
070     */
071    CmsAppCategoryNode() {
072
073        m_data = new CmsAppCategory(null, null, 0, 0);
074    }
075
076    /**
077     * Adds an app configuration.<p>
078     *
079     * @param appConfig the app configuration to add
080     */
081    public void addAppConfiguration(I_CmsWorkplaceAppConfiguration appConfig) {
082
083        m_appConfigurations.add(appConfig);
084    }
085
086    /**
087     * Adds a child node.<p>
088     *
089     * @param node the child node
090     */
091    public void addChild(CmsAppCategoryNode node) {
092
093        m_children.add(node);
094
095    }
096
097    /**
098     * Gets the app configurations for this category.<p>
099     *
100     * @return the app configurations
101     */
102    public List<I_CmsWorkplaceAppConfiguration> getAppConfigurations() {
103
104        return m_appConfigurations;
105    }
106
107    /**
108     * Gets the app category data for this node.<p>
109     *
110     * @return the app category data
111     */
112    public I_CmsAppCategory getCategory() {
113
114        return m_data;
115    }
116
117    /**
118     * Gets the child nodes of this node.<p>
119     *
120     * @return the child nodes
121     */
122    public List<CmsAppCategoryNode> getChildren() {
123
124        return m_children;
125    }
126
127    /**
128     * @see org.opencms.ui.apps.I_CmsHasOrder#getOrder()
129     */
130    public int getOrder() {
131
132        return getCategory().getOrder();
133    }
134
135    /**
136     * Recursively removes subtrees containing no app configurations.<p>
137     */
138    public void removeApplessSubtrees() {
139
140        internalRemoveApplessSubtrees(true);
141    }
142
143    /**
144     * Sorts the child nodes *and* the apps of this node by their order.<p>
145     */
146    public void sort() {
147
148        Collections.sort(m_appConfigurations, new ConfigurationComparator<I_CmsWorkplaceAppConfiguration>());
149        Collections.sort(m_children, new ConfigurationComparator<CmsAppCategoryNode>());
150    }
151
152    /**
153     * Recursively calls sort on all descendants of this node.<p>
154     */
155    public void sortRecursively() {
156
157        sort();
158        for (CmsAppCategoryNode child : m_children) {
159            child.sortRecursively();
160        }
161    }
162
163    /**
164     * Recursively computes the app count for each descendant of this tree node.<p>
165     */
166    private void computeAppCount() {
167
168        m_appCount = m_appConfigurations.size();
169        for (CmsAppCategoryNode child : m_children) {
170            child.computeAppCount();
171            m_appCount += child.m_appCount;
172        }
173    }
174
175    /**
176     * Internal helper method used to remove subtrees containing no app configurations.<p>
177     *
178     * @param isRoot should be true if this is a root node
179     */
180    private void internalRemoveApplessSubtrees(boolean isRoot) {
181
182        if (isRoot) {
183            computeAppCount();
184        }
185        Iterator<CmsAppCategoryNode> iter = m_children.iterator();
186        while (iter.hasNext()) {
187            CmsAppCategoryNode child = iter.next();
188            if (child.m_appCount == 0) {
189                iter.remove();
190            } else {
191                child.internalRemoveApplessSubtrees(false);
192            }
193        }
194    }
195
196}