package com.tcs.wenrgise.util.common;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class FWXMLUtility {
  private static boolean bReverseOrderAttr;
  
  private static String timerClassName;
  
  private static final String LINESEPARATOR = "\n";
  
  static {
    try {
      Class cTempClass = Class.forName("com.tcs.wenrgise.util.common.FWXMLUtilitySequence");
      Field[] fFieldArray = cTempClass.getDeclaredFields();
      if (fFieldArray[0].getName().equals("ATTRIBUTE1")) {
        bReverseOrderAttr = false;
      } else {
        bReverseOrderAttr = true;
      } 
    } catch (Exception exception) {}
  }
  
  public static void setTimerClassName(String timerClassName_) {
    timerClassName = timerClassName_;
  }
  
  public static Object xmlToObject(String className, String sFileName) throws Exception {
    String methodName = "xmlToObject";
    FWSAXParser handler = null;
    InputSource aSource = null;
    SAXParser parser = null;
    FileReader aFileReader = null;
    try {
      Class c = Class.forName(className);
      Object objFinal = c.newInstance();
      String sPackage = getPackage(className);
      parser = null;
      try {
        parser = new SAXParser();
      } catch (Exception e) {
        e.printStackTrace();
        parser = null;
        System.err.println(String.valueOf(String.valueOf("error: Unable to instantiate parser(").concat(String.valueOf(parser))).concat(String.valueOf(")")));
        return null;
      } 
      handler = new FWSAXParser();
      handler.setObject(objFinal);
      handler.setPackage(sPackage);
      parser.setContentHandler(handler);
      aFileReader = new FileReader(sFileName);
      aSource = new InputSource(aFileReader);
      parser.parse(aSource);
      aSource = null;
      parser = null;
      return handler.getFinalObject();
    } catch (Throwable e) {
      aSource = null;
      parser = null;
      throw new Exception(e.getMessage());
    } finally {
      if (null != aFileReader) {
        aFileReader.close();
        aFileReader = null;
      } 
      aSource = null;
      parser = null;
    } 
  }
  
  public static void display(Object obj) throws Exception {
    if (obj == null)
      return; 
    Method[] mList = obj.getClass().getMethods();
    if (mList != null)
      for (int i = 0; i < mList.length; i++) {
        String methodName = mList[i].getName();
        if (methodName.startsWith("get_")) {
          Object objRet = null;
          try {
            objRet = mList[i].invoke(obj, null);
          } catch (Exception e) {}
          Class retClass = mList[i].getReturnType();
          if (retClass.getName().equals("java.lang.String")) {
            System.out.println(String.valueOf(String.valueOf(String.valueOf(String.valueOf(obj.getClass().getName()).concat(String.valueOf(":"))).concat(String.valueOf(methodName))).concat(String.valueOf("="))).concat(String.valueOf(objRet)));
          } else if (retClass.getName().equals("java.util.ArrayList")) {
            if (objRet != null) {
              ArrayList aList = (ArrayList)objRet;
              for (int j = 0; j < aList.size(); j++) {
                if (aList.get(j) instanceof String) {
                  System.out.println(String.valueOf(String.valueOf(String.valueOf(String.valueOf(String.valueOf(String.valueOf(obj.getClass().getName()).concat(String.valueOf(":"))).concat(String.valueOf(methodName))).concat(String.valueOf("["))).concat(String.valueOf(j))).concat(String.valueOf("]="))).concat(String.valueOf(aList.get(j))));
                } else {
                  display(aList.get(j));
                } 
              } 
            } 
          } else {
            display(objRet);
          } 
        } 
      }  
  }
  
  private static String getPackage(String classWithPackage) {
    if (classWithPackage == null)
      return ""; 
    int intLastIndexOfDot = classWithPackage.lastIndexOf(".");
    if (intLastIndexOfDot == -1)
      return ""; 
    return classWithPackage.substring(0, intLastIndexOfDot + 1);
  }
  
  private static String getClassNameWithoutPackage(String sClassNameWithPackage) {
    if (null == sClassNameWithPackage)
      return ""; 
    int indexOfDot = sClassNameWithPackage.lastIndexOf(".");
    if (indexOfDot != -1 && indexOfDot < sClassNameWithPackage.length())
      return sClassNameWithPackage.substring(indexOfDot + 1, sClassNameWithPackage.length()); 
    return sClassNameWithPackage;
  }
  
  public static String objectToXSD(String sClassName) throws Exception {
    Class cClass = Class.forName(sClassName);
    Object objIn = cClass.newInstance();
    String sClassNameWithoutPackage = getClassNameWithoutPackage(sClassName);
    String sPackageName = getPackage(sClassName);
    String sXSD = "";
    int level = 0;
    sXSD = String.valueOf(sXSD).concat(String.valueOf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("\n"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\">"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("\n"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf(String.valueOf(String.valueOf(String.valueOf(getSpaces(level + 1)).concat(String.valueOf("<xs:element name=\""))).concat(String.valueOf(sClassNameWithoutPackage))).concat(String.valueOf("\">"))));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("\n"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf(String.valueOf(getSpaces(level + 2)).concat(String.valueOf("<xs:complexType>"))));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("\n"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf(String.valueOf(getSpaces(level + 3)).concat(String.valueOf("<xs:sequence>"))));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("\n"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf(objectToXSDInternal(objIn, sPackageName, level + 3)));
    sXSD = String.valueOf(sXSD).concat(String.valueOf(String.valueOf(getSpaces(level + 3)).concat(String.valueOf("</xs:sequence>"))));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("\n"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf(String.valueOf(getSpaces(level + 2)).concat(String.valueOf("</xs:complexType>"))));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("\n"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf(String.valueOf(getSpaces(level + 1)).concat(String.valueOf("</xs:element>"))));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("\n"));
    sXSD = String.valueOf(sXSD).concat(String.valueOf("</xs:schema>"));
    return sXSD;
  }
  
  private static String objectToXSDInternal(Object objIn, String sPackageName, int level) throws Exception {
    if (null == objIn)
      return ""; 
    String sXML = "";
    Class cIn = objIn.getClass();
    String sClassName = cIn.getName();
    if (sClassName.equals("java.util.ArrayList")) {
      ArrayList aList = (ArrayList)objIn;
      for (int i = 0; i < aList.size(); i++) {
        Object obj = aList.get(i);
        sXML = String.valueOf(sXML).concat(String.valueOf(objectToXSDInternal(obj, sPackageName, level)));
      } 
    } else {
      if (sClassName.equals("java.lang.String"))
        return objIn.toString(); 
      Field[] fFieldArray = cIn.getDeclaredFields();
      for (int i = 0; i < fFieldArray.length; i++) {
        Field aField = fFieldArray[i];
        String sFieldName = aField.getName();
        Class cType = aField.getType();
        String sTagName = getTagName(sFieldName);
        String sMethodName = String.valueOf("get").concat(String.valueOf(sFieldName));
        Method m = cIn.getMethod(sMethodName, null);
        Class cReturnType = m.getReturnType();
        if (cReturnType.getName().equals("java.util.ArrayList")) {
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(String.valueOf(String.valueOf(getSpaces(level + 1)).concat(String.valueOf("<xs:element name=\""))).concat(String.valueOf(sTagName))).concat(String.valueOf("\" maxOccurs=\"unbounded\">"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 2)).concat(String.valueOf("<xs:complexType>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 3)).concat(String.valueOf("<xs:sequence>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          Class cRetType = Class.forName(getClassNameWithPackage(sTagName, sPackageName));
          Object objRet = cRetType.newInstance();
          sXML = String.valueOf(sXML).concat(String.valueOf(objectToXSDInternal(objRet, sPackageName, level + 3)));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 3)).concat(String.valueOf("</xs:sequence>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 2)).concat(String.valueOf("</xs:complexType>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 1)).concat(String.valueOf("</xs:element>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
        } else if (cReturnType.getName().equals("java.lang.String")) {
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(String.valueOf(String.valueOf(getSpaces(level + 1)).concat(String.valueOf("<xs:element name=\""))).concat(String.valueOf(sTagName))).concat(String.valueOf("\" type=\"xs:string\" minOccurs=\"0\">"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 1)).concat(String.valueOf("</xs:element>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
        } else {
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(String.valueOf(String.valueOf(getSpaces(level + 1)).concat(String.valueOf("<xs:element name=\""))).concat(String.valueOf(sTagName))).concat(String.valueOf("\" minOccurs=\"0\">"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 2)).concat(String.valueOf("<xs:complexType>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 3)).concat(String.valueOf("<xs:sequence>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          Object objRet = cReturnType.newInstance();
          sXML = String.valueOf(sXML).concat(String.valueOf(objectToXSDInternal(objRet, sPackageName, level + 3)));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 3)).concat(String.valueOf("</xs:sequence>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 2)).concat(String.valueOf("</xs:complexType>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
          sXML = String.valueOf(sXML).concat(String.valueOf(String.valueOf(getSpaces(level + 1)).concat(String.valueOf("</xs:element>"))));
          sXML = String.valueOf(sXML).concat(String.valueOf("\n"));
        } 
      } 
    } 
    return sXML;
  }
  
  public static String objectToXML(Object objIn) throws Exception {
    String methodName = "objectToXML";
    try {
      StringBuffer sXMLBuffer = new StringBuffer();
      sXMLBuffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
      if (objIn == null)
        return sXMLBuffer.toString(); 
      sXMLBuffer.append("\n");
      String sClassName = objIn.getClass().getName();
      String sClassNameWithoutPackage = getClassNameWithoutPackage(sClassName);
      sXMLBuffer.append("<").append(sClassNameWithoutPackage).append(">");
      sXMLBuffer.append("\n");
      sXMLBuffer.append(objectToXMLInternal(objIn, 0));
      sXMLBuffer.append("</").append(sClassNameWithoutPackage).append(">");
      return sXMLBuffer.toString();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {}
    return null;
  }
  
  private static StringBuffer objectToXMLInternal(Object objIn, int level) throws Exception {
    if (null == objIn)
      return new StringBuffer(); 
    StringBuffer sXMLBuffer = new StringBuffer();
    Class cIn = objIn.getClass();
    String sClassName = cIn.getName();
    if (sClassName.equals("java.util.ArrayList")) {
      ArrayList aList = (ArrayList)objIn;
      if (aList.size() > 0)
        if (bReverseOrderAttr) {
          for (int i = aList.size() - 1; i >= 0; i--) {
            Object obj = aList.get(i);
            if (obj != null) {
              String sTempClassName = obj.getClass().getName();
              if (sTempClassName.equals("java.lang.String")) {
                sXMLBuffer.append(objectToXMLInternal(obj, level + 1));
              } else {
                String sClassNameWithoutPackage = getClassNameWithoutPackage(sTempClassName);
                sXMLBuffer.append(getSpaces(level + 1)).append("<").append(sClassNameWithoutPackage).append(">");
                sXMLBuffer.append("\n");
                sXMLBuffer.append(objectToXMLInternal(obj, level + 1));
                sXMLBuffer.append(getSpaces(level + 1)).append("</").append(sClassNameWithoutPackage).append(">");
                sXMLBuffer.append("\n");
              } 
            } 
          } 
        } else {
          for (int i = 0; i < aList.size(); i++) {
            Object obj = aList.get(i);
            if (obj != null) {
              String sTempClassName = obj.getClass().getName();
              if (sTempClassName.equals("java.lang.String")) {
                sXMLBuffer.append(objectToXMLInternal(obj, level + 1));
              } else {
                String sClassNameWithoutPackage = getClassNameWithoutPackage(sTempClassName);
                sXMLBuffer.append(getSpaces(level + 1)).append("<").append(sClassNameWithoutPackage).append(">");
                sXMLBuffer.append("\n");
                sXMLBuffer.append(objectToXMLInternal(obj, level + 1));
                sXMLBuffer.append(getSpaces(level + 1)).append("</").append(sClassNameWithoutPackage).append(">");
                sXMLBuffer.append("\n");
              } 
            } 
          } 
        }  
    } else {
      if (sClassName.equals("java.lang.String")) {
        String sTempStr = objIn.toString();
        if (sTempStr.startsWith("<![CDATA"))
          return new StringBuffer(sTempStr); 
        return new StringBuffer(encodeXML(sTempStr));
      } 
      Field[] fFieldArray = cIn.getDeclaredFields();
      if (bReverseOrderAttr) {
        for (int i = fFieldArray.length - 1; i >= 0; i--) {
          Field aField = fFieldArray[i];
          String sFieldName = aField.getName();
          Class cType = aField.getType();
          String sTagName = getTagName(sFieldName);
          String sMethodName = String.valueOf("get").concat(String.valueOf(sFieldName));
          Method m = null;
          try {
            m = cIn.getMethod(sMethodName, null);
          } catch (Exception e) {}
          Object objRet = m.invoke(objIn, null);
          String sReturnClassName = "";
          if (objRet != null) {
            sReturnClassName = objRet.getClass().getName();
            if (sReturnClassName.equals("java.util.ArrayList")) {
              ArrayList aList = (ArrayList)objRet;
              if (aList.size() > 0) {
                Object objTemp = aList.get(0);
                if (objTemp instanceof String) {
                  sXMLBuffer.append(getSpaces(level + 1)).append("<").append(sTagName).append(">");
                  sXMLBuffer.append(objectToXMLInternal(objRet, level + 1));
                  sXMLBuffer.append("</").append(sTagName).append(">");
                  sXMLBuffer.append("\n");
                } else {
                  sXMLBuffer.append(objectToXMLInternal(objRet, level));
                } 
              } 
            } else if (sReturnClassName.equals("java.lang.String")) {
              sXMLBuffer.append(getSpaces(level + 1)).append("<").append(sTagName).append(">");
              sXMLBuffer.append(objectToXMLInternal(objRet, level + 1));
              sXMLBuffer.append(String.valueOf(String.valueOf("</").concat(String.valueOf(sTagName))).concat(String.valueOf(">")));
              sXMLBuffer.append("\n");
            } else {
              sXMLBuffer.append(getSpaces(level + 1)).append("<").append(sTagName).append(">");
              sXMLBuffer.append("\n");
              sXMLBuffer.append(objectToXMLInternal(objRet, level + 1));
              sXMLBuffer.append(getSpaces(level + 1)).append(String.valueOf("</").concat(String.valueOf(sTagName))).append(">");
              sXMLBuffer.append("\n");
            } 
          } 
        } 
      } else {
        for (int i = 0; i < fFieldArray.length; i++) {
          Field aField = fFieldArray[i];
          String sFieldName = aField.getName();
          Class cType = aField.getType();
          String sTagName = getTagName(sFieldName);
          String sMethodName = String.valueOf("get").concat(String.valueOf(sFieldName));
          Method m = null;
          try {
            m = cIn.getMethod(sMethodName, null);
          } catch (Exception e) {}
          Object objRet = m.invoke(objIn, null);
          String sReturnClassName = "";
          if (objRet != null) {
            sReturnClassName = objRet.getClass().getName();
            if (sReturnClassName.equals("java.util.ArrayList")) {
              ArrayList aList = (ArrayList)objRet;
              if (aList.size() > 0) {
                Object objTemp = aList.get(0);
                if (objTemp instanceof String) {
                  sXMLBuffer.append(getSpaces(level + 1)).append("<").append(sTagName).append(">");
                  sXMLBuffer.append(objectToXMLInternal(objRet, level + 1));
                  sXMLBuffer.append("</").append(sTagName).append(">");
                  sXMLBuffer.append("\n");
                } else {
                  sXMLBuffer.append(objectToXMLInternal(objRet, level));
                } 
              } 
            } else if (sReturnClassName.equals("java.lang.String")) {
              sXMLBuffer.append(getSpaces(level + 1)).append("<").append(sTagName).append(">");
              sXMLBuffer.append(objectToXMLInternal(objRet, level + 1));
              sXMLBuffer.append("</").append(sTagName).append(">");
              sXMLBuffer.append("\n");
            } else {
              sXMLBuffer.append(getSpaces(level + 1)).append("<").append(sTagName).append(">");
              sXMLBuffer.append("\n");
              sXMLBuffer.append(objectToXMLInternal(objRet, level + 1));
              sXMLBuffer.append(getSpaces(level + 1)).append("</").append(sTagName).append(">");
              sXMLBuffer.append("\n");
            } 
          } 
        } 
      } 
    } 
    return sXMLBuffer;
  }
  
  private static String getTagName(String sFieldName) {
    if (sFieldName == null)
      return ""; 
    int indexOfUnderScore = sFieldName.indexOf("_");
    if (indexOfUnderScore == 0 && sFieldName.length() >= 2)
      return sFieldName.substring(1, sFieldName.length()); 
    return sFieldName;
  }
  
  private static String getClassNameWithPackage(String sTagName, String sPackageName) {
    if (sPackageName == null || sPackageName.trim().length() <= 0)
      return sTagName; 
    return String.valueOf(sPackageName).concat(String.valueOf(sTagName));
  }
  
  private static String getSpaces(int iCount) {
    String sRet = "";
    for (int i = 0; i < iCount; i++)
      sRet = String.valueOf(sRet).concat(String.valueOf("    ")); 
    return sRet;
  }
  
  public static String encodeXML(String strIn) {
    String[] xmlEncFrom = { "&", "\"", "<", ">" };
    String[] xmlEncTo = { "&amp;", "&quot;", "&lt;", "&gt;" };
    int idx = 0;
    if (strIn == null)
      return null; 
    StringBuffer strOut = new StringBuffer(strIn);
    StringBuffer strTemp = null;
    for (int i = 0; i < xmlEncFrom.length; i++) {
      idx = strOut.toString().indexOf(xmlEncFrom[i]);
      while (idx != -1) {
        strTemp = new StringBuffer();
        strTemp.append(strOut.substring(0, idx)).append(xmlEncTo[i]).append(strOut.substring(idx + xmlEncFrom[i].length()));
        strOut = strTemp;
        idx = strOut.toString().indexOf(xmlEncFrom[i], idx + xmlEncTo[i].length());
      } 
    } 
    return strOut.toString();
  }
  
  public static ArrayList validateXMLWithXSD(String xml, String schema) throws IOException, ParserConfigurationException, SAXException {
    try {
      SAXParserFactory parserFactory = SAXParserFactory.newInstance();
      parserFactory.setNamespaceAware(true);
      parserFactory.setValidating(true);
      parserFactory.setFeature("http://apache.org/xml/features/validation/schema", true);
      parserFactory.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
      SAXParser saxParser = parserFactory.newSAXParser();
      saxParser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", schema);
      InputSource is = new InputSource(new StringReader(xml));
      XMLValidationHandler handler = new XMLValidationHandler();
      saxParser.parse(is, handler);
      ArrayList aList = handler.getResults();
      return aList;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    } 
  }
  
  public static ArrayList validateXMLWithXSD(File file, String schema) throws IOException, ParserConfigurationException, SAXException {
    try {
      String sFileName = file.getAbsolutePath();
      SAXParserFactory parserFactory = SAXParserFactory.newInstance();
      parserFactory.setNamespaceAware(true);
      parserFactory.setValidating(true);
      parserFactory.setFeature("http://apache.org/xml/features/validation/schema", true);
      parserFactory.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
      SAXParser saxParser = parserFactory.newSAXParser();
      saxParser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", schema);
      InputSource is = new InputSource(sFileName);
      XMLValidationHandler handler = new XMLValidationHandler();
      saxParser.parse(is, handler);
      ArrayList aList = handler.getResults();
      return aList;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    } 
  }
}
