View Javadoc

1   /**
2    * This file Copyright (c) 2008-2013 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.rssaggregator.templates.components;
35  
36  import info.magnolia.cms.util.QueryUtil;
37  import info.magnolia.context.MgnlContext;
38  import info.magnolia.jcr.util.NodeUtil;
39  import info.magnolia.jcr.util.PropertyUtil;
40  import info.magnolia.jcr.util.SessionUtil;
41  import info.magnolia.rendering.model.RenderingModel;
42  import info.magnolia.rendering.model.RenderingModelImpl;
43  import info.magnolia.rendering.template.RenderableDefinition;
44  import info.magnolia.templating.functions.TemplatingFunctions;
45  
46  import java.util.ArrayList;
47  import java.util.Collection;
48  import java.util.Date;
49  import java.util.List;
50  
51  import javax.inject.Inject;
52  import javax.jcr.Node;
53  import javax.jcr.NodeIterator;
54  import javax.jcr.RepositoryException;
55  
56  import org.apache.commons.lang.StringUtils;
57  import org.slf4j.Logger;
58  import org.slf4j.LoggerFactory;
59  
60  
61  /**
62   * Base class for rendering models.
63   *
64   * @param <RD> Definition type.
65   * @author had
66   * @version $Id:$
67   */
68  public abstract class AbstractFeedModel<RD extends RenderableDefinition> extends RenderingModelImpl<RD> implements RenderingModel<RD> {
69      protected final static Logger log = LoggerFactory.getLogger(AbstractFeedModel.class);
70  
71      public static final String ORDER_BY_PUBLICATION_DATE = "@pubDate";
72      public static final String ORDER_BY_TITLE_NAME = "@title";
73      public static final String SORT_ASCENDING = "ascending";
74      public static final String SORT_DESCENDING = "descending";
75  
76      protected static final String AGGREGATOR_NODE = "/rssaggregator";
77      protected static final String DATA_WORKSPACE = "data";
78      protected static final String FEEDS_NODE = "feeds";
79  
80      protected static final int MAX_RESULTS = 20;
81  
82      protected final TemplatingFunctions templatingFunctions;
83  
84      @Inject
85      public AbstractFeedModel(Node content, RD definition, RenderingModel<?> parent, TemplatingFunctions templatingFunctions) {
86          super(content, definition, parent);
87          this.templatingFunctions = templatingFunctions;
88      }
89  
90      /**
91       * This can get sometimes confusing. Freemarker will not create date from the java long time stamp format so we need to convert it to date first.
92       * Depending on circumstances (whether coming from node or from node wrapper) the time stamp will be passed in as a String or as a Long object
93       */
94      @SuppressWarnings("unused")
95      public Date convertPubDate(Object timestamp) {
96          if (timestamp == null) {
97              return null;
98          }
99          if (timestamp instanceof String) {
100             if (StringUtils.isEmpty((String) timestamp)) {
101                 return null;
102             }
103             return new Date(Long.parseLong((String) timestamp));
104         }
105 
106         return new Date((Long) timestamp);
107     }
108 
109     /**
110      * Select items from the data module for planet components.
111      *
112      * @param feedPath path where the items should be taken from
113      * @param condition query conditions
114      * @param order order of the resulting list
115      * @param limit if set to true, the resulting list will be shortend to the maximum number of entries allowed (if specified)
116      */
117     public Collection<Node> getPlanetItems(String feedPath, String condition, String order, boolean limit) {
118         int maxResults = MAX_RESULTS;
119 
120         List<Node> results = new ArrayList<Node>();
121         try {
122             if (limit && content.hasProperty("maxResults")) {
123                 maxResults = (int) content.getProperty("maxResults").getLong();
124             }
125             String feedName = NodeUtil.getNodeByIdentifier(DATA_WORKSPACE, PropertyUtil.getString(content, "feed")).getName();
126 
127             String sql = "select * from [dataItemNode] as t where ISDESCENDANTNODE([" + AGGREGATOR_NODE + "/" + feedName + "/" + feedPath + "])";
128             if (StringUtils.isNotBlank(condition)) {
129                 sql += " " + condition;
130             }
131             if (StringUtils.isNotBlank(order)) {
132                 sql += " " + order;
133             }
134             NodeIterator nit = QueryUtil.search("data", sql);
135 
136             int resCount = 0;
137             while (nit.hasNext()) {
138                 resCount++;
139                 Node statNode = nit.nextNode();
140                 if (limit) {
141                     if (resCount <= maxResults) {
142                         results.add(statNode);
143                     } else {
144                         break;
145                     }
146 
147                 } else {
148                     results.add(statNode);
149                 }
150             }
151             return results;
152         } catch (RepositoryException e) {
153             log.error(e.getLocalizedMessage(), e);
154         }
155         return null;
156     }
157 
158     /**
159      * Retrieve the title attribute of an individual feed subscription.
160      *
161      * @param feedLink Link to the feed.
162      * @return Assigned title of a feed if defined in the dialog or null.
163      */
164     @SuppressWarnings("unused")
165     public String getFeedTitle(String feedLink) {
166         try {
167             if (content.hasProperty("feed")) {
168                 Node rssParent = SessionUtil.getNodeByIdentifier(DATA_WORKSPACE, content.getProperty("feed").getString());
169                 return getFeedProperty(rssParent, FEEDS_NODE, "link", feedLink, "title");
170             }
171         } catch (RepositoryException e) {
172             log.error("Problem while fetching feed title for statistics: " + e.getMessage());
173         }
174         return null;
175     }
176 
177     /**
178      * Find a feed node and return a property.
179      *
180      * @param parentNode Planet feed node.
181      * @param subNode Node of the feed node where search should happen.
182      * @param searchProperty Node Property that should be searched.
183      * @param searchValue Search value.
184      * @param resultProperty Property value od found node to be returned or null.
185      */
186     public String getFeedProperty(Node parentNode, String subNode, String searchProperty, String searchValue, String resultProperty) {
187         String propertyValue = null;
188         try {
189             if (parentNode != null) {
190                 String searchNode = AGGREGATOR_NODE + "/" + parentNode.getName() + "/" + subNode;
191                 String sql = "select * from [nt:base] as t where ISDESCENDANTNODE([" + searchNode + "]) "
192                         + "and t." + searchProperty + "='" + searchValue + "'";
193 
194                 NodeIterator nit = QueryUtil.search(DATA_WORKSPACE, sql);
195 
196                 if (nit != null && nit.hasNext()) {
197                     Node fsn = nit.nextNode();
198                     // there shoul dbe only one node in the result list
199                     if (NodeUtil.getCollectionFromNodeIterator(nit).size() == 0) {
200                         if (fsn.hasProperty(resultProperty)) {
201                             propertyValue = fsn.getProperty(resultProperty).getString();
202                         }
203                     }
204                 }
205             }
206         } catch (RepositoryException e) {
207             log.error("Problem while getting node property: " + e.getMessage());
208         }
209         return propertyValue;
210     }
211 
212     public String getContextPath() {
213         return MgnlContext.getContextPath();
214     }
215 
216 }