mv com/google/domain/registry google/registry

This change renames directories in preparation for the great package
rename. The repository is now in a broken state because the code
itself hasn't been updated. However this should ensure that git
correctly preserves history for each file.
This commit is contained in:
Justine Tunney 2016-05-13 18:55:08 -04:00
parent a41677aea1
commit 5012893c1d
2396 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,63 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import com.google.domain.registry.util.TypeUtils.TypeInstantiator;
import com.googlecode.objectify.impl.Path;
import com.googlecode.objectify.impl.Property;
import com.googlecode.objectify.impl.translate.CreateContext;
import com.googlecode.objectify.impl.translate.LoadContext;
import com.googlecode.objectify.impl.translate.SaveContext;
import com.googlecode.objectify.impl.translate.ValueTranslator;
import com.googlecode.objectify.impl.translate.ValueTranslatorFactory;
import java.lang.reflect.Type;
/** Common boilerplate for translator factories. */
public abstract class AbstractSimpleTranslatorFactory<P, D> extends ValueTranslatorFactory<P, D> {
public AbstractSimpleTranslatorFactory(Class<P> clazz) {
super(clazz);
}
@Override
protected final ValueTranslator<P, D> createSafe(
Path path, Property property, Type type, CreateContext ctx) {
return new ValueTranslator<P, D>(path, new TypeInstantiator<D>(getClass()){}.getExactType()) {
SimpleTranslator<P, D> simpleTranslator = createTranslator();
@Override
protected P loadValue(D datastoreValue, LoadContext ctx) {
return simpleTranslator.loadValue(datastoreValue);
}
@Override
protected D saveValue(P pojoValue, SaveContext ctx) {
return simpleTranslator.saveValue(pojoValue);
}
};
}
/** Translator with reduced boilerplate. */
interface SimpleTranslator<P, D> {
P loadValue(D datastoreValue);
D saveValue(P pojoValue);
}
abstract SimpleTranslator<P, D> createTranslator();
}

View file

@ -0,0 +1,40 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import com.google.domain.registry.util.CidrAddressBlock;
/** Stores {@link CidrAddressBlock} as a canonicalized string. */
public class CidrAddressBlockTranslatorFactory
extends AbstractSimpleTranslatorFactory<CidrAddressBlock, String> {
public CidrAddressBlockTranslatorFactory() {
super(CidrAddressBlock.class);
}
@Override
SimpleTranslator<CidrAddressBlock, String> createTranslator() {
return new SimpleTranslator<CidrAddressBlock, String>(){
@Override
public CidrAddressBlock loadValue(String datastoreValue) {
return CidrAddressBlock.create(datastoreValue);
}
@Override
public String saveValue(CidrAddressBlock pojoValue) {
return pojoValue.toString();
}};
}
}

View file

@ -0,0 +1,77 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.domain.registry.model.ofy.ObjectifyService.ofy;
import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Ordering;
import com.google.domain.registry.config.RegistryEnvironment;
import com.google.domain.registry.model.ofy.CommitLogManifest;
import com.googlecode.objectify.Ref;
import org.joda.time.DateTime;
/**
* Objectify translator for {@code ImmutableSortedMap<DateTime, Ref<CommitLogManifest>>} fields.
*
* <p>This translator is responsible for doing three things:
* <ol>
* <li>Translating the data into two lists of {@code Date} and {@code Key} objects, in a manner
* similar to {@code @Mapify}.
* <li>Inserting a reference to the transaction's {@link CommitLogManifest} on save.
* <li>Truncating the map to include only the last key per day for the last 30 days.
* </ol>
*
* <p>This allows you to have a field on your model object that tracks historical revisions of
* itself, which can be binary searched for point-in-time restoration.
*
* <p><b>Warning:</b> Fields of this type must not be {@code null}, or else new entries can't be
* inserted. You must take care to initialize the field to empty.
*
* @see com.google.domain.registry.model.EppResource
*/
public final class CommitLogRevisionsTranslatorFactory
extends ImmutableSortedMapTranslatorFactory<DateTime, Ref<CommitLogManifest>> {
private static final RegistryEnvironment ENVIRONMENT = RegistryEnvironment.get();
/**
* Add a reference to the current commit log to the resource's revisions map.
*
* <p>This method also prunes the revisions map. It guarantees to keep enough data so that floor
* will work going back N days. It does this by making sure one entry exists before that duration,
* and pruning everything after it. The size of the map is guaranteed to never exceed N+2.
*
* <p>We store a maximum of one entry per day. It will be the last transaction that happened on
* that day.
*
* @see com.google.domain.registry.config.RegistryConfig#getCommitLogDatastoreRetention()
*/
@Override
ImmutableSortedMap<DateTime, Ref<CommitLogManifest>> transformBeforeSave(
ImmutableSortedMap<DateTime, Ref<CommitLogManifest>> revisions) {
DateTime now = ofy().getTransactionTime();
DateTime threshold = now.minus(ENVIRONMENT.config().getCommitLogDatastoreRetention());
DateTime preThresholdTime = firstNonNull(revisions.floorKey(threshold), START_OF_TIME);
return new ImmutableSortedMap.Builder<DateTime, Ref<CommitLogManifest>>(Ordering.natural())
.putAll(revisions.subMap(preThresholdTime, true, now.withTimeAtStartOfDay(), false))
.put(now, Ref.create(ofy().getCommitLogManifestKey()))
.build();
}
}

