calendarThreadLocal = new DefaultCalendarThreadLocal();
38 |
39 | public static long getTimeForDay(int year, int month, int day) {
40 | return getTimeForDay(calendarThreadLocal.get(), year, month, day);
41 | }
42 |
43 | /** @param calendar helper object needed for conversion */
44 | public static long getTimeForDay(Calendar calendar, int year, int month, int day) {
45 | calendar.clear();
46 | calendar.set(year, month - 1, day);
47 | return calendar.getTimeInMillis();
48 | }
49 |
50 | /** Sets hour, minutes, seconds and milliseconds to the given values. Leaves date info untouched. */
51 | public static void setTime(Calendar calendar, int hourOfDay, int minute, int second, int millisecond) {
52 | calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
53 | calendar.set(Calendar.MINUTE, minute);
54 | calendar.set(Calendar.SECOND, second);
55 | calendar.set(Calendar.MILLISECOND, millisecond);
56 | }
57 |
58 | /** Readable yyyyMMdd int representation of a day, which is also sortable. */
59 | public static int getDayAsReadableInt(long time) {
60 | Calendar cal = calendarThreadLocal.get();
61 | cal.setTimeInMillis(time);
62 | return getDayAsReadableInt(cal);
63 | }
64 |
65 | /** Readable yyyyMMdd representation of a day, which is also sortable. */
66 | public static int getDayAsReadableInt(Calendar calendar) {
67 | int day = calendar.get(Calendar.DAY_OF_MONTH);
68 | int month = calendar.get(Calendar.MONTH) + 1;
69 | int year = calendar.get(Calendar.YEAR);
70 | return year * 10000 + month * 100 + day;
71 | }
72 |
73 | /** Returns midnight of the given day. */
74 | public static long getTimeFromDayReadableInt(int day) {
75 | return getTimeFromDayReadableInt(calendarThreadLocal.get(), day, 0);
76 | }
77 |
78 | /** @param calendar helper object needed for conversion */
79 | public static long getTimeFromDayReadableInt(Calendar calendar, int readableDay, int hour) {
80 | int day = readableDay % 100;
81 | int month = readableDay / 100 % 100;
82 | int year = readableDay / 10000;
83 |
84 | calendar.clear(); // We don't set all fields, so we should clear the calendar first
85 | calendar.set(Calendar.HOUR_OF_DAY, hour);
86 | calendar.set(Calendar.DAY_OF_MONTH, day);
87 | calendar.set(Calendar.MONTH, month - 1);
88 | calendar.set(Calendar.YEAR, year);
89 |
90 | return calendar.getTimeInMillis();
91 | }
92 |
93 | public static int getDayDifferenceOfReadableInts(int dayOfBroadcast1, int dayOfBroadcast2) {
94 | long time1 = getTimeFromDayReadableInt(dayOfBroadcast1);
95 | long time2 = getTimeFromDayReadableInt(dayOfBroadcast2);
96 |
97 | // Don't use getDayDifference(time1, time2) here, it's wrong for some days.
98 | // Do float calculation and rounding at the end to cover daylight saving stuff etc.
99 | float daysFloat = (time2 - time1) / 1000 / 60 / 60 / 24f;
100 | return Math.round(daysFloat);
101 | }
102 |
103 | public static int getDayDifference(long time1, long time2) {
104 | return (int) ((time2 - time1) / 1000 / 60 / 60 / 24);
105 | }
106 |
107 | public static long addDays(long time, int days) {
108 | Calendar calendar = calendarThreadLocal.get();
109 | calendar.setTimeInMillis(time);
110 | calendar.add(Calendar.DAY_OF_YEAR, days);
111 | return calendar.getTimeInMillis();
112 | }
113 |
114 | public static void addDays(Calendar calendar, int days) {
115 | calendar.add(Calendar.DAY_OF_YEAR, days);
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/collections/AbstractMultimap.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.collections;
18 |
19 | import java.util.Collection;
20 | import java.util.Map;
21 | import java.util.Set;
22 |
23 | /**
24 | * Combines a Map with List values to provide simple way to store multiple values for a key (multimap).
25 | *
26 | * Threading note: All methods are synchronized
27 | */
28 | public abstract class AbstractMultimap> implements Map {
29 |
30 | protected Map map;
31 |
32 | protected AbstractMultimap(Map map) {
33 | this.map = map;
34 | }
35 |
36 | abstract protected C createNewCollection();
37 |
38 | @Override
39 | public void putAll(Map extends K, ? extends C> m) {
40 | map.putAll(m);
41 | }
42 |
43 | @Override
44 | public synchronized int size() {
45 | return map.size();
46 | }
47 |
48 | @Override
49 | public synchronized boolean isEmpty() {
50 | return map.isEmpty();
51 | }
52 |
53 | @Override
54 | public synchronized boolean containsKey(Object key) {
55 | return map.containsKey(key);
56 | }
57 |
58 | @Override
59 | public synchronized boolean containsValue(Object value) {
60 | return map.containsValue(value);
61 | }
62 |
63 | @Override
64 | public synchronized C get(Object key) {
65 | return map.get(key);
66 | }
67 |
68 | @Override
69 | public synchronized C remove(Object key) {
70 | return map.remove(key);
71 | }
72 |
73 | @Override
74 | public synchronized void clear() {
75 | map.clear();
76 | }
77 |
78 | @Override
79 | public synchronized Set keySet() {
80 | return map.keySet();
81 | }
82 |
83 | @Override
84 | public synchronized Collection values() {
85 | return map.values();
86 | }
87 |
88 | @Override
89 | public synchronized boolean equals(Object o) {
90 | return map.equals(o);
91 | }
92 |
93 | @Override
94 | public synchronized int hashCode() {
95 | return map.hashCode();
96 | }
97 |
98 | /**
99 | * @return number of elements stored for given key after storing the given value.
100 | */
101 | public synchronized int putElement(K key, V value) {
102 | C collection = map.get(key);
103 | if (collection == null) {
104 | collection = createNewCollection();
105 | map.put(key, collection);
106 | }
107 | collection.add(value);
108 | return collection.size();
109 | }
110 |
111 | @Override
112 | public synchronized C put(K key, C value) {
113 | return map.put(key, value);
114 | }
115 |
116 | @Override
117 | public synchronized Set> entrySet() {
118 | return map.entrySet();
119 | }
120 |
121 | /** @return true if the collection was changed. */
122 | public synchronized boolean putElements(K key, Collection values) {
123 | C collection = map.get(key);
124 | if (collection == null) {
125 | collection = createNewCollection();
126 | map.put(key, collection);
127 | }
128 | return collection.addAll(values);
129 | }
130 |
131 | /** @return true if the given element was removed. */
132 | public synchronized boolean removeElement(K key, V value) {
133 | C collection = map.get(key);
134 | if (collection == null) {
135 | return false;
136 | } else {
137 | boolean removed = collection.remove(value);
138 | if (collection.isEmpty()) {
139 | map.remove(key);
140 | }
141 | return removed;
142 | }
143 | }
144 |
145 | public synchronized int countElements(K key) {
146 | C collection = map.get(key);
147 | if (collection == null) {
148 | return 0;
149 | } else {
150 | return collection.size();
151 | }
152 | }
153 |
154 | public synchronized int countElements() {
155 | int count = 0;
156 | for (C collection : map.values()) {
157 | count += collection.size();
158 | }
159 | return count;
160 | }
161 |
162 | public synchronized boolean containsElement(K key, V value) {
163 | C collection = map.get(key);
164 | if (collection == null) {
165 | return false;
166 | } else {
167 | return collection.contains(value);
168 | }
169 | }
170 |
171 | public synchronized boolean containsElement(V value) {
172 | for (C collection : map.values()) {
173 | if (collection.contains(value)) {
174 | return true;
175 | }
176 | }
177 | return false;
178 | }
179 |
180 | public synchronized C valuesElements() {
181 | C all = createNewCollection();
182 | for (C collection : map.values()) {
183 | all.addAll(collection);
184 | }
185 | return all;
186 | }
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/collections/Multimap.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.collections;
18 |
19 | import java.util.ArrayList;
20 | import java.util.HashMap;
21 | import java.util.LinkedList;
22 | import java.util.List;
23 | import java.util.Map;
24 | import java.util.concurrent.CopyOnWriteArrayList;
25 |
26 | /**
27 | * Combines a Map with List values to provide simple way to store multiple values for a key.
28 | */
29 | // Top level class to get rid of 3rd generic collection parameter for more convenient usage.
30 | public class Multimap extends AbstractMultimap> {
31 | private final ListType listType;
32 |
33 | public enum ListType {
34 | /** Aka ArrayList */
35 | REGULAR,
36 |
37 | /** Aka CopyOnWriteArrayList */
38 | THREAD_SAFE,
39 |
40 | /** Aka LinkedList */
41 | LINKED
42 | }
43 |
44 | public static Multimap create() {
45 | return create(ListType.REGULAR);
46 | }
47 |
48 | public static Multimap create(ListType listType) {
49 | return new Multimap<>(new HashMap>(), listType);
50 | }
51 |
52 | protected Multimap(Map> map, ListType listType) {
53 | super(map);
54 | this.listType = listType;
55 | if (listType == null) {
56 | throw new IllegalArgumentException("List type may not be null");
57 | }
58 | }
59 |
60 | protected List createNewCollection() {
61 | switch (listType) {
62 | case REGULAR:
63 | return new ArrayList<>();
64 | case THREAD_SAFE:
65 | return new CopyOnWriteArrayList<>();
66 | case LINKED:
67 | return new LinkedList<>();
68 | default:
69 | throw new IllegalStateException("Unknown list type: " + listType);
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/collections/MultimapSet.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.collections;
18 |
19 | import java.util.HashMap;
20 | import java.util.HashSet;
21 | import java.util.Map;
22 | import java.util.Set;
23 | import java.util.concurrent.CopyOnWriteArraySet;
24 |
25 | /**
26 | * Combines a Map with Set values to provide simple way to store multiple values for a key.
27 | * Like {@link org.greenrobot.essentials.collections.Multimap}, but element values are stored in Sets.
28 | */
29 | // Top level class to get rid of 3rd generic collection parameter for more convenient usage.
30 | public class MultimapSet extends AbstractMultimap> {
31 | private final SetType setType;
32 |
33 | public enum SetType {
34 | /** Aka HashSet */
35 | REGULAR,
36 |
37 | /** Aka CopyOnWriteArraySet */
38 | THREAD_SAFE
39 | }
40 |
41 | public static MultimapSet create() {
42 | return create(SetType.REGULAR);
43 | }
44 |
45 | public static MultimapSet create(SetType setType) {
46 | return new MultimapSet<>(new HashMap>(), setType);
47 | }
48 |
49 | protected MultimapSet(Map> map, SetType setType) {
50 | super(map);
51 | this.setType = setType;
52 | }
53 |
54 | protected Set createNewCollection() {
55 | switch (setType) {
56 | case REGULAR:
57 | return new HashSet<>();
58 | case THREAD_SAFE:
59 | return new CopyOnWriteArraySet<>();
60 | default:
61 | throw new IllegalStateException("Unknown set type: " + setType);
62 | }
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/hash/Checksum128.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.hash;
18 |
19 | import java.math.BigInteger;
20 | import java.util.zip.Checksum;
21 |
22 | /** Checksum interface to access 128 bit in various ways. */
23 | public interface Checksum128 extends Checksum {
24 | /** Returns the higher 64 bits of the 128 bit hash. */
25 | long getValueHigh();
26 |
27 | /** Positive value. */
28 | BigInteger getValueBigInteger();
29 |
30 | /** Padded with leading 0s to ensure length of 32. */
31 | String getValueHexString();
32 |
33 | /** Big endian is the default in Java / network byte order. */
34 | byte[] getValueBytesBigEndian();
35 |
36 | /** Big endian is used by most machines natively. */
37 | byte[] getValueBytesLittleEndian();
38 | }
39 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/hash/FNV32.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.hash;
18 |
19 | import java.util.zip.Checksum;
20 |
21 | /** Hash function FNV-1a (http://www.isthe.com/chongo/tech/comp/fnv). */
22 | public class FNV32 implements Checksum {
23 | private final static int INITIAL_VALUE = 0x811C9DC5;
24 | private final static int MULTIPLIER = 16777619;
25 |
26 | private int hash = INITIAL_VALUE;
27 |
28 | @Override
29 | public void update(int b) {
30 | hash ^= 0xff & b;
31 | hash *= MULTIPLIER;
32 | }
33 |
34 | @Override
35 | public void update(byte[] b, int off, int len) {
36 | int stop = off + len;
37 | for (int i = off; i < stop; i++) {
38 | hash ^= 0xff & b[i];
39 | hash *= MULTIPLIER;
40 |
41 | // This optimization of the multiplication might work in C, but not in Java (~2 times slower)
42 | // hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
43 | }
44 | }
45 |
46 | @Override
47 | public long getValue() {
48 | return hash & 0xffffffffL;
49 | }
50 |
51 | @Override
52 | public void reset() {
53 | hash = INITIAL_VALUE;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/hash/FNV64.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.hash;
18 |
19 | import java.util.zip.Checksum;
20 |
21 | /** Hash function FNV-1a (http://www.isthe.com/chongo/tech/comp/fnv). */
22 | public class FNV64 implements Checksum {
23 | private final static long INITIAL_VALUE = 0xcbf29ce484222325L;
24 | private final static long MULTIPLIER = 0x100000001b3L;
25 |
26 | private long hash = INITIAL_VALUE;
27 |
28 | @Override
29 | public void update(int b) {
30 | hash ^= 0xffL & b;
31 | hash *= MULTIPLIER;
32 | }
33 |
34 | @Override
35 | public void update(byte[] b, int off, int len) {
36 | int stop = off + len;
37 | for (int i = off; i < stop; i++) {
38 | hash ^= 0xffL & b[i];
39 | hash *= MULTIPLIER;
40 | }
41 | }
42 |
43 | @Override
44 | /** Note: Java's long is signed. */
45 | public long getValue() {
46 | return hash;
47 | }
48 |
49 | @Override
50 | public void reset() {
51 | hash = INITIAL_VALUE;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/hash/PrimitiveDataChecksum.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.hash;
18 |
19 | import java.io.UnsupportedEncodingException;
20 | import java.util.zip.Checksum;
21 |
22 | /** Wrapper for Checksum that accepts all kind of primitive data to update the hash. */
23 | public class PrimitiveDataChecksum implements Checksum {
24 | private final Checksum checksum;
25 |
26 | public PrimitiveDataChecksum(Checksum checksum) {
27 | this.checksum = checksum;
28 | }
29 |
30 | @Override
31 | public void update(int b) {
32 | checksum.update(b);
33 | }
34 |
35 | @Override
36 | public void update(byte[] b, int off, int len) {
37 | checksum.update(b, off, len);
38 | }
39 |
40 | @Override
41 | public long getValue() {
42 | return checksum.getValue();
43 | }
44 |
45 | @Override
46 | public void reset() {
47 | checksum.reset();
48 | }
49 |
50 | /** Note: leaves the checksum untouched if given value is null (provide a special value for stronger hashing). */
51 | public void updateUtf8(String string) {
52 | if (string != null) {
53 | byte[] bytes;
54 | try {
55 | bytes = string.getBytes("UTF-8");
56 | } catch (UnsupportedEncodingException e) {
57 | throw new RuntimeException(e);
58 | }
59 | update(bytes, 0, bytes.length);
60 | }
61 | }
62 |
63 | /** Note: leaves the checksum untouched if given value is null (provide a special value for stronger hashing). */
64 | public void updateUtf8(String[] strings) {
65 | if (strings != null) {
66 | for (String string : strings) {
67 | updateUtf8(string);
68 | }
69 | }
70 | }
71 |
72 | /** updates a byte with 0 for false and 1 for true */
73 | public void updateBoolean(boolean value) {
74 | update(value ? 1 : 0);
75 | }
76 |
77 | public void updateShort(short number) {
78 | update((number >>> 8) & 0xff);
79 | update(number & 0xff);
80 | }
81 |
82 | public void updateInt(int number) {
83 | update((number >>> 24) & 0xff);
84 | update((number >>> 16) & 0xff);
85 | update((number >>> 8) & 0xff);
86 | update(number & 0xff);
87 | }
88 |
89 | public void updateLong(long number) {
90 | update((int) (number >>> 56) & 0xff);
91 | update((int) (number >>> 48) & 0xff);
92 | update((int) (number >>> 40) & 0xff);
93 | update((int) (number >>> 32) & 0xff);
94 | update((int) (number >>> 24) & 0xff);
95 | update((int) (number >>> 16) & 0xff);
96 | update((int) (number >>> 8) & 0xff);
97 | update((int) (number & 0xff));
98 | }
99 |
100 | public void updateFloat(float number) {
101 | updateInt(Float.floatToIntBits(number));
102 | }
103 |
104 | public void updateDouble(double number) {
105 | updateLong(Double.doubleToLongBits(number));
106 | }
107 |
108 | /** Note: leaves the checksum untouched if given value is null (provide a special value for stronger hashing). */
109 | public void update(byte[] numbers) {
110 | if (numbers != null) {
111 | update(numbers, 0, numbers.length);
112 | }
113 | }
114 |
115 | /** Note: leaves the checksum untouched if given value is null (provide a special value for stronger hashing). */
116 | public void update(short[] numbers) {
117 | if (numbers != null) {
118 | for (short number : numbers) {
119 | updateShort(number);
120 | }
121 | }
122 | }
123 |
124 | /** Note: leaves the checksum untouched if given value is null (provide a special value for stronger hashing). */
125 | public void update(int[] numbers) {
126 | if (numbers != null) {
127 | for (int number : numbers) {
128 | updateInt(number);
129 | }
130 | }
131 | }
132 |
133 | /** Note: leaves the checksum untouched if given value is null (provide a special value for stronger hashing). */
134 | public void update(long[] numbers) {
135 | if (numbers != null) {
136 | for (long number : numbers) {
137 | updateLong(number);
138 | }
139 | }
140 | }
141 |
142 | /** Note: leaves the checksum untouched if given value is null (provide a special value for stronger hashing). */
143 | public void update(float[] numbers) {
144 | if (numbers != null) {
145 | for (float number : numbers) {
146 | updateFloat(number);
147 | }
148 | }
149 | }
150 |
151 | /** Note: leaves the checksum untouched if given value is null (provide a special value for stronger hashing). */
152 | public void update(double[] numbers) {
153 | if (numbers != null) {
154 | for (double number : numbers) {
155 | updateDouble(number);
156 | }
157 | }
158 | }
159 |
160 | }
161 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/io/IoUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.io;
18 |
19 | import org.greenrobot.essentials.StringUtils;
20 |
21 | import java.io.ByteArrayOutputStream;
22 | import java.io.Closeable;
23 | import java.io.IOException;
24 | import java.io.InputStream;
25 | import java.io.OutputStream;
26 | import java.io.Reader;
27 | import java.io.Writer;
28 | import java.security.MessageDigest;
29 | import java.security.NoSuchAlgorithmException;
30 | import java.util.zip.Checksum;
31 |
32 | /**
33 | * Utils for dealing with IO (streams, readers, ...).
34 | *
35 | * @author Markus
36 | */
37 | public class IoUtils {
38 | private static final int BUFFER_SIZE = 8192;
39 |
40 | public static byte[] readAllBytes(InputStream in) throws IOException {
41 | ByteArrayOutputStream out = new ByteArrayOutputStream();
42 | copyAllBytes(in, out);
43 | return out.toByteArray();
44 | }
45 |
46 | public static byte[] readAllBytesAndClose(InputStream in) throws IOException {
47 | try {
48 | return readAllBytes(in);
49 | } finally {
50 | safeClose(in);
51 | }
52 | }
53 |
54 | public static String readAllChars(Reader reader) throws IOException {
55 | char[] buffer = new char[BUFFER_SIZE / 2];
56 | StringBuilder builder = new StringBuilder();
57 | while (true) {
58 | int read = reader.read(buffer);
59 | if (read == -1) {
60 | break;
61 | }
62 | builder.append(buffer, 0, read);
63 | }
64 | return builder.toString();
65 | }
66 |
67 | public static String readAllCharsAndClose(Reader reader) throws IOException {
68 | try {
69 | return readAllChars(reader);
70 | } finally {
71 | safeClose(reader);
72 | }
73 | }
74 |
75 | public static void writeAllCharsAndClose(Writer writer, CharSequence text) throws IOException {
76 | try {
77 | writer.append(text);
78 | } finally {
79 | safeClose(writer);
80 | }
81 | }
82 |
83 | public static void updateChecksum(InputStream in, Checksum checksum) throws IOException {
84 | byte[] buffer = new byte[BUFFER_SIZE];
85 | while (true) {
86 | int read = in.read(buffer);
87 | if (read == -1) {
88 | break;
89 | }
90 | checksum.update(buffer, 0, read);
91 | }
92 | }
93 |
94 | /** @return MD5 digest (32 hex characters). */
95 | public static String getMd5(InputStream in) throws IOException {
96 | byte[] digest = getDigest(in, "MD5");
97 | return StringUtils.hex(digest);
98 | }
99 |
100 | /** @return SHA-1 digest (40 hex characters). */
101 | public static String getSha1(InputStream in) throws IOException {
102 | byte[] digest = getDigest(in, "SHA-1");
103 | return StringUtils.hex(digest);
104 | }
105 |
106 | /** @return SHA-256 digest (64 hex characters). */
107 | public static String getSha256(InputStream in) throws IOException {
108 | byte[] digest = getDigest(in, "SHA-256");
109 | return StringUtils.hex(digest);
110 | }
111 |
112 | public static byte[] getDigest(InputStream in, String digestAlgo) throws IOException {
113 | MessageDigest digester;
114 | try {
115 | digester = MessageDigest.getInstance(digestAlgo);
116 | } catch (NoSuchAlgorithmException nsae) {
117 | throw new RuntimeException(nsae);
118 | }
119 |
120 | byte[] buffer = new byte[BUFFER_SIZE];
121 | while (true) {
122 | int read = in.read(buffer);
123 | if (read == -1) {
124 | break;
125 | }
126 | digester.update(buffer, 0, read);
127 | }
128 | return digester.digest();
129 | }
130 |
131 | /**
132 | * Copies all available data from in to out without closing any stream.
133 | *
134 | * @return number of bytes copied
135 | */
136 | public static int copyAllBytes(InputStream in, OutputStream out) throws IOException {
137 | int byteCount = 0;
138 | byte[] buffer = new byte[BUFFER_SIZE];
139 | while (true) {
140 | int read = in.read(buffer);
141 | if (read == -1) {
142 | break;
143 | }
144 | out.write(buffer, 0, read);
145 | byteCount += read;
146 | }
147 | return byteCount;
148 | }
149 |
150 |
151 | /**
152 | * Closes the given resource (e.g. stream, reader, writer, etc.) inside a try/catch.
153 | * Does nothing if stream is null.
154 | */
155 | public static void safeClose(Closeable closeable) {
156 | if (closeable != null) {
157 | try {
158 | closeable.close();
159 | } catch (IOException e) {
160 | // Silent
161 | }
162 | }
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/io/LimitedInputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.io;
18 |
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.util.zip.GZIPInputStream;
22 |
23 | /**
24 | * Wraps around an InputStream and limits the amount of bytes that can be read from it. Use it if you operate on an
25 | * InputStream that consists of chunks of a know size, each to be processed using a buffered input stream (e.g.
26 | * GZIPInputStream). Normal buffered input streams would read beyond the limit. The LimitedInputStream never closes the
27 | * inside InputStream(close does nothing).
28 | *
29 | * @author Markus
30 | */
31 | public class LimitedInputStream extends InputStream {
32 |
33 | public static GZIPInputStream createGZIPInputStream(InputStream in, int maxBytes) throws IOException {
34 | LimitedInputStream limitedInputStream = new LimitedInputStream(in, maxBytes);
35 | return new GZIPInputStream(limitedInputStream);
36 | }
37 |
38 | private int bytesLeft;
39 | private final InputStream in;
40 |
41 | public LimitedInputStream(InputStream in, int maxBytes) {
42 | this.in = in;
43 | bytesLeft = maxBytes;
44 | }
45 |
46 | @Override
47 | public int available() throws IOException {
48 | int available = in.available();
49 | return Math.min(available, bytesLeft);
50 | }
51 |
52 | @Override
53 | public int read() throws IOException {
54 | if (bytesLeft <= 0) {
55 | return -1;
56 | }
57 | int read = in.read();
58 | if (read != -1) {
59 | bytesLeft--;
60 | }
61 | return read;
62 | }
63 |
64 | @Override
65 | public int read(byte[] buffer, int offset, int count) throws IOException {
66 | if (bytesLeft <= 0) {
67 | return -1;
68 | }
69 | int countToRead = Math.min(bytesLeft, count);
70 | int read = in.read(buffer, offset, countToRead);
71 | if (read > 0) {
72 | bytesLeft -= read;
73 | }
74 | return read;
75 | }
76 |
77 | @Override
78 | public int read(byte[] buffer) throws IOException {
79 | return read(buffer, 0, buffer.length);
80 | }
81 |
82 | @Override
83 | public long skip(long byteCount) throws IOException {
84 | if (byteCount <= 0) {
85 | return 0;
86 | }
87 | long countToSkip = Math.min(bytesLeft, byteCount);
88 | long skipped = in.skip(countToSkip);
89 | if (skipped > 0) {
90 | bytesLeft -= skipped;
91 | }
92 | return skipped;
93 | }
94 |
95 | @Override
96 | /** Does nothing, because the inner stream is intended to be left open and closed separately (by design).*/
97 | public void close() throws IOException {
98 | }
99 |
100 | public int getBytesLeft() {
101 | return bytesLeft;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/io/PipelineOutputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.io;
18 |
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.io.OutputStream;
22 |
23 | /**
24 | * Replacement for Java's PipedOutputStream: all data written to this stream will get available in the integrated
25 | * InputStream (see {@link #getInputStream()}).
26 | *
27 | * Note: Usually, you will have exactly two threads: one to write and one to read. If you use a single thread, avoid
28 | * reading more bytes than previously written or writing more bytes than the internal buffer can handle.
29 | */
30 | public class PipelineOutputStream extends OutputStream {
31 | private final PipelineInputStream inputStream;
32 | final CircularByteBuffer buffer;
33 | boolean closedOut;
34 | boolean closedIn;
35 |
36 | public PipelineOutputStream() {
37 | this(8192);
38 | }
39 |
40 | public PipelineOutputStream(int bufferCapacity) {
41 | this.buffer = new CircularByteBuffer(bufferCapacity);
42 | inputStream = new PipelineInputStream();
43 | }
44 |
45 | public InputStream getInputStream() {
46 | return inputStream;
47 | }
48 |
49 | @Override
50 | public synchronized void write(byte[] data, int off, int len) throws IOException {
51 | int done = 0;
52 | while (done != len) {
53 | checkPipelineInput();
54 | int count = buffer.put(data, off + done, len - done);
55 | if (count > 0) {
56 | done += count;
57 | notifyBuffer();
58 | } else {
59 | waitForBuffer();
60 | }
61 | }
62 | }
63 |
64 | private void checkPipelineInput() throws IOException {
65 | if (closedIn) {
66 | throw new IOException("PipelineInputStream was closed (broken pipeline)");
67 | }
68 | }
69 |
70 | @Override
71 | public synchronized void write(int b) throws IOException {
72 | checkPipelineInput();
73 | while (!buffer.put((byte) b)) {
74 | waitForBuffer();
75 | checkPipelineInput();
76 | }
77 | notifyBuffer();
78 | }
79 |
80 | @Override
81 | public synchronized void close() throws IOException {
82 | closedOut = true;
83 | notifyBuffer();
84 | }
85 |
86 | void waitForBuffer() throws IOException {
87 | try {
88 | wait();
89 | } catch (InterruptedException e) {
90 | throw new IOException(e);
91 | }
92 | }
93 |
94 | void notifyBuffer() {
95 | notifyAll();
96 | }
97 |
98 | protected class PipelineInputStream extends InputStream {
99 |
100 | @Override
101 | public int read(byte[] b, int off, int len) throws IOException {
102 | if (len == 0) {
103 | return closedOut ? -1 : 0;
104 | }
105 | int read;
106 | synchronized (PipelineOutputStream.this) {
107 | do {
108 | read = buffer.get(b, off, len);
109 | if (read == 0) {
110 | if (closedOut) {
111 | return -1;
112 | }
113 | waitForBuffer();
114 | }
115 | } while (read == 0);
116 | notifyBuffer();
117 | }
118 |
119 | return read;
120 | }
121 |
122 | @Override
123 | public int read() throws IOException {
124 | synchronized (PipelineOutputStream.this) {
125 | int value = buffer.get();
126 | while (value == -1) {
127 | if (closedOut) {
128 | return -1;
129 | }
130 | waitForBuffer();
131 | value = buffer.get();
132 | }
133 | notifyBuffer();
134 | return value;
135 | }
136 | }
137 |
138 | @Override
139 | public int available() throws IOException {
140 | return buffer.available();
141 | }
142 |
143 | @Override
144 | public long skip(long n) throws IOException {
145 | int len = (int) Math.min(n, Integer.MAX_VALUE);
146 | int total = 0;
147 | synchronized (PipelineOutputStream.this) {
148 | while (total < len) {
149 | int skipped = buffer.skip(len - total);
150 | if (skipped == 0) {
151 | if (closedOut) {
152 | return total;
153 | }
154 | waitForBuffer();
155 | } else {
156 | total += skipped;
157 | notifyBuffer();
158 | }
159 | }
160 | return total;
161 | }
162 | }
163 |
164 | @Override
165 | public void close() throws IOException {
166 | closedIn = true;
167 | }
168 | }
169 |
170 | }
171 |
--------------------------------------------------------------------------------
/java-essentials/src/main/java/org/greenrobot/essentials/io/RepeaterInputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2016 Markus Junginger, greenrobot (http://greenrobot.org)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.io;
18 |
19 | import java.io.FilterInputStream;
20 | import java.io.IOException;
21 | import java.io.InputStream;
22 | import java.io.OutputStream;
23 |
24 | /**
25 | * Repeats an input stream to an additional OutputStream. The data of the InputStream becomes available for two
26 | * purposes, e.g. reading data and storing for caching.
27 | *
28 | * Note: OutputStream is not closed when close() is called.
29 | *
30 | * @author Markus
31 | */
32 | public class RepeaterInputStream extends FilterInputStream {
33 | private final OutputStream out;
34 |
35 | public RepeaterInputStream(InputStream in, OutputStream out) {
36 | super(in);
37 | this.out = out;
38 | }
39 |
40 | @Override
41 | public int read() throws IOException {
42 | int read = in.read();
43 | if (read > 0) {
44 | out.write(read);
45 | }
46 | return read;
47 | }
48 |
49 | @Override
50 | public int read(byte[] b, int off, int len) throws IOException {
51 | int read = in.read(b, off, len);
52 | if (read > 0) {
53 | out.write(b, off, read);
54 | }
55 | return read;
56 | }
57 |
58 | public int read(byte[] b) throws IOException {
59 | return read(b, 0, b.length);
60 | }
61 |
62 | @Override
63 | /** Unsupported. */
64 | public boolean markSupported() {
65 | return false;
66 | }
67 |
68 | @Override
69 | /** Unsupported. */
70 | public void mark(int readlimit) {
71 | }
72 |
73 | @Override
74 | /** Unsupported. */
75 | public void reset() throws IOException {
76 | throw new IOException("Unsupported");
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/java-essentials/src/test/java/org/greenrobot/essentials/DateUtilsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Markus Junginger, greenrobot (http://greenrobot.de)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials;
18 |
19 | import org.junit.Assert;
20 | import org.junit.Test;
21 |
22 | import java.util.Calendar;
23 |
24 | public class DateUtilsTest {
25 |
26 | @Test
27 | public void testGetDayDifferenceOfReadableIntsPlusMinusNDays() {
28 | testGetDayDifferenceOfReadableIntsPlusMinusNDays(1);
29 | testGetDayDifferenceOfReadableIntsPlusMinusNDays(-1);
30 | }
31 |
32 | private void testGetDayDifferenceOfReadableIntsPlusMinusNDays(int sign) {
33 | Calendar calendar = Calendar.getInstance();
34 | DateUtils.setTime(calendar, 12, 0, 0, 0);
35 | int today = DateUtils.getDayAsReadableInt(calendar);
36 | for (int i = 1; i <= 5000; i++) {
37 | DateUtils.addDays(calendar, sign);
38 | int day = DateUtils.getDayAsReadableInt(calendar);
39 | int diff = DateUtils.getDayDifferenceOfReadableInts(today, day);
40 | Assert.assertEquals(sign * i, diff);
41 | }
42 | }
43 |
44 | @Test
45 | public void testGetDayDifferenceOfReadableInts() {
46 | checkDayDifference(20110101, 20110101, 0);
47 | checkDayDifference(20110101, 20110102, 1);
48 | checkDayDifference(20110101, 20110103, 2);
49 | checkDayDifference(20110101, 20110201, 31);
50 | checkDayDifference(20110101, 20110301, 59);
51 | checkDayDifference(20110102, 20110101, -1);
52 | checkDayDifference(20110103, 20110101, -2);
53 | checkDayDifference(20110201, 20110101, -31);
54 | checkDayDifference(20110301, 20110101, -59);
55 | checkDayDifference(20111231, 20120101, 1);
56 | }
57 |
58 | private void checkDayDifference(int day1, int day2, int expectedDifference) {
59 | int actualDifference = DateUtils.getDayDifferenceOfReadableInts(day1, day2);
60 | Assert.assertEquals(expectedDifference, actualDifference);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/java-essentials/src/test/java/org/greenrobot/essentials/LimitedInputStreamTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Markus Junginger, greenrobot (http://greenrobot.de)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials;
18 |
19 | import org.greenrobot.essentials.io.LimitedInputStream;
20 | import org.junit.Test;
21 |
22 | import java.io.BufferedInputStream;
23 | import java.io.ByteArrayInputStream;
24 | import java.io.IOException;
25 |
26 | import static org.junit.Assert.assertArrayEquals;
27 | import static org.junit.Assert.assertEquals;
28 |
29 | public class LimitedInputStreamTest {
30 | @Test
31 | public void testsBasics() throws IOException {
32 | ByteArrayInputStream in = new ByteArrayInputStream(new byte[]{1, 2, 3, 4});
33 | LimitedInputStream limited = new LimitedInputStream(in, 2);
34 | BufferedInputStream buffered = new BufferedInputStream(limited);
35 |
36 | byte[] readBuffer = new byte[4];
37 | assertEquals(2, buffered.read(readBuffer));
38 | assertArrayEquals(new byte[]{1, 2, 0, 0}, readBuffer);
39 | assertEquals(-1, buffered.read());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/java-essentials/src/test/java/org/greenrobot/essentials/ObjectCacheTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Markus Junginger, greenrobot (http://greenrobot.de)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials;
18 |
19 | import org.junit.Test;
20 |
21 | import static org.junit.Assert.*;
22 |
23 | public class ObjectCacheTest {
24 | @Test
25 | public void testBasics() {
26 | doTestBasics(ObjectCache.ReferenceType.SOFT);
27 | doTestBasics(ObjectCache.ReferenceType.STRONG);
28 | doTestBasics(ObjectCache.ReferenceType.WEAK);
29 | }
30 |
31 | private void doTestBasics(ObjectCache.ReferenceType referenceType) {
32 | ObjectCache cache = new ObjectCache(referenceType, 10, 0);
33 | String value = "foo";
34 | String value2 = "bar";
35 | String key = "mykey";
36 | assertNull(cache.get(key));
37 | assertNull(cache.put(key, value));
38 | assertTrue(cache.containsKey(key));
39 | assertTrue(cache.containsKeyWithValue(key));
40 | assertEquals(value, cache.get(key));
41 | assertEquals(value, cache.put(key, value2));
42 | assertEquals(value2, cache.get(key));
43 | assertEquals(value2, cache.remove(key));
44 | assertNull(value2, cache.get(key));
45 | assertFalse(cache.containsKey(key));
46 | assertFalse(cache.containsKeyWithValue(key));
47 | }
48 |
49 |
50 | @Test
51 | public void testMaxSize() {
52 | ObjectCache cache = createCacheWith4Entries(0);
53 | cache.put("5", "e");
54 | assertEquals(4, cache.size());
55 | assertNull(cache.get("1"));
56 | assertEquals(cache.get("5"), "e");
57 | assertEquals(1, cache.getCountEvicted());
58 | }
59 |
60 | @Test
61 | public void testEvictToTargetSize() {
62 | ObjectCache cache = createCacheWith4Entries(0);
63 | cache.evictToTargetSize(2);
64 | assertEquals(2, cache.size());
65 | assertEquals(cache.get("3"), "c");
66 | assertEquals(cache.get("4"), "d");
67 |
68 | cache.evictToTargetSize(0);
69 | assertEquals(0, cache.size());
70 | }
71 |
72 | @Test
73 | public void testExpired() throws InterruptedException {
74 | ObjectCache cache = new ObjectCache(ObjectCache.ReferenceType.STRONG, 4, 1);
75 | cache.put("1", "a");
76 | Thread.sleep(3);
77 | assertNull(cache.get("1"));
78 | assertEquals(0, cache.size());
79 | assertEquals(1, cache.getCountExpired());
80 | }
81 |
82 | @Test
83 | public void testCleanUpObsoleteEntries() throws InterruptedException {
84 | // Use more than one entry to detect ConcurrentModificationException
85 | ObjectCache cache = createCacheWith4Entries(1);
86 | Thread.sleep(3);
87 | cache.checkCleanUpObsoleteEntries();
88 | assertEquals(0, cache.size());
89 | assertEquals(4, cache.getCountExpired());
90 | }
91 |
92 | @Test
93 | public void testNotExpired() throws InterruptedException {
94 | ObjectCache cache = new ObjectCache(ObjectCache.ReferenceType.STRONG, 4, 1000);
95 | cache.put("1", "a");
96 | Thread.sleep(3);
97 | assertEquals(cache.get("1"), "a");
98 | assertEquals(0, cache.getCountExpired());
99 | }
100 |
101 | private ObjectCache createCacheWith4Entries(int expirationMillis) {
102 | ObjectCache cache = new ObjectCache(ObjectCache.ReferenceType.STRONG, 4, expirationMillis);
103 | cache.put("1", "a");
104 | cache.put("2", "b");
105 | cache.put("3", "c");
106 | cache.put("4", "d");
107 | assertEquals(4, cache.size());
108 | return cache;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/java-essentials/src/test/java/org/greenrobot/essentials/PrimitiveArrayUtilsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Markus Junginger, greenrobot (http://greenrobot.de)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials;
18 |
19 | import org.junit.Assert;
20 | import org.junit.Before;
21 | import org.junit.BeforeClass;
22 | import org.junit.Test;
23 |
24 | import java.nio.ByteBuffer;
25 | import java.nio.ByteOrder;
26 | import java.util.Random;
27 |
28 | public class PrimitiveArrayUtilsTest {
29 | private byte[] bytes;
30 | private ByteBuffer byteBufferLE;
31 | private ByteBuffer byteBufferBE;
32 |
33 | static PrimitiveArrayUtils primitiveArrayUtilsPotentiallyUnsafe;
34 | PrimitiveArrayUtils primitiveArrayUtilsSafe = PrimitiveArrayUtils.getInstanceSafe();
35 |
36 | @BeforeClass
37 | public static void setupBytes() {
38 | boolean hasUnsafe = PrimitiveArrayUtils.initUnsafeInstance();
39 | System.out.println("Unsafe available: " + hasUnsafe);
40 | primitiveArrayUtilsPotentiallyUnsafe = PrimitiveArrayUtils.getInstance();
41 | }
42 |
43 | @Before
44 | public void setUp() {
45 | bytes = new byte[102400];
46 | new Random(42).nextBytes(bytes);
47 |
48 | byteBufferLE = ByteBuffer.wrap(bytes);
49 | byteBufferLE.order(ByteOrder.LITTLE_ENDIAN);
50 | byteBufferBE = ByteBuffer.wrap(bytes);
51 | }
52 |
53 | @Test
54 | public void testGetIntLE() {
55 | for (int i = 0; i < bytes.length - 3; i++) {
56 | int expected = byteBufferLE.getInt(i);
57 | int value = primitiveArrayUtilsPotentiallyUnsafe.getIntLE(bytes, i);
58 | Assert.assertEquals(expected, value);
59 | }
60 | }
61 |
62 | @Test
63 | public void testGetIntLEPlainJava() {
64 | for (int i = 0; i < bytes.length - 3; i++) {
65 | int expected = byteBufferLE.getInt(i);
66 | int value = primitiveArrayUtilsSafe.getIntLE(bytes, i);
67 | Assert.assertEquals(expected, value);
68 | }
69 | }
70 |
71 | @Test
72 | public void testGetLongLE() {
73 | for (int i = 0; i < bytes.length - 7; i++) {
74 | long expected = byteBufferLE.getLong(i);
75 | long value = primitiveArrayUtilsPotentiallyUnsafe.getLongLE(bytes, i);
76 | Assert.assertEquals(expected, value);
77 | }
78 | }
79 |
80 | @Test
81 | public void testGetLongLEPlainJava() {
82 | for (int i = 0; i < bytes.length - 7; i++) {
83 | long expected = byteBufferLE.getLong(i);
84 | long value = primitiveArrayUtilsSafe.getLongLE(bytes, i);
85 | Assert.assertEquals(expected, value);
86 | }
87 | }
88 |
89 | @Test
90 | public void testGetIntBE() {
91 | for (int i = 0; i < bytes.length - 3; i++) {
92 | int expected = byteBufferBE.getInt(i);
93 | int value = primitiveArrayUtilsPotentiallyUnsafe.getIntBE(bytes, i);
94 | Assert.assertEquals(expected, value);
95 | }
96 | }
97 |
98 | @Test
99 | public void testGetIntBEPlainJava() {
100 | for (int i = 0; i < bytes.length - 3; i++) {
101 | int expected = byteBufferBE.getInt(i);
102 | int value = primitiveArrayUtilsSafe.getIntBE(bytes, i);
103 | Assert.assertEquals(expected, value);
104 | }
105 | }
106 |
107 | @Test
108 | public void testGetLongBE() {
109 | for (int i = 0; i < bytes.length - 7; i++) {
110 | long expected = byteBufferBE.getLong(i);
111 | long value = primitiveArrayUtilsPotentiallyUnsafe.getLongBE(bytes, i);
112 | Assert.assertEquals(expected, value);
113 | }
114 | }
115 |
116 | @Test
117 | public void testGetLongBEPlainJava() {
118 | for (int i = 0; i < bytes.length - 7; i++) {
119 | long expected = byteBufferBE.getLong(i);
120 | long value = primitiveArrayUtilsSafe.getLongBE(bytes, i);
121 | Assert.assertEquals(expected, value);
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/java-essentials/src/test/java/org/greenrobot/essentials/StringUtilsJvmTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Markus Junginger, greenrobot (http://greenrobot.de)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials;
18 |
19 | import com.google.common.hash.HashCode;
20 | import org.junit.Test;
21 |
22 | import static org.junit.Assert.assertEquals;
23 |
24 | public class StringUtilsJvmTest {
25 | @Test
26 | public void testHexBig() {
27 | for (int i = 0; i < 256 * 256; i++) {
28 | byte[] bytes = {(byte) (i >> 8), (byte) i};
29 |
30 | String hexExpected = HashCode.fromBytes(bytes).toString().toUpperCase();
31 | String hex = StringUtils.hex(bytes);
32 | assertEquals(hexExpected, hex);
33 |
34 | byte[] bytes2 = StringUtils.parseHex(hex);
35 | assertEquals(bytes[0], bytes2[0]);
36 | assertEquals(bytes[1], bytes2[1]);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/java-essentials/src/test/java/org/greenrobot/essentials/StringUtilsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Markus Junginger, greenrobot (http://greenrobot.de)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials;
18 |
19 | import org.junit.Test;
20 |
21 | import java.util.ArrayList;
22 | import java.util.Arrays;
23 | import java.util.List;
24 |
25 | import static org.junit.Assert.assertArrayEquals;
26 | import static org.junit.Assert.assertEquals;
27 |
28 | public class StringUtilsTest {
29 | private final static String LINES = "Line 1\nLine 2\n\nLine 4\r\nLine 5\r\n\r\nLine 7";
30 |
31 | @Test
32 | public void testSplitLines() {
33 | String[] lines = StringUtils.splitLines(LINES, false);
34 | assertEquals(7, lines.length);
35 |
36 | assertEquals("Line 1", lines[0]);
37 | assertEquals("Line 2", lines[1]);
38 | assertEquals("", lines[2]);
39 | assertEquals("Line 4", lines[3]);
40 | assertEquals("Line 5", lines[4]);
41 | assertEquals("", lines[5]);
42 | assertEquals("Line 7", lines[6]);
43 | }
44 |
45 | @Test
46 | public void testSplitLinesSkipEmptyLines() {
47 | String[] lines = StringUtils.splitLines(LINES, true);
48 | assertEquals(5, lines.length);
49 |
50 | assertEquals("Line 1", lines[0]);
51 | assertEquals("Line 2", lines[1]);
52 | assertEquals("Line 4", lines[2]);
53 | assertEquals("Line 5", lines[3]);
54 | assertEquals("Line 7", lines[4]);
55 | }
56 |
57 | @Test
58 | public void testSplit() throws Exception {
59 | assertArrayEquals(ss("John", "Doe"), StringUtils.split("John Doe", ' '));
60 | assertArrayEquals(ss("John", "", "Doe", ""), StringUtils.split("John Doe ", ' '));
61 | assertArrayEquals(ss("", "John", "Doe", ""), StringUtils.split(" John Doe ", ' '));
62 | assertArrayEquals(ss("John", "Christoph", "Doe"), StringUtils.split("John Christoph Doe", ' '));
63 | assertArrayEquals(ss("John", "", "", "Doe"), StringUtils.split("John,,,Doe", ','));
64 | assertArrayEquals(ss("John", "Doe", ""), StringUtils.split("John Doe ", ' '));
65 | assertArrayEquals(ss("John", "", "", ""), StringUtils.split("John,,,", ','));
66 | }
67 |
68 | private String[] ss(String... values) {
69 | return values;
70 | }
71 |
72 | @Test
73 | public void testFindLinesContaining() {
74 | String text = "LiXXXne 1\nLine 2\n\nLXXXine 4\r\nLine 5\r\nXXX\r\nLine 7";
75 | List lines = StringUtils.findLinesContaining(text, "XXX");
76 | assertEquals(3, lines.size());
77 |
78 | assertEquals("LiXXXne 1", lines.get(0));
79 | assertEquals("LXXXine 4", lines.get(1));
80 | assertEquals("XXX", lines.get(2));
81 | }
82 |
83 | @Test
84 | public void testConcatLines() {
85 | String[] lines = StringUtils.splitLines(LINES, false);
86 | ArrayList list = new ArrayList();
87 | for (String line : lines) {
88 | list.add(line);
89 | }
90 | String concated = StringUtils.join(list, "\n");
91 | assertEquals("Line 1\nLine 2\n\nLine 4\nLine 5\n\nLine 7", concated);
92 | }
93 |
94 | @Test
95 | public void testJoinIterable() {
96 | assertEquals("", StringUtils.join((Iterable) null, "blub"));
97 | List fooBarList = Arrays.asList("foo", "bar");
98 | assertEquals("foo,bar", StringUtils.join(fooBarList, ","));
99 | assertEquals("foo, bar", StringUtils.join(fooBarList, ", "));
100 | }
101 |
102 | @Test
103 | public void testJoinIntArray() {
104 | assertEquals("", StringUtils.join((int[]) null, "blub"));
105 | int[] ints = {42, 23};
106 | assertEquals("42,23", StringUtils.join(ints, ","));
107 | assertEquals("42, 23", StringUtils.join(ints, ", "));
108 | }
109 |
110 | @Test
111 | public void testJoinStringArray() {
112 | assertEquals("", StringUtils.join((String[]) null, "blub"));
113 | String[] fooBar = {"foo", "bar"};
114 | assertEquals("foo,bar", StringUtils.join(fooBar, ","));
115 | assertEquals("foo, bar", StringUtils.join(fooBar, ", "));
116 | }
117 |
118 | @Test
119 | public void testEllipsize() {
120 | assertEquals("He...", StringUtils.ellipsize("Hello world", 5));
121 | assertEquals("Hell>", StringUtils.ellipsize("Hello world", 5, ">"));
122 | }
123 |
124 | @Test
125 | public void testHex() {
126 | assertArrayEquals(new byte[] {0, 0x66, -1}, StringUtils.parseHex("0066FF"));
127 | }
128 |
129 | @Test
130 | public void testDigests() {
131 | String text = "The quick brown fox jumps over the lazy dog";
132 | assertEquals("9E107D9D372BB6826BD81D3542A419D6", StringUtils.md5(text));
133 | assertEquals("2FD4E1C67A2D28FCED849EE1BB76E7391B93EB12", StringUtils.sha1(text));
134 | assertEquals("D7A8FBB307D7809469CA9ABCB0082E4F8D5651E46D3CDB762D02D0BF37C9E592",
135 | StringUtils.sha256(text));
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/java-essentials/src/test/java/org/greenrobot/essentials/collections/LongHashMapTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Markus Junginger, greenrobot (http://greenrobot.de)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.greenrobot.essentials.collections;
18 |
19 | import org.junit.Test;
20 |
21 | import java.util.Arrays;
22 | import java.util.Random;
23 |
24 | import static org.junit.Assert.*;
25 |
26 | public class LongHashMapTest {
27 |
28 | Random random;
29 | private String traceName;
30 | private long start;
31 |
32 | public LongHashMapTest() {
33 | this.random = new Random();
34 | }
35 |
36 | @Test
37 | public void testLongHashMapSimple() {
38 | LongHashMap