diff --git a/java/google/registry/backup/RestoreCommitLogsAction.java b/java/google/registry/backup/RestoreCommitLogsAction.java index c06d16474..2a504962e 100644 --- a/java/google/registry/backup/RestoreCommitLogsAction.java +++ b/java/google/registry/backup/RestoreCommitLogsAction.java @@ -15,6 +15,7 @@ package google.registry.backup; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.Iterators.peekingIterator; import static google.registry.backup.BackupUtils.createDeserializingIterator; import static google.registry.model.ofy.ObjectifyService.ofy; @@ -25,8 +26,6 @@ import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.EntityTranslator; import com.google.appengine.tools.cloudstorage.GcsFileMetadata; import com.google.appengine.tools.cloudstorage.GcsService; -import com.google.common.base.Function; -import com.google.common.collect.FluentIterable; import com.google.common.collect.Lists; import com.google.common.collect.PeekingIterator; import com.googlecode.objectify.Key; @@ -50,8 +49,8 @@ import java.nio.channels.Channels; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; +import java.util.stream.Stream; import javax.inject.Inject; import org.joda.time.DateTime; @@ -117,15 +116,18 @@ public class RestoreCommitLogsAction implements Runnable { } // Restore the CommitLogCheckpointRoot and CommitLogBuckets. saveOfy( - FluentIterable.from(bucketTimestamps.entrySet()) - .transform( - (Function, ImmutableObject>) - entry -> - new CommitLogBucket.Builder() - .setBucketNum(entry.getKey()) - .setLastWrittenTime(entry.getValue()) - .build()) - .append(CommitLogCheckpointRoot.create(lastCheckpoint.getCheckpointTime()))); + Stream.concat( + bucketTimestamps + .entrySet() + .stream() + .map( + entry -> + new CommitLogBucket.Builder() + .setBucketNum(entry.getKey()) + .setLastWrittenTime(entry.getValue()) + .build()), + Stream.of(CommitLogCheckpointRoot.create(lastCheckpoint.getCheckpointTime()))) + .collect(toImmutableList())); logger.info("Restore complete"); } diff --git a/java/google/registry/bigquery/BigqueryConnection.java b/java/google/registry/bigquery/BigqueryConnection.java index 2cf17c41c..383e26aa3 100644 --- a/java/google/registry/bigquery/BigqueryConnection.java +++ b/java/google/registry/bigquery/BigqueryConnection.java @@ -51,7 +51,6 @@ import com.google.api.services.bigquery.model.TableFieldSchema; import com.google.api.services.bigquery.model.TableReference; import com.google.api.services.bigquery.model.TableRow; import com.google.api.services.bigquery.model.ViewDefinition; -import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableTable; import com.google.common.io.BaseEncoding; @@ -359,36 +358,33 @@ public class BigqueryConnection implements AutoCloseable { } /** - * A function that updates the specified Bigquery table to reflect the metadata from the input - * DestinationTable, passing the same DestinationTable through as the output. If the specified - * table does not already exist, it will be inserted into the dataset. + * Updates the specified Bigquery table to reflect the metadata from the input. + * + *

Returns the input DestinationTable. If the specified table does not already exist, it will + * be inserted into the dataset. * *

