Package com.vercer.engine.persist.strategy

Source Code of com.vercer.engine.persist.strategy.DefaultFieldStrategy$ReplacedListType

package com.vercer.engine.persist.strategy;

import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.vercer.engine.persist.conversion.PrimitiveTypeConverter;
import com.vercer.engine.persist.util.generic.GenericTypeReflector;

/**
* @author John Patterson <john@vercer.com>
*
*/
public class DefaultFieldStrategy implements FieldStrategy
{
  private static final class ReplacedListType implements ParameterizedType
  {
    private final Type type;
    private final Type replaced;

    private ReplacedListType(Type type, Type replaced)
    {
      this.type = type;
      this.replaced = replaced;
    }

    public Type getRawType()
    {
      return ArrayList.class;
    }

    public Type getOwnerType()
    {
      return null;
    }

    public Type[] getActualTypeArguments()
    {
      return new Type[] { replaced };
    }

    @Override
    public String toString()
    {
      return "(Replaced " + type + " with List<" + replaced + ">)";
    }
  }

  private final int defaultVersion;

  public DefaultFieldStrategy(int defaultVersion)
  {
    this.defaultVersion = defaultVersion;
  }

  /**
   * Decode a type name - possibly abbreviated - into a type.
   *
   * @param name The portion of the kind name that specifies the Type
   */
  protected Type nameToType(String name)
  {
    try
    {
      return Class.forName(name);
    }
    catch (ClassNotFoundException e)
    {
      throw new IllegalStateException(e);
    }
  }

  private final static Pattern pattern = Pattern.compile("v\\d_");
  public final Type kindToType(String name)
  {
        Matcher matcher = pattern.matcher(name);
    if (matcher.lookingAt())
    {
      name = name.substring(matcher.end());
    }
   
    //use space as a place holder as it cannot exist in property names
    name = name.replaceAll("__", " ");
    name = name.replace('_', '.');
    name = name.replace(' ', '_');
    return nameToType(name);
  }

  /**
   *
   * @see com.vercer.engine.persist.strategy.FieldStrategy#name(java.lang.reflect.Field)
   */
  public final String name(Field field)
  {
    String name = field.getName();
    if (name.charAt(0) == '_')
    {
      name = name.substring(1);
    }
    return name;
  }

  public final String typeToKind(Type type)
  {
    String kind = typeToName(type);
   
    kind = kind.replace('.', ' ');
    kind = kind.replaceAll("_", "__");
    kind = kind.replace(' ', '_');
   
    int version = version(type);
    if (version > 0)
    {
      kind = "v" + version + "_" + kind;
    }
    return kind;
  }

  /**
   * The converse method nametoType must understand how to "decode" type
   * names encoded by this method
   *
   * @return A representation that can unambiguously specify the type
   */
  protected String typeToName(Type type)
  {
    Class<?> clazz = GenericTypeReflector.erase(type);
    String kind = clazz.getName();
    return kind;
  }

  /**
   * @return The datastore version to store this type under
   */
  protected int version(Type type)
  {
    return defaultVersion;
  }

  /**
   * Replaces all Collection types and Arrays with List. Converts all elements of
   * the collection to the component type.
   *
   * @see com.vercer.engine.persist.strategy.FieldStrategy#typeOf(java.lang.reflect.Field)
   */
  public Type typeOf(Field field)
  {
    return replace(field.getGenericType());
  }

  protected Type replace(final Type type)
  {
    // turn every collection or array into an array list
    Type componentType = null;
    Class<?> erased = GenericTypeReflector.erase(type);
    if (type instanceof GenericArrayType)
    {
      // we have a generic array like Provider<Twig>[]
      GenericArrayType arrayType = (GenericArrayType) type;
      componentType = arrayType.getGenericComponentType();
    }
    else if (erased.isArray())
    {
      // we have a normal array like Twig[]
      componentType = erased.getComponentType();
    }
    else if (Collection.class.isAssignableFrom(erased) && !ArrayList.class.isAssignableFrom(erased))
    {
      // we have some kind of collection like Set<Twig>
      Type exact = GenericTypeReflector.getExactSuperType(type, Collection.class);
      componentType = ((ParameterizedType) exact).getActualTypeArguments()[0];
    }
    else
    {
      // we have a non-collection type
      return type;
    }

    // we have a collection type so need to convert it to

    // recurse in case we have e.g. List<Twig[]>
    Type replaced = replace(componentType);
   
    // use wrapper type for primitives
    if (GenericTypeReflector.erase(replaced).isPrimitive())
    {
      replaced = PrimitiveTypeConverter.getWrapperClassForPrimitive((Class<?>) replaced);
    }

    // replace the collection type with a list type
    return new ReplacedListType(type, replaced);
  }



}
TOP

Related Classes of com.vercer.engine.persist.strategy.DefaultFieldStrategy$ReplacedListType

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.