001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package info.jtrac.util;
018:
019: import info.jtrac.domain.Attachment;
020: import info.jtrac.domain.Field;
021: import info.jtrac.domain.History;
022: import info.jtrac.domain.Item;
023: import info.jtrac.domain.ItemItem;
024: import java.io.BufferedReader;
025: import java.io.StringReader;
026: import java.util.List;
027: import java.util.Locale;
028: import java.util.Map;
029: import java.util.Set;
030: import javax.servlet.http.HttpServletRequest;
031: import javax.servlet.http.HttpServletResponse;
032: import org.dom4j.Document;
033: import org.dom4j.Element;
034: import org.springframework.context.MessageSource;
035: import org.springframework.web.servlet.support.RequestContextUtils;
036: import org.springframework.web.util.HtmlUtils;
037:
038: /**
039: * Utilities to convert an Item into HTML etc.
040: * The getAsHtml() routine is used to diplay an item - within a tag lib for JSP
041: * And we are able to re-use this to send HTML e-mail etc.
042: */
043: public final class ItemUtils {
044:
045: /**
046: * does HTML escaping, converts tabs to spaces and converts leading
047: * spaces (for each multi-line) to as many ' ' sequences as required
048: */
049: public static String fixWhiteSpace(String text) {
050: if (text == null) {
051: return "";
052: }
053: String temp = HtmlUtils.htmlEscape(text);
054: BufferedReader reader = new BufferedReader(new StringReader(
055: temp));
056: StringBuilder sb = new StringBuilder();
057: String s;
058: boolean first = true;
059: try {
060: while ((s = reader.readLine()) != null) {
061: if (first) {
062: first = false;
063: } else {
064: sb.append("<br/>");
065: }
066: if (s.startsWith(" ")) {
067: int i;
068: for (i = 0; i < s.length(); i++) {
069: if (s.charAt(i) == ' ') {
070: sb.append(" ");
071: } else {
072: break;
073: }
074: }
075: s = s.substring(i);
076: }
077: sb.append(s);
078: }
079: } catch (Exception e) {
080: throw new RuntimeException(e);
081: }
082: return sb.toString().replaceAll("\t",
083: " ");
084: }
085:
086: private static String fmt(String key, MessageSource messageSource,
087: Locale locale) {
088: try {
089: return messageSource.getMessage("item_view." + key, null,
090: locale);
091: } catch (Exception e) {
092: return "???item_view." + key + "???";
093: }
094: }
095:
096: public static String getAsHtml(Item item,
097: MessageSource messageSource, Locale locale) {
098: return getAsHtml(item, null, null, messageSource, locale);
099: }
100:
101: public static String getAsHtml(Item item,
102: HttpServletRequest request, HttpServletResponse response) {
103: Locale locale = RequestContextUtils.getLocale(request);
104: MessageSource messageSource = RequestContextUtils
105: .getWebApplicationContext(request);
106: return getAsHtml(item, request, response, messageSource, locale);
107: }
108:
109: private static String getAsHtml(Item item,
110: HttpServletRequest request, HttpServletResponse response,
111: MessageSource ms, Locale loc) {
112:
113: boolean isWeb = request != null && response != null;
114:
115: String tableStyle = " class='jtrac'";
116: String tdStyle = "";
117: String thStyle = "";
118: String altStyle = " class='alt'";
119: String labelStyle = " class='label'";
120:
121: if (!isWeb) {
122: // inline CSS so that HTML mail works across most mail-reader clients
123: String tdCommonStyle = "border: 1px solid black";
124: tableStyle = " class='jtrac' style='border-collapse: collapse; font-family: Arial; font-size: 75%'";
125: tdStyle = " style='" + tdCommonStyle + "'";
126: thStyle = " style='" + tdCommonStyle
127: + "; background: #CCCCCC'";
128: altStyle = " style='background: #e1ecfe'";
129: labelStyle = " style='"
130: + tdCommonStyle
131: + "; background: #CCCCCC; font-weight: bold; text-align: right'";
132: }
133:
134: StringBuffer sb = new StringBuffer();
135: sb.append("<table width='100%'" + tableStyle + ">");
136: sb.append("<tr" + altStyle + ">");
137: sb.append(" <td" + labelStyle + ">" + fmt("id", ms, loc)
138: + "</td>");
139: sb.append(" <td" + tdStyle + ">" + item.getRefId() + "</td>");
140: sb.append(" <td" + labelStyle + ">"
141: + fmt("relatedItems", ms, loc) + "</td>");
142: sb.append(" <td colspan='3'" + tdStyle + ">");
143: if (item.getRelatedItems() != null
144: || item.getRelatingItems() != null) {
145: String flowUrlParam = null;
146: String flowUrl = null;
147: if (isWeb) {
148: flowUrlParam = "_flowExecutionKey="
149: + request.getAttribute("flowExecutionKey");
150: flowUrl = "/flow?" + flowUrlParam;
151: }
152: if (item.getRelatedItems() != null) {
153: // ItemViewForm itemViewForm = null;
154: if (isWeb) {
155: // itemViewForm = (ItemViewForm) request.getAttribute("itemViewForm");
156: sb
157: .append("<input type='hidden' name='_removeRelated'/>");
158: }
159: for (ItemItem itemItem : item.getRelatedItems()) {
160: String refId = itemItem.getRelatedItem().getRefId();
161: if (isWeb) {
162: String checked = "";
163: Set<Long> set = null; // itemViewForm.getRemoveRelated();
164: if (set != null
165: && set.contains(itemItem.getId())) {
166: checked = " checked='true'";
167: }
168: String url = flowUrl
169: + "&_eventId=viewRelated&itemId="
170: + itemItem.getRelatedItem().getId();
171: refId = "<a href='"
172: + response.encodeURL(request
173: .getContextPath()
174: + url)
175: + "'>"
176: + refId
177: + "</a>"
178: + "<input type='checkbox' name='removeRelated' value='"
179: + itemItem.getId() + "' title='"
180: + fmt("remove", ms, loc) + "'"
181: + checked + "/>";
182: }
183: sb.append(fmt(itemItem.getRelationText(), ms, loc)
184: + " " + refId + " ");
185: }
186: }
187: if (item.getRelatingItems() != null) {
188: for (ItemItem itemItem : item.getRelatingItems()) {
189: String refId = itemItem.getItem().getRefId();
190: if (isWeb) {
191: String url = flowUrl
192: + "&_eventId=viewRelated&itemId="
193: + itemItem.getItem().getId();
194: refId = "<a href='"
195: + response.encodeURL(request
196: .getContextPath()
197: + url) + "'>" + refId + "</a>";
198: }
199: sb.append(refId
200: + " "
201: + fmt(itemItem.getRelationText() + "This",
202: ms, loc) + ". ");
203: }
204: }
205: }
206: sb.append(" </td>");
207: sb.append("</tr>");
208: sb.append("<tr>");
209: sb.append(" <td width='15%'" + labelStyle + ">"
210: + fmt("status", ms, loc) + "</td>");
211: sb.append(" <td" + tdStyle + ">" + item.getStatusValue()
212: + "</td>");
213: sb.append(" <td" + labelStyle + ">" + fmt("loggedBy", ms, loc)
214: + "</td>");
215: sb.append(" <td" + tdStyle + ">"
216: + item.getLoggedBy().getName() + "</td>");
217: sb.append(" <td" + labelStyle + ">"
218: + fmt("assignedTo", ms, loc) + "</td>");
219: sb.append(" <td width='15%'"
220: + tdStyle
221: + ">"
222: + (item.getAssignedTo() == null ? "" : item
223: .getAssignedTo().getName()) + "</td>");
224: sb.append("</tr>");
225: sb.append("<tr" + altStyle + ">");
226: sb.append(" <td" + labelStyle + ">" + fmt("summary", ms, loc)
227: + "</td>");
228: sb.append(" <td colspan='5'" + tdStyle + ">"
229: + HtmlUtils.htmlEscape(item.getSummary()) + "</td>");
230: sb.append("</tr>");
231: sb.append("<tr>");
232: sb.append(" <td valign='top'" + labelStyle + ">"
233: + fmt("detail", ms, loc) + "</td>");
234: sb.append(" <td colspan='5'" + tdStyle + ">"
235: + fixWhiteSpace(item.getDetail()) + "</td>");
236: sb.append("</tr>");
237:
238: int row = 0;
239: Map<Field.Name, Field> fields = item.getSpace().getMetadata()
240: .getFields();
241: for (Field.Name fieldName : item.getSpace().getMetadata()
242: .getFieldOrder()) {
243: Field field = fields.get(fieldName);
244: sb.append("<tr" + (row % 2 == 0 ? altStyle : "") + ">");
245: sb.append(" <td" + labelStyle + ">" + field.getLabel()
246: + "</td>");
247: sb.append(" <td colspan='5'" + tdStyle + ">"
248: + item.getCustomValue(fieldName) + "</td>");
249: sb.append("</tr>");
250: row++;
251: }
252: sb.append("</table>");
253:
254: //=========================== HISTORY ==================================
255: sb.append("<br/> <b" + tableStyle + ">"
256: + fmt("history", ms, loc) + "</b>");
257: sb.append("<table width='100%'" + tableStyle + ">");
258: sb.append("<tr>");
259: sb.append(" <th" + thStyle + ">" + fmt("loggedBy", ms, loc)
260: + "</th><th" + thStyle + ">" + fmt("status", ms, loc)
261: + "</th>" + "<th" + thStyle + ">"
262: + fmt("assignedTo", ms, loc) + "</th><th" + thStyle
263: + ">" + fmt("comment", ms, loc) + "</th><th" + thStyle
264: + ">" + fmt("timeStamp", ms, loc) + "</th>");
265: List<Field> editable = item.getSpace().getMetadata()
266: .getEditableFields();
267: for (Field field : editable) {
268: sb.append("<th" + thStyle + ">" + field.getLabel()
269: + "</th>");
270: }
271: sb.append("</tr>");
272:
273: if (item.getHistory() != null) {
274: row = 1;
275: for (History history : item.getHistory()) {
276: sb.append("<tr valign='top'"
277: + (row % 2 == 0 ? altStyle : "") + ">");
278: sb.append(" <td" + tdStyle + ">"
279: + history.getLoggedBy().getName() + "</td>");
280: sb.append(" <td" + tdStyle + ">"
281: + history.getStatusValue() + "</td>");
282: sb.append(" <td"
283: + tdStyle
284: + ">"
285: + (history.getAssignedTo() == null ? ""
286: : history.getAssignedTo().getName())
287: + "</td>");
288: sb.append(" <td" + tdStyle + ">");
289: Attachment attachment = history.getAttachment();
290: if (attachment != null) {
291: if (request != null && response != null) {
292: String href = response.encodeURL(request
293: .getContextPath()
294: + "/app/attachments/"
295: + attachment.getFileName()
296: + "?filePrefix="
297: + attachment.getFilePrefix());
298: sb.append("<a target='_blank' href='" + href
299: + "'>" + attachment.getFileName()
300: + "</a> ");
301: } else {
302: sb.append("(attachment: "
303: + attachment.getFileName() + ") ");
304: }
305: }
306: sb.append(fixWhiteSpace(history.getComment()));
307: sb.append(" </td>");
308: sb.append(" <td" + tdStyle + ">"
309: + history.getTimeStamp() + "</td>");
310: for (Field field : editable) {
311: sb.append("<td" + tdStyle + ">"
312: + history.getCustomValue(field.getName())
313: + "</td>");
314: }
315: sb.append("</tr>");
316: row++;
317: }
318: }
319: sb.append("</table>");
320: return sb.toString();
321: }
322:
323: public static Document getAsXml(Item item) {
324: Document d = XmlUtils.getNewDocument("item");
325: Element root = d.getRootElement();
326: root.addAttribute("refId", item.getRefId());
327: if (item.getRelatedItems() != null
328: && item.getRelatedItems().size() > 0) {
329: Element relatedItems = root.addElement("relatedItems");
330: for (ItemItem itemItem : item.getRelatedItems()) {
331: Element relatedItem = relatedItems
332: .addElement("relatedItem");
333: relatedItem.addAttribute("refId", itemItem.getItem()
334: .getRefId());
335: }
336: }
337: if (item.getRelatingItems() != null
338: && item.getRelatingItems().size() > 0) {
339: Element relatingItems = root.addElement("relatingItems");
340: for (ItemItem itemItem : item.getRelatingItems()) {
341: Element relatingItem = relatingItems
342: .addElement("relatingItem");
343: relatingItem.addAttribute("refId", itemItem.getItem()
344: .getRefId());
345: }
346: }
347: if (item.getSummary() != null) {
348: root.addElement("summary").addText(item.getSummary());
349: }
350: if (item.getDetail() != null) {
351: root.addElement("detail").addText(item.getDetail());
352: }
353: Element loggedBy = root.addElement("loggedBy");
354: loggedBy
355: .addAttribute("userId", item.getLoggedBy().getId() + "");
356: loggedBy.addText(item.getLoggedBy().getName());
357: if (item.getAssignedTo() != null) {
358: Element assignedTo = root.addElement("assignedTo");
359: assignedTo.addAttribute("userId", item.getAssignedTo()
360: .getId()
361: + "");
362: assignedTo.addText(item.getAssignedTo().getName());
363: }
364: return d;
365: }
366:
367: }
|