BrightSide Workbench Full Report + Source Code
WorkloadQuery.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2015 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 package org.turro.dossier.workload;
20 
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.EnumSet;
24 import java.util.Set;
25 import org.turro.string.Strings;
26 import org.turro.action.Contacts;
27 import org.turro.auth.Authentication;
28 import org.turro.dossier.db.DossierPU;
29 import org.turro.dossier.entity.Category;
30 import org.turro.dossier.entity.Dossier;
31 import org.turro.dossier.entity.DossierStatus;
32 import org.turro.dossier.entity.IssueParticipantRole;
33 import org.turro.dossier.entity.IssueResolution;
34 import org.turro.dossier.entity.IssueStatus;
35 import org.turro.dossier.entity.IssueType;
36 import org.turro.dossier.entity.ParticipantRole;
37 import org.turro.dossier.entity.Worksheet;
38 import org.turro.dossier.issue.IssueSet;
39 import org.turro.dossier.issue.IssueWrapper;
40 import org.turro.dossier.util.WorksheetUtil;
41 import org.turro.elephant.context.Application;
42 import org.turro.elephant.db.WhereClause;
43 import org.turro.jpa.Dao;
44 import org.turro.plugin.contacts.IContact;
45 import org.turro.util.Chars;
46 
51 public class WorkloadQuery {
52 
53  private Application app = Application.getApplication();
54 
55  private String searchValue = "*";
56  private IContact realParticipant, byParticipant;
57  private Long dossierId;
58  private Dossier dossier;
59  private EnumSet<IssueParticipantRole> roles = EnumSet.noneOf(IssueParticipantRole.class);
60  private EnumSet<IssueStatus> status = EnumSet.noneOf(IssueStatus.class);
61  private EnumSet<IssueResolution> resolutions = EnumSet.noneOf(IssueResolution.class);
62  private EnumSet<IssueType> types = EnumSet.noneOf(IssueType.class);
63  private Category category;
64  private IContact subject;
65 
66  public WorkloadQuery() {
67  resetToDefault();
68  }
69 
70  // Used by headless mail notifications
71  public WorkloadQuery(IContact contact) {
72  realParticipant = contact;
73  app = null;
74  resetToDefault();
75  }
76 
77  private void resetToDefault() {
78  if(realParticipant == null) {
79  realParticipant = Authentication.getIContact();
80  }
81  if(byParticipant == null) {
82  byParticipant = realParticipant;
83  }
84  roles.addAll(Arrays.asList(IssueParticipantRole.values()));
85  types.addAll(Arrays.asList(IssueType.values()));
86  status.addAll(Arrays.asList(IssueStatus.values()));
87  status.remove(IssueStatus.STATUS_CLOSED);
88  resolutions.addAll(Arrays.asList(IssueResolution.values()));
89  }
90 
91  public void setApplication(Application app) {
92  this.app = app;
93  }
94 
95  public void markSelf() {
96  resetToDefault();
97  }
98 
100  if(byParticipant == null) {
101  byParticipant = realParticipant;
102  }
103  WorkloadSet results = new WorkloadSet();
104  if((Strings.isEmpty(searchValue) || "*".equals(searchValue)) &&
105  category == null && dossier == null && (dossierId == null || dossierId == 0)) {
106  for(Worksheet worksheet : WorksheetUtil.getWorksheet(byParticipant.getId())) {
107  if(!WorksheetUtil.cleared(worksheet, byParticipant)) {
108  results.add(new WorkloadItem(worksheet));
109  }
110  }
111  }
112  for(IssueWrapper iw : getResultSet()) {
113  WorkloadItem wi = new WorkloadItem(iw);
114  if(!results.inWorksheet(wi.getIssue().getId())) {
115  results.add(wi);
116  }
117  }
118  return results;
119  }
120 
121  public Set<IssueWrapper> getResultSet() {
122  Dao dao = new DossierPU();
124  if(wc != null) {
125  return new IssueSet(dao.getResultList(wc), false, byParticipant);
126  } else {
127  return Collections.EMPTY_SET;
128  }
129  }
130 
132  return category;
133  }
134 
135  public void setCategory(Category category) {
136  this.category = category;
137  }
138 
139  public Set<IssueResolution> getResolutions() {
140  return resolutions;
141  }
142 
143  public void setResolutions(Set<IssueResolution> resolutions) {
144  this.resolutions = EnumSet.copyOf(resolutions);
145  }
146 
147  public Set<IssueParticipantRole> getRoles() {
148  return roles;
149  }
150 
151  public void setRoles(Set<IssueParticipantRole> roles) {
152  this.roles = EnumSet.copyOf(roles);
153  }
154 
155  public Set<IssueStatus> getStatus() {
156  return status;
157  }
158 
159  public void setStatus(Set<IssueStatus> status) {
160  this.status = EnumSet.copyOf(status);
161  }
162 
163  public IContact getSubject() {
164  return subject;
165  }
166 
167  public void setSubject(IContact subject) {
168  this.subject = subject;
169  }
170 
171  public Set<IssueType> getTypes() {
172  return types;
173  }
174 
175  public void setTypes(Set<IssueType> types) {
176  this.types = EnumSet.copyOf(types);
177  }
178 
179  public void setType(IssueType type) {
180  this.types = EnumSet.of(type);
181  }
182 
184  boolean canSeeAll = app != null && app.isInRole("issue:all");
185 
186  WhereClause wc = new WhereClause();
187  wc.addClause("select distinct issue from Issue as issue");
188  wc.addClause("left outer join issue.participants participant");
189  wc.addClause("left outer join issue.sources source");
190  if(!"*".equals(searchValue)) {
191  wc.addClause("left outer join issue.comments comment");
192  }
193  wc.addClause("where 1=1");
194 
195  boolean asParticipant =
196  roles.contains(IssueParticipantRole.ISSUE_REPORTER) ||
197  roles.contains(IssueParticipantRole.ISSUE_RESPONSIBLE) ||
198  roles.contains(IssueParticipantRole.ISSUE_QA) ||
199  roles.contains(IssueParticipantRole.ISSUE_ASSISTANT);
200 
201  if(Strings.isEmpty(searchValue) || (!asParticipant && !canSeeAll)) {
202  return null;
203  }
204 
205  if(byParticipant == null) {
206  byParticipant = realParticipant;
207  }
208 
209  long id = 0;
210 
211  try {
212  if(searchValue.startsWith("#") && canSeeAll) {
213  id = Long.valueOf(searchValue.substring(1));
214  if(id > 0) {
215  wc.addClause("and issue.id = :id");
216  wc.addNamedValue("id", id);
217  return wc;
218  }
219  }
220  id = Long.valueOf(searchValue);
221  if(id > 0) {
222  wc.addClause("and ((issue.id = :id)");
223  wc.addNamedValue("id", id);
224  wc.setPrefix("or");
225  }
226  } catch(Exception ex) {}
227 
228  if(searchValue.startsWith("#") && searchValue.length() > 2 && canSeeAll) {
229  wc.addLikeFields(new String[] {
230  "issue.description",
231  "comment.comment"
232  }, searchValue.substring(1).replaceAll("\\*", "%"));
233  return wc;
234  }
235 
236  if(!"*".equals(searchValue)) {
237  wc.addLikeFields(new String[] {
238  "issue.description",
239  "comment.comment"
240  }, (searchValue == null ? "" : searchValue.replaceAll("\\*", "%")));
241  }
242 
243  if(id > 0) {
244  wc.addClause(")");
245  wc.setPrefix(null);
246  }
247 
248  if(asParticipant) {
249  wc.addClause("and participant.idContact = :idContact");
250  wc.addNamedValue("idContact", byParticipant.getId());
251  if(!roles.containsAll(EnumSet.allOf(IssueParticipantRole.class))) {
252  wc.addClause("and participant.role in (:roles)");
253  wc.addNamedValue("roles", roles);
254  }
255  }
256 
257  if(!status.containsAll(EnumSet.allOf(IssueStatus.class))) {
258  wc.addClause("and issue.status in (:status)");
259  wc.addNamedValue("status", status);
260  }
261 
262  if(!resolutions.containsAll(EnumSet.allOf(IssueResolution.class))) {
263  wc.addClause("and issue.resolution in (:resolutions)");
264  wc.addNamedValue("resolutions", resolutions);
265  }
266 
267  if(!types.containsAll(EnumSet.allOf(IssueType.class))) {
268  wc.addClause("and issue.type in (:types)");
269  wc.addNamedValue("types", types);
270  }
271 
272  if(subject != null) {
273  wc.addClause("and exists ( select subject from Participant as subject");
274  wc.addClause("where subject.dossier = issue.dossier");
275  wc.addClause("and subject.idContact = :idSubject");
276  wc.addNamedValue("idSubject", subject.getId());
277  wc.addClause("and subject.role = :roleSubject )");
279  }
280 
281  if(dossier != null) {
282  wc.addClause("and issue.dossier = :dossier");
283  wc.addNamedValue("dossier", dossier);
284  } else if(dossierId != null && dossierId > 0) {
285  wc.addClause("and issue.dossier.id = :dossierId");
286  wc.addNamedValue("dossierId", dossierId);
287  } else {
288  wc.addClause("and issue.dossier.status = :dstatus");
290  }
291 
292  if(category != null) {
293  wc.addClause("and (");
294  wc.addClause("issue.dossier.category.fullDescription = :fullCatDesc");
295  wc.addClause("or issue.dossier.category.fullDescription like concat(:fullCatDesc, '" + Chars.backward().spaced() + "%')");
296  wc.addNamedValue("fullCatDesc", category.getFullDescription());
297  wc.addClause(")");
298  }
299 
300  if(!realParticipant.getId().equals(byParticipant.getId()) && !canSeeAll) {
301  wc.addClause("and (");
302  // dossier
303  wc.addClause("exists (");
304  wc.addClause("select p from Participant as p");
305  wc.addClause("where p.dossier = issue.dossier");
306  wc.addClause("and p.idContact = :idObserver");
307  wc.addClause("and p.showAllIssues = TRUE");
308  wc.addClause(")");
309  // categories
310  wc.addClause("or exists (");
311  wc.addClause("select cp from CategoryParticipant as cp");
312  wc.addClause("where cp.idContact = :idObserver");
313  wc.addClause("and cp.showAllIssues = TRUE");
314  wc.addClause("and (");
315  wc.addClause("cp.category.fullDescription = issue.dossier.category.fullDescription");
316  wc.addClause("or issue.dossier.category.fullDescription like concat(cp.category.fullDescription, '" + Chars.backward().spaced() + "%')");
317  wc.addClause("))");
318  //
319  wc.addClause(")");
320  // parameter
321  wc.addNamedValue("idObserver", realParticipant.getId());
322  }
323 
324  return wc;
325  }
326 
327  public Dossier getDossier() {
328  return dossier;
329  }
330 
331  public void setDossier(Dossier dossier) {
332  this.dossier = dossier;
333  }
334 
335  public Long getDossierId() {
336  return dossierId;
337  }
338 
339  public void setDossierId(Long dossierId) {
340  this.dossierId = dossierId;
341  }
342 
343  public String getSearchValue() {
344  return searchValue;
345  }
346 
347  public void setSearchValue(String searchValue) {
348  this.searchValue = searchValue;
349  }
350 
352  return byParticipant;
353  }
354 
355  public void setByParticipant(IContact byParticipant) {
356  this.byParticipant = byParticipant;
357  }
358 
359  public void setByParticipantId(String id) {
360  this.byParticipant = Contacts.getContactById(id);
361  }
362 
363 }
static IContact getContactById(String id)
Definition: Contacts.java:72
static boolean cleared(Worksheet worksheet, IContact contact)
static Collection< Worksheet > getWorksheet(String idContact)
void setResolutions(Set< IssueResolution > resolutions)
void setStatus(Set< IssueStatus > status)
void setRoles(Set< IssueParticipantRole > roles)
Set< IssueParticipantRole > getRoles()
void setTypes(Set< IssueType > types)
void setByParticipant(IContact byParticipant)
void addLikeFields(String[] fields, String value)
void addNamedValue(String name, Object value)