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.generator;
35
36 import info.magnolia.cms.util.QueryUtil;
37 import info.magnolia.commands.MgnlCommand;
38 import info.magnolia.context.Context;
39 import info.magnolia.context.MgnlContext;
40 import info.magnolia.jcr.util.NodeUtil;
41 import info.magnolia.jcr.util.PropertyUtil;
42 import info.magnolia.module.data.DataConsts;
43 import info.magnolia.module.rssaggregator.RSSAggregator;
44 import info.magnolia.module.rssaggregator.util.PlanetUtil;
45
46 import java.util.ArrayList;
47 import java.util.Calendar;
48 import java.util.Date;
49 import java.util.List;
50
51 import javax.jcr.Node;
52 import javax.jcr.NodeIterator;
53 import javax.jcr.RepositoryException;
54 import javax.jcr.Session;
55
56 import org.apache.commons.collections.MapIterator;
57 import org.apache.commons.collections.keyvalue.MultiKey;
58 import org.apache.commons.collections.map.MultiKeyMap;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62
63
64
65
66
67 public class CollectStatisticsCommand extends MgnlCommand {
68
69 private static final Logger log = LoggerFactory.getLogger(CollectStatisticsCommand.class);
70
71 private static final String CONTENTTYPE_RSSAGGREGATOR = "RssAggregator";
72 private static final String FEED_DATA_NAME = "planetData";
73 private static final String STATISTICS_NODE = "statistics";
74 private static final String STATS_AUTHORS_NODE = "authors";
75 private Session session;
76
77 @Override
78 public boolean execute(Context context) throws Exception {
79 log.info("Starting command for creating Planet data statistics.");
80
81 session = MgnlContext.getSystemContext().getJCRSession("data");
82
83 traverseFeedEntries();
84
85 log.info("Finished generating Planet data statistics.");
86
87 return true;
88 }
89
90
91
92
93
94
95 protected Date getStatisticsStartDate() {
96 RSSAggregator module = RSSAggregator.getInstance();
97 int lastMonthsIncluded = module.getMonthsIncluded();
98
99 Calendar calendar = Calendar.getInstance();
100 calendar.setTime(new Date());
101 calendar.add(Calendar.MONTH, (lastMonthsIncluded) * -1);
102
103 return calendar.getTime();
104 }
105
106
107
108
109 private void traverseFeedEntries() throws RepositoryException {
110 Node rssParent = session.getNode("/rssaggregator");
111 Date startDate = getStatisticsStartDate();
112 log.info("Statistics will be build on content with date " + startDate + " or later.");
113
114 if (rssParent != null) {
115 NodeIterator feeds = rssParent.getNodes();
116 while (feeds.hasNext()) {
117 Node feedNode = feeds.nextNode();
118 if (NodeUtil.isNodeType(feedNode, CONTENTTYPE_RSSAGGREGATOR) && PlanetUtil.isPlanetNode(feedNode)) {
119 log.info("Creating statistics for planet feed: " + feedNode.getName());
120
121 MultiKeyMap entryMap = new MultiKeyMap();
122
123 String sql2 = "select * from [dataItemNode] as t where ISDESCENDANTNODE([" + feedNode.getPath() + "/"
124 + FEED_DATA_NAME + "]) and t.rssLink IS NOT NULL AND t.author IS NOT NULL ORDER BY t.author, t.rssLink";
125
126 NodeIterator entries = QueryUtil.search("data", sql2);
127 while (entries.hasNext()) {
128 Node entry = entries.nextNode();
129 createMapEntry(entryMap, entry);
130 }
131 createStatisticsNodes(entryMap, feedNode);
132 }
133 }
134 } else {
135 log.info("Could not find parent node for data/rssaggregator feed entries.");
136 }
137 }
138
139
140
141
142
143
144
145 @SuppressWarnings("unchecked")
146 protected void createMapEntry(MultiKeyMap mkm, Node blogEntry) {
147 List<Node> blogEntries = new ArrayList<Node>();
148
149 try {
150 String author = PlanetUtil.formatName(blogEntry, "author");
151 String rssLink = PropertyUtil.getString(blogEntry, "rssLink", "");
152
153 if (mkm.containsKey(author, rssLink)) {
154 blogEntries = (ArrayList<Node>) mkm.get(author, rssLink);
155 }
156
157 if (blogEntry.hasProperty("pubDate")) {
158 blogEntries.add(blogEntry);
159 mkm.put(author, rssLink, blogEntries);
160 }
161 } catch (Exception e) {
162 log.error("Could not add blog entry to statistics list: " + e.getMessage());
163 }
164 }
165
166
167
168
169
170
171
172 @SuppressWarnings("unchecked")
173 protected void createStatisticsNodes(MultiKeyMap statEntries, Node topNode) {
174 Date startDate = getStatisticsStartDate();
175 try {
176
177 if (topNode.hasNode(STATISTICS_NODE)) {
178 String absPath = topNode.getNode(STATISTICS_NODE).getPath();
179 topNode.getSession().removeItem(absPath);
180 }
181
182 Node authors = NodeUtil.createPath(topNode, STATISTICS_NODE + "/" + STATS_AUTHORS_NODE,
183 DataConsts.MODULE_DATA_CONTENT_NODE_TYPE, false);
184
185 int authorCount = 0;
186 MapIterator mit = statEntries.mapIterator();
187 while (mit.hasNext()) {
188 mit.next();
189
190 MultiKey mk = (MultiKey) mit.getKey();
191 String author = (String) mk.getKey(0);
192 String rssLink = (String) mk.getKey(1);
193
194 Node trgNode = PlanetUtil.findAuthorNode(authors, author, rssLink, authorCount);
195 PropertyUtil.setProperty(trgNode, "author", author);
196 PropertyUtil.setProperty(trgNode, "feedLink", rssLink);
197
198 Node countedPosts = NodeUtil.createPath(trgNode, "countedPosts", DataConsts.MODULE_DATA_CONTENT_NODE_TYPE, false);
199
200 List<Node> blogEntries = (ArrayList<Node>) mit.getValue();
201
202 long postCount = 0;
203 for (Node entry : blogEntries) {
204 PropertyUtil.setProperty(trgNode, "blogLink", PropertyUtil.getString(entry, "authorLink", ""));
205
206 Date pubDate = new Date(entry.getProperty("pubDate").getLong());
207 if (pubDate.after(startDate)) {
208 NodeUtil.createPath(countedPosts, entry.getIdentifier(), DataConsts.MODULE_DATA_CONTENT_NODE_TYPE, false);
209 postCount++;
210 }
211 }
212
213 PropertyUtil.setProperty(trgNode, "postCount", postCount);
214 authorCount++;
215
216 session.save();
217 }
218 } catch (Exception e) {
219 log.error("Problem while creating nodes for statistics: " + e.getMessage());
220 }
221 }
222
223 }