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}