1 package com.xtremelabs.robolectric.shadows;
2 
3 import java.util.Arrays;
4 import java.util.HashMap;
5 import java.util.List;
6 
7 import android.content.UriMatcher;
8 import android.net.Uri;
9 
10 import com.xtremelabs.robolectric.internal.Implementation;
11 import com.xtremelabs.robolectric.internal.Implements;
12 
13 @Implements(UriMatcher.class)
14 public 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 
MatchNode(int code)22 		public MatchNode(int code) {
23 			this.code = code;
24 		}
25 	}
26 
27 	public MatchNode rootNode;
28 
__constructor__(int code)29 	public void __constructor__(int code) {
30 		rootNode = new MatchNode(code);
31 	}
32 
33 	@Implementation
addURI(String authority, String path, int code)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
match(Uri uri)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 
matchSegments(MatchNode node, List<String> segments)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 
addNodes(MatchNode baseNode, List<String> segments, int code)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