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
083        m_root = root;
084        m_localeContext = context;
085        try {
086            m_cms = OpenCms.initCmsObject(cms);
087            List<CmsResource> folders = m_cms.readResources(
088                root,
089                CmsResourceFilter.IGNORE_EXPIRATION.addRequireFolder(),
090                true);
091            Collections.sort(folders, new Comparator<CmsResource>() {
092
093                public int compare(CmsResource arg0, CmsResource arg1) {
094
095                    return arg0.getRootPath().compareTo(arg1.getRootPath());
096                }
097            });
098            CmsResource lastFolder = null;
099            Set<CmsUUID> foldersWithNoChildFolders = Sets.newHashSet();
100
101            folders.add(null); // add null as a dummy value so that in the loop below, lastFolder takes all real folders as values
102            for (CmsResource folder : folders) {
103                if ((lastFolder != null)
104                    && ((folder == null)
105                        || !(CmsStringUtil.isPrefixPath(lastFolder.getRootPath(), folder.getRootPath())))) {
106                    foldersWithNoChildFolders.add(lastFolder.getStructureId());
107
108                }
109                lastFolder = folder;
110            }
111            m_foldersWithNoChildFolders = foldersWithNoChildFolders;
112        } catch (CmsException e) {
113            LOG.error(e.getLocalizedMessage(), e);
114        }
115    }
116
117    /**
118     * Gets the node data for children of a given node.<p>
119     *
120     * @param nodeData the node whose children to get
121     * @return the children
122     */
123    public List<CmsSitemapTreeNodeData> getChildren(CmsSitemapTreeNodeData nodeData) {
124
125        CmsClientSitemapEntry entry = nodeData.getClientEntry();
126
127        List<CmsSitemapTreeNodeData> result = Lists.newArrayList();
128
129        try {
130            CmsVfsSitemapService svc = getSitemapService();
131            CmsClientSitemapEntry ent = svc.getChildren(m_root.getRootPath(), entry.getId(), 1);
132            for (CmsClientSitemapEntry subEnt : ent.getSubEntries()) {
133                if (subEnt.isInNavigation()
134                    && ((subEnt.getDefaultFileId() != null) || subEnt.isNavigationLevelType())) {
135                    try {
136                        CmsUUID idToRead = subEnt.getId();
137                        if (subEnt.getDefaultFileId() != null) {
138                            idToRead = subEnt.getDefaultFileId();
139                        }
140                        Locale l1 = OpenCms.getLocaleManager().getDefaultLocale(
141                            svc.getCmsObject(),
142                            svc.getCmsObject().readResource(idToRead));
143                        Locale l2 = OpenCms.getLocaleManager().getDefaultLocale(
144                            svc.getCmsObject(),
145                            svc.getCmsObject().readResource(ent.getId(), CmsResourceFilter.IGNORE_EXPIRATION));
146                        if (!l1.equals(l2)) {
147                            continue;
148                        }
149                    } catch (Exception e) {
150                        LOG.error(e.getLocalizedMessage(), e);
151                    }
152
153                    CmsSitemapTreeNodeData data = new CmsSitemapTreeNodeData(
154                        m_localeContext.getRootLocale(),
155                        m_localeContext.getComparisonLocale());
156                    if (m_foldersWithNoChildFolders.contains(subEnt.getId())) {
157                        data.setHasNoChildren(true);
158                    }
159                    data.setClientEntry(subEnt);
160                    try {
161                        data.initialize(m_cms);
162                        result.add(data);
163                    } catch (Exception e) {
164                        LOG.error(e.getLocalizedMessage());
165                    }
166                }
167            }
168        } catch (CmsException e) {
169            LOG.error(e.getLocalizedMessage(), e);
170        } catch (CmsRpcException e) {
171            LOG.error(e.getLocalizedMessage(), e);
172
173        }
174        return result;
175    }
176
177    /**
178     * Gets the tree data for a resource.<p>
179     *
180     * @param resource a resource
181     * @return the data for the resource
182     */
183    public CmsSitemapTreeNodeData getData(CmsResource resource) {
184
185        try {
186            CmsVfsSitemapService svc = new CmsVfsSitemapService();
187            CmsObject cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject());
188            cms.getRequestContext().setSiteRoot("");
189            svc.setCms(cms);
190
191            CmsClientSitemapEntry ent = svc.getChildren(resource.getRootPath(), resource.getStructureId(), 0);
192            CmsSitemapTreeNodeData data = new CmsSitemapTreeNodeData(
193                m_localeContext.getRootLocale(),
194                m_localeContext.getComparisonLocale());
195            data.setClientEntry(ent);
196            data.initialize(cms);
197            return data;
198        } catch (Exception e) {
199            LOG.error(e.getLocalizedMessage(), e);
200            return null;
201        }
202
203    }
204
205    /**
206     * Gets the node data for the tree's root.<p>
207     *
208     * @return the node data
209     */
210    public CmsSitemapTreeNodeData getRoot() {
211
212        return getData(m_root);
213
214    }
215
216    /**
217     * Gets the sitemap service.<p>
218     *
219     * @return the sitemap service
220     *
221     * @throws CmsException if something goes wrong
222     */
223    public CmsVfsSitemapService getSitemapService() throws CmsException {
224
225        CmsVfsSitemapService svc = new CmsVfsSitemapService();
226        CmsObject cms = OpenCms.initCmsObject(m_cms);
227        cms.getRequestContext().setSiteRoot("");
228        svc.setCms(cms);
229        return svc;
230    }
231
232}