Package com.baidu.qa.service.test.template

Source Code of com.baidu.qa.service.test.template.VariableGenerator

package com.baidu.qa.service.test.template;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;
import java.util.Set;

import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.junit.Assert;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.baidu.qa.service.test.dto.Constant;
import com.baidu.qa.service.test.util.CCJSONUtils;
import com.baidu.qa.service.test.util.DateTimeUtil;

import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.Template;

/**
*
* @author cuican
* @date 2013-8-9
* @classname VariableGenerator
* @version 1.0.0
* @desc 模板相关的操作,用以对tpl文件中的${}变量做赋值替换
*/
public class VariableGenerator {
 
  private static Logger log = Logger.getLogger(VariableGenerator.class);
 
  private static Map<String, VariableGenerator> all = new HashMap<String, VariableGenerator>();
 
  private Map props = null;
 
  public Map getProps() {
    return props;
  }

  public void setProps(Map props) {
    this.props = props;
  }


  private VariableGenerator parent = null;
 
 
  public VariableGenerator(Map map){
    props = map;
  }
 
  /**
   * Factory method, key is the .properties full filename of the case
   * @param filename
   * @return VariableGenerator
   */
  public static VariableGenerator getGenerator(String filename){
    if (all.get(filename) == null){
      all.put(filename, new VariableGenerator(filename));
    }
    return all.get(filename);
  }
 
 
  private VariableGenerator(String filename, VariableGenerator parent){
    this(filename);
    setParent(parent);
  }
 
  private VariableGenerator(){
  }
 
  private VariableGenerator(String filename){
    init(filename);
  }

  private void init(String filename) {
    //2012-10-16 merge the properties file in config.properties, mapping the key-value 'var=foo,bar,...'
    Properties props = new Properties();
    try {
      props.load(new FileInputStream(filename));
    } catch (FileNotFoundException e) {
      log.warn("the file " + filename + " does not exist. if there is no need for this file, please ignore this warning.");
      log.warn(e.getMessage());
    } catch (IOException e) {
      log.error(e.getMessage(), e);
    }
    this.props = new HashMap();
    String value = props.getProperty("var");
    if(value == null || "".equals(value)){
      return;
    }
    try {
      initWithVarList(value);
    } catch (Exception e) {
      log.error("there is properly something wrong at the item 'var' in the file '" + filename + "' anyway, please check." );
      log.error(e.getMessage(), e);
    }
  }

  private void initWithVarList(String value) {
    String[] vars = value.split(",");
    for (String var : vars) {
       if(!(var == null) && !("".equals(var))){
         if(var.contains("=")){
           String[] temp=var.split("=");
           if(temp!=null&&temp.length==2&&temp[1].trim().equals("random")){           
               this.props.put(temp[0], String.valueOf(DateTimeUtil.nextLong()));
          }       
          
           else if(temp!=null&&temp.length==1){
              this.props.put(temp[0], "");
           }
           else {
             log.error("wrong var set:"+value);
           }
         }
         else{
            this.props.put(var, "");

         }
      }
    }
  }


  /**
   * if one case is in a suit, set its parent with the suit's generator
   *
   * @param parent
   */
  public void setParent(VariableGenerator parent) {
    this.parent = parent;
  }

  /**
   * get its parent Object
   *
   * @return
   */
  public VariableGenerator getParent() {
    return parent;
  }
 
  public void add2Map(Map map){
    this.props.putAll(map);
  }
 
  public Object removeFromMap(Object key){
    return this.props.remove(key);
  }
 
  public void processProps(File response){
    processProps(response, null);
  }
  /**
   * with the response file, fulfill the .properties's value
   *
   * @param response
   */
  public void processProps(File response, String type){

    if(this.parent != null){
      this.parent.processProps(response,type);
    }
   
    String basename = response.getName().split("\\.")[0];
   

    Set<Object> keys = props.keySet();
    for (Object key : keys) {
      if(((String)key).split("\\.")[0].equals(basename)){
        String value = null;
        if(Constant.FILE_TYPE_XML.equals(type)){
          value = searchFromXml((String)key, response);
        }else{
          value = searchFromJson((String)key, response);
        }
        if(value == null){
          log.warn("there is no field '" + key + "' found in the response: " + response);
        }
        props.put(key, value == null ? "" : value);
      }
    }
  }


