Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add new dedupe utility method to Option classes #2063

Merged
merged 1 commit into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.security.Key;
import java.time.OffsetDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -163,6 +164,40 @@ public static BlobSourceOption shouldReturnRawInputStream(boolean shouldReturnRa
return new BlobSourceOption(UnifiedOpts.returnRawInputStream(shouldReturnRawInputStream));
}

/**
* Deduplicate any options which are the same parameter. The value which comes last in {@code
* os} will be the value included in the return.
*/
@BetaApi
public static BlobSourceOption[] dedupe(BlobSourceOption... os) {
return Option.dedupe(BlobSourceOption[]::new, os);
}

/**
* Deduplicate any options which are the same parameter.
*
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
* in the return. All options from {@code os} will override their counterparts in {@code
* collection}.
*/
@BetaApi
public static BlobSourceOption[] dedupe(
Collection<BlobSourceOption> collection, BlobSourceOption... os) {
return Option.dedupe(BlobSourceOption[]::new, collection, os);
}

/**
* Deduplicate any options which are the same parameter.
*
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
* in the return. All options from {@code os} will override their counterparts in {@code
* collection}.
*/
@BetaApi
public static BlobSourceOption[] dedupe(BlobSourceOption[] array, BlobSourceOption... os) {
return Option.dedupe(BlobSourceOption[]::new, array, os);
}

