001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (C) Alkacon Software (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.site.xmlsitemap;
029
030import org.opencms.util.CmsFileUtil;
031import org.opencms.util.CmsStringUtil;
032
033import java.util.ArrayList;
034import java.util.Collections;
035import java.util.HashSet;
036import java.util.Iterator;
037import java.util.List;
038import java.util.Set;
039import java.util.TreeSet;
040
041/**
042 * A helper class used for calculating which paths need to be included or excluded from the XML sitemap generation.<p>
043 */
044public class CmsPathIncludeExcludeSet {
045
046    /** The set of all paths of includes or excludes. */
047    private Set<String> m_allPaths = new TreeSet<String>();
048
049    /** The set of excluded paths. */
050    private Set<String> m_excludes = new HashSet<String>();
051
052    /** The set of included paths. */
053    private Set<String> m_includes = new HashSet<String>();
054
055    /**
056     * Adds an excluded path.<p>
057     *
058     * @param exclude the path to add
059     */
060    public void addExclude(String exclude) {
061
062        exclude = normalizePath(exclude);
063        m_excludes.add(exclude);
064        m_allPaths.add(exclude);
065    }
066
067    /**
068     * Adds an included path.<p>
069     *
070     * @param include the path to add
071     */
072    public void addInclude(String include) {
073
074        include = normalizePath(include);
075        m_includes.add(include);
076        m_allPaths.add(include);
077    }
078
079    /**
080     * Gets the root include paths, i.e. those include paths which don't have an ancestor path which is also an include path.<p>
081     *
082     * @return the list of root include paths
083     */
084    public Set<String> getIncludeRoots() {
085
086        List<String> pathList = new ArrayList<String>(m_includes);
087        Set<String> includeRoots = new HashSet<String>();
088        Collections.sort(pathList);
089        while (!pathList.isEmpty()) {
090            Iterator<String> iterator = pathList.iterator();
091            String firstPath = iterator.next();
092            includeRoots.add(firstPath);
093            iterator.remove();
094            while (iterator.hasNext()) {
095                String currentPath = iterator.next();
096                if (CmsStringUtil.isPrefixPath(firstPath, currentPath)) {
097                    iterator.remove();
098                }
099            }
100        }
101        return includeRoots;
102    }
103
104    /**
105     * Checks if the given path is excluded by the include/exclude configuration.<p>
106     *
107     * @param path the path to check
108     *
109     * @return true if the path is excluded
110     */
111    public boolean isExcluded(String path) {
112
113        path = normalizePath(path);
114        List<String> pathList = new ArrayList<String>(m_allPaths);
115        // m_allPaths is already sorted, we need the reverse ordering so children come before their parents
116        Collections.reverse(pathList);
117        for (String pathInList : pathList) {
118            if (CmsStringUtil.isPrefixPath(pathInList, path)) {
119                return m_excludes.contains(pathInList);
120            }
121        }
122        return false;
123    }
124
125    /**
126     * Converts a path to a normalized form.<p>
127     *
128     * @param path the path to normalize
129     *
130     * @return the normalized path
131     */
132    protected String normalizePath(String path) {
133
134        if (path.equals("/")) {
135            return path;
136        } else {
137            return CmsFileUtil.removeTrailingSeparator(path);
138        }
139
140    }
141}