package au.id.teda.broadband.usage.parser;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.util.Xml;
public class AccountInfoParser {
//private static final String DEBUG_TAG = BaseActivity.DEBUG_TAG;
private static final String ns = null; // We don't use namespaces
private static final String FEED_TAG = "ii_feed";
private static final String ACCOUNT_INFO_TAG = "account_info";
private static final String PLAN_TAG = "plan";
private static final String PRODUCT_TAG = "product";
private static final String VOLUME_USAGE_TAG = "volume_usage";
private static final String OFFPEAK_START_TAG = "offpeak_start";
private static final String OFFPEAK_END_TAG = "offpeak_end";
private static final String EXPECTED_TRAFFIC_TYPES_TAG = "expected_traffic_types";
private static final String TYPE_TAG = "type";
private static final String QUOTA_ALLOCATION = "quota_allocation";
private static final String ANYTIME_ATT = "anytime";
private static final String PEAK_ATT = "peak";
private static final String OFFPEAK_ATT = "offpeak";
private static final String CLASSIFICATION_ATT = "classification";
private String mPlan = null;
private String mProduct = null;
private boolean bIsAnyTime = false;
private long mOffpeakStartTime = -1;
private long mOffpeakEndTime = -1;
private long mAnytimeQuota = -1;
private long mPeakQuota = -1;
private long mOffpeakQuota = -1;
private long MB = 1000000;
// This class represents the account info in the XML feed.
public static class AccountInfo {
public final String plan;
public final String product;
public final boolean isAnyTime;
public final long offpeakStartTime;
public final long offpeakEndTime;
public final long anytimeQuota;
public final long peakQuota;
public final long offpeakQuota;
private AccountInfo(String plan, String product, boolean isAnyTime
, long offpeakStartTime, long offpeakEndTime
, long anytimeQuota, long peakQuota, long offpeakQuota) {
this.plan = plan;
this.product = product;
this.isAnyTime = isAnyTime;
this.offpeakStartTime = offpeakStartTime;
this.offpeakEndTime = offpeakEndTime;
this.anytimeQuota = anytimeQuota;
this.peakQuota = peakQuota;
this.offpeakQuota = offpeakQuota;
}
}
public List<AccountInfo> parse (InputStream inputStream) throws XmlPullParserException, IOException {
try {
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(inputStream, null);
parser.nextTag();
return readFeed(parser);
} finally {
inputStream.close();
}
}
private List<AccountInfo> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
List<AccountInfo> accountInfo = new ArrayList<AccountInfo>();
parser.require(XmlPullParser.START_TAG, ns, FEED_TAG);
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
// Starts by looking for the account info tag
if (tagName.equals(ACCOUNT_INFO_TAG)) {
readAccountInfo(parser);
} else if (tagName.equals(VOLUME_USAGE_TAG)){
readVolumeUsage(parser);
} else {
skip(parser);
}
}
accountInfo.add(new AccountInfo(mPlan, mProduct, bIsAnyTime
, mOffpeakStartTime, mOffpeakEndTime
, mAnytimeQuota, mPeakQuota, mOffpeakQuota));
return accountInfo;
}
private void readAccountInfo(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, ACCOUNT_INFO_TAG);
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals(PLAN_TAG)) {
mPlan = readAccountPlan(parser);
} else if (name.equals(PRODUCT_TAG)) {
mProduct = readAccountProduct(parser);
} else {
skip(parser);
}
}
}
private void readVolumeUsage(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, VOLUME_USAGE_TAG);
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if (tagName.equals(OFFPEAK_START_TAG)){
mOffpeakStartTime = getCalendarInMillis(readOffpeakStart(parser));
} else if (tagName.equals(OFFPEAK_END_TAG)){
mOffpeakEndTime = getCalendarInMillis(readOffpeakEnd(parser));
} else if (tagName.equals(EXPECTED_TRAFFIC_TYPES_TAG)){
readExpectedTrafficTypes(parser);
} else {
skip(parser);
}
}
}
private void readExpectedTrafficTypes(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, EXPECTED_TRAFFIC_TYPES_TAG);
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if (tagName.equals(TYPE_TAG)) {
readType(parser);
} else {
skip(parser);
}
}
}
private void readType(XmlPullParser parser) throws IOException, XmlPullParserException {
String classification = parser.getAttributeValue(null, CLASSIFICATION_ATT);
parser.require(XmlPullParser.START_TAG, ns, TYPE_TAG);
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if (tagName.equals(QUOTA_ALLOCATION)){
if (classification.equals(ANYTIME_ATT)){
mAnytimeQuota = stringToLong(readQuota(parser)) * MB;
bIsAnyTime = true;
} else if (classification.equals(PEAK_ATT)){
mPeakQuota = stringToLong(readQuota(parser)) * MB;
} else if (classification.equals(OFFPEAK_ATT)){
mOffpeakQuota = stringToLong(readQuota(parser)) * MB;
}
} else {
skip(parser);
}
}
}
private String readQuota(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, QUOTA_ALLOCATION);
String quota = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, QUOTA_ALLOCATION);
return quota;
}
private String readAccountPlan(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, PLAN_TAG);
String plan = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, PLAN_TAG);
return plan;
}
private String readAccountProduct(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, PRODUCT_TAG);
String product = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, PRODUCT_TAG);
return product;
}
private String readOffpeakStart(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, OFFPEAK_START_TAG);
String start = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, OFFPEAK_START_TAG);
return start;
}
private String readOffpeakEnd(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, OFFPEAK_END_TAG);
String end = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, OFFPEAK_END_TAG);
return end;
}
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
String text = null;
if (parser.next() == XmlPullParser.TEXT) {
text = parser.getText();
parser.nextTag();
}
return text;
}
private long getCalendarInMillis(String time){
SimpleDateFormat hourMintueFormat = new SimpleDateFormat("HH:mm", Locale.getDefault());
Calendar timeValue = Calendar.getInstance();
try {
timeValue.setTime(hourMintueFormat.parse(time));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return timeValue.getTimeInMillis();
}
private Long stringToLong(String s){
Long l = Long.parseLong(s);
return l;
}
// Skips tags the parser isn't interested in. Uses depth to handle nested tags.
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
}