1 package dolda.jsvc.util;
6 public class AcceptMap implements Iterable<AcceptMap.Entry> {
7 private static final Entry[] typehint = new Entry[0];
8 private final Entry[] list;
9 private static final Comparator<Entry> lcmp = new Comparator<Entry>() {
10 public int compare(Entry a, Entry b) {
19 public static class Entry {
21 public double q = 1.0;
22 public Map<String, String> pars = new HashMap<String, String>();
25 private AcceptMap(Entry[] list) {
29 private static String token(PushbackReader in) throws IOException {
31 StringBuilder buf = new StringBuilder();
34 if((c < 0) || Character.isWhitespace((char)c) || (",;=:\\\"?".indexOf((char)c) >= 0)) {
39 return(buf.toString());
46 public static AcceptMap parse(Reader in) throws IOException {
47 PushbackReader pin = new PushbackReader(in);
48 List<Entry> lbuf = new LinkedList<Entry>();
49 List<Entry> ebuf = new LinkedList<Entry>();
51 Entry e = new Entry();
52 if((e.type = token(pin)) == null)
53 throw(new Http.EncodingException("Illegal format for Accept* header (expected type)"));
60 } else if(sep == ';') {
62 boolean flush = false;
65 String key = Http.tokenunquote(pin);
68 throw(new Http.EncodingException("Illegal format for Accept* header (expected `=' in parameter)"));
69 String val = Http.tokenunquote(pin);
71 int psep = pin.read();
76 q = Double.parseDouble(val);
77 } catch(NumberFormatException exc) {
78 throw(new Http.EncodingException(exc.getMessage()));
87 } else if(st == "ap") {
88 /* No known accept-params */
94 } else if(psep == ';') {
95 } else if(psep == ',') {
98 throw(new Http.EncodingException("Illegal format for Accept* header (expected `;', `,' or end of parameters)"));
103 ebuf = new LinkedList<Entry>();
107 } else if(sep == ',') {
109 throw(new Http.EncodingException("Illegal format for Accept* header (expected `;', `,' or end of list)"));
112 Entry[] list = lbuf.toArray(typehint);
113 Arrays.sort(list, lcmp);
114 return(new AcceptMap(list));
117 public static AcceptMap parse(String input) {
119 return(parse(new StringReader(input)));
120 } catch(IOException e) {
125 public Iterator<Entry> iterator() {
126 return(new Iterator<Entry>() {
129 public Entry next() {
133 public boolean hasNext() {
134 return(i < list.length);
137 public void remove() {
138 throw(new UnsupportedOperationException());
143 public Entry accepts(String type) {
144 for(Entry e : list) {
145 if(e.type.equals(type))
151 public String toString() {
152 StringBuilder buf = new StringBuilder();
154 buf.append(String.format("%s %f %s\n", e.type, e.q, e.pars));
155 return(buf.toString());