Package com.googlecode.objectify.impl.translate

Source Code of com.googlecode.objectify.impl.translate.CollectionTranslatorFactory

package com.googlecode.objectify.impl.translate;

import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.impl.Path;
import com.googlecode.objectify.util.GenericUtils;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


/**
* <p>Translator which can load things into a collection field. Those things are themselves translated.</p>
*
* <p>This translator is clever about recycling an existing collection in the POJO field when loading.
* That way a collection that has been initialized with a sort (or other data) will remain intact.</p>
*
* <p>Note that empty or null collections are not stored in the datastore, and null values for the collection
* field are ignored when they are loaded from the Entity.  This is because the datastore doesn't store empty
* collections, and storing null fields will confuse filtering for actual nulls in the collection contents.</p>
*
* @author Jeff Schnitzer <jeff@infohazard.org>
*/
public class CollectionTranslatorFactory implements TranslatorFactory<Collection<Object>, Collection<Object>>
{
  @Override
  public Translator<Collection<Object>, Collection<Object>> create(TypeKey<Collection<Object>> tk, CreateContext ctx, Path path) {
    @SuppressWarnings("unchecked")
    final Class<? extends Collection<?>> collectionType = tk.getTypeAsClass();

    if (!Collection.class.isAssignableFrom(collectionType))
      return null;

    final ObjectifyFactory fact = ctx.getFactory();

    Type componentType = GenericUtils.getCollectionComponentType(tk.getType());
    final Translator<Object, Object> componentTranslator = ctx.getTranslator(new TypeKey<>(componentType, tk), ctx, path);

    return new TranslatorRecycles<Collection<Object>, Collection<Object>>() {

      @Override
      public Collection<Object> loadInto(Collection<Object> node, LoadContext ctx, Path path, Collection<Object> collection) throws SkipException {
        // If the collection does not exist, skip it entirely. This mirrors the underlying behavior
        // of collections in the datastore; if they are empty, they don't exist.
        if (node == null)
          throw new SkipException();

        if (collection == null)
          //noinspection unchecked
          collection = (Collection<Object>)fact.constructCollection(collectionType, node.size());
        else
          collection.clear();

        for (Object child: node) {
          try {
            Object value = componentTranslator.load(child, ctx, path);
            collection.add(value);
          }
          catch (SkipException ex) {
            // No prob, just skip that one
          }
        }

        return collection;
      }

      @Override
      public Collection<Object> save(Collection<Object> pojo, boolean index, SaveContext ctx, Path path) throws SkipException {

        // If it's empty, might as well skip it - the datastore doesn't store empty lists
        if (pojo == null || pojo.isEmpty())
          throw new SkipException();

        List<Object> list = new ArrayList<>();

        for (Object obj: pojo) {
          try {
            Object translatedChild = componentTranslator.save(obj, index, ctx, path);
            list.add(translatedChild);
          }
          catch (SkipException ex) {
            // Just skip that node, no prob
          }
        }

        return list;
      }
    };
  }
}
TOP

Related Classes of com.googlecode.objectify.impl.translate.CollectionTranslatorFactory

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.