  private String searchFromXml(String key, File response) {
   
    org.w3c.dom.Document doc = null;
    XPath xpath = null;
   
    // 将XML文档加载到DOM Document对象中
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true); // never forget this!
    DocumentBuilder builder = null;
    try {
      builder = factory.newDocumentBuilder();
      doc = builder.parse(new FileInputStream(response));
    } catch (Exception e) {
      log.error("parse the xml failed.");
      log.error(e.getMessage(), e);
      Assert.fail("parse the xml failed.");
    }
    // };xmlFilename);//"src/result.xml");
    // 创建 XPathFactory
    XPathFactory pathFactory = XPathFactory.newInstance();
    // 使用XPathFactory工厂创建 XPath 对象
    xpath = pathFactory.newXPath();
    xpath.setNamespaceContext(new NamespaceContext() {
      public String getNamespaceURI(String prefix) {
        if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) {
          return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
        } else if (prefix.equals("soap")) {
          return "http://schemas.xmlsoap.org/soap/envelope/";
        } else if (prefix.equals("ns1")) {
          return "http://api.baidu.com/sem/common/v2";
        } else if (prefix.equals("ns2")) {
          return "https://api.baidu.com/sem/sms/v2";
        } else if (prefix.equals("ns4")) {
          return "https://api.baidu.com/sem/nms/v2";
        }
        return XMLConstants.NULL_NS_URI;
      }
      public String getPrefix(String namespaceURI) {
        return null;
      }
      public Iterator getPrefixes(String namespaceURI) {
        return null;
      }
    });
    // 使用XPath对象编译XPath表达式
    XPathExpression pathExpression = null;
    String subKey = ((String)key).split("\\.")[1];
    String searchKey = "//" + subKey + "/text()";
    try {
      pathExpression = xpath.compile(searchKey);
    } catch (XPathExpressionException e) {
      log.error("the xpath ` " + searchKey + " ` is invalid.");
      log.error(e.getMessage(), e);
      Assert.fail("the xpath ` " + searchKey + " ` is invalid.");
    }
    // 计算 XPath 表达式得到结果
    Object result = null;
    try {
      result = pathExpression.evaluate(doc, XPathConstants.NODESET);
    } catch (XPathExpressionException e) {
      log.error("the xpath ` " + searchKey + " ` is invalid.");
      log.error(e.getMessage(), e);
      Assert.fail("the xpath ` " + searchKey + " ` is invalid.");
    }
    // 节点集node-set转化为NodeList
    // 将结果强制转化成 DOM NodeList
    org.w3c.dom.NodeList nodes = (NodeList) result;
   
    if(nodes.getLength() == 0){
      log.error("nothing was found by the xpath ` " + searchKey + " `.");
      Assert.fail("nothing was found by the xpath ` " + searchKey + " `.");
    }else if(nodes.getLength() > 1){
      log.error("more than 1 items were found by the xpath ` " + searchKey + " `.");
      Assert.fail("more than 1 items were found by the xpath ` " + searchKey + " `.");
    }
   
    Node theOne = nodes.item(0);
    if (theOne == null) {
      return "";
    }
    String itemValue = theOne.getNodeValue().trim();
    return itemValue;
  }


  private String searchFromJson(String key, File response) {
    String subKey = ((String)key).split("\\.")[1];
    Scanner in = null;
    try {
      in = new Scanner(response);
    } catch (FileNotFoundException e) {
      log.error("the file '" + response + "' does not exist.");
      log.error(e.getMessage(), e);
    }
    StringBuilder sb = new StringBuilder();
    while(in.hasNextLine()){
      sb.append(in.nextLine());
    }
    String allLines = sb.toString();
   
    JSONObject jobj = JSONObject.fromObject((allLines == null || allLines.equals("")) ? "{}" 
                : allLines)
   
    String value = CCJSONUtils.getFirst(jobj, subKey);
   
    return value;
  }


  /**
   *  process the template , generate the real request file
   * @param template
   * @return
   */
  public File processTemplate(File template) {
    return processTemplate(template, null);
  }
 
  /**
   *  process the template with customed key-values, generate the real request file
   * @param template
   * @return
   */
  public File processTemplate(File template, Map keyValue) {
    Configuration cfg = new Configuration();
    File path = template.getParentFile();
    String tName = template.getName();
    int lastDot = tName.lastIndexOf('.');
//    String realName = tName.split("\\.")[0];
    String realName = tName.substring(0, lastDot);
    //put it to ${case_path}/Output/
    File output = new File(path.getParent() + "/" + Constant.FILENAME_OUTPUT);
    if(!output.exists()){
      output.mkdir();
      log.info("mkdir " + output);
    }
    File real = new File(output + "/" + realName);
    //delete if exists
    if(real.exists()){
      log.info("delete existed filed first.");
      real.delete();
    }
    Writer out = null;
    try {
     
      cfg.setDirectoryForTemplateLoading(path);
      cfg.setObjectWrapper(new BeansWrapper());
      Template temp = cfg.getTemplate(tName);
      out = new PrintWriter(real);

      if (this.parent != null) {
        log.info("need to putall parent.props");
        this.props.putAll(this.parent.props);
      }
      if (keyValue != null && !keyValue.isEmpty()){
        log.info("need to putall customed vars");
        this.props.putAll(keyValue);
      }
      temp.process(makeLevelMap(this.props), out);
      out.flush();
    } catch (Exception e) {
      log.error("processing template errors, please check");
      log.error(e.getMessage(), e);
    }finally{
      try {
        out.close();
      } catch (IOException e) {
      }
    }

    return real;
  }
 
 
 
  /**
   * kengdie de freemaker will parse the 'a.b=xxx' as map A with a map B, B has a key that value is b.
   * so this method will make a plain map to a level-relationship-map.
   * @param props
   * @return
   */
  private Map makeLevelMap(Map props){
    Map level = new HashMap();
    Set<Object> keys = props.keySet();
    for (Object key : keys) {
      String k = (String)key;
      if(k.contains(".")){
        String[] two = k.split("\\.");
        if(level.get(two[0]) == null){
          level.put(two[0], new HashMap());
        }
        ((Map)(level.get(two[0]))).put(two[1], props.get(key));
      }else{
        level.put(key, props.get(key));
      }
    }
   
    return level;
  }
 
 
  public static void main(String[] args) throws FileNotFoundException, IOException {
   
    File prop = new File("E:\\cctest.properties");
    /*
     * E:\\cctest.properties  content:
     *
     * addAdgroup.adgroupId=
     *
     */
   
    File res = new File("E:\\addAdgroup.response");
    /*
     * E:\\addAdgroup.response  content:
     *
     * {"jsonrpc":"2.0",
     * "result":{
     *   "data":[
     *     {"adgroupId":131977020,
     *     "campaignId":21573518,
     *     "adgroupName":"ccc",
     *     "maxPrice":88.0,
     *     "pause":false,
     *     "negativeWords":[],
     *     "exactNegativeWords":[],
     *     "status":31,
     *     "opt":null}
     *     ],
     * "errors":[],
     * "options":{
     *   "total":1,
     *   "success":1}
     * },
     * "id":"0"}
     *
     */
   
    File template = new File("E:\\template.cc.ftl");
    /*
     * E:\\template.cc.ftl  content:
     *
     * {"opUser":111,"dataUser":222},{"creativeType":1, "tableId":0, "tablePositionId":0, "number":1, "adgroupId":${addAdgroup.adgroupId},{"options":{}}
     *
     */
    VariableGenerator vg = VariableGenerator.getGenerator(prop.getAbsolutePath());
   
    vg.processProps(res);
   
//    System.out.println(vg.props.get("addAdgroup.adgroupId"));
   
    vg.processTemplate(template);
    /*
     * expect: E:\\Output\\template.cc
     *
     * {"opUser":111,"dataUser":222},{"creativeType":1, "tableId":0, "tablePositionId":0, "number":1, "adgroupId":131977020,{"options":{}}
     *
     */
   
   
   
//    VariableGenerator vg = new VariableGenerator();
//   
//    Properties a = vg.getProps();
//   
//    for (Object obj : a.keySet()){
//      System.out.println(obj + "=" + a.getProperty((String)obj));
//    }
//    a.put("ccc", "99999");
//    a.store(new FileOutputStream("src/variable.propertirs"), null);
     
  }
 
}
TOP

Related Classes of com.baidu.qa.service.test.template.VariableGenerator

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.