Package com.vercer.engine.persist.translator

Source Code of com.vercer.engine.persist.translator.MapTranslator

package com.vercer.engine.persist.translator;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.vercer.engine.persist.Path;
import com.vercer.engine.persist.Property;
import com.vercer.engine.persist.PropertyTranslator;
import com.vercer.engine.persist.Path.Part;
import com.vercer.engine.persist.conversion.TypeConverter;
import com.vercer.engine.persist.util.PropertySets;
import com.vercer.engine.persist.util.PropertySets.PrefixPropertySet;
import com.vercer.engine.persist.util.generic.GenericTypeReflector;
import com.vercer.util.collections.MergeSet;

public class MapTranslator extends DecoratingTranslator
{
  private final TypeConverter converter;

  public MapTranslator(PropertyTranslator delegate, TypeConverter converter)
  {
    super(delegate);
    this.converter = converter;
  }
 
  @Override
  public Object propertiesToTypesafe(Set<Property> properties, Path path, Type type)
  {
    // only try if we can set a map to the field
    if (!GenericTypeReflector.erase(type).isAssignableFrom(HashMap.class))
    {
      // pass on all other types down the chain
      return chained.propertiesToTypesafe(properties, path, type);
    }

    if (properties.isEmpty())
    {
      return NULL_VALUE;
    }
   
    // group the properties by prefix to create each item
    Collection<PrefixPropertySet> ppss = PropertySets.prefixPropertySets(properties, path);

    // find the types of the key and value from the generic parameters
    Type exact = GenericTypeReflector.getExactSuperType(type, Map.class);
    Type keyType = ((ParameterizedType) exact).getActualTypeArguments()[0];
    Type valueType = ((ParameterizedType) exact).getActualTypeArguments()[1];
   
    // type erasure means we can use object as the generic parameters
    Map<Object, Object> result = new HashMap<Object, Object>(ppss.size());
    for (PrefixPropertySet pps : ppss)
    {
      // the key must be converted from a String
      Part partAfterPrefix = pps.getPrefix().firstPartAfterPrefix(path);
      Object key = converter.convert(partAfterPrefix.getName(), keyType);
     
      // decode the value properties using the generic type info
      Object value = chained.propertiesToTypesafe(pps.getProperties(), pps.getPrefix(), valueType);
     
      result.put(key, value);
    }
    return result;
  }

  @Override
  public Set<Property> typesafeToProperties(Object instance, Path path, boolean indexed)
  {
    if (instance instanceof Map<?, ?> == false)
    {
      // pass it on down the line
      return chained.typesafeToProperties(instance, path, indexed);
    }
   
    Map<?, ?> map = (Map<?, ?>) instance;
    Set<?> keys = map.keySet();
    Set<Property> merged = new MergeSet<Property>(map.size());
    for (Object key: keys)
    {
      Object value = map.get(key);
      String keyString = converter.convert(key, String.class);
      Path childPath = Path.builder(path).field(keyString).build();
      Set<Property> properties = chained.typesafeToProperties(value, childPath, indexed);
     
      if (properties == null)
      {
        // we could not handle a value so pass the whole map down the chain
        return chained.typesafeToProperties(instance, path, indexed);
      }
     
      merged.addAll(properties);
    }
   
    return merged;
  }

}
TOP

Related Classes of com.vercer.engine.persist.translator.MapTranslator

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.