1package com.android.hotspot2.pps;
2
3import com.android.hotspot2.Utils;
4
5import java.util.ArrayList;
6import java.util.Collections;
7import java.util.HashMap;
8import java.util.Iterator;
9import java.util.List;
10import java.util.Map;
11
12public class DomainMatcher {
13
14    public enum Match {None, Primary, Secondary}
15
16    private final Label mRoot;
17
18    private static class Label {
19        private final Map<String, Label> mSubDomains;
20        private final Match mMatch;
21
22        private Label(Match match) {
23            mMatch = match;
24            mSubDomains = match == Match.None ? new HashMap<String, Label>() : null;
25        }
26
27        private void addDomain(Iterator<String> labels, Match match) {
28            String labelName = labels.next();
29            if (labels.hasNext()) {
30                Label subLabel = new Label(Match.None);
31                mSubDomains.put(labelName, subLabel);
32                subLabel.addDomain(labels, match);
33            } else {
34                mSubDomains.put(labelName, new Label(match));
35            }
36        }
37
38        private Label getSubLabel(String labelString) {
39            return mSubDomains.get(labelString);
40        }
41
42        public Match getMatch() {
43            return mMatch;
44        }
45
46        private void toString(StringBuilder sb) {
47            if (mSubDomains != null) {
48                sb.append(".{");
49                for (Map.Entry<String, Label> entry : mSubDomains.entrySet()) {
50                    sb.append(entry.getKey());
51                    entry.getValue().toString(sb);
52                }
53                sb.append('}');
54            } else {
55                sb.append('=').append(mMatch);
56            }
57        }
58
59        @Override
60        public String toString() {
61            StringBuilder sb = new StringBuilder();
62            toString(sb);
63            return sb.toString();
64        }
65    }
66
67    public DomainMatcher(List<String> primary, List<List<String>> secondary) {
68        mRoot = new Label(Match.None);
69        for (List<String> secondaryLabel : secondary) {
70            mRoot.addDomain(secondaryLabel.iterator(), Match.Secondary);
71        }
72        // Primary overwrites secondary.
73        mRoot.addDomain(primary.iterator(), Match.Primary);
74    }
75
76    /**
77     * Check if domain is either a the same or a sub-domain of any of the domains in the domain tree
78     * in this matcher, i.e. all or or a sub-set of the labels in domain matches a path in the tree.
79     *
80     * @param domain Domain to be checked.
81     * @return None if domain is not a sub-domain, Primary if it matched one of the primary domains
82     * or Secondary if it matched on of the secondary domains.
83     */
84    public Match isSubDomain(List<String> domain) {
85
86        Label label = mRoot;
87        for (String labelString : domain) {
88            label = label.getSubLabel(labelString);
89            if (label == null) {
90                return Match.None;
91            } else if (label.getMatch() != Match.None) {
92                return label.getMatch();
93            }
94        }
95        return Match.None;  // Domain is a super domain
96    }
97
98    public static boolean arg2SubdomainOfArg1(List<String> arg1, List<String> arg2) {
99        if (arg2.size() < arg1.size()) {
100            return false;
101        }
102
103        Iterator<String> l1 = arg1.iterator();
104        Iterator<String> l2 = arg2.iterator();
105
106        while (l1.hasNext()) {
107            if (!l1.next().equals(l2.next())) {
108                return false;
109            }
110        }
111        return true;
112    }
113
114    @Override
115    public String toString() {
116        return "Domain matcher " + mRoot;
117    }
118
119    private static final String[] TestDomains = {
120            "garbage.apple.com",
121            "apple.com",
122            "com",
123            "jan.android.google.com.",
124            "jan.android.google.com",
125            "android.google.com",
126            "google.com",
127            "jan.android.google.net.",
128            "jan.android.google.net",
129            "android.google.net",
130            "google.net",
131            "net.",
132            "."
133    };
134
135    public static void main(String[] args) {
136        DomainMatcher dm1 = new DomainMatcher(Utils.splitDomain("android.google.com"),
137                Collections.<List<String>>emptyList());
138        for (String domain : TestDomains) {
139            System.out.println(domain + ": " + dm1.isSubDomain(Utils.splitDomain(domain)));
140        }
141        List<List<String>> secondaries = new ArrayList<List<String>>();
142        secondaries.add(Utils.splitDomain("apple.com"));
143        secondaries.add(Utils.splitDomain("net"));
144        DomainMatcher dm2 = new DomainMatcher(Utils.splitDomain("android.google.com"), secondaries);
145        for (String domain : TestDomains) {
146            System.out.println(domain + ": " + dm2.isSubDomain(Utils.splitDomain(domain)));
147        }
148    }
149}
150