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.site;
029
030import org.opencms.configuration.I_CmsXmlConfiguration;
031import org.opencms.util.CmsPath;
032import org.opencms.util.CmsStringUtil;
033
034import java.io.Serializable;
035import java.util.Collections;
036import java.util.List;
037import java.util.stream.Collectors;
038
039import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
040import org.apache.commons.lang3.builder.ToStringStyle;
041
042import org.dom4j.Element;
043
044/**
045 * Describes a mapping rule that selects a different site root based on whether the requested path matches a set of prefixes or not.
046 *
047 * <p>The path prefixes must be non-trivial, they can't just be the empty string or '/' - these values will be ignored.
048 */
049public class CmsAlternativeSiteRootMapping implements Serializable {
050
051    /** Node name for the alternative site root mapping. */
052    public static final String N_ALTERNATIVE_SITE_ROOT_MAPPING = "alternative-site-root";
053
054    /** Node name for mapped paths. */
055    public static final String N_PATH = "path";
056
057    /** Suffix to append to the title of the site. */
058    public static final String A_TITLE_SUFFIX = "title-suffix";
059
060    /** Serial version id. */
061    private static final long serialVersionUID = 1L;
062
063    /** The list of prefixes which should map to the different site root. */
064    private List<CmsPath> m_prefixes;
065
066    /** The alternative site root. */
067    private CmsPath m_siteRoot;
068
069    /** Suffix to append to the site title. */
070    private String m_titleSuffix;
071
072    /**
073     * Creates a new instance.
074     *
075     * @param siteRoot the site root
076     * @param prefixes the prefixes
077     * @param titleSuffix the title suffix
078     */
079    public CmsAlternativeSiteRootMapping(String siteRoot, List<String> prefixes, String titleSuffix) {
080
081        super();
082        m_siteRoot = new CmsPath(siteRoot);
083        m_titleSuffix = titleSuffix != null ? titleSuffix : "";
084        // remove invalid prefixes, like empty string or '/'
085        m_prefixes = prefixes.stream().filter(prefix -> prefix != null).map(prefix -> prefix.trim()).filter(
086            prefix -> !prefix.equals("/") && !CmsStringUtil.isEmptyOrWhitespaceOnly(prefix)).map(CmsPath::new).collect(
087                Collectors.toList());
088        Collections.sort(m_prefixes);
089    }
090
091    /**
092     * Appends configuration data to the given parent element.
093     *
094     * @param parent the parent element
095     */
096    public void appendXml(Element parent) {
097
098        Element mapping = parent.addElement(N_ALTERNATIVE_SITE_ROOT_MAPPING);
099        mapping.addAttribute(I_CmsXmlConfiguration.A_URI, m_siteRoot.asString());
100        mapping.addAttribute(A_TITLE_SUFFIX, m_titleSuffix);
101        for (CmsPath path : getPrefixes()) {
102            mapping.addElement(N_PATH).addText(path.asString());
103        }
104    }
105
106    /**
107     * @see java.lang.Object#equals(java.lang.Object)
108     */
109    @Override
110    public boolean equals(Object obj) {
111
112        if (!(obj instanceof CmsAlternativeSiteRootMapping)) {
113            return false;
114        }
115        CmsAlternativeSiteRootMapping that = (CmsAlternativeSiteRootMapping)obj;
116        return that.getSiteRoot().equals(getSiteRoot())
117            && that.getPrefixes().equals(getPrefixes())
118            && that.getTitleSuffix().equals(getTitleSuffix());
119    }
120
121    /**
122     * Gets the path prefixes.
123     *
124     * @return the path prefixes
125     */
126    public List<CmsPath> getPrefixes() {
127
128        return Collections.unmodifiableList(m_prefixes);
129    }
130
131    /**
132     * Gets the site root as a CmsPath.
133     *
134     * @return the site root as a CmsPath
135     */
136    public CmsPath getSiteRoot() {
137
138        return m_siteRoot;
139    }
140
141    /**
142     * Gets the suffix to append to the site title.
143     *
144     * @return the suffix to append to the site title
145     */
146    public String getTitleSuffix() {
147
148        return m_titleSuffix;
149    }
150
151    /**
152     * @see java.lang.Object#hashCode()
153     */
154    @Override
155    public int hashCode() {
156
157        return ((((m_prefixes.hashCode()) * 31) + m_siteRoot.hashCode()) * 31) + m_titleSuffix.hashCode();
158    }
159
160    /**
161     * @see java.lang.Object#toString()
162     */
163    @Override
164    public String toString() {
165
166        return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
167
168    }
169
170}