1 package net.sf.gaeappmanager.google.appengine;
2
3 import java.io.InputStream;
4 import java.math.BigDecimal;
5 import java.util.regex.Matcher;
6 import java.util.regex.Pattern;
7
8 import org.dom4j.Attribute;
9 import org.dom4j.Document;
10 import org.dom4j.Element;
11 import org.dom4j.io.DOMReader;
12 import org.w3c.tidy.Tidy;
13
14
15
16
17
18
19 public class QuotaDetailsParser {
20
21
22
23
24
25
26
27
28
29 private Element getNthElementByTag(Element el, String tag, int index) {
30 int idx = 0;
31 for (Object obj : el.elements()) {
32 Element e = (Element) obj;
33 if (e.getName().equals(tag) && idx++ == index) {
34 return e;
35 }
36 }
37 return null;
38 }
39
40 private Element getElementByTagAndValue(Element el, String tag, String value) {
41 if (el.getName().equals(tag) && el.getStringValue().equals(value)) {
42 return el;
43 }
44
45 for (Object obj : el.elements()) {
46 Element result = getElementByTagAndValue((Element) obj, tag, value);
47 if (result != null) {
48 return result;
49 }
50 }
51
52 return null;
53 }
54
55 private Element getElementById(Element el, String id) {
56 if (el.attributeCount() > 0) {
57 Attribute attr = el.attribute("id");
58 if (attr != null && attr.getValue().equals(id)) {
59 return el;
60 }
61 }
62
63 for (Object obj : el.elements()) {
64 Element result = getElementById((Element) obj, id);
65 if (result != null) {
66 return result;
67 }
68 }
69
70 return null;
71 }
72
73 private QuotaValue parseValue(Element parentEl, Quota quota) {
74 QuotaValue qVal = new QuotaValue();
75 qVal.setQuota(quota);
76
77 Element valEl = getElementByTagAndValue(parentEl, "td", quota
78 .getQuotaName());
79 if (valEl == null) {
80 return null;
81 }
82
83 Element el = getNthElementByTag(valEl.getParent(), "td", 2);
84 if (el == null) {
85 return null;
86 }
87
88 qVal
89 .setPercent(new BigDecimal(el.getStringValue().replaceAll("%",
90 "")));
91
92 el = getNthElementByTag(valEl.getParent(), "td", 3);
93 if (el == null) {
94 return null;
95 }
96
97 String[] parts = el.getStringValue().split(" ");
98 if (parts.length < 3) {
99 return null;
100 }
101
102 qVal.setValue(new BigDecimal(parts[0]));
103 qVal.setLimit(new BigDecimal(parts[2]));
104
105 StringBuilder unitBuilder = new StringBuilder();
106 for (int i = 3; i < parts.length; i++) {
107 if (unitBuilder.length() > 0) {
108 unitBuilder.append(" ");
109 }
110 unitBuilder.append(parts[i]);
111 }
112 qVal.setUnit(unitBuilder.toString());
113
114 el = getNthElementByTag(valEl.getParent(), "td", 4);
115 if (el == null) {
116 return null;
117 }
118
119 qVal.setOkay(el.getStringValue().equals("Okay"));
120
121 return qVal;
122 }
123
124 private void parseRefreshNote(Element parentEl, QuotaDetails result) {
125 Element el = getElementById(parentEl, "ae-quota-refresh-note");
126 if (el == null) {
127 return;
128 }
129
130 Pattern pattern = Pattern
131 .compile("Quotas are reset every ([0-9]*) hours. Next reset: ([0-9]*) hours");
132
133 Matcher matcher = pattern.matcher(el.getStringValue());
134 if (matcher.matches()) {
135 result.setResetIntervalHours(Integer.valueOf(matcher.group(1)));
136 result.setNextResetWithinHours(Integer.valueOf(matcher.group(2)));
137 }
138 }
139
140 public QuotaDetails parse(InputStream inputStream) {
141 QuotaDetails result = new QuotaDetails();
142
143 Tidy tidy = new Tidy();
144 tidy.setXHTML(true);
145 tidy.setShowWarnings(false);
146 tidy.setQuiet(true);
147 tidy.setXmlOut(false);
148 org.w3c.dom.Document xhtml = tidy.parseDOM(inputStream, null);
149
150 DOMReader xmlReader = new DOMReader();
151 Document document = xmlReader.read(xhtml);
152
153 Element quotaDetailsElement = getElementById(document.getRootElement(),
154 "ae-quota-details");
155
156 parseRefreshNote(quotaDetailsElement, result);
157
158 for (Quota quota : Quota.values()) {
159 QuotaValue qValue = parseValue(quotaDetailsElement, quota);
160 if (qValue != null) {
161 result.getValues().add(qValue);
162 }
163 }
164
165 return result;
166 }
167 }