View file

@ -0,0 +1,54 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.domain.registry.model.ofy.ObjectifyService.ofy;
import static org.joda.time.DateTimeZone.UTC;
import com.google.domain.registry.model.CreateAutoTimestamp;
import org.joda.time.DateTime;
import java.util.Date;
/** Saves {@link CreateAutoTimestamp} as either its value, or the current time if it was null. */
public class CreateAutoTimestampTranslatorFactory
extends AbstractSimpleTranslatorFactory<CreateAutoTimestamp, Date> {
public CreateAutoTimestampTranslatorFactory() {
super(CreateAutoTimestamp.class);
}
@Override
SimpleTranslator<CreateAutoTimestamp, Date> createTranslator() {
return new SimpleTranslator<CreateAutoTimestamp, Date>() {
/**
* Load an existing timestamp. It can be assumed to be non-null since if the field is null in
* datastore then Objectify will skip this translator and directly load a null.
*/
@Override
public CreateAutoTimestamp loadValue(Date datastoreValue) {
return CreateAutoTimestamp.create(new DateTime(datastoreValue, UTC));
}
/** Save a timestamp, setting it to the current time if it did not have a previous value. */
@Override
public Date saveValue(CreateAutoTimestamp pojoValue) {
return firstNonNull(pojoValue.getTimestamp(), ofy().getTransactionTime()).toDate();
}};
}
}

View file

@ -0,0 +1,44 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import static com.google.common.base.Strings.nullToEmpty;
import org.joda.money.CurrencyUnit;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/** Adapter to use Joda {@link CurrencyUnit} when marshalling strings. */
public class CurrencyUnitAdapter extends XmlAdapter<String, CurrencyUnit> {
/** Parses a string into a {@link CurrencyUnit} object. */
@Override
public CurrencyUnit unmarshal(String currency) throws UnknownCurrencyException {
try {
return CurrencyUnit.of(nullToEmpty(currency).trim());
} catch (IllegalArgumentException e) {
throw new UnknownCurrencyException();
}
}
/** Converts {@link CurrencyUnit} to a string. */
@Override
public String marshal(CurrencyUnit currency) {
return currency == null ? null : currency.toString();
}
/** Exception to throw when failing to parse a currency. */
public static class UnknownCurrencyException extends Exception {}
}

View file

@ -0,0 +1,40 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import org.joda.money.CurrencyUnit;
/** Stores {@link CurrencyUnit} as a canonicalized string. */
public class CurrencyUnitTranslatorFactory
extends AbstractSimpleTranslatorFactory<CurrencyUnit, String> {
public CurrencyUnitTranslatorFactory() {
super(CurrencyUnit.class);
}
@Override
SimpleTranslator<CurrencyUnit, String> createTranslator() {
return new SimpleTranslator<CurrencyUnit, String>(){
@Override
public CurrencyUnit loadValue(String datastoreValue) {
return CurrencyUnit.of(datastoreValue);
}
@Override
public String saveValue(CurrencyUnit pojoValue) {
return pojoValue.toString();
}};
}
}

