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