001    package com.thaiopensource.validate.schematron;
002    
003    import org.xml.sax.helpers.DefaultHandler;
004    import org.xml.sax.ErrorHandler;
005    import org.xml.sax.SAXParseException;
006    import org.xml.sax.SAXException;
007    import org.xml.sax.Attributes;
008    import com.thaiopensource.util.Localizer;
009    
010    class OutputHandler extends DefaultHandler {
011      private final ErrorHandler eh;
012      private int lineNumber = -1;
013      private int columnNumber = -1;
014      private String systemId = null;
015      private final StringBuffer message = new StringBuffer();
016      private boolean inMessage = false;
017      private final String lineSeparator;
018      private static final String indent = "  ";
019      private final Localizer localizer = new Localizer(OutputHandler.class);
020    
021      OutputHandler(ErrorHandler eh) {
022        this.eh = eh;
023        this.lineSeparator = System.getProperty("line.separator");
024      }
025    
026      public void characters(char ch[], int start, int length)
027              throws SAXException {
028        if (inMessage) {
029          for (int i = 0; i < length; i++) {
030            char c = ch[start + i];
031            switch (c) {
032            case ' ':
033            case '\r':
034            case '\n':
035            case '\t':
036              if (message.length() == 0 || message.charAt(message.length() - 1) != ' ')
037                message.append(' ');
038              break;
039            default:
040              message.append(c);
041              break;
042            }
043          }
044        }
045      }
046    
047      public void ignorableWhitespace(char ch[], int start, int length)
048              throws SAXException {
049        characters(ch, start, length);
050      }
051    
052      public void startElement(String uri, String localName,
053                               String qName, Attributes attributes)
054              throws SAXException {
055        if (localName.equals("failed-assertion")
056            || localName.equals("report")) {
057          String value = attributes.getValue("", "line-number");
058          if (value == null)
059            lineNumber = -1;
060          else {
061            try {
062              lineNumber = Integer.parseInt(value);
063            }
064            catch (NumberFormatException e) {
065              lineNumber = -1;
066            }
067          }
068          value = attributes.getValue("", "column-number");
069          if (value == null)
070            columnNumber = -1;
071          else {
072            try {
073              columnNumber = Integer.parseInt(value);
074            }
075            catch (NumberFormatException e) {
076              columnNumber = -1;
077            }
078          }
079          value = attributes.getValue("", "system-id");
080          if (value != null && value.equals(""))
081            value = null;
082          systemId = value;
083          message.append(localizer.message(localName.equals("failed-assertion")
084                                           ? "failed_assertion"
085                                           : "report"));
086        }
087        else if (localName.equals("statement") || localName.equals("diagnostic")) {
088          inMessage = true;
089          message.append(lineSeparator);
090          message.append(indent);
091        }
092      }
093    
094      public void endElement(String uri, String localName, String qName)
095              throws SAXException {
096        if (localName.equals("statement") || localName.equals("diagnostic")) {
097          if (message.length() > 0 && message.charAt(message.length() - 1) == ' ')
098            message.setLength(message.length() - 1);
099          inMessage = false;
100        }
101        else if (localName.equals("failed-assertion")
102                 || localName.equals("report")) {
103          eh.error(new SAXParseException(message.toString(), null, systemId, lineNumber, columnNumber));
104          message.setLength(0);
105        }
106      }
107    }