comparison src/main/java/org/msgpack/type/SequentialMapValueImpl.java @ 0:cb825acd883a

first commit
author sugi
date Sat, 18 Oct 2014 15:06:15 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:cb825acd883a
1 //
2 // MessagePack for Java
3 //
4 // Copyright (C) 2009 - 2013 FURUHASHI Sadayuki
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 //
10 // http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
18 package org.msgpack.type;
19
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.AbstractMap;
25 import java.util.AbstractSet;
26 import java.util.AbstractCollection;
27 import java.util.NoSuchElementException;
28 import java.io.IOException;
29 import org.msgpack.packer.Packer;
30 import org.msgpack.util.android.PortedImmutableEntry;
31
32 class SequentialMapValueImpl extends AbstractMapValue {
33 private static SequentialMapValueImpl emptyInstance = new SequentialMapValueImpl(new Value[0], true);
34
35 public static MapValue getEmptyInstance() {
36 return emptyInstance;
37 }
38
39 private Value[] array;
40
41 @Override
42 public Value[] getKeyValueArray() {
43 return array;
44 }
45
46 SequentialMapValueImpl(Value[] array, boolean gift) {
47 if (array.length % 2 != 0) {
48 throw new IllegalArgumentException(); // TODO message
49 }
50 if (gift) {
51 this.array = array;
52 } else {
53 this.array = new Value[array.length];
54 System.arraycopy(array, 0, this.array, 0, array.length);
55 }
56 }
57
58 @Override
59 public Value get(Object key) {
60 if (key == null) {
61 return null;
62 }
63 for (int i = array.length - 2; i >= 0; i -= 2) {
64 if (array[i].equals(key)) {
65 return array[i + 1];
66 }
67 }
68 return null;
69 }
70
71 private static class EntrySet extends AbstractSet<Map.Entry<Value, Value>> {
72 private Value[] array;
73
74 EntrySet(Value[] array) {
75 this.array = array;
76 }
77
78 @Override
79 public int size() {
80 return array.length / 2;
81 }
82
83 @Override
84 public Iterator<Map.Entry<Value, Value>> iterator() {
85 return new EntrySetIterator(array);
86 }
87 }
88
89 private static class EntrySetIterator implements
90 Iterator<Map.Entry<Value, Value>> {
91 private Value[] array;
92 private int pos;
93 private static final boolean hasDefaultImmutableEntry;
94 static {
95 boolean hasIt = true;
96 try {
97 Class.forName("java.util.AbstractMap.SimpleImmutableEntry");
98 } catch (ClassNotFoundException e) {
99 hasIt = false;
100 } finally {
101 hasDefaultImmutableEntry = hasIt;
102 }
103 }
104
105 EntrySetIterator(Value[] array) {
106 this.array = array;
107 this.pos = 0;
108 }
109
110 @Override
111 public boolean hasNext() {
112 return pos < array.length;
113 }
114
115 @Override
116 public Map.Entry<Value, Value> next() {
117 if (pos >= array.length) {
118 throw new NoSuchElementException(); // TODO message
119 }
120
121 Value key = array[pos];
122 Value value = array[pos + 1];
123 /**
124 * @see https://github.com/msgpack/msgpack-java/pull/27
125 *
126 * msgpack-java was crashed on Android 2.2 or below because
127 * the method calls java.util.AbstractMap$SimpleImmutableEntry
128 * that doesn't exist in Android 2.2 or below.
129 */
130 Map.Entry<Value, Value> pair = hasDefaultImmutableEntry ?
131 new AbstractMap.SimpleImmutableEntry<Value, Value>(key, value) :
132 new PortedImmutableEntry<Value, Value>(key, value);
133
134 pos += 2;
135 return pair;
136 }
137
138 @Override
139 public void remove() {
140 throw new UnsupportedOperationException(); // TODO message
141 }
142 }
143
144 private static class KeySet extends AbstractSet<Value> {
145 private Value[] array;
146
147 KeySet(Value[] array) {
148 this.array = array;
149 }
150
151 @Override
152 public int size() {
153 return array.length / 2;
154 }
155
156 @Override
157 public Iterator<Value> iterator() {
158 return new ValueIterator(array, 0);
159 }
160 }
161
162 private static class ValueCollection extends AbstractCollection<Value> {
163 private Value[] array;
164
165 ValueCollection(Value[] array) {
166 this.array = array;
167 }
168
169 @Override
170 public int size() {
171 return array.length / 2;
172 }
173
174 @Override
175 public Iterator<Value> iterator() {
176 return new ValueIterator(array, 1);
177 }
178 }
179
180 private static class ValueIterator implements Iterator<Value> {
181 private Value[] array;
182 private int pos;
183
184 ValueIterator(Value[] array, int offset) {
185 this.array = array;
186 this.pos = offset;
187 }
188
189 @Override
190 public boolean hasNext() {
191 return pos < array.length;
192 }
193
194 @Override
195 public Value next() {
196 if (pos >= array.length) {
197 throw new NoSuchElementException(); // TODO message
198 }
199 Value v = array[pos];
200 pos += 2;
201 return v;
202 }
203
204 @Override
205 public void remove() {
206 throw new UnsupportedOperationException(); // TODO message
207 }
208 }
209
210 @Override
211 public Set<Map.Entry<Value, Value>> entrySet() {
212 return new EntrySet(array);
213 }
214
215 @Override
216 public Set<Value> keySet() {
217 return new KeySet(array);
218 }
219
220 @Override
221 public Collection<Value> values() {
222 return new ValueCollection(array);
223 }
224
225 @Override
226 public void writeTo(Packer pk) throws IOException {
227 pk.writeMapBegin(array.length / 2);
228 for (int i = 0; i < array.length; i++) {
229 array[i].writeTo(pk);
230 }
231 pk.writeMapEnd();
232 }
233
234 @Override
235 public boolean equals(Object o) {
236 if (o == this) {
237 return true;
238 }
239 if (!(o instanceof Value)) {
240 return false;
241 }
242 Value v = (Value) o;
243 if (!v.isMapValue()) {
244 return false;
245 }
246
247 Map<Value, Value> om = v.asMapValue();
248 if (om.size() != array.length / 2) {
249 return false;
250 }
251
252 try {
253 for (int i = 0; i < array.length; i += 2) {
254 Value key = array[i];
255 Value value = array[i + 1];
256 if (!value.equals(om.get(key))) {
257 return false;
258 }
259 }
260 } catch (ClassCastException ex) {
261 return false;
262 } catch (NullPointerException ex) {
263 return false;
264 }
265
266 return true;
267 }
268
269 // private boolean equals(SequentialMapValueImpl o) {
270 // if(array.length != o.array.length) {
271 // return false;
272 // }
273 // for(int i=0; i < array.length; i+=2) {
274 // if(!equalsValue(o.array, array[i], array[i+1], i)) {
275 // return false;
276 // }
277 // }
278 // return true;
279 // }
280
281 // private boolean equalsValue(Value[] oarray, Value key, Value val, int hint) {
282 // for(int j=hint; j < array.length; j+=2) {
283 // if(key.equals(oarray[j])) {
284 // if(val.equals(oarray[j+1])) {
285 // return true;
286 // } else {
287 // return false;
288 // }
289 // }
290 // }
291 // for(int j=0; j < hint; j+=2) {
292 // if(key.equals(oarray[j])) {
293 // if(val.equals(oarray[j+1])) {
294 // return true;
295 // } else {
296 // return false;
297 // }
298 // }
299 // }
300 // return false;
301 // }
302
303 // TODO compareTo?
304
305 @Override
306 public int hashCode() {
307 int h = 0;
308 for (int i = 0; i < array.length; i += 2) {
309 h += array[i].hashCode() ^ array[i + 1].hashCode();
310 }
311 return h;
312 }
313
314 @Override
315 public String toString() {
316 return toString(new StringBuilder()).toString();
317 }
318
319 @Override
320 public StringBuilder toString(StringBuilder sb) {
321 if (array.length == 0) {
322 return sb.append("{}");
323 }
324 sb.append("{");
325 sb.append(array[0]);
326 sb.append(":");
327 sb.append(array[1]);
328 for (int i = 2; i < array.length; i += 2) {
329 sb.append(",");
330 array[i].toString(sb);
331 sb.append(":");
332 array[i + 1].toString(sb);
333 }
334 sb.append("}");
335 return sb;
336 }
337 }