package com.googlecode.objectify.impl.translate;
import com.google.appengine.api.datastore.RawValue;
import com.google.common.primitives.Primitives;
import com.googlecode.objectify.impl.Path;
/**
* <p>Watches out for RawValue and performs the necessary conversion if we get one. This will happen
* during projection queries.</p>
*
* @author Jeff Schnitzer <jeff@infohazard.org>
*/
abstract public class ProjectionSafeTranslator<P, D> extends NullSafeTranslator<P, D>
{
/** The class in the datastore that we project to */
private Class<? extends D> projectionClass;
/** */
public ProjectionSafeTranslator(Class<? extends D> projectionClass) {
// Projection fails if we do not use the wrapper type
this.projectionClass = Primitives.wrap(projectionClass);
}
@Override
final protected P loadSafe(D value, LoadContext ctx, Path path) throws SkipException {
// Projection queries produce RawValue because the index data is not self-describing.
// Here we have the expected datastore type, so we can obtain it right away.
if (value instanceof RawValue) {
value = (D)((RawValue)value).asType(projectionClass);
// Annoyingly, null values still come back as a RawValue but the content is null
if (value == null)
return null;
}
return loadSafe2(value, ctx, path);
}
/**
* Decode from a property value as stored in the datastore to a type that will be stored in a pojo.
*
* @param value will not be null and will not be RawValue
* @return the format which should be stored in the pojo; a null means store a literal null!
* @throws com.googlecode.objectify.impl.translate.SkipException if this field subtree should be skipped
*/
abstract protected P loadSafe2(D value, LoadContext ctx, Path path) throws SkipException;
}