001/*
002 *  Copyright 2011 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.blog.posts;
017
018import java.io.IOException;
019import java.time.ZoneId;
020import java.time.ZonedDateTime;
021import java.util.HashMap;
022import java.util.Map;
023
024import javax.jcr.Node;
025import javax.jcr.NodeIterator;
026import javax.jcr.Repository;
027import javax.jcr.RepositoryException;
028import javax.jcr.Session;
029import javax.jcr.query.Query;
030
031import org.apache.avalon.framework.service.ServiceException;
032import org.apache.avalon.framework.service.ServiceManager;
033import org.apache.cocoon.ProcessingException;
034import org.apache.cocoon.environment.ObjectModelHelper;
035import org.apache.cocoon.environment.Request;
036import org.apache.cocoon.generation.ServiceableGenerator;
037import org.apache.cocoon.xml.AttributesImpl;
038import org.apache.cocoon.xml.XMLUtils;
039import org.xml.sax.SAXException;
040
041import org.ametys.cms.repository.Content;
042import org.ametys.cms.repository.comment.Comment;
043import org.ametys.core.util.DateUtils;
044import org.ametys.plugins.repository.AmetysObjectResolver;
045import org.ametys.plugins.repository.AmetysRepositoryException;
046import org.ametys.plugins.repository.RepositoryConstants;
047import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata;
048import org.ametys.plugins.repository.metadata.jcr.JCRCompositeMetadata;
049import org.ametys.plugins.repository.provider.AbstractRepository;
050import org.ametys.web.repository.content.jcr.DefaultWebContent;
051
052/**
053 * Generate the latest comments.
054 */
055public class CommentsGenerator extends ServiceableGenerator
056{
057    
058    /** RSS max number of comments. */
059    public static final int RSS_MAX_COMMENTS = 20;
060    
061    /** The ametys object resolver. */
062    protected AmetysObjectResolver _resolver;
063    
064    /** The repository. */
065    protected Repository _repository;
066    
067    @Override
068    public void service(ServiceManager serviceManager) throws ServiceException
069    {
070        super.service(serviceManager);
071        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
072        _repository = (Repository) serviceManager.lookup(AbstractRepository.ROLE);
073    }
074    
075    @Override
076    public void generate() throws IOException, SAXException, ProcessingException
077    {
078        Request request = ObjectModelHelper.getRequest(objectModel);
079        
080        String siteName = parameters.getParameter("siteName", (String) request.getAttribute("site"));
081        
082        Map<Comment, Content> comments = getComments(siteName, RSS_MAX_COMMENTS);
083        
084        AttributesImpl attrs = new AttributesImpl();
085        attrs.addCDATAAttribute("site", siteName);
086        attrs.addCDATAAttribute("now", DateUtils.getISODateTimeFormatter().format(ZonedDateTime.now()));
087        
088        contentHandler.startDocument();
089        XMLUtils.startElement(contentHandler, "comments", attrs);
090        
091        for (Comment comment : comments.keySet())
092        {
093            Content content = comments.get(comment);
094            
095            AttributesImpl cmtAttrs = new AttributesImpl();
096            
097            cmtAttrs.addCDATAAttribute("id", comment.getId());
098            cmtAttrs.addCDATAAttribute("date", DateUtils.getISODateTimeFormatter().format(comment.getCreationDate().toInstant().atZone(ZoneId.systemDefault())));
099            cmtAttrs.addCDATAAttribute("sortDate", Long.toString(comment.getCreationDate().getTime()));
100            cmtAttrs.addCDATAAttribute("authorName", comment.getAuthorName());
101            cmtAttrs.addCDATAAttribute("contentId", content.getId());
102            cmtAttrs.addCDATAAttribute("contentName", content.getName());
103            cmtAttrs.addCDATAAttribute("contentTitle", content.getTitle());
104            
105            XMLUtils.startElement(contentHandler, "comment", cmtAttrs);
106            XMLUtils.valueOf(contentHandler, comment.getContent());
107            XMLUtils.endElement(contentHandler, "comment");
108        }
109        
110        XMLUtils.endElement(contentHandler, "comments");
111        contentHandler.endDocument();
112    }
113    
114    /**
115     * Get a site's latest comments.
116     * @param siteName the site name.
117     * @param max the maximum number of comments.
118     * @return the comments.
119     */
120    @SuppressWarnings("deprecation")
121    protected Map<Comment, Content> getComments(String siteName, int max)
122    {
123        Map<Comment, Content> comments = new HashMap<>();
124        
125        // element(*, ametys:content)[(@ametys:site = 'siteName')]/ametys-internal:unversioned/@ametys:comments/element(*, ametys:compositeMetadata)
126        String jcrQuery = "//element(*, ametys:content)[@" + RepositoryConstants.NAMESPACE_PREFIX + ":" + DefaultWebContent.METADATA_SITE + " = '" + siteName + "']/"
127            + RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":unversioned/"
128            + RepositoryConstants.NAMESPACE_PREFIX + ":" + Comment.METADATA_COMMENTS
129            + "/element(*, ametys:compositeMetadata)[@ametys:validated = true()]"
130            + " order by @ametys:creation descending";
131        
132        Session session = null;
133        try
134        {
135            session = _repository.login();
136            
137            Query query = session.getWorkspace().getQueryManager().createQuery(jcrQuery, Query.XPATH);
138            
139            NodeIterator nodes = query.execute().getNodes();
140            int processed = 0;
141            while (nodes.hasNext() && processed < max)
142            {
143                Node commentNode = nodes.nextNode();
144                
145                Node unversionedNode = commentNode.getParent().getParent();
146                Node contentNode = unversionedNode.getParent();
147                
148                String nodeName = commentNode.getName();
149                String commentId = nodeName.substring(RepositoryConstants.NAMESPACE_PREFIX.length() + 1);
150                ModifiableCompositeMetadata unversionedMeta = new JCRCompositeMetadata(unversionedNode, _resolver);
151                
152                Comment comment = new Comment(unversionedMeta, commentId);
153                
154                Content content = _resolver.resolve(contentNode, false);
155                
156                comments.put(comment, content);
157                
158                processed++;
159            }
160        }
161        catch (RepositoryException ex)
162        {
163            if (session != null)
164            {
165                session.logout();
166            }
167
168            throw new AmetysRepositoryException("An error occurred executing the JCR query : " + jcrQuery, ex);
169        }
170        
171        return comments;
172//        return commentedContents;
173    }
174
175}