package com.bluevia.android.commons.parser.xmlrpc;
import java.io.IOException;
import java.io.InputStream;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.util.Log;
import android.util.Xml;
import com.bluevia.android.commons.Entity;
import com.bluevia.android.commons.data.xmlrpc.MethodResponse;
import com.bluevia.android.commons.data.xmlrpc.RpcError;
import com.bluevia.android.commons.parser.IParser;
import com.bluevia.android.commons.parser.ParseException;
import com.bluevia.android.commons.parser.xml.XmlConstants;
import com.bluevia.android.commons.parser.xml.XmlParserSerializerUtils;
/**
* Abstract Xml parser for MethodResponse entities.
*
* @author Telefonica I+D
*
*/
public abstract class XmlMethodResponseParser implements IParser {
private static final String TAG = "XmlMethodResponseParser";
protected XmlPullParser mParser = null;
public MethodResponse parse(InputStream is) throws ParseException {
//Check first that is is not null
if (is == null) {
return null;
}
mParser = Xml.newPullParser();
try{
mParser.setInput(is,null);
} catch(XmlPullParserException e){
Log.e(TAG, "Exception occureed while reading the XML Document", e);
throw new ParseException("Could not create the CallSessionResult", e);
}
int eventType;
try {
eventType = mParser.getEventType();
} catch (XmlPullParserException e) {
throw new ParseException("Could not parse adResponse entity.", e);
}
if (eventType != XmlPullParser.START_DOCUMENT) {
throw new ParseException("", new XmlPullParserException(
"Attempting to initialize parsing beyond the start of the document."));
}
try {
// Gets the first eventType
eventType = mParser.next();
// Gets the MethodResponse
MethodResponse response = handleMethodResponse(eventType);
if ((response == null) || (! (response.isValid())))
throw new ParseException("The xml received for the adResponse is not valid.");
return response;
} catch (XmlPullParserException xppe) {
throw new ParseException("Could not read next event.", xppe);
} catch (IOException ioe) {
throw new ParseException("Could not read next event.", ioe);
}
}
/**
* This function parse the common methodResponse tag
*
* @param eventType
* @return
* @throws ParseException
* @throws XmlPullParserException
* @throws IOException
*/
private MethodResponse handleMethodResponse(int eventType) throws ParseException, XmlPullParserException, IOException{
MethodResponse response = null;
Log.d(TAG, "Start handleMethodResponse");
if (eventType != XmlPullParser.START_TAG) {
throw new ParseException("Expected event START_TAG: Actual event: "
+ XmlPullParser.TYPES[eventType]);
}
while (eventType != XmlPullParser.END_DOCUMENT) {
String name = mParser.getName();
Log.d(TAG, "mParser: " + name);
switch (eventType) {
case XmlPullParser.END_TAG:
if (XmlConstants.XSD_RPC_METHOD_RESPONSE.equals(name)) {
return response;
}
break;
case XmlPullParser.START_TAG:
if (name.equals(XmlConstants.XSD_RPC_METHOD_RESPONSE)) {
response = new MethodResponse();
} else if (name.equals(XmlConstants.XSD_RPC_ID_ATTR)) {
response.setId(XmlParserSerializerUtils.getChildText(mParser));
} else if (name.equals(XmlConstants.XSD_RPC_VERSION_ATTR)) {
String version = XmlParserSerializerUtils.getChildText(mParser);
if ((version == null) || (version.trim().length() == 0))
throw new ParseException("The xml received for the CallSessionResult is not valid.");
response.setVersion(version);
} else if (name.equals(XmlConstants.XSD_RPC_RESULT)) {
if (response == null)
throw new ParseException("MethodResponse Element is missing");
//Check there is not already one ResponseEntity. (xml should contain just one result element)
if (response.getResponseEntity() != null)
throw new ParseException("MethodResponse Element has several result elements. It should contain just one.");
response.setResponseEntity(handleResult(eventType));
} else if (name.equals(XmlConstants.XSD_RPC_ERROR)) {
if (response == null)
throw new ParseException("MethodResponse Element is missing");
response.setResponseEntity(handleError(eventType));
}
}
eventType = mParser.next();
}
return null;
}
/**
* Method to be implemented by extended classes to parse the result of the method response.
*
* @param eventType
* @return the result Entity of the MethodResponse
* @throws ParseException
* @throws IOException
* @throws XmlPullParserException
*/
protected abstract Entity handleResult(int eventType) throws ParseException, XmlPullParserException, IOException;
/**
*
* @param eventType
* @return
* @throws ParseException
* @throws XmlPullParserException
* @throws IOException
*/
private RpcError handleError(int eventType) throws ParseException, XmlPullParserException, IOException {
RpcError error = null;
if (eventType != XmlPullParser.START_TAG) {
throw new ParseException("Expected event START_TAG: Actual event: "
+ XmlPullParser.TYPES[eventType]);
}
while (eventType != XmlPullParser.END_DOCUMENT) {
String name = mParser.getName();
switch (eventType) {
case XmlPullParser.END_TAG:
if (name.equals(XmlConstants.XSD_RPC_ERROR)) {
if (error == null)
throw new ParseException("Error parsing response");
return error;
}
break;
case XmlPullParser.START_TAG:
if (name.equals(XmlConstants.XSD_RPC_ERROR)) {
error = new RpcError();
} else if (name.equals(XmlConstants.XSD_RPC_ERROR_CODE)) {
String code = XmlParserSerializerUtils.getChildText(mParser);
error.setCode(code);
} else if (name.equals(XmlConstants.XSD_RPC_ERROR_MESSAGE)) {
String message = XmlParserSerializerUtils.getChildText(mParser);
error.setMessage(message);
}
default:
break;
}
eventType = mParser.next();
}
return null;
}
}