package org.esupportail.portal.channels.CAnnuaire;
/** 
 * <p>Titre : Table</p>
 * <p>Description : table de valeurs</p>
 * <p>Copyright : Copyright (c) 2003</p>
 * <p>Société : esupPortail</p>
 * @author Sébatien GAUDIN
 * @version 1.0
 */

import java.io.IOException;
import java.net.URL;
import java.util.*;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.apache.commons.digester.Digester;
import org.jasig.portal.services.LogService;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class Table {


	/**
	 * Represente le nom de la table
	 */
	private String name;
	
	/**
	 * Represente le type de la table (LDAP, XML, statique)
	 */
	private String type;
	
	/**
	 * Si la table est du type LDAP : 
	 * indique le mode de recherche dans LDAP
	 */
	private String scope;
	
	/**
	 * Si la table est du type LDAP : 
	 * indique la base de recherche dans LDAP
	 */
	private String base;
	
	/**
	 * Si la table est du type LDAP : 
	 * indique le nom de l'attribut "code"
	 */
	private String attrCode;
	
	/**
	 * Si la table est du type LDAP : 
	 * indique le nom de l'attribut "value"
	 */
	private String attrValue;

	/**
	 * Si la table est du type LDAP : 
	 * indique le filtre appliqué pour sélectionner les éléménts
	 */
	private String filter;
	
	/**
	 * Si la table est du type LDAP : 
	 * indique l'attribut servant à ordonner les résultats
	 */
	private String fieldOrder;

	/**
	 * Si la table est du type LDAP : 
	 * indique l'adresse du serveur LDAP
	 */
	private String url;

	/**
	 * Si la table est du type LDAP : 
	 * indique le Dn de la connection
	 */
	private String bindDn;

	/**
	 * Si la table est du type LDAP : 
	 * indique le mot de passe de la connection de la connection
	 */
	private String bindPass;
	
	/**
	 * Si la table est du type XML : 
	 * indique le chemin vers le fichier qui contient la table
	 */
	private String file;

	/**
	 * Represente la liste des items, indéxée par le code
	 */
	private Hashtable listeItems;

	public Table() {
		listeItems = new Hashtable();
	}
	
	/**
	 * Permet d'ajouter un élément à la table
	 * si on connait son code, sa valeur et son ordre
	 * si on ne connait son code, il est valué automatiquement
	 * 
	 * @param String code
	 * @param String value
	 * @param String ordreValue
	 */
	public void addItem(String code, String value, String ordreValue) {
		itemTable iT = new itemTable();
		if (code == null)
			code = "code" + listeItems.size();
		LogService.log(
			LogService.DEBUG,
			" code="
				+ code
				+ " -- value="
				+ value
				+ " -- ordreValue="
				+ ordreValue);
		iT.setCode(code);
		iT.setValue(value);
		iT.setOrderValue(ordreValue);
		listeItems.put(code, iT);
	}

	/**
	 * Retourne les éléments de la table
	 * 
	 * @return une Hashtable indéxée sur le code des éléments
	 */
	public Hashtable getItems() {
		return listeItems;
	}

	/**
	 * Retourne l'élément de la table dont le code est passé en paramètre
	 * 
	 * @param code
	 * @return un itemTable
	 */
	public itemTable getItem(String code) {
		return (itemTable) listeItems.get(code);
	}

	/**
	 * Le nom du fichier utilisé (dans le cas d'une table XML)
	 * 
	 * @return le nom du fichier
	 */
	public String getFile() {
		return file;
	}


	/**
	 * Retourne le nom de la table
	 * 
	 * @return Le nom de la table
	 */
	public String getName() {
		return name;
	}

	/**
	 * dans le cas d'une table LDAP
	 * Retrourne le mode de recherche dans LDAP 
	 *  
	 * @return le scope
	 */
	public String getScope() {
		return scope;
	}

	/**
	 * dans le cas d'une table LDAP
	 * Retrourne le mode de recherche dans LDAP sous forme numérique
	 * 
	 * @return SearchControls.SUBTREE_SCOPE ou SearchControls.ONELEVEL_SCOPE
	 */
	public int getScopeNum() {
		int a;
		if (scope.equalsIgnoreCase("sub")) {
			a = SearchControls.SUBTREE_SCOPE;
		} else {
			a = SearchControls.ONELEVEL_SCOPE;
		}
		return a;
	}

	/**
	 * Retourne le type le la table
	 * 
	 * @return Xml, Ldap, statique
	 */
	public String getType() {
		return type;
	}

	/**
	 * dans le cas d'une table XML
	 * Définit le fichier à utiliser pour charger les éléments
	 * 
	 * @param string
	 */
	public void setFile(String string) {
		file = string;
	}

	/**
	 * Définit le nom de la table
	 * 
	 * @param string
	 */
	public void setName(String string) {
		name = string;
	}

	/**
	 * dans le cas d'une table LDAP	
	 * définit le mode de recherche dans LDAP 
	 * 	
	 * @param string
	 */
	public void setScope(String string) {
		scope = string;
	}

	/**
	 * Défnit le type de la table (Xml, Ldap, statique)
	 * 
	 * @param string
	 */
	public void setType(String string) {
		type = string;
	}




	/**
	 * Lance la fonction de chargement des éléments
	 * suivant le type de la table
	 *  
	 */
	public void loadItems() {
		if (type.equals("xml")) {
			loadItemXml();
		} else if (type.equals("ldap")) {
			loadItemLdap();
		} else if (type.equals("static")) {
			/*item ajouté lors de la lecture du fichier de config*/
		}
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * retourne le filtre LDAP des éléments de la table
	 * 
	 * @return le filtre LDAP
	 */
	public String getFilter() {
		return filter;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * définit le filtre LDAP des éléments de la table
	 * 
	 * @param _filter
	 */
	public void setfilter(String _filter) {
		filter = _filter;
	}

	/**
	 * fonction de chargement des éléments pour une table de type xml
	 * 
	 */
	private void loadItemXml() {
		Digester digester = new Digester();
		digester.setValidating(true);
		digester.push(this);

		/*MONTAGE DES TABLES*/
		digester.addCallMethod("list/item", "addItem", 3);
		digester.addCallParam("list/item", 0, "code");
		digester.addCallParam("list/item", 1, "value");
		digester.addCallParam("list/item", 2, "fieldOrder");

		Class requestingClass = this.getClass();
		//Emplacement du fichier de config à parser à partir du répertoire classes
		URL resourceURL = requestingClass.getResource(file);

		try {
			digester.parse(new InputSource(resourceURL.toExternalForm()));

		} catch (IOException e) {
			LogService.log(
				LogService.ERROR,
				"Table::loadItemXml() : ERREUR : Impossible d'ouvrir le fichier de config :"
					+ file
					+ "\n"
					+ e.toString());
		} catch (SAXException e) {
			LogService.log(
				LogService.ERROR,
				"Table::loadItemXml() : ERREUR : SAXException :\n"
					+ e.toString());
		} catch (Exception e) {
			LogService.log(
				LogService.ERROR,
				"Table::loadItemXml() : ERREUR : \n" + e.toString());
		}
	}


	/**
	 * fonction de chargement des éléments pour une table de type ldap
	 * 
	 */
	private void loadItemLdap() {

		/*Met les attributs LDAP à récupérer dans un tableau de chaines*/
		int NbChamp = 2;
		if (fieldOrder != null)
			NbChamp++;
		String[] attrIDs = new String[NbChamp];
		attrIDs[0] = attrCode;
		attrIDs[1] = attrValue;
		if (fieldOrder != null)
			attrIDs[2] = fieldOrder;
		LDAPHandler LDAP = new LDAPHandler();
		LDAP.setUrl(url);
		LDAP.setAttributes(attrIDs);
		LDAP.setMaxEntries(0);
		LDAP.setBase(base);
		LDAP.setFilter(filter);
		LDAP.setScope(this.getScopeNum());
		NamingEnumeration answer = LDAP.search();

		/*Parcours les réponses*/
		if (answer != null) {
			try {
				while (answer.hasMore()) {

					SearchResult sr;
					try {
						sr = (SearchResult) answer.next();

					} catch (NamingException e) {
						LogService.log(
							LogService.ERROR,
							"Table::loadItemLdap() : Parcours les réponses NullPointerException : "
								+ e.toString());
						LDAP.close();
						break;
					}

					/*Parcours les attributs de la réponse*/
					Attribute attrib = sr.getAttributes().get(attrIDs[0]);
					if (fieldOrder != null)
						addItem(
							(String) sr.getAttributes().get(attrIDs[0]).get(0),
							(String) sr.getAttributes().get(attrIDs[1]).get(0),
							(String) sr.getAttributes().get(attrIDs[2]).get(0));
					else
						addItem(
							(String) sr.getAttributes().get(attrIDs[0]).get(0),
							(String) sr.getAttributes().get(attrIDs[1]).get(0),
							null);
				}
			} catch (NullPointerException e) {
				LogService.log(
					LogService.ERROR,
					"Table::loadItemLdap() : aucune réponse : " + e.toString());
				LDAP.close();
			} catch (NamingException e) {
				LogService.log(
					LogService.ERROR,
					"Table::loadItemLdap() : search : " + e.toString());
				LDAP.close();
			}
		}
	}
	/**
	 * Dans le cas d'une table LDAP	
	 * retourne la base de recherche dans LDAP
	 * 
	 * @return la base de recherche dans LDAP
	 */
	public String getBase() {
		return base;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * définit la base de recherche dans LDAP
	 * 
	 * @param string
	 */
	public void setBase(String string) {
		base = string;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * retourne le nom de l'attribut "code"
	 * 
	 * @return le nom de l'attribut LDAP 
	 */
	public String getAttrCode() {
		return attrCode;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * retourne le nom de l'attribut "value"
	 * 
	 * @return le nom de l'attribut LDAP 
	 */
	public String getAttrValue() {
		return attrValue;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * 
	 * @param string
	 */
	public void setAttrCode(String string) {
		attrCode = string;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * 
	 * @param string
	 */
	public void setAttrValue(String string) {
		attrValue = string;
	}

	/**
	 * Dans le cas d'une table LDAP
	 * retourne le Dn de la connection
	 * 
	 * @return le Dn de la connection
	 */
	public String getBindDn() {
		return bindDn;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * retourne l'url du serveur LDAP
	 * 
	 * @return l'url
	 */
	public String getUrl() {
		return url;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * définit le Dn de connection
	 * 
	 * @param string
	 */
	public void setBindDn(String string) {
		bindDn = string;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * définit le mot de passe de connection
	 * 
	 * @param string
	 */
	public void setBindPass(String string) {
		bindPass = string;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * définit l'url du serveur LDAP
	 * 
	 * @param string
	 */
	public void setUrl(String string) {
		url = string;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * retourne le nom de l'attribut LDAP qui sert de tri
	 * 
	 * @return le nom de l'attribut
	 */
	public String getFieldOrder() {
		return fieldOrder;
	}

	/**
	 * Dans le cas d'une table LDAP	
	 * définit le nom de l'attribut LDAP qui sert de tri
	 * 
	 * @param string
	 */
	public void setFieldOrder(String string) {
		fieldOrder = string;
	}

}
