View Javadoc

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(); // to allow case insensitive search
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 //        TermQuery tQuery = (TermQuery) query;
171 //
172 //        if (tQuery.isMatchingSubstring())
173 //        {
174 //            GroupNameTermQuery q = new GroupNameTermQuery(tQuery.getTerm(), tQuery.getMatchingRule());
175 //            Pager pager = find(q);
176 //            Iterator iter = pager.iterator();
177 //
178 //            if (pager.isEmpty())
179 //                return new DefaultPager();
180 //            else
181 //            {
182 //                Pager members = null;
183 //                while (iter.hasNext())
184 //                {
185 //                    Group group = (Group) iter.next();
186 //
187 //                    if (members == null)
188 //                        members = groupManager.getMemberNames(group);
189 //                    else
190 //                        members = new MergedPager(members, groupManager.getMemberNames(group));
191 //                }
192 //
193 //                return members;
194 //            }
195 //
196 //        }
197 //        else
198 //            return groupManager.getMemberNames(groupManager.getGroup(tQuery.getTerm()));
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 // OR
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 }