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 GmbH & Co. KG, 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.xml.CmsXmlUtils;
032import org.opencms.xml.types.I_CmsXmlContentValue;
033import org.opencms.xml.types.I_CmsXmlSchemaType;
034
035import java.util.List;
036import java.util.Locale;
037
038/**
039 * Describes the sequence of XML content values of a specific type in an XML content instance.<p>
040 *
041 * @since 6.0.0
042 */
043public class CmsXmlContentValueSequence {
044
045    /** The XML content this sequence element is based on. */
046    private CmsXmlContent m_content;
047
048    /** Indicates if this is a choice sequence or not. */
049    private boolean m_isChoiceSequence;
050
051    /** The locale this sequence is based on. */
052    private Locale m_locale;
053
054    /** The maximum occurrences of the elements in this sequence. */
055    private int m_maxOccurs;
056
057    /** The minimum occurrences of the elements in this sequence. */
058    private int m_minOccurs;
059
060    /** The Xpath this content value sequence was generated for. */
061    private String m_path;
062
063    /** The list of XML content values for the selected schema type and locale in the XML content. */
064    private List<I_CmsXmlContentValue> m_values;
065
066    /**
067     * Generates a new content sequence element from the given type, content and content definition.<p>
068     *
069     * @param path the path in the document to generate the value sequence for
070     * @param locale the locale to get the content values from
071     * @param content the XML content to generate the sequence element out of
072     */
073    public CmsXmlContentValueSequence(String path, Locale locale, CmsXmlContent content) {
074
075        m_locale = locale;
076        m_content = content;
077        m_path = CmsXmlUtils.removeXpathIndex(path);
078        I_CmsXmlSchemaType type = m_content.getContentDefinition().getSchemaType(m_path);
079        m_isChoiceSequence = type.isChoiceOption();
080        if (m_isChoiceSequence) {
081            m_values = m_content.getSubValues(CmsXmlUtils.removeLastXpathElement(m_path), m_locale);
082        } else {
083            m_values = m_content.getValues(path, m_locale);
084        }
085        if (type.getContentDefinition().getChoiceMaxOccurs() > 1) {
086            m_minOccurs = 0;
087            m_maxOccurs = type.getContentDefinition().getChoiceMaxOccurs();
088        } else {
089            if (m_isChoiceSequence && !m_values.isEmpty()) {
090                type = m_values.get(0);
091            }
092            m_minOccurs = type.getMinOccurs();
093            m_maxOccurs = type.getMaxOccurs();
094        }
095    }
096
097    /**
098     * Adds a value element of the given type
099     * at the selected index to the XML content document.<p>
100     *
101     * @param cms the current users OpenCms context
102     * @param type the type to add
103     * @param index the index where to add the new value element
104     *
105     * @return the added XML content value element
106     *
107     * @see CmsXmlContent#addValue(CmsObject, String, Locale, int)
108     * @see #addValue(CmsObject, String, int)
109     * @see #addValue(CmsObject, int)
110     */
111    public I_CmsXmlContentValue addValue(CmsObject cms, I_CmsXmlSchemaType type, int index) {
112
113        String xpath = CmsXmlUtils.concatXpath(CmsXmlUtils.removeLastXpathElement(getPath()), type.getName());
114        return addValue(cms, xpath, index);
115    }
116
117    /**
118     * Adds a value element of the type the original xpath indicates
119     * at the selected index to the XML content document.<p>
120     *
121     * The "original xpath" is the path used in the constructor when creating
122     * this value sequence.<p>
123     *
124     * @param cms the current users OpenCms context
125     * @param index the index where to add the new value element
126     *
127     * @return the added XML content value element
128     *
129     * @see CmsXmlContent#addValue(CmsObject, String, Locale, int)
130     * @see #addValue(CmsObject, String, int)
131     * @see #addValue(CmsObject, I_CmsXmlSchemaType, int)
132     */
133    public I_CmsXmlContentValue addValue(CmsObject cms, int index) {
134
135        return addValue(cms, getPath(), index);
136    }
137
138    /**
139     * Adds a value element of the type indicated by the given xpath
140     * at the selected index to the XML content document.<p>
141     *
142     * @param cms the current users OpenCms context
143     * @param xpath the path that indicates the element type in the content definition
144     * @param index the index where to add the new value element
145     *
146     * @return the added XML content value element
147     *
148     * @see CmsXmlContent#addValue(CmsObject, String, Locale, int)
149     * @see #addValue(CmsObject, I_CmsXmlSchemaType, int)
150     * @see #addValue(CmsObject, int)
151     */
152    public I_CmsXmlContentValue addValue(CmsObject cms, String xpath, int index) {
153
154        I_CmsXmlContentValue newValue = m_content.addValue(cms, xpath, getLocale(), index);
155
156        // re-initialize the value list
157        m_values = m_content.getValues(getPath(), getLocale());
158
159        return newValue;
160    }
161
162    /**
163     * Returns the count of XML content values for the selected schema type and locale in the XML content.<p>
164     *
165     * @return the count of XML content values for the selected schema type and locale in the XML content
166     */
167    public int getElementCount() {
168
169        return m_values.size();
170    }
171
172    /**
173     * Returns the locale this sequence is based on.<p>
174     *
175     * @return the locale this sequence is based on
176     */
177    public Locale getLocale() {
178
179        return m_locale;
180    }
181
182    /**
183     * Returns the maximum occurrences of this type in the XML content schema.<p>
184     *
185     * @return the maximum occurrences of this type in the XML content schema
186     *
187     * @see I_CmsXmlSchemaType#getMaxOccurs()
188     */
189    public int getMaxOccurs() {
190
191        return m_maxOccurs;
192    }
193
194    /**
195     * Returns the minimum occurrences of this type in the XML content schema.<p>
196     *
197     * @return the minimum occurrences of this type in the XML content schema
198     *
199     * @see I_CmsXmlSchemaType#getMinOccurs()
200     */
201    public int getMinOccurs() {
202
203        return m_minOccurs;
204    }
205
206    /**
207     * Returns the (simplified) Xpath expression that identifies the root node
208     * of this content value sequence.<p>
209     *
210     * @return the (simplified) Xpath expression that identifies the root node
211     *      of this content value sequence
212     */
213    public String getPath() {
214
215        return m_path;
216    }
217
218    /**
219     * Returns the XML content values from the index position of this sequence.<p>
220     *
221     * @param index the index position to get the value from
222     *
223     * @return the XML content values from the index position of this sequence
224     */
225    public I_CmsXmlContentValue getValue(int index) {
226
227        return m_values.get(index);
228    }
229
230    /**
231     * Returns the list of XML content values for the selected schema type and locale in the XML content.<p>
232     *
233     * @return the list of XML content values for the selected schema type and locale in the XML content
234     *
235     * @see #getValue(int)
236     */
237    public List<I_CmsXmlContentValue> getValues() {
238
239        return m_values;
240    }
241
242    /**
243     * Returns <code>true</code> if this sequence represents a choice sequence.<p>
244     *
245     * @return <code>true</code> if this sequence represents a choice sequence
246     */
247    public boolean isChoiceSequence() {
248
249        return m_isChoiceSequence;
250    }
251
252    /**
253     * Removes the value element of the sequence type at the selected index from XML content document.<p>
254     *
255     * @param index the index where to remove the value element
256     *
257     * @see CmsXmlContent#removeValue(String, Locale, int)
258     */
259    public void removeValue(int index) {
260
261        m_content.removeValue(getPath(), getLocale(), index);
262
263        // re-initialize the value list
264        m_values = m_content.getValues(getPath(), getLocale());
265    }
266}