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 AccountStatusParser {
//private static final String DEBUG_TAG = BaseActivity.DEBUG_TAG;
// We don't use namespaces
private static final String ns = null;
// XML tag strings
private static final String FEED_TAG = "ii_feed";
private static final String VOLUME_USAGE_TAG = "volume_usage";
private static final String QUOTA_RESET_TAG = "quota_reset";
private static final String DAYS_REMAINING_TAG = "days_remaining";
private static final String DAYS_SO_FARE_TAG = "days_so_far";
private static final String EXPECTED_TRAFFIC_TYPES_TAG = "expected_traffic_types";
private static final String TYPE_TAG = "type";
private static final String CLASSIFICATION_ATT = "classification";
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 UPLOADS_ATT = "uploads";
private static final String FREEZONE_ATT = "freezone";
private static final String USED_ATT = "used";
private static final String IS_SHAPED_TAG = "is_shaped";
private static final String SPEED_ATT = "speed";
private static final String CONNECTIONS_TAG = "connections";
private static final String IP_TAG = "ip";
private static final String ON_SINCE_ATT = "on_since";
private long mQuotaResetDate;
private long mQuotaStartDate;
private long mAnyTimeDataUsed = -1;
private int mAnyTimeSpeed = -1;
private boolean mAnyTimeIsShaped = false;
private long mPeakDataUsed = -1;
private int mPeakSpeed = -1;
private boolean mPeakIsShaped = false;
private long mOffpeakDataUsed = -1;
private int mOffpeakSpeed = -1;
private boolean mOffpeakIsShaped = false;
private long mUploadsDataUsed =-1;
private long mFreezoneDataUsed = -1;
private String mIpAddress = null;
private long mUpTimeDate;
// This class represents the account info in the XML feed.
public static class AccountStatus {
public final long quotaResetDate;
public final long quotaStartDate;
public final long anyTimeDataUsed;
public final int anyTimeSpeed;
public final boolean anyTimeIsShaped;
public final long peakDataUsed;
public final int peakSpeed;
public final boolean peakIsShaped;
public final long offpeakDataUsed;
public final int offpeakSpeed;
public final boolean offpeakIsShaped;
public final long uploadsDataUsed;
public final long freezoneDataUsed;
public final String ipAddress;
public final long upTimeDate;
private AccountStatus( long quotaResetDate, long quotaStartDate
, long anyTimeDataUsed, int anyTimeSpeed, boolean anyTimeIsShaped
, long peakDataUsed, int peakSpeed, boolean peakIsShaped
, long offpeakDataUsed, int offpeakSpeed, boolean offpeakIsShaped
, long uploadsDataUsed
, long freezoneDataUsed
, String ipAddress, long upTimeDate) {
this.quotaStartDate = quotaStartDate;
this.quotaResetDate = quotaResetDate;
this.anyTimeDataUsed = anyTimeDataUsed;
this.anyTimeSpeed = anyTimeSpeed;
this.anyTimeIsShaped = anyTimeIsShaped;
this.peakDataUsed = peakDataUsed;
this.peakSpeed = peakSpeed;
this.peakIsShaped = peakIsShaped;
this.offpeakDataUsed = offpeakDataUsed;
this.offpeakSpeed = offpeakSpeed;
this.offpeakIsShaped = offpeakIsShaped;
this.uploadsDataUsed = uploadsDataUsed;
this.freezoneDataUsed = freezoneDataUsed;
this.ipAddress = ipAddress;
this.upTimeDate = upTimeDate;
}
}
public List<AccountStatus> 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<AccountStatus> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
List<AccountStatus> status = new ArrayList<AccountStatus>();
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();
if (tagName.equals(VOLUME_USAGE_TAG)) {
readVolumeUsage(parser);
} else if (tagName.equals(CONNECTIONS_TAG)){
readConnectionInfo(parser);
} else {
skip(parser);
}
}
status.add( new AccountStatus(mQuotaResetDate, mQuotaStartDate
, mAnyTimeDataUsed, mAnyTimeSpeed, mAnyTimeIsShaped
, mPeakDataUsed, mPeakSpeed, mPeakIsShaped
, mOffpeakDataUsed, mOffpeakSpeed, mOffpeakIsShaped
, mUploadsDataUsed, mFreezoneDataUsed
, mIpAddress, mUpTimeDate));
return status;
}
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(QUOTA_RESET_TAG)){
readQuotaReset(parser);
} else if (tagName.equals(EXPECTED_TRAFFIC_TYPES_TAG)){
readExpectedTrafficTypes(parser);
} else {
skip(parser);
}
}
}
public void readConnectionInfo(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, CONNECTIONS_TAG);
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if (tagName.equals(IP_TAG)){
readIpInfo(parser);
} else {
skip(parser);
}
}
}
private void readQuotaReset(XmlPullParser parser) throws IOException, XmlPullParserException {
String daysRemaining = null;
String daysSoFare = null;
parser.require(XmlPullParser.START_TAG, ns, QUOTA_RESET_TAG);
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if (tagName.equals(DAYS_REMAINING_TAG)){
daysRemaining = readText(parser);
} else if (tagName.equals(DAYS_SO_FARE_TAG)){
daysSoFare = readText(parser);
} else {
skip(parser);
}
}
Calendar quotaResetDate = Calendar.getInstance();
quotaResetDate.add(Calendar.DATE, Integer.parseInt(daysRemaining) );
quotaResetDate.set(Calendar.HOUR_OF_DAY, 0);
mQuotaResetDate = quotaResetDate.getTimeInMillis();
Calendar quotaStartDate = Calendar.getInstance();
quotaStartDate.add(Calendar.DATE, ( -1 * Integer.parseInt(daysSoFare) ) );
quotaStartDate.set(Calendar.HOUR_OF_DAY, 0);
mQuotaStartDate = quotaStartDate.getTimeInMillis();
}
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();
String tagAtt = parser.getAttributeValue(null, CLASSIFICATION_ATT);
if (tagName.equals(TYPE_TAG)) {
if (tagAtt.equals(ANYTIME_ATT)){
mAnyTimeDataUsed = stringToLong(readDataUsed(parser));
} else if (tagAtt.equals(PEAK_ATT)){
mPeakDataUsed = stringToLong(readDataUsed(parser));
} else if (tagAtt.equals(OFFPEAK_ATT)){
mOffpeakDataUsed = stringToLong(readDataUsed(parser));
} else if (tagAtt.equals(UPLOADS_ATT)){
mUploadsDataUsed = stringToLong(readDataUsed(parser));
} else if (tagAtt.equals(FREEZONE_ATT)){
mFreezoneDataUsed = stringToLong(readDataUsed(parser));
}
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.nextTag() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if (tagName.equals(IS_SHAPED_TAG)){
if (classification.equals(ANYTIME_ATT)){
mAnyTimeSpeed = stringToInt(readShapedSpeed(parser));
mAnyTimeIsShaped = readIsShaped(parser);
}
if (classification.equals(PEAK_ATT)){
mPeakSpeed = stringToInt(readShapedSpeed(parser));
mPeakIsShaped = readIsShaped(parser);
} else if (classification.equals(OFFPEAK_ATT)){
mOffpeakSpeed = stringToInt(readShapedSpeed(parser));
mOffpeakIsShaped = readIsShaped(parser);
}
} else {
skip(parser);
}
}
}
private boolean readIsShaped(XmlPullParser parser) throws IOException, XmlPullParserException {
boolean flag = false;
parser.require(XmlPullParser.START_TAG, ns, IS_SHAPED_TAG);
String shaped = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, IS_SHAPED_TAG);
if (shaped == "true"){
flag = true;
} else {
flag = false;
}
return flag;
}
private void readIpInfo(XmlPullParser parser) throws IOException, XmlPullParserException {
Calendar upDate = getDateTimeValue(parser.getAttributeValue(null, ON_SINCE_ATT));
mUpTimeDate = upDate.getTimeInMillis();
parser.require(XmlPullParser.START_TAG, ns, IP_TAG);
mIpAddress = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, IP_TAG);
}
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
String text = null;
if (parser.next() == XmlPullParser.TEXT) {
text = parser.getText();
parser.nextTag();
}
return text;
}
private String readDataUsed(XmlPullParser parser) throws IOException, XmlPullParserException {
String dataUsed;
dataUsed = parser.getAttributeValue(null, USED_ATT);
return dataUsed;
}
private String readShapedSpeed(XmlPullParser parser) throws IOException, XmlPullParserException {
String shapedSpeed;
shapedSpeed = parser.getAttributeValue(null, SPEED_ATT);
return shapedSpeed;
}
private Calendar getDateTimeValue(String dateTime){
SimpleDateFormat hourMintueFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
Calendar timeValue = Calendar.getInstance();
try {
timeValue.setTime(hourMintueFormat.parse(dateTime));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return timeValue;
}
private Long stringToLong(String s){
Long l = Long.parseLong(s);
return l;
}
private int stringToInt(String s){
int i = Integer.parseInt(s);
return i;
}
// 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;
}
}
}
}