001/* 002 * Copyright 2010 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 */ 016 017package org.ametys.web.synchronization; 018 019import java.util.Map; 020 021import javax.jcr.ItemNotFoundException; 022import javax.jcr.Node; 023import javax.jcr.PathNotFoundException; 024import javax.jcr.RepositoryException; 025import javax.jcr.Session; 026 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.commons.collections.PredicateUtils; 030 031import org.ametys.cms.ObservationConstants; 032import org.ametys.cms.repository.Content; 033import org.ametys.cms.repository.ModifiableContentHelper; 034import org.ametys.cms.repository.comment.AbstractComment; 035import org.ametys.cms.repository.comment.Comment; 036import org.ametys.core.observation.Event; 037import org.ametys.plugins.repository.AmetysObjectResolver; 038import org.ametys.plugins.repository.RepositoryConstants; 039import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData; 040import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData; 041import org.ametys.plugins.repository.jcr.JCRAmetysObject; 042 043/** 044 * When a comment (validated) is modifier, synchronize it 045 */ 046public class SynchronizeContentCommentedObserver extends AbstractSynchronizeObserver 047{ 048 private static final String COMMENTS_DATA_PREFIX = RepositoryConstants.NAMESPACE_PREFIX + ":"; 049 050 /** Ametys object resolver. */ 051 protected AmetysObjectResolver _ametysObjectResolver; 052 053 @Override 054 public void service(ServiceManager manager) throws ServiceException 055 { 056 super.service(manager); 057 _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 058 } 059 060 @Override 061 public boolean supports(Event event) 062 { 063 return event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_VALIDATED) 064 || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_UNVALIDATED) 065 || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_DELETED) 066 || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_MODIFYING) 067 || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_REACTION_CHANGED); 068 } 069 070 @Override 071 protected void _internalObserve(Event event, Session liveSession) throws RepositoryException 072 { 073 if (event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_DELETED) || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_UNVALIDATED)) 074 { 075 _synchronizeDeletedContentComment(event, liveSession); 076 } 077 else 078 { 079 _synchronizeContentComment(event, liveSession); 080 } 081 082 if (liveSession.hasPendingChanges()) 083 { 084 liveSession.save(); 085 } 086 } 087 088 /** 089 * Synchronize deleted content comment 090 * @param event the event 091 * @param liveSession the live session 092 * @throws RepositoryException if an error occurred 093 */ 094 protected void _synchronizeDeletedContentComment(Event event, Session liveSession) throws RepositoryException 095 { 096 try 097 { 098 Map<String, Object> arguments = event.getArguments(); 099 Content content = (Content) arguments.get(ObservationConstants.ARGS_CONTENT); 100 Comment comment = (Comment) arguments.get(ObservationConstants.ARGS_COMMENT); 101 102 String commentId = comment != null ? comment.getId() : (String) arguments.get(ObservationConstants.ARGS_COMMENT_ID); 103 104 Node node = ((JCRAmetysObject) content).getNode(); 105 106 // let's check that content is in live 107 Node liveContentNode = liveSession.getNodeByIdentifier(node.getIdentifier()); 108 Node unversionnedMetadata = liveContentNode.getNode("ametys-internal:unversioned"); 109 Node commentNode = _getCommentNode(unversionnedMetadata, commentId); 110 111 commentNode.remove(); 112 } 113 catch (PathNotFoundException e) 114 { 115 // comment does not exist in the live, do nothing 116 } 117 } 118 119 /** 120 * Synchronize content comment 121 * @param event the event 122 * @param liveSession the live session 123 * @throws RepositoryException if an error occurred 124 */ 125 protected void _synchronizeContentComment(Event event, Session liveSession) throws RepositoryException 126 { 127 Map<String, Object> arguments = event.getArguments(); 128 Content content = (Content) arguments.get(ObservationConstants.ARGS_CONTENT); 129 Comment comment = (Comment) arguments.get(ObservationConstants.ARGS_COMMENT); 130 131 ModifiableRepositoryData repositoryData = comment.getRepositoryData(); 132 133 if (!(content instanceof JCRAmetysObject) || !(repositoryData instanceof JCRRepositoryData)) 134 { 135 return; 136 } 137 138 Node node = ((JCRAmetysObject) content).getNode(); 139 Node initialCommentNode = ((JCRRepositoryData) repositoryData).getNode(); 140 141 try 142 { 143 // let's check that content is in live 144 Node liveContentNode = liveSession.getNodeByIdentifier(node.getIdentifier()); 145 146 try 147 { 148 Node unversionedMetadata = liveContentNode.getNode("ametys-internal:unversioned"); 149 String commentId = comment.getId(); 150 Node commentNode = _getCommentNode(unversionedMetadata, commentId); 151 Node parent = commentNode.getParent(); 152 commentNode.remove(); 153 154 Node clonedNode = _synchronizeComponent.addNodeWithUUID(initialCommentNode, parent, initialCommentNode.getName()); 155 _synchronizeComponent.cloneNodeAndPreserveUUID(initialCommentNode, clonedNode, PredicateUtils.truePredicate(), PredicateUtils.truePredicate()); 156 } 157 catch (PathNotFoundException e) 158 { 159 // comment was not already existing 160 Node clonedParentNode = _synchronizeComponent.cloneAncestorsAndPreserveUUID(initialCommentNode, liveSession); 161 Node clonedNode = _synchronizeComponent.addNodeWithUUID(initialCommentNode, clonedParentNode, initialCommentNode.getName()); 162 _synchronizeComponent.cloneNodeAndPreserveUUID(initialCommentNode, clonedNode, PredicateUtils.truePredicate(), PredicateUtils.truePredicate()); 163 } 164 } 165 catch (ItemNotFoundException e) 166 { 167 // content does not exist in the live workspace 168 } 169 } 170 171 /** 172 * Get the node of the comment id 173 * @param unversionedMetadata the unversioned metadata 174 * @param commentId the comment id 175 * @return the node of the comment id 176 * @throws PathNotFoundException if an error occurred 177 * @throws RepositoryException if an error occurred 178 */ 179 protected Node _getCommentNode(Node unversionedMetadata, String commentId) throws PathNotFoundException, RepositoryException 180 { 181 Node commentsNode = unversionedMetadata.getNode(COMMENTS_DATA_PREFIX + ModifiableContentHelper.METADATA_COMMENTS); 182 183 String[] commentIdAsTab = commentId.split(AbstractComment.ID_SEPARATOR); 184 int i = 0; 185 int lastIndex = commentIdAsTab.length - 1; 186 while (i < lastIndex) 187 { 188 Node commentNode = commentsNode.getNode(COMMENTS_DATA_PREFIX + commentIdAsTab[i]); 189 commentsNode = commentNode.getNode(COMMENTS_DATA_PREFIX + AbstractComment.SUB_COMMENTS_DATA_NAME); 190 i++; 191 } 192 193 return commentsNode.getNode(COMMENTS_DATA_PREFIX + commentIdAsTab[lastIndex]); 194 } 195}