001/*
002 *  Copyright 2012 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.repository;
017
018import java.time.ZonedDateTime;
019import java.util.Collection;
020import java.util.Date;
021import java.util.List;
022import java.util.Locale;
023import java.util.Map;
024
025import javax.jcr.Node;
026
027import org.ametys.cms.content.references.OutgoingReferences;
028import org.ametys.cms.contenttype.ContentType;
029import org.ametys.cms.repository.comment.Comment;
030import org.ametys.cms.repository.comment.CommentableContent;
031import org.ametys.cms.repository.comment.contributor.ContributorCommentableContent;
032import org.ametys.core.user.UserIdentity;
033import org.ametys.plugins.repository.AmetysRepositoryException;
034import org.ametys.plugins.repository.data.extractor.xml.XMLValuesExtractorAdditionalDataGetter;
035import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder;
036import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
037import org.ametys.plugins.repository.jcr.DublinCoreHelper;
038import org.ametys.plugins.repository.lock.LockableAmetysObject;
039import org.ametys.plugins.repository.tag.TaggableAmetysObjectHelper;
040
041/**
042 * Default implementation of a {@link Content}, also versionable, lockable and workflow-aware.
043 * @param <F> the actual type of factory.
044 */
045public class ModifiableDefaultContent<F extends ModifiableContentFactory> extends DefaultContent<F> implements CommentableContent, ContributorCommentableContent, LockableAmetysObject, ModifiableWorkflowAwareContent/*, AnnotableContent*/ //, CopiableAmetysObject
046{
047    private boolean _lockAlreadyChecked;
048    
049    /**
050     * Creates a JCR-based Content.
051     * @param node the JCR Node backing this Content.
052     * @param parentPath the parent path in the Ametys hierarchy.
053     * @param factory the corresponding {@link ContentFactory}.
054     */
055    public ModifiableDefaultContent(Node node, String parentPath, F factory)
056    {
057        super(node, parentPath, factory);
058    }
059
060    public void setTitle(String title, Locale locale) throws AmetysRepositoryException
061    {
062        _getFactory()._getModifiableContentHelper().setTitle(this, title, locale);
063    }
064    
065    public void setTitle(String title) throws AmetysRepositoryException
066    {
067        _getFactory()._getModifiableContentHelper().setTitle(this, title);
068    }
069    
070    public void setCreator(UserIdentity user) throws AmetysRepositoryException
071    {
072        _getFactory()._getModifiableContentHelper().setCreator(this, user);
073    }
074    
075    public void setCreationDate(ZonedDateTime creationDate) throws AmetysRepositoryException
076    {
077        _getFactory()._getModifiableContentHelper().setCreationDate(this, creationDate);
078    }
079    
080    public void setLastContributor(UserIdentity user)
081    {
082        _getFactory()._getModifiableContentHelper().setLastContributor(this, user);
083    }
084    
085    public void setLastModified(ZonedDateTime lastModified) throws AmetysRepositoryException
086    {
087        _getFactory()._getModifiableContentHelper().setLastModified(this, lastModified);
088    }
089    
090    public void setFirstValidator(UserIdentity user) throws AmetysRepositoryException
091    {
092        _getFactory()._getModifiableContentHelper().setFirstValidator(this, user);
093    }
094    
095    @Override
096    public void setFirstValidationDate(ZonedDateTime validationDate) throws AmetysRepositoryException
097    {
098        _getFactory()._getModifiableContentHelper().setFirstValidationDate(this, validationDate);
099    }
100    
101    public void setLastValidator(UserIdentity user) throws AmetysRepositoryException
102    {
103        _getFactory()._getModifiableContentHelper().setLastValidator(this, user);
104    }
105    
106    @Override
107    public void setLastValidationDate(ZonedDateTime validationDate) throws AmetysRepositoryException
108    {
109        _getFactory()._getModifiableContentHelper().setLastValidationDate(this, validationDate);
110    }
111    
112    public void setLastMajorValidator(UserIdentity user) throws AmetysRepositoryException
113    {
114        _getFactory()._getModifiableContentHelper().setLastMajorValidator(this, user);
115    }
116    
117    @Override
118    public void setLastMajorValidationDate(ZonedDateTime validationDate) throws AmetysRepositoryException
119    {
120        _getFactory()._getModifiableContentHelper().setLastMajorValidationDate(this, validationDate);
121    }
122    
123    @Override
124    public void setOutgoingReferences(Map<String, OutgoingReferences> references) throws AmetysRepositoryException
125    {
126        _getFactory()._getModifiableContentHelper().setOutgoingReferences(this, references);
127    }
128    
129    // ------------------- Tags management -------------------- //
130    @Override
131    public void tag(String tag) throws AmetysRepositoryException
132    {
133        TaggableAmetysObjectHelper.tag(this, tag);
134    }
135    
136    @Override
137    public void untag(String tag) throws AmetysRepositoryException
138    {
139        TaggableAmetysObjectHelper.untag(this, tag);
140    }
141    
142    // ------------------- Workflow management -------------------- //
143    @Override
144    public long getWorkflowId() throws AmetysRepositoryException
145    {
146        return WorkflowAwareContentHelper.getWorkflowId(this);
147    }
148    
149    @Override
150    public void setWorkflowId(long workflowId) throws AmetysRepositoryException
151    {
152        WorkflowAwareContentHelper.setWorkflowId(this, workflowId);
153    }
154    
155    @Override
156    public long getCurrentStepId() throws AmetysRepositoryException
157    {
158        return WorkflowAwareContentHelper.getCurrentStepId(this);
159    }
160    
161    @Override
162    public void setCurrentStepId (long stepId) throws AmetysRepositoryException
163    {
164        WorkflowAwareContentHelper.setCurrentStepId(this, stepId);
165    }
166    
167    @Override
168    public ZonedDateTime getProposalDate() throws AmetysRepositoryException
169    {
170        return WorkflowAwareContentHelper.getProposalDate(this);
171    }
172    
173    @Override
174    public void setProposalDate(ZonedDateTime proposalDate) throws AmetysRepositoryException
175    {
176        WorkflowAwareContentHelper.setProposalDate(this, proposalDate);
177    }
178    
179    // --------------------- Lock management ----------------------- //
180    @Override
181    public void lock() throws AmetysRepositoryException
182    {
183        _getFactory().getLockComponent().lock(this);
184        
185        // the lock component immediately detached the lock token, so we have to check it again at next usage 
186        _lockAlreadyChecked = false;
187    }
188    
189    @Override
190    public void unlock() throws AmetysRepositoryException
191    {
192        _getFactory().getLockComponent().unlock(this);
193        
194        // the lock component removed the lock token on unlock
195        _lockAlreadyChecked = true;
196    }
197    
198    @Override
199    public void setLockInfoOnCurrentContext() throws AmetysRepositoryException
200    {
201        if (!_lockAlreadyChecked)
202        {
203            _getFactory().getLockComponent().setLockTokenOnCurrentSession(this);
204            _lockAlreadyChecked = true;
205        }
206    }
207    
208    @Override
209    public boolean isLocked() throws AmetysRepositoryException
210    {
211        return _getFactory().getLockComponent().isLocked(this);
212    }
213    
214    @Override
215    public UserIdentity getLockOwner() throws AmetysRepositoryException
216    {
217        return _getFactory().getLockComponent().getLockOwner(this);
218    }
219    
220    // -------------------------- DUBLIN CORE ---------------------------- //
221    @Override
222    public void setDCTitle(String title) throws AmetysRepositoryException
223    {
224        DublinCoreHelper.setDCTitle(this, title);
225    }
226
227    @Override
228    public void setDCCreator(String creator) throws AmetysRepositoryException
229    {
230        DublinCoreHelper.setDCCreator(this, creator);
231    }
232
233    @Override
234    public void setDCSubject(String[] subject) throws AmetysRepositoryException
235    {
236        DublinCoreHelper.setDCSubject(this, subject);
237    }
238
239    @Override
240    public void setDCDescription(String description) throws AmetysRepositoryException
241    {
242        DublinCoreHelper.setDCDescription(this, description);
243    }
244
245    @Override
246    public void setDCPublisher(String publisher) throws AmetysRepositoryException
247    {
248        DublinCoreHelper.setDCPublisher(this, publisher);
249    }
250
251    @Override
252    public void setDCContributor(String contributor) throws AmetysRepositoryException
253    {
254        DublinCoreHelper.setDCContributor(this, contributor);
255    }
256
257    @Override
258    public void setDCDate(Date date) throws AmetysRepositoryException
259    {
260        DublinCoreHelper.setDCDate(this, date);
261    }
262
263    @Override
264    public void setDCType(String type) throws AmetysRepositoryException
265    {
266        DublinCoreHelper.setDCType(this, type);
267    }
268
269    @Override
270    public void setDCFormat(String format) throws AmetysRepositoryException
271    {
272        DublinCoreHelper.setDCFormat(this, format);
273    }
274
275    @Override
276    public void setDCIdentifier(String identifier) throws AmetysRepositoryException
277    {
278        DublinCoreHelper.setDCIdentifier(this, identifier);
279    }
280
281    @Override
282    public void setDCSource(String source) throws AmetysRepositoryException
283    {
284        DublinCoreHelper.setDCSource(this, source);
285    }
286
287    @Override
288    public void setDCLanguage(String language) throws AmetysRepositoryException
289    {
290        DublinCoreHelper.setDCLanguage(this, language);
291    }
292
293    @Override
294    public void setDCRelation(String relation) throws AmetysRepositoryException
295    {
296        DublinCoreHelper.setDCRelation(this, relation);
297    }
298    
299    @Override
300    public void setDCCoverage(String coverage) throws AmetysRepositoryException
301    {
302        DublinCoreHelper.setDCCoverage(this, coverage);
303    }
304    
305    @Override
306    public void setDCRights(String rights) throws AmetysRepositoryException
307    {
308        DublinCoreHelper.setDCRights(this, rights);
309    }
310    
311    // ---------------------------- COMMENTS ------------------------------ //
312    @Override
313    public Comment createComment()
314    {
315        return new Comment(_getFactory()._getModifiableContentHelper().getCommentsDataHolder(this, true));
316    }
317    
318    public Comment createComment(String commentId, ZonedDateTime creationDate)
319    {
320        return new Comment(_getFactory()._getModifiableContentHelper().getCommentsDataHolder(this, true), commentId, creationDate);
321    }
322    
323    @Override
324    public Comment getComment(String commentId) throws AmetysRepositoryException
325    {
326        ModifiableModelLessDataHolder commentsDataHolder = _getFactory()._getModifiableContentHelper().getCommentsDataHolder(this, false);
327        return commentsDataHolder != null ? Comment.getComment(commentsDataHolder, commentId) : null;
328    }
329    
330    @Override
331    public List<Comment> getComments(boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException
332    {
333        ModifiableModelLessDataHolder commentsDataHolder = _getFactory()._getModifiableContentHelper().getCommentsDataHolder(this, false);
334        return commentsDataHolder != null ? Comment.getComments(commentsDataHolder, includeNotValidatedComments, includeValidatedComments) : List.of();
335    }
336    
337    // ---------------------------- CONTRIBUTOR COMMENTS ------------------------------ //
338    @Override
339    public Comment createContributorComment()
340    {
341        return new Comment(_getFactory()._getModifiableContentHelper().getContributorCommentsDataHolder(this, true));
342    }
343    
344    public Comment createContributorComment(String commentId, ZonedDateTime creationDate)
345    {
346        return new Comment(_getFactory()._getModifiableContentHelper().getContributorCommentsDataHolder(this, true), commentId, creationDate);
347    }
348    
349    @Override
350    public Comment getContributorComment(String commentId) throws AmetysRepositoryException
351    {
352        ModifiableModelLessDataHolder commentsDataHolder = _getFactory()._getModifiableContentHelper().getContributorCommentsDataHolder(this, false);
353        return commentsDataHolder != null ? Comment.getComment(commentsDataHolder, commentId) : null;
354    }
355    
356    @Override
357    public List<Comment> getContributorComments() throws AmetysRepositoryException
358    {
359        ModifiableModelLessDataHolder commentsDataHolder = _getFactory()._getModifiableContentHelper().getContributorCommentsDataHolder(this, false);
360        return commentsDataHolder != null ? Comment.getComments(commentsDataHolder, false, true) : List.of();
361    }
362    
363    // ---------------------------- DATA HOLDER --------------------------- //
364    @Override
365    public ModifiableContentDataHolder getDataHolder()
366    {
367        // It is necessary to instantiate the repository data because of locks:
368        // when the content is locked, the lock token is released to be taken by anyone
369        // in repository data there is a lock checked boolean that need to be reset in order to take the token
370        // this boolean is only reset at instantiation
371        Collection<ContentType> contentTypes = _getFactory().getContentHelper().getContentTypes(this);
372        return new ModifiableContentDataHolder(this, _getFactory().getContentDataHelper(), new JCRRepositoryData(getNode()), contentTypes);
373    }
374    
375    public void fillContent(org.w3c.dom.Node node, XMLValuesExtractorAdditionalDataGetter additionalDataGetter) throws Exception
376    {
377        _getFactory().getContentExtractor().fillContent(this, node, additionalDataGetter);
378    }
379}