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