package com.ejie.aa21b.ldap;

import org.xml.sax.InputSource;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import n38a.exe.N38APISesion;
import n38c.exe.N38API;
import n38c.exe.N38Estructura;

import org.apache.commons.lang.ArrayUtils;
import org.apache.xpath.XPathAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.ejie.aa21b.util.Aa21bConstantes;
import com.ejie.x38.security.UserCredentials;

/**
 * Clase auxiliar para tratar con LDAP
 */
public class SecurityHelpperXLNets implements ISecurityInfo {

	/**
	 * Final static logger.
	 */
	private static final Logger logger = LoggerFactory
			.getLogger(SecurityHelpperXLNets.class);

	private HttpServletRequest request;
	private N38API n38API;

	// private Locale clocLocale = Locale.getDefault();

	public SecurityHelpperXLNets() {
		logger.info("Instanciando la clase");
		HttpServletRequest currentRequest = ((ServletRequestAttributes) RequestContextHolder
				.currentRequestAttributes()).getRequest();
		try {
			this.setHttpRequest(currentRequest);
			this.getSecurityObject(Aa21bConstantes.XLNET_OBJETO_SEGURIDAD);
		} catch (SecurityHelpperException e) {
			logger.error("ERROR: " + e.getMessage());
			throw new SecurityException(
					"SecurityHelpperException:SecurityHelpperXLNets: " + e);
		}
	}

	public SecurityHelpperXLNets(String token) {
		SecurityHelpperXLNets.logger.info("Instanciando la clase");

		try {
			n38API = new N38API(this.stringToDom(token));

		} catch (Exception e) {
			logger.error("ERROR: " + e.getMessage());
			throw new SecurityException(
					"SecurityHelpperException:SecurityHelpperXLNets: " + e);
		}
	}

	public Document getItemSession() {
		return this.n38API.n38ItemSesion();
	}

	/* Asociar la request de la sesión N38 */
	public void setHttpRequest(HttpServletRequest request)
			throws SecurityHelpperException {
		try {
			this.request = request;
			n38API = new N38API(request);
		} catch (Exception e) {
			throw new SecurityHelpperException(
					"Error al obtener instancia del api N38");
		}
	}

	/* Obtener los perfiles asociados al Usuario que realiza Login. */
	public String[] getPerfiles() throws SecurityHelpperException {
		try {
			logger.info("getPerfiles=Obteniendo los perfiles del usuario logeado");
			String[] resultado = this.n38API.n38ItemSesion("n38perfiles");
			logger.info(ArrayUtils.toString(resultado));
			return resultado;
		} catch (Throwable e) {
			throw new SecurityHelpperException("SecurityHelpper:getPerfiles");
		}
	}

	/* Obtener el idioma asociado al Usuario que realiza Login. */
	public String getIdioma() throws SecurityHelpperException {
		try {
			return this.n38API.n38ItemSesion("n38idioma")[0];
		} catch (Exception e) {
			throw new SecurityHelpperException("SecurityHelpper:getIdioma");
		}
	}

	/* Obtener la Persona asociada al Usuario que realiza Login. */
	public String getPersonaNombre() throws SecurityHelpperException {
		try {
			String uidPersona = this.getPersonaUID();
			Document personaDocument = this.n38API
					.n38ItemObtenerPersonas("n38PuestoUID=" + uidPersona);

			String filtro = "//elemento[@subtipo=\"n38persona\"]/parametro[@id=\"cn\"]/valor/text()";
			// El cn contiene el nombre y apellidos de la persona.
			String nombre = XPathAPI.selectNodeList(personaDocument, filtro)
					.item(0).getNodeValue();
			return nombre;
		} catch (Exception e) {
			throw new SecurityHelpperException(
					"SecurityHelpper:getPersonaNombre");
		}
	}

	/* Obtener la Persona asociada al Usuario que realiza Login. */
	public String getPersonaNombreYApellidos() throws SecurityHelpperException {
		try {
			Document personaDocument = this.n38API
					.n38ItemObtenerPersonas("uid=" + this.getUsuario());
			String filtro = "//elemento[@subtipo=\"n38persona\"]/parametro[@id=\"givenname\"]/valor/text()";
			String nombre = XPathAPI.selectNodeList(personaDocument, filtro)
					.item(0).getNodeValue();
			filtro = "//elemento[@subtipo=\"n38persona\"]/parametro[@id=\"sn\"]/valor/text()";
			String apellidos = XPathAPI.selectNodeList(personaDocument, filtro)
					.item(0).getNodeValue();
			return nombre + " " + apellidos;
		} catch (Exception e) {
			throw new SecurityHelpperException(
					"SecurityHelpper:getPersonaNombreYApellidos");
		}
	}

