1 package com.atlassian.user.search.query;
2
3 /**
4 * This {@link EntityQueryParser} is not efficient, as it handles all queries by loading
5 * user and group {@link Entity} objects into memory.
6 */
7
8 import com.atlassian.user.*;
9 import com.atlassian.user.configuration.Configuration;
10 import com.atlassian.user.configuration.ConfigurationException;
11 import com.atlassian.user.configuration.util.InitializationCheck;
12 import com.atlassian.user.repository.RepositoryIdentifier;
13 import com.atlassian.user.search.DefaultSearchResult;
14 import com.atlassian.user.search.SearchResult;
15 import com.atlassian.user.search.query.match.*;
16 import com.atlassian.user.search.page.DefaultPager;
17 import com.atlassian.user.search.page.Pager;
18 import com.atlassian.user.search.page.PagerUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.log4j.Logger;
21
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Method;
24 import java.util.*;
25
26 public class DefaultEntityQueryParser extends AbstractEntityQueryParser implements EntityQueryParser
27 {
28 private static final Logger log = Logger.getLogger(DefaultEntityQueryParser.class);
29
30 protected UserManager userManager;
31 protected GroupManager groupManager;
32 protected RepositoryIdentifier repository;
33 protected Method entityNameMethod;
34 protected Method emailMethod;
35 protected Method fullnameMethod;
36 private static final Class userClass = User.class;
37
38 public DefaultEntityQueryParser(RepositoryIdentifier repo, UserManager userManager, GroupManager groupManager)
39 {
40 try
41 {
42 entityNameMethod = userClass.getMethod("getName", null);
43 emailMethod = userClass.getMethod("getEmail", null);
44 fullnameMethod = userClass.getMethod("getFullName", null);
45 }
46 catch (NoSuchMethodException e)
47 {
48 log.error(e.getMessage());
49 }
50
51 this.userManager = userManager;
52 this.groupManager = groupManager;
53 this.repository = repo;
54 }
55
56 public void init(HashMap args) throws ConfigurationException
57 {
58 this.userManager = (UserManager) args.get(Configuration.USERMANAGER);
59 this.groupManager = (GroupManager) args.get(Configuration.GROUPMANAGER);
60 this.repository = (RepositoryIdentifier) args.get(Configuration.REPOSITORY);
61
62 InitializationCheck.validateArgs(args, new String[]{Configuration.USERMANAGER,
63 Configuration.GROUPMANAGER,
64 Configuration.REPOSITORY}, this);
65
66 try
67 {
68 entityNameMethod = userClass.getMethod("getName", null);
69 emailMethod = userClass.getMethod("getEmail", null);
70 fullnameMethod = userClass.getMethod("getFullName", null);
71 }
72 catch (NoSuchMethodException e)
73 {
74 log.error(e.getMessage());
75 }
76 }
77
78 protected Pager parseQuery(Method userMethod, TermQuery q, Pager data)
79 throws IllegalAccessException, InvocationTargetException
80 {
81 String searchTerm = StringUtils.defaultString(q.getTerm()).toLowerCase();
82 if (searchTerm.indexOf(TermQuery.WILDCARD) >= 0)
83 return data;
84
85 Matcher matcher;
86 if (q.isMatchingSubstring())
87 {
88 if (q.getMatchingRule().equals(TermQuery.SUBSTRING_STARTS_WITH))
89 {
90 matcher = new StartsWithIgnoreCaseMatcher();
91 }
92 else if (q.getMatchingRule().equals(TermQuery.SUBSTRING_ENDS_WITH))
93 {
94 matcher = new EndsWithIgnoreCaseMatcher();
95 }
96 else
97 {
98 matcher = new ContainsIgnoreCaseMatcher();
99 }
100 }
101 else
102 {
103 matcher = new EqualsIgnoreCaseMatcher();
104 }
105
106 List matches = new ArrayList();
107 for (Iterator iterator = data.iterator(); iterator.hasNext();)
108 {
109 Entity entity = (Entity) iterator.next();
110 String userInfo = (String) userMethod.invoke(entity, null);
111
112 if (matcher.matches(userInfo, searchTerm))
113 matches.add(entity);
114 }
115 return new DefaultPager(matches);
116 }
117
118 public Pager find(Query query) throws EntityException
119 {
120 Pager result = null;
121
122 if (query instanceof TermQuery)
123 {
124 try
125 {
126 if (query instanceof UserNameTermQuery)
127 result = parseQuery(entityNameMethod, (TermQuery) query, userManager.getUsers());
128 else if (query instanceof GroupNameTermQuery)
129 result = parseQuery(entityNameMethod, (TermQuery) query, groupManager.getGroups());
130 else if (query instanceof EmailTermQuery)
131 result = parseQuery(emailMethod, (TermQuery) query, userManager.getUsers());
132 else if (query instanceof FullNameTermQuery)
133 result = parseQuery(fullnameMethod, (TermQuery) query, userManager.getUsers());
134 }
135 catch (IllegalAccessException e)
136 {
137 throw new EntityException(e);
138 }
139 catch (InvocationTargetException e)
140 {
141 throw new EntityException(e);
142 }
143 }
144 else if (query instanceof MembershipQuery)
145 {
146 result = parseMembershipQuery(query);
147 }
148 else if (query instanceof BooleanQuery)
149 {
150 BooleanQuery bQuery = (BooleanQuery) query;
151 result = evaluateBoolean(bQuery);
152 }
153
154 return result;
155 }
156
157 private Pager parseMembershipQuery(Query query) throws EntityException
158 {
159 Pager result = null;
160
161 if (query instanceof UsersInGroupTwoTermQuery)
162 {
163 result = parseUsersInGroupTwoTermQuery((UsersInGroupTwoTermQuery) query);
164 }
165 else if (query instanceof GroupsOfUserTwoTermQuery)
166 {
167 result = parseGroupsOfUserTwoTermQuery((GroupsOfUserTwoTermQuery) query);
168 }
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200 return result;
201 }
202
203 private Pager parseUsersInGroupTwoTermQuery(UsersInGroupTwoTermQuery query) throws EntityException
204 {
205 UserNameTermQuery userQuery = query.getUserNameTermQuery();
206 GroupNameTermQuery groupQuery = query.getGroupNameTermQuery();
207
208 Pager users = find(userQuery);
209 Pager groups = find(groupQuery);
210
211 Iterator groupsIter = groups.iterator();
212 Set candidateUsers = new HashSet();
213
214 while (groupsIter.hasNext())
215 {
216 Group group = (Group) groupsIter.next();
217 candidateUsers.addAll(PagerUtils.toList(groupManager.getLocalMemberNames(group)));
218 }
219
220 List userQueryList = PagerUtils.toList(users);
221
222 userQueryList.retainAll(candidateUsers);
223
224 return new DefaultPager(userQueryList);
225 }
226
227 private Pager evaluateBoolean(BooleanQuery query) throws EntityException
228 {
229 List queries = query.getQueries();
230 Pager allResults = null;
231
232 if (query instanceof MembershipQuery)
233 {
234 return parseMembershipQuery(query);
235 }
236
237 boolean anding = query.isAND();
238
239 for (int i = 0; i < queries.size(); i++)
240 {
241 Query nextQuery = (Query) queries.get(i);
242 List initialResult;
243
244 try
245 {
246 if (allResults == null)
247 {
248 allResults = find(nextQuery);
249 }
250 else if (nextQuery instanceof BooleanQuery)
251 {
252 if (anding)
253 {
254 Pager resultsToAnd = evaluateBoolean((BooleanQuery) nextQuery);
255 List resultsToAndList = PagerUtils.toList(resultsToAnd);
256 List allResultsList = PagerUtils.toList(allResults);
257
258 resultsToAndList.retainAll(allResultsList);
259 allResults = new DefaultPager(resultsToAndList);
260 }
261 else
262 {
263 Pager resultsToOr = evaluateBoolean((BooleanQuery) nextQuery);
264 List resultsToOrList = PagerUtils.toList(resultsToOr);
265 List intersection = findIntersection(PagerUtils.toList(allResults), resultsToOrList);
266 allResults = new DefaultPager(intersection);
267 }
268 }
269 else if (anding)
270 {
271
272 if (nextQuery instanceof UserNameTermQuery)
273 {
274 initialResult = PagerUtils.toList(parseQuery(entityNameMethod, (TermQuery) nextQuery,
275 allResults));
276 initialResult.addAll(PagerUtils.toList(allResults));
277 allResults = new DefaultPager(initialResult);
278 }
279 else if (nextQuery instanceof GroupNameTermQuery)
280 {
281 initialResult = PagerUtils.toList(parseQuery(entityNameMethod, (TermQuery) nextQuery,
282 allResults));
283 initialResult.addAll(PagerUtils.toList(allResults));
284 allResults = new DefaultPager(initialResult);
285 }
286 else if (nextQuery instanceof EmailTermQuery)
287 {
288 initialResult = PagerUtils.toList(parseQuery(emailMethod, (TermQuery) nextQuery, allResults));
289 initialResult.addAll(PagerUtils.toList(allResults));
290 allResults = new DefaultPager(initialResult);
291 }
292 else if (nextQuery instanceof FullNameTermQuery)
293 {
294 initialResult = PagerUtils.toList(parseQuery(fullnameMethod, (TermQuery) nextQuery,
295 allResults));
296 initialResult.addAll(PagerUtils.toList(allResults));
297 allResults = new DefaultPager(initialResult);
298 }
299 }
300 else
301 {
302 initialResult = PagerUtils.toList(find(nextQuery));
303 List intersection = findIntersection(PagerUtils.toList(allResults), initialResult);
304 allResults = new DefaultPager(intersection);
305 }
306 }
307 catch (Exception e)
308 {
309 log.error(e.getClass().getName() + " - " + e.getMessage());
310 }
311 }
312
313 return allResults;
314 }
315
316 private List findIntersection(List list1, List list2)
317 {
318 list2.removeAll(list1);
319 list1.addAll(list2);
320
321 return list1;
322 }
323
324 private Pager parseGroupsOfUserTwoTermQuery(GroupsOfUserTwoTermQuery query) throws EntityException
325 {
326 UserNameTermQuery userQuery = query.getUserNameTermQuery();
327 GroupNameTermQuery groupQuery = query.getGroupNameTermQuery();
328
329 Pager groups = find(groupQuery);
330 Pager users = find(userQuery);
331
332 Iterator usersIter = users.iterator();
333 Set candidateGroups = new HashSet();
334
335 while (usersIter.hasNext())
336 {
337 User user = (User) usersIter.next();
338 candidateGroups.addAll(PagerUtils.toList(groupManager.getGroups(user)));
339 }
340
341 List groupQueryList = PagerUtils.toList(groups);
342
343 groupQueryList.retainAll(candidateGroups);
344
345 return new DefaultPager(groupQueryList);
346 }
347
348 public SearchResult findUsers(Query query) throws EntityException
349 {
350 validateQuery(query);
351 Pager pager = find(query);
352 return new DefaultSearchResult(pager, repository.getKey());
353 }
354
355 public SearchResult findGroups(Query query) throws EntityException
356 {
357 validateQuery(query);
358 Pager pager = find(query);
359 return new DefaultSearchResult(pager, repository.getKey());
360 }
361
362 public SearchResult findUsers(Query query, QueryContext context) throws EntityException
363 {
364 validateQuery(query);
365 SearchResult result = null;
366 if (context.getRepositoryKeys().contains(repository.getKey()) || context.getRepositoryKeys().contains(
367 QueryContext.ALL_REPOSITORIES))
368 {
369 result = findUsers(query);
370 }
371
372 return result;
373 }
374
375 public SearchResult findGroups(Query query, QueryContext context) throws EntityException
376 {
377 validateQuery(query);
378 SearchResult result = null;
379
380 if (context.getRepositoryKeys().contains(repository.getKey()) || context.getRepositoryKeys().contains(
381 QueryContext.ALL_REPOSITORIES))
382 {
383 result = findGroups(query);
384 }
385
386 return result;
387 }
388 }