1 package com.atlassian.user.impl.hibernate.search.query;
2
3 import com.atlassian.user.EntityException;
4 import com.atlassian.user.impl.RepositoryException;
5 import com.atlassian.user.impl.hibernate.DefaultHibernateExternalEntity;
6 import com.atlassian.user.impl.hibernate.DefaultHibernateGroup;
7 import com.atlassian.user.impl.hibernate.DefaultHibernateUser;
8 import com.atlassian.user.impl.hibernate.repository.HibernateRepository;
9 import com.atlassian.user.repository.RepositoryIdentifier;
10 import com.atlassian.user.search.DefaultSearchResult;
11 import com.atlassian.user.search.SearchResult;
12 import com.atlassian.user.search.page.DefaultPager;
13 import com.atlassian.user.search.query.*;
14 import net.sf.hibernate.Criteria;
15 import net.sf.hibernate.HibernateException;
16 import net.sf.hibernate.Session;
17 import net.sf.hibernate.expression.*;
18 import org.springframework.orm.hibernate.SessionFactoryUtils;
19
20 import java.util.Iterator;
21 import java.util.List;
22
23
24
25
26
27
28 public class HibernateEntityQueryParser extends AbstractEntityQueryParser implements EntityQueryParser
29 {
30 private final RepositoryIdentifier identifier;
31 private final HibernateRepository repository;
32
33 public HibernateEntityQueryParser(RepositoryIdentifier identifier, HibernateRepository repository)
34 {
35 this.identifier = identifier;
36 this.repository = repository;
37 }
38
39 public SearchResult findUsers(Query query) throws EntityException
40 {
41 validateQuery(query);
42 return parseQuery(query);
43 }
44
45 public SearchResult findGroups(Query query) throws EntityException
46 {
47 validateQuery(query);
48 return parseQuery(query);
49 }
50
51 public SearchResult findUsers(Query query, QueryContext context) throws EntityException
52 {
53 validateQuery(query);
54
55 if (context instanceof AllRepositoriesQueryContext ||
56 context.getRepositoryKeys().contains(identifier.getKey()) ||
57 context.getRepositoryKeys().contains(QueryContext.ALL_REPOSITORIES))
58 return parseQuery(query);
59
60 return null;
61 }
62
63 public SearchResult findGroups(Query query, QueryContext context) throws EntityException
64 {
65 validateQuery(query);
66
67 if (context instanceof AllRepositoriesQueryContext ||
68 context.getRepositoryKeys().contains(identifier.getKey()) ||
69 context.getRepositoryKeys().contains(QueryContext.ALL_REPOSITORIES))
70
71 return parseQuery(query);
72
73 return null;
74 }
75
76 private MatchMode getMatchMode(String matchingRule)
77 {
78 if (matchingRule.equals(TermQuery.SUBSTRING_CONTAINS))
79 {
80 return MatchMode.ANYWHERE;
81 }
82 if (matchingRule.equals(TermQuery.SUBSTRING_ENDS_WITH))
83 {
84 return MatchMode.END;
85 }
86 if (matchingRule.equals(TermQuery.SUBSTRING_STARTS_WITH))
87 {
88 return MatchMode.START;
89 }
90 return MatchMode.EXACT;
91 }
92
93 private String identifyProperty(TermQuery q)
94 {
95 String entityProperty = null;
96
97 if (q instanceof UserNameTermQuery)
98 entityProperty = "name";
99 else if (q instanceof EmailTermQuery)
100 entityProperty = "email";
101 else if (q instanceof FullNameTermQuery)
102 entityProperty = "fullName";
103 else if (q instanceof GroupNameTermQuery)
104 entityProperty = "name";
105 else if (q instanceof GroupsOfUserTwoTermQuery)
106 entityProperty = "entity";
107
108 return entityProperty;
109 }
110
111
112
113
114
115 private SearchResult parseQuery(Query q) throws EntityException
116 {
117
118 Session session = SessionFactoryUtils.getSession(repository.getSessionFactory(), true);
119 Query definingQuery = q;
120
121 if (q instanceof BooleanQuery)
122 definingQuery = identifyDefiningQuery((BooleanQuery) q);
123
124 List result;
125 try
126 {
127 Criteria baseCriteria = getBaseCriteria(definingQuery, session);
128 baseCriteria = identifyAndAddSearchCriteria(q, definingQuery, baseCriteria);
129 baseCriteria.addOrder(Order.asc("name"));
130
131 result = baseCriteria.list();
132 }
133 catch (HibernateException e)
134 {
135 throw new RepositoryException(e);
136 }
137
138 return new DefaultSearchResult(new DefaultPager(result), identifier.getName());
139 }
140
141 private Criteria identifyAndAddSearchCriteria(Query q, Query definingQuery, Criteria baseCriteria)
142 throws EntityQueryException, HibernateException
143 {
144 if (q instanceof BooleanQuery)
145 return addSearchCriteria((BooleanQuery) q, definingQuery, baseCriteria);
146 else
147 {
148 return addSearchCriteria((TermQuery) q, baseCriteria);
149 }
150 }
151
152 private Criteria addSearchCriteria(BooleanQuery q, Query definingQuery, Criteria baseCriteria)
153 throws EntityQueryException, HibernateException
154 {
155
156
157
158 if (definingQuery instanceof MembershipQuery)
159 {
160 return addMembershipSearchCriteria(q, baseCriteria);
161 }
162
163 Junction junction = identifyAndOrJunction(q);
164 baseCriteria.add(junction);
165 Iterator iter = q.getQueries().iterator();
166
167 while (iter.hasNext())
168 {
169 Query query = (Query) iter.next();
170
171 if (query instanceof BooleanQuery)
172 {
173 addSearchCriteria((BooleanQuery) query, definingQuery, baseCriteria);
174 }
175 else if (query instanceof TermQuery)
176 {
177 junction.add(getQueryExpression((TermQuery) query));
178 }
179 else
180 throw new EntityQueryException("Unknown query type: [" + query.getClass().getName() + "]");
181 }
182
183 return baseCriteria;
184 }
185
186 private Junction identifyAndOrJunction(BooleanQuery q)
187 {
188 Junction junction;
189 if (q.isAND())
190 junction = Expression.conjunction();
191 else
192 junction = Expression.disjunction();
193
194 return junction;
195 }
196
197 private Criteria addMembershipSearchCriteria(BooleanQuery q, Criteria baseCriteria) throws HibernateException
198 {
199 if (q instanceof GroupsOfUserTwoTermQuery)
200 {
201 addGroupsOfUserSearchCriteria(q, baseCriteria);
202 }
203 else if (q instanceof GroupsOfExternalEntityTwoTermQuery)
204 {
205 addGroupsOfExternalEntitySearchCriteria(q, baseCriteria);
206 }
207
208 return baseCriteria;
209 }
210
211 private void addGroupsOfUserSearchCriteria(BooleanQuery q, Criteria baseCriteria) throws HibernateException
212 {
213 UserNameTermQuery userNameQuery = ((GroupsOfUserTwoTermQuery) q).getUserNameTermQuery();
214 GroupNameTermQuery groupNameQuery = ((GroupsOfUserTwoTermQuery) q).getGroupNameTermQuery();
215
216 if (groupNameQuery.getTerm().equals(TermQuery.WILDCARD))
217 {
218
219 }
220 else if (groupNameQuery.isMatchingSubstring())
221 {
222 baseCriteria.add(getLikeExpression("name", groupNameQuery, false));
223 }
224 else
225 {
226 baseCriteria.add(new EqExpression("name", groupNameQuery.getTerm(), false));
227 }
228
229 if (userNameQuery.isMatchingSubstring())
230 {
231 baseCriteria.createCriteria("localMembers").add(getLikeExpression("name", userNameQuery, false));
232 }
233 else
234 {
235 baseCriteria.createCriteria("localMembers").add(new EqExpression("name", userNameQuery.getTerm(), false));
236 }
237 }
238
239 private Criterion getLikeExpression(String entityAttribute, TermQuery termQuery, boolean caseInsensitive)
240 {
241 if (caseInsensitive)
242 return Expression.ilike(entityAttribute, termQuery.getTerm(), getMatchMode(termQuery.getMatchingRule()));
243 else
244 return Expression.like(entityAttribute, termQuery.getTerm(), getMatchMode(termQuery.getMatchingRule()));
245 }
246
247 private void addGroupsOfExternalEntitySearchCriteria(BooleanQuery q, Criteria baseCriteria)
248 throws HibernateException
249 {
250 ExternalEntityNameTermQuery nameQuery =
251 ((GroupsOfExternalEntityTwoTermQuery) q).getExternalEntityNameTermQuery();
252 GroupNameTermQuery groupQuery = ((GroupsOfExternalEntityTwoTermQuery) q).getGroupNameTermQuery();
253
254 if (groupQuery.getTerm().equals(TermQuery.WILDCARD))
255 {
256
257 }
258 else if (groupQuery.isMatchingSubstring())
259 {
260 baseCriteria.add(getLikeExpression("name", groupQuery, false));
261 }
262 else
263 {
264 baseCriteria.add(new EqExpression("name", groupQuery.getTerm(), false));
265 }
266
267 if (nameQuery.isMatchingSubstring())
268 {
269 baseCriteria.createCriteria("externalMembers").add(getLikeExpression("name", nameQuery, false));
270 }
271 else
272 {
273 baseCriteria.createCriteria("externalMembers").add(new EqExpression("name", nameQuery.getTerm(), false));
274 }
275 }
276
277 private Criteria addSearchCriteria(TermQuery q, Criteria baseCriteria)
278 {
279 Criterion expression = getQueryExpression(q);
280 baseCriteria.add(expression);
281 return baseCriteria;
282 }
283
284 private Criterion getQueryExpression(TermQuery termQuery)
285 {
286 String hqlField = identifyProperty(termQuery);
287
288 if (termQuery.isMatchingSubstring())
289 {
290 return getLikeExpression(hqlField, termQuery, true);
291 }
292 else
293 {
294 return new EqExpression(hqlField, termQuery.getTerm(), true);
295 }
296 }
297
298 private Criteria getBaseCriteria(Query query, Session session)
299 {
300 Criteria baseCriteria = null;
301
302 if (query instanceof UserQuery)
303 {
304 baseCriteria = session.createCriteria(DefaultHibernateUser.class);
305 }
306 else if (query instanceof GroupQuery)
307 {
308 baseCriteria = session.createCriteria(DefaultHibernateGroup.class);
309 }
310 else if (query instanceof UsersInGroupTwoTermQuery)
311 {
312 baseCriteria = session.createCriteria(DefaultHibernateUser.class);
313 }
314 else if (query instanceof GroupsOfUserTwoTermQuery || query instanceof GroupsOfExternalEntityTwoTermQuery)
315 {
316 baseCriteria = session.createCriteria(DefaultHibernateGroup.class);
317 }
318 else if (query instanceof ExternalEntitiesInGroupTwoTermQuery)
319 {
320 baseCriteria = session.createCriteria(DefaultHibernateExternalEntity.class);
321 }
322
323 return baseCriteria;
324 }
325 }