19 package org.turro.dossier.www;
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.Date;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27 import javax.servlet.ServletContext;
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
30 import org.turro.string.Strings;
31 import org.apache.commons.fileupload.FileItemIterator;
32 import org.apache.commons.fileupload.FileItemStream;
33 import org.apache.commons.fileupload.FileUploadException;
34 import org.apache.commons.fileupload.servlet.ServletFileUpload;
35 import org.apache.commons.fileupload.util.Streams;
36 import org.apache.commons.lang3.math.NumberUtils;
37 import org.turro.attach.db.AttachPU;
38 import org.turro.attach.entity.AttachContent;
39 import org.turro.attach.entity.Attachment;
40 import org.turro.auth.Authentication;
41 import org.turro.contacts.Contact;
42 import org.turro.describeit.DescribeItUtil;
43 import org.turro.dossier.db.DossierPU;
44 import org.turro.dossier.dossier.ProjectContext;
45 import org.turro.dossier.dw.DossierDWReport;
46 import org.turro.dossier.entity.Dossier;
47 import org.turro.dossier.entity.Issue;
48 import org.turro.dossier.entity.IssueComment;
49 import org.turro.dossier.entity.IssueParticipant;
50 import org.turro.dossier.entity.IssuePriority;
51 import org.turro.dossier.entity.IssueResolution;
52 import org.turro.dossier.entity.IssueType;
53 import org.turro.dossier.issue.IssueMail;
54 import org.turro.dossier.issue.IssueWrapper;
55 import org.turro.dossier.project.AbstractDossierNotification;
56 import org.turro.dossier.search.DossierResults;
57 import org.turro.elephant.context.Application;
58 import org.turro.elephant.context.ElephantContext;
59 import org.turro.elephant.context.IConstructor;
60 import org.turro.elephant.direct.DirectContent;
61 import org.turro.elephant.direct.DirectContents;
62 import org.turro.elephant.direct.IDirectContent;
63 import org.turro.html.HTMLEntities;
64 import org.turro.i18n.I_;
65 import org.turro.jpa.Dao;
66 import org.turro.log.SystemLogType;
67 import org.turro.log.SystemLogger;
68 import org.turro.marker.ElephantMarker;
69 import org.turro.plugin.contacts.IContact;
70 import org.turro.registry.ChangeCategory;
71 import org.turro.registry.Changes;
72 import org.turro.registry.EnumChange;
73 import org.turro.registry.StringChange;
74 import org.turro.registry.UniqueString;
80 @DirectContent(identifier=
"issue-create")
85 return "/user/newissue?dossierId=" + dossierId;
88 public static String
createIssue(String link, String dossierId, String
template) {
90 if(constructor.
isInRole(
"issue:edit")) {
94 marker.
put(
"redirect", link);
95 if(Long.valueOf(dossierId) > 0) {
96 marker.
put(
"dossierId", dossierId);
103 return marker.
parse(
"issue", Strings.isBlank(
template) ?
"create" :
template);
114 return getIdentifier().equals(
id);
118 public boolean myTurn(HttpServletRequest request) {
123 public void execute(ServletContext context, HttpServletRequest request, HttpServletResponse response) {
124 if(ServletFileUpload.isMultipartContent(request)) {
126 processInformation(request, response);
127 }
catch (FileUploadException | IOException ex) {
133 private void processInformation(HttpServletRequest request, HttpServletResponse response)
throws FileUploadException, IOException {
138 if(contact ==
null || !contact.
isValid()) {
141 Changes changes =
new Changes();
142 ChangeCategory issueCat =
new ChangeCategory(2, I_.get(
"Changes"));
143 ChangeCategory attachCat =
new ChangeCategory(3, I_.get(
"Attachments"));
144 ChangeCategory commentCat =
new ChangeCategory(5, I_.get(
"Comment"));
145 Long dossierId =
null;
146 String redirect =
null, comment =
null, description =
null, webDefault =
null, grouping =
null;
147 Double hours = 0.0d, expenses = 0.0d, price = 0.0d;
148 IssuePriority priority =
null;
149 IssueType type =
null;
150 Boolean cancelEmails =
false, responsibleIsReporter =
false;
151 ServletFileUpload upload =
new ServletFileUpload();
152 upload.setHeaderEncoding(ElephantContext.getEncoding());
153 FileItemIterator iter = upload.getItemIterator(request);
154 while(iter.hasNext()) {
155 FileItemStream item = iter.next();
156 String name = item.getFieldName();
157 InputStream stream = item.openStream();
158 if(item.isFormField()) {
161 dossierId = Long.valueOf(Streams.asString(stream));
163 Dossier dossier = dao.find(Dossier.class, dossierId);
170 redirect = Streams.asString(stream, ElephantContext.getEncoding());
173 description = Streams.asString(stream, ElephantContext.getEncoding());
174 if(!Strings.isBlank(description)) {
175 description = HTMLEntities.plainWhenPossible(description);
176 changes.addChange(
new StringChange(issueCat, I_.get(
"Description"),
182 comment = Streams.asString(stream, ElephantContext.getEncoding());
183 if(!Strings.isBlank(comment)) {
184 comment = HTMLEntities.plainWhenPossible(comment);
185 changes.addComment(commentCat, comment);
189 String p = Streams.asString(stream, ElephantContext.getEncoding());
191 priority = IssuePriority.PRIORITY_CANT_CONTINUE;
192 }
else if(
"p2".equals(p)) {
193 priority = IssuePriority.PRIORITY_WORKAROUND_IMPRACTICAL;
194 }
else if(
"p3".equals(p)) {
195 priority = IssuePriority.PRIORITY_HAS_WORKAROUND;
196 }
else if(
"p4".equals(p)) {
197 priority = IssuePriority.PRIORITY_WRONG_BEHAVIOR;
198 }
else if(
"p5".equals(p)) {
199 priority = IssuePriority.PRIORITY_CAUSE_UNEASE;
201 if(priority !=
null) {
202 changes.addChange(
new EnumChange(issueCat, I_.get(
"Priority"),
203 IssuePriority.PRIORITY_HAS_WORKAROUND, priority));
208 String t = Streams.asString(stream, ElephantContext.getEncoding());
209 if(
"task".equals(t)) {
210 type = IssueType.TYPE_TASK;
211 }
else if(
"defect".equals(t)) {
212 type = IssueType.TYPE_DEFECT;
213 }
else if(
"enhancement".equals(t)) {
214 type = IssueType.TYPE_ENHANCEMENT;
215 }
else if(
"prevention".equals(t)) {
216 type = IssueType.TYPE_PREVENTION;
217 }
else if(
"feature".equals(t)) {
218 type = IssueType.TYPE_FEATURE;
219 }
else if(
"document".equals(t)) {
220 type = IssueType.TYPE_DOCUMENT;
221 }
else if(
"patch".equals(t)) {
222 type = IssueType.TYPE_PATCH;
223 }
else if(
"question".equals(t)) {
224 type = IssueType.TYPE_QUESTION;
225 }
else if(
"nonconformity".equals(t)) {
226 type = IssueType.TYPE_NONCONFORMITY;
227 }
else if(
"bestpractice".equals(t)) {
228 type = IssueType.TYPE_BESTPRACTICE;
229 }
else if(
"process".equals(t)) {
230 type = IssueType.TYPE_PROCESS;
231 }
else if(
"proposition".equals(t)) {
232 type = IssueType.TYPE_PROPOSITION;
235 changes.addChange(
new EnumChange(issueCat, I_.get(
"Type"),
236 IssueType.TYPE_TASK, type));
241 grouping = Streams.asString(stream, ElephantContext.getEncoding());
242 if(!Strings.isBlank(grouping)) {
243 changes.addChange(
new StringChange(issueCat, I_.get(
"Grouping"),
249 expenses = NumberUtils.toDouble(Streams.asString(stream), 0);
252 hours = NumberUtils.toDouble(Streams.asString(stream), 0);
255 price = NumberUtils.toDouble(Streams.asString(stream), 0);
258 webDefault = Streams.asString(stream, ElephantContext.getEncoding());
261 cancelEmails = Boolean.parseBoolean(Streams.asString(stream, ElephantContext.getEncoding()));
263 case "responsibleIsReporter":
264 responsibleIsReporter = Boolean.parseBoolean(Streams.asString(stream, ElephantContext.getEncoding()));
267 }
else if(issue !=
null && !Strings.isBlank(issue.
getDescription())) {
271 issue = checkSave(constructor, dao, changes, issue, issueCat, responsibleIsReporter);
272 Attachment attachment =
new Attachment();
274 attachment.setPath(
"/issue/" + issue.
getId());
275 attachment.setOwner(contact.
getId());
276 attachment.setOnlyOwner(
false);
277 attachment.setComment(
"");
278 attachment.setShowKey(
null);
279 attachment.setPublishable(
true);
280 AttachContent ac =
new AttachContent();
281 ByteArrayOutputStream baos =
new ByteArrayOutputStream();
282 Streams.copy(item.openStream(), baos,
true);
283 ac.setFileContent(baos.toByteArray());
284 attachment.setAttachContent(ac);
285 attachment.setFileName(convertToFileName(item.getName()));
286 attachment.setFileContentType(item.getContentType());
287 attachment.setFileSize(ac.getFileContent().length);
288 attachment.setValidated(Application.getApplication().isInRole(
"attach:self-validate"));
289 if(attachment.getFileSize() > 0) {
290 attachment =
new AttachPU().saveObject(attachment);
291 SystemLogger.getInstance().doLog(SystemLogType.LOG_INFO, attachment,
"uploaded",
null);
292 changes.addChange(
new StringChange(attachCat, I_.get(
"Upload"), attachment.getFileName(),
null,
true));
296 changes.clearEquals();
297 if(changes.stringSize() > 0) {
299 IssueComment ic =
new IssueComment();
302 ic.setIContact(Authentication.getIContact());
303 ic.setComment(changes.getChangesString());
305 issue = checkSave(constructor, dao, changes, issue, issueCat, responsibleIsReporter);
306 SystemLogger.getInstance().doLog(SystemLogType.LOG_INFO, issue,
"saved",
309 AbstractDossierNotification notif = AbstractDossierNotification.getByGrouping(issue);
311 new IssueMail(changes, issue, 0, 0, 0).sendMail();
313 notif.sendNotification();
316 if(!Strings.isBlank(webDefault)) {
317 DescribeItUtil.addDescription(issue, DescribeItUtil.DEFAULT_ID, webDefault, (Contact) contact.
getContact(),
null);
321 if(!Strings.isBlank(redirect)) {
322 constructor.
redirect(redirect.replaceAll(
"\\#ID", issue.
getId() +
""));
326 private String convertToFileName(String fileName) {
327 if(fileName.contains(
"/")) {
328 fileName = fileName.substring(fileName.lastIndexOf(
"/") + 1);
333 private Issue checkSave(IConstructor constructor, Dao dao, Changes changes, Issue issue, ChangeCategory issueCat,
334 Boolean responsibleIsReporter) {
335 if(issue.getId() ==
null) {
336 changes.addChange(
new StringChange(issueCat, I_.get(
"Dossier"),
337 "", issue.getDossier() !=
null ? issue.getDossier().getDescription() :
""));
338 ChangeCategory cc =
new ChangeCategory(4, I_.get(
"Participants"));
339 IContact responsible = issue.getDossier().getDefaultResponsible();
340 IContact reporter = Authentication.getIContact();
341 if(responsible ==
null || !responsible.isWebUser()) {
342 responsible = reporter;
344 IssueParticipant ip = issue.addReporter(responsibleIsReporter ? responsible : reporter);
345 changes.addChange(
new UniqueString(cc, I_.byKey(ip.getRole().toString()), ip.getName(),
true));
346 ip = issue.addResponsible(responsible);
347 changes.addChange(
new UniqueString(cc, I_.byKey(ip.getRole().toString()), ip.getName(),
true));
348 issue.setResolution(IssueResolution.RESOLUTION_NONE);
349 if(Strings.isBlank(issue.getDescription())) {
350 issue.setDescription(
"********");
353 IssueWrapper iw =
new IssueWrapper(issue);
355 issue = dao.saveObject(issue);
static IContact getIContact()
void setReportValues(Dossier dossier)
void setType(IssueType type)
void setDescription(String description)
static Issue getDefaultIssue()
void setModification(Date modification)
void setDossier(Dossier dossier)
void setPriority(IssuePriority priority)
Set< IssueComment > getComments()
void setHours(double hours)
void setGrouping(String grouping)
void setPrice(double price)
void setExpenses(double expenses)
boolean myTurn(HttpServletRequest request)
static String createIssue(String link, String dossierId, String template)
static String getIdentifier()
void execute(ServletContext context, HttpServletRequest request, HttpServletResponse response)
static String linkToCreateIssue(String link, String dossierId, String template)
IConstructor getConstructor()
static Application getApplication()
static String logMsg(String msg)
static boolean isYourTurn(HttpServletRequest request, String path)
static String createRelativeURL(String id)
String parse(String rootTmpl, String tmpl)
Object put(Object key, Object value)
void redirect(String path)
boolean isInRole(String role)