View file

@ -0,0 +1,39 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import org.joda.time.Duration;
/** Stores {@link Duration} as a canonicalized string. */
public class DurationTranslatorFactory extends AbstractSimpleTranslatorFactory<Duration, String> {
public DurationTranslatorFactory() {
super(Duration.class);
}
@Override
protected SimpleTranslator<Duration, String> createTranslator() {
return new SimpleTranslator<Duration, String>() {
@Override
public Duration loadValue(String datastoreValue) {
return Duration.parse(datastoreValue);
}
@Override
public String saveValue(Duration pojoValue) {
return pojoValue.toString();
}};
}
}

View file

@ -0,0 +1,56 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/**
* Used by JAXB to convert enums to the peculiar EPP format that puts the value in an attribute.
*
* @param <E> the enum type
*/
public class EnumToAttributeAdapter<E extends Enum<E> & EnumToAttributeAdapter.EppEnum>
extends XmlAdapter<EnumToAttributeAdapter.EnumShim, E> {
/** Interface for epp enums that can be transformed with this adapter. */
public interface EppEnum {
String getXmlName();
}
/**
* EPP's peculiar enum format.
* <p>
* It's meant to allow more information inside the element, but it's an annoyance when we want to
* deal with pure enums.
*/
static class EnumShim {
@XmlAttribute
String s;
}
// Enums that can be unmarshalled from input can override this.
@Override
public E unmarshal(EnumShim shim) throws Exception {
throw new UnsupportedOperationException();
}
@Override
public final EnumShim marshal(E enumeration) throws Exception {
EnumShim shim = new EnumShim();
shim.s = enumeration.getXmlName();
return shim;
}
}

View file