Clients can call this function directly to update a table on demand, or can pass it to * Futures.transform() to update a table produced as the asynchronous result of a load or query * job (e.g. to add a description to it). */ - private class UpdateTableFunction implements Function { - @Override - public DestinationTable apply(final DestinationTable destinationTable) { - Table table = destinationTable.getTable(); - TableReference ref = table.getTableReference(); - try { - if (checkTableExists(ref.getDatasetId(), ref.getTableId())) { - // Make sure to use patch() rather than update(). The former changes only those properties - // which are specified, while the latter would change everything, blanking out unspecified - // properties. - bigquery.tables() - .patch(ref.getProjectId(), ref.getDatasetId(), ref.getTableId(), table) - .execute(); - } else { - bigquery.tables() - .insert(ref.getProjectId(), ref.getDatasetId(), table) - .execute(); - } - return destinationTable; - } catch (IOException e) { - throw BigqueryJobFailureException.create(e); + private DestinationTable updateTable(final DestinationTable destinationTable) { + Table table = destinationTable.getTable(); + TableReference ref = table.getTableReference(); + try { + if (checkTableExists(ref.getDatasetId(), ref.getTableId())) { + // Make sure to use patch() rather than update(). The former changes only those properties + // which are specified, while the latter would change everything, blanking out unspecified + // properties. + bigquery + .tables() + .patch(ref.getProjectId(), ref.getDatasetId(), ref.getTableId(), table) + .execute(); + } else { + bigquery.tables().insert(ref.getProjectId(), ref.getDatasetId(), table).execute(); } + return destinationTable; + } catch (IOException e) { + throw BigqueryJobFailureException.create(e); } } @@ -408,7 +404,7 @@ public class BigqueryConnection implements AutoCloseable { .setSourceFormat(sourceFormat.toString()) .setSourceUris(ImmutableList.copyOf(sourceUris)) .setDestinationTable(dest.getTableReference()))); - return transform(runJobToCompletion(job, dest), new UpdateTableFunction(), directExecutor()); + return transform(runJobToCompletion(job, dest), this::updateTable, directExecutor()); } /** @@ -421,11 +417,9 @@ public class BigqueryConnection implements AutoCloseable { DestinationTable dest) { if (dest.type == TableType.VIEW) { // Use Futures.transform() rather than calling apply() directly so that any exceptions thrown - // by calling UpdateTableFunction will be propagated on the get() call, not from here. + // by calling updateTable will be propagated on the get() call, not from here. return transform( - Futures.immediateFuture(dest.withQuery(querySql)), - new UpdateTableFunction(), - directExecutor()); + Futures.immediateFuture(dest.withQuery(querySql)), this::updateTable, directExecutor()); } else { Job job = new Job() .setConfiguration(new JobConfiguration() @@ -434,7 +428,7 @@ public class BigqueryConnection implements AutoCloseable { .setDefaultDataset(getDataset()) .setWriteDisposition(dest.getWriteDisposition().toString()) .setDestinationTable(dest.getTableReference()))); - return transform(runJobToCompletion(job, dest), new UpdateTableFunction(), directExecutor()); + return transform(runJobToCompletion(job, dest), this::updateTable, directExecutor()); } } diff --git a/java/google/registry/bigquery/BigqueryModule.java b/java/google/registry/bigquery/BigqueryModule.java index a1df8d5d7..d2943f756 100644 --- a/java/google/registry/bigquery/BigqueryModule.java +++ b/java/google/registry/bigquery/BigqueryModule.java @@ -20,7 +20,6 @@ import com.google.api.client.json.JsonFactory; import com.google.api.services.bigquery.Bigquery; import com.google.api.services.bigquery.BigqueryScopes; import com.google.api.services.bigquery.model.TableFieldSchema; -import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; @@ -28,6 +27,7 @@ import dagger.multibindings.Multibinds; import google.registry.config.RegistryConfig.Config; import java.util.Map; import java.util.Set; +import java.util.function.Function; /** Dagger module for Google {@link Bigquery} connection objects. */ @Module diff --git a/java/google/registry/billing/BillingModule.java b/java/google/registry/billing/BillingModule.java index 7c135ada4..d0d99ae0d 100644 --- a/java/google/registry/billing/BillingModule.java +++ b/java/google/registry/billing/BillingModule.java @@ -18,12 +18,12 @@ import com.google.api.client.googleapis.extensions.appengine.auth.oauth2.AppIden import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.services.dataflow.Dataflow; -import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import dagger.Module; import dagger.Provides; import google.registry.config.RegistryConfig.Config; import java.util.Set; +import java.util.function.Function; /** Module for dependencies required by monthly billing actions. */ @Module diff --git a/java/google/registry/dns/writer/clouddns/CloudDnsWriterModule.java b/java/google/registry/dns/writer/clouddns/CloudDnsWriterModule.java index 2e8084f6b..aed305223 100644 --- a/java/google/registry/dns/writer/clouddns/CloudDnsWriterModule.java +++ b/java/google/registry/dns/writer/clouddns/CloudDnsWriterModule.java @@ -19,7 +19,6 @@ import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.services.dns.Dns; import com.google.api.services.dns.DnsScopes; -import com.google.common.base.Function; import com.google.common.util.concurrent.RateLimiter; import dagger.Module; import dagger.Provides; @@ -30,6 +29,7 @@ import google.registry.config.RegistryConfig.Config; import google.registry.dns.writer.DnsWriter; import java.util.Optional; import java.util.Set; +import java.util.function.Function; import javax.inject.Named; /** Dagger module for Google Cloud DNS service connection objects. */ diff --git a/java/google/registry/export/DriveModule.java b/java/google/registry/export/DriveModule.java index 784e3e343..8ee8bf8a3 100644 --- a/java/google/registry/export/DriveModule.java +++ b/java/google/registry/export/DriveModule.java @@ -19,11 +19,11 @@ import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.services.drive.Drive; import com.google.api.services.drive.DriveScopes; -import com.google.common.base.Function; import dagger.Module; import dagger.Provides; import google.registry.config.RegistryConfig.Config; import java.util.Set; +import java.util.function.Function; /** Dagger module for Google {@link Drive} service connection objects. */ @Module diff --git a/java/google/registry/flows/ResourceFlowUtils.java b/java/google/registry/flows/ResourceFlowUtils.java index ddcb4d337..08220a696 100644 --- a/java/google/registry/flows/ResourceFlowUtils.java +++ b/java/google/registry/flows/ResourceFlowUtils.java @@ -24,7 +24,6 @@ import static google.registry.model.domain.DomainResource.extendRegistrationWith import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey; import static google.registry.model.ofy.ObjectifyService.ofy; -import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -67,6 +66,7 @@ import google.registry.model.transfer.TransferStatus; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.function.Function; import org.joda.time.DateTime; /** Static utility functions for resource flows. */ diff --git a/java/google/registry/keyring/kms/KmsModule.java b/java/google/registry/keyring/kms/KmsModule.java index c9114ff04..3e3291e66 100644 --- a/java/google/registry/keyring/kms/KmsModule.java +++ b/java/google/registry/keyring/kms/KmsModule.java @@ -19,12 +19,12 @@ import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.services.cloudkms.v1.CloudKMS; import com.google.api.services.cloudkms.v1.CloudKMSScopes; -import com.google.common.base.Function; import dagger.Binds; import dagger.Module; import dagger.Provides; import google.registry.config.RegistryConfig.Config; import java.util.Set; +import java.util.function.Function; /** Dagger module for Cloud KMS connection objects. */ @Module diff --git a/java/google/registry/loadtest/LoadTestAction.java b/java/google/registry/loadtest/LoadTestAction.java index 6af3bbeb3..1d245e644 100644 --- a/java/google/registry/loadtest/LoadTestAction.java +++ b/java/google/registry/loadtest/LoadTestAction.java @@ -19,7 +19,6 @@ import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.Lists.partition; -import static com.google.common.collect.Lists.transform; import static google.registry.security.XsrfTokenManager.X_CSRF_TOKEN; import static google.registry.util.FormattingLogger.getLoggerForCallerClass; import static google.registry.util.ResourceUtils.readResourceUtf8; @@ -27,7 +26,6 @@ import static java.util.Arrays.asList; import static org.joda.time.DateTimeZone.UTC; import com.google.appengine.api.taskqueue.TaskOptions; -import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; import google.registry.config.RegistryEnvironment; @@ -41,6 +39,7 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Random; +import java.util.function.Function; import javax.inject.Inject; import org.joda.time.DateTime; @@ -235,15 +234,17 @@ public class LoadTestAction implements Runnable { // Do successful creates on random names tasks.addAll( createTasks( - transform( - createNumCopies(xmlContactCreateTmpl, successfulContactCreatesPerSecond), - randomNameReplacer("%contact%", MAX_CONTACT_LENGTH)), + createNumCopies(xmlContactCreateTmpl, successfulContactCreatesPerSecond) + .stream() + .map(randomNameReplacer("%contact%", MAX_CONTACT_LENGTH)) + .collect(toImmutableList()), startSecond)); tasks.addAll( createTasks( - transform( - createNumCopies(xmlHostCreateTmpl, successfulHostCreatesPerSecond), - randomNameReplacer("%host%", ARBITRARY_VALID_HOST_LENGTH)), + createNumCopies(xmlHostCreateTmpl, successfulHostCreatesPerSecond) + .stream() + .map(randomNameReplacer("%host%", ARBITRARY_VALID_HOST_LENGTH)) + .collect(toImmutableList()), startSecond)); tasks.addAll( createTasks( diff --git a/java/google/registry/model/EppResourceUtils.java b/java/google/registry/model/EppResourceUtils.java index 1f00a3abc..189532642 100644 --- a/java/google/registry/model/EppResourceUtils.java +++ b/java/google/registry/model/EppResourceUtils.java @@ -21,7 +21,6 @@ import static google.registry.util.DateTimeUtils.isAtOrAfter; import static google.registry.util.DateTimeUtils.isBeforeOrAt; import static google.registry.util.DateTimeUtils.latestOf; -import com.google.common.base.Function; import com.googlecode.objectify.Key; import com.googlecode.objectify.Result; import com.googlecode.objectify.cmd.Query; @@ -44,6 +43,7 @@ import google.registry.util.FormattingLogger; import java.util.List; import java.util.Map.Entry; import java.util.Set; +import java.util.function.Function; import javax.annotation.Nullable; import org.joda.time.DateTime; import org.joda.time.Interval; diff --git a/java/google/registry/model/ImmutableObject.java b/java/google/registry/model/ImmutableObject.java index cd69b4fa7..9e11f9a34 100644 --- a/java/google/registry/model/ImmutableObject.java +++ b/java/google/registry/model/ImmutableObject.java @@ -14,15 +14,14 @@ package google.registry.model; -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Maps.transformValues; import static google.registry.model.ofy.ObjectifyService.ofy; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toList; -import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.Maps; import com.googlecode.objectify.Key; @@ -34,6 +33,7 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Map.Entry; import java.util.NavigableMap; @@ -125,8 +125,7 @@ public abstract class ImmutableObject implements Cloneable { Field field = entry.getKey(); Object value = entry.getValue(); sortedFields.put( - field.getName(), - field.isAnnotationPresent(DoNotHydrate.class) ? value : HYDRATOR.apply(value)); + field.getName(), field.isAnnotationPresent(DoNotHydrate.class) ? value : hydrate(value)); } return toStringHelper(sortedFields); } @@ -141,54 +140,60 @@ public abstract class ImmutableObject implements Cloneable { } /** Helper function to recursively hydrate an ImmutableObject. */ - private static final Function HYDRATOR = - new Function() { - @Override - public Object apply(Object value) { - if (value instanceof Key) { - return apply(ofy().load().key((Key) value).now()); - } else if (value instanceof Map) { - return transformValues((Map) value, this); - } else if (value instanceof Collection) { - return transform((Collection) value, this); - } else if (value instanceof ImmutableObject) { - return ((ImmutableObject) value).toHydratedString(); - } - return value; - }}; + private static final Object hydrate(Object value) { + if (value instanceof Key) { + return hydrate(ofy().load().key((Key) value).now()); + } else if (value instanceof Map) { + return transformValues((Map) value, ImmutableObject::hydrate); + } else if (value instanceof Collection) { + return transform((Collection) value, ImmutableObject::hydrate); + } else if (value instanceof ImmutableObject) { + return ((ImmutableObject) value).toHydratedString(); + } + return value; + } /** Helper function to recursively convert a ImmutableObject to a Map of generic objects. */ - private static final Function TO_MAP_HELPER = - new Function() { - @Override - public Object apply(Object o) { - if (o == null) { - return null; - } else if (o instanceof ImmutableObject) { - // LinkedHashMap to preserve field ordering and because ImmutableMap forbids null - // values. - Map result = new LinkedHashMap<>(); - for (Entry entry : ModelUtils.getFieldValues(o).entrySet()) { - result.put(entry.getKey().getName(), apply(entry.getValue())); - } - return result; - } else if (o instanceof Map) { - return Maps.transformValues((Map) o, this); - } else if (o instanceof Set) { - return ((Set) o).stream().map(this).collect(toImmutableSet()); - } else if (o instanceof Collection) { - return ((Collection) o).stream().map(this).collect(toImmutableList()); - } else if (o instanceof Number || o instanceof Boolean) { - return o; - } else { - return o.toString(); - } - } - }; + private static Object toMapRecursive(Object o) { + if (o == null) { + return null; + } else if (o instanceof ImmutableObject) { + // LinkedHashMap to preserve field ordering and because ImmutableMap forbids null + // values. + Map result = new LinkedHashMap<>(); + for (Entry entry : ModelUtils.getFieldValues(o).entrySet()) { + result.put(entry.getKey().getName(), toMapRecursive(entry.getValue())); + } + return result; + } else if (o instanceof Map) { + return Maps.transformValues((Map) o, ImmutableObject::toMapRecursive); + } else if (o instanceof Set) { + return ((Set) o) + .stream() + .map(ImmutableObject::toMapRecursive) + // We can't use toImmutableSet here, because values can be null (especially since the + // original ImmutableObject might have been the result of a cloneEmptyToNull call). + // + // We can't use toSet either, because we want to preserve order. So we use LinkedHashSet + // instead. + .collect(toCollection(LinkedHashSet::new)); + } else if (o instanceof Collection) { + return ((Collection) o) + .stream() + .map(ImmutableObject::toMapRecursive) + // We can't use toImmutableList here, because values can be null (especially since the + // original ImmutableObject might have been the result of a cloneEmptyToNull call). + .collect(toList()); + } else if (o instanceof Number || o instanceof Boolean) { + return o; + } else { + return o.toString(); + } + } /** Returns a map of all object fields (including sensitive data) that's used to produce diffs. */ @SuppressWarnings("unchecked") public Map toDiffableFieldMap() { - return (Map) TO_MAP_HELPER.apply(this); + return (Map) toMapRecursive(this); } } diff --git a/java/google/registry/model/JsonMapBuilder.java b/java/google/registry/model/JsonMapBuilder.java index 7424ccb58..5b7956b37 100644 --- a/java/google/registry/model/JsonMapBuilder.java +++ b/java/google/registry/model/JsonMapBuilder.java @@ -16,7 +16,6 @@ package google.registry.model; import static com.google.common.collect.ImmutableList.toImmutableList; -import com.google.common.base.Functions; import com.google.common.collect.Streams; import java.util.Collections; import java.util.LinkedHashMap; @@ -67,7 +66,7 @@ public final class JsonMapBuilder { name, value == null ? Collections.EMPTY_LIST - : Streams.stream(value).map(Functions.toStringFunction()).collect(toImmutableList())); + : Streams.stream(value).map(Object::toString).collect(toImmutableList())); return this; } diff --git a/java/google/registry/model/ModelUtils.java b/java/google/registry/model/ModelUtils.java index fef76d030..566a92601 100644 --- a/java/google/registry/model/ModelUtils.java +++ b/java/google/registry/model/ModelUtils.java @@ -17,12 +17,11 @@ package google.registry.model; import static com.google.common.base.Predicates.instanceOf; import static com.google.common.base.Predicates.isNull; import static com.google.common.base.Predicates.or; -import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.transformValues; -import static com.google.common.collect.Sets.newLinkedHashSet; +import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toList; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.cache.CacheBuilder; @@ -44,42 +43,48 @@ import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.AbstractList; +import java.util.ArrayDeque; import java.util.Collection; import java.util.Deque; import java.util.LinkedHashMap; -import java.util.LinkedList; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.stream.Stream; /** A collection of static methods that deal with reflection on model classes. */ public class ModelUtils { /** Caches all instance fields on an object, including non-public and inherited fields. */ private static final LoadingCache, ImmutableMap> ALL_FIELDS_CACHE = - CacheBuilder.newBuilder().build(new CacheLoader, ImmutableMap>() { - @Override - public ImmutableMap load(Class clazz) { - Deque> hierarchy = new LinkedList<>(); - // Walk the hierarchy up to but not including ImmutableObject (to ignore hashCode). - for (; clazz != ImmutableObject.class; clazz = clazz.getSuperclass()) { - // Add to the front, so that shadowed fields show up later in the list. - // This will mean that getFieldValues will show the most derived value. - hierarchy.addFirst(clazz); - } - Map fields = new LinkedHashMap<>(); - for (Class hierarchyClass : hierarchy) { - // Don't use hierarchyClass.getFields() because it only picks up public fields. - for (Field field : hierarchyClass.getDeclaredFields()) { - if (!Modifier.isStatic(field.getModifiers())) { - field.setAccessible(true); - fields.put(field.getName(), field); + CacheBuilder.newBuilder() + .build( + new CacheLoader, ImmutableMap>() { + @Override + public ImmutableMap load(Class clazz) { + Deque> hierarchy = new ArrayDeque<>(); + // Walk the hierarchy up to but not including ImmutableObject (to ignore + // hashCode). + for (; clazz != ImmutableObject.class; clazz = clazz.getSuperclass()) { + // Add to the front, so that shadowed fields show up later in the list. + // This will mean that getFieldValues will show the most derived value. + hierarchy.addFirst(clazz); + } + Map fields = new LinkedHashMap<>(); + for (Class hierarchyClass : hierarchy) { + // Don't use hierarchyClass.getFields() because it only picks up public fields. + for (Field field : hierarchyClass.getDeclaredFields()) { + if (!Modifier.isStatic(field.getModifiers())) { + field.setAccessible(true); + fields.put(field.getName(), field); + } + } + } + return ImmutableMap.copyOf(fields); } - } - } - return ImmutableMap.copyOf(fields); - }}); + }); /** Lists all instance fields on an object, including non-public and inherited fields. */ static Map getAllFields(Class clazz) { @@ -208,53 +213,55 @@ public class ModelUtils { } /** Functional helper for {@link #cloneEmptyToNull}. */ - private static final Function CLONE_EMPTY_TO_NULL = - new Function() { - @Override - public Object apply(Object obj) { - if (obj instanceof ImmutableSortedMap) { - // ImmutableSortedMapTranslatorFactory handles empty for us. If the object is null, then - // its on-save hook can't run. - return obj; - } - if ("".equals(obj) - || (obj instanceof Collection && ((Collection) obj).isEmpty()) - || (obj instanceof Map && ((Map) obj).isEmpty()) - || (obj != null && obj.getClass().isArray() && Array.getLength(obj) == 0)) { - return null; - } - Predicate immutableObjectOrNull = or(isNull(), instanceOf(ImmutableObject.class)); - if ((obj instanceof Set || obj instanceof List) - && Streams.stream((Iterable) obj).allMatch(immutableObjectOrNull)) { - // Recurse into sets and lists, but only if they contain ImmutableObjects. - FluentIterable fluent = FluentIterable.from((Iterable) obj).transform(this); - return (obj instanceof List) ? newArrayList(fluent) : newLinkedHashSet(fluent); - } - if (obj instanceof Map - && ((Map) obj).values().stream().allMatch(immutableObjectOrNull)) { - // Recurse into maps with ImmutableObject values. - return transformValues((Map) obj, this); - } - if (obj instanceof ImmutableObject) { - // Recurse on the fields of an ImmutableObject. - ImmutableObject copy = ImmutableObject.clone((ImmutableObject) obj); - for (Field field : getAllFields(obj.getClass()).values()) { - Object oldValue = getFieldValue(obj, field); - Object newValue = apply(oldValue); - if (!Objects.equals(oldValue, newValue)) { - setFieldValue(copy, field, newValue); - } - } - return copy; - } - return obj; + private static Object cloneEmptyToNullRecursive(Object obj) { + if (obj instanceof ImmutableSortedMap) { + // ImmutableSortedMapTranslatorFactory handles empty for us. If the object is null, then + // its on-save hook can't run. + return obj; + } + if (obj == null + || obj.equals("") + || (obj instanceof Collection && ((Collection) obj).isEmpty()) + || (obj instanceof Map && ((Map) obj).isEmpty()) + || (obj.getClass().isArray() && Array.getLength(obj) == 0)) { + return null; + } + Predicate immutableObjectOrNull = or(isNull(), instanceOf(ImmutableObject.class)); + if ((obj instanceof Set || obj instanceof List) + && Streams.stream((Iterable) obj).allMatch(immutableObjectOrNull)) { + // Recurse into sets and lists, but only if they contain ImmutableObjects. + Stream stream = + Streams.stream((Iterable) obj).map(ModelUtils::cloneEmptyToNullRecursive); + // We can't use toImmutable(List/Set) because the values can be null. + // We can't use toSet because we have to preserve order in the Set. + // So we use toList (accepts null) and LinkedHashSet (preserves order and accepts null) + return (obj instanceof List) + ? stream.collect(toList()) + : stream.collect(toCollection(LinkedHashSet::new)); + } + if (obj instanceof Map && ((Map) obj).values().stream().allMatch(immutableObjectOrNull)) { + // Recurse into maps with ImmutableObject values. + return transformValues((Map) obj, ModelUtils::cloneEmptyToNullRecursive); + } + if (obj instanceof ImmutableObject) { + // Recurse on the fields of an ImmutableObject. + ImmutableObject copy = ImmutableObject.clone((ImmutableObject) obj); + for (Field field : getAllFields(obj.getClass()).values()) { + Object oldValue = getFieldValue(obj, field); + Object newValue = cloneEmptyToNullRecursive(oldValue); + if (!Objects.equals(oldValue, newValue)) { + setFieldValue(copy, field, newValue); } - }; + } + return copy; + } + return obj; + } /** Returns a clone of the object and sets empty collections, arrays, maps and strings to null. */ @SuppressWarnings("unchecked") protected static T cloneEmptyToNull(T obj) { - return (T) CLONE_EMPTY_TO_NULL.apply(obj); + return (T) cloneEmptyToNullRecursive(obj); } @VisibleForTesting diff --git a/java/google/registry/model/ofy/AugmentedDeleter.java b/java/google/registry/model/ofy/AugmentedDeleter.java index 873975432..d53a756b1 100644 --- a/java/google/registry/model/ofy/AugmentedDeleter.java +++ b/java/google/registry/model/ofy/AugmentedDeleter.java @@ -15,10 +15,9 @@ package google.registry.model.ofy; import static com.googlecode.objectify.ObjectifyService.ofy; -import static google.registry.util.ObjectifyUtils.OBJECTS_TO_KEYS; -import com.google.common.base.Functions; import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.googlecode.objectify.Key; import com.googlecode.objectify.Result; @@ -38,13 +37,13 @@ abstract class AugmentedDeleter implements Deleter { @Override public Result entities(Iterable entities) { - handleDeletion(Iterables.transform(entities, OBJECTS_TO_KEYS)); + handleDeletion(Iterables.transform(entities, Key::create)); return delegate.entities(entities); } @Override public Result entities(Object... entities) { - handleDeletion(FluentIterable.from(entities).transform(OBJECTS_TO_KEYS)); + handleDeletion(FluentIterable.from(entities).transform(Key::create)); return delegate.entities(entities); } @@ -65,11 +64,8 @@ abstract class AugmentedDeleter implements Deleter { // Magic to convert the type Iterable> (a family of types which allows for // homogeneous iterables of a fixed Key type, e.g. List>, and is convenient for // callers) into the type Iterable> (a concrete type of heterogeneous keys, which is - // convenient for users). We do this by passing each key through the identity function - // parameterized for Key, which erases any homogeneous typing on the iterable. - // See: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ104 - Iterable> retypedKeys = Iterables.transform(keys, Functions.>identity()); - handleDeletion(retypedKeys); + // convenient for users). + handleDeletion(ImmutableList.>copyOf(keys)); return delegate.keys(keys); } diff --git a/java/google/registry/model/ofy/CommitLoggedWork.java b/java/google/registry/model/ofy/CommitLoggedWork.java index 1fcf50467..8da543c85 100644 --- a/java/google/registry/model/ofy/CommitLoggedWork.java +++ b/java/google/registry/model/ofy/CommitLoggedWork.java @@ -25,7 +25,6 @@ import static google.registry.model.ofy.CommitLogBucket.loadBucket; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.util.DateTimeUtils.isBeforeOrAt; -import com.google.common.base.Function; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.googlecode.objectify.Key; @@ -153,9 +152,7 @@ class CommitLoggedWork extends VoidWork { mutations = union(info.getSaves(), untouchedRootsWithTouchedChildren) .stream() - .map( - (Function) - (Object saveEntity) -> CommitLogMutation.create(manifestKey, saveEntity)) + .map(entity -> (ImmutableObject) CommitLogMutation.create(manifestKey, entity)) .collect(toImmutableSet()); ofy().saveWithoutBackup() .entities(new ImmutableSet.Builder<>() diff --git a/java/google/registry/model/ofy/Ofy.java b/java/google/registry/model/ofy/Ofy.java index 1d35a313c..661518034 100644 --- a/java/google/registry/model/ofy/Ofy.java +++ b/java/google/registry/model/ofy/Ofy.java @@ -21,7 +21,6 @@ import static com.google.common.collect.Maps.uniqueIndex; import static com.googlecode.objectify.ObjectifyService.ofy; import static google.registry.config.RegistryConfig.getBaseOfyRetryDuration; import static google.registry.util.CollectionUtils.union; -import static google.registry.util.ObjectifyUtils.OBJECTS_TO_KEYS; import com.google.appengine.api.datastore.DatastoreFailureException; import com.google.appengine.api.datastore.DatastoreTimeoutException; @@ -170,7 +169,7 @@ public class Ofy { assertInTransaction(); checkState(Streams.stream(entities).allMatch(notNull()), "Can't save a null entity."); checkProhibitedAnnotations(entities, NotBackedUp.class, VirtualEntity.class); - ImmutableMap, ?> keysToEntities = uniqueIndex(entities, OBJECTS_TO_KEYS); + ImmutableMap, ?> keysToEntities = uniqueIndex(entities, Key::create); TRANSACTION_INFO.get().putSaves(keysToEntities); } }; diff --git a/java/google/registry/model/ofy/TransactionInfo.java b/java/google/registry/model/ofy/TransactionInfo.java index 611799ec8..2a369ea61 100644 --- a/java/google/registry/model/ofy/TransactionInfo.java +++ b/java/google/registry/model/ofy/TransactionInfo.java @@ -14,7 +14,6 @@ package google.registry.model.ofy; -import static com.google.common.base.Functions.constant; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.Maps.filterValues; @@ -76,7 +75,7 @@ class TransactionInfo { void putDeletes(Iterable> keys) { assertNotReadOnly(); - changesBuilder.putAll(toMap(keys, constant(TransactionInfo.Delete.SENTINEL))); + changesBuilder.putAll(toMap(keys, k -> TransactionInfo.Delete.SENTINEL)); } ImmutableSet> getTouchedKeys() { diff --git a/java/google/registry/model/registrar/RegistrarContact.java b/java/google/registry/model/registrar/RegistrarContact.java index c99d19c40..5fc16b14b 100644 --- a/java/google/registry/model/registrar/RegistrarContact.java +++ b/java/google/registry/model/registrar/RegistrarContact.java @@ -14,13 +14,11 @@ package google.registry.model.registrar; -import static com.google.common.base.Functions.toStringFunction; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.Sets.difference; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy; -import static google.registry.util.ObjectifyUtils.OBJECTS_TO_KEYS; import static java.util.stream.Collectors.joining; import com.google.common.base.Enums; @@ -171,7 +169,7 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable { .type(RegistrarContact.class) .ancestor(registrar) .keys()), - contacts.stream().map(OBJECTS_TO_KEYS).collect(toImmutableSet()))); + contacts.stream().map(Key::create).collect(toImmutableSet()))); ofy().save().entities(contacts); } }); @@ -272,7 +270,7 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable { .put("emailAddress", emailAddress) .put("phoneNumber", phoneNumber) .put("faxNumber", faxNumber) - .put("types", getTypes().stream().map(toStringFunction()).collect(joining(","))) + .put("types", getTypes().stream().map(Object::toString).collect(joining(","))) .put("visibleInWhoisAsAdmin", visibleInWhoisAsAdmin) .put("visibleInWhoisAsTech", visibleInWhoisAsTech) .put("visibleInDomainWhoisAsAbuse", visibleInDomainWhoisAsAbuse) diff --git a/java/google/registry/monitoring/metrics/contrib/AbstractMetricSubject.java b/java/google/registry/monitoring/metrics/contrib/AbstractMetricSubject.java index 899d0ba02..6a39fdb9d 100644 --- a/java/google/registry/monitoring/metrics/contrib/AbstractMetricSubject.java +++ b/java/google/registry/monitoring/metrics/contrib/AbstractMetricSubject.java @@ -15,11 +15,10 @@ package google.registry.monitoring.metrics.contrib; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.ImmutableList.toImmutableList; -import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; import com.google.common.collect.Ordering; import com.google.common.truth.FailureMetadata; import com.google.common.truth.Subject; @@ -63,15 +62,13 @@ abstract class AbstractMetricSubject> */ protected final Set> expectedNondefaultLabelTuples = new HashSet<>(); - /** - * Function to convert a metric point to a nice string representation for use in error messages. - */ - protected final Function, String> metricPointConverter = - metricPoint -> - String.format( - "%s => %s", - Joiner.on(':').join(metricPoint.labelValues()), - getMessageRepresentation(metricPoint.value())); + /** Converts a metric point to a nice string representation for use in error messages. */ + protected String convertMetricPoint(MetricPoint metricPoint) { + return String.format( + "%s => %s", + Joiner.on(':').join(metricPoint.labelValues()), + getMessageRepresentation(metricPoint.value())); + } protected AbstractMetricSubject(FailureMetadata metadata, Metric actual) { super(metadata, checkNotNull(actual)); @@ -101,9 +98,11 @@ abstract class AbstractMetricSubject> "has a value for labels", Joiner.on(':').join(labels), "has labeled values", - Lists.transform( - Ordering.>natural().sortedCopy(actual().getTimestampedValues()), - metricPointConverter)); + Ordering.>natural() + .sortedCopy(actual().getTimestampedValues()) + .stream() + .map(this::convertMetricPoint) + .collect(toImmutableList())); } if (!metricPoint.value().equals(value)) { failWithBadResults( @@ -129,9 +128,11 @@ abstract class AbstractMetricSubject> "has a value for labels", Joiner.on(':').join(labels), "has labeled values", - Lists.transform( - Ordering.>natural().sortedCopy(actual().getTimestampedValues()), - metricPointConverter)); + Ordering.>natural() + .sortedCopy(actual().getTimestampedValues()) + .stream() + .map(this::convertMetricPoint) + .collect(toImmutableList())); } if (hasDefaultValue(metricPoint)) { failWithBadResults( @@ -169,9 +170,11 @@ abstract class AbstractMetricSubject> "has", "no other nondefault values", "has labeled values", - Lists.transform( - Ordering.>natural().sortedCopy(actual().getTimestampedValues()), - metricPointConverter)); + Ordering.>natural() + .sortedCopy(actual().getTimestampedValues()) + .stream() + .map(this::convertMetricPoint) + .collect(toImmutableList())); } return andChainer(); } diff --git a/java/google/registry/monitoring/whitebox/StackdriverModule.java b/java/google/registry/monitoring/whitebox/StackdriverModule.java index b533ad29a..889c094cc 100644 --- a/java/google/registry/monitoring/whitebox/StackdriverModule.java +++ b/java/google/registry/monitoring/whitebox/StackdriverModule.java @@ -21,7 +21,6 @@ import com.google.api.services.monitoring.v3.Monitoring; import com.google.api.services.monitoring.v3.MonitoringScopes; import com.google.api.services.monitoring.v3.model.MonitoredResource; import com.google.appengine.api.modules.ModulesService; -import com.google.common.base.Function; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.ThreadFactoryBuilder; import dagger.Module; @@ -31,6 +30,7 @@ import google.registry.monitoring.metrics.MetricReporter; import google.registry.monitoring.metrics.MetricWriter; import google.registry.monitoring.metrics.stackdriver.StackdriverWriter; import java.util.Set; +import java.util.function.Function; import org.joda.time.Duration; /** Dagger module for Google Stackdriver service connection objects. */ diff --git a/java/google/registry/rdap/RdapJsonFormatter.java b/java/google/registry/rdap/RdapJsonFormatter.java index 1d2e3eccb..5296f8492 100644 --- a/java/google/registry/rdap/RdapJsonFormatter.java +++ b/java/google/registry/rdap/RdapJsonFormatter.java @@ -21,15 +21,12 @@ import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.util.CollectionUtils.union; import static google.registry.util.DomainNameUtils.ACE_PREFIX; -import com.google.common.base.Functions; -import com.google.common.base.Predicates; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.common.collect.Ordering; -import com.google.common.collect.Streams; import com.google.common.net.InetAddresses; import com.googlecode.objectify.Key; import google.registry.config.RdapNoticeDescriptor; @@ -59,7 +56,9 @@ import java.net.URI; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.stream.Stream; import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Singleton; @@ -1091,16 +1090,17 @@ public class RdapJsonFormatter { */ private static ImmutableList makeStatusValueList( ImmutableSet statusValues, boolean isDeleted) { - FluentIterable iterable = - FluentIterable.from(statusValues) - .transform(Functions.forMap(statusToRdapStatusMap, RdapStatus.OBSCURED)); + Stream stream = + statusValues + .stream() + .map(status -> statusToRdapStatusMap.getOrDefault(status, RdapStatus.OBSCURED)); if (isDeleted) { - iterable = - iterable - .filter(Predicates.not(Predicates.equalTo(RdapStatus.ACTIVE))) - .append(RdapStatus.REMOVED); + stream = + Stream.concat( + stream.filter(rdapStatus -> !Objects.equals(rdapStatus, RdapStatus.ACTIVE)), + Stream.of(RdapStatus.REMOVED)); } - return Streams.stream(iterable) + return stream .map(RdapStatus::getDisplayName) .collect(toImmutableSortedSet(Ordering.natural())) .asList(); diff --git a/java/google/registry/rde/imports/XjcToDomainResourceConverter.java b/java/google/registry/rde/imports/XjcToDomainResourceConverter.java index f107fb9d4..0904f6364 100644 --- a/java/google/registry/rde/imports/XjcToDomainResourceConverter.java +++ b/java/google/registry/rde/imports/XjcToDomainResourceConverter.java @@ -22,7 +22,6 @@ import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static org.joda.time.DateTimeZone.UTC; import com.google.common.base.Ascii; -import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import com.google.common.net.InternetDomainName; import com.googlecode.objectify.Key; @@ -59,6 +58,7 @@ import java.security.NoSuchAlgorithmException; import java.security.ProviderException; import java.security.SecureRandom; import java.util.Random; +import java.util.function.Function; import org.joda.time.DateTime; /** Utility class that converts an {@link XjcRdeDomainElement} into a {@link DomainResource}. */ diff --git a/java/google/registry/reporting/IcannReportingStager.java b/java/google/registry/reporting/IcannReportingStager.java index 1fcfb8797..4bd099296 100644 --- a/java/google/registry/reporting/IcannReportingStager.java +++ b/java/google/registry/reporting/IcannReportingStager.java @@ -16,6 +16,7 @@ package google.registry.reporting; import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.common.collect.ImmutableList.toImmutableList; import static google.registry.reporting.IcannReportingModule.MANIFEST_FILE_NAME; import static java.nio.charset.StandardCharsets.UTF_8; @@ -119,7 +120,7 @@ public class IcannReportingStager { return fields .stream() .map((schema) -> schema.getName().replace('_', '-')) - .collect(ImmutableList.toImmutableList()); + .collect(toImmutableList()); } /** Creates and stores activity reports on GCS, returns a list of files stored. */ @@ -183,7 +184,7 @@ public class IcannReportingStager { // Ignore TLD, Registrar name and IANA id .skip(3) .map((Object o) -> Integer.parseInt(o.toString())) - .collect(Collectors.toList()); + .collect(toImmutableList()); checkState( rowVals.size() == totals.size(), "Number of elements in totals not equal to number of elements in row!"); diff --git a/java/google/registry/request/Modules.java b/java/google/registry/request/Modules.java index fbfe4000c..27482a670 100644 --- a/java/google/registry/request/Modules.java +++ b/java/google/registry/request/Modules.java @@ -33,7 +33,6 @@ import com.google.appengine.api.urlfetch.URLFetchService; import com.google.appengine.api.urlfetch.URLFetchServiceFactory; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; -import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import dagger.Binds; import dagger.Module; @@ -43,6 +42,7 @@ import google.registry.keyring.api.KeyModule.Key; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Set; +import java.util.function.Function; import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; diff --git a/java/google/registry/request/Route.java b/java/google/registry/request/Route.java index 124c6641c..66536174f 100644 --- a/java/google/registry/request/Route.java +++ b/java/google/registry/request/Route.java @@ -15,7 +15,7 @@ package google.registry.request; import com.google.auto.value.AutoValue; -import com.google.common.base.Function; +import java.util.function.Function; /** * Mapping of an {@link Action} to a {@link Runnable} instantiator for request handling. diff --git a/java/google/registry/request/Router.java b/java/google/registry/request/Router.java index d4bdc8ec6..181e9ef87 100644 --- a/java/google/registry/request/Router.java +++ b/java/google/registry/request/Router.java @@ -17,7 +17,6 @@ package google.registry.request; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Throwables.throwIfUnchecked; -import com.google.common.base.Function; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.Ordering; import java.lang.reflect.InvocationTargetException; @@ -25,6 +24,7 @@ import java.lang.reflect.Method; import java.util.Map; import java.util.Optional; import java.util.TreeMap; +import java.util.function.Function; /** * Path prefix request router. diff --git a/java/google/registry/tools/CreateAuctionCreditsCommand.java b/java/google/registry/tools/CreateAuctionCreditsCommand.java index b6fba4c8b..39308e28f 100644 --- a/java/google/registry/tools/CreateAuctionCreditsCommand.java +++ b/java/google/registry/tools/CreateAuctionCreditsCommand.java @@ -24,7 +24,6 @@ import static org.joda.time.DateTimeZone.UTC; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; -import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Iterables; @@ -43,6 +42,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.function.Function; import java.util.stream.Stream; import org.joda.money.BigMoney; import org.joda.money.CurrencyUnit; diff --git a/java/google/registry/tools/LockDomainCommand.java b/java/google/registry/tools/LockDomainCommand.java index 49d0fdcff..dcb43f2f6 100644 --- a/java/google/registry/tools/LockDomainCommand.java +++ b/java/google/registry/tools/LockDomainCommand.java @@ -15,9 +15,9 @@ package google.registry.tools; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.ImmutableList.toImmutableList; import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.util.FormattingLogger.getLoggerForCallerClass; -import static java.util.stream.Collectors.toList; import static org.joda.time.DateTimeZone.UTC; import com.beust.jcommander.Parameters; @@ -64,7 +64,8 @@ public class LockDomainCommand extends LockOrUnlockDomainCommand { "addNameservers", ImmutableList.of(), "addAdmins", ImmutableList.of(), "addTechs", ImmutableList.of(), - "addStatuses", statusesToAdd.stream().map(StatusValue::getXmlName).collect(toList()), + "addStatuses", + statusesToAdd.stream().map(StatusValue::getXmlName).collect(toImmutableList()), "remove", false, "removeNameservers", ImmutableList.of(), "removeAdmins", ImmutableList.of(), diff --git a/java/google/registry/tools/MutatingCommand.java b/java/google/registry/tools/MutatingCommand.java index f2a1c3ad1..823891ab0 100644 --- a/java/google/registry/tools/MutatingCommand.java +++ b/java/google/registry/tools/MutatingCommand.java @@ -16,7 +16,6 @@ package google.registry.tools; import static com.google.common.base.CaseFormat.UPPER_CAMEL; import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; -import static com.google.common.base.Functions.toStringFunction; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; @@ -227,6 +226,6 @@ public abstract class MutatingCommand extends ConfirmingCommand implements Remot protected String prompt() { return changedEntitiesMap.isEmpty() ? "No entity changes to apply." - : changedEntitiesMap.values().stream().map(toStringFunction()).collect(joining("\n")); + : changedEntitiesMap.values().stream().map(Object::toString).collect(joining("\n")); } } diff --git a/java/google/registry/tools/PendingEscrowCommand.java b/java/google/registry/tools/PendingEscrowCommand.java index d2ab3dbc4..0fc5e6745 100644 --- a/java/google/registry/tools/PendingEscrowCommand.java +++ b/java/google/registry/tools/PendingEscrowCommand.java @@ -17,7 +17,6 @@ package google.registry.tools; import static java.util.stream.Collectors.joining; import com.beust.jcommander.Parameters; -import com.google.common.base.Functions; import com.google.common.collect.ComparisonChain; import com.google.common.collect.Ordering; import google.registry.rde.PendingDeposit; @@ -49,7 +48,7 @@ final class PendingEscrowCommand implements RemoteApiCommand { SORTER .sortedCopy(checker.getTldsAndWatermarksPendingDepositForRdeAndBrda().values()) .stream() - .map(Functions.toStringFunction()) + .map(Object::toString) .collect(joining("\n"))); } } diff --git a/java/google/registry/tools/UnlockDomainCommand.java b/java/google/registry/tools/UnlockDomainCommand.java index 598814629..55c45554b 100644 --- a/java/google/registry/tools/UnlockDomainCommand.java +++ b/java/google/registry/tools/UnlockDomainCommand.java @@ -15,9 +15,9 @@ package google.registry.tools; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.ImmutableList.toImmutableList; import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.util.FormattingLogger.getLoggerForCallerClass; -import static java.util.stream.Collectors.toList; import static org.joda.time.DateTimeZone.UTC; import com.beust.jcommander.Parameters; @@ -71,7 +71,7 @@ public class UnlockDomainCommand extends LockOrUnlockDomainCommand { "removeAdmins", ImmutableList.of(), "removeTechs", ImmutableList.of(), "removeStatuses", - statusesToRemove.stream().map(StatusValue::getXmlName).collect(toList()), + statusesToRemove.stream().map(StatusValue::getXmlName).collect(toImmutableList()), "change", false)); } } diff --git a/java/google/registry/tools/server/ListObjectsAction.java b/java/google/registry/tools/server/ListObjectsAction.java index d05bfe093..1438b4dd8 100644 --- a/java/google/registry/tools/server/ListObjectsAction.java +++ b/java/google/registry/tools/server/ListObjectsAction.java @@ -18,8 +18,6 @@ import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.ImmutableSet.toImmutableSet; -import com.google.common.base.Function; -import com.google.common.base.Functions; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Strings; @@ -42,6 +40,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.function.Function; import java.util.stream.Stream; import javax.inject.Inject; @@ -187,7 +186,7 @@ public abstract class ListObjectsAction implements Ru // Next, add to the mapping all the aliases, with their values defined as whatever was in the // map under the aliased field's original name. fieldMap.putAll( - Maps.transformValues(getFieldAliases(), Functions.forMap(new HashMap<>(fieldMap)))); + new HashMap<>(Maps.transformValues(getFieldAliases(), value -> fieldMap.get(value)))); Set expectedFields = ImmutableSortedSet.copyOf(fieldMap.keySet()); for (String field : fields) { checkArgument(fieldMap.containsKey(field), @@ -235,8 +234,7 @@ public abstract class ListObjectsAction implements Ru if (isHeaderRowInUse(data)) { // Add a row of headers (column names mapping to themselves). - Map headerRow = - Maps.asMap(data.columnKeySet(), Functions.identity()); + Map headerRow = Maps.asMap(data.columnKeySet(), key -> key); lines.add(rowFormatter.apply(headerRow)); // Add a row of separator lines (column names mapping to '-' * column width). diff --git a/java/google/registry/ui/forms/FormField.java b/java/google/registry/ui/forms/FormField.java index d6e34d0d5..7b6e9f6ab 100644 --- a/java/google/registry/ui/forms/FormField.java +++ b/java/google/registry/ui/forms/FormField.java @@ -22,8 +22,6 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet; import com.google.common.base.Ascii; import com.google.common.base.CharMatcher; -import com.google.common.base.Function; -import com.google.common.base.Functions; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -36,6 +34,7 @@ import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.function.Function; import javax.annotation.Detainted; import javax.annotation.Nullable; import javax.annotation.Tainted; @@ -137,7 +136,7 @@ public final class FormField { /** Returns an optional form field named {@code name} with a specific {@code inputType}. */ public static Builder named(String name, Class typeIn) { checkArgument(!name.isEmpty()); - return new Builder<>(name, checkNotNull(typeIn), typeIn, Functions.identity()); + return new Builder<>(name, checkNotNull(typeIn), typeIn, x -> x); } /** @@ -445,8 +444,8 @@ public final class FormField { * @see #transform(Function) */ public Builder transform(Class newType, Function transform) { - return new Builder<>(name, typeIn, checkNotNull(newType), - Functions.compose(checkNotNull(transform), converter)); + return new Builder<>( + name, typeIn, checkNotNull(newType), this.converter.andThen(checkNotNull(transform))); } /** @@ -456,7 +455,7 @@ public final class FormField { * which {@code transform} is expected to conform. */ public Builder transform(Function transform) { - this.converter = Functions.compose(checkNotNull(transform), converter); + this.converter = this.converter.andThen(checkNotNull(transform)); return this; } diff --git a/java/google/registry/ui/server/RegistrarFormFields.java b/java/google/registry/ui/server/RegistrarFormFields.java index 923dc4ac0..bbb70032e 100644 --- a/java/google/registry/ui/server/RegistrarFormFields.java +++ b/java/google/registry/ui/server/RegistrarFormFields.java @@ -20,7 +20,6 @@ import static com.google.common.collect.Range.closed; import static google.registry.util.DomainNameUtils.canonicalizeDomainName; import com.google.common.base.Ascii; -import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.net.InternetDomainName; @@ -38,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.function.Function; /** Form fields for validating input for the {@code Registrar} class. */ public final class RegistrarFormFields { diff --git a/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java b/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java index 61ffdb23d..3ccf791d4 100644 --- a/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java +++ b/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java @@ -14,7 +14,6 @@ package google.registry.ui.server.registrar; -import static com.google.common.base.Functions.toStringFunction; import static com.google.common.collect.ImmutableList.toImmutableList; import static google.registry.security.JsonResponseHelper.Status.ERROR; import static google.registry.security.JsonResponseHelper.Status.SUCCESS; @@ -118,7 +117,7 @@ public final class RegistrarPaymentSetupAction implements Runnable, JsonAction { accountIds .keySet() .stream() - .map(toStringFunction()) + .map(Object::toString) .collect(toImmutableList())))); } } diff --git a/java/google/registry/util/Concurrent.java b/java/google/registry/util/Concurrent.java index 0d7aa862d..9d2656f56 100644 --- a/java/google/registry/util/Concurrent.java +++ b/java/google/registry/util/Concurrent.java @@ -21,7 +21,6 @@ import static java.lang.Math.max; import static java.lang.Math.min; import static java.util.concurrent.Executors.newFixedThreadPool; -import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.common.util.concurrent.Uninterruptibles; @@ -32,6 +31,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.ThreadFactory; +import java.util.function.Function; /** Utilities for multithreaded operations in App Engine requests. */ public final class Concurrent { diff --git a/java/google/registry/util/ObjectifyUtils.java b/java/google/registry/util/ObjectifyUtils.java deleted file mode 100644 index 7b99749da..000000000 --- a/java/google/registry/util/ObjectifyUtils.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.util; - -import com.google.common.base.Function; -import com.googlecode.objectify.Key; - -/** Utilities for working with Objectify. */ -public class ObjectifyUtils { - - public static final Function> OBJECTS_TO_KEYS = Key::create; -} diff --git a/java/google/registry/whois/WhoisResponseImpl.java b/java/google/registry/whois/WhoisResponseImpl.java index a56e5ef25..8e5e39878 100644 --- a/java/google/registry/whois/WhoisResponseImpl.java +++ b/java/google/registry/whois/WhoisResponseImpl.java @@ -19,7 +19,6 @@ import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.html.HtmlEscapers.htmlEscaper; -import com.google.common.base.Function; import com.google.common.base.Joiner; import google.registry.model.eppcommon.Address; import google.registry.util.Idn; @@ -27,6 +26,7 @@ import google.registry.xml.UtcDateTimeAdapter; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.function.Function; import javax.annotation.Nullable; import org.joda.time.DateTime; diff --git a/javatests/google/registry/backup/RestoreCommitLogsActionTest.java b/javatests/google/registry/backup/RestoreCommitLogsActionTest.java index 3274b0598..9baa4deeb 100644 --- a/javatests/google/registry/backup/RestoreCommitLogsActionTest.java +++ b/javatests/google/registry/backup/RestoreCommitLogsActionTest.java @@ -15,7 +15,6 @@ package google.registry.backup; import static com.google.appengine.tools.cloudstorage.GcsServiceFactory.createGcsService; -import static com.google.common.base.Functions.constant; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Maps.toMap; import static com.google.common.truth.Truth.assertThat; @@ -247,7 +246,7 @@ public class RestoreCommitLogsActionTest { } private CommitLogCheckpoint createCheckpoint(DateTime now) { - return CommitLogCheckpoint.create(now, toMap(getBucketIds(), constant(now))); + return CommitLogCheckpoint.create(now, toMap(getBucketIds(), x -> now)); } private Iterable saveDiffFile( diff --git a/javatests/google/registry/flows/FlowTestCase.java b/javatests/google/registry/flows/FlowTestCase.java index e1cdf6c5c..d2b1ba4f2 100644 --- a/javatests/google/registry/flows/FlowTestCase.java +++ b/javatests/google/registry/flows/FlowTestCase.java @@ -16,23 +16,24 @@ package google.registry.flows; import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.Sets.difference; import static com.google.common.truth.Truth.assertThat; import static google.registry.flows.EppXmlTransformer.marshal; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.testing.DatastoreHelper.BILLING_EVENT_ID_STRIPPER; +import static google.registry.testing.DatastoreHelper.POLL_MESSAGE_ID_STRIPPER; import static google.registry.testing.DatastoreHelper.getPollMessages; import static google.registry.xml.XmlTestUtils.assertXmlEquals; import static java.nio.charset.StandardCharsets.UTF_8; import static org.joda.time.DateTimeZone.UTC; -import com.google.common.base.Function; -import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.ObjectArrays; +import com.google.common.collect.Streams; import google.registry.config.RegistryConfig.ConfigModule.TmchCaMode; import google.registry.flows.EppTestComponent.FakesAndMocksModule; import google.registry.flows.picker.FlowPicker; @@ -58,8 +59,10 @@ import google.registry.tmch.TmchCertificateAuthority; import google.registry.tmch.TmchXmlSignature; import google.registry.util.TypeUtils.TypeInstantiator; import google.registry.xml.ValidationMode; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.function.Function; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Rule; @@ -217,6 +220,18 @@ public abstract class FlowTestCase extends ShardableTestCase { return builder.build(); } + private static BillingEvent expandGracePeriod(GracePeriod gracePeriod) { + assertThat(gracePeriod.hasBillingEvent()) + .named("Billing event is present for grace period: " + gracePeriod) + .isTrue(); + return ofy() + .load() + .key( + firstNonNull( + gracePeriod.getOneTimeBillingEvent(), gracePeriod.getRecurringBillingEvent())) + .now(); + } + /** * Assert that the actual grace periods and the corresponding billing events referenced from * their keys match the expected map of grace periods to billing events. For the expected map, @@ -225,19 +240,7 @@ public abstract class FlowTestCase extends ShardableTestCase { public void assertGracePeriods( Iterable actual, ImmutableMap expected) { - Function gracePeriodExpander = - gracePeriod -> { - assertThat(gracePeriod.hasBillingEvent()) - .named("Billing event is present for grace period: " + gracePeriod) - .isTrue(); - return ofy() - .load() - .key( - firstNonNull( - gracePeriod.getOneTimeBillingEvent(), gracePeriod.getRecurringBillingEvent())) - .now(); - }; - assertThat(canonicalizeGracePeriods(Maps.toMap(actual, gracePeriodExpander))) + assertThat(canonicalizeGracePeriods(Maps.toMap(actual, FlowTestCase::expandGracePeriod))) .isEqualTo(canonicalizeGracePeriods(expected)); } @@ -261,12 +264,11 @@ public abstract class FlowTestCase extends ShardableTestCase { /** Assert that the list matches all the poll messages in the fake Datastore. */ public void assertPollMessagesHelper(Iterable pollMessages, PollMessage... expected) throws Exception { - // To facilitate comparison, remove the ids. - Function idStripper = - pollMessage -> pollMessage.asBuilder().setId(1L).build(); // Ordering is irrelevant but duplicates should be considered independently. - assertThat(FluentIterable.from(pollMessages).transform(idStripper)) - .containsExactlyElementsIn(FluentIterable.from(expected).transform(idStripper)); + assertThat( + Streams.stream(pollMessages).map(POLL_MESSAGE_ID_STRIPPER).collect(toImmutableList())) + .containsExactlyElementsIn( + Arrays.stream(expected).map(POLL_MESSAGE_ID_STRIPPER).collect(toImmutableList())); } private EppOutput runFlowInternal(CommitMode commitMode, UserPrivileges userPrivileges) diff --git a/javatests/google/registry/flows/domain/DomainTransferApproveFlowTest.java b/javatests/google/registry/flows/domain/DomainTransferApproveFlowTest.java index 087273f67..a87ac7511 100644 --- a/javatests/google/registry/flows/domain/DomainTransferApproveFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainTransferApproveFlowTest.java @@ -37,8 +37,6 @@ import static google.registry.testing.JUnitBackports.expectThrows; import static google.registry.util.DateTimeUtils.START_OF_TIME; import static org.joda.money.CurrencyUnit.USD; -import com.google.common.base.Function; -import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; @@ -72,6 +70,8 @@ import google.registry.model.reporting.HistoryEntry; import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferResponse.DomainTransferResponse; import google.registry.model.transfer.TransferStatus; +import java.util.Arrays; +import java.util.stream.Stream; import org.joda.money.Money; import org.joda.time.DateTime; import org.joda.time.Duration; @@ -262,22 +262,21 @@ public class DomainTransferApproveFlowTest .build(); assertBillingEventsForResource( domain, - FluentIterable.from(expectedCancellationBillingEvents) - .transform( - (Function) - builder -> builder.setParent(historyEntryTransferApproved).build()) - .append( - transferBillingEvent, - getLosingClientAutorenewEvent() - .asBuilder() - .setRecurrenceEndTime(clock.nowUtc()) - .build(), - getGainingClientAutorenewEvent() - .asBuilder() - .setEventTime(domain.getRegistrationExpirationTime()) - .setParent(historyEntryTransferApproved) - .build()) - .toArray(BillingEvent.class)); + Stream.concat( + Arrays.stream(expectedCancellationBillingEvents) + .map(builder -> builder.setParent(historyEntryTransferApproved).build()), + Stream.of( + transferBillingEvent, + getLosingClientAutorenewEvent() + .asBuilder() + .setRecurrenceEndTime(clock.nowUtc()) + .build(), + getGainingClientAutorenewEvent() + .asBuilder() + .setEventTime(domain.getRegistrationExpirationTime()) + .setParent(historyEntryTransferApproved) + .build())) + .toArray(size -> new BillingEvent[size])); // There should be a grace period for the new transfer billing event. assertGracePeriods( domain.getGracePeriods(), @@ -299,21 +298,20 @@ public class DomainTransferApproveFlowTest // for the gaining client that begins at the new expiration time. assertBillingEventsForResource( domain, - FluentIterable.from(expectedCancellationBillingEvents) - .transform( - (Function) - builder -> builder.setParent(historyEntryTransferApproved).build()) - .append( - getLosingClientAutorenewEvent() - .asBuilder() - .setRecurrenceEndTime(clock.nowUtc()) - .build(), - getGainingClientAutorenewEvent() - .asBuilder() - .setEventTime(domain.getRegistrationExpirationTime()) - .setParent(historyEntryTransferApproved) - .build()) - .toArray(BillingEvent.class)); + Stream.concat( + Arrays.stream(expectedCancellationBillingEvents) + .map(builder -> builder.setParent(historyEntryTransferApproved).build()), + Stream.of( + getLosingClientAutorenewEvent() + .asBuilder() + .setRecurrenceEndTime(clock.nowUtc()) + .build(), + getGainingClientAutorenewEvent() + .asBuilder() + .setEventTime(domain.getRegistrationExpirationTime()) + .setParent(historyEntryTransferApproved) + .build())) + .toArray(size -> new BillingEvent[size])); // There should be no grace period. assertGracePeriods(domain.getGracePeriods(), ImmutableMap.of()); } diff --git a/javatests/google/registry/flows/domain/DomainTransferRequestFlowTest.java b/javatests/google/registry/flows/domain/DomainTransferRequestFlowTest.java index 7499807d0..c3c44c577 100644 --- a/javatests/google/registry/flows/domain/DomainTransferRequestFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainTransferRequestFlowTest.java @@ -14,6 +14,7 @@ package google.registry.flows.domain; +import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.MoreCollectors.onlyElement; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; @@ -37,12 +38,10 @@ import static google.registry.testing.HostResourceSubject.assertAboutHosts; import static google.registry.testing.JUnitBackports.assertThrows; import static google.registry.testing.JUnitBackports.expectThrows; import static google.registry.util.DateTimeUtils.START_OF_TIME; -import static java.util.stream.Collectors.toSet; import static org.joda.money.CurrencyUnit.EUR; import static org.joda.money.CurrencyUnit.USD; import com.google.appengine.repackaged.com.google.common.collect.Sets; -import com.google.common.base.Function; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -91,7 +90,6 @@ import google.registry.model.transfer.TransferResponse; import google.registry.model.transfer.TransferStatus; import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.stream.Stream; import org.joda.money.Money; import org.joda.time.DateTime; @@ -257,6 +255,11 @@ public class DomainTransferRequestFlowTest expectedExpirationTime, implicitTransferTime, Period.create(1, Unit.YEARS)); } + /** Implements the missing Optional.stream function that is added in Java 9. */ + private static Stream optionalToStream(Optional optional) { + return optional.map(Stream::of).orElseGet(Stream::empty); + } + private void assertHistoryEntriesContainBillingEventsAndGracePeriods( DateTime expectedExpirationTime, DateTime implicitTransferTime, @@ -304,16 +307,16 @@ public class DomainTransferRequestFlowTest BillingEvent.Recurring gainingClientAutorenew = getGainingClientAutorenewEvent().asBuilder().setEventTime(expectedExpirationTime).build(); // Construct extra billing events expected by the specific test. - Set extraBillingEvents = + ImmutableSet extraBillingEvents = Stream.of(extraExpectedBillingEvents) - .map( - (Function) - builder -> builder.setParent(historyEntryTransferRequest).build()) - .collect(toSet()); + .map(builder -> builder.setParent(historyEntryTransferRequest).build()) + .collect(toImmutableSet()); // Assert that the billing events we constructed above actually exist in Datastore. - Set expectedBillingEvents = - Sets.newHashSet(losingClientAutorenew, gainingClientAutorenew); - optionalTransferBillingEvent.ifPresent(expectedBillingEvents::add); + ImmutableSet expectedBillingEvents = + Stream.concat( + Stream.of(losingClientAutorenew, gainingClientAutorenew), + optionalToStream(optionalTransferBillingEvent)) + .collect(toImmutableSet()); assertBillingEvents(Sets.union(expectedBillingEvents, extraBillingEvents)); // Assert that the domain's TransferData server-approve billing events match the above. if (expectTransferBillingEvent) { @@ -328,8 +331,10 @@ public class DomainTransferRequestFlowTest gainingClientAutorenew); // Assert that the full set of server-approve billing events is exactly the extra ones plus // the transfer billing event (if present) and the gaining client autorenew. - Set expectedServeApproveBillingEvents = Sets.newHashSet(gainingClientAutorenew); - optionalTransferBillingEvent.ifPresent(expectedServeApproveBillingEvents::add); + ImmutableSet expectedServeApproveBillingEvents = + Stream.concat( + Stream.of(gainingClientAutorenew), optionalToStream(optionalTransferBillingEvent)) + .collect(toImmutableSet()); assertBillingEventsEqual( Iterables.filter( ofy() diff --git a/javatests/google/registry/model/EntityClassesTest.java b/javatests/google/registry/model/EntityClassesTest.java index 1869788cd..62cd7e61f 100644 --- a/javatests/google/registry/model/EntityClassesTest.java +++ b/javatests/google/registry/model/EntityClassesTest.java @@ -18,7 +18,6 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.EntityClasses.ALL_CLASSES; import static google.registry.util.TypeUtils.hasAnnotation; -import static java.util.stream.Collectors.toSet; import com.google.common.collect.Ordering; import com.googlecode.objectify.Key; @@ -63,13 +62,13 @@ public class EntityClassesTest { .stream() .filter(hasAnnotation(Entity.class)) .map(Key::getKind) - .collect(toSet()); + .collect(toImmutableSet()); Set entitySubclassKinds = ALL_CLASSES .stream() .filter(hasAnnotation(EntitySubclass.class)) .map(Key::getKind) - .collect(toSet()); + .collect(toImmutableSet()); assertThat(baseEntityKinds).named("base entity kinds").containsAllIn(entitySubclassKinds); } diff --git a/javatests/google/registry/model/ImmutableObjectTest.java b/javatests/google/registry/model/ImmutableObjectTest.java index 7b31d1b68..66dc03477 100644 --- a/javatests/google/registry/model/ImmutableObjectTest.java +++ b/javatests/google/registry/model/ImmutableObjectTest.java @@ -251,6 +251,27 @@ public class ImmutableObjectTest { assertThat(cloned.heterogenousMap).containsEntry("b", ""); } + /** Subclass of ImmutableObject with fields that are containers containing null values. */ + public static class NullInContainersObject extends ImmutableObject { + Object[] array = new Object[] {null}; + List list = newArrayList((Object) null); + Set set = newHashSet((Object) null); + Map map = newHashMap(); + + public NullInContainersObject() { + map.put("a", null); + } + } + + @Test + public void testToDiffableFieldMap_withEmptyAndNulls() { + Map diffableFieldMap = new NullInContainersObject().toDiffableFieldMap(); + assertThat((List) diffableFieldMap.get("array")).containsExactly((Object) null); + assertThat((List) diffableFieldMap.get("list")).containsExactly((Object) null); + assertThat((Set) diffableFieldMap.get("set")).containsExactly((Object) null); + assertThat((Map) diffableFieldMap.get("map")).containsExactly("a", (Object) null); + } + /** Subclass of ImmutableObject with keys to other objects. */ public static class RootObject extends ImmutableObject { diff --git a/javatests/google/registry/model/registry/RegistryTest.java b/javatests/google/registry/model/registry/RegistryTest.java index c461cc6ae..ba0ee59fd 100644 --- a/javatests/google/registry/model/registry/RegistryTest.java +++ b/javatests/google/registry/model/registry/RegistryTest.java @@ -14,12 +14,11 @@ package google.registry.model.registry; -import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.ofy.ObjectifyService.ofy; -import static google.registry.model.registry.label.ReservedListTest.GET_NAME_FUNCTION; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.newRegistry; import static google.registry.testing.DatastoreHelper.persistPremiumList; @@ -142,7 +141,7 @@ public class RegistryTest extends EntityTestCase { "mouse,FULLY_BLOCKED"); Registry r = Registry.get("tld") .asBuilder().setReservedLists(ImmutableSet.of(rl5, rl6)).build(); - assertThat(transform(r.getReservedLists(), GET_NAME_FUNCTION)) + assertThat(r.getReservedLists().stream().map(Key::getName).collect(toImmutableList())) .containsExactly("tld-reserved5", "tld-reserved6"); r = Registry.get("tld").asBuilder().setReservedLists(ImmutableSet. of()).build(); assertThat(r.getReservedLists()).isEmpty(); @@ -163,7 +162,7 @@ public class RegistryTest extends EntityTestCase { .asBuilder() .setReservedListsByName(ImmutableSet.of("tld-reserved24", "tld-reserved25")) .build(); - assertThat(transform(r.getReservedLists(), GET_NAME_FUNCTION)) + assertThat(r.getReservedLists().stream().map(Key::getName).collect(toImmutableList())) .containsExactly("tld-reserved24", "tld-reserved25"); r = Registry.get("tld").asBuilder().setReservedListsByName(ImmutableSet. of()).build(); assertThat(r.getReservedLists()).isEmpty(); diff --git a/javatests/google/registry/model/registry/label/ReservedListTest.java b/javatests/google/registry/model/registry/label/ReservedListTest.java index ffd330fce..abc0103ba 100644 --- a/javatests/google/registry/model/registry/label/ReservedListTest.java +++ b/javatests/google/registry/model/registry/label/ReservedListTest.java @@ -36,11 +36,9 @@ import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.testing.JUnitBackports.assertThrows; import static google.registry.testing.JUnitBackports.expectThrows; -import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.net.InternetDomainName; -import com.googlecode.objectify.Key; import google.registry.model.ofy.Ofy; import google.registry.model.registry.Registry; import google.registry.model.registry.label.ReservedList.ReservedListEntry; @@ -585,7 +583,4 @@ public class ReservedListTest { .contains( "List 'blah' cannot contain duplicate labels. Dupes (with counts) were: [lol x 2]"); } - - /** Gets the name of a reserved list. */ - public static final Function, String> GET_NAME_FUNCTION = Key::getName; } diff --git a/javatests/google/registry/request/RouterTest.java b/javatests/google/registry/request/RouterTest.java index 18d5306f7..8111ac3ba 100644 --- a/javatests/google/registry/request/RouterTest.java +++ b/javatests/google/registry/request/RouterTest.java @@ -19,9 +19,9 @@ import static com.google.common.truth.Truth8.assertThat; import static google.registry.request.auth.Auth.AUTH_INTERNAL_ONLY; import static google.registry.testing.JUnitBackports.expectThrows; -import com.google.common.base.Function; import java.util.Optional; import java.util.concurrent.Callable; +import java.util.function.Function; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/javatests/google/registry/testing/DatastoreHelper.java b/javatests/google/registry/testing/DatastoreHelper.java index a8e510414..d125da02c 100644 --- a/javatests/google/registry/testing/DatastoreHelper.java +++ b/javatests/google/registry/testing/DatastoreHelper.java @@ -43,10 +43,8 @@ import static java.util.Arrays.asList; import static org.joda.money.CurrencyUnit.USD; import com.google.common.base.Ascii; -import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.base.Supplier; -import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -103,6 +101,7 @@ import google.registry.tmch.LordnTask; import java.util.Arrays; import java.util.List; import java.util.Set; +import java.util.function.Function; import javax.annotation.Nullable; import org.joda.money.Money; import org.joda.time.DateTime; @@ -669,8 +668,9 @@ public class DatastoreHelper { /** Assert that the actual billing events match the expected ones, ignoring IDs and order. */ public static void assertBillingEventsEqual( Iterable actual, Iterable expected) { - assertThat(Iterables.transform(actual, BILLING_EVENT_ID_STRIPPER)) - .containsExactlyElementsIn(Iterables.transform(expected, BILLING_EVENT_ID_STRIPPER)); + assertThat(Streams.stream(actual).map(BILLING_EVENT_ID_STRIPPER).collect(toImmutableList())) + .containsExactlyElementsIn( + Streams.stream(expected).map(BILLING_EVENT_ID_STRIPPER).collect(toImmutableList())); } /** Assert that the expected billing events are exactly the ones found in the fake Datastore. */ @@ -688,9 +688,12 @@ public class DatastoreHelper { */ public static void assertBillingEventsForResource( EppResource resource, BillingEvent... expected) throws Exception { - assertThat(FluentIterable.from(getBillingEvents(resource)).transform(BILLING_EVENT_ID_STRIPPER)) + assertThat( + Streams.stream(getBillingEvents(resource)) + .map(BILLING_EVENT_ID_STRIPPER) + .collect(toImmutableList())) .containsExactlyElementsIn( - FluentIterable.from(expected).transform(BILLING_EVENT_ID_STRIPPER)); + Arrays.stream(expected).map(BILLING_EVENT_ID_STRIPPER).collect(toImmutableList())); } /** Assert that there are no billing events. */ @@ -711,15 +714,20 @@ public class DatastoreHelper { /** Assert that the actual poll messages match the expected ones, ignoring IDs and order. */ public static void assertPollMessagesEqual( Iterable actual, Iterable expected) { - assertThat(Iterables.transform(actual, POLL_MESSAGE_ID_STRIPPER)) - .containsExactlyElementsIn(Iterables.transform(expected, POLL_MESSAGE_ID_STRIPPER)); + assertThat(Streams.stream(actual).map(POLL_MESSAGE_ID_STRIPPER).collect(toImmutableList())) + .containsExactlyElementsIn( + Streams.stream(expected).map(POLL_MESSAGE_ID_STRIPPER).collect(toImmutableList())); } public static void assertPollMessagesForResource(EppResource resource, PollMessage... expected) throws Exception { - assertThat(FluentIterable.from(getPollMessages(resource)).transform(POLL_MESSAGE_ID_STRIPPER)) + assertThat( + getPollMessages(resource) + .stream() + .map(POLL_MESSAGE_ID_STRIPPER) + .collect(toImmutableList())) .containsExactlyElementsIn( - FluentIterable.from(expected).transform(POLL_MESSAGE_ID_STRIPPER)); + Arrays.stream(expected).map(POLL_MESSAGE_ID_STRIPPER).collect(toImmutableList())); } /** Helper to effectively erase the poll message ID to facilitate comparison. */ diff --git a/javatests/google/registry/testing/TaskQueueHelper.java b/javatests/google/registry/testing/TaskQueueHelper.java index 8d59e1785..f2d0832a2 100644 --- a/javatests/google/registry/testing/TaskQueueHelper.java +++ b/javatests/google/registry/testing/TaskQueueHelper.java @@ -18,8 +18,8 @@ import static com.google.appengine.tools.development.testing.LocalTaskQueueTestC import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Predicates.in; import static com.google.common.base.Predicates.not; +import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.Iterables.getFirst; -import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Multisets.containsOccurrences; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assert_; @@ -32,7 +32,6 @@ import com.google.appengine.api.taskqueue.dev.QueueStateInfo; import com.google.appengine.api.taskqueue.dev.QueueStateInfo.HeaderWrapper; import com.google.appengine.api.taskqueue.dev.QueueStateInfo.TaskStateInfo; import com.google.common.base.Ascii; -import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.collect.ArrayListMultimap; @@ -55,6 +54,7 @@ import java.util.LinkedList; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.function.Function; import javax.annotation.Nonnull; import org.joda.time.Duration; @@ -196,7 +196,12 @@ public class TaskQueueHelper { Function propertyGetter, String... expectedTaskProperties) throws Exception { // Ordering is irrelevant but duplicates should be considered independently. - assertThat(transform(getQueueInfo(queueName).getTaskInfo(), propertyGetter)) + assertThat( + getQueueInfo(queueName) + .getTaskInfo() + .stream() + .map(propertyGetter) + .collect(toImmutableList())) .containsExactly((Object[]) expectedTaskProperties); } diff --git a/javatests/google/registry/tools/CreateTldCommandTest.java b/javatests/google/registry/tools/CreateTldCommandTest.java index e192ceca9..c59f49b05 100644 --- a/javatests/google/registry/tools/CreateTldCommandTest.java +++ b/javatests/google/registry/tools/CreateTldCommandTest.java @@ -14,9 +14,8 @@ package google.registry.tools; -import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.registry.label.ReservedListTest.GET_NAME_FUNCTION; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.persistPremiumList; import static google.registry.testing.DatastoreHelper.persistReservedList; @@ -31,6 +30,7 @@ import static org.joda.time.Duration.standardMinutes; import com.beust.jcommander.ParameterException; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Range; +import com.googlecode.objectify.Key; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import java.io.ByteArrayOutputStream; @@ -283,7 +283,12 @@ public class CreateTldCommandTest extends CommandTestCase { "--roid_suffix=Q9JYB4C", "--dns_writers=VoidDnsWriter", "xn--q9jyb4c"); - assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION)) + assertThat( + Registry.get("xn--q9jyb4c") + .getReservedLists() + .stream() + .map(Key::getName) + .collect(toImmutableList())) .containsExactly("xn--q9jyb4c_abuse", "common_abuse"); } diff --git a/javatests/google/registry/tools/UpdateTldCommandTest.java b/javatests/google/registry/tools/UpdateTldCommandTest.java index 0bb39aa52..535f41025 100644 --- a/javatests/google/registry/tools/UpdateTldCommandTest.java +++ b/javatests/google/registry/tools/UpdateTldCommandTest.java @@ -14,9 +14,8 @@ package google.registry.tools; -import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.registry.label.ReservedListTest.GET_NAME_FUNCTION; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.persistPremiumList; import static google.registry.testing.DatastoreHelper.persistReservedList; @@ -282,7 +281,12 @@ public class UpdateTldCommandTest extends CommandTestCase { public void testSuccess_setReservedLists() throws Exception { runCommandForced("--reserved_lists=xn--q9jyb4c_r1,xn--q9jyb4c_r2", "xn--q9jyb4c"); - assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION)) + assertThat( + Registry.get("xn--q9jyb4c") + .getReservedLists() + .stream() + .map(Key::getName) + .collect(toImmutableList())) .containsExactly("xn--q9jyb4c_r1", "xn--q9jyb4c_r2"); } @@ -292,7 +296,12 @@ public class UpdateTldCommandTest extends CommandTestCase { .setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1", "xn--q9jyb4c_r2")) .build()); runCommandForced("--reserved_lists=xn--q9jyb4c_r2", "xn--q9jyb4c"); - assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION)) + assertThat( + Registry.get("xn--q9jyb4c") + .getReservedLists() + .stream() + .map(Key::getName) + .collect(toImmutableList())) .containsExactly("xn--q9jyb4c_r2"); } @@ -302,7 +311,12 @@ public class UpdateTldCommandTest extends CommandTestCase { .setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1")) .build()); runCommandForced("--add_reserved_lists=xn--q9jyb4c_r2", "xn--q9jyb4c"); - assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION)) + assertThat( + Registry.get("xn--q9jyb4c") + .getReservedLists() + .stream() + .map(Key::getName) + .collect(toImmutableList())) .containsExactly("xn--q9jyb4c_r1", "xn--q9jyb4c_r2"); } @@ -321,7 +335,12 @@ public class UpdateTldCommandTest extends CommandTestCase { .setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1", "xn--q9jyb4c_r2")) .build()); runCommandForced("--remove_reserved_lists=xn--q9jyb4c_r1", "xn--q9jyb4c"); - assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION)) + assertThat( + Registry.get("xn--q9jyb4c") + .getReservedLists() + .stream() + .map(Key::getName) + .collect(toImmutableList())) .containsExactly("xn--q9jyb4c_r2"); } diff --git a/javatests/google/registry/ui/forms/FormFieldTest.java b/javatests/google/registry/ui/forms/FormFieldTest.java index 111df1f07..7b3112f6a 100644 --- a/javatests/google/registry/ui/forms/FormFieldTest.java +++ b/javatests/google/registry/ui/forms/FormFieldTest.java @@ -25,8 +25,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import com.google.common.base.CharMatcher; -import com.google.common.base.Function; -import com.google.common.base.Functions; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -36,6 +34,7 @@ import com.google.common.testing.NullPointerTester; import com.google.re2j.Pattern; import java.util.List; import java.util.Set; +import java.util.function.Function; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -241,7 +240,7 @@ public class FormFieldTest { assertThat( FormField.named("lol") .transform(Object.class, Integer::parseInt) - .transform(String.class, Functions.toStringFunction()) + .transform(String.class, Object::toString) .build() .convert("123")) .hasValue("123"); @@ -484,11 +483,12 @@ public class FormFieldTest { @Test public void testNullness() { - NullPointerTester tester = new NullPointerTester() - .setDefault(Class.class, Object.class) - .setDefault(Function.class, Functions.identity()) - .setDefault(Pattern.class, Pattern.compile(".")) - .setDefault(String.class, "hello.com"); + NullPointerTester tester = + new NullPointerTester() + .setDefault(Class.class, Object.class) + .setDefault(Function.class, x -> x) + .setDefault(Pattern.class, Pattern.compile(".")) + .setDefault(String.class, "hello.com"); tester.testAllPublicStaticMethods(FormField.class); tester.testAllPublicInstanceMethods(FormField.named("lol")); tester.testAllPublicInstanceMethods(FormField.named("lol").build()); diff --git a/javatests/google/registry/util/ConcurrentTest.java b/javatests/google/registry/util/ConcurrentTest.java index 7f0d54439..681b6827b 100644 --- a/javatests/google/registry/util/ConcurrentTest.java +++ b/javatests/google/registry/util/ConcurrentTest.java @@ -17,12 +17,11 @@ package google.registry.util; import static com.google.common.truth.Truth.assertThat; import static google.registry.testing.JUnitBackports.expectThrows; -import com.google.common.base.Function; -import com.google.common.base.Functions; import com.google.common.collect.ImmutableList; import com.google.common.testing.NullPointerTester; import com.google.common.util.concurrent.UncheckedExecutionException; import google.registry.testing.AppEngineRule; +import java.util.function.Function; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,7 +38,7 @@ public class ConcurrentTest { @Test public void testTransform_emptyList_returnsEmptyList() throws Exception { - assertThat(Concurrent.transform(ImmutableList.of(), Functions.identity())).isEmpty(); + assertThat(Concurrent.transform(ImmutableList.of(), x -> x)).isEmpty(); } @Test @@ -66,8 +65,7 @@ public class ConcurrentTest { @Test public void testNullness() throws Exception { - NullPointerTester tester = new NullPointerTester() - .setDefault(Function.class, Functions.identity()); + NullPointerTester tester = new NullPointerTester().setDefault(Function.class, x -> x); tester.testAllPublicStaticMethods(Concurrent.class); } }