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.DefaultIndexableAmetysObject; 030import org.ametys.cms.repository.comment.Comment; 031import org.ametys.core.user.UserIdentity; 032import org.ametys.plugins.repository.AmetysRepositoryException; 033import org.ametys.plugins.repository.data.holder.ModifiableDataHolder; 034import org.ametys.plugins.repository.data.holder.group.ModifiableRepeater; 035import org.ametys.plugins.repository.data.holder.group.ModifiableRepeaterEntry; 036import org.ametys.plugins.repository.data.holder.impl.DefaultModifiableDataHolder; 037import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData; 038import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData; 039import org.ametys.plugins.repository.tag.TaggableAmetysObjectHelper; 040import org.ametys.plugins.workspaces.tasks.Task; 041 042/** 043 * JCR implementation of a task 044 */ 045public class JCRTask extends DefaultIndexableAmetysObject<JCRTaskFactory> implements Task 046{ 047 /** Attribute Taskid */ 048 public static final String ATTRIBUTE_TASK_ID = "id"; 049 /** Attribute Taskid */ 050 public static final String ATTRIBUTE_TASKSLISTID = "tasksListId"; 051 /** Attribute Taskid */ 052 public static final String ATTRIBUTE_TASKSLISTPOSITION = "tasksListPosition"; 053 /** Attribute Label */ 054 public static final String ATTRIBUTE_LABEL = "label"; 055 /** Attribute Description */ 056 public static final String ATTRIBUTE_DESCRIPTION = "description"; 057 /** Attribute Startdate */ 058 public static final String ATTRIBUTE_STARTDATE = "startDate"; 059 /** Attribute DueDate */ 060 public static final String ATTRIBUTE_DUEDATE = "dueDate"; 061 /** Attribute IsClosed */ 062 public static final String ATTRIBUTE_ISCLOSED = "isClosed"; 063 /** Attribute CloseDate */ 064 public static final String ATTRIBUTE_CLOSEDATE = "closeDate"; 065 /** Attribute CloseAuthor */ 066 public static final String ATTRIBUTE_CLOSEAUTHOR = "closeAuthor"; 067 /** Attribute Author */ 068 public static final String ATTRIBUTE_AUTHOR = "author"; 069 /** Attribute Assignments */ 070 public static final String ATTRIBUTE_ASSIGNMENTS = "assignments"; 071 /** Attribute Creationdate */ 072 public static final String ATTRIBUTE_CREATIONDATE = "creationDate"; 073 /** Attribute Lastmodified */ 074 public static final String ATTRIBUTE_LASTMODIFIED = "lastModified"; 075 /** Attribute Attachments */ 076 public static final String ATTRIBUTE_ATTACHMENTS = "attachments"; 077 /** Attribute CheckList */ 078 public static final String ATTRIBUTE_CHECKLIST = "checkList"; 079 /** Attribute Label for checkList */ 080 public static final String ATTRIBUTE_CHECKLIST_LABEL = "label"; 081 /** Attribute IsChecked for checkList */ 082 public static final String ATTRIBUTE_CHECKLIST_ISCHECKED = "isChecked"; 083 /** Attribute Tags */ 084 public static final String ATTRIBUTE_TAGS = "tags"; 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 getValueOrDefault(ATTRIBUTE_ISCLOSED, 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 = getValueOrDefault(ATTRIBUTE_ASSIGNMENTS, 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 = getValueOrDefault(ATTRIBUTE_ATTACHMENTS, 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 ModifiableRepeater repeater = getRepeater(ATTRIBUTE_CHECKLIST, true); 257 return repeater.getEntries() 258 .stream() 259 .map(e -> new CheckItem(e.getValue(ATTRIBUTE_CHECKLIST_LABEL), e.getValueOrDefault(ATTRIBUTE_CHECKLIST_ISCHECKED, false))) 260 .collect(Collectors.toList()); 261 } 262 263 public void setCheckListItem(List<CheckItem> checkItems) 264 { 265 ModifiableRepeater repeater = getRepeater(ATTRIBUTE_CHECKLIST, true); 266 for (ModifiableRepeaterEntry entry : repeater.getEntries()) 267 { 268 repeater.removeEntry(entry.getPosition()); 269 } 270 271 for (CheckItem checkItem : checkItems) 272 { 273 ModifiableRepeaterEntry 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 ModifiableDataHolder _getCommentsDataHolder() 281 { 282 try 283 { 284 Node baseNode = getBaseNode(); 285 if (!baseNode.hasNode("ametys:comments")) 286 { 287 baseNode.addNode("ametys:comments", "ametys:compositeMetadata"); 288 } 289 Node commentsNode = baseNode.getNode("ametys:comments"); 290 291 // FIXME WORKSPACES-1614: there is a double level of comments nodes 292 if (!commentsNode.hasNode("ametys:comments")) 293 { 294 commentsNode.addNode("ametys:comments", "ametys:compositeMetadata"); 295 } 296 Node secondLevelCommentsNode = commentsNode.getNode("ametys:comments"); 297 298 baseNode.getSession().save(); 299 300 ModifiableRepositoryData repositoryData = new JCRRepositoryData(secondLevelCommentsNode); 301 return new DefaultModifiableDataHolder(_getFactory().getUnversionedDataTypeExtensionPoint(), repositoryData); 302 } 303 catch (RepositoryException e) 304 { 305 throw new AmetysRepositoryException(e); 306 } 307 } 308 309 public Comment createComment() 310 { 311 return new Comment(_getCommentsDataHolder()); 312 } 313 314 public Comment createComment(String commentId, ZonedDateTime creationDate) 315 { 316 return new Comment(_getCommentsDataHolder(), commentId, creationDate); 317 } 318 319 public Comment getComment(String commentId) throws AmetysRepositoryException 320 { 321 return Comment.getComment(_getCommentsDataHolder(), commentId); 322 } 323 324 public List<Comment> getComments(boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException 325 { 326 return Comment.getComments(_getCommentsDataHolder(), includeNotValidatedComments, includeValidatedComments); 327 } 328}