Package com.googlecode.objectify.impl

Source Code of com.googlecode.objectify.impl.EntityMetadata

package com.googlecode.objectify.impl;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PropertyContainer;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.LoadException;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.SaveException;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.impl.translate.ClassTranslator;
import com.googlecode.objectify.impl.translate.EntityCreator;
import com.googlecode.objectify.impl.translate.LoadContext;
import com.googlecode.objectify.impl.translate.SaveContext;
import com.googlecode.objectify.impl.translate.Translator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;


/**
* Holds basic information about POJO entities, and can translate back and forth to the
* datastore representation.
*
* @author Jeff Schnitzer <jeff@infohazard.org>
*/
public class EntityMetadata<P>
{
  /** The base entity class type, ie the class with the @Entity annotation */
  private Class<P> entityClass;

  /** The cached annotation, or null if entity should not be cached */
  private Cache cached;

  /** */
  private ClassTranslator<P> translator;

  /** */
  private KeyMetadata<P> keyMetadata;

  /**
   * @param clazz must have @Entity in its hierarchy
   */
  public EntityMetadata(ObjectifyFactory fact, Class<P> clazz) {
    assert clazz.isAnnotationPresent(com.googlecode.objectify.annotation.Entity.class);

    this.entityClass = clazz;
    this.cached = clazz.getAnnotation(Cache.class);
    this.translator = (ClassTranslator<P>)fact.getTranslators().getRoot(clazz);
    this.keyMetadata = ((EntityCreator<P>)translator.getCreator()).getKeyMetadata();
  }

  /**
   * Get the expiry associated with this kind, defined by the @Cached annotation.
   * For polymorphic types, this is always the instruction on the root @Entity - you
   * cannot provide per-type caching.
   *
   * @return null means DO NOT CACHE, 0 means "no limit", otherwise # of seconds
   */
  public Integer getCacheExpirySeconds() {
    return this.cached == null ? null : this.cached.expirationSeconds();
  }

  /**
   * Converts an entity to an object of the appropriate type for this metadata structure.
   * Does not check that the entity is appropriate; that should be done when choosing
   * which EntityMetadata to call.
   */
  public P load(Entity ent, LoadContext ctx) {
    try {
      // The context needs to know the root entity for any given point
      ctx.setCurrentRoot(Key.create(ent.getKey()));

      return translator.load(ent, ctx, Path.root());
    }
    catch (LoadException ex) { throw ex; }
    catch (Exception ex) {
      throw new LoadException(ent, ex.getMessage(), ex);
    }
  }

  /**
   * Converts an object to a datastore Entity with the appropriate Key type.
   */
  public Entity save(P pojo, SaveContext ctx) {
    try {
      ctx.startOneEntity();

      Entity ent = (Entity) translator.save(pojo, false, ctx, Path.root());
      createSyntheticIndexes(ent, ctx);
      return ent;
    }
    catch (SaveException ex) { throw ex; }
    catch (Exception ex) {
      throw new SaveException(pojo, ex.getMessage(), ex);
    }
  }

  /**
   * Gets the class associated with this entity.
   */
  public Class<P> getEntityClass() {
    return this.entityClass;
  }

  /**
   * Get specific metadata about the key for this type.
   */
  public KeyMetadata<P> getKeyMetadata() {
    return keyMetadata;
  }

  /**
=   * @return the translator that will convert between native datastore representation and pojo for this type.
   */
  public Translator<P, PropertyContainer> getTranslator() {
    return translator;
  }

  /**
   * Establish any synthetic dot-separate indexes for embedded things that are indexed.
   */
  private void createSyntheticIndexes(Entity entity, SaveContext ctx) {

    // Look for anything which is embedded and therefore won't be automatically indexed
    for (Map.Entry<Path, Collection<Object>> index: ctx.getIndexes().entrySet()) {
      Path path = index.getKey();
      Collection<Object> values = index.getValue();

      if (path.isEmbedded()) {
        // Need to copy the values list otherwise it will clear when we reset the context indexes
        entity.setProperty(path.toPathString(), new ArrayList<>(values));
      }
    }
  }

}
TOP

Related Classes of com.googlecode.objectify.impl.EntityMetadata

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.