BrightSide Workbench Full Report + Source Code
KnowledgeBaseDashboard.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2016 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.io.IOException;
22 import java.io.PrintWriter;
23 import java.io.UnsupportedEncodingException;
24 import java.net.URLEncoder;
25 import java.util.EnumSet;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.logging.Level;
29 import java.util.logging.Logger;
30 import javax.servlet.ServletException;
31 import org.turro.string.ObjectString;
32 import org.turro.string.Strings;
33 import org.turro.auth.Authentication;
34 import org.turro.collections.CollectionUtil;
35 import org.turro.collections.KeyValueMap;
36 import org.turro.dossier.db.DossierPU;
37 import org.turro.dossier.entity.Category;
38 import org.turro.dossier.entity.Dossier;
39 import org.turro.dossier.entity.Issue;
40 import org.turro.dossier.entity.IssueResolution;
41 import org.turro.dossier.entity.IssueStatus;
42 import org.turro.dossier.entity.IssueType;
43 import org.turro.dossier.issue.IssueWrapper;
44 import org.turro.dossier.kb.KnowledgeBaseList;
45 import org.turro.dossier.kb.KnowledgeBaseQuery;
46 import org.turro.elephant.context.Application;
47 import org.turro.elephant.context.ElephantContext;
48 import org.turro.elephant.context.IElement;
49 import org.turro.elephant.impl.abstracts.AbstractElement;
50 import org.turro.elephant.impl.context.AttributeItem;
51 import org.turro.elephant.layout.IManageable;
52 import org.turro.elephant.layout.IRenderable;
53 import org.turro.elephant.security.IDefendable;
54 import org.turro.entities.Entities;
55 import org.turro.file.util.FileAttach;
56 import org.turro.marker.ElephantMarker;
57 import org.turro.marker.MarkerHelper;
58 import org.turro.plugin.contacts.ContactList;
59 import org.turro.plugin.contacts.IContact;
60 import org.turro.www.describeit.DescribeItCtrl;
61 import org.turro.www.starit.StarItCtrl;
62 import org.turro.www.voteit.VoteItCtrl;
63 
69 
70  protected String sclass, fullTemplate, summaryTemplate, issuePath;
71  protected List<String> issueTypes, issueStatus;
72  protected long categoryId, dossierId;
73  protected int count;
74  protected boolean allowInterest, allowComments, allowVotes, showDescriptions, showFiles;
77  protected IContact contact;
78  protected Long item;
79  protected Issue issue;
80 
81  @Override
82  public void loadData() throws ServletException, IOException {
83  sclass = getAttributes().getAttributeValue("attrib:sclass", "");
84  categoryId = getAttributes().getAttributeIntegerValue("attrib:categoryId", 0);
85  dossierId = getAttributes().getAttributeIntegerValue("attrib:dossierId", 0);
86  // TYPE_DEFECT,TYPE_ENHANCEMENT,TYPE_FEATURE,TYPE_NONCONFORMITY,TYPE_PREVENTION,TYPE_TASK,TYPE_PATCH,TYPE_QUESTION,TYPE_DOCUMENT,TYPE_BESTPRACTICE,TYPE_PROCES,TYPE_PROPOSITION
87  issueTypes = getAttributes().getAttributeListValue("attrib:issueTypes", "");
88  // STATUS_NEW,STATUS_STARTED,STATUS_INCOMPLETE,STATUS_REOPENED,STATUS_REUNION,STATUS_FROZEN,STATUS_RESOLVED,STATUS_VERIFIED,STATUS_CLOSED
89  issueStatus = getAttributes().getAttributeListValue("attrib:issueStatus", "");
90  count = getAttributes().getAttributeIntegerValue("attrib:count", 10);
91  allowInterest = getAttributes().getAttributeBooleanValue("attrib:allowInterest", true);
92  allowComments = getAttributes().getAttributeBooleanValue("attrib:allowComments", true);
93  allowVotes = getAttributes().getAttributeBooleanValue("attrib:allowVotes", true);
94  showDescriptions = getAttributes().getAttributeBooleanValue("attrib:showDescriptions", true);
95  showFiles = getAttributes().getAttributeBooleanValue("attrib:showFiles", true);
96  fullTemplate = getAttributes().getAttributeValue("attrib:fullTemplate", "");
97  summaryTemplate = getAttributes().getAttributeValue("attrib:summaryTemplate", "");
98  issuePath = getAttributes().getAttributeValue("attrib:issuePath", "");
99 
101  kbq = new KnowledgeBaseQuery();
102  kbq.setSearchValue(AttributeItem.getFromParameter(getConstructor(), "search-value", "").getValue());
103  kbq.setOnlyTitle(AttributeItem.getFromParameter(getConstructor(), "only-title", null).getBooleanValue(false));
104  kbq.setMaxResults(AttributeItem.getFromParameter(getConstructor(), "max-results", null).getIntegerValue(300));
105  kbq.setTypes(AttributeItem.getFromParameter(getConstructor(), "type", null).getEnumSet(IssueType.class));
106  kbq.setStatus(AttributeItem.getFromParameter(getConstructor(), "status", null).getEnumSet(IssueStatus.class));
107  kbq.setResolutions(AttributeItem.getFromParameter(getConstructor(), "resolution", null).getEnumSet(IssueResolution.class));
108  kbq.setDossierId(AttributeItem.getFromParameter(getConstructor(), "dossier-id", null).getLongValue(0));
109 
110  KeyValueMap kvm = MarkerHelper.getObfuscatedParameters();
111  if(kvm != null && !kvm.isEmpty() && kvm.containsKey("item")) {
112  item = kvm.get(Long.class, "item");
113  } else {
114  item = (Long) ObjectString.parseString(getConstructor().getParameter("item"), Long.class, true);
115  }
116 
117  if(item > 0) {
118  issue = new DossierPU().find(Issue.class, item);
119  if(!canLink(new IssueWrapper(issue, contact))) {
120  issue = null;
121  }
122  }
123 
124  if(issue != null) {
126  } else {
127  item = 0L;
128  if(categoryId > 0) {
129  Category category = new DossierPU().find(Category.class, categoryId);
130  kbq.setCategory(category);
131  }
132  if(dossierId > 0) {
133  Dossier dossier = new DossierPU().find(Dossier.class, dossierId);
134  kbq.setDossier(dossier);
135  }
136  kbq.setByParticipant(null);
137  kbl = kbq.getResultList();
138  }
139 
140  }
141 
142  @Override
143  public void startConstruction() throws ServletException, IOException {
144  PrintWriter out = getConstructor().getOut();
145  out.print(getStart());
146  out.print(getStartBody());
147 
149  marker.put("searchValue", kbq.getSearchValue());
150  marker.put("onlyTitle", kbq.isOnlyTitle());
151  marker.put("maxResults", kbq.getMaxResults());
152  marker.put("types", kbq.getTypes());
153  marker.put("status", kbq.getStatus());
154  marker.put("resolutions", kbq.getResolutions());
155  marker.put("ntypes", EnumSet.complementOf(EnumSet.copyOf(kbq.getTypes())));
156  marker.put("nstatus", EnumSet.complementOf(EnumSet.copyOf(kbq.getStatus())));
157  marker.put("nresolutions", EnumSet.complementOf(EnumSet.copyOf(kbq.getResolutions())));
158  marker.put("dossierId", kbq.getDossierId());
159  if(item > 0) {
160  IssueWrapper wrapper = new IssueWrapper(issue, contact);
161  prepareValues(marker, wrapper.getIssue(), 0);
162  marker.put("wrapper", wrapper);
163  marker.put("issue", wrapper.getIssue());
164  if(contact.isWebUser() && (Application.getApplication().isInRole("issue:edit") || wrapper.isFullParticipant())) {
165  marker.put("addInfo", AddInformationCtrl.addInformation(wrapper, getItemLink(wrapper.getIssue(), 0)));
166  }
167  marker.process("issue", getFullTemplate());
168  } else if(kbl.isEmpty()) {
169  marker.put("divider", false);
170  marker.put("header", true);
171  marker.put("footer", true);
172  marker.put("empty", true);
173  marker.process("issue", getSummaryTemplate());
174  } else {
175  int index = 0;
176  marker.put("empty", false);
177  for(IssueWrapper wrapper : kbl) {
178  marker.put("divider", index > 0);
179  marker.put("header", index == 0);
180  marker.put("footer", index == kbl.size() - 1);
181  prepareValues(marker, wrapper.getIssue(), 0);
182  marker.put("wrapper", wrapper);
183  marker.put("issue", wrapper.getIssue());
184  marker.process("issue", getSummaryTemplate());
185  index++;
186  }
187  }
188 
189  out.print(getEndBody());
190  out.print(getEnd());
191  }
192 
193  @Override
194  public String getStart() {
195  return "<div class='" + sclass + "dossier-web'>";
196  }
197 
198  @Override
199  public String getEnd() {
200  return "</div>";
201  }
202 
203  private void prepareValues(ElephantMarker marker, Issue issue, int page) {
204  marker.put("iee", Entities.getController(issue));
205 
206  marker.put("name", issue.getDescription());
207 
208  String link = getItemLink(issue, page);
209  if(link != null) {
210  marker.put("path", link);
211  marker.put("all", getPageLink(page));
212  }
213  marker.put("readall", getItemLink(issue, page));
214  marker.put("issueClass", getIssueClass(issue));
215 
216  if(allowVotes) {
217  Dossier dossier = issue.getDossier();
218  if(dossier.getType().isVotes()) {
219  VoteItCtrl vic = new VoteItCtrl(getConstructor());
220  vic.setEntityPath(DossierPU.getObjectPath(issue));
221  vic.setForbiden(issue.getStatus().isFinished());
222  if(dossier.getType().isSecret()) {
223  vic.setForbid(true);
224  vic.setAllowed((ContactList) dossier.getFullParticipants().getVoteIParticipants());
225  }
226  marker.put("vic", vic);
227  }
228  }
229  if(allowInterest) {
230  StarItCtrl sic = new StarItCtrl(getConstructor());
231  sic.setEntityPath(DossierPU.getObjectPath(issue));
232  marker.put("sic", sic);
233  }
234  if(showDescriptions) {
235  DescribeItCtrl dic = new DescribeItCtrl(getConstructor());
236  dic.setEntityPath(DossierPU.getObjectPath(issue));
237  marker.put("dic", dic);
238  }
239 
240  if(showFiles) {
241  marker.put("files", new FileAttach(DossierPU.getObjectPath(issue)));
242  }
243  }
244 
245  private String getItemLink(Issue issue, int page) {
246  return getContext().getFullPath() + "?" + MarkerHelper.setObfuscatedPars("item=" + issue.getId() + ";page=" + page);
247  }
248 
249  private String getPageLink(int page) {
250  return getContext().getFullPath() + "?page=" + page;
251  }
252 
253  private String getIssueClass(Issue issue) {
254  return"issue" +
255  (issue.getStatus().equals(IssueStatus.STATUS_NEW) ? " new" : "") +
256  (issue.getStatus().equals(IssueStatus.STATUS_STARTED) ? " started" : "") +
257  (issue.getStatus().equals(IssueStatus.STATUS_INCOMPLETE) ? " incomplete" : "") +
258  (issue.getStatus().equals(IssueStatus.STATUS_REOPENED) ? " reopened" : "") +
259  (issue.getStatus().equals(IssueStatus.STATUS_REUNION) ? " reunion" : "") +
260  (issue.getStatus().equals(IssueStatus.STATUS_FROZEN) ? " frozen" : "") +
261  (issue.getStatus().equals(IssueStatus.STATUS_RESOLVED) ? " resolved" : "") +
262  (issue.getStatus().equals(IssueStatus.STATUS_VERIFIED) ? " verified" : "") +
263  (issue.getStatus().equals(IssueStatus.STATUS_CLOSED) ? " closed" : "") +
264 
265  (issue.getType().equals(IssueType.TYPE_DEFECT) ? " defect" : "") +
266  (issue.getType().equals(IssueType.TYPE_ENHANCEMENT) ? " enhancement" : "") +
267  (issue.getType().equals(IssueType.TYPE_FEATURE) ? " feature" : "") +
268  (issue.getType().equals(IssueType.TYPE_NONCONFORMITY) ? " nonconformity" : "") +
269  (issue.getType().equals(IssueType.TYPE_PATCH) ? " patch" : "") +
270  (issue.getType().equals(IssueType.TYPE_PREVENTION) ? " prevention" : "") +
271  (issue.getType().equals(IssueType.TYPE_QUESTION) ? " question" : "") +
272  (issue.getType().equals(IssueType.TYPE_TASK) ? " task" : "") +
273  (issue.getType().equals(IssueType.TYPE_DOCUMENT) ? " document" : "") +
274  (issue.getType().equals(IssueType.TYPE_BESTPRACTICE) ? " bestpractice" : "") +
275  (issue.getType().equals(IssueType.TYPE_PROCESS) ? " process" : "") +
276  (issue.getType().equals(IssueType.TYPE_PROPOSITION) ? " proposition" : "") +
277 
278  (issue.getResolution().equals(IssueResolution.RESOLUTION_DUPLICATED) ? " duplicated" : "") +
279  (issue.getResolution().equals(IssueResolution.RESOLUTION_FIXED) ? " fixed" : "") +
280  (issue.getResolution().equals(IssueResolution.RESOLUTION_INVALID) ? " invalid" : "") +
281  (issue.getResolution().equals(IssueResolution.RESOLUTION_MOVED) ? " moved" : "") +
282  (issue.getResolution().equals(IssueResolution.RESOLUTION_NONE) ? " none" : "") +
283  (issue.getResolution().equals(IssueResolution.RESOLUTION_WONTFIX) ? " wontfix" : "") +
284  (issue.getResolution().equals(IssueResolution.RESOLUTION_WORKSFORME) ? " worksforme" : "");
285  }
286 
287  private String getSummaryTemplate() {
288  return Strings.isBlank(summaryTemplate) ? "kbSummary" : summaryTemplate;
289  }
290 
291  private String getFullTemplate() {
292  return Strings.isBlank(fullTemplate) ? "kbFull" : fullTemplate;
293  }
294 
295  private boolean canLink(IssueWrapper iw) {
296  Application app = Application.getApplication();
297  boolean show = app.isInRole("issue:show"),
298  all = app.isInRole("issue:all");
299  return (iw.getIssue().isKnowledgeBase() || (show && (all || iw.isFullParticipant())));
300  }
301 
302  public static String createLink(String searchValue, boolean onlyTitle,
303  Set<IssueType> type, Set<IssueStatus> status, Set<IssueResolution> resolution,
304  Long dossierId) {
305  StringBuilder sb = new StringBuilder();
306  String sep = "?";
307  sb.append("/user/kbase");
308  if(!Strings.isBlank(searchValue)) {
309  sb.append(sep); sep = "&";
310  try {
311  sb.append("search-value=").append(URLEncoder.encode(searchValue, "UTF-8"));
312  } catch (UnsupportedEncodingException ex) {
313  Logger.getLogger(KnowledgeBaseDashboard.class.getName()).log(Level.SEVERE, ElephantContext.logMsg(null), ex);
314  }
315  }
316  if(onlyTitle) {
317  sb.append(sep); sep = "&";
318  sb.append("only-title=true");
319  }
320  if(dossierId != null && dossierId > 0) {
321  sb.append(sep); sep = "&";
322  sb.append("dossier-id=" + dossierId);
323  }
324  if(type != null && !type.isEmpty()) {
325  sb.append(sep); sep = "&";
326  sb.append("type=");
327  sb.append(CollectionUtil.from(type).getCSV(t -> t.toString()));
328  }
329  if(status != null && !status.isEmpty()) {
330  sb.append(sep); sep = "&";
331  sb.append("status=");
332  sb.append(CollectionUtil.from(status).getCSV(t -> t.toString()));
333  }
334  if(resolution != null && !resolution.isEmpty()) {
335  sb.append(sep); sep = "&";
336  sb.append("resolution=");
337  sb.append(CollectionUtil.from(resolution).getCSV(t -> t.toString()));
338  }
339  return sb.toString();
340  }
341 
342  public static String createLink(Issue issue) {
343  StringBuilder sb = new StringBuilder();
344  String sep = "?";
345  sb.append("/user/kbase");
346  if(issue != null) {
347  sb.append(sep); sep = "&";
348  sb.append(MarkerHelper.setObfuscatedPars("item=" + issue.getId()));
349  }
350  return sb.toString();
351  }
352 }
IssueResolution getResolution()
Definition: Issue.java:226
void setResolutions(Set< IssueResolution > resolutions)
void setByParticipant(IContact byParticipant)
void setStatus(Set< IssueStatus > status)
static String addInformation(String issueId, String link, String template)
static String createLink(String searchValue, boolean onlyTitle, Set< IssueType > type, Set< IssueStatus > status, Set< IssueResolution > resolution, Long dossierId)
static AttributeItem getFromParameter(IConstructor constructor, String name, String defaultValue)
static IElephantEntity getController(String path)
Definition: Entities.java:78
void process(String rootTmpl, String tmpl)
Object put(Object key, Object value)
static KeyValueMap getObfuscatedParameters()
static String setObfuscatedPars(String parameters)