Skip to content

Commit 12f937c

Browse files
committed
refactor!: improve reducer API
1 parent 821ca1e commit 12f937c

16 files changed

Lines changed: 173 additions & 510 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Since the `AString` represent any generic `CharSequence`, it might be useful
6464
to transform the value before its use.
6565

6666
aString.format("arg", AppId)
67-
aString.defaultIfNull("value")
67+
aString.ifNull("value")
6868
aString.nullIfBlank()
6969
aString.mapToString()
7070
aString.trim()

astring/src/androidTest/java/xyz/tynn/astring/AStringReducerAndroidTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import static org.junit.Assert.assertEquals;
77
import static org.junit.Assert.assertNotEquals;
88
import static xyz.tynn.astring.AStringFactory.createFromCharSequence;
9+
import static xyz.tynn.astring.AStringFactory.getAppId;
10+
import static xyz.tynn.astring.AStringFactory.getAppVersion;
911
import static xyz.tynn.astring.test.AStringAssert.assertParcelableAStringInvocation;
1012

1113
import androidx.annotation.NonNull;
@@ -17,7 +19,7 @@
1719

1820
public class AStringReducerAndroidTest {
1921

20-
private final Iterable<AString> aStrings = List.of(AString.Null);
22+
private final Iterable<AString> aStrings = List.of(getAppId(), getAppVersion());
2123

2224
@Test
2325
public void delegate_should_implement_parcelable() {

astring/src/androidTest/java/xyz/tynn/astring/ParcelableAStringTest.java

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@
2020

2121
public class ParcelableAStringTest {
2222

23-
private static final Locale LOCALE = Locale.UK;
24-
private static final int RES_ID = 123;
25-
private static final int QUANTITY = 456;
2623
private static final AString FORMAT = new FormatAString();
2724
private static final Object[] FORMAT_ARGS = {"arg1", 2, 3L, 4.5, 6F, new Date(), Wrapper.wrap("test-string")};
2825

@@ -36,24 +33,24 @@ public void Wrapper_should_implement_parcelable() {
3633

3734
@Test
3835
public void Format_should_implement_parcelable() {
39-
assertParcelableAStringEquality(Format.wrap(FORMAT, LOCALE, FORMAT_ARGS));
40-
assertParcelableAStringInvocation(Format.wrap(FORMAT, LOCALE, FORMAT_ARGS));
36+
assertParcelableAStringEquality(Format.wrap(FORMAT, Locale.UK, FORMAT_ARGS));
37+
assertParcelableAStringInvocation(Format.wrap(FORMAT, Locale.UK, FORMAT_ARGS));
4138
assertParcelableAStringEquality(Format.wrap(FORMAT, null, FORMAT_ARGS));
4239
assertParcelableAStringInvocation(Format.wrap(FORMAT, null, FORMAT_ARGS));
43-
assertParcelableAStringEquality(Format.wrap(FORMAT, LOCALE, null));
44-
assertParcelableAStringInvocation(Format.wrap(FORMAT, LOCALE, null));
40+
assertParcelableAStringEquality(Format.wrap(FORMAT, Locale.UK, null));
41+
assertParcelableAStringInvocation(Format.wrap(FORMAT, Locale.UK, null));
4542
assertParcelableAStringEquality(Format.wrap(FORMAT, null, null));
4643
assertParcelableAStringInvocation(Format.wrap(FORMAT, null, null));
4744
}
4845

4946
@Test
5047
public void Resource_should_implement_parcelable() {
51-
assertParcelableAStringEquality(Resource.wrap(RES_ID, null));
52-
assertParcelableAStringEquality(Resource.wrap(RES_ID, QUANTITY));
53-
assertParcelableAStringEquality(Resource.wrap(RES_ID, null, FORMAT_ARGS));
54-
assertParcelableAStringEquality(Resource.wrap(RES_ID, QUANTITY, FORMAT_ARGS));
55-
assertParcelableAStringEquality(Resource.wrap(RES_ID, null, null));
56-
assertParcelableAStringEquality(Resource.wrap(RES_ID, QUANTITY, null));
48+
assertParcelableAStringEquality(Resource.wrap(123, null));
49+
assertParcelableAStringEquality(Resource.wrap(123, 456));
50+
assertParcelableAStringEquality(Resource.wrap(123, null, FORMAT_ARGS));
51+
assertParcelableAStringEquality(Resource.wrap(123, 456, FORMAT_ARGS));
52+
assertParcelableAStringEquality(Resource.wrap(123, null, null));
53+
assertParcelableAStringEquality(Resource.wrap(123, 456, null));
5754
}
5855

5956
@Test
@@ -65,18 +62,22 @@ public void Delegate_should_implement_parcelable() {
6562
assertParcelableAStringEquality(Delegate.wrap(Provider.AppVersion));
6663
assertParcelableAStringInvocation(Delegate.wrap(Provider.AppVersion));
6764
assertParcelableAStringInvocation(Delegate.wrap(Object::toString));
68-
assertParcelableAStringIdentity(Delegate.wrap((AString) null, null));
69-
assertParcelableAStringInvocation(Delegate.wrap((AString) null, null));
70-
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Predicate.NonBlank));
71-
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Predicate.NonBlank));
72-
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Predicate.NonEmpty));
73-
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Predicate.NonEmpty));
74-
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Predicate.NonNull));
75-
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Predicate.NonNull));
76-
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Transformer.ToString));
77-
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Transformer.ToString));
78-
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Transformer.Trim));
79-
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Transformer.Trim));
65+
assertParcelableAStringIdentity(Delegate.wrap((AString.Transformer) null, null));
66+
assertParcelableAStringInvocation(Delegate.wrap((AString.Transformer) null, null));
67+
assertParcelableAStringEquality(Delegate.wrap(Transformer.ToString, FORMAT));
68+
assertParcelableAStringInvocation(Delegate.wrap(Transformer.ToString, FORMAT));
69+
assertParcelableAStringEquality(Delegate.wrap(Transformer.Trim, FORMAT));
70+
assertParcelableAStringInvocation(Delegate.wrap(Transformer.Trim, FORMAT));
71+
assertParcelableAStringIdentity(Delegate.wrap((AString.Reducer) null));
72+
assertParcelableAStringInvocation(Delegate.wrap((AString.Reducer) null));
73+
assertParcelableAStringEquality(Delegate.wrap(Predicate.AnyValue, FORMAT));
74+
assertParcelableAStringInvocation(Delegate.wrap(Predicate.AnyValue, FORMAT));
75+
assertParcelableAStringEquality(Delegate.wrap(Predicate.NonBlank, FORMAT));
76+
assertParcelableAStringInvocation(Delegate.wrap(Predicate.NonBlank, FORMAT));
77+
assertParcelableAStringEquality(Delegate.wrap(Predicate.NonEmpty, FORMAT));
78+
assertParcelableAStringInvocation(Delegate.wrap(Predicate.NonEmpty, FORMAT));
79+
assertParcelableAStringEquality(Delegate.wrap(Predicate.NonNull, FORMAT));
80+
assertParcelableAStringInvocation(Delegate.wrap(Predicate.NonNull, FORMAT));
8081
}
8182

