BrightSide Workbench Full Report + Source Code
IssueIterator.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2013 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.www;
20 
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.List;
24 import org.turro.string.ObjectString;
25 import org.turro.string.Strings;
26 import org.turro.action.LinkType;
27 import org.turro.attach.www.AttachCtrl;
28 import org.turro.auth.Authentication;
29 import org.turro.dossier.db.DossierPU;
30 import org.turro.dossier.dossier.DossierWrapper;
31 import org.turro.dossier.entity.Category;
32 import org.turro.dossier.entity.Dossier;
33 import org.turro.dossier.entity.DossierStatus;
34 import org.turro.dossier.entity.Issue;
35 import org.turro.dossier.entity.IssueResolution;
36 import org.turro.dossier.entity.IssueStatus;
37 import org.turro.dossier.entity.IssueType;
38 import org.turro.dossier.issue.IssueWrapper;
39 import org.turro.elephant.context.Application;
40 import org.turro.elephant.context.ElephantContext;
41 import org.turro.elephant.context.IConstructor;
42 import org.turro.elephant.db.WhereClause;
43 import org.turro.elephant.impl.repository.Repository;
44 import org.turro.elephant.impl.repository.RepositoryFile;
45 import org.turro.elephant.web.SocialImageMap;
46 import org.turro.elephant.web.SocialNet;
47 import org.turro.entities.Entities;
48 import org.turro.file.util.FileAttach;
49 import org.turro.jpa.iterator.DaoHtmlIterator;
50 import org.turro.jpa.search.DaoHtmlSearch;
51 import org.turro.jpa.search.DaoSearchKey;
52 import org.turro.mail.recipients.MailContact;
53 import org.turro.marker.ElephantMarker;
54 import org.turro.marker.MarkerHelper;
55 import org.turro.plugin.contacts.ContactList;
56 import org.turro.plugin.contacts.IContact;
57 import org.turro.www.commentit.CommentItCtrl;
58 import org.turro.www.describeit.DescribeItCtrl;
59 import org.turro.www.starit.StarItCtrl;
60 import org.turro.www.voteit.VoteItCtrl;
61 
66 public class IssueIterator extends DaoHtmlIterator<Issue, Long> {
67 
68  private String pubPath, actualParameters, uniqueId;
69  private long categoryId, dossierId, lastDosierId = -1, lastCategoryId = -1;
70  private List<String> issueTypes, issueStatus, dossierStatus;
71  private boolean showSubject;
72  private boolean all, onlyAssists;
74 
75  public IssueIterator(IConstructor constructor, String pubPath, String uniqueId) {
76  this(constructor, false, pubPath, uniqueId);
77  }
78 
79  public IssueIterator(IConstructor constructor, boolean mail, String pubPath, String uniqueId) {
80  super(new DossierPU(), new ElephantMarker(constructor, mail));
81  this.pubPath = pubPath;
82  this.uniqueId = uniqueId;
83  this.all = Application.getApplication().isInRole("issue:all");
84  }
85 
86  public void setCategoryId(long categoryId) {
87  this.categoryId = categoryId;
88  }
89 
90  public void setDossierId(long dossierId) {
91  this.dossierId = dossierId;
92  }
93 
94  public void setDossierStatus(List<String> dossierStatus) {
95  this.dossierStatus = dossierStatus;
96  }
97 
98  public void setIssueTypes(List<String> issueTypes) {
99  this.issueTypes = issueTypes;
100  }
101 
102  public void setIssueStatus(List<String> issueStatus) {
103  this.issueStatus = issueStatus;
104  }
105 
106  public boolean isShowSubject() {
107  return showSubject;
108  }
109 
110  public void setShowSubject(boolean showSubject) {
111  this.showSubject = showSubject;
112  }
113 
115  return orderBy;
116  }
117 
118  public void setOrderBy(IssueOrdering orderBy) {
119  this.orderBy = orderBy;
120  }
121 
122  public boolean isOnlyAssists() {
123  return onlyAssists;
124  }
125 
126  public void setOnlyAssists(boolean onlyAssists) {
127  this.onlyAssists = onlyAssists;
128  }
129 
130  @Override
132  WhereClause wc = new WhereClause();
133  wc.addClause("select distinct i from Issue as i");
134  wc.addClause("join i.participants as p");
135  addCriteria(wc);
136  wc.addClause(IssueOrdering.ORDER_BY_ACTIVITY.getOrderBy());
137  return wc;
138  }
139 
140  @Override
142  WhereClause wc = new WhereClause();
143  wc.addClause("select count(distinct i) from Issue as i");
144  wc.addClause("join i.participants as p");
145  addCriteria(wc);
146  return wc;
147  }
148 
149  public String getActualParameters() {
150  return Strings.isBlank(actualParameters) ? "?a=b" : actualParameters;
151  }
152 
153  @Override
154  protected void renderSummary(ElephantMarker marker, Issue e, int page) {
155  if(e != null) {
156  marker.put("issue", e);
157  marker.put("newCategory", e.getDossier().getCategory().getId() != lastCategoryId);
158  marker.put("newDossier", e.getDossier().getId() != lastDosierId);
159  lastCategoryId = e.getDossier().getCategory().getId();
160  lastDosierId = e.getDossier().getId();
161  prepareValues(e, page, false);
162  marker.put("restricted", isRestricted());
163  }
164  marker.process("issue", getSummaryTemplate());
165  actualParameters = getPageLink(page);
166  }
167 
168  @Override
169  protected void renderItem(ElephantMarker marker, Issue e, int page) {
170  Long dossId = (Long) ObjectString.parseString(constructor.getParameter("dossierId"), Long.class, false);
171  if(dossId != null) {
172  if(e.getDossier().getId().equals(dossId)) {
173  Dossier dossier = dao.find(Dossier.class, dossId);
174  marker.put("dossier", dossier);
175  if(!Strings.isBlank(dossier.getFullDescription(showSubject))) {
177  "jQuery('title').html('" + dossier.getFullDescription(showSubject).replace("'", "\\'") + "');"
178  );
179  }
180  prepareValues(dossier, page, false);
181  marker.put("restricted", isRestricted());
182  marker.process("dossier", getFullTemplate());
183  }
184  } else {
185  marker.put("issue", e);
186 // if(!Strings.isBlank(e.getFullDescription(showSubject))) {
187 // constructor.addOnLoadedJavaScript(
188 // "jQuery('title').html('" + e.getFullDescription(showSubject).replace("'", "\\'") + "');"
189 // );
190 // }
191  prepareValues(e, page, false);
192  marker.put("restricted", isRestricted());
193  marker.process("issue", getFullTemplate());
194  }
195  actualParameters = getPageLink(page);
196  }
197 
198  @Override
199  protected String entityRoot() {
200  return "issue";
201  }
202 
203  @Override
204  protected Issue entity(Long value) {
205  WhereClause wc = new WhereClause();
206  wc.addClause("select distinct i from Issue as i");
207  wc.addClause("join i.participants as p");
208  addCriteria(wc);
209  wc.addClause("and i.id = :id");
210  wc.addNamedValue("id", value);
211  return (Issue) dao.getSingleResultOrNull(wc);
212  }
213 
214  private void addCriteria(WhereClause wc) {
215  wc.addClause("where i.publishable = TRUE");
216  if(!Strings.isBlank(pubPath) && isSearchOption()) {
218  if(dhs != null) {
219  DaoSearchKey dsk = dhs.get("search-value");
220  if(dsk != null) {
221  String searchValue = dsk.getValue();
222  if(!Strings.isBlank(searchValue)) {
223  wc.addClause("and i.description like :search01");
224  wc.addNamedValue("search01", "%" + searchValue + "%");
225  }
226  }
227  }
228  }
229  if(categoryId > 0) {
230  wc.addClause("and i.dossier.category.id in (" + getCategories(categoryId) + ")");
231  } else if(dossierId > 0) {
232  wc.addClause("and i.dossier.id = " + dossierId);
233  }
234  if(dossierStatus != null && dossierStatus.size() > 0) {
235  wc.addClause("and (");
236  String sep = "";
237  for(String s : dossierStatus) {
238  DossierStatus ds = DossierStatus.valueOf(s);
239  if(ds != null) {
240  String par = "status" + wc.getUniqueSuffix();
241  wc.addClause(sep + "i.dossier.status = :" + par);
242  wc.addNamedValue(par, ds);
243  sep = " or ";
244  }
245  }
246  wc.addClause(")");
247  }
248  if(issueStatus != null && issueStatus.size() > 0) {
249  wc.addClause("and (");
250  String sep = "";
251  for(String s : issueStatus) {
252  IssueStatus is = IssueStatus.valueOf(s);
253  if(is != null) {
254  String par = "status" + wc.getUniqueSuffix();
255  wc.addClause(sep + "i.status = :" + par);
256  wc.addNamedValue(par, is);
257  sep = " or ";
258  }
259  }
260  wc.addClause(")");
261  }
262  if(issueTypes != null && issueTypes.size() > 0) {
263  wc.addClause("and (");
264  String sep = "";
265  for(String s : issueTypes) {
266  IssueType it = IssueType.valueOf(s);
267  if(it != null) {
268  String par = "type" + wc.getUniqueSuffix();
269  wc.addClause(sep + "i.type = :" + par);
270  wc.addNamedValue(par, it);
271  sep = " or ";
272  }
273  }
274  wc.addClause(")");
275  }
276  }
277 
278  @Override
279  protected boolean isValid(Issue e) {
280  if(isRestricted() && e != null) {
281  return participates(e);
282  } else {
283  return super.isValid(e);
284  }
285  }
286 
287  private boolean participates(Issue e) {
288  if(onlyAssists) {
289  return new IssueWrapper(e).isAssistant();
290  } else {
291  return all || new IssueWrapper(e).isFullParticipant();
292  }
293  }
294 
295  private String getCategories(long categoryId) {
296  String result = null;
297  Category category = dao.find(Category.class, Long.valueOf(categoryId));
298  return addCategory(category, result);
299  }
300 
301  private String addCategory(Category category, String result) {
302  if(category != null) {
303  result = (String) (((result == null) ? "" : result + ",") + category.getId());
304  for(Category c : category.getChildren()) {
305  result = addCategory(c, result);
306  }
307  }
308  return result;
309  }
310 
311  private void prepareValues(Issue issue, int page, boolean asMail) {
312  marker.put("wrapper", new IssueWrapper(issue));
313  if(asMail && pubPath != null) {
314  marker.put("name", MailContact.createLink(issue.getDescription(), getItemLink(issue, page), false));
315  } else {
316  marker.put("name", issue.getDescription());
317  }
318  String link = getItemLink(issue, page);
319  if(link != null) {
320  marker.put("path", link);
321  marker.put("all", getPageLink(page));
322  }
323  marker.put("issueClass", getIssueClass(issue));
324  if(!Strings.isBlank(pubPath)) {
325  marker.put("readall", getItemLink(issue, page));
326  }
327  Dossier dossier = issue.getDossier();
328  marker.put("dossierClass", "dossier" +
329  (dossier.getStatus().equals(DossierStatus.DOSSIER_OPENED) ? " openned" : "") +
330  (dossier.getStatus().equals(DossierStatus.DOSSIER_CLOSED) ? " closed" : "") +
331  (dossier.getStatus().equals(DossierStatus.DOSSIER_FROZEN) ? " frozen" : ""));
332 
333  if(isAllowVotes()) {
334  if(dossier.getType().isVotes()) {
335  VoteItCtrl vic = new VoteItCtrl(constructor);
336  vic.setEntityPath(DossierPU.getObjectPath(issue));
337  vic.setForbiden(issue.getStatus().isFinished());
338  if(dossier.getType().isSecret()) {
339  vic.setForbid(true);
340  vic.setAllowed((ContactList) dossier.getFullParticipants().getVoteIParticipants());
341  }
342  marker.put("vic", vic);
343  }
344  }
345  if(isAllowInterest()) {
346  StarItCtrl sic = new StarItCtrl(constructor);
347  sic.setEntityPath(DossierPU.getObjectPath(issue));
348  marker.put("sic", sic);
349  }
350  if(isAllowComments()) {
351  CommentItCtrl cic = new CommentItCtrl(constructor);
352  cic.setEntityPath(DossierPU.getObjectPath(issue));
353  marker.put("cic", cic);
354  }
355  if(isAllowAttachments()) {
356  AttachCtrl ac = new AttachCtrl(constructor);
357  ac.setEntityPath(DossierPU.getObjectPath(issue));
358  ac.setPublicOnly(true);
359  if(issue.getFullParticipants().canShowAllAttachments(Authentication.getIContact())) {
360  ac.setPublicOnly(false);
361  }
362  marker.put("ac", ac);
363  }
364  if(isAllowDescriptions()) {
365  DescribeItCtrl dic = new DescribeItCtrl(constructor);
366  dic.setEntityPath(DossierPU.getObjectPath(issue));
367  marker.put("dic", dic);
368  }
369  marker.put("files", new FileAttach(DossierPU.getObjectPath(issue)));
370 
371  IContact contact = Authentication.getIContact();
372  if(contact.isWebapp()) {
373  marker.put("linkWebapp", Entities.getController(issue).getAppUrl());
374  }
375  if(issue.getFullParticipants().isParticipant(contact)) {
376  marker.put("linkWebint", Entities.getController(issue).getEntityUrl(LinkType.WEB_INTERNAL, null));
377  }
378 // if(contact.isWebapp()) {
379 // marker.put("linkWebapp", DossierEntityInfo.linkForPath(
380 // new Path(DossierPU.getObjectPath(issue)), contact, LinkType.INTERNAL));
381 // }
382 // if(issue.getFullParticipants().isParticipant(contact)) {
383 // marker.put("linkWebint", DossierEntityInfo.linkForPath(
384 // new Path(DossierPU.getObjectPath(issue)), contact, LinkType.WEB_INTERNAL));
385 // }
386  }
387 
388  private void prepareValues(Dossier dossier, int page, boolean asMail) {
389  marker.put("wrapper", new DossierWrapper(dossier));
390  if(isAllowVotes()) {
391  if(dossier.getType().isVotes()) {
392  VoteItCtrl vic = new VoteItCtrl(constructor);
393  vic.setEntityPath(DossierPU.getObjectPath(dossier));
394  vic.setForbiden(!dossier.getStatus().isOpen());
395  if(dossier.getType().isSecret()) {
396  vic.setForbid(true);
397  vic.setAllowed((ContactList) dossier.getFullParticipants().getVoteIParticipants());
398  }
399  marker.put("vic", vic);
400  }
401  }
402  if(isAllowInterest()) {
403  StarItCtrl sic = new StarItCtrl(constructor);
404  sic.setEntityPath(DossierPU.getObjectPath(dossier));
405  marker.put("sic", sic);
406  }
407  if(isAllowComments()) {
408  CommentItCtrl cic = new CommentItCtrl(constructor);
409  cic.setEntityPath(DossierPU.getObjectPath(dossier));
410  marker.put("cic", cic);
411  }
412  if(isAllowAttachments()) {
413  AttachCtrl ac = new AttachCtrl(constructor);
414  ac.setEntityPath(DossierPU.getObjectPath(dossier));
415  if(isRestricted() && new DossierWrapper(dossier).getCanShowAllAttachments()) {
416  ac.setPublicOnly(false);
417  } else {
418  ac.setPublicOnly(true);
419  }
420  marker.put("ac", ac);
421  }
422  if(isAllowDescriptions()) {
423  DescribeItCtrl dic = new DescribeItCtrl(constructor);
424  dic.setEntityPath(DossierPU.getObjectPath(dossier));
425  marker.put("dic", dic);
426  }
427  marker.put("files", new FileAttach(DossierPU.getObjectPath(dossier)));
428  }
429 
430  private String getItemLink(Issue issue, int page) {
431  if(pubPath == null) {
432  String link = issue.getIssueURL();
433  if(link == null) {
434  return null;
435  } else {
436  return ElephantContext.getRootWebPath() + link;
437  }
438  } else {
439  return pubPath + "?" + MarkerHelper.setObfuscatedPars("item=" + issue.getId() + ";page=" + page);
440  }
441  }
442 
443  private String getPageLink(int page) {
444  return pubPath + "?page=" + page;
445  }
446 
447  private String getIssueClass(Issue issue) {
448  return"issue" +
449  (issue.getStatus().equals(IssueStatus.STATUS_NEW) ? " new" : "") +
450  (issue.getStatus().equals(IssueStatus.STATUS_STARTED) ? " started" : "") +
451  (issue.getStatus().equals(IssueStatus.STATUS_INCOMPLETE) ? " incomplete" : "") +
452  (issue.getStatus().equals(IssueStatus.STATUS_REOPENED) ? " reopened" : "") +
453  (issue.getStatus().equals(IssueStatus.STATUS_REUNION) ? " reunion" : "") +
454  (issue.getStatus().equals(IssueStatus.STATUS_FROZEN) ? " frozen" : "") +
455  (issue.getStatus().equals(IssueStatus.STATUS_RESOLVED) ? " resolved" : "") +
456  (issue.getStatus().equals(IssueStatus.STATUS_VERIFIED) ? " verified" : "") +
457  (issue.getStatus().equals(IssueStatus.STATUS_CLOSED) ? " closed" : "") +
458 
459  (issue.getType().equals(IssueType.TYPE_DEFECT) ? " defect" : "") +
460  (issue.getType().equals(IssueType.TYPE_ENHANCEMENT) ? " enhancement" : "") +
461  (issue.getType().equals(IssueType.TYPE_FEATURE) ? " feature" : "") +
462  (issue.getType().equals(IssueType.TYPE_NONCONFORMITY) ? " nonconformity" : "") +
463  (issue.getType().equals(IssueType.TYPE_PATCH) ? " patch" : "") +
464  (issue.getType().equals(IssueType.TYPE_PREVENTION) ? " prevention" : "") +
465  (issue.getType().equals(IssueType.TYPE_QUESTION) ? " question" : "") +
466  (issue.getType().equals(IssueType.TYPE_TASK) ? " task" : "") +
467  (issue.getType().equals(IssueType.TYPE_DOCUMENT) ? " document" : "") +
468  (issue.getType().equals(IssueType.TYPE_BESTPRACTICE) ? " bestpractice" : "") +
469  (issue.getType().equals(IssueType.TYPE_PROCESS) ? " process" : "") +
470  (issue.getType().equals(IssueType.TYPE_PROPOSITION) ? " proposition" : "") +
471 
472  (issue.getResolution().equals(IssueResolution.RESOLUTION_DUPLICATED) ? " duplicated" : "") +
473  (issue.getResolution().equals(IssueResolution.RESOLUTION_FIXED) ? " fixed" : "") +
474  (issue.getResolution().equals(IssueResolution.RESOLUTION_INVALID) ? " invalid" : "") +
475  (issue.getResolution().equals(IssueResolution.RESOLUTION_MOVED) ? " moved" : "") +
476  (issue.getResolution().equals(IssueResolution.RESOLUTION_NONE) ? " none" : "") +
477  (issue.getResolution().equals(IssueResolution.RESOLUTION_WONTFIX) ? " wontfix" : "") +
478  (issue.getResolution().equals(IssueResolution.RESOLUTION_WORKSFORME) ? " worksforme" : "");
479  }
480 
481  @Override
482  protected String title(Issue e) {
483  if(!Strings.isBlank(e.getFullDescription(showSubject))) {
484  return e.getFullDescription(showSubject);
485  }
486  return null;
487  }
488 
489  @Override
490  protected Collection<String> metas(Issue e) {
491  ArrayList<RepositoryFile> files = new ArrayList<>();
492  String path = getItemLink(e, 0);
493  if(!SocialImageMap.hasImage(path)) {
496  files.addAll(repository.getRepositoryFiles("*_social.png,*_social.jpg"));
497  files.addAll(repository.getRepositoryFiles("*.png,*.jpg"));
498  }
499  SocialNet sn = new SocialNet(path, e.getDescription(), e.getFullDescription(), files);
500  return sn.getMetas();
501  }
502 
503 }
static String getObjectPath(Object object)
Definition: DossierPU.java:66
IssueIterator(IConstructor constructor, String pubPath, String uniqueId)
void setShowSubject(boolean showSubject)
IssueIterator(IConstructor constructor, boolean mail, String pubPath, String uniqueId)
void setIssueStatus(List< String > issueStatus)
void setOnlyAssists(boolean onlyAssists)
void setDossierStatus(List< String > dossierStatus)
void renderSummary(ElephantMarker marker, Issue e, int page)
void setOrderBy(IssueOrdering orderBy)
void setCategoryId(long categoryId)
Collection< String > metas(Issue e)
void renderItem(ElephantMarker marker, Issue e, int page)
void setIssueTypes(List< String > issueTypes)
static String getContextVariable(IConstructor constructor)
void addNamedValue(String name, Object value)
static boolean hasImage(String url)
Repository getPublishableRepository(IConstructor constructor)
Definition: FileAttach.java:47
Object getSingleResultOrNull(SqlClause sc)
Definition: Dao.java:419
static DaoHtmlSearch getInstance(IConstructor constructor, String context)
void process(String rootTmpl, String tmpl)
Object put(Object key, Object value)
void addOnLoadedJavaScript(String script)