• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.unicode.cldr.draft;
2 
3 import java.util.Arrays;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.Map;
7 import java.util.Map.Entry;
8 import java.util.Set;
9 
10 import org.unicode.cldr.draft.XLocaleDistance.DistanceNode;
11 import org.unicode.cldr.draft.XLocaleDistance.DistanceTable;
12 import org.unicode.cldr.draft.XLocaleDistance.IdMakerFull;
13 import org.unicode.cldr.draft.XLocaleDistance.StringDistanceNode;
14 import org.unicode.cldr.draft.XLocaleDistance.StringDistanceTable;
15 
16 import com.google.common.base.Objects;
17 import com.ibm.icu.util.Output;
18 
19 final class IntDistanceNode extends DistanceNode {
20     final IntDistanceNode.IntDistanceTable distanceTable;
21 
IntDistanceNode(int distance, IntDistanceNode.IntDistanceTable distanceTable)22     public IntDistanceNode(int distance, IntDistanceNode.IntDistanceTable distanceTable) {
23         super(distance);
24         this.distanceTable = distanceTable;
25     }
26 
getDistanceTable()27     public IntDistanceNode.IntDistanceTable getDistanceTable() {
28         return distanceTable;
29     }
30 
31     @Override
equals(Object obj)32     public boolean equals(Object obj) {
33         IntDistanceNode other = (IntDistanceNode) obj;
34         return distance == other.distance && Objects.equal(distanceTable, other.distanceTable);
35     }
36 
37     @Override
hashCode()38     public int hashCode() {
39         return distance ^ Objects.hashCode(distanceTable);
40     }
41 
42     @Override
toString()43     public String toString() {
44         return "\ndistance: " + distance + ", " + distanceTable;
45     }
46 
from(int distance, IntDistanceNode.IntDistanceTable otherTable)47     public static DistanceNode from(int distance, IntDistanceNode.IntDistanceTable otherTable) {
48         return otherTable == null ? new DistanceNode(distance) : new IntDistanceNode(distance, otherTable);
49     }
50 
51     static class IntDistanceTable extends DistanceTable {
52         private static final IdMakerFull[] ids = { new IdMakerFull<String>("lang", XLocaleDistance.ANY), new IdMakerFull<String>("script", XLocaleDistance.ANY),
53             new IdMakerFull<String>("region", XLocaleDistance.ANY) };
54         private static final IdMakerFull<IntDistanceNode.IntDistanceTable> cache = new IdMakerFull<>("table");
55 
56         private final IdMakerFull<String> id;
57         private final DistanceNode[][] distanceNodes; // map from desired, supported => node
58 
IntDistanceTable(StringDistanceTable source)59         public IntDistanceTable(StringDistanceTable source) {
60             this(source, loadIds(source, 0));
61         }
62 
loadIds(StringDistanceTable source, int idNumber)63         private static int loadIds(StringDistanceTable source, int idNumber) {
64             IdMakerFull id = ids[idNumber]; // use different Id for language, script, region
65             for (Entry<String, Map<String, DistanceNode>> e1 : source.subtables.entrySet()) {
66                 int desired = id.add(e1.getKey());
67                 for (Entry<String, DistanceNode> e2 : e1.getValue().entrySet()) {
68                     int supported = id.add(e2.getKey());
69                     StringDistanceNode oldNode = (StringDistanceNode) e2.getValue();
70                     if (oldNode.distanceTable != null) {
71                         loadIds((StringDistanceTable) oldNode.distanceTable, idNumber + 1);
72                     }
73                 }
74             }
75             return 0;
76         }
77 
IntDistanceTable(StringDistanceTable source, int idNumber)78         private IntDistanceTable(StringDistanceTable source, int idNumber) { // move construction out later
79             id = ids[idNumber]; // use different Id for language, script, region
80             int size = id.size();
81             distanceNodes = new DistanceNode[size][size];
82 
83             // fill in the values in the table
84             for (Entry<String, Map<String, DistanceNode>> e1 : source.subtables.entrySet()) {
85                 int desired = id.add(e1.getKey());
86                 for (Entry<String, DistanceNode> e2 : e1.getValue().entrySet()) {
87                     int supported = id.add(e2.getKey());
88                     DistanceNode oldNode = e2.getValue();
89                     final StringDistanceTable oldDistanceTable = (StringDistanceTable) oldNode.getDistanceTable();
90                     IntDistanceNode.IntDistanceTable otherTable = oldDistanceTable == null ? null
91                         : cache.intern(new IntDistanceTable(oldDistanceTable, idNumber + 1));
92                     DistanceNode node = IntDistanceNode.from(oldNode.distance, otherTable);
93                     distanceNodes[desired][supported] = node;
94                 }
95             }
96             // now, to make star work,
97             // copy all the zero columns/rows down to any null value
98             for (int row = 0; row < size; ++row) {
99                 for (int column = 0; column < size; ++column) {
100                     DistanceNode value = distanceNodes[row][column];
101                     if (value != null) {
102                         continue;
103                     }
104                     value = distanceNodes[0][column];
105                     if (value == null) {
106                         value = distanceNodes[row][0];
107                         if (value == null) {
108                             value = distanceNodes[0][0];
109                         }
110                     }
111                     distanceNodes[row][column] = value;
112                 }
113             }
114         }
115 
116         @Override
getDistance(String desired, String supported, Output<DistanceTable> distanceTable, boolean starEquals)117         public int getDistance(String desired, String supported, Output<DistanceTable> distanceTable, boolean starEquals) {
118             final int desiredId = id.toId(desired);
119             final int supportedId = id.toId(supported); // can optimize later
120             DistanceNode value = distanceNodes[desiredId][supportedId];
121             if (distanceTable != null) {
122                 distanceTable.value = value.getDistanceTable();
123             }
124             return starEquals && desiredId == supportedId && (desiredId != 0 || desired.equals(supported)) ? 0
125                 : value.distance;
126         }
127 
128         @Override
equals(Object obj)129         public boolean equals(Object obj) {
130             IntDistanceNode.IntDistanceTable other = (IntDistanceNode.IntDistanceTable) obj;
131             if (!id.equals(other.id)) {
132                 return false;
133             }
134             ;
135             return Arrays.deepEquals(distanceNodes, other.distanceNodes);
136         }
137 
138         @Override
hashCode()139         public int hashCode() {
140             return id.hashCode() ^ Arrays.deepHashCode(distanceNodes);
141         }
142 
143         @Override
toString()144         public String toString() {
145             return abbreviate("\t", new HashMap<DistanceNode, Integer>(), new StringBuilder(id.name + ": ")).toString();
146         }
147 
abbreviate(String indent, Map<DistanceNode, Integer> cache, StringBuilder result)148         private StringBuilder abbreviate(String indent, Map<DistanceNode, Integer> cache, StringBuilder result) {
149             for (int i = 0; i < distanceNodes.length; ++i) {
150                 DistanceNode[] row = distanceNodes[i];
151                 for (int j = 0; j < row.length; ++j) {
152                     DistanceNode value = row[j];
153                     if (value == null) {
154                         continue;
155                     }
156                     result.append(value.distance);
157                     IntDistanceNode.IntDistanceTable dt = (IntDistanceNode.IntDistanceTable) value.getDistanceTable();
158                     if (dt == null) {
159                         result.append(";");
160                         continue;
161                     }
162                     Integer old = cache.get(value);
163                     result.append("/");
164                     if (old != null) {
165                         result.append(old + ";");
166                     } else {
167                         final int table = cache.size();
168                         cache.put(value, table);
169                         result.append("\n" + indent + table + "=" + dt.id.name + ": ");
170                         dt.abbreviate(indent + "\t", cache, result);
171                     }
172                 }
173             }
174             return result;
175         }
176 
177         @Override
getCloser(int threshold)178         public Set<String> getCloser(int threshold) {
179             Set<String> result = new HashSet<>();
180             for (int i = 0; i < distanceNodes.length; ++i) {
181                 DistanceNode[] row = distanceNodes[i];
182                 for (int j = 0; j < row.length; ++j) {
183                     DistanceNode value = row[j];
184                     if (value.distance < threshold) {
185                         result.add(id.fromId(i));
186                         break;
187                     }
188                 }
189             }
190             return result;
191         }
192 
193         @Override
toString(boolean abbreviate)194         String toString(boolean abbreviate) {
195             return toString();
196         }
197     }
198 }