001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
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: package org.outerj.daisy.tools.importexport.export;
017:
018: import org.outerj.daisy.tools.importexport.model.ImpExpVariantKey;
019: import org.outerj.daisy.linkextraction.LinkType;
020: import org.xml.sax.ContentHandler;
021: import org.xml.sax.SAXException;
022: import org.xml.sax.helpers.AttributesImpl;
023:
024: import java.util.*;
025: import java.io.StringWriter;
026: import java.io.PrintWriter;
027:
028: /**
029: * Provides some base functionality that is likely useful for
030: * different ExportListener implementations.
031: */
032: public abstract class BaseExportListener implements ExportListener {
033: private List<FailureInfo> failed = new ArrayList<FailureInfo>();
034: private List<ImpExpVariantKey> succeeded = new ArrayList<ImpExpVariantKey>();
035: private List<ImpExpVariantKey> skippedBecauseRetired = new ArrayList<ImpExpVariantKey>();
036: private List<ImpExpVariantKey> skippedBecauseNoLiveVersion = new ArrayList<ImpExpVariantKey>();
037: private Set<ImpExpVariantKey> links = new HashSet<ImpExpVariantKey>();
038: private List<ImpExpVariantKey> brokenLinks;
039: private List<ItemFailureInfo> failedItems = new ArrayList<ItemFailureInfo>();
040:
041: public void failed(ImpExpVariantKey variantKey, Throwable e)
042: throws Exception {
043: String errorDescription = getThrowableDescription(e);
044: String stackTrace = getStackTrace(e);
045:
046: failed.add(new FailureInfo(variantKey, errorDescription,
047: stackTrace));
048: }
049:
050: private String getThrowableDescription(Throwable e) {
051: StringBuilder errorDescription = new StringBuilder(200);
052: Throwable current = e;
053: do {
054: if (errorDescription.length() > 0)
055: errorDescription.append(" --> ");
056: errorDescription.append(current.getMessage());
057: current = current.getCause();
058: } while (current != null);
059:
060: return errorDescription.toString();
061: }
062:
063: private String getStackTrace(Throwable e) {
064: String stackTrace;
065: if (includeFullStackTracesOfFailures()) {
066: StringWriter exceptionWriter = new StringWriter();
067: e.printStackTrace(new PrintWriter(exceptionWriter));
068: stackTrace = exceptionWriter.toString();
069: } else {
070: stackTrace = getStackTraceDisabledMessage();
071: }
072: return stackTrace;
073: }
074:
075: protected abstract boolean includeFullStackTracesOfFailures();
076:
077: protected abstract String getStackTraceDisabledMessage();
078:
079: public void success(ImpExpVariantKey variantKey) {
080: succeeded.add(variantKey);
081: }
082:
083: public void skippedBecauseRetired(ImpExpVariantKey variantKey) {
084: skippedBecauseRetired.add(variantKey);
085: }
086:
087: public void skippedBecauseNoLiveVersion(ImpExpVariantKey variantKey) {
088: skippedBecauseNoLiveVersion.add(variantKey);
089: }
090:
091: public void hasLink(ImpExpVariantKey sourceVariantKeyk,
092: ImpExpVariantKey targetVariantKey, LinkType linkType) {
093: links.add(targetVariantKey);
094: }
095:
096: public Set<ImpExpVariantKey> getLinks() {
097: return links;
098: }
099:
100: public List<ImpExpVariantKey> getSucceeded() {
101: return succeeded;
102: }
103:
104: public List<FailureInfo> getFailed() {
105: return failed;
106: }
107:
108: public List<ImpExpVariantKey> getSkippedBecauseRetired() {
109: return skippedBecauseRetired;
110: }
111:
112: public List<ImpExpVariantKey> getSkippedBecauseNoLiveVersion() {
113: return skippedBecauseNoLiveVersion;
114: }
115:
116: public static class FailureInfo {
117: private final ImpExpVariantKey variantKey;
118: private final String errorDescription;
119: private final String stackTrace;
120:
121: public FailureInfo(ImpExpVariantKey variantKey,
122: String errorDescription, String stackTrace) {
123: this .variantKey = variantKey;
124: this .errorDescription = errorDescription;
125: this .stackTrace = stackTrace;
126: }
127:
128: public ImpExpVariantKey getVariantKey() {
129: return variantKey;
130: }
131:
132: public String getErrorDescription() {
133: return errorDescription;
134: }
135:
136: public String getStackTrace() {
137: return stackTrace;
138: }
139: }
140:
141: /**
142: * Failure info for non-documents.
143: */
144: public static class ItemFailureInfo {
145: private final String type;
146: private final String name;
147: private final String errorDescription;
148: private final String stackTrace;
149:
150: public ItemFailureInfo(String type, String name,
151: String errorDescription, String stackTrace) {
152: this .type = type;
153: this .name = name;
154: this .errorDescription = errorDescription;
155: this .stackTrace = stackTrace;
156: }
157:
158: public String getType() {
159: return type;
160: }
161:
162: public String getName() {
163: return name;
164: }
165:
166: public String getErrorDescription() {
167: return errorDescription;
168: }
169:
170: public String getStackTrace() {
171: return stackTrace;
172: }
173: }
174:
175: /**
176: * Gets list of broken links. The broken links are determined the first
177: * time this method is called.
178: */
179: public List getBrokenLinks() {
180: if (brokenLinks != null)
181: return brokenLinks;
182:
183: Set<ImpExpVariantKey> succeededHash = new HashSet<ImpExpVariantKey>(
184: getSucceeded());
185: Set<ImpExpVariantKey> retiredHash = new HashSet<ImpExpVariantKey>(
186: getSkippedBecauseRetired());
187: List<ImpExpVariantKey> list = new ArrayList<ImpExpVariantKey>();
188:
189: for (ImpExpVariantKey variantKey : getLinks()) {
190: if (!succeededHash.contains(variantKey)
191: && !retiredHash.contains(variantKey)) {
192: list.add(variantKey);
193: }
194: }
195:
196: this .brokenLinks = list;
197: return list;
198: }
199:
200: public void failedItem(String itemType, String itemName, Throwable e) {
201: String errorDescription = getThrowableDescription(e);
202: String stackTrace = getStackTrace(e);
203:
204: failedItems.add(new ItemFailureInfo(itemType, itemName,
205: errorDescription, stackTrace));
206: }
207:
208: public List<ItemFailureInfo> getFailedItems() {
209: return Collections.unmodifiableList(failedItems);
210: }
211:
212: public void generateSax(ContentHandler contentHandler)
213: throws SAXException {
214: contentHandler.startDocument();
215: contentHandler.startElement("", EXPORT_RESULT_EL,
216: EXPORT_RESULT_EL, new AttributesImpl());
217:
218: if (skippedBecauseRetired.size() > 0) {
219: contentHandler.startElement("", SKIPPED_BECAUSE_RETIRED_EL,
220: SKIPPED_BECAUSE_RETIRED_EL, new AttributesImpl());
221:
222: Iterator it = skippedBecauseRetired.iterator();
223: org.xml.sax.helpers.AttributesImpl attrs = new org.xml.sax.helpers.AttributesImpl();
224: while (it.hasNext()) {
225: ImpExpVariantKey variantKey = (ImpExpVariantKey) it
226: .next();
227: attrs.clear();
228: attrs.addAttribute("", ID_ATTR, ID_ATTR, "CDATA",
229: variantKey.getDocumentId());
230: attrs.addAttribute("", BRANCH_ATTR, BRANCH_ATTR,
231: "CDATA", variantKey.getBranch());
232: attrs.addAttribute("", LANG_ATTR, LANG_ATTR, "CDATA",
233: variantKey.getLanguage());
234: contentHandler.startElement("", DOCUMENT_EL,
235: DOCUMENT_EL, attrs);
236: contentHandler.endElement("", DOCUMENT_EL, DOCUMENT_EL);
237: }
238: contentHandler.endElement("", SKIPPED_BECAUSE_RETIRED_EL,
239: SKIPPED_BECAUSE_RETIRED_EL);
240: }
241:
242: if (skippedBecauseNoLiveVersion.size() > 0) {
243: contentHandler.startElement("",
244: SKIPPED_BECAUSE_NO_LIVE_VERSION_EL,
245: SKIPPED_BECAUSE_NO_LIVE_VERSION_EL,
246: new AttributesImpl());
247:
248: Iterator it = skippedBecauseNoLiveVersion.iterator();
249: org.xml.sax.helpers.AttributesImpl attrs = new org.xml.sax.helpers.AttributesImpl();
250: while (it.hasNext()) {
251: ImpExpVariantKey variantKey = (ImpExpVariantKey) it
252: .next();
253: attrs.clear();
254: attrs.addAttribute("", ID_ATTR, ID_ATTR, "CDATA",
255: variantKey.getDocumentId());
256: attrs.addAttribute("", BRANCH_ATTR, BRANCH_ATTR,
257: "CDATA", variantKey.getBranch());
258: attrs.addAttribute("", LANG_ATTR, LANG_ATTR, "CDATA",
259: variantKey.getLanguage());
260: contentHandler.startElement("", DOCUMENT_EL,
261: DOCUMENT_EL, attrs);
262: contentHandler.endElement("", DOCUMENT_EL, DOCUMENT_EL);
263: }
264: contentHandler.endElement("",
265: SKIPPED_BECAUSE_NO_LIVE_VERSION_EL,
266: SKIPPED_BECAUSE_NO_LIVE_VERSION_EL);
267: }
268:
269: if (failed.size() > 0) {
270: contentHandler.startElement("", FAILURES_EL, FAILURES_EL,
271: new AttributesImpl());
272:
273: Iterator it = failed.iterator();
274: AttributesImpl attrs = new AttributesImpl();
275: while (it.hasNext()) {
276: FailureInfo failureInfo = (FailureInfo) it.next();
277: attrs.clear();
278: attrs.addAttribute("", ID_ATTR, ID_ATTR, "CDATA",
279: failureInfo.getVariantKey().getDocumentId());
280: attrs.addAttribute("", BRANCH_ATTR, BRANCH_ATTR,
281: "CDATA", failureInfo.getVariantKey()
282: .getBranch());
283: attrs.addAttribute("", LANG_ATTR, LANG_ATTR, "CDATA",
284: failureInfo.getVariantKey().getLanguage());
285: contentHandler.startElement("", DOCUMENT_EL,
286: DOCUMENT_EL, attrs);
287:
288: contentHandler.startElement("", "description",
289: "description", new AttributesImpl());
290: contentHandler.characters(failureInfo
291: .getErrorDescription().toCharArray(), 0,
292: failureInfo.getErrorDescription().length());
293: contentHandler.endElement("", "description",
294: "description");
295:
296: contentHandler.startElement("", "stackTrace",
297: "stackTrace", new AttributesImpl());
298: contentHandler.characters(failureInfo.getStackTrace()
299: .toCharArray(), 0, failureInfo.getStackTrace()
300: .length());
301: contentHandler.endElement("", "stackTrace",
302: "stackTrace");
303:
304: contentHandler.endElement("", DOCUMENT_EL, DOCUMENT_EL);
305: }
306: contentHandler.endElement("", FAILURES_EL, FAILURES_EL);
307: }
308:
309: getBrokenLinks(); // to make sure they are determined
310: if (brokenLinks.size() > 0) {
311: contentHandler.startElement("", BROKENLINK_EL,
312: BROKENLINK_EL, new AttributesImpl());
313:
314: Iterator it = brokenLinks.iterator();
315: org.xml.sax.helpers.AttributesImpl attrs = new org.xml.sax.helpers.AttributesImpl();
316: while (it.hasNext()) {
317: ImpExpVariantKey variantKey = (ImpExpVariantKey) it
318: .next();
319: attrs.clear();
320: attrs.addAttribute("", ID_ATTR, ID_ATTR, "CDATA",
321: variantKey.getDocumentId());
322: attrs.addAttribute("", BRANCH_ATTR, BRANCH_ATTR,
323: "CDATA", variantKey.getBranch());
324: attrs.addAttribute("", LANG_ATTR, LANG_ATTR, "CDATA",
325: variantKey.getLanguage());
326: contentHandler.startElement("", DOCUMENT_EL,
327: DOCUMENT_EL, attrs);
328: contentHandler.endElement("", DOCUMENT_EL, DOCUMENT_EL);
329: }
330: contentHandler.endElement("", BROKENLINK_EL, BROKENLINK_EL);
331: }
332:
333: if (succeeded.size() > 0) {
334: contentHandler.startElement("", SUCCEEDED_EL, SUCCEEDED_EL,
335: new AttributesImpl());
336:
337: Iterator it = succeeded.iterator();
338: org.xml.sax.helpers.AttributesImpl attrs = new org.xml.sax.helpers.AttributesImpl();
339: while (it.hasNext()) {
340: ImpExpVariantKey variantKey = (ImpExpVariantKey) it
341: .next();
342: attrs.clear();
343: attrs.addAttribute("", ID_ATTR, ID_ATTR, "CDATA",
344: variantKey.getDocumentId());
345: attrs.addAttribute("", BRANCH_ATTR, BRANCH_ATTR,
346: "CDATA", variantKey.getBranch());
347: attrs.addAttribute("", LANG_ATTR, LANG_ATTR, "CDATA",
348: variantKey.getLanguage());
349: contentHandler.startElement("", DOCUMENT_EL,
350: DOCUMENT_EL, attrs);
351: contentHandler.endElement("", DOCUMENT_EL, DOCUMENT_EL);
352: }
353: contentHandler.endElement("", SUCCEEDED_EL, SUCCEEDED_EL);
354: }
355:
356: if (failedItems.size() > 0) {
357: contentHandler.startElement("", OTHER_FAILURES_EL,
358: OTHER_FAILURES_EL, new AttributesImpl());
359: org.xml.sax.helpers.AttributesImpl attrs = new org.xml.sax.helpers.AttributesImpl();
360: for (ItemFailureInfo item : failedItems) {
361: attrs.clear();
362: attrs.addAttribute("", "type", "type", "CDATA", item
363: .getType());
364: attrs.addAttribute("", "name", "name", "CDATA", item
365: .getName());
366:
367: contentHandler.startElement("", OTHER_FAILURE_EL,
368: OTHER_FAILURE_EL, attrs);
369:
370: contentHandler.startElement("", "description",
371: "description", new AttributesImpl());
372: contentHandler.characters(item.getErrorDescription()
373: .toCharArray(), 0, item.getErrorDescription()
374: .length());
375: contentHandler.endElement("", "description",
376: "description");
377:
378: contentHandler.startElement("", "stackTrace",
379: "stackTrace", new AttributesImpl());
380: contentHandler.characters(item.getStackTrace()
381: .toCharArray(), 0, item.getStackTrace()
382: .length());
383: contentHandler.endElement("", "stackTrace",
384: "stackTrace");
385:
386: contentHandler.endElement("", OTHER_FAILURE_EL,
387: OTHER_FAILURE_EL);
388: }
389: contentHandler.endElement("", OTHER_FAILURES_EL,
390: OTHER_FAILURES_EL);
391: }
392:
393: contentHandler.endElement("", EXPORT_RESULT_EL,
394: EXPORT_RESULT_EL);
395: contentHandler.endDocument();
396: }
397:
398: private static final String EXPORT_RESULT_EL = "exportResult";
399: private static final String SKIPPED_BECAUSE_RETIRED_EL = "skippedBecauseRetired";
400: private static final String SKIPPED_BECAUSE_NO_LIVE_VERSION_EL = "skippedBecauseNoLiveVersion";
401: private static final String FAILURES_EL = "failed";
402: private static final String SUCCEEDED_EL = "succeeded";
403: private static final String BROKENLINK_EL = "brokenLink";
404: private static final String DOCUMENT_EL = "document";
405: private static final String ID_ATTR = "id";
406: private static final String BRANCH_ATTR = "branch";
407: private static final String LANG_ATTR = "language";
408: private static final String OTHER_FAILURES_EL = "otherFailures";
409: private static final String OTHER_FAILURE_EL = "failure";
410: }
|