Refactor some RDE import logic to be generic

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=136076610
This commit is contained in:
Wolfgang Meyers 2016-10-13 13:10:24 -07:00 committed by Ben McIlwain
parent 71d7a382f3
commit 94af94ddff
4 changed files with 51 additions and 50 deletions

View file

@ -23,7 +23,6 @@ import com.google.appengine.tools.cloudstorage.GcsService;
import com.google.appengine.tools.cloudstorage.GcsServiceFactory; import com.google.appengine.tools.cloudstorage.GcsServiceFactory;
import com.google.appengine.tools.cloudstorage.RetryParams; import com.google.appengine.tools.cloudstorage.RetryParams;
import com.google.appengine.tools.mapreduce.Mapper; import com.google.appengine.tools.mapreduce.Mapper;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import google.registry.config.ConfigModule; import google.registry.config.ConfigModule;
@ -80,21 +79,15 @@ public class RdeContactImportAction implements Runnable {
/** /**
* Creates a new {@link RdeContactInput} * Creates a new {@link RdeContactInput}
*
* <p>Should be overridden in a subclass for the purposes of unit testing.
*/ */
@VisibleForTesting private RdeContactInput createInput() {
RdeContactInput createInput() {
return new RdeContactInput(mapShards, importBucketName, importFileName); return new RdeContactInput(mapShards, importBucketName, importFileName);
} }
/** /**
* Creates a new {@link RdeContactImportMapper} * Creates a new {@link RdeContactImportMapper}
*
* <p>Should be overridden in a subclass for the purposes of unit testing.
*/ */
@VisibleForTesting private RdeContactImportMapper createMapper() {
RdeContactImportMapper createMapper() {
return new RdeContactImportMapper(importBucketName); return new RdeContactImportMapper(importBucketName);
} }

View file

@ -101,10 +101,8 @@ public class RdeContactInput extends Input<ContactResource> {
/** /**
* Creates a new instance of {@link RdeContactReader} * Creates a new instance of {@link RdeContactReader}
*
* <p>This method can be overridden by a subclass for the purposes of unit testing.
*/ */
protected RdeContactReader newReader(int offset, int maxResults) { private RdeContactReader newReader(int offset, int maxResults) {
return new RdeContactReader(importBucketName, importFileName, offset, maxResults); return new RdeContactReader(importBucketName, importFileName, offset, maxResults);
} }

View file

@ -22,6 +22,7 @@ import com.googlecode.objectify.Key;
import com.googlecode.objectify.Work; import com.googlecode.objectify.Work;
import google.registry.config.ConfigModule.Config; import google.registry.config.ConfigModule.Config;
import google.registry.gcs.GcsUtils; import google.registry.gcs.GcsUtils;
import google.registry.model.EppResource;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.index.EppResourceIndex; import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.ForeignKeyIndex; import google.registry.model.index.ForeignKeyIndex;
@ -60,6 +61,44 @@ public class RdeImportUtils {
this.escrowBucketName = escrowBucketName; this.escrowBucketName = escrowBucketName;
} }
private <T extends EppResource> boolean importEppResource(final T resource, final String type) {
@SuppressWarnings("unchecked")
final Class<T> resourceClass = (Class<T>) resource.getClass();
return ofy.transact(
new Work<Boolean>() {
@Override
public Boolean run() {
EppResource existing = ofy.load().key(Key.create(resource)).now();
if (existing == null) {
ForeignKeyIndex<T> existingForeignKeyIndex =
ForeignKeyIndex.load(
resourceClass, resource.getForeignKey(), clock.nowUtc());
// foreign key index should not exist, since existing resource was not found.
checkState(
existingForeignKeyIndex == null,
"New %s resource has existing foreign key index; foreignKey=%s, repoId=%s",
type,
resource.getForeignKey(),
resource.getRepoId());
ofy.save().entity(resource);
ofy.save().entity(ForeignKeyIndex.create(resource, resource.getDeletionTime()));
ofy.save().entity(EppResourceIndex.create(Key.create(resource)));
logger.infofmt(
"Imported %s resource - ROID=%s, id=%s",
type, resource.getRepoId(), resource.getForeignKey());
return true;
} else if (!existing.getRepoId().equals(resource.getRepoId())) {
logger.warningfmt(
"Existing %s with same id but different ROID. "
+ "id=%s, existing ROID=%s, new ROID=%s",
type, resource.getForeignKey(), existing.getRepoId(), resource.getRepoId());
}
return false;
}
});
}
/**
/** /**
* Imports a contact from an escrow file. * Imports a contact from an escrow file.
* *
@ -71,38 +110,7 @@ public class RdeImportUtils {
* @return true if the contact was created or updated, false otherwise. * @return true if the contact was created or updated, false otherwise.
*/ */
public boolean importContact(final ContactResource resource) { public boolean importContact(final ContactResource resource) {
return ofy.transact( return importEppResource(resource, "contact");
new Work<Boolean>() {
@Override
public Boolean run() {
ContactResource existing = ofy.load().key(Key.create(resource)).now();
if (existing == null) {
ForeignKeyIndex<ContactResource> existingForeignKeyIndex =
ForeignKeyIndex.load(
ContactResource.class, resource.getContactId(), clock.nowUtc());
// foreign key index should not exist, since existing contact was not found.
checkState(
existingForeignKeyIndex == null,
String.format(
"New contact resource has existing foreign key index. "
+ "contactId=%s, repoId=%s",
resource.getContactId(), resource.getRepoId()));
ofy.save().entity(resource);
ofy.save().entity(ForeignKeyIndex.create(resource, resource.getDeletionTime()));
ofy.save().entity(EppResourceIndex.create(Key.create(resource)));
logger.infofmt(
"Imported contact resource - ROID=%s, id=%s",
resource.getRepoId(), resource.getContactId());
return true;
} else if (!existing.getRepoId().equals(resource.getRepoId())) {
logger.warningfmt(
"Existing contact with same contact id but different ROID. "
+ "contactId=%s, existing ROID=%s, new ROID=%s",
resource.getContactId(), existing.getRepoId(), resource.getRepoId());
}
return false;
}
});
} }
/** /**

View file

@ -14,6 +14,8 @@
package google.registry.util; package google.registry.util;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlEnumValue;
@ -38,12 +40,12 @@ public final class XmlToEnumMapper<T extends Enum<?>> {
ImmutableMap.Builder<String, T> mapBuilder = new ImmutableMap.Builder<>(); ImmutableMap.Builder<String, T> mapBuilder = new ImmutableMap.Builder<>();
for (T value : enumValues) { for (T value : enumValues) {
try { try {
String xmlName = XmlEnumValue xmlAnnotation = value
value
.getDeclaringClass() .getDeclaringClass()
.getField(value.name()) .getField(value.name())
.getAnnotation(XmlEnumValue.class) .getAnnotation(XmlEnumValue.class);
.value(); checkArgumentNotNull(xmlAnnotation, "Cannot map enum value to xml name: " + value);
String xmlName = xmlAnnotation.value();
mapBuilder = mapBuilder.put(xmlName, value); mapBuilder = mapBuilder.put(xmlName, value);
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
throw new RuntimeException(e); throw new RuntimeException(e);