	/* Obtener el código del usuario al Usuario que realiza Login. */
	public String getUsuario() throws SecurityHelpperException {
		try {
			UserCredentials userCredentials = (UserCredentials) SecurityContextHolder
					.getContext().getAuthentication().getCredentials();

			return userCredentials.getUserName();

			// return this.n38API.n38ItemSesion("n38personauid")[0];
		} catch (Exception e) {
			throw new SecurityHelpperException("SecurityHelpper:getUsuario"
					+ e.getMessage());
		}
	}

	/* Obtener el dni del usuario al Usuario que realiza Login. */
	public String getDni() throws SecurityHelpperException {
		try {
			return this.n38API.n38ItemSesion("dni")[0];
		} catch (Exception e) {
			throw new SecurityHelpperException("SecurityHelpper:getUsuario"
					+ e.getMessage());
		}
	}

	/* Obtener el uid del usuario que realiza Login. */
	public String getPersonaUID() throws SecurityHelpperException {
		try {
			return this.n38API.n38ItemSesion("n38puestouid")[0];
		} catch (Exception e) {
			throw new SecurityHelpperException("SecurityHelpper:getPersonaUID");
		}
	}

	/* Obtener el grupo orgánico del usuario que realiza Login. */
	public String getPersonaGrupoOrganicoUID() throws SecurityHelpperException {
		try {
			return this.n38API.n38ItemSesion("n38grupoorganicouid")[0];
		} catch (Exception e) {
			throw new SecurityHelpperException(
					"SecurityHelpper:getPersonaGrupoOrganicoUID");
		}
	}

	/* Comprobar si el usuario tiene permiso para la función dada */
	public boolean hasPermission(String uidFuncion)
			throws SecurityHelpperException {
		NodeList lista;
		try {
			Document itemSeguridad = this.n38API.n38ItemSeguridad(uidFuncion);
			lista = XPathAPI.selectNodeList(itemSeguridad, "//elementos");
		} catch (Exception e) {
			throw new SecurityHelpperException(
					"SecurityHelpperXLNets:hasPermision");
		}
		return (lista.getLength() != 0);
	}

	/*
	 * public void cambioIdioma() { if (getIdIdioma().equals("eu"))
	 * setIdIdioma("es"); else setIdIdioma("eu"); clocLocale = new
	 * Locale(cstrIdIdioma, cstrIdIdioma); }
	 */
	/**
	 * Crea un objecto de seguridad para una funcion dada. Si devuelve Null es
	 * que no se tiene permiso para esa Función o recurso de LDAP.
	 */
	public SecurityObject getSecurityObject(String uidFuncion)
			throws SecurityHelpperException {

		StringBuffer strLog = new StringBuffer();
		SecurityObject objetoSeguridad = null;
		String clocLocale = "ES";
		String XLNetsIdioma = "";

		try {
			objetoSeguridad = new SecurityObject(this.getPersonaUID());

			strLog.append(" - objetoSeguridad.getPuesto(): ").append(
					objetoSeguridad.getPuesto());

			objetoSeguridad.setUsuario(this.getUsuario());
			strLog.append(" - objetoSeguridad.getUsuario(): ").append(
					objetoSeguridad.getUsuario());

			objetoSeguridad.setPerfiles(this.getPerfiles());
			XLNetsIdioma = this.getIdioma();
			strLog.append(" - this.getIdioma(): ").append(this.getIdioma());

			if (XLNetsIdioma != null) {
				objetoSeguridad.setIdioma(XLNetsIdioma);
				if ("1".equals(XLNetsIdioma)) {
					clocLocale = "ES";
				} else {
					clocLocale = "EU";
				}
				objetoSeguridad.setPersona(this.getPersonaNombre());
				strLog.append(" - objetoSeguridad.getPersona(): ").append(
						objetoSeguridad.getPersona());
				Locale idioma = new Locale(clocLocale, "");

				HttpSession session = this.request.getSession(true);
				session.setAttribute("IdiomaActual", idioma);
			}
		} catch (Exception e) {
			logger.error("Error al obtener el uidFuncion: " + uidFuncion
					+ " - ERROR: " + e.getMessage());
			throw new SecurityException(
					"SecurityHelpperException:getSecurityObject: " + e);
		} finally {
			logger.info(strLog.toString());
		}
		return objetoSeguridad;
	}

