More error handling/reporting. Normalizing auth resp
[mkjsf-moved-to-github.git] / src / main / java / com / indexdata / mkjsf / pazpar2 / data / ResponseParser.java
1 package com.indexdata.mkjsf.pazpar2.data;\r
2 \r
3 import java.io.ByteArrayInputStream;\r
4 import java.io.IOException;\r
5 import java.io.UnsupportedEncodingException;\r
6 import java.util.Arrays;\r
7 import java.util.List;\r
8 import java.util.Stack;\r
9 \r
10 import javax.xml.parsers.ParserConfigurationException;\r
11 import javax.xml.parsers.SAXParser;\r
12 import javax.xml.parsers.SAXParserFactory;\r
13 \r
14 import org.apache.log4j.Logger;\r
15 import org.xml.sax.Attributes;\r
16 import org.xml.sax.InputSource;\r
17 import org.xml.sax.SAXException;\r
18 import org.xml.sax.XMLReader;\r
19 import org.xml.sax.helpers.DefaultHandler;\r
20 \r
21 import com.indexdata.mkjsf.pazpar2.ClientCommandResponse;\r
22 \r
23 public class ResponseParser extends DefaultHandler {\r
24 \r
25   private XMLReader xmlReader = null;\r
26   private ResponseDataObject currentElement = null;\r
27   private Stack<ResponseDataObject> dataElements = new Stack<ResponseDataObject>();\r
28   private ResponseDataObject result = null;\r
29   private String xml = null;\r
30   private static Logger logger = Logger.getLogger(ResponseParser.class);\r
31 \r
32   public static List<String> docTypes = Arrays.asList(  "bytarget","termlist","show","stat","record","search","init",\r
33                                         /* SP extras */ "auth" );                                        \r
34   \r
35   public ResponseParser() {\r
36     try {\r
37       initSax();\r
38     } catch (ParserConfigurationException e) {\r
39       // TODO Auto-generated catch block\r
40       e.printStackTrace();\r
41     } catch (SAXException e) {\r
42       // TODO Auto-generated catch block\r
43       e.printStackTrace();\r
44     }\r
45   }\r
46   \r
47   public static ResponseParser getParser() {\r
48     return new ResponseParser();\r
49   }\r
50   \r
51   private void initSax() throws ParserConfigurationException, SAXException {\r
52     SAXParserFactory spf = SAXParserFactory.newInstance();\r
53     spf.setNamespaceAware(true);\r
54     SAXParser saxParser = spf.newSAXParser();\r
55     xmlReader = saxParser.getXMLReader();\r
56     xmlReader.setContentHandler(this);         \r
57   }\r
58   \r
59   /**\r
60    * Parses a Pazpar2 XML response -- or an error response as XML -- and produces a \r
61    * ResponseDataObject object, i.e. a 'show' object\r
62    * \r
63    * @param response XML response string from Pazpar2\r
64    * @return Response data object\r
65    */\r
66   public ResponseDataObject getDataObject (ClientCommandResponse response) {\r
67     this.xml = response.getResponseString();\r
68     try {      \r
69       xmlReader.parse(new InputSource(new ByteArrayInputStream(response.getResponseToParse())));\r
70     } catch (UnsupportedEncodingException e) {\r
71       e.printStackTrace(); \r
72     } catch (IOException e) {\r
73       e.printStackTrace();\r
74     } catch (SAXException e) {\r
75       e.printStackTrace();      \r
76     }\r
77     return result;\r
78   }\r
79 \r
80   /** \r
81    * Receive notification at the start of element \r
82    * \r
83    */\r
84   @Override\r
85   public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {\r
86     if (localName.equals("init")) {\r
87       currentElement = new InitResponse();\r
88     } else if (localName.equals("search")) {\r
89       currentElement = new SearchResponse();\r
90     } else if (localName.equals("show")) {\r
91       currentElement = new ShowResponse();      \r
92     } else if (localName.equals("hit")) {\r
93       currentElement = new Hit();\r
94     } else if (localName.equals("location")) {\r
95       currentElement = new Location();\r
96     } else if (localName.equals("record")) {\r
97       currentElement = new RecordResponse();            \r
98     } else if (localName.equals("bytarget")) {\r
99       currentElement = new ByTarget();      \r
100     } else if (localName.equals("target")) {\r
101       currentElement = new Target();\r
102     } else if (localName.equals("stat")) {\r
103       currentElement = new StatResponse();      \r
104     } else if (localName.equals("termlist")) {\r
105       currentElement = new TermListsResponse();      \r
106     } else if (localName.equals("list")) {\r
107       currentElement = new TermListResponse();\r
108       ((TermListResponse)currentElement).setName(atts.getValue("name"));\r
109       ((TermListsResponse)dataElements.peek()).addTermList((TermListResponse)currentElement);\r
110     } else if (localName.equals("term")) {\r
111       if (dataElements.peek().getAttribute("name").equals("xtargets")) {\r
112         currentElement = new TermXTargetResponse();        \r
113       } else {\r
114         currentElement = new TermResponse();\r
115       }\r
116       ((TermListResponse)dataElements.peek()).addTerm((TermResponse)currentElement);\r
117     } else if (localName.equals("applicationerror")) {\r
118       currentElement = new CommandError();\r
119     } else if (localName.equals("error") && dataElements.peek().getType().equals("applicationerror")) {\r
120       currentElement = new Pazpar2Error(); \r
121     } else if (localName.equals("auth")) {  \r
122       currentElement = new AuthResponse();\r
123     } else {\r
124       currentElement = new ResponseDataObject();\r
125     }\r
126     currentElement.setType(localName);\r
127     for (int i=0; i< atts.getLength(); i++) {\r
128        currentElement.setAttribute(atts.getLocalName(i), atts.getValue(i));\r
129     }    \r
130     if (!docTypes.contains(localName)) {\r
131       if (dataElements.size() == 0) {\r
132         logger.info("Encountered unknown top level element [" + localName + "]. Creating generic data object.");\r
133         currentElement.setType(localName);\r
134       } else {\r
135         dataElements.peek().addElement(localName, currentElement);\r
136       }\r
137     }\r
138     if (this.xml != null) { // Store XML for doc level elements\r
139       currentElement.setXml(xml);\r
140       xml = null;\r
141     }\r
142     dataElements.push(currentElement);    \r
143   }\r
144  \r
145   @Override\r
146   public void characters(char[] ch, int start, int length) throws SAXException {\r
147     String data = new String(ch, start, length);        \r
148     dataElements.peek().appendContent(data);    \r
149   }\r
150   \r
151   @Override\r
152   public void endElement(String namespaceURI, String localName, String qName) throws SAXException {\r
153     if (dataElements.size()==1) {\r
154       result = dataElements.pop();\r
155     } else {\r
156       dataElements.pop();\r
157     }\r
158   }\r
159 }\r