import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.util.HashMap;

import java.util.Set;


import org.ho.yaml.Yaml;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.support.ui.ExpectedCondition;

import org.openqa.selenium.support.ui.WebDriverWait;


import com.tc.util.DefinedException;

import com.tc.util.ReadProp;


/**

 * 传入文件名

 * @author yedeng

 *

 */

public class GetElementFromYaml{

/**

* yaml文件的名称

*/

private String yamlFile;

private HashMap> ml =new HashMap>();//map对象

public WebDriver driver;

/**

 * 多个页面共有的对象的yaml文件的内容

 */

private HashMap> extendLocator;

 

 

/**

* 传入文件yaml文件名称

* @param yamlFile1 需要读取的yaml文件名称

*/

public GetElementFromYaml(String yamlFile)

{      

   this.yamlFile=yamlFile;

       this.getYamlFile();

   }

       

                   /**

                    * 打开yaml文件,将文件的内容放入Map中

                    * @return

                    */

   @SuppressWarnings("unchecked")

   public HashMap> getYamlFile(){

 

 

       File f = new File("data/yaml/"+yamlFile + ".yaml");

       try {

        ml= Yaml.loadType(new FileInputStream(f.getAbsolutePath()), HashMap.class);

       

       }catch (FileNotFoundException

e) {

       //e.printStackTrace();

       throw new DefinedException("没找到"+yamlFile);

       }

       return ml;

   }

   

   

   

   /**

    * 存放多个页面公共的元素对象

    * @param fileName 多个页面都存在的公共元素对象的yaml文件

    */

   @SuppressWarnings("unchecked")

public void loadExtendLocator(String fileName){

   File f = new File("data/yaml/" +fileName + ".yaml");

           try {

               extendLocator= Yaml.loadType(new FileInputStream(f.getAbsolutePath()), HashMap.class);

               ml.putAll(extendLocator);

           }catch (FileNotFoundException

    e) {

               //e.printStackTrace();

               throw new DefinedException("没找到"+fileName);

           }

       }

   

   /**

    * value存在相同部分的处理

    * value:"//div[@id='%productId%']//div"  value:"//div[@id='%productId%']//input[@name='button']"

    * @param variable  相同部分的数据,如“productId”

    * @param value    名称

    */

    public void setLocatorVariableValue(String variable, String value){

          Set keys = ml.keySet();

           for(String key:keys){

                String v = ml.get(key).get("value").replaceAll("%"+variable+"%",value);

                ml.get(key).put("value",v);

           }

       }

   

   

   /**

    * 通过key和value获取By对象

    * @param type   

    * @param value

    * @return  

    */

   @SuppressWarnings("unused")

private By getBy(String type, String value){

   By by=null;

       if (type.equals("id"))

       {

              by= By.id(value);

          }

          if (type.equals("name"))

       {

              by= By.name(value);

          }

          if (type.equals("xpath"))

       {

              by= By.xpath(value);

          }

          if (type.equals("className"))

       {

              by= By.className(value);

          }

          if (type.equals("linkText"))

       {

              by= By.linkText(value);

          }

          else{

          throw new DefinedException(by+"的值不正确");

          }

          return by;

      }

   

   /**

    * 添加超时等待的方法

    * @param by

    * @return 

    */

   @SuppressWarnings("unused")

private WebElement watiForElement(final By by) {

      WebElement  element = null;

      int waitTime = Integer.parseInt(ReadProp.readprop("waittime", "Gloup"));

      try {element = new WebDriverWait(driver, waitTime).until(new ExpectedCondition() {

             public WebElement apply(WebDriver d) {

                          return d.findElement(by);

                      }

                  });

      }catch (Exception e) {

      throw new DefinedException(by.toString()+ "is not exist until " +waitTime);

      }

      return element;

  }

   

           /**

            * 去掉隐藏的对象,只显示displayed的元素对象

            * @param element

            * @return false

            */

   @SuppressWarnings("unused")

private boolean waitElementToBeDisplayed(final WebElement element) {

       boolean wait = false;

       if (element == null)

           return wait;

       try {

           wait = new WebDriverWait(driver, Integer.parseInt(ReadProp.readprop("waittime", "Gloup"))).until(new ExpectedCondition()

   

           public Boolean apply(WebDriver d) {

                                  return element.isDisplayed();

                       }

                   });

       }catch (Exception e) {

        throw new DefinedException(element.toString()+ "is not displayed");

       }

       return wait;

   }

   

   

   /**

    * 等待元素对象消失的方法

    * @param element

    * @return false

    */

   public boolean waitElementToBeNonDisplayed(final WebElement element) {

       boolean wait= false;

       if (element == null)

           return wait;

       try {

           wait = new WebDriverWait(driver, Integer.parseInt(ReadProp.readprop("waittime", "Gloup"))).until(new ExpectedCondition()

                    {

                       public Boolean apply(WebDriver d) {

                          return !element.isDisplayed();

                       }

                   });

       }catch (Exception

    e) {

        throw new DefinedException("Locator[" +element.toString() +"]is also displayed");

       }

       return wait;

   }

   

   /**

    * 组合方法,获取元素对象

    * @param key

    * @param wait

    * @return

    */

   @SuppressWarnings("unused")

private WebElement getLocator(String key,String[] replace, boolean wait) {

      WebElement element = null;

      

      if (ml.containsKey(key)){

          HashMap m = ml.get(key);

          String type = m.get("type");

          String value = m.get("value"); 

          if (replace != null){

         value = this.getLocatorString(value,replace);}

          By by = this.getBy(type,value);

          /**

           * 是否等待,等待页面元素的出现

           */

          if (wait) {

              element = this.watiForElement(by);

              boolean flag = this.waitElementToBeDisplayed(element);

              if (!flag){

              element = null;

              }               

              }

          /**

           * 不等待页面元素的出现

           */

          else {

              try {

                  element= driver.findElement(by);

              }catch (Exception e) {

                  element= null;

              }

          }

      }else

      throw new DefinedException("Locator " + key + "is not exist in " +yamlFile +".yaml");

      return element;

  } 

   

   

   /**

    * yaml参数化%s value的值为这种模式: value:"%s%s"

    * @param locatorString

    * @param ss

    * @return

    */

   @SuppressWarnings("unused")

private String

   getLocatorString(String locatorString, String[] ss) {

      for (String s : ss) {

          locatorString = locatorString.replaceFirst("%s", s);

      }

      return locatorString;

  }

    

   /**

    * 无参数化不进行等待获取元素对象

    * @param key

    * @return WebElement对象

    */

   public WebElement getElementNoWait(String key) {

    return this.getLocator(key,null,false);

  }

   /**

    *   有参数化不进行等待获取元素对象 

    * @param key

    * @param replace 参数

    * @return WebElement对象

    */

   public WebElement getElementNoWait(String key,String[] replace) {

    return this.getLocator(key,replace,false);

  }

   

   

   

   /**

    * 无参数化通过等待获取元素对象

    * @param key 

    * @return WebElement对象

    */

   public WebElement getElement(String key) {

    return this.getLocator(key,null,false);

      }

   

   /**

    * 有参数化通过等待获取元素对象

    * @param key

    * @param replace

    * @return WebElement对象

    */

   public WebElement getElement(String key,String[] replace) {

    return this.getLocator(key,replace,false);

      }

    

   }