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.data.holder.ModifiableIndexableDataHolder; 030import org.ametys.cms.data.holder.impl.DefaultModifiableModelAwareDataHolder; 031import org.ametys.cms.repository.comment.Comment; 032import org.ametys.core.user.UserIdentity; 033import org.ametys.plugins.repository.AmetysRepositoryException; 034import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder; 035import org.ametys.plugins.repository.data.holder.group.ModifiableModelAwareRepeater; 036import org.ametys.plugins.repository.data.holder.group.ModifiableModelAwareRepeaterEntry; 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 /** Attribute Tags */ 086 public static final String ATTRIBUTE_TAGS = "tags"; 087 088 /** 089 * Default constructor for the JCRTask 090 * @param node The task node 091 * @param parentPath The parent path 092 * @param factory The factory 093 */ 094 public JCRTask(Node node, String parentPath, JCRTaskFactory factory) 095 { 096 super(node, parentPath, factory); 097 } 098 099 public String getTaskListId() 100 { 101 return getValue(ATTRIBUTE_TASKSLISTID); 102 } 103 104 public void setTasksListId(String taskListId) 105 { 106 setValue(ATTRIBUTE_TASKSLISTID, taskListId); 107 } 108 109 public Long getPosition() 110 { 111 return getValue(ATTRIBUTE_TASKSLISTPOSITION); 112 } 113 114 public void setPosition(Long position) 115 { 116 setValue(ATTRIBUTE_TASKSLISTPOSITION, position); 117 } 118 119 public String getLabel() 120 { 121 return getValue(ATTRIBUTE_LABEL); 122 } 123 124 public void setLabel(String label) 125 { 126 setValue(ATTRIBUTE_LABEL, label); 127 } 128 129 public String getDescription() 130 { 131 return getValue(ATTRIBUTE_DESCRIPTION); 132 } 133 134 public void setDescription(String description) 135 { 136 setValue(ATTRIBUTE_DESCRIPTION, description); 137 } 138 139 public LocalDate getStartDate() 140 { 141 return getValue(ATTRIBUTE_STARTDATE); 142 } 143 144 public void setStartDate(LocalDate startDate) 145 { 146 setValue(ATTRIBUTE_STARTDATE, startDate); 147 } 148 149 public LocalDate getDueDate() 150 { 151 return getValue(ATTRIBUTE_DUEDATE); 152 } 153 154 public void setDueDate(LocalDate dueDate) 155 { 156 setValue(ATTRIBUTE_DUEDATE, dueDate); 157 } 158 159 public boolean isClosed() 160 { 161 return getValue(ATTRIBUTE_ISCLOSED, false, false); 162 } 163 164 public void close(boolean isClosed) 165 { 166 setValue(ATTRIBUTE_ISCLOSED, isClosed); 167 } 168 169 public UserIdentity getCloseAuthor() 170 { 171 return getValue(ATTRIBUTE_CLOSEAUTHOR); 172 } 173 174 public void setCloseAuthor(UserIdentity author) 175 { 176 setValue(ATTRIBUTE_CLOSEAUTHOR, author); 177 } 178 179 public LocalDate getCloseDate() 180 { 181 return getValue(ATTRIBUTE_CLOSEDATE); 182 } 183 184 public void setCloseDate(LocalDate closedDate) 185 { 186 setValue(ATTRIBUTE_CLOSEDATE, closedDate); 187 } 188 189 public UserIdentity getAuthor() 190 { 191 return getValue(ATTRIBUTE_AUTHOR); 192 } 193 194 public void setAuthor(UserIdentity author) 195 { 196 setValue(ATTRIBUTE_AUTHOR, author); 197 } 198 199 public List<UserIdentity> getAssignments() 200 { 201 UserIdentity[] users = getValue(ATTRIBUTE_ASSIGNMENTS, false, new UserIdentity[0]); 202 return Arrays.asList(users); 203 } 204 205 public void setAssignments(List<UserIdentity> assignments) 206 { 207 setValue(ATTRIBUTE_ASSIGNMENTS, assignments.toArray(new UserIdentity[assignments.size()])); 208 } 209 210 public ZonedDateTime getCreationDate() 211 { 212 return getValue(ATTRIBUTE_CREATIONDATE); 213 } 214 215 public void setCreationDate(ZonedDateTime creationDate) 216 { 217 setValue(ATTRIBUTE_CREATIONDATE, creationDate); 218 } 219 220 public ZonedDateTime getLastModified() 221 { 222 return getValue(ATTRIBUTE_LASTMODIFIED); 223 } 224 225 public void setLastModified(ZonedDateTime lastModifiedDate) 226 { 227 setValue(ATTRIBUTE_LASTMODIFIED, lastModifiedDate); 228 } 229 230 public List<Binary> getAttachments() 231 { 232 Binary[] attachements = getValue(ATTRIBUTE_ATTACHMENTS, false, new Binary[0]); 233 return Arrays.asList(attachements); 234 } 235 236 public void setAttachments(List<Binary> attachments) 237 { 238 setValue(ATTRIBUTE_ATTACHMENTS, attachments.toArray(new Binary[attachments.size()])); 239 } 240 241 public void tag(String tag) throws AmetysRepositoryException 242 { 243 TaggableAmetysObjectHelper.tag(this, tag); 244 } 245 246 public void untag(String tag) throws AmetysRepositoryException 247 { 248 TaggableAmetysObjectHelper.untag(this, tag); 249 } 250 251 public Set<String> getTags() throws AmetysRepositoryException 252 { 253 return TaggableAmetysObjectHelper.getTags(this); 254 } 255 256 public List<CheckItem> getCheckList() 257 { 258 ModifiableModelAwareRepeater repeater = getRepeater(ATTRIBUTE_CHECKLIST, true); 259 return repeater.getEntries() 260 .stream() 261 .map(e -> new CheckItem(e.getValue(ATTRIBUTE_CHECKLIST_LABEL), e.getValue(ATTRIBUTE_CHECKLIST_ISCHECKED, false, false))) 262 .collect(Collectors.toList()); 263 } 264 265 public void setCheckListItem(List<CheckItem> checkItems) 266 { 267 ModifiableModelAwareRepeater repeater = getRepeater(ATTRIBUTE_CHECKLIST, true); 268 for (ModifiableModelAwareRepeaterEntry entry : repeater.getEntries()) 269 { 270 repeater.removeEntry(entry.getPosition()); 271 } 272 273 for (CheckItem checkItem : checkItems) 274 { 275 ModifiableModelAwareRepeaterEntry entry = repeater.addEntry(); 276 277 entry.setValue(ATTRIBUTE_CHECKLIST_LABEL, checkItem.getLabel()); 278 entry.setValue(ATTRIBUTE_CHECKLIST_ISCHECKED, checkItem.isChecked()); 279 } 280 } 281 282 private ModifiableModelLessDataHolder _getCommentsDataHolder() 283 { 284 try 285 { 286 Node baseNode = getBaseNode(); 287 if (!baseNode.hasNode("ametys:comments")) 288 { 289 baseNode.addNode("ametys:comments", "ametys:compositeMetadata"); 290 } 291 Node commentsNode = baseNode.getNode("ametys:comments"); 292 293 // FIXME WORKSPACES-1614: there is a double level of comments nodes 294 if (!commentsNode.hasNode("ametys:comments")) 295 { 296 commentsNode.addNode("ametys:comments", "ametys:compositeMetadata"); 297 } 298 Node secondLevelCommentsNode = commentsNode.getNode("ametys:comments"); 299 300 baseNode.getSession().save(); 301 302 ModifiableRepositoryData repositoryData = new JCRRepositoryData(secondLevelCommentsNode); 303 return new DefaultModifiableModelLessDataHolder(_getFactory().getUnversionedDataTypeExtensionPoint(), repositoryData); 304 } 305 catch (RepositoryException e) 306 { 307 throw new AmetysRepositoryException(e); 308 } 309 } 310 311 public Comment createComment() 312 { 313 314 return new Comment(_getCommentsDataHolder()); 315 } 316 317 public Comment createComment(String commentId, ZonedDateTime creationDate) 318 { 319 return new Comment(_getCommentsDataHolder(), commentId, creationDate); 320 } 321 322 public Comment getComment(String commentId) throws AmetysRepositoryException 323 { 324 return Comment.getComment(_getCommentsDataHolder(), commentId); 325 } 326 327 public List<Comment> getComments(boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException 328 { 329 return Comment.getComments(_getCommentsDataHolder(), includeNotValidatedComments, includeValidatedComments); 330 } 331 332 public ModifiableIndexableDataHolder getDataHolder() 333 { 334 ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode()); 335 return new DefaultModifiableModelAwareDataHolder(repositoryData, _getFactory().getTaskModel()); 336 } 337}