	public ArrayList<Aa21bDepartamentoXLNET> getDepartamentosGrupoOrganicoXLNETs(
			String grupoOrganico) throws SecurityHelpperException {

		ArrayList<Aa21bDepartamentoXLNET> listaDepartamentos = new ArrayList<Aa21bDepartamentoXLNET>();
		try {
			N38Estructura estructura = new N38Estructura();
			estructura.setTipoEntrada("GO");
			estructura.setUidEntrada(grupoOrganico);
			Document document = this.n38API.n38ItemOrganizacion(estructura);

			NodeList lista;
			try {
				lista = XPathAPI.selectNodeList(document,
						"//elemento[@subtipo=\"n38gruposorganicos\"]");
			} catch (TransformerException e) {
				logger.error("ERROR con grupoOrganico: " + grupoOrganico
						+ " - ERROR: " + e.getMessage());
				throw new SecurityHelpperException(
						"SecurityHelpperXLNets:getDepartamentosXLNETs");
			}

			Aa21bDepartamentoXLNET departamento;

			if (lista != null) {
				int nNodos = lista.getLength();
				if (nNodos > 0) {
					for (int i = 0; i < nNodos; i++) {
						if (lista.item(i).getChildNodes().getLength() > 0) {

							String v1 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38uidgrupoorganico\"]/valor/text()")
									.item(0).getNodeValue();
							String v2 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38cadescripcion\"]/valor/text()")
									.item(0).getNodeValue();
							String v3 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38eudescripcion\"]/valor/text()")
									.item(0).getNodeValue();

							departamento = new Aa21bDepartamentoXLNET();
							departamento.setCodigo(v1);
							departamento.setDescC(v2);
							departamento.setDescE(v3);

							listaDepartamentos.add(departamento);
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("ERROR con grupoOrganico: " + grupoOrganico
					+ " - ERROR: " + e.getMessage());
		}

		return listaDepartamentos;
	}

	public ArrayList<Aa21bServicioXLNET> getServiciosXLNETs(String ou)
			throws SecurityHelpperException {

		ArrayList<Aa21bServicioXLNET> listaServicios = new ArrayList<Aa21bServicioXLNET>();
		try {
			N38Estructura estructura = new N38Estructura();
			estructura.setTipoEntrada("CO");
			estructura.setUidEntrada(ou);
			Document document = this.n38API.n38ItemOrganizacion(estructura);

			NodeList lista;
			try {
				// lista = XPathAPI.selectNodeList(document,
				// "/n38/elementos/elemento/elemento[@subtipo=\"n38gruposorganicos\"]");
				lista = XPathAPI.selectNodeList(document,
						"//elemento[@subtipo=\"n38organizationalunit\"]");
			} catch (TransformerException e) {
				logger.error("Error con ou: " + ou + " - ERROR: "
						+ e.getMessage());
				throw new SecurityHelpperException(
						"SecurityHelpperXLNets:getServiciosXLNETs");
			}

			Aa21bServicioXLNET servicio;

			if (lista != null) {
				int nNodos = lista.getLength();
				if (nNodos > 0) {
					for (int i = 0; i < nNodos; i++) {
						if (lista.item(i).getChildNodes().getLength() > 0) {

							String v1 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38uidorgunit\"]/valor/text()")
									.item(0).getNodeValue();
							String v2 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38cadescripcion\"]/valor/text()")
									.item(0).getNodeValue();
							String v3 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38eudescripcion\"]/valor/text()")
									.item(0).getNodeValue();

							servicio = new Aa21bServicioXLNET();
							servicio.setCodigo(v1);
							servicio.setDescC(v2);
							servicio.setDescE(v3);

							listaServicios.add(servicio);
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("Error con ou: " + ou + " - ERROR: " + e.getMessage());
		}

		return listaServicios;
	}

	public Aa21bDireccionXLNET getDireccionPuestoXLNETs(String puesto)
			throws SecurityHelpperException {

		try {
			Document documentPuesto = this.n38API
					.n38ItemObtenerPuestos("n38uidpuesto=" + puesto);
			NodeList lista = XPathAPI.selectNodeList(documentPuesto,
					"//elemento[@subtipo=\"n38puesto\"]");
			String codEstrus = XPathAPI
					.selectNodeList(lista.item(0),
							"parametro[@id=\"n38codestrus\"]/valor/text()")
					.item(0).getNodeValue();
			String grupoOrganico = XPathAPI
					.selectNodeList(lista.item(0),
							"parametro[@id=\"n38grupoorganicouid\"]/valor/text()")
					.item(0).getNodeValue();

			// Con el código cogemos ahora las descripciones en castellano y en
			// euskera
			N38Estructura estructura = new N38Estructura();
			estructura.setTipoEntrada("GO*");
			estructura.setUidEntrada(grupoOrganico);
			Document documentDireccion = this.n38API
					.n38ItemOrganizacion(estructura);

			try {
				lista = XPathAPI.selectNodeList(documentDireccion,
						"//elemento[@subtipo=\"n38organizationalunit\"]");

				if (lista != null) {
					String codigo = "";
					String descc = "";
					String desce = "";
					for (int i = 0; i < lista.getLength(); i++) {
						codigo = XPathAPI
								.selectNodeList(lista.item(i),
										"parametro[@id=\"n38codestrus\"]/valor/text()")
								.item(0).getNodeValue();
						if (codigo.substring(0, 4).equals(
								codEstrus.substring(0, 4))) {
							descc = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38cadescripcion\"]/valor/text()")
									.item(0).getNodeValue();
							desce = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38eudescripcion\"]/valor/text()")
									.item(0).getNodeValue();
							Aa21bDireccionXLNET direccion = new Aa21bDireccionXLNET();
							direccion.setCodigo(codigo.substring(0, 4));
							direccion.setDescC(descc);
							direccion.setDescE(desce);

							return direccion;
						}
					}
				}

			} catch (TransformerException e) {
				logger.error("Error con puesto: " + puesto + " - ERROR: "
						+ e.getMessage());
				throw new SecurityHelpperException(
						"SecurityHelpperXLNets:getServiciosXLNETs");
			}
		} catch (Exception e) {
			logger.error("Error con puesto: " + puesto + " - ERROR: "
					+ e.getMessage());
		}

		return null;
	}

