package com.bluevia.android.ad.parser.xml;
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.ad.data.Ad;
import com.bluevia.android.ad.data.AdResponse;
import com.bluevia.android.ad.data.AdsAttribute;
import com.bluevia.android.ad.data.FullCreativeElement;
import com.bluevia.android.ad.data.Interaction;
import com.bluevia.android.ad.data.Resource;
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;
/**
* Xml parser for XmlAdResponse entities.
*
* @author Telefonica I+D
*
*/
class XmlAdResponseParser implements IParser {
private static final String TAG = "XmlAdResponseParser";
private XmlPullParser mParser = null;
public AdResponse parse(InputStream is) throws ParseException {
if (is == null) {
return null;
}
// init the parser
this.mParser = Xml.newPullParser();
try {
this.mParser.setInput(is, null);
} catch (XmlPullParserException e) {
Log.e(TAG, "Exception occurred while reading the XML Document", e);
throw new ParseException("Could not create XmlAdResponse Parser", e);
}
// Start the parse process
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 adResponse
AdResponse response = handleAdResponse(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);
}
}
/**
*
* @param eventType Last tag gathered with XmlPullParser from the XML.
* @return the handleAdResponse
* @throws ParseException
* @throws XmlPullParserException
* @throws IOException
*/
private AdResponse handleAdResponse(int eventType) throws XmlPullParserException, IOException,
ParseException {
AdResponse adResponse = 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 (XmlConstants.XSD_AD_ADRESPONSE.equals(name)) {
return adResponse;
}
break;
case XmlPullParser.START_TAG:
if (name.equals(XmlConstants.XSD_AD_ADRESPONSE)) {
try {
adResponse = new AdResponse();
String id = mParser.getAttributeValue(null/* ns */,
XmlConstants.XSD_AD_AD_RESPONSE_ATTR_ID);
String version = mParser.getAttributeValue(null/* ns */,
XmlConstants.XSD_AD_AD_RESPONSE_ATTR_VERSION);
adResponse.setId(id);
if ((version == null) || (version.trim().length() == 0))
throw new ParseException("The xml received for the adResponse is not valid.");
adResponse.setVersion(Integer.parseInt(version));
} catch (NumberFormatException e) {
throw new ParseException("The xml received for the adResponse is not valid.");
}
} else if (name.equals(XmlConstants.XSD_AD_AD)) {
if (adResponse == null)
throw new ParseException("AdResponse Element is missing");
//Check there is not already one Ad. (xml should contain just one ad element)
if (adResponse.getAd() != null)
throw new ParseException("AdResponse Element has several ad elements. It should contain just one.");
adResponse.setAd(handleAd(eventType));
}
}
eventType = mParser.next();
}
return null;
}
/**
*
* @param eventType Last tag gathered with XmlPullParser from the XML.
* @return the handleAd
* @throws ParseException
* @throws XmlPullParserException
* @throws IOException
*/
private Ad handleAd(int eventType) throws XmlPullParserException, IOException, ParseException {
Ad ad = 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_AD_AD)) {
return ad;
}
break;
case XmlPullParser.START_TAG:
if (name.equals(XmlConstants.XSD_AD_AD)) {
ad = new Ad();
try {
String adPlacement = mParser.getAttributeValue(null /* ns */,
XmlConstants.XSD_AD_AD_ATTR_AD_PLACEMENT);
if (adPlacement != null)
ad.setAdPlacement(Integer.parseInt(adPlacement));
} catch (NumberFormatException e) {
throw new ParseException("The xml received for the adResponse is not valid.");
}
ad.setCampaign(mParser.getAttributeValue(null/* ns */,
XmlConstants.XSD_AD_AD_ATTR_CAMPAIGN));
ad.setFlight(mParser.getAttributeValue(null/* ns */,
XmlConstants.XSD_AD_AD_ATTR_FLIGHT));
ad.setId(mParser.getAttributeValue(null/* ns */,
XmlConstants.XSD_AD_AD_ATTR_ID));
} else if (name.equals(XmlConstants.XSD_AD_RESOURCE)) {
if (ad == null)
throw new ParseException("Ad Element is missing");
if(ad.getResource() != null)
throw new ParseException("Ad Element has several Resource elements. It should contain just one.");
ad.setResource(handleResource(eventType));
}
default:
break;
}
eventType = mParser.next();
}
return null;
}
/**
*
* @param eventType Last tag gathered with XmlPullParser from the XML.
* @return the handleResource
* @throws ParseException
* @throws XmlPullParserException
* @throws IOException
*/
private Resource handleResource(int eventType) throws XmlPullParserException, IOException,
ParseException {
Resource resource = 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_AD_RESOURCE)) {
return resource;
}
break;
case XmlPullParser.START_TAG:
if (name.equals(XmlConstants.XSD_AD_RESOURCE)) {
resource = new Resource();
resource.setAdRepresentation(mParser.getAttributeValue(null/* ns */,
XmlConstants.XSD_AD_RESOURCE_ATTR_AD_PRESENTATION));
} else if (name.equals(XmlConstants.XSD_AD_CREATIVE_ELEMENT)) {
if (resource == null)
throw new ParseException("Resource Element is missing");
resource.addCreativeElement(handleCreativeElement(eventType));
}
default:
break;
}
eventType = mParser.next();
}
return null;
}
/**
*
* @param eventType Last tag gathered with XmlPullParser from the XML.
* @return the handleCreativeElement
* @throws ParseException
* @throws XmlPullParserException
* @throws IOException
*/
private FullCreativeElement handleCreativeElement(int eventType) throws XmlPullParserException,
IOException, ParseException {
FullCreativeElement creativeElement = 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_AD_CREATIVE_ELEMENT)) {
return creativeElement;
}
break;
case XmlPullParser.START_TAG:
if (name.equals(XmlConstants.XSD_AD_CREATIVE_ELEMENT)) {
creativeElement = new FullCreativeElement();
creativeElement.setType(stringToCreativeElementType(mParser.getAttributeValue(null/* ns */,
XmlConstants.XSD_AD_CREATIVE_ELEMENT_ATTR_TYPE)));
} else if (name.equals(XmlConstants.XSD_AD_ATTRIBUTE)) {
if (creativeElement == null)
throw new ParseException("Resource Element is missing");
creativeElement.addAdsAttribute(handleAttribute(eventType));
} else if (name.equals(XmlConstants.XSD_AD_INTERACTION)) {
if (creativeElement == null)
throw new ParseException("Resource Element is missing");
creativeElement.addInteraction(handleInteraction(eventType));
}
default:
break;
}
eventType = mParser.next();
}
return null;
}
/**
*
* @param eventType Last tag gathered with XmlPullParser from the XML.
* @return the handleInteraction
* @throws ParseException
* @throws XmlPullParserException
* @throws IOException
*/
private Interaction handleInteraction(int eventType) throws XmlPullParserException,
IOException, ParseException {
Interaction interaction = 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_AD_INTERACTION)) {
return interaction;
}
break;
case XmlPullParser.START_TAG:
if (name.equals(XmlConstants.XSD_AD_INTERACTION)) {
interaction = new Interaction();
interaction.setType(stringToInteractionType(mParser.getAttributeValue(null /* ns */,
XmlConstants.XSD_AD_INTERACTION_ATTR_TYPE)));
} else if (name.equals(XmlConstants.XSD_AD_ATTRIBUTE)) {
if (interaction == null)
throw new ParseException("Interaction Element is missing");
interaction.addAttribute(handleAttribute(eventType));
}
default:
break;
}
eventType = mParser.next();
}
return null;
}
/**
*
* @param eventType Last tag gathered with XmlPullParser from the XML.
* @return the handleAttribute
* @throws ParseException
* @throws XmlPullParserException
* @throws IOException
*/
private AdsAttribute handleAttribute(int eventType) throws XmlPullParserException, IOException,
ParseException {
AdsAttribute attribute = 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_AD_ATTRIBUTE)) {
return attribute;
}
break;
case XmlPullParser.START_TAG:
if (name.equals(XmlConstants.XSD_AD_ATTRIBUTE)) {
attribute = new AdsAttribute();
attribute.setType(stringToAdsAttributeType(mParser.getAttributeValue(null/* ns */,
XmlConstants.XSD_AD_ATTRIBUTE_ATTR_TYPE)));
int[] textEventType = new int[1];
String value = XmlParserSerializerUtils.getChildText(mParser, textEventType);
if ((value == null) && (textEventType[0] == XmlPullParser.END_TAG)) {
eventType = textEventType[0];
continue;
}
attribute.setValue(value);
}
default:
break;
}
eventType = mParser.next();
}
return null;
}
/**
* Return the creative element type from a string
*
* @param typeStr String that represents the creative element type
* @return FullCreativeElement.Type. Values included: IMAGE, TEXT, SOUND, ZIP, PAGE
*/
private FullCreativeElement.Type stringToCreativeElementType(String typeStr) {
if (typeStr == null)
return null;
typeStr = typeStr.trim();
if (typeStr.equals(XmlConstants.XSD_AD_CREATIVE_ELEMENT_ATTR_TYPE_IMAGE_VALUE)) {
return FullCreativeElement.Type.IMAGE;
} else if (typeStr.equals(XmlConstants.XSD_AD_CREATIVE_ELEMENT_ATTR_TYPE_TEXT_VALUE)) {
return FullCreativeElement.Type.TEXT;
} else if (typeStr.equals(XmlConstants.XSD_AD_CREATIVE_ELEMENT_ATTR_TYPE_SOUND_VALUE)) {
return FullCreativeElement.Type.SOUND;
} else if (typeStr.equals(XmlConstants.XSD_AD_CREATIVE_ELEMENT_ATTR_TYPE_ZIP_VALUE)) {
return FullCreativeElement.Type.ZIP;
} else if (typeStr.equals(XmlConstants.XSD_AD_CREATIVE_ELEMENT_ATTR_TYPE_PAGE_VALUE)) {
return FullCreativeElement.Type.PAGE;
} else
return null;
}
/**
* Return the ads attribute type from a string
*
* @param typeStr String that represents the ads attribute type
* @return AdsAttribute.Type. Values included: ADTEXT, LOCATOR, URL, CODEC
*/
private AdsAttribute.Type stringToAdsAttributeType(String typeStr) {
if (typeStr == null)
return null;
typeStr = typeStr.trim();
if (typeStr.equals(XmlConstants.XSD_AD_ATTRIBUTE_ATTR_TYPE_ADTEXT_VALUE)) {
return AdsAttribute.Type.ADTEXT;
} else if (typeStr.equals(XmlConstants.XSD_AD_ATTRIBUTE_ATTR_TYPE_LOCATOR_VALUE)) {
return AdsAttribute.Type.LOCATOR;
} else if (typeStr.equals(XmlConstants.XSD_AD_ATTRIBUTE_ATTR_TYPE_URL_VALUE)) {
return AdsAttribute.Type.URL;
} else if (typeStr.equals(XmlConstants.XSD_AD_ATTRIBUTE_ATTR_TYPE_CODEC_VALUE)) {
return AdsAttribute.Type.CODEC;
} else
return null;
}
/**
* Return the interaction type from a string
*
* @param typeStr String that represents the interaction type
* @return Interaction.Type. Values included: CLICK_2_WAP
*/
private Interaction.Type stringToInteractionType(String typeStr) {
if (typeStr == null)
return null;
typeStr = typeStr.trim();
if (typeStr.equals(XmlConstants.XSD_AD_INTERACTION_ATTR_TYPE_CLICK2WAP_VALUE)) {
return Interaction.Type.CLICK_2_WAP;
} else
return null;
}
}