static Storage.BlobSourceOption[] toSourceOptions(
BlobInfo blobInfo, BlobSourceOption... options) {
Storage.BlobSourceOption[] convertedOptions = new Storage.BlobSourceOption[options.length];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import com.google.cloud.storage.UnifiedOpts.BucketSourceOpt;
import com.google.cloud.storage.UnifiedOpts.ObjectOptExtractor;
import com.google.cloud.storage.UnifiedOpts.ObjectTargetOpt;
import com.google.cloud.storage.UnifiedOpts.OptionShim;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.io.IOException;
Expand All @@ -41,6 +40,7 @@
import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -99,6 +99,41 @@ public static BucketSourceOption userProject(@NonNull String userProject) {
return new BucketSourceOption(UnifiedOpts.userProject(userProject));
}

/**
* Deduplicate any options which are the same parameter. The value which comes last in {@code
* os} will be the value included in the return.
*/
@BetaApi
public static BucketSourceOption[] dedupe(BucketSourceOption... os) {
return Option.dedupe(BucketSourceOption[]::new, os);
}

/**
* Deduplicate any options which are the same parameter.
*
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
* in the return. All options from {@code os} will override their counterparts in {@code
* collection}.
*/
@BetaApi
public static BucketSourceOption[] dedupe(
Collection<BucketSourceOption> collection, BucketSourceOption... os) {
return Option.dedupe(BucketSourceOption[]::new, collection, os);
}

/**
* Deduplicate any options which are the same parameter.
*
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
* in the return. All options from {@code os} will override their counterparts in {@code
* collection}.
*/
@BetaApi
public static BucketSourceOption[] dedupe(
BucketSourceOption[] array, BucketSourceOption... os) {
return Option.dedupe(BucketSourceOption[]::new, array, os);
}

static Storage.BucketSourceOption[] toSourceOptions(
BucketInfo bucketInfo, BucketSourceOption... options) {
Storage.BucketSourceOption[] convertedOptions =
Expand Down Expand Up @@ -237,6 +272,40 @@ public static BlobTargetOption userProject(@NonNull String userProject) {
return new BlobTargetOption(UnifiedOpts.userProject(userProject));
}

/**
* Deduplicate any options which are the same parameter. The value which comes last in {@code
* os} will be the value included in the return.
*/
@BetaApi
public static BlobTargetOption[] dedupe(BlobTargetOption... os) {
return Option.dedupe(BlobTargetOption[]::new, os);
}

/**
* Deduplicate any options which are the same parameter.
*
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
* in the return. All options from {@code os} will override their counterparts in {@code
* collection}.
*/
@BetaApi
public static BlobTargetOption[] dedupe(
Collection<BlobTargetOption> collection, BlobTargetOption... os) {
return Option.dedupe(BlobTargetOption[]::new, collection, os);
}

/**
* Deduplicate any options which are the same parameter.
*
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
* in the return. All options from {@code os} will override their counterparts in {@code
* collection}.
*/
@BetaApi
public static BlobTargetOption[] dedupe(BlobTargetOption[] array, BlobTargetOption... os) {
return Option.dedupe(BlobTargetOption[]::new, array, os);
}

static Storage.BlobTargetOption[] toTargetOptions(
BlobInfo blobInfo, BlobTargetOption... options) {
Storage.BlobTargetOption[] targetOptions = new Storage.BlobTargetOption[options.length];
Expand All @@ -255,7 +324,7 @@ static Storage.BlobTargetOption[] toTargetOptions(
}

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

private static final long serialVersionUID = 59762268190041584L;

Expand Down Expand Up @@ -366,6 +435,40 @@ public static BlobWriteOption userProject(@NonNull String userProject) {
return new BlobWriteOption(UnifiedOpts.userProject(userProject));
}

/**
* Deduplicate any options which are the same parameter. The value which comes last in {@code
* os} will be the value included in the return.
*/
@BetaApi
public static BlobWriteOption[] dedupe(BlobWriteOption... os) {
return Option.dedupe(BlobWriteOption[]::new, os);
}

/**
* Deduplicate any options which are the same parameter.
*
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
* in the return. All options from {@code os} will override their counterparts in {@code
* collection}.
*/
@BetaApi
public static BlobWriteOption[] dedupe(
Collection<BlobWriteOption> collection, BlobWriteOption... os) {
return Option.dedupe(BlobWriteOption[]::new, collection, os);
}

/**
* Deduplicate any options which are the same parameter.
*
* <p>The value which comes last in {@code collection} and {@code os} will be the value included
* in the return. All options from {@code os} will override their counterparts in {@code
* collection}.
*/
@BetaApi
public static BlobWriteOption[] dedupe(BlobWriteOption[] array, BlobWriteOption... os) {
return Option.dedupe(BlobWriteOption[]::new, array, os);
}

static Storage.BlobWriteOption[] toWriteOptions(BlobInfo blobInfo, BlobWriteOption... options) {
Storage.BlobWriteOption[] convertedOptions = new Storage.BlobWriteOption[options.length];
for (int i = 0; i < options.length; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@

import com.google.cloud.storage.UnifiedOpts.Opt;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/** Base class for Storage operation option. */
@Deprecated
Expand All @@ -29,4 +34,32 @@ public abstract class Option<O extends Opt> extends UnifiedOpts.OptionShim<O>
Option(O opt) {
super(opt);
}

@SafeVarargs
static <O extends Option<?>> O[] dedupe(IntFunction<O[]> gen, O... os) {
return dedupe(gen, Arrays.stream(os));
}

@SafeVarargs
static <O extends Option<?>> O[] dedupe(IntFunction<O[]> gen, Collection<O> collection, O... os) {
return dedupe(gen, Stream.of(collection.stream(), Arrays.stream(os)).flatMap(s -> s));
}

@SafeVarargs
static <O extends Option<?>> O[] dedupe(IntFunction<O[]> gen, O[] array, O... os) {
return dedupe(gen, Stream.of(Arrays.stream(array), Arrays.stream(os)).flatMap(s -> s));
}

/**
* All Options contain an {@link Opt}, {@code Opt}s are distinct classes allowing us to group
* based on those classes. Once grouped, we select the last element to provide last wins behavior.
*
* <p>Each of these helpers is an internal implementation detail, primarily due to the fact that
* generic arrays can not be instantiated in Java and requires a factory to be passed in.
*/
private static <O extends Option<?>> O[] dedupe(IntFunction<O[]> gen, Stream<O> s) {
return s.collect(Collectors.groupingBy(o -> o.getOpt().getClass())).values().stream()
.map(l -> l.get(l.size() - 1))
.toArray(gen);
}
}
Loading