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