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