Convert domain label list code to use Java 8 streams features

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=172774927
This commit is contained in:
mcilwain 2017-10-19 11:37:00 -07:00 committed by jianglai
parent f1c76d035f
commit 4828417c73
4 changed files with 69 additions and 95 deletions

View file

@ -16,6 +16,7 @@ package google.registry.model.registry.label;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.registry.Registries.getTlds; import static google.registry.model.registry.Registries.getTlds;
@ -136,14 +137,11 @@ public abstract class BaseDomainLabelList<T extends Comparable<?>, R extends Dom
/** Gets the names of the tlds that reference this list. */ /** Gets the names of the tlds that reference this list. */
public final ImmutableSet<String> getReferencingTlds() { public final ImmutableSet<String> getReferencingTlds() {
ImmutableSet.Builder<String> builder = new ImmutableSet.Builder<>();
Key<? extends BaseDomainLabelList<?, ?>> key = Key.create(this); Key<? extends BaseDomainLabelList<?, ?>> key = Key.create(this);
for (String tld : getTlds()) { return getTlds()
if (refersToKey(Registry.get(tld), key)) { .stream()
builder.add(tld); .filter((tld) -> refersToKey(Registry.get(tld), key))
} .collect(toImmutableSet());
}
return builder.build();
} }
protected abstract boolean refersToKey( protected abstract boolean refersToKey(

View file

@ -33,7 +33,6 @@ import com.google.common.cache.LoadingCache;
import com.google.common.hash.BloomFilter; import com.google.common.hash.BloomFilter;
import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.common.util.concurrent.UncheckedExecutionException;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
import com.googlecode.objectify.Work;
import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Parent; import com.googlecode.objectify.annotation.Parent;
@ -113,13 +112,12 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
// encoding on them. // encoding on them.
revision.probablePremiumLabels = revision.probablePremiumLabels =
BloomFilter.create(unencodedCharsFunnel(), premiumLabels.size()); BloomFilter.create(unencodedCharsFunnel(), premiumLabels.size());
for (String label : premiumLabels) { premiumLabels.forEach(revision.probablePremiumLabels::put);
revision.probablePremiumLabels.put(label);
}
try { try {
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
revision.probablePremiumLabels.writeTo(bos); revision.probablePremiumLabels.writeTo(bos);
checkArgument(bos.size() <= MAX_BLOOM_FILTER_BYTES, checkArgument(
bos.size() <= MAX_BLOOM_FILTER_BYTES,
"Too many premium labels were specified; Bloom filter exceeds max entity size"); "Too many premium labels were specified; Bloom filter exceeds max entity size");
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException("Could not serialize premium labels Bloom filter", e); throw new IllegalStateException("Could not serialize premium labels Bloom filter", e);
@ -137,26 +135,28 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
static final LoadingCache<String, PremiumList> cachePremiumLists = static final LoadingCache<String, PremiumList> cachePremiumLists =
CacheBuilder.newBuilder() CacheBuilder.newBuilder()
.expireAfterWrite(getDomainLabelListCacheDuration().getMillis(), MILLISECONDS) .expireAfterWrite(getDomainLabelListCacheDuration().getMillis(), MILLISECONDS)
.build(new CacheLoader<String, PremiumList>() { .build(
new CacheLoader<String, PremiumList>() {
@Override @Override
public PremiumList load(final String listName) { public PremiumList load(final String listName) {
return ofy().doTransactionless(new Work<PremiumList>() { return ofy()
@Override .doTransactionless(
public PremiumList run() { () ->
return ofy().load() ofy()
.load()
.type(PremiumList.class) .type(PremiumList.class)
.parent(getCrossTldKey()) .parent(getCrossTldKey())
.id(listName) .id(listName)
.now(); .now());
}}); }
}}); });
/** /**
* In-memory cache for {@link PremiumListRevision}s, used for retrieving Bloom filters quickly. * In-memory cache for {@link PremiumListRevision}s, used for retrieving Bloom filters quickly.
* *
* <p>This is cached for a long duration (essentially indefinitely) because a given * <p>This is cached for a long duration (essentially indefinitely) because a given {@link
* {@link PremiumListRevision} is immutable and cannot ever be changed once created, so its cache * PremiumListRevision} is immutable and cannot ever be changed once created, so its cache need
* need not ever expire. * not ever expire.
*/ */
static final LoadingCache<Key<PremiumListRevision>, PremiumListRevision> static final LoadingCache<Key<PremiumListRevision>, PremiumListRevision>
cachePremiumListRevisions = cachePremiumListRevisions =
@ -166,14 +166,9 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
new CacheLoader<Key<PremiumListRevision>, PremiumListRevision>() { new CacheLoader<Key<PremiumListRevision>, PremiumListRevision>() {
@Override @Override
public PremiumListRevision load(final Key<PremiumListRevision> revisionKey) { public PremiumListRevision load(final Key<PremiumListRevision> revisionKey) {
return ofy() return ofy().doTransactionless(() -> ofy().load().key(revisionKey).now());
.doTransactionless( }
new Work<PremiumListRevision>() { });
@Override
public PremiumListRevision run() {
return ofy().load().key(revisionKey).now();
}});
}});
/** /**
* In-memory cache for {@link PremiumListEntry}s for a given label and {@link PremiumListRevision} * In-memory cache for {@link PremiumListEntry}s for a given label and {@link PremiumListRevision}
@ -206,10 +201,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
@Override @Override
public Optional<PremiumListEntry> load(final Key<PremiumListEntry> entryKey) { public Optional<PremiumListEntry> load(final Key<PremiumListEntry> entryKey) {
return ofy() return ofy()
.doTransactionless( .doTransactionless(() -> Optional.ofNullable(ofy().load().key(entryKey).now()));
() -> {
return Optional.ofNullable(ofy().load().key(entryKey).now());
});
} }
}); });
} }

View file

@ -36,6 +36,7 @@ import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.net.InternetDomainName; import com.google.common.net.InternetDomainName;
import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.common.util.concurrent.UncheckedExecutionException;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
@ -45,7 +46,6 @@ import com.googlecode.objectify.annotation.Mapify;
import com.googlecode.objectify.mapper.Mapper; import com.googlecode.objectify.mapper.Mapper;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.model.registry.label.DomainLabelMetrics.MetricsReservedListMatch; import google.registry.model.registry.label.DomainLabelMetrics.MetricsReservedListMatch;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -96,6 +96,7 @@ public final class ReservedList
/** Mapper for use with @Mapify */ /** Mapper for use with @Mapify */
static class LabelMapper implements Mapper<String, ReservedListEntry> { static class LabelMapper implements Mapper<String, ReservedListEntry> {
@Override @Override
public String getKey(ReservedListEntry entry) { public String getKey(ReservedListEntry entry) {
return entry.getLabel(); return entry.getLabel();
@ -130,7 +131,8 @@ public final class ReservedList
entry.allowedNameservers = Joiner.on(',').join(allowedNameservers); entry.allowedNameservers = Joiner.on(',').join(allowedNameservers);
} }
} else { } else {
checkArgument(reservationType != RESERVED_FOR_ANCHOR_TENANT, checkArgument(
reservationType != RESERVED_FOR_ANCHOR_TENANT,
"Anchor tenant reservations must have an auth code configured"); "Anchor tenant reservations must have an auth code configured");
checkArgument( checkArgument(
reservationType != NAMESERVER_RESTRICTED, reservationType != NAMESERVER_RESTRICTED,
@ -143,13 +145,13 @@ public final class ReservedList
} }
private static void checkNameserversAreValid(Set<String> nameservers) { private static void checkNameserversAreValid(Set<String> nameservers) {
for (String nameserver : nameservers) {
// A domain name with fewer than two parts cannot be a hostname, as a nameserver should be. // A domain name with fewer than two parts cannot be a hostname, as a nameserver should be.
nameservers.forEach(
(ns) ->
checkArgument( checkArgument(
InternetDomainName.from(nameserver).parts().size() >= 3, InternetDomainName.from(ns).parts().size() >= 3,
"%s is not a valid nameserver hostname", "%s is not a valid nameserver hostname",
nameserver); ns));
}
} }
@Override @Override
@ -218,7 +220,7 @@ public final class ReservedList
} }
return getReservedListEntries(label, tld) return getReservedListEntries(label, tld)
.stream() .stream()
.map((ReservedListEntry reservedListEntry) -> reservedListEntry.reservationType) .map(ReservedListEntry::getValue)
.collect(toImmutableSet()); .collect(toImmutableSet());
} }
@ -230,15 +232,13 @@ public final class ReservedList
*/ */
public static boolean matchesAnchorTenantReservation( public static boolean matchesAnchorTenantReservation(
InternetDomainName domainName, String authCode) { InternetDomainName domainName, String authCode) {
ImmutableSet<ReservedListEntry> entries =
getReservedListEntries(domainName.parts().get(0), domainName.parent().toString());
Set<String> domainAuthCodes = new HashSet<>(); ImmutableSet<String> domainAuthCodes =
for (ReservedListEntry entry : entries) { getReservedListEntries(domainName.parts().get(0), domainName.parent().toString())
if (entry.reservationType == RESERVED_FOR_ANCHOR_TENANT) { .stream()
domainAuthCodes.add(entry.getAuthCode()); .filter((entry) -> entry.reservationType == RESERVED_FOR_ANCHOR_TENANT)
} .map(ReservedListEntry::getAuthCode)
} .collect(toImmutableSet());
checkState( checkState(
domainAuthCodes.size() <= 1, "There are conflicting auth codes for domain: %s", domainName); domainAuthCodes.size() <= 1, "There are conflicting auth codes for domain: %s", domainName);
@ -253,22 +253,13 @@ public final class ReservedList
* domain is not set with {@code NAMESERVER_RESTRICTED} reservation type. * domain is not set with {@code NAMESERVER_RESTRICTED} reservation type.
*/ */
public static ImmutableSet<String> getAllowedNameservers(InternetDomainName domainName) { public static ImmutableSet<String> getAllowedNameservers(InternetDomainName domainName) {
HashSet<String> allowedNameservers = new HashSet<>(); return getReservedListEntries(domainName.parts().get(0), domainName.parent().toString())
boolean foundFirstNameserverRestricted = false; .stream()
for (ReservedListEntry entry : .filter((entry) -> entry.reservationType == NAMESERVER_RESTRICTED)
getReservedListEntries(domainName.parts().get(0), domainName.parent().toString())) { .map(ReservedListEntry::getAllowedNameservers)
if (entry.reservationType == NAMESERVER_RESTRICTED) { .reduce((types1, types2) -> Sets.intersection(types1, types2).immutableCopy())
if (foundFirstNameserverRestricted) { .orElse(ImmutableSet.of());
allowedNameservers.retainAll(entry.getAllowedNameservers());
} else {
allowedNameservers = new HashSet<String>(entry.getAllowedNameservers());
foundFirstNameserverRestricted = true;
} }
}
}
return ImmutableSet.copyOf(allowedNameservers);
}
/** /**
* Helper function to retrieve the entries associated with this label and TLD, or an empty set if * Helper function to retrieve the entries associated with this label and TLD, or an empty set if
@ -276,15 +267,13 @@ public final class ReservedList
*/ */
private static ImmutableSet<ReservedListEntry> getReservedListEntries(String label, String tld) { private static ImmutableSet<ReservedListEntry> getReservedListEntries(String label, String tld) {
DateTime startTime = DateTime.now(UTC); DateTime startTime = DateTime.now(UTC);
Registry registry = Registry.get(checkNotNull(tld, "tld")); Registry registry = Registry.get(checkNotNull(tld, "tld must not be null"));
ImmutableSet<Key<ReservedList>> reservedLists = registry.getReservedLists();
ImmutableSet<ReservedList> lists = loadReservedLists(reservedLists);
ImmutableSet.Builder<ReservedListEntry> entriesBuilder = new ImmutableSet.Builder<>(); ImmutableSet.Builder<ReservedListEntry> entriesBuilder = new ImmutableSet.Builder<>();
ImmutableSet.Builder<MetricsReservedListMatch> metricMatchesBuilder = ImmutableSet.Builder<MetricsReservedListMatch> metricMatchesBuilder =
new ImmutableSet.Builder<>(); new ImmutableSet.Builder<>();
// Loop through all reservation lists and add each of them. // Loop through all reservation lists and add each of them.
for (ReservedList rl : lists) { for (ReservedList rl : loadReservedLists(registry.getReservedLists())) {
if (rl.getReservedListEntries().containsKey(label)) { if (rl.getReservedListEntries().containsKey(label)) {
ReservedListEntry entry = rl.getReservedListEntries().get(label); ReservedListEntry entry = rl.getReservedListEntries().get(label);
entriesBuilder.add(entry); entriesBuilder.add(entry);
@ -300,17 +289,20 @@ public final class ReservedList
private static ImmutableSet<ReservedList> loadReservedLists( private static ImmutableSet<ReservedList> loadReservedLists(
ImmutableSet<Key<ReservedList>> reservedListKeys) { ImmutableSet<Key<ReservedList>> reservedListKeys) {
ImmutableSet.Builder<ReservedList> builder = new ImmutableSet.Builder<>(); return reservedListKeys
for (Key<ReservedList> listKey : reservedListKeys) { .stream()
.map(
(listKey) -> {
try { try {
builder.add(cache.get(listKey.getName())); return cache.get(listKey.getName());
} catch (ExecutionException e) { } catch (ExecutionException e) {
throw new UncheckedExecutionException(String.format( throw new UncheckedExecutionException(
"Could not load the reserved list '%s' from the cache", listKey.getName()), e); String.format(
"Could not load the reserved list '%s' from the cache", listKey.getName()),
e);
} }
} })
.collect(toImmutableSet());
return builder.build();
} }
private static LoadingCache<String, ReservedList> cache = private static LoadingCache<String, ReservedList> cache =

View file

@ -16,18 +16,14 @@ package google.registry.model.registry.label;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.Truth8.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistPremiumList; import static google.registry.testing.DatastoreHelper.persistPremiumList;
import static google.registry.testing.DatastoreHelper.persistReservedList; import static google.registry.testing.DatastoreHelper.persistReservedList;
import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.testing.DatastoreHelper.persistResource;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.googlecode.objectify.Key;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.model.registry.label.PremiumList.PremiumListEntry;
import google.registry.model.registry.label.PremiumList.PremiumListRevision; import google.registry.model.registry.label.PremiumList.PremiumListRevision;
import google.registry.testing.AppEngineRule; import google.registry.testing.AppEngineRule;
import google.registry.testing.ExceptionRule; import google.registry.testing.ExceptionRule;
@ -93,8 +89,4 @@ public class PremiumListTest {
ImmutableList.of( ImmutableList.of(
"lol,USD 100", "rofl,USD 90", "paper,USD 80", "wood,USD 70", "lol,USD 200")); "lol,USD 100", "rofl,USD 90", "paper,USD 80", "wood,USD 70", "lol,USD 200"));
} }
/** Gets the label of a premium list entry. */
public static final Function<Key<PremiumListEntry>, String> GET_ENTRY_NAME_FUNCTION =
Key::getName;
} }