Skip to content

Commit 2ad196c

Browse files
authored
feat: add new dedup utility method to Option classes (#2063)
When providing options duplicates are not allowed, however there are times when you might end up providing two options which would collide. These new utility methods encapsulate the logic necessary to deduplicate any overlap wil returing an array which can be passed directly to the respective operation method. `dedupe` utility methods added to each of the following Option classes: * Storage.BlobGetOption.dedupe(); * Storage.BlobListOption.dedupe(); * Storage.BlobSourceOption.dedupe(); * Storage.BlobTargetOption.dedupe(); * Storage.BlobWriteOption.dedupe(); * Storage.BucketGetOption.dedupe(); * Storage.BucketListOption.dedupe(); * Storage.BucketSourceOption.dedupe(); * Storage.BucketTargetOption.dedupe(); * Storage.CreateHmacKeyOption.dedupe(); * Storage.DeleteHmacKeyOption.dedupe(); * Storage.GetHmacKeyOption.dedupe(); * Storage.ListHmacKeysOption.dedupe(); * Storage.UpdateHmacKeyOption.dedupe(); * Bucket.BlobTargetOption.dedupe(); * Bucket.BlobWriteOption.dedupe(); * Bucket.BucketSourceOption.dedupe(); * Blob.BlobSourceOption.dedupe(); There are overloads which accept a collection or array in addition to varargs.
1 parent e48862a commit 2ad196c

File tree

5 files changed

+818
-4
lines changed

5 files changed

+818
-4
lines changed

google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.security.Key;
4141
import java.time.OffsetDateTime;
4242
import java.util.Arrays;
43+
import java.util.Collection;
4344
import java.util.List;
4445
import java.util.Map;
4546
import java.util.Objects;
@@ -163,6 +164,40 @@ public static BlobSourceOption shouldReturnRawInputStream(boolean shouldReturnRa
163164
return new BlobSourceOption(UnifiedOpts.returnRawInputStream(shouldReturnRawInputStream));
164165
}
165166

167+
/**
168+
* Deduplicate any options which are the same parameter. The value which comes last in {@code
169+
* os} will be the value included in the return.
170+
*/
171+
@BetaApi
172+
public static BlobSourceOption[] dedupe(BlobSourceOption... os) {
173+
return Option.dedupe(BlobSourceOption[]::new, os);
174+
}
175+
176+
/**
177+
* Deduplicate any options which are the same parameter.
178+
*
179+
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
180+
* in the return. All options from {@code os} will override their counterparts in {@code
181+
* collection}.
182+
*/
183+
@BetaApi
184+
public static BlobSourceOption[] dedupe(
185+
Collection<BlobSourceOption> collection, BlobSourceOption... os) {
186+
return Option.dedupe(BlobSourceOption[]::new, collection, os);
187+
}
188+
189+
/**
190+
* Deduplicate any options which are the same parameter.
191+
*
192+
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
193+
* in the return. All options from {@code os} will override their counterparts in {@code
194+
* collection}.
195+
*/
196+
@BetaApi
197+
public static BlobSourceOption[] dedupe(BlobSourceOption[] array, BlobSourceOption... os) {
198+
return Option.dedupe(BlobSourceOption[]::new, array, os);
199+
}
200+
166201
static Storage.BlobSourceOption[] toSourceOptions(
167202
BlobInfo blobInfo, BlobSourceOption... options) {
168203
Storage.BlobSourceOption[] convertedOptions = new Storage.BlobSourceOption[options.length];

google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import com.google.cloud.storage.UnifiedOpts.BucketSourceOpt;
3131
import com.google.cloud.storage.UnifiedOpts.ObjectOptExtractor;
3232
import com.google.cloud.storage.UnifiedOpts.ObjectTargetOpt;
33-
import com.google.cloud.storage.UnifiedOpts.OptionShim;
3433
import com.google.common.collect.ImmutableList;
3534
import com.google.common.collect.Lists;
3635
import java.io.IOException;
@@ -41,6 +40,7 @@
4140
import java.time.Duration;
4241
import java.time.OffsetDateTime;
4342
import java.util.Arrays;
43+
import java.util.Collection;
4444
import java.util.List;
4545
import java.util.Map;
4646
import java.util.Objects;
@@ -99,6 +99,41 @@ public static BucketSourceOption userProject(@NonNull String userProject) {
9999
return new BucketSourceOption(UnifiedOpts.userProject(userProject));
100100
}
101101

102+
/**
103+
* Deduplicate any options which are the same parameter. The value which comes last in {@code
104+
* os} will be the value included in the return.
105+
*/
106+
@BetaApi
107+
public static BucketSourceOption[] dedupe(BucketSourceOption... os) {
108+
return Option.dedupe(BucketSourceOption[]::new, os);
109+
}
110+
111+
/**
112+
* Deduplicate any options which are the same parameter.
113+
*
114+
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
115+
* in the return. All options from {@code os} will override their counterparts in {@code
116+
* collection}.
117+
*/
118+
@BetaApi
119+
public static BucketSourceOption[] dedupe(
120+
Collection<BucketSourceOption> collection, BucketSourceOption... os) {
121+
return Option.dedupe(BucketSourceOption[]::new, collection, os);
122+
}
123+
124+
/**
125+
* Deduplicate any options which are the same parameter.
126+
*
127+
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
128+
* in the return. All options from {@code os} will override their counterparts in {@code
129+
* collection}.
130+
*/
131+
@BetaApi
132+
public static BucketSourceOption[] dedupe(
133+
BucketSourceOption[] array, BucketSourceOption... os) {
134+
return Option.dedupe(BucketSourceOption[]::new, array, os);
135+
}
136+
102137
static Storage.BucketSourceOption[] toSourceOptions(
103138
BucketInfo bucketInfo, BucketSourceOption... options) {
104139
Storage.BucketSourceOption[] convertedOptions =
@@ -237,6 +272,40 @@ public static BlobTargetOption userProject(@NonNull String userProject) {
237272
return new BlobTargetOption(UnifiedOpts.userProject(userProject));
238273
}
239274

275+
/**
276+
* Deduplicate any options which are the same parameter. The value which comes last in {@code
277+
* os} will be the value included in the return.
278+
*/
279+
@BetaApi
280+
public static BlobTargetOption[] dedupe(BlobTargetOption... os) {
281+
return Option.dedupe(BlobTargetOption[]::new, os);
282+
}
283+
284+
/**
285+
* Deduplicate any options which are the same parameter.
286+
*
287+
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
288+
* in the return. All options from {@code os} will override their counterparts in {@code
289+
* collection}.
290+
*/
291+
@BetaApi
292+
public static BlobTargetOption[] dedupe(
293+
Collection<BlobTargetOption> collection, BlobTargetOption... os) {
294+
return Option.dedupe(BlobTargetOption[]::new, collection, os);
295+
}
296+
297+
/**
298+
* Deduplicate any options which are the same parameter.
299+
*
300+
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
301+
* in the return. All options from {@code os} will override their counterparts in {@code
302+
* collection}.
303+
*/
304+
@BetaApi
305+
public static BlobTargetOption[] dedupe(BlobTargetOption[] array, BlobTargetOption... os) {
306+
return Option.dedupe(BlobTargetOption[]::new, array, os);
307+
}
308+
240309
static Storage.BlobTargetOption[] toTargetOptions(
241310
BlobInfo blobInfo, BlobTargetOption... options) {
242311
Storage.BlobTargetOption[] targetOptions = new Storage.BlobTargetOption[options.length];
@@ -255,7 +324,7 @@ static Storage.BlobTargetOption[] toTargetOptions(
255324
}
256325

257326
/** Class for specifying blob write options when {@code Bucket} methods are used. */
258-
public static class BlobWriteOption extends OptionShim<ObjectTargetOpt> implements Serializable {
327+
public static class BlobWriteOption extends Option<ObjectTargetOpt> implements Serializable {
259328

260329
private static final long serialVersionUID = 59762268190041584L;
261330

@@ -366,6 +435,40 @@ public static BlobWriteOption userProject(@NonNull String userProject) {
366435
return new BlobWriteOption(UnifiedOpts.userProject(userProject));
367436
}
368437

438+
/**
439+
* Deduplicate any options which are the same parameter. The value which comes last in {@code
440+
* os} will be the value included in the return.
441+
*/
442+
@BetaApi
443+
public static BlobWriteOption[] dedupe(BlobWriteOption... os) {
444+
return Option.dedupe(BlobWriteOption[]::new, os);
445+
}
446+
447+
/**
448+
* Deduplicate any options which are the same parameter.
449+
*
450+
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
451+
* in the return. All options from {@code os} will override their counterparts in {@code
452+
* collection}.
453+
*/
454+
@BetaApi
455+
public static BlobWriteOption[] dedupe(
456+
Collection<BlobWriteOption> collection, BlobWriteOption... os) {
457+
return Option.dedupe(BlobWriteOption[]::new, collection, os);
458+
}
459+
460+
/**
461+
* Deduplicate any options which are the same parameter.
462+
*
463+
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
464+
* in the return. All options from {@code os} will override their counterparts in {@code
465+
* collection}.
466+
*/
467+
@BetaApi
468+
public static BlobWriteOption[] dedupe(BlobWriteOption[] array, BlobWriteOption... os) {
469+
return Option.dedupe(BlobWriteOption[]::new, array, os);
470+
}
471+
369472
static Storage.BlobWriteOption[] toWriteOptions(BlobInfo blobInfo, BlobWriteOption... options) {
370473
Storage.BlobWriteOption[] convertedOptions = new Storage.BlobWriteOption[options.length];
371474
for (int i = 0; i < options.length; i++) {

google-cloud-storage/src/main/java/com/google/cloud/storage/Option.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818

1919
import com.google.cloud.storage.UnifiedOpts.Opt;
2020
import java.io.Serializable;
21+
import java.util.Arrays;
22+
import java.util.Collection;
23+
import java.util.function.IntFunction;
24+
import java.util.stream.Collectors;
25+
import java.util.stream.Stream;
2126

2227
/** Base class for Storage operation option. */
2328
@Deprecated
@@ -29,4 +34,32 @@ public abstract class Option<O extends Opt> extends UnifiedOpts.OptionShim<O>
2934
Option(O opt) {
3035
super(opt);
3136
}
37+
38+
@SafeVarargs
39+
static <O extends Option<?>> O[] dedupe(IntFunction<O[]> gen, O... os) {
40+
return dedupe(gen, Arrays.stream(os));
41+
}
42+
43+
@SafeVarargs
44+
static <O extends Option<?>> O[] dedupe(IntFunction<O[]> gen, Collection<O> collection, O... os) {
45+
return dedupe(gen, Stream.of(collection.stream(), Arrays.stream(os)).flatMap(s -> s));
46+
}
47+
48+
@SafeVarargs
49+
static <O extends Option<?>> O[] dedupe(IntFunction<O[]> gen, O[] array, O... os) {
50+
return dedupe(gen, Stream.of(Arrays.stream(array), Arrays.stream(os)).flatMap(s -> s));
51+
}
52+
53+
/**
54+
* All Options contain an {@link Opt}, {@code Opt}s are distinct classes allowing us to group
55+
* based on those classes. Once grouped, we select the last element to provide last wins behavior.
56+
*
57+
* <p>Each of these helpers is an internal implementation detail, primarily due to the fact that
58+
* generic arrays can not be instantiated in Java and requires a factory to be passed in.
59+
*/
60+
private static <O extends Option<?>> O[] dedupe(IntFunction<O[]> gen, Stream<O> s) {
61+
return s.collect(Collectors.groupingBy(o -> o.getOpt().getClass())).values().stream()
62+
.map(l -> l.get(l.size() - 1))
63+
.toArray(gen);
64+
}
3265
}

0 commit comments

Comments
 (0)