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        _outgoingReferences = references;
128    }
129    
130    // ------------------- Tags management -------------------- //
131    @Override
132    public void tag(String tag) throws AmetysRepositoryException
133    {
134        TaggableAmetysObjectHelper.tag(this, tag);
135    }
136    
137    @Override
138    public void untag(String tag) throws AmetysRepositoryException
139    {
140        TaggableAmetysObjectHelper.untag(this, tag);
141    }
142    
143    // ------------------- Workflow management -------------------- //
144    @Override
145    public long getWorkflowId() throws AmetysRepositoryException
146    {
147        return WorkflowAwareContentHelper.getWorkflowId(this);
148    }
149    
150    @Override
151    public void setWorkflowId(long workflowId) throws AmetysRepositoryException
152    {
153        WorkflowAwareContentHelper.setWorkflowId(this, workflowId);
154    }
155    
156    @Override
157    public long getCurrentStepId() throws AmetysRepositoryException
158    {
159        return WorkflowAwareContentHelper.getCurrentStepId(this);
160    }
161    
162    @Override
163    public void setCurrentStepId (long stepId) throws AmetysRepositoryException
164    {
165        WorkflowAwareContentHelper.setCurrentStepId(this, stepId);
166    }
167    
168    @Override
169    public ZonedDateTime getProposalDate() throws AmetysRepositoryException
170    {
171        return WorkflowAwareContentHelper.getProposalDate(this);
172    }
173    
174    @Override
175    public void setProposalDate(ZonedDateTime proposalDate) throws AmetysRepositoryException
176    {
177        WorkflowAwareContentHelper.setProposalDate(this, proposalDate);
178    }
179    
180    // --------------------- Lock management ----------------------- //
181    @Override
182    public void lock() throws AmetysRepositoryException
183    {
184        _getFactory().getLockComponent().lock(this);
185        
186        // the lock component immediately detached the lock token, so we have to check it again at next usage
187        _lockAlreadyChecked = false;
188    }
189    
190    @Override
191    public void unlock() throws AmetysRepositoryException
192    {
193        _getFactory().getLockComponent().unlock(this);
194        
195        // the lock component removed the lock token on unlock
196        _lockAlreadyChecked = true;
197    }
198    
199    @Override
200    public void setLockInfoOnCurrentContext() throws AmetysRepositoryException
201    {
202        if (!_lockAlreadyChecked)
203        {
204            _getFactory().getLockComponent().setLockTokenOnCurrentSession(this);
205            _lockAlreadyChecked = true;
206        }
207    }
208    
209    @Override
210    public boolean isLocked() throws AmetysRepositoryException
211    {
212        return _getFactory().getLockComponent().isLocked(this);
213    }
214    
215    @Override
216    public UserIdentity getLockOwner() throws AmetysRepositoryException
217    {
218        return _getFactory().getLockComponent().getLockOwner(this);
219    }
220    
221    // -------------------------- DUBLIN CORE ---------------------------- //
222    @Override
223    public void setDCTitle(String title) throws AmetysRepositoryException
224    {
225        DublinCoreHelper.setDCTitle(this, title);
226    }
227
228    @Override
229    public void setDCCreator(String creator) throws AmetysRepositoryException
230    {
231        DublinCoreHelper.setDCCreator(this, creator);
232    }
233
234    @Override
235    public void setDCSubject(String[] subject) throws AmetysRepositoryException
236    {
237        DublinCoreHelper.setDCSubject(this, subject);
238    }
239
240    @Override
241    public void setDCDescription(String description) throws AmetysRepositoryException
242    {
243        DublinCoreHelper.setDCDescription(this, description);
244    }
245
246    @Override
247    public void setDCPublisher(String publisher) throws AmetysRepositoryException
248    {
249        DublinCoreHelper.setDCPublisher(this, publisher);
250    }
251
252    @Override
253    public void setDCContributor(String contributor) throws AmetysRepositoryException
254    {
255        DublinCoreHelper.setDCContributor(this, contributor);
256    }
257
258    @Override
259    public void setDCDate(Date date) throws AmetysRepositoryException
260    {
261        DublinCoreHelper.setDCDate(this, date);
262    }
263
264    @Override
265    public void setDCType(String type) throws AmetysRepositoryException
266    {
267        DublinCoreHelper.setDCType(this, type);
268    }
269
270    @Override
271    public void setDCFormat(String format) throws AmetysRepositoryException
272    {
273        DublinCoreHelper.setDCFormat(this, format);
274    }
275
276    @Override
277    public void setDCIdentifier(String identifier) throws AmetysRepositoryException
278    {
279        DublinCoreHelper.setDCIdentifier(this, identifier);
280    }
281
282    @Override
283    public void setDCSource(String source) throws AmetysRepositoryException
284    {
285        DublinCoreHelper.setDCSource(this, source);
286    }
287
288    @Override
289    public void setDCLanguage(String language) throws AmetysRepositoryException
290    {
291        DublinCoreHelper.setDCLanguage(this, language);
292    }
293
294    @Override
295    public void setDCRelation(String relation) throws AmetysRepositoryException
296    {
297        DublinCoreHelper.setDCRelation(this, relation);
298    }
299    
300    @Override
301    public void setDCCoverage(String coverage) throws AmetysRepositoryException
302    {
303        DublinCoreHelper.setDCCoverage(this, coverage);
304    }
305    
306    @Override
307    public void setDCRights(String rights) throws AmetysRepositoryException
308    {
309        DublinCoreHelper.setDCRights(this, rights);
310    }
311    
312    // ---------------------------- COMMENTS ------------------------------ //
313    @Override
314    public Comment createComment()
315    {
316        return new Comment(_getFactory()._getModifiableContentHelper().getCommentsDataHolder(this, true));
317    }
318    
319    public Comment createComment(String commentId, ZonedDateTime creationDate)
320    {
321        return new Comment(_getFactory()._getModifiableContentHelper().getCommentsDataHolder(this, true), commentId, creationDate);
322    }
323    
324    @Override
325    public Comment getComment(String commentId) throws AmetysRepositoryException
326    {
327        ModifiableModelLessDataHolder commentsDataHolder = _getFactory()._getModifiableContentHelper().getCommentsDataHolder(this, false);
328        return commentsDataHolder != null ? Comment.getComment(commentsDataHolder, commentId) : null;
329    }
330    
331    @Override
332    public List<Comment> getComments(boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException
333    {
334        ModifiableModelLessDataHolder commentsDataHolder = _getFactory()._getModifiableContentHelper().getCommentsDataHolder(this, false);
335        return commentsDataHolder != null ? Comment.getComments(commentsDataHolder, includeNotValidatedComments, includeValidatedComments) : List.of();
336    }
337    
338    // ---------------------------- CONTRIBUTOR COMMENTS ------------------------------ //
339    @Override
340    public Comment createContributorComment()
341    {
342        return new Comment(_getFactory()._getModifiableContentHelper().getContributorCommentsDataHolder(this, true));
343    }
344    
345    public Comment createContributorComment(String commentId, ZonedDateTime creationDate)
346    {
347        return new Comment(_getFactory()._getModifiableContentHelper().getContributorCommentsDataHolder(this, true), commentId, creationDate);
348    }
349    
350    @Override
351    public Comment getContributorComment(String commentId) throws AmetysRepositoryException
352    {
353        ModifiableModelLessDataHolder commentsDataHolder = _getFactory()._getModifiableContentHelper().getContributorCommentsDataHolder(this, false);
354        return commentsDataHolder != null ? Comment.getComment(commentsDataHolder, commentId) : null;
355    }
356    
357    @Override
358    public List<Comment> getContributorComments() throws AmetysRepositoryException
359    {
360        ModifiableModelLessDataHolder commentsDataHolder = _getFactory()._getModifiableContentHelper().getContributorCommentsDataHolder(this, false);
361        return commentsDataHolder != null ? Comment.getComments(commentsDataHolder, false, true) : List.of();
362    }
363    
364    // ---------------------------- DATA HOLDER --------------------------- //
365    @Override
366    public ModifiableContentDataHolder getDataHolder()
367    {
368        // It is necessary to instantiate the repository data because of locks:
369        // when the content is locked, the lock token is released to be taken by anyone
370        // in repository data there is a lock checked boolean that need to be reset in order to take the token
371        // this boolean is only reset at instantiation
372        Collection<ContentType> contentTypes = _getFactory().getContentHelper().getContentTypes(this);
373        return new ModifiableContentDataHolder(this, _getFactory().getContentDataHelper(), new JCRRepositoryData(getNode()), contentTypes);
374    }
375    
376    public void fillContent(org.w3c.dom.Node node, XMLValuesExtractorAdditionalDataGetter additionalDataGetter) throws Exception
377    {
378        _getFactory().getContentExtractor().fillContent(this, node, additionalDataGetter);
379    }
380}