001/*
002 *  Copyright 2019 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.cms.data;
017
018import java.io.IOException;
019import java.util.Collection;
020import java.util.Locale;
021import java.util.Map;
022import java.util.Objects;
023import java.util.Optional;
024
025import javax.jcr.RepositoryException;
026import javax.jcr.Session;
027
028import org.xml.sax.ContentHandler;
029import org.xml.sax.SAXException;
030
031import org.ametys.cms.data.type.AbstractContentElementType;
032import org.ametys.cms.repository.ModifiableContent;
033import org.ametys.plugins.repository.AmetysObjectResolver;
034import org.ametys.plugins.repository.AmetysRepositoryException;
035import org.ametys.plugins.repository.UnknownAmetysObjectException;
036import org.ametys.plugins.repository.data.UnknownDataException;
037import org.ametys.plugins.repository.data.external.ExternalizableDataProvider.ExternalizableDataStatus;
038import org.ametys.plugins.repository.data.external.ExternalizableDataProviderExtensionPoint;
039import org.ametys.plugins.repository.data.holder.ModifiableModelAwareDataHolder;
040import org.ametys.plugins.repository.data.holder.group.impl.ModifiableModelAwareComposite;
041import org.ametys.plugins.repository.data.holder.group.impl.ModifiableModelAwareRepeater;
042import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData;
043import org.ametys.runtime.model.ModelItem;
044import org.ametys.runtime.model.ModelItemContainer;
045import org.ametys.runtime.model.ViewItemContainer;
046import org.ametys.runtime.model.exception.BadDataPathCardinalityException;
047import org.ametys.runtime.model.exception.BadItemTypeException;
048import org.ametys.runtime.model.exception.UndefinedItemPathException;
049
050/**
051 * Content wrapper used by attributes of type content
052 * @see AbstractContentElementType
053 */
054public class ContentValue implements ModifiableModelAwareDataHolder
055{
056    private AmetysObjectResolver _resolver;
057    private String _contentId;
058    private ModifiableContent _content;
059    private Session _session;
060
061    /**
062     * Constructor of the content wrapper
063     * @param resolver resolver used to get the content from its identifier
064     * @param contentId content identifier
065     */
066    public ContentValue(AmetysObjectResolver resolver, String contentId)
067    {
068        this(resolver, contentId, null);
069    }
070
071    /**
072     * Constructor of the content wrapper
073     * @param resolver resolver used to get the content from its identifier
074     * @param contentId content identifier
075     * @param session the current session. If <code>null</code>, a new session will be used to retrieve the content 
076     */
077    public ContentValue(AmetysObjectResolver resolver, String contentId, Session session)
078    {
079        _resolver = resolver;
080        _contentId = contentId;
081        _session = session;
082    }
083    
084    /**
085     * Retrieves the content's identifier
086     * @return the content's identifier
087     */
088    public String getContentId()
089    {
090        return _contentId;
091    }
092    
093    /**
094     * Retrieves the content
095     * @return the content
096     * @throws AmetysRepositoryException if an error occurs.
097     * @throws UnknownAmetysObjectException if no content exists for the identifier
098     */
099    public ModifiableContent getContent() throws AmetysRepositoryException, UnknownAmetysObjectException
100    {
101        if (_content == null)
102        {
103            if (_session != null)
104            {
105                try
106                {
107                    _content = _resolver.resolveById(_contentId, _session);
108                }
109                catch (RepositoryException e)
110                {
111                    throw new AmetysRepositoryException("Unable to retrieve the content with the id '" + _contentId + "'.", e);
112                }
113            }
114            else
115            {
116                _content = _resolver.resolveById(_contentId);
117            }
118        }
119        
120        return _content; 
121    }
122    
123    /**
124     * Retrieves an {@link Optional} describing the content, or an empty {@link Optional} if the content does not exist 
125     * @return an {@link Optional} describing the content
126     */
127    public Optional<ModifiableContent> getContentIfExists()
128    {
129        try
130        {
131            return Optional.ofNullable(getContent());
132        }
133        catch (AmetysRepositoryException e)
134        {
135            return Optional.empty();
136        }
137    }
138    
139    @Override
140    public int hashCode()
141    {
142        return Objects.hash(_contentId);
143    }
144
145    @Override
146    public boolean equals(Object obj)
147    {
148        if (this == obj)
149        {
150            return true;
151        }
152        if (obj == null)
153        {
154            return false;
155        }
156        if (getClass() != obj.getClass())
157        {
158            return false;
159        }
160        ContentValue other = (ContentValue) obj;
161        return Objects.equals(_contentId, other._contentId);
162    }
163
164    public boolean hasValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
165    {
166        return getContent().hasValue(dataPath);
167    }
168    
169    public boolean hasLocalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
170    {
171        return getContent().hasLocalValue(dataPath);
172    }
173    
174    public boolean hasExternalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
175    {
176        return getContent().hasExternalValue(dataPath);
177    }
178
179    public Collection<String> getDataNames()
180    {
181        return getContent().getDataNames();
182    }
183
184    public <T> T getValue(String dataPath, boolean allowMultiValuedPathSegments) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
185    {
186        return getContent().getValue(dataPath, allowMultiValuedPathSegments);
187    }
188
189    public <T> T getValue(String dataPath, boolean useDefaultFromModel, T defaultValue) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
190    {
191        return getContent().getValue(dataPath, useDefaultFromModel, defaultValue);
192    }
193    
194    public <T> T getLocalValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
195    {
196        return getContent().getLocalValue(dataPath);
197    }
198    
199    public <T> T getExternalValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
200    {
201        return getContent().getExternalValue(dataPath);
202    }
203    
204    public ExternalizableDataStatus getStatus(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadDataPathCardinalityException
205    {
206        return getContent().getStatus(dataPath);
207    }
208    
209    public Collection< ? extends ModelItemContainer> getModel()
210    {
211        return getContent().getModel();
212    }
213
214    public ModelItem getDefinition(String path) throws IllegalArgumentException, UndefinedItemPathException
215    {
216        return getContent().getDefinition(path);
217    }
218    
219    public boolean hasDefinition(String path) throws IllegalArgumentException
220    {
221        return getContent().hasDefinition(path);
222    }
223
224    public ModifiableModelAwareComposite getComposite(String compositePath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
225    {
226        return getContent().getComposite(compositePath);
227    }
228    
229    public ModifiableModelAwareComposite getLocalComposite(String compositePath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
230    {
231        return getContent().getLocalComposite(compositePath);
232    }
233    
234    public ModifiableModelAwareComposite getExternalComposite(String compositePath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
235    {
236        return getContent().getExternalComposite(compositePath);
237    }
238
239    public ModifiableModelAwareRepeater getRepeater(String repeaterPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
240    {
241        return getContent().getRepeater(repeaterPath);
242    }
243    
244    public ModifiableModelAwareRepeater getLocalRepeater(String repeaterPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
245    {
246        return getContent().getLocalRepeater(repeaterPath);
247    }
248    
249    public ModifiableModelAwareRepeater getExternalRepeater(String repeaterPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
250    {
251        return getContent().getExternalRepeater(repeaterPath);
252    }
253
254    public void dataToSAX(ContentHandler contentHandler, String dataPath, Locale locale) throws SAXException, IOException
255    {
256        getContent().dataToSAX(contentHandler, dataPath, locale);
257    }
258    
259    public void dataToSAX(ContentHandler contentHandler, Locale locale) throws SAXException, IOException, BadItemTypeException
260    {
261        getContent().dataToSAX(contentHandler, locale);
262    }
263
264    public ModifiableModelAwareComposite getComposite(String compositePath, boolean createNew) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
265    {
266        return getContent().getComposite(compositePath, createNew);
267    }
268    
269    public ModifiableModelAwareComposite getLocalComposite(String compositePath, boolean createNew) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
270    {
271        return getContent().getLocalComposite(compositePath, createNew);
272    }
273    
274    public ModifiableModelAwareComposite getExternalComposite(String compositePath, boolean createNew) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
275    {
276        return getContent().getExternalComposite(compositePath, createNew);
277    }
278
279    public ModifiableModelAwareRepeater getRepeater(String repeaterPath, boolean createNew) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
280    {
281        return getContent().getRepeater(repeaterPath, createNew);
282    }
283    
284    public ModifiableModelAwareRepeater getLocalRepeater(String repeaterPath, boolean createNew) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
285    {
286        return getContent().getLocalRepeater(repeaterPath, createNew);
287    }
288    
289    public ModifiableModelAwareRepeater getExternalRepeater(String repeaterPath, boolean createNew) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
290    {
291        return getContent().getExternalRepeater(repeaterPath, createNew);
292    }
293    
294    public boolean synchronizeValues(Map<String, Object> values, ExternalizableDataProviderExtensionPoint externalizableDataProviderEP, boolean useDefaultFromModel) throws UndefinedItemPathException, BadItemTypeException, IOException
295    {
296        return getContent().synchronizeValues(values, externalizableDataProviderEP, useDefaultFromModel);
297    }
298    
299    public boolean synchronizeValues(ViewItemContainer viewItemContainer, Map<String, Object> values, ExternalizableDataProviderExtensionPoint externalizableDataProviderEP, boolean useDefaultFromModel) throws UndefinedItemPathException, BadItemTypeException, IOException
300    {
301        return getContent().synchronizeValues(viewItemContainer, values, externalizableDataProviderEP, useDefaultFromModel);
302    }
303
304    public void setValue(String dataPath, Object value) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
305    {
306        getContent().setValue(dataPath, value);
307    }
308    
309    public void setLocalValue(String dataPath, Object localValue) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
310    {
311        getContent().setLocalValue(dataPath, localValue);
312    }
313    
314    public void setExternalValue(String dataPath, Object externalValue) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
315    {
316        getContent().setExternalValue(dataPath, externalValue);
317    }
318    
319    public void setStatus(String dataPath, ExternalizableDataStatus status) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
320    {
321        getContent().setStatus(dataPath, status);
322    }
323
324    public void removeValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, UnknownDataException, BadDataPathCardinalityException
325    {
326        getContent().removeValue(dataPath);
327    }
328    
329    public void removeLocalValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, UnknownDataException, BadDataPathCardinalityException
330    {
331        getContent().removeLocalValue(dataPath);
332    }
333    
334    public void removeExternalValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, UnknownDataException, BadDataPathCardinalityException
335    {
336        getContent().removeExternalValue(dataPath);
337    }
338    
339    public ModifiableRepositoryData getRepositoryData()
340    {
341        return getContent().getRepositoryData();
342    }
343}