--- /dev/null
+package com.indexdata.mkjsf.pazpar2.data;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.IOException;\r
+import java.io.UnsupportedEncodingException;\r
+import java.util.Arrays;\r
+import java.util.List;\r
+import java.util.Stack;\r
+\r
+import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.parsers.SAXParser;\r
+import javax.xml.parsers.SAXParserFactory;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.xml.sax.Attributes;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.XMLReader;\r
+import org.xml.sax.helpers.DefaultHandler;\r
+\r
+import com.indexdata.mkjsf.pazpar2.ClientCommandResponse;\r
+import com.indexdata.mkjsf.pazpar2.data.sp.AuthResponse;\r
+import com.indexdata.mkjsf.pazpar2.data.sp.CategoriesResponse;\r
+import com.indexdata.mkjsf.pazpar2.data.sp.TargetCategory;\r
+\r
+/**\r
+ * Parses the XML stored in ClientCommandResponses and builds ResponseDataObjects from it.\r
+ * \r
+ * @author Niels Erik\r
+ *\r
+ */\r
+public class ResponseParser extends DefaultHandler {\r
+\r
+ private XMLReader xmlReader = null;\r
+ private ResponseDataObject currentElement = null;\r
+ private Stack<ResponseDataObject> dataElements = new Stack<ResponseDataObject>();\r
+ private ResponseDataObject result = null;\r
+ private String xml = null;\r
+ private static Logger logger = Logger.getLogger(ResponseParser.class);\r
+\r
+ public static List<String> docTypes = Arrays.asList( "bytarget","termlist","show","stat","record","search","init",\r
+ /* SP extras */ "auth", "categories" ); \r
+ \r
+ public ResponseParser() {\r
+ try {\r
+ initSax();\r
+ } catch (ParserConfigurationException e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ } catch (SAXException e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ \r
+ public static ResponseParser getParser() {\r
+ return new ResponseParser();\r
+ }\r
+ \r
+ private void initSax() throws ParserConfigurationException, SAXException {\r
+ SAXParserFactory spf = SAXParserFactory.newInstance();\r
+ spf.setNamespaceAware(true);\r
+ SAXParser saxParser = spf.newSAXParser();\r
+ xmlReader = saxParser.getXMLReader();\r
+ xmlReader.setContentHandler(this); \r
+ }\r
+ \r
+ /**\r
+ * Parses a Pazpar2 XML response -- or an error response as XML -- and produces a \r
+ * ResponseDataObject object, i.e. a 'show' object\r
+ * \r
+ * @param response XML response string from Pazpar2\r
+ * @return Response data object\r
+ */\r
+ public ResponseDataObject getDataObject (ClientCommandResponse response) {\r
+ this.xml = response.getResponseString();\r
+ try { \r
+ xmlReader.parse(new InputSource(new ByteArrayInputStream(response.getResponseToParse())));\r
+ } catch (UnsupportedEncodingException e) {\r
+ e.printStackTrace(); \r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ } catch (SAXException e) {\r
+ e.printStackTrace(); \r
+ }\r
+ return result;\r
+ }\r
+\r
+ /** \r
+ * Receive notification at the start of element \r
+ * \r
+ */\r
+ @Override\r
+ public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {\r
+ if (localName.equals("init")) {\r
+ currentElement = new InitResponse();\r
+ } else if (localName.equals("search")) {\r
+ currentElement = new SearchResponse();\r
+ } else if (localName.equals("show")) {\r
+ currentElement = new ShowResponse(); \r
+ } else if (localName.equals("hit")) {\r
+ currentElement = new Hit();\r
+ } else if (localName.equals("location")) {\r
+ currentElement = new Location();\r
+ } else if (localName.equals("record")) {\r
+ currentElement = new RecordResponse(); \r
+ } else if (localName.equals("bytarget")) {\r
+ currentElement = new ByTargetResponse(); \r
+ } else if (localName.equals("target")) {\r
+ currentElement = new Target();\r
+ } else if (localName.equals("stat")) {\r
+ currentElement = new StatResponse(); \r
+ } else if (localName.equals("termlist")) {\r
+ currentElement = new TermListsResponse(); \r
+ } else if (localName.equals("list")) {\r
+ currentElement = new TermListResponse();\r
+ ((TermListResponse)currentElement).setName(atts.getValue("name"));\r
+ ((TermListsResponse)dataElements.peek()).addTermList((TermListResponse)currentElement);\r
+ } else if (localName.equals("term")) {\r
+ if (dataElements.peek().getAttribute("name").equals("xtargets")) {\r
+ currentElement = new TermXTargetResponse(); \r
+ } else {\r
+ currentElement = new TermResponse();\r
+ }\r
+ ((TermListResponse)dataElements.peek()).addTerm((TermResponse)currentElement);\r
+ } else if (localName.equals("applicationerror")) {\r
+ currentElement = new CommandError();\r
+ } else if (localName.equals("error") && dataElements.peek().getType().equals("applicationerror")) {\r
+ currentElement = new ServiceError(); \r
+ // Service Proxy extras \r
+ } else if (localName.equals("auth")) { \r
+ currentElement = new AuthResponse();\r
+ } else if (localName.equals("categories")) {\r
+ currentElement = new CategoriesResponse();\r
+ } else if (localName.equals("category") && dataElements.peek().getType().equals("categories")) {\r
+ currentElement = new TargetCategory();\r
+ // Catch all\r
+ } else {\r
+ currentElement = new ResponseDataObject();\r
+ }\r
+ currentElement.setType(localName);\r
+ for (int i=0; i< atts.getLength(); i++) {\r
+ currentElement.setAttribute(atts.getLocalName(i), atts.getValue(i));\r
+ } \r
+ if (!docTypes.contains(localName)) {\r
+ if (dataElements.size() == 0) {\r
+ logger.info("Encountered unknown top level element [" + localName + "]. Creating generic data object.");\r
+ currentElement.setType(localName);\r
+ } else {\r
+ dataElements.peek().addElement(localName, currentElement);\r
+ }\r
+ }\r
+ if (this.xml != null) { // Store XML for doc level elements\r
+ currentElement.setXml(xml);\r
+ xml = null;\r
+ }\r
+ dataElements.push(currentElement); \r
+ }\r
+ \r
+ @Override\r
+ public void characters(char[] ch, int start, int length) throws SAXException {\r
+ String data = new String(ch, start, length); \r
+ dataElements.peek().appendContent(data); \r
+ }\r
+ \r
+ @Override\r
+ public void endElement(String namespaceURI, String localName, String qName) throws SAXException {\r
+ if (dataElements.size()==1) {\r
+ result = dataElements.pop();\r
+ } else {\r
+ dataElements.pop();\r
+ }\r
+ }\r
+}\r