/*
 * LIUS - Lucene Index Update and Search
 * http://sourceforge.net/projects/lius/
 *
 * Copyright (c) 2004, Laval University Library.  All rights reserved.
 *
 * This program is a free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package ca.ulaval.bibl.lius.config;


import org.jdom.*;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Collection;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.*;
import org.jdom.Element;

import ca.ulaval.bibl.lius.config.LiusConfig;
import ca.ulaval.bibl.lius.config.LiusField;
import ca.ulaval.bibl.lius.index.XML.XmlFileIndexer;

/**
 * Classe permettant de parser le fichier de configuration.
 * <br/><br/>
 * Class for parsing configuration file.
 * @author Rida Benjelloun (rida.benjelloun@bibl.ulaval.ca)
 */
public class LiusConfigBuilder {
  private XmlFileIndexer xi = new XmlFileIndexer();
  private LiusConfig xc = null;
  private static LiusConfigBuilder liusConfigBuilder;

  public static LiusConfigBuilder getSingletonInstance() {
    if (liusConfigBuilder == null)
      liusConfigBuilder = new LiusConfigBuilder();
    return liusConfigBuilder;
  }

  protected Document parse(String file) {
    org.jdom.Document xmlDoc = new org.jdom.Document();
    try {
      SAXBuilder builder = new SAXBuilder();
      xmlDoc = builder.build(new File(file));
    }
    catch (JDOMException e) {
      System.out.println(e.getMessage());
    }
    catch (IOException e) {
      System.out.println(e.getMessage());
    }
    return xmlDoc;
  }

  /**
   * Méthode permettant de parser le fichier de configuration et de
   * retourner un objet de type LiusConfig.
   * <br/><br/>
   * Method for parsing the configuration file, returns a LiusConfig object.
   */
  public LiusConfig getLiusConfig(String xmlConfigFile) {

    if (xc == null) {
      Document doc = parse(xmlConfigFile);
      xc = new LiusConfig();
      populateLiusConfig(doc, xc);
    }
    else {
      return xc;
    }
    return xc;
  }



  private void populateLiusConfig(Document doc, LiusConfig xc) {
    xc.setAnalyzer(getAnlyzerClassString(doc));
    xc.setStopWord(getStopWordValue(doc));
    xc.setValueCreateIndex(getCreateIndexValue(doc));
    xc.setMergeFactor(getMergeFactorValue(doc));
    xc.setMaxMergeDocs(getMaxMergeDocs(doc));
    xc.setOptimizeValue(getOptimizeValue(doc));
    xc.setXmlFileFields(getXmlFileFields(doc));
    xc.setXmlNodesFields(getXmlNodesFields(doc));
    xc.setDisplayFields(getDisplayFields(doc));
    xc.setElemSearch(getQueryType(doc, xc));
    xc.setJavaBeansFields(getJavaBeansFields(doc));
    xc.setPdfFields(getPdfFields(doc));
    xc.setMsWordFields(getMsWordFields(doc));
    xc.setHtmlFields(getHtmlFields(doc));
    xc.setMixteIndexingElements(getMixteIndexingElements(doc));
    xc.setRtfFields(getRtfFields(doc));
    xc.setExcelFields(getExcelFields(doc));
    xc.setTxtFields(getTxtFields(doc));
    xc.setOOFields(getOOFields(doc));
    xc.setPPTFields(getPPTFields(doc));

  }

  /**
   * Méthode permettant de récupérer l'analyseur à partir du fichier XML.
   * <br/><br/>
   * Method for getting the analyser from XML file.
   */
  public String getAnlyzerClassString(Document doc) {
    String className = null;
    try {
      Attribute classN = (Attribute) XPath.selectSingleNode(doc,
          "//properties/analyzer/@class");
      if (classN != null)
        className = classN.getValue();
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }
    return className;
  }

