Package org.jtester.fit.fixture

Source Code of org.jtester.fit.fixture.DtoPropertyFixture

package org.jtester.fit.fixture;

import java.util.List;
import java.util.Map;

import org.jtester.bytecode.reflector.FieldAccessor;
import org.jtester.bytecode.reflector.MethodAccessor;
import org.jtester.bytecode.reflector.helper.MethodHelper;
import org.jtester.exception.NoSuchMethodRuntimeException;
import org.jtester.fit.util.ParseArg;
import org.jtester.utility.StringHelper;

import fit.Parse;
import fit.TypeAdapter;
import fit.exception.FitFailureException;

@SuppressWarnings({ "rawtypes" })
public class DtoPropertyFixture extends SpringFixture {
  private Class dtoClazz;
  private MethodAccessor accessor;
  private PropertyBinding bindings[];
  private String parsePropertyMethodName;

  public void doRows(Parse rows) {
    Parse first = rows.parts;
    if (first == null) {
      throw new FitFailureException("You must specify a method.");
    }
    findMethod(first);
    Parse rest = rows.more;
    if (rest == null || rest.parts == null) {
      throw new RuntimeException("No test case is found!");
    }
    bindDtoProperties(rest.parts);
    super.doRows(rest.more);
  }

  /**
   * 查找方法参数的class值<br>
   * 如果在fit文件中指定了参数类型,那么返回指定了类型<br>
   * 否则,查找名为methodname的唯一方法,并且返回参数的类型
   *
   * @param methodname
   * @param methodArg
   * @return
   */
  protected void findMethod(Parse cell) {
    String methodname = cell.text();
    methodname = StringHelper.camel(methodname);
    Parse argument = cell.more;
    if (StringHelper.isBlankOrNull(methodname)) {
      throw new FitFailureException("You must specify a method.");
    }
    try {
      if (argument == null) {
        this.accessor = MethodHelper.findMethodByArgCount(this, methodname, 1);
        this.dtoClazz = this.accessor.getMethod().getParameterTypes()[0];
      } else {
        String clazzName = argument.text();
        this.dtoClazz = Class.forName(clazzName);
        this.accessor = new MethodAccessor<Object>(this, methodname, dtoClazz);
      }
      this.right(cell);
    } catch (Throwable e) {
      this.wrong(cell);
      throw new RuntimeException(e);
    }
  }

  /**
   * 绑定参数类型
   *
   * @param dtoProps
   */
  private void bindDtoProperties(Parse dtoProps) {
    int size = dtoProps.size();
    try {
      String prop = dtoProps.text().trim();
      if (size == 1 && prop.startsWith(">>")) {
        this.parsePropertyMethodName = camel("parse " + prop.substring(2));
        this.bindings = null;
      } else {
        this.parsePropertyMethodName = null;
        this.bindings = new PropertyBinding[size];
        for (int i = 0; dtoProps != null; i++, dtoProps = dtoProps.more) {
          String property = camel(dtoProps.text());
          bindings[i] = new PropertyBinding(property);
        }
      }
    } catch (Throwable e) {
      this.wrong(dtoProps);
      throw new RuntimeException(e);
    }
  }

  @Override
  public void doRow(Parse row) {
    Parse cells = row.parts;
    try {
      Object para = this.instancePara(cells);
      Object result = accessor.invoke(this, new Object[] { para });
      if (!(result instanceof Boolean)) {
        this.right(cells);
      } else if ((Boolean) result == true) {
        this.right(cells);
      } else {
        this.wrong(cells);
      }
    } catch (Throwable e) {
      this.exception(cells, e);
    }
  }

  /**
   * 根据当前行的值,初始化参数值
   *
   * @param cells
   * @return
   * @throws Exception
   */
  private Object instancePara(Parse cells) throws Exception {
    if (this.parsePropertyMethodName != null) {
      String text = cells.text();
      try {
        MethodAccessor methodAccessor = new MethodAccessor<Object>(this, parsePropertyMethodName, String.class);
        return methodAccessor.invoke(this, new Object[] { text });
      } catch (NoSuchMethodRuntimeException e) {
        TypeAdapter typeAdapter = TypeAdapter.on(this, dtoClazz);
        return typeAdapter.parse(text);
      }
    }
    Object obj = dtoClazz.newInstance();

    for (int i = 0; cells != null && i < bindings.length; i++, cells = cells.more) {
      PropertyBinding binding = bindings[i];
      String text = ParseArg.parseCellValue(cells);
      binding.setValue(obj, text);
    }
    return obj;
  }

  protected class PropertyBinding {
    private FieldAccessor fieldAccessor;
    private String parseMethodName;
    private TypeAdapter typeAdapter;

    public PropertyBinding(String property) throws Exception {
      this.fieldAccessor = new FieldAccessor(dtoClazz, camel(property));
      this.parseMethodName = camel("parse " + property);
      this.typeAdapter = TypeAdapter.on(DtoPropertyFixture.this, fieldAccessor.getFieldType());
    }

    public void setValue(Object obj, String value) throws Exception {
      try {
        MethodAccessor methodAccessor = new MethodAccessor<Object>(obj, parseMethodName, String.class);
        methodAccessor.invoke(obj, new Object[] { value });
      } catch (NoSuchMethodRuntimeException e) {
        Object _value = typeAdapter.parse(value);
        fieldAccessor.set(obj, _value);
      }
    }
  }

  /**
   * 解析以";"分割的字符串为list对象
   *
   * @param value
   * @return
   */
  protected static List<String> parseList(String value) {
    return ParseArg.parseList(value);
  }

  /**
   * 解析以split分割的字符串为list对象
   *
   * @param value
   * @param split
   * @return
   */
  protected static List<String> parseList(String value, String split) {
    return ParseArg.parseList(value, split);
  }

  /**
   * 解析默认的方式组装map数据的字符串,map entry用";"分割,key-value以":"分割<br>
   * 例子: "key1:value1;key2:value2"
   *
   * @param value
   * @return
   */
  protected static Map<String, String> parseMap(String value) {
    return ParseArg.parseMap(value);
  }

  /**
   * 将字符串解析为map,map entry用entrySplit分割,key-value以keySplit分割
   *
   * @param value
   * @param entrySplit
   * @param keySplit
   * @return
   */
  protected static Map<String, String> parseMap(String value, String entrySplit, String keySplit) {
    return ParseArg.parseMap(value, entrySplit, keySplit);
  }

  /**
   * 解析json对象
   *
   * @param <T>
   * @param clazz
   * @param json
   * @return
   */
  protected static <T> T paserJson(Class<T> clazz, String json) {
    return ParseArg.paserJson(clazz, json);
  }
}
TOP

Related Classes of org.jtester.fit.fixture.DtoPropertyFixture

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.