View Javadoc
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   * Draft methods that should be centralized in the activityService as soon as
25   * stabilized
26   */
27  public class ActivityUtils {
28  
29  	// private final static Log log = LogFactory.getLog(ActivityUtils.class);
30  	private final static NumberFormat nbFormat = DecimalFormat.getInstance();
31  
32  	/** Simply returns the poll name that is relevant for the given rate */
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  			// XPath
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  			// SQL2
63  			// String queryStr = "SELECT * FROM [" +
64  			// ActivitiesTypes.ACTIVITIES_POLL
65  			// + "] WHERE ISDESCENDANTNODE('" + pollable.getPath() + "')";
66  			// Query query = session.getWorkspace().getQueryManager()
67  			// .createQuery(queryStr, Query.JCR_SQL2);
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  			// XPath
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  			// // SQL2
86  			// String queryStr = "SELECT * FROM [" +
87  			// ActivitiesTypes.ACTIVITIES_RATE
88  			// + "] WHERE ISDESCENDANTNODE('" + pollable.getPath() + "')";
89  			// Query query = session.getWorkspace().getQueryManager()
90  			// .createQuery(queryStr, Query.JCR_SQL2);
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 			// Activity Date
132 			vote.setProperty(ActivitiesNames.ACTIVITIES_ACTIVITY_DATE, new GregorianCalendar());
133 
134 			// related to
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 				// TODO enhance retrieval of vote count
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 	// Prevents instantiation
192 	private ActivityUtils() {
193 	}
194 }