8283
private static class FormatAString implements AString {

astring/src/androidTest/kotlin/xyz/tynn/astring/AStringReducerKtAndroidTest.kt

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@ import xyz.tynn.astring.test.AStringAssert.assertParcelableAStringInvocation
1212
@InefficientAStringApi
1313
internal class AStringReducerKtAndroidTest {
1414

15-
private val aString1 = AString.Null
16-
private val aString2 = "+".asAString()
17-
private val aStrings = listOf(aString1, aString2)
18-
private val aStringIterable = sequenceOf(aString1, aString2).asIterable()
15+
private val aStrings = listOf(AString.Null, AppId)
16+
private val aStringIterable = sequenceOf(AString.Null, AppId).asIterable()
1917

2018
@Test
2119
fun firstNonBlank_should_be_parcelable() {
22-
assertParcelableAStringEquality(firstNonBlank(aString1, aString2))
23-
assertParcelableAStringInvocation(firstNonBlank(aString1, aString2))
20+
assertParcelableAStringEquality(firstNonBlank(AString.Null, AppId))
21+
assertParcelableAStringInvocation(firstNonBlank(AString.Null, AppId))
2422
assertParcelableAStringEquality(aStrings.firstNonBlank())
2523
assertParcelableAStringInvocation(aStrings.firstNonBlank())
2624
assertParcelableAStringEquality(aStringIterable.firstNonBlank())
@@ -29,8 +27,8 @@ internal class AStringReducerKtAndroidTest {
2927

3028
@Test
3129
fun firstNonEmpty_should_be_parcelable() {
32-
assertParcelableAStringEquality(firstNonEmpty(aString1, aString2))
33-
assertParcelableAStringInvocation(firstNonEmpty(aString1, aString2))
30+
assertParcelableAStringEquality(firstNonEmpty(AString.Null, AppId))
31+
assertParcelableAStringInvocation(firstNonEmpty(AString.Null, AppId))
3432
assertParcelableAStringEquality(aStrings.firstNonEmpty())
3533
assertParcelableAStringInvocation(aStrings.firstNonEmpty())
3634
assertParcelableAStringEquality(aStringIterable.firstNonEmpty())
@@ -39,8 +37,8 @@ internal class AStringReducerKtAndroidTest {
3937

4038
@Test
4139
fun firstNonNull_should_be_parcelable() {
42-
assertParcelableAStringEquality(firstNonNull(aString1, aString2))
43-
assertParcelableAStringInvocation(firstNonNull(aString1, aString2))
40+
assertParcelableAStringEquality(firstNonNull(AString.Null, AppId))
41+
assertParcelableAStringInvocation(firstNonNull(AString.Null, AppId))
4442
assertParcelableAStringEquality(aStrings.firstNonNull())
4543
assertParcelableAStringInvocation(aStrings.firstNonNull())
4644
assertParcelableAStringEquality(aStringIterable.firstNonNull())
@@ -49,8 +47,8 @@ internal class AStringReducerKtAndroidTest {
4947

5048
@Test
5149
fun join_should_be_parcelable() {
52-
assertParcelableAStringEquality(join(aString1, aString2, separator = "-"))
53-
assertParcelableAStringInvocation(join(aString1, aString2, separator = "-"))
50+
assertParcelableAStringEquality(join(AString.Null, AppId, separator = "-"))
51+
assertParcelableAStringInvocation(join(AString.Null, AppId, separator = "-"))
5452
assertParcelableAStringEquality(aStrings.join(separator = "-"))
5553
assertParcelableAStringInvocation(aStrings.join(separator = "-"))
5654
assertParcelableAStringEquality(aStringIterable.join(separator = "-"))
@@ -59,8 +57,8 @@ internal class AStringReducerKtAndroidTest {
5957

6058
@Test
6159
fun joinNonBlank_should_be_parcelable() {
62-
assertParcelableAStringEquality(joinNonBlank(aString1, aString2, separator = "-"))
63-
assertParcelableAStringInvocation(joinNonBlank(aString1, aString2, separator = "-"))
60+
assertParcelableAStringEquality(joinNonBlank(AString.Null, AppId, separator = "-"))
61+
assertParcelableAStringInvocation(joinNonBlank(AString.Null, AppId, separator = "-"))
6462
assertParcelableAStringEquality(aStrings.joinNonBlank(separator = "-"))
6563
assertParcelableAStringInvocation(aStrings.joinNonBlank(separator = "-"))
6664
assertParcelableAStringEquality(aStringIterable.joinNonBlank(separator = "-"))
@@ -69,8 +67,8 @@ internal class AStringReducerKtAndroidTest {
6967

7068
@Test
7169
fun joinNonEmpty_should_be_parcelable() {
72-
assertParcelableAStringEquality(joinNonEmpty(aString1, aString2, separator = "-"))
73-
assertParcelableAStringInvocation(joinNonEmpty(aString1, aString2, separator = "-"))
70+
assertParcelableAStringEquality(joinNonEmpty(AString.Null, AppId, separator = "-"))
71+
assertParcelableAStringInvocation(joinNonEmpty(AString.Null, AppId, separator = "-"))
7472
assertParcelableAStringEquality(aStrings.joinNonEmpty(separator = "-"))
7573
assertParcelableAStringInvocation(aStrings.joinNonEmpty(separator = "-"))
7674
assertParcelableAStringEquality(aStringIterable.joinNonEmpty(separator = "-"))
@@ -79,8 +77,8 @@ internal class AStringReducerKtAndroidTest {
7977

8078
@Test
8179
fun joinNonNull_should_be_parcelable() {
82-
assertParcelableAStringEquality(joinNonNull(aString1, aString2, separator = "-"))
83-
assertParcelableAStringInvocation(joinNonNull(aString1, aString2, separator = "-"))
80+
assertParcelableAStringEquality(joinNonNull(AString.Null, AppId, separator = "-"))
81+
assertParcelableAStringInvocation(joinNonNull(AString.Null, AppId, separator = "-"))
8482
assertParcelableAStringEquality(aStrings.joinNonNull(separator = "-"))
8583
assertParcelableAStringInvocation(aStrings.joinNonNull(separator = "-"))
8684
assertParcelableAStringEquality(aStringIterable.joinNonNull(separator = "-"))
@@ -91,15 +89,15 @@ internal class AStringReducerKtAndroidTest {
9189
@Suppress("RedundantSamConstructor")
9290
fun interface_should_not_be_efficient() {
9391
assertNotEquals(
94-
reduce(aString1, aString2, reducer = AString.Reducer { "" }),
95-
reduce(aString1, aString2, reducer = AString.Reducer { "" }),
92+
reduce(AString.Null, AppId, reducer = AString.Reducer { "" }),
93+
reduce(AString.Null, AppId, reducer = AString.Reducer { "" }),
9694
)
9795
assertNotEquals(
98-
reduce(aString1, aString2, reducer = AString.Reducer { "" }),
96+
reduce(AString.Null, AppId, reducer = AString.Reducer { "" }),
9997
aStrings.reduce(reducer = AString.Reducer { "" }),
10098
)
10199
assertNotEquals(
102-
reduce(aString1, aString2, reducer = AString.Reducer { "" }),
100+
reduce(AString.Null, AppId, reducer = AString.Reducer { "" }),
103101
aStringIterable.reduce(reducer = AString.Reducer { "" }),
104102
)
105103
}
@@ -108,31 +106,31 @@ internal class AStringReducerKtAndroidTest {
108106
fun interface_val_should_be_efficient() {
109107
val function = AString.Reducer { "" }
110108
assertEquals(
111-
reduce(aString1, aString2, reducer = function),
112-
reduce(aString1, aString2, reducer = function),
109+
reduce(AString.Null, AppId, reducer = function),
110+
reduce(AString.Null, AppId, reducer = function),
113111
)
114112
assertEquals(
115-
reduce(aString1, aString2, reducer = function),
113+
reduce(AString.Null, AppId, reducer = function),
116114
aStrings.reduce(reducer = function),
117115
)
118116
assertEquals(
119-
reduce(aString1, aString2, reducer = function),
117+
reduce(AString.Null, AppId, reducer = function),
120118
aStringIterable.reduce(reducer = function),
121119
)
122120
}
123121

124122
@Test
125123
fun instance_should_be_efficient() {
126124
assertEquals(
127-
reduce(aString1, aString2, reducer = Reducer()),
128-
reduce(aString1, aString2, reducer = Reducer()),
125+
reduce(AString.Null, AppId, reducer = Reducer()),
126+
reduce(AString.Null, AppId, reducer = Reducer()),
129127
)
130128
assertEquals(
131-
reduce(aString1, aString2, reducer = Reducer()),
129+
reduce(AString.Null, AppId, reducer = Reducer()),
132130
aStrings.reduce(reducer = Reducer()),
133131
)
134132
assertEquals(
135-
reduce(aString1, aString2, reducer = Reducer()),
133+
reduce(AString.Null, AppId, reducer = Reducer()),
136134
aStringIterable.reduce(reducer = Reducer()),
137135
)
138136
}
@@ -141,31 +139,31 @@ internal class AStringReducerKtAndroidTest {
141139
fun instance_val_should_be_efficient() {
142140
val function = Reducer()
143141
assertEquals(
144-
reduce(aString1, aString2, reducer = function),
145-
reduce(aString1, aString2, reducer = function),
142+
reduce(AString.Null, AppId, reducer = function),
143+
reduce(AString.Null, AppId, reducer = function),
146144
)
147145
assertEquals(
148-
reduce(aString1, aString2, reducer = function),
146+
reduce(AString.Null, AppId, reducer = function),
149147
aStrings.reduce(reducer = function),
150148
)
151149
assertEquals(
152-
reduce(aString1, aString2, reducer = function),
150+
reduce(AString.Null, AppId, reducer = function),
153151
aStringIterable.reduce(reducer = function),
154152
)
155153
}
156154

157155
@Test
158156
fun function_reference_should_be_efficient() {
159157
assertEquals(
160-
reduce(aString1, aString2, reducer = ::function),
161-
reduce(aString1, aString2, reducer = ::function),
158+
reduce(AString.Null, AppId, reducer = ::function),
159+
reduce(AString.Null, AppId, reducer = ::function),
162160
)
163161
assertEquals(
164-
reduce(aString1, aString2, reducer = ::function),
162+
reduce(AString.Null, AppId, reducer = ::function),
165163
aStrings.reduce(reducer = ::function),
166164
)
167165
assertEquals(
168-
reduce(aString1, aString2, reducer = ::function),
166+
reduce(AString.Null, AppId, reducer = ::function),
169167
aStringIterable.reduce(reducer = ::function),
170168
)
171169
}
@@ -174,31 +172,31 @@ internal class AStringReducerKtAndroidTest {
174172
fun function_reference_val_should_be_efficient() {
175173
val function = ::function
176174
assertEquals(
177-
reduce(aString1, aString2, reducer = function),
178-
reduce(aString1, aString2, reducer = function),
175+
reduce(AString.Null, AppId, reducer = function),
176+
reduce(AString.Null, AppId, reducer = function),
179177
)
180178
assertEquals(
181-
reduce(aString1, aString2, reducer = function),
179+
reduce(AString.Null, AppId, reducer = function),
182180
aStrings.reduce(reducer = function),
183181
)
184182
assertEquals(
185-
reduce(aString1, aString2, reducer = function),
183+
reduce(AString.Null, AppId, reducer = function),
186184
aStringIterable.reduce(reducer = function),
187185
)
188186
}
189187

190188
@Test
191189
fun lambda_should_not_be_efficient() {
192190
assertNotEquals(
193-
reduce(aString1, aString2) { it.toString() },
194-
reduce(aString1, aString2) { it.toString() },
191+
reduce(AString.Null, AppId) { it.toString() },
192+
reduce(AString.Null, AppId) { it.toString() },
195193
)
196194
assertNotEquals(
197-
reduce(aString1, aString2) { it.toString() },
195+
reduce(AString.Null, AppId) { it.toString() },
198196
aStrings.reduce { it.toString() },
199197
)
200198
assertNotEquals(
201-
reduce(aString1, aString2) { it.toString() },
199+
reduce(AString.Null, AppId) { it.toString() },
202200
aStringIterable.reduce { it.toString() },
203201
)
204202
}
@@ -207,15 +205,15 @@ internal class AStringReducerKtAndroidTest {
207205
fun lambda_val_should_be_efficient() {
208206
val function = { _: Iterable<CharSequence?> -> "" }
209207
assertEquals(
210-
reduce(aString1, aString2, reducer = function),
211-
reduce(aString1, aString2, reducer = function),
208+
reduce(AString.Null, AppId, reducer = function),
209+
reduce(AString.Null, AppId, reducer = function),
212210
)
213211
assertEquals(
214-
reduce(aString1, aString2, reducer = function),
212+
reduce(AString.Null, AppId, reducer = function),
215213
aStrings.reduce(reducer = function),
216214
)
217215
assertEquals(
218-
reduce(aString1, aString2, reducer = function),
216+
reduce(AString.Null, AppId, reducer = function),
219217
aStringIterable.reduce(reducer = function),
220218
)
221219
}

astring/src/main/java/xyz/tynn/astring/Delegate.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
import androidx.annotation.Nullable;
1616

1717
import java.io.Serializable;
18-
import java.util.ArrayList;
1918
import java.util.Arrays;
2019
import java.util.Collection;
2120
import java.util.Iterator;
21+
import java.util.LinkedList;
2222
import java.util.Objects;
2323

2424
final class Delegate implements AString {
@@ -43,21 +43,22 @@ static AString wrap(AString.Provider provider) {
4343

4444
@InefficientAStringApi
4545
static AString wrap(AString.Reducer reducer, AString... aStrings) {
46-
if (reducer == null || aStrings == null || aStrings.length == 0) return Null;
47-
return new Delegate(new Serializer.Reducer(reducer), aStrings);
46+
if (reducer == null || aStrings == null) return Null;
47+
AString aString = Wrapper.maybeReduce(reducer, aStrings);
48+
return aString != null ? aString : new Delegate(new Serializer.Reducer(reducer), aStrings);
4849
}
4950

5051
@InefficientAStringApi
5152
static AString wrap(AString.Reducer reducer, Iterable<AString> aStrings) {
5253
if (reducer == null || aStrings == null) return Null;
5354
Collection<AString> list = aStrings instanceof Collection<?>
54-
? (Collection<AString>) aStrings : new ArrayList<>();
55+
? (Collection<AString>) aStrings : new LinkedList<>();
5556
if (list != aStrings) for (AString aString : aStrings) list.add(aString);
5657
return wrap(reducer, list.toArray(EMPTY));
5758
}
5859

5960
@InefficientAStringApi
60-
static AString wrap(AString aString, Transformer transformer) {
61+
static AString wrap(Transformer transformer, AString aString) {
6162
if (transformer == null) return Null;
6263
if (aString == null || aString == Null) return Wrapper.wrap(transformer.invoke(null));
6364
if (aString instanceof Wrapper) return ((Wrapper) aString).map(transformer);

0 commit comments

Comments
 (0)