diff --git a/core/build.gradle b/core/build.gradle
index 7041faf21..e1bd92714 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -163,11 +163,6 @@ configurations {
dependencies {
def deps = rootProject.dependencyMap
- // Custom-built objectify jar at commit ecd5165, included in Nomulus
- // release.
- implementation files(
- "${rootDir}/third_party/objectify/v4_1/objectify-4.1.3.jar")
-
testRuntimeOnly files(sourceSets.test.resources.srcDirs)
implementation deps['com.beust:jcommander']
diff --git a/core/src/main/java/google/registry/beam/common/RegistryPipelineWorkerInitializer.java b/core/src/main/java/google/registry/beam/common/RegistryPipelineWorkerInitializer.java
index baaa861c1..0f849aa42 100644
--- a/core/src/main/java/google/registry/beam/common/RegistryPipelineWorkerInitializer.java
+++ b/core/src/main/java/google/registry/beam/common/RegistryPipelineWorkerInitializer.java
@@ -21,7 +21,6 @@ import com.google.common.flogger.FluentLogger;
import dagger.Lazy;
import google.registry.config.RegistryEnvironment;
import google.registry.config.SystemPropertySetter;
-import google.registry.model.AppEngineEnvironment;
import google.registry.model.IdService;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.persistence.transaction.TransactionManagerFactory;
@@ -63,10 +62,6 @@ public class RegistryPipelineWorkerInitializer implements JvmInitializer {
transactionManagerLazy = registryPipelineComponent.getJpaTransactionManager();
}
TransactionManagerFactory.setJpaTmOnBeamWorker(transactionManagerLazy::get);
- // Masquerade all threads as App Engine threads, so we can create Ofy keys in the pipeline. Also
- // loads all ofy entities.
- new AppEngineEnvironment("s~" + registryPipelineComponent.getProjectId())
- .setEnvironmentForAllThreads();
SystemPropertySetter.PRODUCTION_IMPL.setProperty(PROPERTY, "true");
// Use self-allocated IDs if requested. Note that this inevitably results in duplicate IDs from
// multiple workers, which can also collide with existing IDs in the database. So they cannot be
diff --git a/core/src/main/java/google/registry/env/common/backend/WEB-INF/web.xml b/core/src/main/java/google/registry/env/common/backend/WEB-INF/web.xml
index 573a57d06..a13a5b795 100644
--- a/core/src/main/java/google/registry/env/common/backend/WEB-INF/web.xml
+++ b/core/src/main/java/google/registry/env/common/backend/WEB-INF/web.xml
@@ -341,24 +341,4 @@ have been in the database for a certain period of time. -->
CONFIDENTIAL
-
-
-
- ObjectifyFilter
- com.googlecode.objectify.ObjectifyFilter
-
-
- ObjectifyFilter
- /*
-
-
-
-
- OfyFilter
- google.registry.model.ofy.OfyFilter
-
-
- OfyFilter
- /*
-
diff --git a/core/src/main/java/google/registry/env/common/default/WEB-INF/web.xml b/core/src/main/java/google/registry/env/common/default/WEB-INF/web.xml
index 175dc53c5..d76ab31b0 100644
--- a/core/src/main/java/google/registry/env/common/default/WEB-INF/web.xml
+++ b/core/src/main/java/google/registry/env/common/default/WEB-INF/web.xml
@@ -139,24 +139,4 @@
CONFIDENTIAL
-
-
-
- ObjectifyFilter
- com.googlecode.objectify.ObjectifyFilter
-
-
- ObjectifyFilter
- /*
-
-
-
-
- OfyFilter
- google.registry.model.ofy.OfyFilter
-
-
- OfyFilter
- /*
-
diff --git a/core/src/main/java/google/registry/env/common/pubapi/WEB-INF/web.xml b/core/src/main/java/google/registry/env/common/pubapi/WEB-INF/web.xml
index 2cd19223d..24f2fd6a5 100644
--- a/core/src/main/java/google/registry/env/common/pubapi/WEB-INF/web.xml
+++ b/core/src/main/java/google/registry/env/common/pubapi/WEB-INF/web.xml
@@ -105,24 +105,4 @@
CONFIDENTIAL
-
-
-
- ObjectifyFilter
- com.googlecode.objectify.ObjectifyFilter
-
-
- ObjectifyFilter
- /*
-
-
-
-
- OfyFilter
- google.registry.model.ofy.OfyFilter
-
-
- OfyFilter
- /*
-
diff --git a/core/src/main/java/google/registry/env/common/tools/WEB-INF/web.xml b/core/src/main/java/google/registry/env/common/tools/WEB-INF/web.xml
index c8d46ed83..a305d6674 100644
--- a/core/src/main/java/google/registry/env/common/tools/WEB-INF/web.xml
+++ b/core/src/main/java/google/registry/env/common/tools/WEB-INF/web.xml
@@ -135,24 +135,4 @@
CONFIDENTIAL
-
-
-
- ObjectifyFilter
- com.googlecode.objectify.ObjectifyFilter
-
-
- ObjectifyFilter
- /*
-
-
-
-
- OfyFilter
- google.registry.model.ofy.OfyFilter
-
-
- OfyFilter
- /*
-
diff --git a/core/src/main/java/google/registry/model/AppEngineEnvironment.java b/core/src/main/java/google/registry/model/AppEngineEnvironment.java
deleted file mode 100644
index 80f2942d2..000000000
--- a/core/src/main/java/google/registry/model/AppEngineEnvironment.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2020 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.model;
-
-import com.google.apphosting.api.ApiProxy;
-import com.google.apphosting.api.ApiProxy.Environment;
-import com.google.common.collect.ImmutableMap;
-import google.registry.model.annotations.DeleteAfterMigration;
-import google.registry.model.ofy.ObjectifyService;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-/**
- * Sets up a fake {@link Environment} so that the following operations can be performed without the
- * Datastore service:
- *
- *
- * - Create Objectify {@code Keys}.
- *
- Instantiate Objectify objects.
- *
- Convert Datastore {@code Entities} to their corresponding Objectify objects.
- *
- *
- * User has the option to specify their desired {@code appId} string, which forms part of an
- * Objectify {@code Key} and is included in the equality check. This feature makes it easy to
- * compare a migrated object in SQL with the original in Objectify.
- *
- *
Note that conversion from Objectify objects to Datastore {@code Entities} still requires the
- * Datastore service.
- */
-@DeleteAfterMigration
-public class AppEngineEnvironment {
-
- private Environment environment;
-
- /**
- * Constructor for use by tests.
- *
- *
All test suites must use the same appId for environments, since when tearing down we do not
- * clear cached environments in spawned threads. See {@link #unsetEnvironmentForAllThreads} for
- * more information.
- */
- public AppEngineEnvironment() {
- /**
- * Use AppEngineExtension's appId here so that ofy and sql entities can be compared with {@code
- * Objects#equals()}. The choice of this value does not impact functional correctness.
- */
- this("test");
- }
-
- /** Constructor for use by applications, e.g., BEAM pipelines. */
- public AppEngineEnvironment(String appId) {
- environment = createAppEngineEnvironment(appId);
- }
-
- public void setEnvironmentForCurrentThread() {
- ApiProxy.setEnvironmentForCurrentThread(environment);
- ObjectifyService.initOfy();
- }
-
- public void setEnvironmentForAllThreads() {
- setEnvironmentForCurrentThread();
- ApiProxy.setEnvironmentFactory(() -> environment);
- }
-
- public void unsetEnvironmentForCurrentThread() {
- ApiProxy.clearEnvironmentForCurrentThread();
- }
-
- /**
- * Unsets the test environment in all threads with best effort.
- *
- *
This method unsets the environment factory and clears the cached environment in the current
- * thread (the main test runner thread). We do not clear the cache in spawned threads, even though
- * they may be reused. This is not a problem as long as the appId stays the same: those threads
- * are used only in AppEngine or BEAM tests, and expect the presence of an environment.
- */
- public void unsetEnvironmentForAllThreads() {
- unsetEnvironmentForCurrentThread();
-
- try {
- Method method = ApiProxy.class.getDeclaredMethod("clearEnvironmentFactory");
- method.setAccessible(true);
- method.invoke(null);
- } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Returns a placeholder {@link Environment} that can return hardcoded AppId and Attributes. */
- private static Environment createAppEngineEnvironment(String appId) {
- return (Environment)
- Proxy.newProxyInstance(
- Environment.class.getClassLoader(),
- new Class[] {Environment.class},
- (Object proxy, Method method, Object[] args) -> {
- switch (method.getName()) {
- case "getAppId":
- return appId;
- case "getAttributes":
- return ImmutableMap.of();
- default:
- throw new UnsupportedOperationException(method.getName());
- }
- });
- }
-
- /** Returns true if the current thread is in an App Engine Environment. */
- public static boolean isInAppEngineEnvironment() {
- return ApiProxy.getCurrentEnvironment() != null;
- }
-}
diff --git a/core/src/main/java/google/registry/model/CacheUtils.java b/core/src/main/java/google/registry/model/CacheUtils.java
index 37519c3ad..567b2524f 100644
--- a/core/src/main/java/google/registry/model/CacheUtils.java
+++ b/core/src/main/java/google/registry/model/CacheUtils.java
@@ -18,13 +18,9 @@ import static com.google.common.base.Suppliers.memoizeWithExpiration;
import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.base.Supplier;
-import google.registry.model.annotations.DeleteAfterMigration;
import java.time.Duration;
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.checkerframework.checker.nullness.qual.Nullable;
/** Utility methods related to caching Datastore entities. */
public class CacheUtils {
@@ -77,29 +73,4 @@ public class CacheUtils {
}
return caffeine;
}
-
- /**
- * A {@link CacheLoader} that automatically masquerade the background thread where the refresh
- * action runs in to be an GAE thread.
- */
- @DeleteAfterMigration
- public abstract static class AppEngineEnvironmentCacheLoader implements CacheLoader {
-
- private static final AppEngineEnvironment environment = new AppEngineEnvironment();
-
- @Override
- public @Nullable V reload(@NonNull K key, @NonNull V oldValue) throws Exception {
- V value;
- boolean isMasqueraded = false;
- if (!AppEngineEnvironment.isInAppEngineEnvironment()) {
- environment.setEnvironmentForCurrentThread();
- isMasqueraded = true;
- }
- value = load(key);
- if (isMasqueraded) {
- environment.unsetEnvironmentForCurrentThread();
- }
- return value;
- }
- }
}
diff --git a/core/src/main/java/google/registry/model/EppResource.java b/core/src/main/java/google/registry/model/EppResource.java
index 60d6c0aa1..b325ca73d 100644
--- a/core/src/main/java/google/registry/model/EppResource.java
+++ b/core/src/main/java/google/registry/model/EppResource.java
@@ -32,7 +32,6 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import google.registry.config.RegistryConfig;
-import google.registry.model.CacheUtils.AppEngineEnvironmentCacheLoader;
import google.registry.model.annotations.IdAllocation;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.transfer.TransferData;
@@ -354,7 +353,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
}
static final CacheLoader, EppResource> CACHE_LOADER =
- new AppEngineEnvironmentCacheLoader, EppResource>() {
+ new CacheLoader, EppResource>() {
@Override
public EppResource load(VKey extends EppResource> key) {
diff --git a/core/src/main/java/google/registry/model/IdService.java b/core/src/main/java/google/registry/model/IdService.java
index a375d89fc..02f4007c0 100644
--- a/core/src/main/java/google/registry/model/IdService.java
+++ b/core/src/main/java/google/registry/model/IdService.java
@@ -22,7 +22,6 @@ import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.common.flogger.FluentLogger;
import google.registry.beam.common.RegistryPipelineWorkerInitializer;
import google.registry.config.RegistryEnvironment;
-import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.common.DatabaseMigrationStateSchedule;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
import java.math.BigInteger;
@@ -33,7 +32,6 @@ import org.joda.time.DateTime;
/**
* Allocates a {@link long} to use as a {@code @Id}, (part) of the primary SQL key for an entity.
*/
-@DeleteAfterMigration
public final class IdService {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
diff --git a/core/src/main/java/google/registry/model/annotations/NotBackedUp.java b/core/src/main/java/google/registry/model/annotations/NotBackedUp.java
deleted file mode 100644
index 68346284e..000000000
--- a/core/src/main/java/google/registry/model/annotations/NotBackedUp.java
+++ /dev/null
@@ -1,47 +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.model.annotations;
-
-import com.googlecode.objectify.annotation.Entity;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for an Objectify {@link Entity} to indicate that it should not be backed up by the
- * default Datastore backup configuration (it may be backed up by something else).
- */
-@DeleteAfterMigration
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface NotBackedUp {
- Reason reason();
-
- /** Reasons why a given entity does not need to be be backed up. */
- enum Reason {
- /** This entity is transient by design and has only a short-term useful lifetime. */
- TRANSIENT,
-
- /** This entity's data is already regularly pulled down from an external source. */
- EXTERNALLY_SOURCED,
-
- /** This entity is generated automatically by the app and will be recreated if need be. */
- AUTO_GENERATED,
-
- /** Commit log entities are exported separately from the regular backups, by design. */
- COMMIT_LOGS
- }
-}
diff --git a/core/src/main/java/google/registry/model/annotations/VirtualEntity.java b/core/src/main/java/google/registry/model/annotations/VirtualEntity.java
deleted file mode 100644
index 46e89c8b8..000000000
--- a/core/src/main/java/google/registry/model/annotations/VirtualEntity.java
+++ /dev/null
@@ -1,32 +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.model.annotations;
-
-import com.googlecode.objectify.annotation.Entity;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for an Objectify {@link Entity} to indicate that it is a "virtual entity".
- *
- * A virtual entity type exists only to define part of the parentage key hierarchy for its child
- * entities, and is never actually persisted and thus has no fields besides its ID field.
- */
-@DeleteAfterMigration
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface VirtualEntity {}
diff --git a/core/src/main/java/google/registry/model/common/GaeUserIdConverter.java b/core/src/main/java/google/registry/model/common/GaeUserIdConverter.java
deleted file mode 100644
index dcff7ebb7..000000000
--- a/core/src/main/java/google/registry/model/common/GaeUserIdConverter.java
+++ /dev/null
@@ -1,73 +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.model.common;
-
-import static com.google.common.base.Preconditions.checkState;
-import static google.registry.model.IdService.allocateId;
-import static google.registry.model.ofy.ObjectifyService.auditedOfy;
-
-import com.google.appengine.api.users.User;
-import com.google.common.base.Splitter;
-import com.googlecode.objectify.annotation.Entity;
-import com.googlecode.objectify.annotation.Id;
-import google.registry.model.ImmutableObject;
-import google.registry.model.annotations.NotBackedUp;
-import google.registry.model.annotations.NotBackedUp.Reason;
-import java.util.List;
-
-/**
- * A helper class to convert email addresses to GAE user ids. It does so by persisting a User
- * object with the email address to Datastore, and then immediately reading it back.
- */
-@Entity
-@NotBackedUp(reason = Reason.TRANSIENT)
-public class GaeUserIdConverter extends ImmutableObject {
-
- @Id
- public long id;
-
- User user;
-
- /**
- * Converts an email address to a GAE user id.
- *
- * @return Numeric GAE user id (in String form), or null if email address has no GAE id
- */
- public static String convertEmailAddressToGaeUserId(String emailAddress) {
- final GaeUserIdConverter gaeUserIdConverter = new GaeUserIdConverter();
- gaeUserIdConverter.id = allocateId();
- List emailParts = Splitter.on('@').splitToList(emailAddress);
- checkState(emailParts.size() == 2, "'%s' is not a valid email address", emailAddress);
- gaeUserIdConverter.user = new User(emailAddress, emailParts.get(1));
-
- try {
- // Perform these operations in a transactionless context to avoid enlisting in some outer
- // transaction (if any).
- auditedOfy()
- .doTransactionless(
- () -> {
- auditedOfy().saveWithoutBackup().entity(gaeUserIdConverter).now();
- return null;
- });
- // The read must be done in its own transaction to avoid reading from the session cache.
- return auditedOfy()
- .transactNew(() -> auditedOfy().load().entity(gaeUserIdConverter).now().user.getUserId());
- } finally {
- auditedOfy()
- .doTransactionless(
- () -> auditedOfy().deleteWithoutBackup().entity(gaeUserIdConverter).now());
- }
- }
-}
diff --git a/core/src/main/java/google/registry/model/ofy/AugmentedDeleter.java b/core/src/main/java/google/registry/model/ofy/AugmentedDeleter.java
deleted file mode 100644
index 94a6c33a9..000000000
--- a/core/src/main/java/google/registry/model/ofy/AugmentedDeleter.java
+++ /dev/null
@@ -1,90 +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.model.ofy;
-
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.googlecode.objectify.ObjectifyService.ofy;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Streams;
-import com.googlecode.objectify.Key;
-import com.googlecode.objectify.Result;
-import com.googlecode.objectify.cmd.DeleteType;
-import com.googlecode.objectify.cmd.Deleter;
-import google.registry.model.annotations.DeleteAfterMigration;
-import java.util.Arrays;
-import java.util.stream.Stream;
-
-/**
- * A Deleter that forwards to {@code auditedOfy().delete()}, but can be augmented via subclassing to
- * do custom processing on the keys to be deleted prior to their deletion.
- */
-@DeleteAfterMigration
-abstract class AugmentedDeleter implements Deleter {
- private final Deleter delegate = ofy().delete();
-
- /** Extension method to allow this Deleter to do extra work prior to the actual delete. */
- protected abstract void handleDeletion(Iterable> keys);
-
- private void handleDeletionStream(Stream> entityStream) {
- handleDeletion(entityStream.map(Key::create).collect(toImmutableList()));
- }
-
- @Override
- public Result entities(Iterable> entities) {
- handleDeletionStream(Streams.stream(entities));
- return delegate.entities(entities);
- }
-
- @Override
- public Result entities(Object... entities) {
- handleDeletionStream(Arrays.stream(entities));
- return delegate.entities(entities);
- }
-
- @Override
- public Result entity(Object entity) {
- handleDeletionStream(Stream.of(entity));
- return delegate.entity(entity);
- }
-
- @Override
- public Result key(Key> key) {
- handleDeletion(ImmutableList.of(key));
- return delegate.keys(key);
- }
-
- @Override
- public Result keys(Iterable extends Key>> keys) {
- // Magic to convert the type Iterable extends Key>> (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).
- handleDeletion(ImmutableList.copyOf(keys));
- return delegate.keys(keys);
- }
-
- @Override
- public Result keys(Key>... keys) {
- handleDeletion(Arrays.asList(keys));
- return delegate.keys(keys);
- }
-
- /** Augmenting this gets ugly; you can always just use keys(Key.create(...)) instead. */
- @Override
- public DeleteType type(Class> clazz) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/core/src/main/java/google/registry/model/ofy/AugmentedSaver.java b/core/src/main/java/google/registry/model/ofy/AugmentedSaver.java
deleted file mode 100644
index 9896572c0..000000000
--- a/core/src/main/java/google/registry/model/ofy/AugmentedSaver.java
+++ /dev/null
@@ -1,63 +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.model.ofy;
-
-import static com.googlecode.objectify.ObjectifyService.ofy;
-
-import com.google.appengine.api.datastore.Entity;
-import com.google.common.collect.ImmutableList;
-import com.googlecode.objectify.Key;
-import com.googlecode.objectify.Result;
-import com.googlecode.objectify.cmd.Saver;
-import google.registry.model.annotations.DeleteAfterMigration;
-import java.util.Arrays;
-import java.util.Map;
-
-/**
- * A Saver that forwards to {@code ofy().save()}, but can be augmented via subclassing to do custom
- * processing on the entities to be saved prior to their saving.
- */
-@DeleteAfterMigration
-abstract class AugmentedSaver implements Saver {
- private final Saver delegate = ofy().save();
-
- /** Extension method to allow this Saver to do extra work prior to the actual save. */
- protected abstract void handleSave(Iterable> entities);
-
- @Override
- public Result