@ -0,0 +1,168 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.domain.registry.util.CollectionUtils.nullToEmpty;
import static com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector.erase;
import static com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector.getTypeParameter;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Ordering;
import com.google.common.reflect.TypeToken;
import com.googlecode.objectify.impl.Node;
import com.googlecode.objectify.impl.Path;
import com.googlecode.objectify.impl.Property;
import com.googlecode.objectify.impl.translate.CreateContext;
import com.googlecode.objectify.impl.translate.ListNodeTranslator;
import com.googlecode.objectify.impl.translate.LoadContext;
import com.googlecode.objectify.impl.translate.SaveContext;
import com.googlecode.objectify.impl.translate.SkipException;
import com.googlecode.objectify.impl.translate.Translator;
import com.googlecode.objectify.impl.translate.TranslatorFactory;
import com.googlecode.objectify.impl.translate.TranslatorRegistry;
import java.lang.reflect.Type;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Abstract Objectify translator for {@link ImmutableSortedMap} fields.
*
* <p>This class should be extended for each set of concrete key/value types you wish to support.
* This translator will only apply to {@code ImmutableSortedMap} model fields that have precicely
* the same type parameters you specified.
*
* <p>This translator serves a similar purpose to
* {@link com.googlecode.objectify.impl.translate.MapifyTranslatorFactory @Mapify}. Except this
* maintains perfect immutability of the field value. Subclasses may override the
* {@link #transformBeforeSave(ImmutableSortedMap)} methods to perform mutation on a per-concrete
* type basis. This abstraction is also more readable than {@code @Mapify} because it shifts the
* boilerplate into translator magic, rather than convoluting model data structures.
*
* <h3>Entity Data Layout</h3>
*
* <p>For example, if you had an {@code ImmutableSortedMap<String, String>} on a field named
* {@code field}, then this would look like:<pre> {@code
*
* field.key -> [key1, key2]
* field.value -> [value1, value2]}</pre>
*
* <p>If you had an {@code ImmutableSortedMap<String, EmbeddedClass>} on a field named
* {@code field}, where {@code EmbeddedClass} defines two {@code foo} and {@code bar} fields, then
* the embedded properties might look like:<pre> {@code
*
* field.key -> [key1, key2]
* field.value.foo -> [foo1, foo2]
* field.value.bar -> [bar1, bar2]}</pre>
*
* @param <K> key type for sorted map which must be {@link Comparable}
* @param <V> value type for sorted map
*/
abstract class ImmutableSortedMapTranslatorFactory<K extends Comparable<? super K>, V>
implements TranslatorFactory<ImmutableSortedMap<K, V>> {
private final TypeToken<K> keyType = new TypeToken<K>(getClass()) {};
private final TypeToken<V> valueType = new TypeToken<V>(getClass()) {};
private final String keyProperty;
private final String valueProperty;
ImmutableSortedMapTranslatorFactory() {
this("key", "value");
}
/** Constructs a instance that's compatible with models migrated from {@code @Mapify}. */
ImmutableSortedMapTranslatorFactory(String keyProperty, String valueProperty) {
this.keyProperty = checkNotNull(keyProperty);
this.valueProperty = checkNotNull(valueProperty);
}
/** Allows for changing the field data structure before it's written to the raw entity object. */
ImmutableSortedMap<K, V> transformBeforeSave(ImmutableSortedMap<K, V> map) {
return map;
}
@Override
public final Translator<ImmutableSortedMap<K, V>>
create(Path path, Property property, Type type, CreateContext ctx) {
if (!ImmutableSortedMap.class.equals(erase(type))) {
return null; // skip me and try to find another matching translator
}
Type fieldKeyType = getTypeParameter(type, ImmutableSortedMap.class.getTypeParameters()[0]);
Type fieldValueType = getTypeParameter(type, ImmutableSortedMap.class.getTypeParameters()[1]);
if (fieldKeyType == null || fieldValueType == null) {
return null; // no type information is available
}
if (!keyType.isSupertypeOf(fieldKeyType) || !valueType.isSupertypeOf(fieldValueType)) {
return null; // this ImmutableSortedMap does not have the same concrete component types
}
ctx.enterCollection(path);
ctx.enterEmbed(path);
try {
// The component types can also be translated by Objectify!
TranslatorRegistry translators = ctx.getFactory().getTranslators();
final Translator<K> keyTranslator =
translators.create(path.extend(keyProperty), property, fieldKeyType, ctx);
final Translator<V> valueTranslator =
translators.create(path.extend(valueProperty), property, fieldValueType, ctx);
return new ListNodeTranslator<ImmutableSortedMap<K, V>>() {
@Override
protected ImmutableSortedMap<K, V> loadList(Node node, LoadContext ctx) {
ImmutableSortedMap.Builder<K, V> map =
new ImmutableSortedMap.Builder<>(Ordering.natural());
for (Node child : node) {
try {
map.put(keyTranslator.load(child.get(keyProperty), ctx),
valueTranslator.load(child.get(valueProperty), ctx));
} catch (SkipException e) {
// no problem, just skip that one
}
}
return map.build();
}
@Override
protected Node saveList(
@Nullable ImmutableSortedMap<K, V> mapFromPojo,
Path path,
boolean index,
SaveContext ctx) {
checkState(!index, "At path %s: Index not allowed", path);
ImmutableSortedMap<K, V> mapToSave = transformBeforeSave(
ImmutableSortedMap.copyOfSorted(nullToEmpty(mapFromPojo)));
if (mapToSave.isEmpty()) {
throw new SkipException(); // the datastore doesn't store empty lists
}
Node node = new Node(path);
for (Map.Entry<K, V> entry : mapToSave.entrySet()) {
Node item = new Node(path);
item.put(keyProperty,
keyTranslator.save(entry.getKey(), path.extend(keyProperty), index, ctx));
item.put(valueProperty,
valueTranslator.save(entry.getValue(), path.extend(valueProperty), index, ctx));
node.addToList(item);
}
return node;
}
};
} finally {
ctx.exitEmbed();
ctx.exitCollection();
}
}
}

View file

@ -0,0 +1,42 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import com.google.common.net.InetAddresses;
import java.net.InetAddress;
/** Stores {@link InetAddress} as a canonicalized string. */
public class InetAddressTranslatorFactory
extends AbstractSimpleTranslatorFactory<InetAddress, String> {
public InetAddressTranslatorFactory() {
super(InetAddress.class);
}
@Override
SimpleTranslator<InetAddress, String> createTranslator() {
return new SimpleTranslator<InetAddress, String>() {
@Override
public InetAddress loadValue(String datastoreValue) {
return InetAddresses.forString(datastoreValue);
}
@Override
public String saveValue(InetAddress pojoValue) {
return pojoValue.getHostAddress();
}};
}
}

View file

@ -0,0 +1,68 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import com.googlecode.objectify.impl.Path;
import com.googlecode.objectify.impl.Property;
import com.googlecode.objectify.impl.TypeUtils;
import com.googlecode.objectify.impl.translate.CreateContext;
import com.googlecode.objectify.impl.translate.LoadContext;
import com.googlecode.objectify.impl.translate.SaveContext;
import com.googlecode.objectify.impl.translate.ValueTranslator;
import com.googlecode.objectify.impl.translate.ValueTranslatorFactory;
import com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector;
import org.joda.time.DateTimeZone;
import org.joda.time.ReadableInstant;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.Date;
/**
* Stores Joda {@link ReadableInstant} types ({@code DateTime}, etc) as a {@link java.util.Date}.
* <p>
* This is a fork of the {@code ReadableInstantTranslatorFactory} that comes bundled with Objectify.
* The original reifies a {@link ReadableInstant} using the machine's local time zone. This version
* always uses UTC.
*/
public class ReadableInstantUtcTranslatorFactory
extends ValueTranslatorFactory<ReadableInstant, Date> {
public ReadableInstantUtcTranslatorFactory() {
super(ReadableInstant.class);
}
@Override
protected ValueTranslator<ReadableInstant, Date> createSafe(
Path path, Property property, Type type, CreateContext ctx) {
final Class<?> clazz = GenericTypeReflector.erase(type);
return new ValueTranslator<ReadableInstant, Date>(path, Date.class) {
@Override
protected ReadableInstant loadValue(Date value, LoadContext ctx) {
// All the Joda instants have a constructor that will take a Date and timezone.
Constructor<?> ctor = TypeUtils.getConstructor(clazz, Object.class, DateTimeZone.class);
return (ReadableInstant) TypeUtils.newInstance(ctor, value, DateTimeZone.UTC);
}
@Override
protected Date saveValue(ReadableInstant value, SaveContext ctx) {
return value.toInstant().toDate();
}
};
}
}

View file

@ -0,0 +1,26 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import com.google.domain.registry.model.eppcommon.StatusValue;
/** Adapter for {@link StatusValue}. */
public class StatusValueAdapter extends EnumToAttributeAdapter<StatusValue> {
@Override
public StatusValue unmarshal(EnumShim shim) {
// The value must be a valid enum value from the xsd, or JAXB will never get this far.
return StatusValue.fromXmlName(shim.s);
}
}

View file

@ -0,0 +1,54 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.translators;
import static com.google.domain.registry.model.ofy.ObjectifyService.ofy;
import static org.joda.time.DateTimeZone.UTC;
import com.google.domain.registry.model.UpdateAutoTimestamp;
import org.joda.time.DateTime;
import java.util.Date;
/** Saves {@link UpdateAutoTimestamp} as the current time. */
public class UpdateAutoTimestampTranslatorFactory
extends AbstractSimpleTranslatorFactory<UpdateAutoTimestamp, Date> {
public UpdateAutoTimestampTranslatorFactory() {
super(UpdateAutoTimestamp.class);
}
@Override
SimpleTranslator<UpdateAutoTimestamp, Date> createTranslator() {
return new SimpleTranslator<UpdateAutoTimestamp, Date>() {
/**
* Load an existing timestamp. It can be assumed to be non-null since if the field is null in
* datastore then Objectify will skip this translator and directly load a null.
*/
@Override
public UpdateAutoTimestamp loadValue(Date datastoreValue) {
// Load an existing timestamp, or treat it as START_OF_TIME if none exists.
return UpdateAutoTimestamp.create(new DateTime(datastoreValue, UTC));
}
/** Save a timestamp, setting it to the current time. */
@Override
public Date saveValue(UpdateAutoTimestamp pojoValue) {
return ofy().getTransactionTime().toDate();
}};
}
}