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.sitemap;
029
030import org.opencms.ade.sitemap.CmsVfsSitemapService;
031import org.opencms.ade.sitemap.shared.CmsClientSitemapEntry;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsResource;
034import org.opencms.file.CmsResourceFilter;
035import org.opencms.gwt.CmsRpcException;
036import org.opencms.main.CmsException;
037import org.opencms.main.CmsLog;
038import org.opencms.main.OpenCms;
039import org.opencms.ui.A_CmsUI;
040import org.opencms.util.CmsStringUtil;
041import org.opencms.util.CmsUUID;
042
043import java.util.Collections;
044import java.util.Comparator;
045import java.util.List;
046import java.util.Locale;
047import java.util.Set;
048
049import org.apache.commons.logging.Log;
050
051import com.google.common.collect.Lists;
052import com.google.common.collect.Sets;
053
054/**
055 * Loads node data for the sitemap tree.<p>
056 */
057public class CmsSitemapTreeDataProvider {
058
059    /** The logger instance for this class. */
060    private static final Log LOG = CmsLog.getLog(CmsSitemapTreeDataProvider.class);
061
062    /** The CMS context. */
063    private CmsObject m_cms;
064
065    /** Cached set of ids of folders without child folders, used for rendering the tree. */
066    private Set<CmsUUID> m_foldersWithNoChildFolders;
067
068    /** The locale context. */
069    private I_CmsLocaleCompareContext m_localeContext;
070
071    /** The resource at the root of the tree. */
072    private CmsResource m_root;
073
074    /**
075     * Creates a new instance.<p>
076     *
077     * @param cms the CMS context
078     * @param root the root resource of the tree
079     * @param context the locale context
080     */
081    public CmsSitemapTreeDataProvider(CmsObject cms, CmsResource root, I_CmsLocaleCompareContext context) {
082        m_root = root;
083        m_localeContext = context;
084        try {
085            m_cms = OpenCms.initCmsObject(cms);
086            List<CmsResource> folders = m_cms.readResources(
087                root,
088                CmsResourceFilter.IGNORE_EXPIRATION.addRequireFolder(),
089                true);
090            Collections.sort(folders, new Comparator<CmsResource>() {
091
092                public int compare(CmsResource arg0, CmsResource arg1) {
093
094                    return arg0.getRootPath().compareTo(arg1.getRootPath());
095                }
096            });
097            CmsResource lastFolder = null;
098            Set<CmsUUID> foldersWithNoChildFolders = Sets.newHashSet();
099
100            folders.add(null); // add null as a dummy value so that in the loop below, lastFolder takes all real folders as values
101            for (CmsResource folder : folders) {
102                if ((lastFolder != null)
103                    && ((folder == null)
104                        || !(CmsStringUtil.isPrefixPath(lastFolder.getRootPath(), folder.getRootPath())))) {
105                    foldersWithNoChildFolders.add(lastFolder.getStructureId());
106
107                }
108                lastFolder = folder;
109            }
110            m_foldersWithNoChildFolders = foldersWithNoChildFolders;
111        } catch (CmsException e) {
112            LOG.error(e.getLocalizedMessage(), e);
113        }
114    }
115
116    /**
117     * Gets the node data for children of a given node.<p>
118     *
119     * @param nodeData the node whose children to get
120     * @return the children
121     */
122    public List<CmsSitemapTreeNodeData> getChildren(CmsSitemapTreeNodeData nodeData) {
123
124        CmsClientSitemapEntry entry = nodeData.getClientEntry();
125
126        List<CmsSitemapTreeNodeData> result = Lists.newArrayList();
127
128        try {
129            CmsVfsSitemapService svc = getSitemapService();
130            CmsClientSitemapEntry ent = svc.getChildren(m_root.getRootPath(), entry.getId(), 1);
131            for (CmsClientSitemapEntry subEnt : ent.getSubEntries()) {
132                if (subEnt.isInNavigation()
133                    && ((subEnt.getDefaultFileId() != null) || subEnt.isNavigationLevelType())) {
134                    try {
135                        CmsUUID idToRead = subEnt.getId();
136                        if (subEnt.getDefaultFileId() != null) {
137                            idToRead = subEnt.getDefaultFileId();
138                        }
139                        Locale l1 = OpenCms.getLocaleManager().getDefaultLocale(
140                            svc.getCmsObject(),
141                            svc.getCmsObject().readResource(idToRead));
142                        Locale l2 = OpenCms.getLocaleManager().getDefaultLocale(
143                            svc.getCmsObject(),
144                            svc.getCmsObject().readResource(ent.getId(), CmsResourceFilter.IGNORE_EXPIRATION));
145                        if (!l1.equals(l2)) {
146                            continue;
147                        }
148                    } catch (Exception e) {
149                        LOG.error(e.getLocalizedMessage(), e);
150                    }
151
152                    CmsSitemapTreeNodeData data = new CmsSitemapTreeNodeData(
153                        m_localeContext.getRootLocale(),
154                        m_localeContext.getComparisonLocale());
155                    if (m_foldersWithNoChildFolders.contains(subEnt.getId())) {
156                        data.setHasNoChildren(true);
157                    }
158                    data.setClientEntry(subEnt);
159                    try {
160                        data.initialize(m_cms);
161                        result.add(data);
162                    } catch (Exception e) {
163                        LOG.error(e.getLocalizedMessage());
164                    }
165                }
166            }
167        } catch (CmsException e) {
168            LOG.error(e.getLocalizedMessage(), e);
169        } catch (CmsRpcException e) {
170            LOG.error(e.getLocalizedMessage(), e);
171
172        }
173        return result;
174    }
175
176    /**
177     * Gets the tree data for a resource.<p>
178     *
179     * @param resource a resource
180     * @return the data for the resource
181     */
182    public CmsSitemapTreeNodeData getData(CmsResource resource) {
183
184        try {
185            CmsVfsSitemapService svc = new CmsVfsSitemapService();
186            CmsObject cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject());
187            cms.getRequestContext().setSiteRoot("");
188            svc.setCms(cms);
189
190            CmsClientSitemapEntry ent = svc.getChildren(resource.getRootPath(), resource.getStructureId(), 0);
191            CmsSitemapTreeNodeData data = new CmsSitemapTreeNodeData(
192                m_localeContext.getRootLocale(),
193                m_localeContext.getComparisonLocale());
194            data.setClientEntry(ent);
195            data.initialize(cms);
196            return data;
197        } catch (Exception e) {
198            LOG.error(e.getLocalizedMessage(), e);
199            return null;
200        }
201
202    }
203
204    /**
205     * Gets the node data for the tree's root.<p>
206     *
207     * @return the node data
208     */
209    public CmsSitemapTreeNodeData getRoot() {
210
211        return getData(m_root);
212
213    }
214
215    /**
216     * Gets the sitemap service.<p>
217     *
218     * @return the sitemap service
219     *
220     * @throws CmsException if something goes wrong
221     */
222    public CmsVfsSitemapService getSitemapService() throws CmsException {
223
224        CmsVfsSitemapService svc = new CmsVfsSitemapService();
225        CmsObject cms = OpenCms.initCmsObject(m_cms);
226        cms.getRequestContext().setSiteRoot("");
227        svc.setCms(cms);
228        return svc;
229    }
230
231}