	public ArrayList<Aa21bDepartamentoXLNET> getDepartamentosXLNETs()
			throws SecurityHelpperException {

		ArrayList<Aa21bDepartamentoXLNET> listaDepartamentos = new ArrayList<Aa21bDepartamentoXLNET>();
		try {
			N38Estructura estructura = new N38Estructura();
			estructura.setTipoEntrada("ALL");
			estructura.setUidEntrada("1");
			Document document = this.n38API.n38ItemOrganizacion(estructura); // "ALL",
			// "1"

			NodeList lista;
			try {
				// lista = XPathAPI.selectNodeList(document,
				// "/n38/elementos/elemento/elemento[@subtipo=\"n38gruposorganicos\"]");
				lista = XPathAPI.selectNodeList(document,
						"//elemento[@subtipo=\"n38gruposorganicos\"]");
			} catch (TransformerException e) {
				logger.error("Error: " + e.getMessage());
				throw new SecurityHelpperException(
						"SecurityHelpperXLNets:getDepartamentosXLNETs");
			}

			Aa21bDepartamentoXLNET departamento;

			if (lista != null) {
				int nNodos = lista.getLength();
				if (nNodos > 0) {
					for (int i = 0; i < nNodos; i++) {
						if (lista.item(i).getChildNodes().getLength() > 0) {

							String v1 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38uidgrupoorganico\"]/valor/text()")
									.item(0).getNodeValue();
							String v2 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38cadescripcion\"]/valor/text()")
									.item(0).getNodeValue();
							String v3 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38eudescripcion\"]/valor/text()")
									.item(0).getNodeValue();

							departamento = new Aa21bDepartamentoXLNET();
							departamento.setCodigo(v1);
							departamento.setDescC(v2);
							departamento.setDescE(v3);

							listaDepartamentos.add(departamento);
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("ERROR: " + e.getMessage());
		}

		return listaDepartamentos;
	}

	public ArrayList<String> getCodDepartamentosXLNETs()
			throws SecurityHelpperException {

		ArrayList<String> listaDepartamentos = new ArrayList<String>();
		try {
			N38Estructura estructura = new N38Estructura();
			estructura.setTipoEntrada("ALL");
			estructura.setUidEntrada("1");
			Document document = this.n38API.n38ItemOrganizacion(estructura); // "ALL","1"

			NodeList lista;
			try {
				lista = XPathAPI.selectNodeList(document,
						"//elemento[@subtipo=\"n38gruposorganicos\"]");
			} catch (TransformerException e) {
				logger.error("ERROR: " + e.getMessage());
				throw new SecurityHelpperException(
						"SecurityHelpperXLNets:getDepartamentosXLNETs");
			}

			if (lista != null) {
				int nNodos = lista.getLength();
				if (nNodos > 0) {
					for (int i = 0; i < nNodos; i++) {
						if (lista.item(i).getChildNodes().getLength() > 0) {
							listaDepartamentos
									.add(XPathAPI
											.selectNodeList(lista.item(i),
													"parametro[@id=\"n38uidgrupoorganico\"]/valor/text()")
											.item(0).getNodeValue());
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("ERROR: " + e.getMessage());
		}

		return listaDepartamentos;
	}

	public ArrayList<Aa21bDepartamentoXLNET> getDepartamentosYOrganismosXLNETs()
			throws SecurityHelpperException {

		ArrayList<Aa21bDepartamentoXLNET> listaDepartamentos = new ArrayList<Aa21bDepartamentoXLNET>();
		try {
			N38Estructura estructura = new N38Estructura();
			estructura.setTipoEntrada("ALL");
			estructura.setUidEntrada("ALL");
			Document document = this.n38API.n38ItemOrganizacion(estructura); // "ALL","ALL"

			NodeList lista;
			try {
				lista = XPathAPI.selectNodeList(document,
						"//elemento[@subtipo=\"n38organization\"]");
			} catch (TransformerException e) {
				logger.error("Error: " + e.getMessage());
				throw new SecurityHelpperException(
						"SecurityHelpperXLNets:getDepartamentosYOrganismosXLNETs");
			}

			Aa21bDepartamentoXLNET departamento;

			if (lista != null) {
				int nNodos = lista.getLength();
				if (nNodos > 0) {
					for (int i = 0; i < nNodos; i++) {
						if (lista.item(i).getChildNodes().getLength() > 0) {

							String v1 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38uidorg\"]/valor/text()")
									.item(0).getNodeValue();
							if ("1".equals(v1)) // GV
							{
								// El grupo órganico del GV no lo tratamos
								// porque para el cogemos todos sus
								// departamentos
								// con la función getDepartamentosXLNETs
								ArrayList<Aa21bDepartamentoXLNET> departamentosGV = this
										.getDepartamentosXLNETs();
								listaDepartamentos.addAll(departamentosGV);
							} else {
								String v2 = XPathAPI
										.selectNodeList(lista.item(i),
												"parametro[@id=\"n38cadescripcion\"]/valor/text()")
										.item(0).getNodeValue();
								String v3 = XPathAPI
										.selectNodeList(lista.item(i),
												"parametro[@id=\"n38eudescripcion\"]/valor/text()")
										.item(0).getNodeValue();

								departamento = new Aa21bDepartamentoXLNET();
								departamento.setCodigo(v1);
								departamento.setDescC(v2);
								departamento.setDescE(v3);

								listaDepartamentos.add(departamento);
							}
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("Error: " + e.getMessage());
		}

		return listaDepartamentos;
	}

	public ArrayList<String> getCodDepartamentosYOrganismosGXLNETs()
			throws SecurityHelpperException {

		ArrayList<String> listaDepartamentos = new ArrayList<String>();
		try {
			N38Estructura estructura = new N38Estructura();
			estructura.setTipoEntrada("ALL");
			estructura.setUidEntrada("ALL");
			Document document = this.n38API.n38ItemOrganizacion(estructura); // "ALL","ALL"

			NodeList lista;
			try {
				lista = XPathAPI.selectNodeList(document,
						"//elemento[@subtipo=\"n38organization\"]");
			} catch (TransformerException e) {
				logger.error("Error: " + e.getMessage());
				throw new SecurityHelpperException(
						"SecurityHelpperXLNets:getCodDepartamentosYOrganismosXLNETs");
			}

			if (lista != null) {
				int nNodos = lista.getLength();
				if (nNodos > 0) {
					String v1 = "";
					String v2 = "";
					for (int i = 0; i < nNodos; i++) {
						if (lista.item(i).getChildNodes().getLength() > 0) {
							v1 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38uidorg\"]/valor/text()")
									.item(0).getNodeValue();
							if ("1".equals(v1)) // GV
							{
								// El grupo Órganico del GV no lo tratamos
								// porque para él cogemos todos sus
								// departamentos
								// con la función getDepartamentosXLNETs
								ArrayList<String> departamentosGV = this
										.getCodDepartamentosXLNETs();
								listaDepartamentos.addAll(departamentosGV);
							} else {
								v2 = XPathAPI
										.selectNodeList(lista.item(i),
												"parametro[@id=\"n38idtipoorganizacion\"]/valor/text()")
										.item(0).getNodeValue();
								if ("G".equals(v2)) {
									listaDepartamentos.add(v1);
								}
							}
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("Error: " + e.getMessage());
		}

		return listaDepartamentos;
	}

	/**
	 * Obtener el usuario por XLNETS
	 * 
	 * @param codigo
	 * @param dni
	 * @param nombre
	 * @param apellidos
	 * @param grupoOrganicoUID
	 * @return
	 * @throws SecurityHelpperException
	 */
	public ArrayList<Aa21bPersonaXLNET> getPersonasXLNETs(String codigo,
			String dni, String nombre, String apellidos, String grupoOrganicoUID)
			throws SecurityHelpperException {
		logger.info("Get persona XLNETS" + codigo);
		ArrayList<Aa21bPersonaXLNET> listaPersonas = new ArrayList<Aa21bPersonaXLNET>();
		ArrayList<Aa21bDepartamentoXLNET> listaDepartamentos;
		// ArrayList<m05jServicioXLNET> listaServicios;
		Aa21bDireccionXLNET direccion;
		try {
			StringBuffer filtro = new StringBuffer();
			if (codigo != null && !codigo.equals("")) {
				filtro.append("uid=").append(codigo);
			}
			if (dni != null && !dni.equals("")) {
				filtro.append("dni=").append(dni);
			}
			if (nombre != null && !nombre.equals("")) {
				filtro.append("givenname=").append(nombre).append("*");
			}
			if (apellidos != null && !apellidos.equals("")) {
				filtro.append("sn=").append(apellidos).append("*");
			}
			// if (filtro.length() > 0) {
			// if (grupoOrganicoUID != null && !grupoOrganicoUID.equals("")) {
			// filtro.append("n38grupoorganicouid=").append(grupoOrganicoUID);
			// }
			// }
			logger.info("Filtro aplicado =" + filtro);
			Document document = this.n38API.n38ItemObtenerPersonas(filtro
					.toString());
			Document documentPuesto;

			NodeList lista;
			NodeList listaDepto;
			try {
				lista = XPathAPI.selectNodeList(document,
						"//elemento[@subtipo=\"n38persona\"]");
			} catch (TransformerException e) {
				logger.error("Error con código: " + codigo + " - ERROR: "
						+ e.getMessage());
				throw new SecurityHelpperException(
						"SecurityHelpperXLNets:getPersonasXLNETs");
			}

			Aa21bPersonaXLNET persona;

			if (lista != null) {
				logger.info("crear lista de  objetos persona de la clase Aa21bPersonaXLNET");
				int nNodos = lista.getLength();
				if (nNodos > 0) {
					for (int i = 0; i < nNodos; i++) {
						if (lista.item(i).getChildNodes().getLength() > 0) {
							String v1 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"uid\"]/valor/text()")
									.item(0).getNodeValue();
							String v2 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"dni\"]/valor/text()")
									.item(0).getNodeValue();
							String v3 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"givenname\"]/valor/text()")
									.item(0).getNodeValue();
							String v4 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"sn\"]/valor/text()")
									.item(0).getNodeValue();
							String v5 = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"n38puestouid\"]/valor/text()")
									.item(0).getNodeValue();
							String v6 = "";
							String v7 = "";
							String v8 = "";
							String v9 = "";
							String v10 = "";
							String v11 = "";
							String v12 = "";
							String v13 = "";
							String v14 = "";
							NodeList nlm = XPathAPI.selectNodeList(
									lista.item(i),
									"parametro[@id=\"mail\"]/valor/text()");
							if (nlm.getLength() > 0) {
								v9 = nlm.item(0).getNodeValue();
							}

							NodeList nlt = XPathAPI
									.selectNodeList(lista.item(i),
											"parametro[@id=\"telephonenumber\"]/valor/text()");
							if (nlt.getLength() > 0) {
								v10 = nlt.item(0).getNodeValue();
							}

							persona = new Aa21bPersonaXLNET();
							persona.setCodigo(v1);
							persona.setDni(v2);
							persona.setNombre(v3);
							persona.setApellidos(v4);
							persona.setEMail(v9);
							persona.setTelefono(v10);

							/* CON EL PUESTO OBTENEMOS EL DEPARTAMENTO */
							try {
								documentPuesto = this.n38API
										.n38ItemObtenerPuestos("n38uidpuesto="
												+ v5);
								listaDepto = XPathAPI.selectNodeList(
										documentPuesto,
										"//elemento[@subtipo=\"n38puesto\"]");

								NodeList nlp = XPathAPI
										.selectNodeList(listaDepto.item(0),
												"parametro[@id=\"n38cadescripcion\"]/valor/text()");
								if (nlp.getLength() > 0) {
									v11 = nlp.item(0).getNodeValue();
								}

								v6 = XPathAPI
										.selectNodeList(listaDepto.item(0),
												"parametro[@id=\"n38grupoorganicouid\"]/valor/text()")
										.item(0).getNodeValue();

								listaDepartamentos = this
										.getDepartamentosGrupoOrganicoXLNETs(v6);
								if (listaDepartamentos != null
										&& listaDepartamentos.size() > 0) {
									v6 = listaDepartamentos.get(0).getCodigo();
									v7 = listaDepartamentos.get(0).getDescC();
									v8 = listaDepartamentos.get(0).getDescE();
								}

								v12 = XPathAPI
										.selectNodeList(listaDepto.item(0),
												"parametro[@id=\"ou\"]/valor/text()")
										.item(0).getNodeValue();

								// NUEVO
								direccion = this.getDireccionPuestoXLNETs(v5);
								v12 = direccion.getCodigo();
								v13 = direccion.getDescC();
								v14 = direccion.getDescE();
								//

								/*
								 * listaServicios =
								 * this.getServiciosXLNETs(v12); if
								 * (listaServicios != null &&
								 * listaServicios.size() > 0) { v12 =
								 * listaServicios.get(0).getCodigo(); v13 =
								 * listaServicios.get(0).getDescC(); v14 =
								 * listaServicios.get(0).getDescE(); }
								 */

							} catch (Exception e) {
								logger.error("Error con código: " + codigo
										+ " - ERROR: " + e.getMessage());
							}
							/**/

							persona.setCodDepto(v6);
							persona.setDescDeptoC(v7);
							persona.setDescDeptoE(v8);
							persona.setCodDireccion(v12);
							persona.setDescDireccionC(v13);
							persona.setDescDireccionE(v14);
							persona.setCargo("");
							persona.setPuesto(v11);

							if (grupoOrganicoUID != null
									&& grupoOrganicoUID.length() > 0) {
								if (persona.getCodDepto().equals(
										grupoOrganicoUID)) {
									listaPersonas.add(persona);
								}
							} else {
								listaPersonas.add(persona);
							}
							logger.info("persona añadida " + persona.toString());
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("Error con código: " + codigo + " - ERROR: "
					+ e.getMessage());
		}
		Collections.sort(listaPersonas);
		return listaPersonas;
	}

	/*
	 * public boolean usuarioLogueadoPuedeSolicitar() {
	 * 
	 * try { // Para que en desarrollo funcione con cualquier persona logueada
	 * // en XLNETs independientemente del departamento, añadimos ésto: try {
	 * logger.info(request.getRequestURL().toString()); if
	 * (StringUtils.startsWithIgnoreCase(request.getRequestURL() .toString(),
	 * "http://desarrollo.jakina.ejiedes.net:7001")) {
	 * logger.info("ESTAMOS EN LOCAL..."); return true; } else if (StringUtils
	 * .startsWithIgnoreCase(request.getRequestURL() .toString(),
	 * "http://www.des.ejgv.jaso")) { logger.info("ESTAMOS EN DESARROLLO...");
	 * return true; } else if (StringUtils
	 * .startsWithIgnoreCase(request.getRequestURL() .toString(),
	 * "http://www.pru.ejgv.jaso")) { logger.info("ESTAMOS EN PRUEBAS...");
	 * return true; } } catch (Exception e) { logger.error("ERROR: " +
	 * e.getMessage()); }
	 * 
	 * // Para que el usuario pueda solicitar tiene que: // Ser miembro de un
	 * departamento del gv o de una administración // pública, // o bien ser
	 * miembro del grupo técnico de la aplicación. String codDeptoUsuario =
	 * this.getPersonaGrupoOrganicoUID(); ArrayList<String> listaDeptos = this
	 * .getCodDepartamentosYOrganismosGXLNETs(); if (listaDeptos != null &&
	 * listaDeptos.size() > 0) { for (int i = 0; i < listaDeptos.size(); i++) {
	 * if (listaDeptos.get(i).equals(codDeptoUsuario)) { return true; } } }
	 * 
	 * String perfiles[] = this.getPerfiles(); if (perfiles != null &&
	 * perfiles.length > 0) { for (int i = 0; i < perfiles.length; i++) { if
	 * (perfiles[i] .equals(Aa21bConstantes.XLNET_PERFIL_TECNICO)) {
	 * logger.info("XLNET_PERFIL_TECNICO=true"); return true; } } } } catch
	 * (Exception e) { logger.error("ERROR: " + e.getMessage()); }
	 * 
	 * return false; } /** Si el usuario es Direccion
	 * 
	 * @return
	 */
	public boolean usuarioLogueadoEsDireccion() {
		logger.info("usuarioLogueadoEsDireccion");
		try {
			String perfiles[] = this.getPerfiles();
			if (perfiles != null && perfiles.length > 0) {
				for (int i = 0; i < perfiles.length; i++) {
					if (perfiles[i]
							.equals(Aa21bConstantes.XLNET_PERFIL_DIRECCION)) {
						logger.info("XLNET_PERFIL_DIRECCION=true");
						logger.info("es técnico");
						return true;
					}
				}
			}
		} catch (Exception e) {
			StackTraceElement[] stackTraceElements = Thread.currentThread()
					.getStackTrace();
			for (StackTraceElement stackTrace : stackTraceElements) {
				logger.error(stackTrace.getClassName() + "  "
						+ stackTrace.getMethodName() + " "
						+ stackTrace.getLineNumber());
			}
		}
		logger.info("no es técnico");
		return false;
	}

	/**
	 * True si el usuario es adminsitrador
	 * 
	 * @return
	 */
	public boolean usuarioLogueadoEsAdmininstrador() {
		logger.info("usuarioLogueadoEsAdmininstrador");
		try {
			String perfiles[] = this.getPerfiles();
			if (perfiles != null && perfiles.length > 0) {
				for (int i = 0; i < perfiles.length; i++) {
					if (perfiles[i]
							.equals(Aa21bConstantes.XLNET_PERFIL_ADMINISTRADOR)) {
						logger.info("XLNET_PERFIL_ADMIN_DEPTO=true");
						;
						return true;
					}
				}
			}
		} catch (Exception e) {
			StackTraceElement[] stackTraceElements = Thread.currentThread()
					.getStackTrace();
			for (StackTraceElement stackTrace : stackTraceElements) {
				logger.error(stackTrace.getClassName() + "  "
						+ stackTrace.getMethodName() + " "
						+ stackTrace.getLineNumber());
			}
		}
		logger.info(" no es admindepto");
		return false;
	}

	/**
	 * True si el usuario es Tramitador
	 * 
	 * @return
	 */
	public boolean usuarioLogueadoEsTramitador() {
		logger.info("usuarioLogueadoEsTramitador");
		try {
			String perfiles[] = this.getPerfiles();
			if (perfiles != null && perfiles.length > 0) {
				for (int i = 0; i < perfiles.length; i++) {
					if (perfiles[i]
							.equals(Aa21bConstantes.XLNET_PERFIL_TRAMITADOR)) {
						logger.info("XLNET_PERFIL_ADMIN_DEPTO=true");
						;
						return true;
					}
				}
			}
		} catch (Exception e) {
			StackTraceElement[] stackTraceElements = Thread.currentThread()
					.getStackTrace();
			for (StackTraceElement stackTrace : stackTraceElements) {
				logger.error(stackTrace.getClassName() + "  "
						+ stackTrace.getMethodName() + " "
						+ stackTrace.getLineNumber());
			}
		}
		logger.info(" no es tramitador");
		return false;
	}

	/**
	 * True si el usuario es consultor
	 * 
	 * @return
	 */
	public boolean usuarioLogueadoEsConsultor() {
		logger.info("usuarioLogueadoEsConsultor");
		try {
			String perfiles[] = this.getPerfiles();
			if (perfiles != null && perfiles.length > 0) {
				for (int i = 0; i < perfiles.length; i++) {
					if (perfiles[i]
							.equals(Aa21bConstantes.XLNET_PERFIL_CONSULTADOR)) {
						logger.info("XLNET_PERFIL_ADMIN_DEPTO=true");
						;
						return true;
					}
				}
			}
		} catch (Exception e) {
			StackTraceElement[] stackTraceElements = Thread.currentThread()
					.getStackTrace();
			for (StackTraceElement stackTrace : stackTraceElements) {
				logger.error(stackTrace.getClassName() + "  "
						+ stackTrace.getMethodName() + " "
						+ stackTrace.getLineNumber());
			}
		}
		logger.info(" no es consultor");
		return false;
	}

	/**
	 * Obtiene el token XLNets de aplicacion
	 * 
	 * @param idAplic
	 *            la ID de aplicacion
	 * @return el token de aplicacion
	 */
	public static String getTokenXLNets(String idAplic) {
		String token = null;
		logger.info("getTokenXLNets " + idAplic);
		try {
			N38APISesion miAPISesion = new N38APISesion();
			Document miSesion;
			miSesion = miAPISesion.n38APISesionCrearApp(idAplic);
			token = SecurityHelpperXLNets.DOM2String(miSesion);
			logger.info(token);
		} catch (Exception e) {
			logger.error("Excepcion creando el token de aplicacion");
			StackTraceElement[] stackTraceElements = Thread.currentThread()
					.getStackTrace();
			for (StackTraceElement stackTrace : stackTraceElements) {
				logger.error(stackTrace.getClassName() + "  "
						+ stackTrace.getMethodName() + " "
						+ stackTrace.getLineNumber());
			}
		}
		return token;
	}

	/**
	 * Convierte en String un documento org.w3c.dom.Document
	 * 
	 * @param doc
	 *            Documento de tipo org.w3c.dom.Document
	 * @return String en el que se ha convertido el Document
	 */
	public static String DOM2String(Document doc) {

		TransformerFactory transformerFactory = TransformerFactory
				.newInstance();
		Transformer transformer = null;

		try {
			transformer = transformerFactory.newTransformer();
		} catch (javax.xml.transform.TransformerConfigurationException error) {
			logger.error("DOM2String - Error al crear la instancia de Transformer");
		}

		Source source = new DOMSource(doc);
		StringWriter writer = new StringWriter();
		Result result = new StreamResult(writer);

		try {
			transformer.transform(source, result);
		} catch (javax.xml.transform.TransformerException error) {
			logger.error("DOM2String - Error al transformar el Document");
		}

		return writer.toString();
	}

	private Document stringToDom(String xmlSource) throws SAXException,
			ParserConfigurationException, IOException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		return builder.parse(new InputSource(new StringReader(xmlSource)));
	}

}