  /**
   * Méthode permettant de récupérer la valeur de création de l'index
   * (true, false ou auto) dans le fichier de configuration.
   * <br/><br/>
   * Method for getting the creation value of index (true, false, auto) in
   * the configuration file.
   */
  public String getCreateIndexValue(Document doc) {
    String createIndexValue = null;
    try {
      Attribute createIndexV = (Attribute) XPath.selectSingleNode(doc,
          "//properties/createIndex/@value");
      createIndexValue = createIndexV.getValue();
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return createIndexValue;
  }

  /**
       * Méthode permettant de récupérer la valeur du mergeFactor dans le fichier de
   * configuration.
   * <br/><br/>
   * Method for getting mergeFactor value in configuration file.
   */
  public String getMergeFactorValue(Document doc) {
    String mergeFactorValue = "";
    try {
      Attribute mergeFactor = (Attribute) XPath.selectSingleNode(doc,
          "//indexWriterProperty/@mergeFactor");
      if (mergeFactor != null)
        mergeFactorValue = mergeFactor.getValue();
      else
        return mergeFactorValue = null;
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }
    return mergeFactorValue;
  }

  /**
   * Méthode permettant de récupérer la valeur du maxMergeDocs dans le fichier
   * de configuration.
   * <br/><br/>
   * Method for getting the maxMergeDocs value in the configuration file.
   */
  public String getMaxMergeDocs(Document doc) {
    String maxMergeDocsValue = "";
    try {
      Attribute maxMergeDocs = (Attribute) XPath.selectSingleNode(doc,
          "//indexWriterProperty/@maxMergeDocs");
      if (maxMergeDocs != null)
        maxMergeDocsValue = maxMergeDocs.getValue();
      else
        return maxMergeDocsValue = null;
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }
    return maxMergeDocsValue;

  }

  /**
   * Méthode permettant de récupérer la valeur d'optimize dans le fichier de
   * configuration.
   * <br/><br/>
   * Method for getting the optimize value in the configuration file.
   */
  public String getOptimizeValue(Document doc) {
    String optimizeValue = "";
    try {
      Attribute optimize = (Attribute) XPath.selectSingleNode(doc,
          "//indexWriterProperty/@optimize");
      if (optimize != null)
        optimizeValue = optimize.getValue();
      else
        return optimizeValue = null;
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }
    return optimizeValue;

  }

  /**
   * Méthode permettant de retourner une collection d'objets LiusField à partir
   * du fichier XML si l'élément "xmlFile" existe.
   * <br/><br/>
   * Method returning a Collection of LiusField objects from the XML file if
   * the element xmlFile exists.
   */

  private Collection getXmlFileFields(Document doc) {
    Collection res = new ArrayList();
    HashMap hm = new HashMap();
    try {
      List ls = XPath.selectNodes(doc, "//xmlFile");
      Iterator i = ls.iterator();
      while (i.hasNext()) {
        Collection coll = new ArrayList();
        Element elemNode = (Element) i.next();
        List fieldList = XPath.selectNodes(elemNode, "luceneField");
        for (int j = 0; j < fieldList.size(); j++) {
          LiusField lf = new LiusField();
          Element elem = (Element) fieldList.get(j);
          if (elem.getAttribute("name") != null)
            lf.setName(elem.getAttributeValue("name"));
          if (elem.getAttribute("xpathSelect") != null)
            lf.setXpathSelect(elem.getAttributeValue("xpathSelect"));
          if (elem.getAttribute("type") != null)
            lf.setType(elem.getAttributeValue("type"));
          if (elem.getAttribute("ocurSep") != null)
            lf.setOcurSep(elem.getAttributeValue("ocurSep"));
          if (elem.getAttribute("dateFormat") != null)
            lf.setDateFormat(elem.getAttributeValue("dateFormat"));
          coll.add(lf);
        }

        hm.put(elemNode.getAttributeValue("ns"), coll);

      }
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }
    res.add(hm);
    return res;
  }

  /**
   * Méthode permettant de retourner un HashMap contenant comme clé
   * l'expression XPATH du noeud à indexer, et comme valeur une collection
   * d'objets de type LiusField.
   * <br/><br/>
   * Method returning an HashMap which key containing the XPath expression for
   * the node to index and for value a Collection of LiusField objects.
   */
  private HashMap getXmlNodesFields(Document doc) {
    HashMap hm = new HashMap();
    try {
      List ls = XPath.selectNodes(doc, "//node");
      Iterator i = ls.iterator();
      while (i.hasNext()) {
        Collection coll = new ArrayList();
        Element elemNode = (Element) i.next();
        List fieldList = XPath.selectNodes(elemNode, "luceneField");
        for (int j = 0; j < fieldList.size(); j++) {
          LiusField lf = new LiusField();
          Element elem = (Element) fieldList.get(j);
          if (elem.getAttribute("name") != null)
            lf.setName(elem.getAttributeValue("name"));
          if (elem.getAttribute("xpathSelect") != null)
            lf.setXpathSelect(elem.getAttributeValue("xpathSelect"));
          if (elem.getAttribute("type") != null)
            lf.setType(elem.getAttributeValue("type"));
          if (elem.getAttribute("ocurSep") != null)
            lf.setOcurSep(elem.getAttributeValue("ocurSep"));
          if (elem.getAttribute("dateFormat") != null)
            lf.setDateFormat(elem.getAttributeValue("dateFormat"));
          coll.add(lf);
        }

        hm.put(elemNode.getAttributeValue("select"), coll);

      }
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return hm;
  }

  /**
   * Méthode permettant de retourner un tableau de mots vides à partir de
   * l'élément "stopWord".
   * <br/><br/>
   * Method that returns an array of stop words from the element "stopWord".
   */
  public String[] getStopWordValue(Document doc) {
    String[] stopWords = null;
    String stopWordsString = null;
    String sep = null;
    try {
      Element elem = (Element) XPath.selectSingleNode(doc, "//stopWord");
      if (elem != null) {
        stopWordsString = elem.getText().trim();
        Attribute att = (Attribute) XPath.selectSingleNode(doc,
            "//stopWord/@sep");
        sep = att.getValue();
        if (sep == null)
          sep = ",";
        stopWords = stopWordsString.split(sep);

      }

    }
    catch (JDOMException e) {
      e.printStackTrace();
    }
    return stopWords;
  }

  /**
   * Permet de retourner un tableau d'éléments sur lesquels la recherche
   * va être effectuée. Ce dernier sera passé comme argument au constructeur
   * "MultiFieldQueryParser".
   * <br/><br/>
   * Returns an array of elements which will be searched. It will be passed as parameter
   * for the constructor "MultiFieldQueryParser".
   */
  public String[] getSearchFieldsValue(String text, String sep) {
    String[] champsRecherche = text.split(sep);
    return champsRecherche;
  }

  /**
   * Méthode retournant un tableau qui va contenir la liste des champs à
   * afficher dans le résultat de recherche.
   * <br/><br/>
   * Method that returns an array containing the list of fields to show in the
   * search result.
   */
  public Vector getDisplayFields(Document doc) {
    Vector displayFields = new Vector();
    try {
      List elems = XPath.selectNodes(doc,
          "//searchResult/fieldsToDisplay/luceneField");
      for (int i = 0; i < elems.size(); i++) {
        LiusField lf = new LiusField();
        Element elem = (Element) elems.get(i);
        lf.setName(elem.getAttributeValue("name"));
        lf.setLabel(elem.getAttributeValue("label"));
        displayFields.add(lf);

      }
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return displayFields;

  }

  /**
       * Méthode utilisée pour la recherche. La construction de LiusQuery se base sur
   * l'élément trouvé dans le fichier de configuration pour constuire l'objet.
   * <br/><br/>
   * Method used for search. The construction of LiusQuery is based on the
   * element found in the configuration file for constructing the object.
   */
  public String getQueryType(Document doc, LiusConfig xc) {
    String nomElem = "";
    String[] xpathExp = {
        "//search/queryTerm", "//search/queryParser",
        "//search/multiFieldQueryParser", "//search/rangeQuery"};
    try {
      for (int i = 0; i < xpathExp.length; i++) {
        Element testElem = (Element) XPath.selectSingleNode(doc, xpathExp[i]);
        if (testElem != null) {
          if (i == 0) {
            xc.setQueryTermClass(testElem.getAttributeValue("class"));
            xc.setTermFiled(testElem.getChild("term").getAttributeValue("field"));
            return nomElem = "queryTerm";
          }

          else if (i == 1) {
            xc.setDefaultSearchField(testElem.getChild("defaultSearchField").
                                     getAttributeValue("value"));
            return nomElem = "queryParser";
          }
          else if (i == 2) {
            xc.setSearchFields(getSearchFieldsValue(
                testElem.getChild("searchFields").getText(),
                testElem.getChild("searchFields").getAttributeValue("sep")));
            return nomElem = "multiFieldQueryParser";
          }
          else if (i == 3) {
            String[] vals = new String[2];
            vals[0] = testElem.getChild("term").getAttributeValue("field");
            vals[1] = testElem.getChild("booleanInclusive").getAttributeValue(
                "value");
            xc.setRangeQueryFileds(vals);
            return nomElem = "rangeQuery";
          }
        }
      }

    }
    catch (JDOMException e) {
      e.printStackTrace();
    }
    return nomElem;
  }

  /**
       * Méthode retournant un Map qui va contenir les informations pour l'indexation.
   * <br/><br/>
   * Method returning a Map containing the information for indexation.
   */
  public Map getJavaBeansFields(Document doc) {
    Collection coll = null;
    Map javaBeansMap = new HashMap();
    try {
      List javaBeans = XPath.selectNodes(doc, "//JavaBeans/Bean");
      for (int i = 0; i < javaBeans.size(); i++) {
        coll = new ArrayList();
        Element beanC = (Element) javaBeans.get(i);
        List bean = beanC.getChildren("luceneField");
        for (int j = 0; j < bean.size(); j++) {

          LiusField lf = new LiusField();
          lf.setName( ( (Element) bean.get(j)).getAttributeValue("name"));
          lf.setGetMethod( ( (Element) bean.get(j)).getAttributeValue(
              "getMethod"));
          lf.setType( ( (Element) bean.get(j)).getAttributeValue("type"));
          if (( (Element) bean.get(j)).getAttribute("dateFormat") != null)
            lf.setDateFormat(( (Element) bean.get(j)).getAttributeValue("dateFormat"));
          coll.add(lf);
        }
        javaBeansMap.put(beanC.getAttributeValue("class"), coll);

      }
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return javaBeansMap;
  }

  /**
   * Méthode retournant une collection contenant les propriétés à utiliser pour
   * l'indexation du PDF à partir du fichier de configuration de Lius.
   * <br/><br/>
       * Method returning a collection containing the properties to use for indexing
   * PDF files from the Lius configuration file.
   */
  public Collection getPdfFields(Document doc) {
    Collection coll = new ArrayList();
    try {
      LiusField lf = new LiusField();
      List pdfLs = XPath.selectNodes(doc, "//pdf/luceneField");
      if (pdfLs != null) {
        for (int i = 0; i < pdfLs.size(); i++) {
          lf = new LiusField();
          Element pdf = (Element) pdfLs.get(i);
          if (pdf.getAttribute("name") != null)
            lf.setName(pdf.getAttributeValue("name"));
          if (pdf.getAttribute("get") != null)
            lf.setGet(pdf.getAttributeValue("get"));
          if (pdf.getAttribute("type") != null)
            lf.setType(pdf.getAttributeValue("type"));
          if (pdf.getAttribute("dateFormat") != null)
            lf.setDateFormat(pdf.getAttributeValue("dateFormat"));
          coll.add(lf);
        }

      }
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return coll;
  }

  /**
   * Méthode retournant une collection contenant les propriétés à utiliser pour
   * l'indexation du Excel à partir du fichier de configuration de Lius.
   * <br/><br/>
   * Method returning a collection containing the properties to use
   * for indexing Excel files for Lius configuration file.
   */
  public Collection getExcelFields(Document doc) {
    Collection coll = new ArrayList();
    try {
      LiusField lf = new LiusField();
      List excelLs = XPath.selectNodes(doc, "//msExcel/luceneField");
      if (excelLs.size() > 0) {
        for (int i = 0; i < excelLs.size(); i++) {
          lf = new LiusField();
          Element field = (Element) excelLs.get(i);
          if (field.getAttribute("name") != null)
            lf.setName(field.getAttributeValue("name"));
          if (field.getAttribute("get") != null)
            lf.setGet(field.getAttributeValue("get"));
          if (field.getAttribute("type") != null)
            lf.setType(field.getAttributeValue("type"));
          if (field.getAttribute("path") != null)
            lf.setPath(field.getAttributeValue("path"));
          coll.add(lf);
        }
      }
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return coll;
  }

  /**
   * Méthode retournant une collection contenant les propriétés à utiliser pour
   * l'indexation du MS WORD à partir du fichier de configuration de Lius.
   * <br/><br/>
   * Method returning a collection containing the properties to use
   * for indexing MS WORD files for Lius configuration file.
   */
  public Collection getMsWordFields(Document doc) {
    Collection coll = new ArrayList();
    try {
      LiusField lf = new LiusField();
      List wordLs = XPath.selectNodes(doc, "//msWord/luceneField");
      if (wordLs.size() > 0) {
        for (int i = 0; i < wordLs.size(); i++) {
          lf = new LiusField();
          Element field = (Element) wordLs.get(i);
          if (field.getAttribute("name") != null)
            lf.setName(field.getAttributeValue("name"));
          if (field.getAttribute("get") != null)
            lf.setGet(field.getAttributeValue("get"));
          if (field.getAttribute("type") != null)
            lf.setType(field.getAttributeValue("type"));
          if (field.getAttribute("path") != null)
            lf.setPath(field.getAttributeValue("path"));
          coll.add(lf);
        }
      }

    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return coll;
  }

  /**
   * Méthode retournant une collection contenant les propriétés à utiliser pour
   * l'indexation du XHTML à partir du fichier de configuration de Lius.
   * <br/><br/>
   * Method returning a collection containing the properties to use
   * for indexing XHTML files for Lius configuration file.
   */
  public Collection getHtmlFields(Document doc) {
    Collection col = new ArrayList();
    try {

      List listeElem = XPath.selectNodes(doc, "//html/luceneField");
      for (int i = 0; i < listeElem.size(); i++) {
        LiusField lf = new LiusField();
        Element elem = (Element) listeElem.get(i);
        if (elem.getAttribute("name") != null)
          lf.setName(elem.getAttributeValue("name"));
        if (elem.getAttribute("xpathSelect") != null)
          lf.setXpathSelect(elem.getAttributeValue("xpathSelect"));
        if (elem.getAttribute("type") != null)
          lf.setType(elem.getAttributeValue("type"));
        if (elem.getAttribute("ocurSep") != null)
          lf.setOcurSep(elem.getAttributeValue("ocurSep"));
        if (elem.getAttribute("dateFormat") != null)
            lf.setDateFormat(elem.getAttributeValue("dateFormat"));

        col.add(lf);
      }
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return col;
  }

  /**
   * Méthode retournant une collection contenant les propriétés à utiliser pour
   * l'indexation du RTF à partir du fichier de configuration de Lius.
   * <br/><br/>
   * Method returning a collection containing the properties to use
   * for indexing RTF files for Lius configuration file.
   */
  public Collection getRtfFields(Document doc) {
    Collection coll = new ArrayList();
    try {
      LiusField lf = new LiusField();
      List rtfLs = XPath.selectNodes(doc, "//rtf/luceneField");
      if (rtfLs.size() > 0) {
        for (int i = 0; i < rtfLs.size(); i++) {
          lf = new LiusField();
          Element field = (Element) rtfLs.get(i);
          if (field.getAttribute("name") != null)
            lf.setName(field.getAttributeValue("name"));
          if (field.getAttribute("get") != null)
            lf.setGet(field.getAttributeValue("get"));
          if (field.getAttribute("type") != null)
            lf.setType(field.getAttributeValue("type"));
          if (field.getAttribute("path") != null)
            lf.setPath(field.getAttributeValue("path"));
          coll.add(lf);
        }
      }

    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return coll;
  }

  public Collection getTxtFields(Document doc) {
    Collection coll = new ArrayList();
    try {
      LiusField lf = new LiusField();
      List rtfLs = XPath.selectNodes(doc, "//txt/luceneField");
      if (rtfLs.size() > 0) {
        for (int i = 0; i < rtfLs.size(); i++) {
          lf = new LiusField();
          Element field = (Element) rtfLs.get(i);
          if (field.getAttribute("name") != null)
            lf.setName(field.getAttributeValue("name"));
          if (field.getAttribute("get") != null)
            lf.setGet(field.getAttributeValue("get"));
          if (field.getAttribute("type") != null)
            lf.setType(field.getAttributeValue("type"));
          if (field.getAttribute("path") != null)
            lf.setPath(field.getAttributeValue("path"));
          coll.add(lf);
        }
      }

    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return coll;
  }

  public Collection getPPTFields(Document doc) {
    Collection coll = new ArrayList();
    try {
      LiusField lf = new LiusField();
      List rtfLs = XPath.selectNodes(doc, "//msPowerPoint/luceneField");
      if (rtfLs.size() > 0) {
        for (int i = 0; i < rtfLs.size(); i++) {
          lf = new LiusField();
          Element field = (Element) rtfLs.get(i);
          if (field.getAttribute("name") != null)
            lf.setName(field.getAttributeValue("name"));
          if (field.getAttribute("get") != null)
            lf.setGet(field.getAttributeValue("get"));
          if (field.getAttribute("type") != null)
            lf.setType(field.getAttributeValue("type"));
          if (field.getAttribute("path") != null)
            lf.setPath(field.getAttributeValue("path"));
          coll.add(lf);
        }
      }

    }
    catch (JDOMException e) {
      e.printStackTrace();
    }

    return coll;
  }

  public Collection getOOFields(Document doc) {
    Collection col = new ArrayList();
    //List listeElem =  doc.getRootElement().getChild("storeFileInLucenDoc").getChildren("luceneField");
    try {

      List listeElem = XPath.selectNodes(doc,
                                         "//openOffice/luceneField");
      if (listeElem.size() == 0) {
        return col = null;
      }
      else {
        for (int i = 0; i < listeElem.size(); i++) {
          LiusField lf = new LiusField();
          Element elem = (Element) listeElem.get(i);
          if (elem.getAttribute("name") != null)
            lf.setName(elem.getAttributeValue("name"));
          if (elem.getAttribute("xpathSelect") != null)
            lf.setXpathSelect(elem.getAttributeValue("xpathSelect"));
          if (elem.getAttribute("type") != null)
            lf.setType(elem.getAttributeValue("type"));
          if (elem.getAttribute("ocurSep") != null)
            lf.setOcurSep(elem.getAttributeValue("ocurSep"));
          if (elem.getAttribute("dateFormat") != null)
            lf.setDateFormat(elem.getAttributeValue("dateFormat"));
          col.add(lf);
        }
      }
    }

    catch (JDOMException e) {
      e.printStackTrace();
    }
    return col;
  }

  /**
   * Méthode retournant une collection contenant les propriétés à utiliser pour
   * l'indexation mixte à partir du fichier de configuration de Lius.
   * <br/><br/>
   * Method returning a collection containing the properties to use
   * for mixed indexing for Lius configuration file.
   */
  public List getMixteIndexingElements(Document doc) {
    List lsToIndex = new ArrayList();
    try {
      Element mixteIndexing = (Element) XPath.selectSingleNode(doc,
          "//mixteIndexing");
      if (mixteIndexing != null) {
        List children = mixteIndexing.getChildren();
        for (int i = 0; i < children.size(); i++) {
          if ( ( (Element) children.get(i)).getText().equalsIgnoreCase("true")) {
            lsToIndex.add( ( (Element) children.get(i)).getName().toLowerCase());
          }
        }
      }
    }
    catch (JDOMException e) {
      e.printStackTrace();
    }
    return lsToIndex;
  }
}


