001/*
002 *  Copyright 2020 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.plugins.workspaces.tasks.jcr;
017
018import java.time.LocalDate;
019import java.time.ZonedDateTime;
020import java.util.Arrays;
021import java.util.List;
022import java.util.Set;
023import java.util.stream.Collectors;
024
025import javax.jcr.Node;
026import javax.jcr.RepositoryException;
027
028import org.ametys.cms.data.Binary;
029import org.ametys.cms.repository.comment.Comment;
030import org.ametys.core.user.UserIdentity;
031import org.ametys.plugins.repository.AmetysRepositoryException;
032import org.ametys.plugins.repository.data.holder.ModifiableModelAwareDataHolder;
033import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder;
034import org.ametys.plugins.repository.data.holder.group.impl.ModifiableModelAwareRepeater;
035import org.ametys.plugins.repository.data.holder.group.impl.ModifiableModelAwareRepeaterEntry;
036import org.ametys.plugins.repository.data.holder.impl.DefaultModifiableModelAwareDataHolder;
037import org.ametys.plugins.repository.data.holder.impl.DefaultModifiableModelLessDataHolder;
038import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData;
039import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
040import org.ametys.plugins.repository.jcr.DefaultAmetysObject;
041import org.ametys.plugins.repository.tag.TaggableAmetysObjectHelper;
042import org.ametys.plugins.workspaces.tasks.Task;
043
044/**
045 * JCR implementation of a task
046 */
047public class JCRTask extends DefaultAmetysObject<JCRTaskFactory> implements Task
048{
049    /** Attribute Taskid */
050    public static final String ATTRIBUTE_TASK_ID = "id";
051    /** Attribute Taskid */
052    public static final String ATTRIBUTE_TASKSLISTID = "tasksListId";
053    /** Attribute Taskid */
054    public static final String ATTRIBUTE_TASKSLISTPOSITION = "tasksListPosition";
055    /** Attribute Label */
056    public static final String ATTRIBUTE_LABEL = "label";
057    /** Attribute Description */
058    public static final String ATTRIBUTE_DESCRIPTION = "description";
059    /** Attribute Startdate */
060    public static final String ATTRIBUTE_STARTDATE = "startDate";
061    /** Attribute DueDate */
062    public static final String ATTRIBUTE_DUEDATE = "dueDate";
063    /** Attribute IsClosed */
064    public static final String ATTRIBUTE_ISCLOSED = "isClosed";
065    /** Attribute CloseDate */
066    public static final String ATTRIBUTE_CLOSEDATE = "closeDate";
067    /** Attribute CloseAuthor */
068    public static final String ATTRIBUTE_CLOSEAUTHOR = "closeAuthor";
069    /** Attribute Author */
070    public static final String ATTRIBUTE_AUTHOR = "author";
071    /** Attribute Assignments */
072    public static final String ATTRIBUTE_ASSIGNMENTS = "assignments";
073    /** Attribute Creationdate */
074    public static final String ATTRIBUTE_CREATIONDATE = "creationDate";
075    /** Attribute Lastmodified */
076    public static final String ATTRIBUTE_LASTMODIFIED = "lastModified";
077    /** Attribute Attachments */
078    public static final String ATTRIBUTE_ATTACHMENTS = "attachments";
079    /** Attribute CheckList */
080    public static final String ATTRIBUTE_CHECKLIST = "checkList";
081    /** Attribute Label for checkList */
082    public static final String ATTRIBUTE_CHECKLIST_LABEL = "label";
083    /** Attribute IsChecked for checkList */
084    public static final String ATTRIBUTE_CHECKLIST_ISCHECKED = "isChecked";
085    
086    /**
087     * Default constructor for the JCRTask
088     * @param node The task node
089     * @param parentPath The parent path
090     * @param factory The factory
091     */
092    public JCRTask(Node node, String parentPath, JCRTaskFactory factory)
093    {
094        super(node, parentPath, factory);
095    }
096
097    public String getTaskListId()
098    {
099        return getValue(ATTRIBUTE_TASKSLISTID);
100    }
101    
102    public void setTasksListId(String taskListId)
103    {
104        setValue(ATTRIBUTE_TASKSLISTID, taskListId);
105    }
106    
107    public Long getPosition()
108    {
109        return getValue(ATTRIBUTE_TASKSLISTPOSITION);
110    }
111    
112    public void setPosition(Long position)
113    {
114        setValue(ATTRIBUTE_TASKSLISTPOSITION, position);
115    }
116
117    public String getLabel()
118    {
119        return getValue(ATTRIBUTE_LABEL);
120    }
121
122    public void setLabel(String label)
123    {
124        setValue(ATTRIBUTE_LABEL, label);
125    }
126    
127    public String getDescription()
128    {
129        return getValue(ATTRIBUTE_DESCRIPTION);
130    }
131
132    public void setDescription(String description)
133    {
134        setValue(ATTRIBUTE_DESCRIPTION, description);
135    }
136    
137    public LocalDate getStartDate()
138    {
139        return getValue(ATTRIBUTE_STARTDATE);
140    }
141    
142    public void setStartDate(LocalDate startDate)
143    {
144        setValue(ATTRIBUTE_STARTDATE, startDate);
145    }
146
147    public LocalDate getDueDate()
148    {
149        return getValue(ATTRIBUTE_DUEDATE);
150    }
151
152    public void setDueDate(LocalDate dueDate)
153    {
154        setValue(ATTRIBUTE_DUEDATE, dueDate);
155    }
156    
157    public boolean isClosed()
158    {
159        return getValue(ATTRIBUTE_ISCLOSED, false, false);
160    }
161    
162    public void close(boolean isClosed)
163    {
164        setValue(ATTRIBUTE_ISCLOSED, isClosed);
165    }
166    
167    public UserIdentity getCloseAuthor()
168    {
169        return getValue(ATTRIBUTE_CLOSEAUTHOR);
170    }
171    
172    public void setCloseAuthor(UserIdentity author)
173    {
174        setValue(ATTRIBUTE_CLOSEAUTHOR, author);
175    }
176
177    public LocalDate getCloseDate()
178    {
179        return getValue(ATTRIBUTE_CLOSEDATE);
180    }
181    
182    public void setCloseDate(LocalDate closedDate)
183    {
184        setValue(ATTRIBUTE_CLOSEDATE, closedDate);
185    }
186    
187    public UserIdentity getAuthor()
188    {
189        return getValue(ATTRIBUTE_AUTHOR);
190    }
191    
192    public void setAuthor(UserIdentity author)
193    {
194        setValue(ATTRIBUTE_AUTHOR, author);
195    }
196    
197    public List<UserIdentity> getAssignments()
198    {
199        UserIdentity[] users = getValue(ATTRIBUTE_ASSIGNMENTS, false, new UserIdentity[0]);
200        return Arrays.asList(users);
201    }
202    
203    public void setAssignments(List<UserIdentity> assignments)
204    {
205        setValue(ATTRIBUTE_ASSIGNMENTS, assignments.toArray(new UserIdentity[assignments.size()]));
206    }
207
208    public ZonedDateTime getCreationDate()
209    {
210        return getValue(ATTRIBUTE_CREATIONDATE);
211    }
212    
213    public void setCreationDate(ZonedDateTime creationDate)
214    {
215        setValue(ATTRIBUTE_CREATIONDATE, creationDate);
216    }
217    
218    public ZonedDateTime getLastModified()
219    {
220        return getValue(ATTRIBUTE_LASTMODIFIED);
221    }
222    
223    public void setLastModified(ZonedDateTime lastModifiedDate)
224    {
225        setValue(ATTRIBUTE_LASTMODIFIED, lastModifiedDate);
226    }
227    
228    public List<Binary> getAttachments()
229    {
230        Binary[] attachements = getValue(ATTRIBUTE_ATTACHMENTS, false, new Binary[0]);
231        return Arrays.asList(attachements);
232    }
233    
234    public void setAttachments(List<Binary> attachments)
235    {
236        setValue(ATTRIBUTE_ATTACHMENTS, attachments.toArray(new Binary[attachments.size()]));
237    }
238
239    public void tag(String tag) throws AmetysRepositoryException
240    {
241        TaggableAmetysObjectHelper.tag(this, tag);
242    }
243
244    public void untag(String tag) throws AmetysRepositoryException
245    {
246        TaggableAmetysObjectHelper.untag(this, tag);
247    }
248
249    public Set<String> getTags() throws AmetysRepositoryException
250    {
251        return TaggableAmetysObjectHelper.getTags(this);
252    }
253
254    public List<CheckItem> getCheckList()
255    {
256        ModifiableModelAwareRepeater repeater = getRepeater(ATTRIBUTE_CHECKLIST, true);
257        return repeater.getEntries()
258                    .stream()
259                    .map(e -> new CheckItem(e.getValue(ATTRIBUTE_CHECKLIST_LABEL), e.getValue(ATTRIBUTE_CHECKLIST_ISCHECKED, false, false)))
260                    .collect(Collectors.toList());
261    }
262
263    public void setCheckListItem(List<CheckItem> checkItems)
264    {
265        ModifiableModelAwareRepeater repeater = getRepeater(ATTRIBUTE_CHECKLIST, true);
266        for (ModifiableModelAwareRepeaterEntry entry : repeater.getEntries())
267        {
268            repeater.removeEntry(entry.getPosition());
269        }
270        
271        for (CheckItem checkItem : checkItems)
272        {
273            ModifiableModelAwareRepeaterEntry entry = repeater.addEntry();
274            
275            entry.setValue(ATTRIBUTE_CHECKLIST_LABEL, checkItem.getLabel());
276            entry.setValue(ATTRIBUTE_CHECKLIST_ISCHECKED, checkItem.isChecked());
277        }
278    }
279    
280    private ModifiableModelLessDataHolder _getCommentDataHolder()
281    {
282        try
283        {
284            Node baseNode = getBaseNode();
285            if (!baseNode.hasNode("ametys:comments"))
286            {
287                baseNode.addNode("ametys:comments", "ametys:compositeMetadata");
288            }
289            baseNode.getSession().save();
290            ModifiableRepositoryData repositoryData = new JCRRepositoryData(baseNode.getNode("ametys:comments"));
291            return new DefaultModifiableModelLessDataHolder(_getFactory().getUnversionedDataTypeExtensionPoint(), repositoryData);
292        }
293        catch (RepositoryException e)
294        {
295            throw new AmetysRepositoryException(e);
296        }
297    }
298    
299    public Comment createComment()
300    {
301        
302        return new Comment(_getCommentDataHolder());
303    }
304    
305    public Comment createComment(String commentId, ZonedDateTime creationDate)
306    {
307        return new Comment(_getCommentDataHolder(), commentId, creationDate);
308    }
309    
310    public Comment getComment(String commentId) throws AmetysRepositoryException
311    {
312        return Comment.getComment(_getCommentDataHolder(), commentId);
313    }
314    
315    public List<Comment> getComments(boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException
316    {
317        return Comment.getComments(_getCommentDataHolder(), includeNotValidatedComments, includeValidatedComments);
318    }
319
320    public ModifiableModelAwareDataHolder getDataHolder()
321    {
322        ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode());
323        return new DefaultModifiableModelAwareDataHolder(repositoryData, _getFactory().getTaskModel());
324    }
325}