1package com.xtremelabs.robolectric.shadows;
2
3import java.util.Arrays;
4import java.util.HashMap;
5import java.util.List;
6
7import android.content.UriMatcher;
8import android.net.Uri;
9
10import com.xtremelabs.robolectric.internal.Implementation;
11import com.xtremelabs.robolectric.internal.Implements;
12
13@Implements(UriMatcher.class)
14public class ShadowUriMatcher {
15
16	public static class MatchNode {
17		public int code = UriMatcher.NO_MATCH;
18		public HashMap<String, MatchNode> map = new HashMap<String, ShadowUriMatcher.MatchNode>();
19		public MatchNode number;
20		public MatchNode text;
21
22		public MatchNode(int code) {
23			this.code = code;
24		}
25	}
26
27	public MatchNode rootNode;
28
29	public void __constructor__(int code) {
30		rootNode = new MatchNode(code);
31	}
32
33	@Implementation
34	public void addURI(String authority, String path, int code) {
35		MatchNode authNode = rootNode.map.get(authority);
36		if (authNode == null) {
37			authNode = new MatchNode(rootNode.code);
38			rootNode.map.put(authority, authNode);
39		}
40
41		String[] segments = path.split("/");
42		addNodes(authNode, Arrays.asList(segments), code);
43	}
44
45	@Implementation
46	public int match(Uri uri) {
47		String auth = uri.getAuthority();
48		List<String> segments = uri.getPathSegments();
49
50		if (!rootNode.map.containsKey(auth)) {
51			return rootNode.code;
52		}
53
54		return matchSegments(rootNode.map.get(auth), segments);
55	}
56
57	private int matchSegments(MatchNode node, List<String> segments) {
58		if (segments.isEmpty()) return node.code;
59		String segment = segments.get(0);
60		segments = segments.subList(1, segments.size());
61
62		if (node.map.containsKey(segment)) {
63			return matchSegments(node.map.get(segment), segments);
64		}
65		if (node.number != null) {
66			long id;
67			try {
68				id = Long.parseLong(segment);
69				if (id >= 0) {
70					return matchSegments(node.number, segments);
71				}
72			}
73			catch (NumberFormatException e) {}
74		}
75		if (node.text != null) {
76			return matchSegments(node.text, segments);
77		}
78
79		return rootNode.code;
80	}
81
82	private void addNodes(MatchNode baseNode, List<String> segments, int code) {
83		MatchNode nextNode = null;
84		String segment = segments.get(0);
85
86		if (segment.equals("#")) {
87			nextNode = baseNode.number;
88			if (nextNode == null) {
89				nextNode = new MatchNode(rootNode.code);
90				baseNode.number = nextNode;
91			}
92		}
93		else if (segment.equals("*")) {
94			nextNode = baseNode.text;
95			if (nextNode == null) {
96				nextNode = new MatchNode(rootNode.code);
97				baseNode.text = nextNode;
98			}
99		}
100		else {
101			nextNode = baseNode.map.get(segment);
102			if (nextNode == null) {
103				nextNode = new MatchNode(rootNode.code);
104				baseNode.map.put(segment, nextNode);
105			}
106		}
107
108		if (segments.size() > 1) {
109			addNodes(nextNode, segments.subList(1, segments.size()), code);
110		}
111		else {
112			nextNode.code = code;
113		}
114	}
115
116}
117