All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jsonex.jsoncoder.coder.CoderCollection Maven / Gradle / Ivy

There is a newer version: 0.1.27
Show newest version
/*************************************************************
 Copyright 2018-2019 eBay Inc.
 Author/Developer: Jianwu Chen

 Use of this source code is governed by an MIT-style
 license that can be found in the LICENSE file or at
 https://opensource.org/licenses/MIT.
 ************************************************************/

package org.jsonex.jsoncoder.coder;

import org.jsonex.core.factory.InjectableInstance;
import org.jsonex.core.util.ClassUtil;
import org.jsonex.jsoncoder.BeanCoderContext;
import org.jsonex.jsoncoder.BeanCoderException;
import org.jsonex.jsoncoder.ICoder;
import org.jsonex.treedoc.TDNode;
import lombok.SneakyThrows;

import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.*;

import static org.jsonex.core.util.StringUtil.toTrimmedStr;

public class CoderCollection implements ICoder {
  public static final InjectableInstance it = InjectableInstance.of(CoderCollection.class);
  public static CoderCollection get() { return it.get(); }

  @Override public Class getType() { return Collection.class; }

  @Override public TDNode encode(Collection obj, Type type, BeanCoderContext ctx, TDNode target) {
    target.setType(TDNode.Type.ARRAY);

    Type[] actualTypeParameters = ClassUtil.getGenericTypeActualParams(type);
    Type childType = null;
    if (actualTypeParameters != null)
      childType = actualTypeParameters[0];

    for (Object o1 : (Collection)obj)
      ctx.encode(o1, childType, target.createChild(null));

    return target;
  }

  @SuppressWarnings("unchecked")
  @SneakyThrows
  @Override public Collection decode(TDNode tdNode, Type type, Object targetObj, BeanCoderContext ctx) {
    if (tdNode.getType() != TDNode.Type.ARRAY)
      throw new BeanCoderException("Incorrect input, the input has to be an array:" + toTrimmedStr(tdNode, 500));

    Class cls = ClassUtil.getGenericClass(type);

    Type[] actualTypeParameters = ClassUtil.getGenericTypeActualParams(type);
    if (actualTypeParameters == null)
      throw new BeanCoderException("For collection type, you have to specify the actual type: " + cls);
    Type childType = actualTypeParameters[0];

    Collection result = (Collection) targetObj;
    if (result == null) {
      int modifier = cls.getModifiers();
      if (Modifier.isAbstract(modifier) ||
          Modifier.isInterface(modifier)) {
        //Use the default implementation ArrayList
        if (EnumSet.class.isAssignableFrom(cls))
          result = (EnumSet) EnumSet.noneOf((Class) childType);
        else if (Set.class.isAssignableFrom(cls))
          result = new HashSet<>();
        else
          result = new ArrayList<>();
      } else
        result = (Collection) cls.newInstance();
    }

    ctx.getNodeToObjectMap().put(tdNode, result);

    for (int i = 0; i < tdNode.getChildrenSize(); i++)
      result.add(ctx.decode(tdNode.getChildren().get(i), childType, null, Integer.toString(i)));
    return result;
  }
}