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.xml.content;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsProperty;
032import org.opencms.file.CmsPropertyDefinition;
033import org.opencms.file.CmsResource;
034import org.opencms.file.CmsResourceFilter;
035import org.opencms.loader.I_CmsFileNameGenerator;
036import org.opencms.main.CmsException;
037import org.opencms.main.CmsLog;
038import org.opencms.main.OpenCms;
039import org.opencms.util.CmsStringUtil;
040import org.opencms.util.CmsUUID;
041
042import java.util.Iterator;
043import java.util.List;
044import java.util.Locale;
045import java.util.Set;
046
047import org.apache.commons.logging.Log;
048
049import com.google.common.collect.Lists;
050import com.google.common.collect.Sets;
051
052/**
053 * A class which represents the context for resolving all content value mappings of an XML content.<p>
054 *
055 * Since the content handler instance is shared between all contents of the same XML content type, we can't use
056 * it to store data which is only relevant for resolving the mappings of a single XML content, so this class was created.
057 */
058public class CmsMappingResolutionContext {
059
060    /**
061     * Internal bean used to keep track of URL name mappings.<p>
062     */
063    class InternalUrlNameMappingEntry {
064
065        /** Locale of the mapping. */
066        private Locale m_locale;
067
068        /** URL name of the mapping. */
069        private String m_name;
070
071        /** Structure ID of the mapping. */
072        private CmsUUID m_structureId;
073
074        /**
075         * Creates a new instance.<p>
076         *
077         * @param structureId the structure id
078         * @param name the URL name
079         * @param locale the locale
080         */
081        public InternalUrlNameMappingEntry(CmsUUID structureId, String name, Locale locale) {
082
083            m_name = name;
084            m_structureId = structureId;
085            m_locale = locale;
086        }
087
088        /**
089         * Returns the locale.<p>
090         *
091         * @return the locale
092         */
093        public Locale getLocale() {
094
095            return m_locale;
096        }
097
098        /**
099         * Returns the name.<p>
100         *
101         * @return the name
102         */
103        public String getName() {
104
105            return m_name;
106        }
107
108        /**
109         * Returns the structureId.<p>
110         *
111         * @return the structureId
112         */
113        public CmsUUID getStructureId() {
114
115            return m_structureId;
116        }
117
118    }
119
120    /** The log instance for this class. */
121    private static final Log LOG = CmsLog.getLog(CmsMappingResolutionContext.class);
122
123    /** The CMS context to use. */
124    private CmsObject m_cms;
125
126    /** The list of URL name mappings. */
127    private List<InternalUrlNameMappingEntry> m_urlNameMappingEntries = Lists.newArrayList();
128
129    /**
130     * Creates a new instance.<p>
131     */
132    public CmsMappingResolutionContext() {
133
134        // empty
135    }
136
137    /**
138     * Writes all the stored URL name mappings to the database.<p>
139     *
140     * @throws CmsException if something goes wrong
141     */
142    public void commitUrlNameMappings() throws CmsException {
143
144        Set<CmsUUID> structureIds = Sets.newHashSet();
145        for (InternalUrlNameMappingEntry entry : m_urlNameMappingEntries) {
146            structureIds.add(entry.getStructureId());
147        }
148
149        boolean urlnameReplace = false;
150        for (CmsUUID structureId : structureIds) {
151            try {
152                CmsResource resource = m_cms.readResource(structureId, CmsResourceFilter.ALL);
153                CmsProperty prop = m_cms.readPropertyObject(
154                    resource,
155                    CmsPropertyDefinition.PROPERTY_URLNAME_REPLACE,
156                    true);
157                if (!CmsStringUtil.isEmptyOrWhitespaceOnly(prop.getValue())) {
158                    urlnameReplace = Boolean.parseBoolean(prop.getValue());
159                }
160            } catch (CmsException e) {
161                LOG.error("Error while trying to read urlname.replace: " + e.getLocalizedMessage(), e);
162            }
163
164        }
165
166        I_CmsFileNameGenerator nameGen = OpenCms.getResourceManager().getNameGenerator();
167        for (InternalUrlNameMappingEntry entry : m_urlNameMappingEntries) {
168            Iterator<String> nameSeq = nameGen.getUrlNameSequence(entry.getName());
169            m_cms.writeUrlNameMapping(nameSeq, entry.getStructureId(), entry.getLocale().toString(), urlnameReplace);
170        }
171
172    }
173
174    /**
175     * Finalizes the mappings.<p>
176     *
177     * @throws CmsException if something goes wrong
178     */
179    public void finalizeMappings() throws CmsException {
180
181        commitUrlNameMappings();
182    }
183
184    /**
185     * Sets the CMS context to use.<p>
186     *
187     * @param cms the CMS context
188     */
189    public void setCmsObject(CmsObject cms) {
190
191        m_cms = cms;
192    }
193
194    /**
195     * Adds an URL name mapping which should be written to the database later.<p>
196     *
197     * @param name the mapping name
198     * @param locale the locale
199     * @param structureId the structure ID
200     */
201    void addUrlNameMapping(String name, Locale locale, CmsUUID structureId) {
202
203        m_urlNameMappingEntries.add(new InternalUrlNameMappingEntry(structureId, name, locale));
204    }
205}