diff --git a/java/google/registry/tools/CommandUtilities.java b/java/google/registry/tools/CommandUtilities.java index 3e4652de2..e3a2ef738 100644 --- a/java/google/registry/tools/CommandUtilities.java +++ b/java/google/registry/tools/CommandUtilities.java @@ -16,10 +16,39 @@ package google.registry.tools; import com.google.common.base.Ascii; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import com.googlecode.objectify.Key; +import google.registry.model.EppResource; +import google.registry.model.contact.ContactResource; +import google.registry.model.domain.DomainApplication; +import google.registry.model.domain.DomainResource; +import google.registry.model.host.HostResource; +import google.registry.model.index.ForeignKeyIndex; +import org.joda.time.DateTime; /** Container class for static utility methods. */ class CommandUtilities { + /** A useful parameter enum for commands that operate on {@link EppResource} objects. */ + public enum ResourceType { + CONTACT, + HOST, + DOMAIN, + APPLICATION; + + public Key getKey(String uniqueId, DateTime now) { + return this == APPLICATION + ? Key.create(DomainApplication.class, uniqueId) + : ForeignKeyIndex.loadAndGetKey( + ImmutableMap.of( + CONTACT, ContactResource.class, + HOST, HostResource.class, + DOMAIN, DomainResource.class).get(this), + uniqueId, + now); + } + } + static String addHeader(String header, String body) { return String.format("%s:\n%s\n%s", header, Strings.repeat("-", header.length() + 1), body); } diff --git a/java/google/registry/tools/GetHistoryEntriesCommand.java b/java/google/registry/tools/GetHistoryEntriesCommand.java index eebcbda80..9dd3186fc 100644 --- a/java/google/registry/tools/GetHistoryEntriesCommand.java +++ b/java/google/registry/tools/GetHistoryEntriesCommand.java @@ -14,14 +14,19 @@ package google.registry.tools; +import static com.google.common.base.Preconditions.checkArgument; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.START_OF_TIME; +import static org.joda.time.DateTimeZone.UTC; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; +import com.googlecode.objectify.Key; +import google.registry.model.EppResource; import google.registry.model.reporting.HistoryEntry; import google.registry.tools.Command.RemoteApiCommand; +import google.registry.tools.CommandUtilities.ResourceType; import google.registry.xml.XmlTransformer; import org.joda.time.DateTime; @@ -40,9 +45,29 @@ final class GetHistoryEntriesCommand implements RemoteApiCommand { description = "Only show history entries that occurred at or before this time") private DateTime before = END_OF_TIME; + @Parameter( + names = "--type", + description = "Resource type.") + private ResourceType type; + + @Parameter( + names = "--id", + description = "Foreign key of the resource, or application ID of the domain application.") + private String uniqueId; + @Override public void run() { - for (HistoryEntry entry : ofy().load().type(HistoryEntry.class) + Key parentKey = null; + if (type != null || uniqueId != null) { + checkArgument( + type != null && uniqueId != null, + "If either of 'type' or 'id' are set then both must be"); + parentKey = type.getKey(uniqueId, DateTime.now(UTC)); + } + for (HistoryEntry entry : + (parentKey == null + ? ofy().load().type(HistoryEntry.class) + : ofy().load().type(HistoryEntry.class).ancestor(parentKey)) .order("modificationTime") .filter("modificationTime >=", after) .filter("modificationTime <=", before)) { diff --git a/java/google/registry/tools/ResaveEppResourceCommand.java b/java/google/registry/tools/ResaveEppResourceCommand.java index b5562130d..a838e6257 100644 --- a/java/google/registry/tools/ResaveEppResourceCommand.java +++ b/java/google/registry/tools/ResaveEppResourceCommand.java @@ -14,7 +14,6 @@ package google.registry.tools; -import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static org.joda.time.DateTimeZone.UTC; @@ -23,10 +22,7 @@ import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import com.googlecode.objectify.Key; import google.registry.model.EppResource; -import google.registry.model.contact.ContactResource; -import google.registry.model.domain.DomainApplication; -import google.registry.model.domain.DomainResource; -import google.registry.model.host.HostResource; +import google.registry.tools.CommandUtilities.ResourceType; import org.joda.time.DateTime; /** @@ -40,8 +36,6 @@ import org.joda.time.DateTime; commandDescription = "Load and resave EPP resources by foreign key") public final class ResaveEppResourceCommand extends MutatingCommand { - private enum ResourceType { CONTACT, HOST, DOMAIN, APPLICATION } - @Parameter( names = "--type", description = "Resource type.") @@ -55,27 +49,11 @@ public final class ResaveEppResourceCommand extends MutatingCommand { @Override protected void init() throws Exception { Key resourceKey = checkArgumentNotNull( - getResourceKey(type, uniqueId, DateTime.now(UTC)), + type.getKey(uniqueId, DateTime.now(UTC)), "Could not find active resource of type %s: %s", type, uniqueId); // Load the resource directly to bypass running cloneProjectedAtTime() automatically, which can // cause stageEntityChange() to fail due to implicit projection changes. EppResource resource = ofy().load().key(resourceKey).now(); stageEntityChange(resource, resource); } - - private Key getResourceKey( - ResourceType type, String uniqueId, DateTime now) { - switch (type) { - case CONTACT: - return loadAndGetKey(ContactResource.class, uniqueId, now); - case HOST: - return loadAndGetKey(HostResource.class, uniqueId, now); - case DOMAIN: - return loadAndGetKey(DomainResource.class, uniqueId, now); - case APPLICATION: - return Key.create(DomainApplication.class, uniqueId); - default: - throw new IllegalStateException("Unknown type: " + type); - } - } }