1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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.iterator.FilteringNodeIterator;
39 import info.magnolia.jcr.predicate.NodeTypePredicate;
40 import info.magnolia.jcr.util.NodeUtil;
41 import info.magnolia.jcr.util.PropertyUtil;
42 import info.magnolia.jcr.util.SessionUtil;
43 import info.magnolia.module.data.DataConsts;
44 import info.magnolia.rendering.model.RenderingModel;
45 import info.magnolia.rendering.model.RenderingModelImpl;
46 import info.magnolia.rendering.template.RenderableDefinition;
47 import info.magnolia.templating.functions.TemplatingFunctions;
48
49 import java.util.ArrayList;
50 import java.util.Collection;
51 import java.util.Date;
52 import java.util.List;
53
54 import javax.inject.Inject;
55 import javax.jcr.LoginException;
56 import javax.jcr.Node;
57 import javax.jcr.NodeIterator;
58 import javax.jcr.RepositoryException;
59 import javax.jcr.query.Query;
60 import javax.jcr.query.QueryManager;
61 import javax.jcr.query.QueryResult;
62
63 import org.apache.commons.lang.StringUtils;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67
68
69
70
71
72
73
74 public abstract class AbstractFeedModel<RD extends RenderableDefinition> extends RenderingModelImpl<RD> implements RenderingModel<RD> {
75 protected final static Logger log = LoggerFactory.getLogger(AbstractFeedModel.class);
76
77 public static final String ORDER_BY_PUBLICATION_DATE = "@pubDate";
78 public static final String ORDER_BY_TITLE_NAME = "@title";
79 public static final String SORT_ASCENDING = "ascending";
80 public static final String SORT_DESCENDING = "descending";
81
82 protected static final String AGGREGATOR_NODE = "/rssaggregator";
83 protected static final String DATA_WORKSPACE = "data";
84 protected static final String FEEDS_NODE = "feeds";
85
86 protected static final int MAX_RESULTS = 20;
87
88 protected final TemplatingFunctions templatingFunctions;
89
90 @Inject
91 public AbstractFeedModel(Node content, RD definition, RenderingModel<?> parent, TemplatingFunctions templatingFunctions) {
92 super(content, definition, parent);
93 this.templatingFunctions = templatingFunctions;
94 }
95
96
97
98
99
100 @SuppressWarnings("unused")
101 public Date convertPubDate(Object timestamp) {
102 if (timestamp == null) {
103 return null;
104 }
105 if (timestamp instanceof String) {
106 if (StringUtils.isEmpty((String) timestamp)) {
107 return null;
108 }
109 return new Date(Long.parseLong((String) timestamp));
110 }
111
112 return new Date((Long) timestamp);
113 }
114
115
116
117
118
119
120
121
122
123 public Collection<Node> getPlanetItems(String feedPath, String condition, String order, boolean limit) {
124 int maxResults = MAX_RESULTS;
125
126 List<Node> results = new ArrayList<Node>();
127 try {
128 if (limit && content.hasProperty("maxResults")) {
129 maxResults = (int) content.getProperty("maxResults").getLong();
130 }
131 String feedName = NodeUtil.getNodeByIdentifier(DATA_WORKSPACE, PropertyUtil.getString(content, "feed")).getName();
132
133 String sql = "select * from [dataItemNode] as t where ISDESCENDANTNODE([" + AGGREGATOR_NODE + "/" + feedName + "/" + feedPath + "])";
134 if (StringUtils.isNotBlank(condition)) {
135 sql += " " + condition;
136 }
137 if (StringUtils.isNotBlank(order)) {
138 sql += " " + order;
139 }
140 NodeIterator nit = QueryUtil.search("data", sql);
141
142 int resCount = 0;
143 while (nit.hasNext()) {
144 resCount++;
145 Node statNode = nit.nextNode();
146 if (limit) {
147 if (resCount <= maxResults) {
148 results.add(statNode);
149 } else {
150 break;
151 }
152
153 } else {
154 results.add(statNode);
155 }
156 }
157 return results;
158 } catch (RepositoryException e) {
159 log.error(e.getLocalizedMessage(), e);
160 }
161 return null;
162 }
163
164
165
166
167
168
169
170 @SuppressWarnings("unused")
171 public String getFeedTitle(String feedLink) {
172 try {
173 if (content.hasProperty("feed")) {
174 Node rssParent = SessionUtil.getNodeByIdentifier(DATA_WORKSPACE, content.getProperty("feed").getString());
175 return getFeedProperty(rssParent, FEEDS_NODE, "link", feedLink, "title");
176 }
177 } catch (RepositoryException e) {
178 log.error("Problem while fetching feed title for statistics: " + e.getMessage());
179 }
180 return null;
181 }
182
183
184
185
186
187
188
189
190
191
192 public String getFeedProperty(Node parentNode, String subNode, String searchProperty, String searchValue, String resultProperty) {
193 String propertyValue = null;
194 try {
195 if (parentNode != null) {
196 String searchNode = AGGREGATOR_NODE + "/" + parentNode.getName() + "/" + subNode;
197 String sql = "select * from [nt:base] as t where ISDESCENDANTNODE([" + searchNode + "]) "
198 + "and t." + searchProperty + "='" + searchValue + "'";
199
200 NodeIterator nit = QueryUtil.search(DATA_WORKSPACE, sql);
201
202 if (nit != null && nit.hasNext()) {
203 Node fsn = nit.nextNode();
204
205 if (NodeUtil.getCollectionFromNodeIterator(nit).size() == 0) {
206 if (fsn.hasProperty(resultProperty)) {
207 propertyValue = fsn.getProperty(resultProperty).getString();
208 }
209 }
210 }
211 }
212 } catch (RepositoryException e) {
213 log.error("Problem while getting node property: " + e.getMessage());
214 }
215 return propertyValue;
216 }
217
218 public String getContextPath() {
219 return MgnlContext.getContextPath();
220 }
221
222 protected NodeIterator runQuery(String queryString) throws LoginException, RepositoryException {
223
224 QueryManager qm = MgnlContext.getJCRSession("data").getWorkspace().getQueryManager();
225 log.debug(queryString);
226 Query q = qm.createQuery(queryString, "xpath");
227 QueryResult res = q.execute();
228 NodeIterator feeds = res.getNodes();
229 FilteringNodeIterator iterator = new FilteringNodeIterator(feeds, new NodeTypePredicate(DataConsts.MODULE_DATA_CONTENT_NODE_TYPE));
230 return iterator;
231 }
232 }