package org.ch3ck3r.jgbx.internal;
import java.io.IOException;
import java.io.StringReader;
import java.util.Map;
import org.ch3ck3r.jgbx.callbacks.Callback;
import org.ch3ck3r.jgbx.error.JGBXException;
import org.ch3ck3r.jgbx.error.JGBXFault;
import org.ch3ck3r.jgbx.internal.JGBXContentHandler.MessageType;
import org.ch3ck3r.jgbx.responses.Response;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* Parser for GBX Messages.
*
* @author Frank Zechert
* @version 1
*/
public class JGBXParser {
/**
* The XML Reader.
*/
private final XMLReader reader;
/**
* The content handler.
*/
private final JGBXContentHandler handler;
/**
* Create a new JGBXParser.
*/
public JGBXParser() {
this.handler = new JGBXContentHandler();
try {
this.reader = XMLReaderFactory.createXMLReader();
this.reader.setContentHandler(this.handler);
}
catch (final SAXException e) {
throw new RuntimeException(e);
}
}
/**
* Parse the XML and return a response.
*
* @param xml
* The xml to parse.
* @param clazz
* The class to return.
* @return The response.
* @throws JGBXException
* Something failed.
* @throws JGBXFault
* The server returned an error.
*/
public synchronized Response responseFromXML(final String xml, final Class<? extends Response> clazz)
throws JGBXException, JGBXFault {
try {
this.reader.parse(new InputSource(new StringReader(xml)));
if (this.handler.getMessageType() == MessageType.METHOD_RESPONSE) {
final Response r = clazz.newInstance();
r.setParams(this.handler.getParameters());
return r;
}
else if (this.handler.getMessageType() == MessageType.FAULT) {
@SuppressWarnings("unchecked")
final Map<String, Object> map = (Map<String, Object>) this.handler.getParameters().get(0);
throw new JGBXFault((Integer) map.get("faultCode"), (String) map.get("faultString"));
}
else {
throw new JGBXException("failed to parse a " + this.handler.getMessageType() + " as a response.");
}
}
catch (IOException | SAXException | InstantiationException | IllegalAccessException e) {
throw new JGBXException("Failed to parse the response " + xml, e);
}
}
/**
* Parse the XML and return a callback.
*
* @param xml
* The xml to parse.
* @return The callback.
* @throws JGBXException
* Something failed.
* @throws JGBXFault
* The server returned an error.
*/
public synchronized Callback callbackFromXML(final String xml) throws JGBXException, JGBXFault {
try {
this.reader.parse(new InputSource(new StringReader(xml)));
if (this.handler.getMessageType() == MessageType.METHOD_CALL) {
return new Callback(this.handler.getMethodName(), this.handler.getParameters());
}
else if (this.handler.getMessageType() == MessageType.FAULT) {
@SuppressWarnings("unchecked")
final Map<String, Object> map = (Map<String, Object>) this.handler.getParameters().get(0);
throw new JGBXFault((Integer) map.get("faultCode"), (String) map.get("faultString"));
}
else {
throw new JGBXException("failed to parse a " + this.handler.getMessageType() + " as a callback.");
}
}
catch (IOException | SAXException e) {
throw new JGBXException("Failed to parse the response " + xml, e);
}
}
}