1 package org.argeo.activities.core;
2
3 import java.text.DecimalFormat;
4 import java.text.NumberFormat;
5 import java.util.GregorianCalendar;
6
7 import javax.jcr.Node;
8 import javax.jcr.NodeIterator;
9 import javax.jcr.RepositoryException;
10 import javax.jcr.Session;
11 import javax.jcr.nodetype.NodeType;
12 import javax.jcr.query.Query;
13
14 import org.argeo.activities.ActivitiesException;
15 import org.argeo.activities.ActivitiesNames;
16 import org.argeo.activities.ActivitiesTypes;
17 import org.argeo.connect.ConnectConstants;
18 import org.argeo.connect.util.ConnectJcrUtils;
19 import org.argeo.connect.util.XPathUtils;
20 import org.argeo.eclipse.ui.EclipseUiUtils;
21 import org.argeo.jcr.JcrUtils;
22
23
24
25
26
27 public class ActivityUtils {
28
29
30 private final static NumberFormat nbFormat = DecimalFormat.getInstance();
31
32
33 public static String getPollName(Node rate) {
34 try {
35 Node poll = null;
36 Node curr = rate;
37 while (poll == null)
38 if (curr.isNodeType(ActivitiesTypes.ACTIVITIES_POLL))
39 poll = curr;
40 else
41 curr = curr.getParent();
42 return ConnectJcrUtils.get(poll, ActivitiesNames.ACTIVITIES_POLL_NAME);
43 } catch (RepositoryException re) {
44 throw new ActivitiesException("Unable to get related " + "poll name for " + rate, re);
45 }
46 }
47
48 public static NodeIterator getPolls(Node pollable, boolean onlyOpenPolls) {
49 try {
50 Session session = pollable.getSession();
51
52 if (onlyOpenPolls)
53 throw new ActivitiesException("Unimplemented feature");
54
55
56 StringBuilder builder = new StringBuilder();
57 builder.append(XPathUtils.descendantFrom(pollable.getPath()));
58 builder.append("//element(*, ").append(ActivitiesTypes.ACTIVITIES_POLL).append(")");
59 Query query = session.getWorkspace().getQueryManager().createQuery(builder.toString(),
60 ConnectConstants.QUERY_XPATH);
61
62
63
64
65
66
67
68 return query.execute().getNodes();
69 } catch (RepositoryException re) {
70 throw new ActivitiesException("Unable to get polls for " + pollable, re);
71 }
72 }
73
74 public static NodeIterator getRates(Node pollable) {
75 try {
76 Session session = pollable.getSession();
77
78
79 StringBuilder builder = new StringBuilder();
80 builder.append(XPathUtils.descendantFrom(pollable.getPath()));
81 builder.append("//element(*, ").append(ActivitiesTypes.ACTIVITIES_RATE).append(")");
82 Query query = session.getWorkspace().getQueryManager().createQuery(builder.toString(),
83 ConnectConstants.QUERY_XPATH);
84
85
86
87
88
89
90
91 return query.execute().getNodes();
92 } catch (RepositoryException re) {
93 throw new ActivitiesException("Unable to get rates for " + pollable);
94 }
95 }
96
97 public static Node getMyVote(Node poll) {
98 try {
99 Node myVote = null;
100 if (poll.hasNode(ActivitiesNames.ACTIVITIES_RATES)) {
101 Node allRates = poll.getNode(ActivitiesNames.ACTIVITIES_RATES);
102 String userId = poll.getSession().getUserID();
103 if (allRates.hasNode(userId))
104 myVote = allRates.getNode(userId);
105 }
106 return myVote;
107 } catch (RepositoryException re) {
108 throw new ActivitiesException("Unable to get polls for " + poll);
109 }
110
111 }
112
113 public static Node createVote(Node poll) {
114 return createOneRating(poll, null, null);
115 }
116
117 public static Node createVote(Node poll, String userID) {
118 return createOneRating(poll, userID, null);
119 }
120
121 public static Node createOneRating(Node poll, String userID, Long rate) {
122 try {
123 Node parent = JcrUtils.mkdirs(poll, ActivitiesNames.ACTIVITIES_RATES, NodeType.NT_UNSTRUCTURED);
124
125 String nodeName = EclipseUiUtils.isEmpty(userID) ? poll.getSession().getUserID() : userID;
126
127 Node vote = parent.addNode(nodeName, ActivitiesTypes.ACTIVITIES_ACTIVITY);
128 vote.addMixin(ActivitiesTypes.ACTIVITIES_RATE);
129 vote.setProperty(ActivitiesNames.ACTIVITIES_REPORTED_BY, nodeName);
130
131
132 vote.setProperty(ActivitiesNames.ACTIVITIES_ACTIVITY_DATE, new GregorianCalendar());
133
134
135 ConnectJcrUtils.addRefToMultiValuedProp(vote, ActivitiesNames.ACTIVITIES_RELATED_TO, poll);
136
137 JcrUtils.updateLastModified(vote);
138
139 if (rate != null)
140 vote.setProperty(ActivitiesNames.ACTIVITIES_RATE, rate);
141 updateAvgRatingCache(poll);
142 return vote;
143 } catch (RepositoryException re) {
144 throw new ActivitiesException("Unable to create vote on " + poll, re);
145 }
146 }
147
148 public static void updateAvgRatingCache(Node poll) {
149 try {
150 double average = -1;
151 long nb = 0;
152 long total = 0;
153
154 if (poll.hasNode(ActivitiesNames.ACTIVITIES_RATES)) {
155 NodeIterator nit = poll.getNode(ActivitiesNames.ACTIVITIES_RATES).getNodes();
156 while (nit.hasNext()) {
157 Node node = nit.nextNode();
158 if (node.hasProperty(ActivitiesNames.ACTIVITIES_RATE)) {
159 total += node.getProperty(ActivitiesNames.ACTIVITIES_RATE).getLong();
160 nb++;
161 }
162 }
163 }
164 if (nb > 0)
165 average = (double) total / (double) nb;
166 poll.setProperty(ActivitiesNames.ACTIVITIES_CACHE_AVG_RATE, average);
167 } catch (RepositoryException e) {
168 throw new ActivitiesException("Unable to compute " + "average rating for " + poll, e);
169 }
170 }
171
172 public static String getAvgRating(Node poll) {
173 try {
174 Double avg = -1d;
175 if (poll.hasProperty(ActivitiesNames.ACTIVITIES_CACHE_AVG_RATE))
176 avg = poll.getProperty(ActivitiesNames.ACTIVITIES_CACHE_AVG_RATE).getDouble();
177
178 if (avg <= 0)
179 return "(none yet)";
180 else {
181
182 long nb = poll.getNode(ActivitiesNames.ACTIVITIES_RATES).getNodes().getSize();
183 String result = nbFormat.format(avg) + " (" + nb + (nb == 1 ? " vote)" : " votes)");
184 return result;
185 }
186 } catch (RepositoryException e) {
187 throw new ActivitiesException("unable to compute " + "average rating for " + poll, e);
188 }
189 }
190
191
192 private ActivityUtils() {
193 }
194 }