package com.ejie.y42b.control;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.ejie.x38.control.exception.ControlException;
import com.ejie.x38.control.exception.ResourceNotFoundException;
import com.ejie.x38.dto.JQGridJSONModel;
import com.ejie.x38.dto.Pagination;
import com.ejie.x38.security.Credentials;
import com.ejie.y42b.UserPreferences;
import com.ejie.y42b.constantes.Y42bAgendaConstantes;
import com.ejie.y42b.forms.mant.Y42bFormArbol;
import com.ejie.y42b.model.CodesContact;
import com.ejie.y42b.model.CodesContacts;
import com.ejie.y42b.model.CodesEntities;
import com.ejie.y42b.model.CodesEntity;
import com.ejie.y42b.model.CodesParameter;
import com.ejie.y42b.model.Contacto;
import com.ejie.y42b.model.Entidad;
import com.ejie.y42b.model.Envio;
import com.ejie.y42b.model.Etiqueta;
import com.ejie.y42b.model.Grupo;
import com.ejie.y42b.model.Item;
import com.ejie.y42b.model.Y42bTree;
import com.ejie.y42b.service.ContactoService;
import com.ejie.y42b.service.EntidadService;
import com.ejie.y42b.service.EnvioService;
import com.ejie.y42b.service.EtiquetaService;
import com.ejie.y42b.service.ItemService;
import com.ejie.y42b.service.T17CalleService;
import com.ejie.y42b.service.T17LocalidadService;
import com.ejie.y42b.service.T17MunicipioService;
import com.ejie.y42b.service.T17PaisService;
import com.ejie.y42b.service.T17ProvinciaService;
import com.ejie.y42b.service.Y42bArbolService;
import com.ejie.y42b.service.Y42bGruposService;
import com.ejie.y42b.utils.Y42bEntityGroupTree;
import com.ejie.y42b.utils.Y42bEtiquetasTree;
import com.ejie.y42b.utils.Y42bExcelGenerator;
import com.ejie.y42b.utils.Y42bProcessTree;
import com.ejie.y42b.utils.Y42bUtils;
import com.ejie.y42b.utils.jaxb.Y42bJAXBFactory;
import com.ejie.y42b.constantes.Y42bAgendaConstantes;

/**
 *  
 */

@Controller()
@RequestMapping(value = "/search")
public class SearchController {

	private static final Logger logger = LoggerFactory
			.getLogger(SearchController.class);

	@Autowired()
	private Y42bArbolService arbolService;

	@Autowired()
	private Y42bGruposService groupService;

	@Autowired()
	private EntidadService entityService;

	@Autowired()
	private ContactoService contactService;

	@Autowired()
	private EnvioService envioService;

	@Autowired()
	private ItemService itemService;

	@Autowired()
	private EtiquetaService etiquetaService;

	@Autowired()
	private T17PaisService paisService;

	@Autowired()
	private T17ProvinciaService provinciaService;

	@Autowired()
	private T17MunicipioService municipioService;

	@Autowired()
	private T17LocalidadService localidadService;

	@Autowired()
	private T17CalleService calleService;

	@Autowired()
	private Properties appConfiguration;

	/**
	 * Method 'load'.
	 * 
	 * @param mySession
	 *            HttpSession
	 * @param model
	 *            Model
	 * @return String
	 */
	@RequestMapping(value = "load", method = RequestMethod.GET)
	public ModelAndView load(HttpSession mySession, Model model) {
		model.addAttribute("defaultLanguage",
				this.appConfiguration.get("y42bVistaWar.default.language"));
		model.addAttribute("defaultLayout",
				this.appConfiguration.get("y42bVistaWar.default.layout"));
		model.addAttribute("URL_ENVIO_CONFIRMACION",
				this.appConfiguration.get("URL_ENVIO_CONFIRMACION"));
		model.addAttribute("statics_path",
				this.appConfiguration.get("statics.path"));
		UserPreferences userPreferences = (UserPreferences) mySession
				.getAttribute(Y42bAgendaConstantes.SESSIONBEAN_NODE);
		Y42bFormArbol arbolForm = new Y42bFormArbol();

		if (userPreferences == null) {
			// FIXME Migracion UDA V.2.4.4 (201504) - Cambio para dejar en
			// session atributo UserName
			String userID = (String) mySession.getAttribute("UserName");
			if (userID == null || "".equals(userID)) {
				Authentication authentication = SecurityContextHolder
						.getContext().getAuthentication();
				Credentials credentials = (Credentials) authentication
						.getCredentials();
				userID = credentials.getUserName();
				mySession.setAttribute("UserName", userID);
			}

			userPreferences = new UserPreferences();
			userPreferences.setUserId(userID);
			userPreferences.setUserNombreCompleto(userID);
			userPreferences.setMostrarEntidadesNoActivas(false);
			userPreferences.setNodeActive("G_ROOT");
			mySession.setAttribute(Y42bAgendaConstantes.SESSIONBEAN_NODE,
					userPreferences);

			arbolForm.setChkShowEntidadesNoActivas(userPreferences
					.isMostrarEntidadesNoActivas());
			arbolForm
					.setUrlTree("/y42bVistaWar/arbol/ajaxTree?mostrarEntidadesNoActivas=0");

		} else {
			arbolForm.setChkShowEntidadesNoActivas(userPreferences
					.isMostrarEntidadesNoActivas());
			if (userPreferences.isMostrarEntidadesNoActivas()) {
				arbolForm
						.setUrlTree("/y42bVistaWar/arbol/ajaxTree?mostrarEntidadesNoActivas=1");
			} else {
				arbolForm
						.setUrlTree("/y42bVistaWar/arbol/ajaxTree?mostrarEntidadesNoActivas=0");
			}

		}
		SearchController.logger.debug("Nodo en session: "
				+ userPreferences.getNodeActive());

		arbolForm.setNodeId(userPreferences.getNodeActive());

		return new ModelAndView("search", "model", model);
	}

	/**
	 * <hr />
	 * <b>Busqueda avanzada del buscador de utilidades.</b>
	 * <hr />
	 * 
	 * El buscador cumple con una serie de requisitos avanzados, para facilitar
	 * la localización de entidades o contactos dentro del subsistema de
	 * organismos de Consumo.
	 * 
	 * @param nombreInput
	 *            Nombre (puede ser de entidad o de contacto en función del tipo
	 *            de búsqueda).
	 * @param activa
	 *            Entidad activa (No se usa por compatibilidad a futuro)
	 * @param iskontsumogest
	 *            Entidad de KontsumoGest (por defecto N)
	 * @param iskontsumonet
	 *            Entidad de KontsumoNet (por defecto N)
	 * @param isofertaform
	 *            Entidad de oferta formativa (por defecto N)
	 * @param isconsultasweb
	 *            Entidad de consultas Web (por defecto N)
	 * @param observaciones
	 *            Observaciones de entidad (No se usa por compatibilidad a
	 *            futuro)
	 * @param telefono
	 *            Teléfono (puede ser de entidad o de contacto en función del
	 *            tipo de búsqueda) (No se usa por compatibilidad a futuro)
	 * @param fax
	 *            Fax (puede ser de entidad o de contacto en función del tipo de
	 *            búsqueda) (No se usa por compatibilidad a futuro)
	 * @param email
	 *            Email (puede ser de entidad o de contacto en función del tipo
	 *            de búsqueda) (No se usa por compatibilidad a futuro)
	 * @param url
	 *            URL (puede ser de entidad o de contacto en función del tipo de
	 *            búsqueda) (No se usa por compatibilidad a futuro)
	 * @param usuario
	 *            Usuario (No se usa por compatibilidad a futuro)
	 * @param password
	 *            Contraseña (No se usa por compatibilidad a futuro)
	 * @param isnacional_
	 *            Indica localización nacional (puede ser de entidad o de
	 *            contacto en función del tipo de búsqueda)
	 * @param paisId
	 *            Código de país (puede ser de entidad o de contacto en función
	 *            del tipo de búsqueda)
	 * @param nombrePais
	 *            Nmbre país (puede ser de entidad o de contacto en función del
	 *            tipo de búsqueda)
	 * @param provinciaId
	 *            Código provincia (puede ser de entidad o de contacto en
	 *            función del tipo de búsqueda)
	 * @param nombreProvincia
	 *            Nombre provincia (puede ser de entidad o de contacto en
	 *            función del tipo de búsqueda)
	 * @param municipioId
	 *            Código de municipio (puede ser de entidad o de contacto en
	 *            función del tipo de búsqueda)
	 * @param nombreMunicipio
	 *            Nombre municipio (puede ser de entidad o de contacto en
	 *            función del tipo de búsqueda)
	 * @param localidadId
	 *            Código localidad (puede ser de entidad o de contacto en
	 *            función del tipo de búsqueda)
	 * @param nombreLocalidad_
	 *            Nombre localidad (puede ser de entidad o de contacto en
	 *            función del tipo de búsqueda)
	 * @param calleId
	 *            Código calle (puede ser de entidad o de contacto en función
	 *            del tipo de búsqueda)
	 * @param nombreCalle
	 *            Nombre calle (puede ser de entidad o de contacto en función
	 *            del tipo de búsqueda)
	 * @param cpId
	 *            Código postal (puede ser de entidad o de contacto en función
	 *            del tipo de búsqueda)
	 * @param nombreCp
	 *            Nombre código postal (puede ser de entidad o de contacto en
	 *            función del tipo de búsqueda)
	 * @param portalId
	 *            Códig portal (puede ser de entidad o de contacto en función
	 *            del tipo de búsqueda)
	 * @param nombrePortal
	 *            Nombre portal (puede ser de entidad o de contacto en función
	 *            del tipo de búsqueda)
	 * @param usuultmod
	 *            Usuario ultima modificación (puede ser de entidad o de
	 *            contacto en función del tipo de búsqueda) (No se usa por
	 *            compatibilidad a futuro)
	 * @param fecultmod
	 *            Fecha de ultima modificación (puede ser de entidad o de
	 *            contacto en función del tipo de búsqueda) (No se usa por
	 *            compatibilidad a futuro)
	 * @param tipo
	 *            Tipo de búsqueda E - Entidades, C - Contactos
	 * @param grupoarr
	 *            Listados separados por <code>,</code> de identificadores de
	 *            grupos a los que las entidades o los contactos, deben
	 *            pertenecer.
	 * @param entidadarr
	 *            Listados separados por <code>,</code> de identificadores de
	 *            entidades a los que los contactos, deben pertenecer.
	 * @param etiquetaarr
	 *            Listados separados por <code>,</code> de identificadores de
	 *            etiquetas a los que las entidades o los contactos, deben
	 *            pertenecer.
	 * @param fechaDesde
	 *            Fecha desde de ultima modificación del registro (puede ser de
	 *            entidad o de contacto en función del tipo de búsqueda) (No se
	 *            usa por compatibilidad a futuro)
	 * @param fechaHasta
	 *            Fecha hasta de ultima modificación del registro (puede ser de
	 *            entidad o de contacto en función del tipo de búsqueda) (No se
	 *            usa por compatibilidad a futuro)
	 * @param codorg_
	 *            Codigo Organismo
	 * @param request
	 *            Objeto de petición completa.
	 * @param compleDirec
	 *            String con el complemento de la direccion.
	 * @param tipoOrganismo
	 *            String
	 * @param ambitoGeografico
	 *            String
	 * @param cif
	 *            String
	 * @param activasSi_
	 *            String
	 * @param activasNo_
	 *            String
	 * @param tiporb
	 *            String
	 * @return Se proporciona un listado de envio que cumple con los parámetros
	 *         de búsqeda.
	 */
	@ResponseBody()
	@RequestMapping(value = "busqueda", method = RequestMethod.POST)
	public Object search(
			@RequestParam(value = "nombre", required = false) String nombreInput,
			@RequestParam(value = "activa", required = false) String activa,
			@RequestParam(value = "kontsumoGest", required = false, defaultValue = Y42bAgendaConstantes.DB_FALSE) String iskontsumogest,
			@RequestParam(value = "kontsumoNet", required = false, defaultValue = Y42bAgendaConstantes.DB_FALSE) String iskontsumonet,
			@RequestParam(value = "ofertaFormativa", required = false, defaultValue = Y42bAgendaConstantes.DB_FALSE) String isofertaform,
			@RequestParam(value = "consultaWeb", required = false, defaultValue = Y42bAgendaConstantes.DB_FALSE) String isconsultasweb,
			@RequestParam(value = "observaciones", required = false) String observaciones,
			@RequestParam(value = "telefono", required = false) String telefono,
			@RequestParam(value = "fax", required = false) String fax,
			@RequestParam(value = "email", required = false) String email,
			@RequestParam(value = "url", required = false) String url,
			@RequestParam(value = "usuario", required = false) String usuario,
			@RequestParam(value = "password", required = false) String password,
			@RequestParam(value = "isnacional", required = false) String isnacional_,
			@RequestParam(value = "paisId", required = false) String paisId,
			@RequestParam(value = "nombrePais", required = false) String nombrePais,
			@RequestParam(value = "provinciaId", required = false) String provinciaId,
			@RequestParam(value = "nombreProvincia", required = false) String nombreProvincia,
			@RequestParam(value = "municipioId", required = false) String municipioId,
			@RequestParam(value = "nombreMunicipio", required = false) String nombreMunicipio,
			@RequestParam(value = "localidadId", required = false) String localidadId,
			@RequestParam(value = "nombreLocalidad", required = false) String nombreLocalidad_,
			@RequestParam(value = "noraCalleId", required = false) String calleId,
			@RequestParam(value = "nombreCalle", required = false) String nombreCalle,
			@RequestParam(value = "codigoPostal", required = false) String cpId,
			@RequestParam(value = "nombreCp", required = false) String nombreCp,
			@RequestParam(value = "noraPortalId", required = false) String portalId,
			@RequestParam(value = "nombrePortal", required = false) String nombrePortal,
			@RequestParam(value = "usuultmod", required = false) String usuultmod,
			@RequestParam(value = "fecultmod", required = false) Date fecultmod,
			@RequestParam(value = "tipo", required = true) String tipo,
			@RequestParam(value = "grupoarr", required = false) String grupoarr,
			@RequestParam(value = "entidadarr", required = false) String entidadarr,
			@RequestParam(value = "etiquetaarr", required = false) String etiquetaarr,
			@RequestParam(value = "fechaDesde", required = false) String fechaDesde,
			@RequestParam(value = "fechaHasta", required = false) String fechaHasta,
			@RequestParam(value = "codorg", required = false) String codorg_,
			@RequestParam(value = "compleDirec", required = false) String compleDirec,
			@RequestParam(value = "tipoOrganismo", required = false) String tipoOrganismo,
			@RequestParam(value = "ambitoGeografico", required = false) String ambitoGeografico,
			@RequestParam(value = "cif", required = false) String cif,
			@RequestParam(value = "activasSi", required = false) String activasSi_,
			@RequestParam(value = "activasNo", required = false) String activasNo_,
			@RequestParam(value = "tiporb", required = false) String tiporb,
			HttpServletRequest request) {

		try {
			// Preparación de parámetros de entrada
			Entidad entityFilter = null;
			Contacto contactFilter = null;
			List<Grupo> grupos = new ArrayList<Grupo>();
			List<Etiqueta> etiquetas = new ArrayList<Etiqueta>();
			List<Entidad> entidades = new ArrayList<Entidad>();
			Envio envio = null;

			SearchController.logger.debug("AdvancedSearch: START");
			SearchController.logger.debug("AdvancedSearch.TYPE: " + tipo);
			Locale locale = LocaleContextHolder.getLocale();

			// control checks
			boolean activasSi = ("on".equals(activasSi_)) ? true : false;
			boolean activasNo = ("on".equals(activasNo_)) ? true : false;

			if (activasSi && !activasNo) {
				activa = Y42bAgendaConstantes.SI;
			} else if (!activasSi && activasNo) {
				activa = Y42bAgendaConstantes.NO;
			} else {
				activa = null;
			}

			// normalizacion de nombre y codigos de nora para BBDD
			String codorg = ("".equals(codorg_)) ? null : codorg_;
			String nombre = ("".equals(nombreInput)) ? null : nombreInput;
			/*
			 * Tener cuidado con las dos asignaciones de noraPaisId ya que no lo
			 * ransforma a null
			 */

			// logger.debug("/////////////////paisId/////////////////////////|"+paisId.length()+"|/////////////");
			String noraPaisId = null;
			// ("".equals(paisId)) ? null : paisId;
			// noraPaisId = ("0".equals(paisId)) ? null : paisId;
			// logger.debug("/////////////////noraPaisId1/////////////////////////|"+noraPaisId+"|/////////////");
			if ("".equals(paisId)) {
				// logger.debug("/////////////////paisId1/////////////////////////|"+paisId+"|/////////////");
				noraPaisId = null;
			} else if ("0".equals(paisId)) {
				// logger.debug("/////////////////paisId2/////////////////////////|"+paisId+"|/////////////");
				noraPaisId = null;
			} else if ("108".equals(paisId)) {
				// logger.debug("/////////////////paisId3/////////////////////////|"+paisId+"|/////////////");
				noraPaisId = null;
				// logger.debug("/////////////////noraPaisId/////////////////////////|"+noraPaisId+"|/////////////");
			}
			// logger.debug("/////////////////noraPaisId/////////////////////////|"+noraPaisId+"|/////////////");

			// noraPaisId="108";

			String noraProvinciaId = ("".equals(provinciaId)) ? null
					: provinciaId;
			String noraMunicipioId = ("".equals(municipioId)) ? null
					: municipioId;
			String noraLocalidadId = ("".equals(localidadId)) ? null
					: localidadId;
			String noraCalleId = ("".equals(calleId)) ? null : calleId;
			String noraCpId = ("".equals(cpId)) ? null : cpId;
			String noraPortalId = ("".equals(portalId)) ? null : portalId;
			String nombreCalleStr = ("".equals(nombreCalle)) ? null
					: nombreCalle;
			String isnacional = ("".equals(isnacional_)) ? null : isnacional_;
			String nombreLocalidad = ("".equals(nombreLocalidad_)) ? null
					: nombreLocalidad_;

			String grupoarrStr = ("".equals(grupoarr)) ? null : grupoarr;
			String entidadarrStr = ("".equals(entidadarr)) ? null : entidadarr;

			StringBuffer grupoarr2 = new StringBuffer(
					Y42bAgendaConstantes.NUM_3000);
			StringBuffer entidadarr2 = new StringBuffer(
					Y42bAgendaConstantes.NUM_3000);

			if (null != grupoarrStr && !"".equals(grupoarrStr)) {
				for (String id : grupoarrStr.split(",")) {
					String ids = "";
					if (id.lastIndexOf("#") < 1) {
						ids = id.replace("G_G", "G");
						grupoarr2.append(",");
						grupoarr2.append(ids);
					}
					String grupo1 = "";
					String ide1 = "";
					if (id.lastIndexOf("#") > -1) {
						int fin = id.indexOf("#E_E");
						grupo1 = id.substring(0, fin);
						ide1 = grupo1.replace("G_G", "G");
						grupoarr2.append(",");
						grupoarr2.append(ide1);
					}

					String entidadId = "";
					String ide = "";
					if (id.lastIndexOf("" + ide1 + "#") > -1) {
						int inicio = id.indexOf("" + ide1 + "#");
						entidadId = id.substring(inicio);
						ide = entidadId.replace("" + ide1 + "#E_E", "E");
						entidadarr2.append(",");
						entidadarr2.append(ide);
						// grupoarr2 = new StringBuffer(
						// Y42bAgendaConstantes.NUM_3000);
						// grupoarrStr = "";
					}
					// if (id.lastIndexOf("G_ROOT#") > -1) {
					// int inicio = id.indexOf("G_ROOT#");
					// entidadId = id.substring(inicio);
					// ide = entidadId.replace("G_ROOT#E_E", "E");
					// entidadarr2.append(",");
					// entidadarr2.append(ide);
					// // grupoarr2 = new StringBuffer(
					// // Y42bAgendaConstantes.NUM_3000);
					// // grupoarrStr = "";
					// }

				}
				if (null != grupoarr2 && !"".equals(grupoarr2)
						&& grupoarr2.length() > 0) {
					grupoarrStr = grupoarr2.substring(1).toString();

					grupoarrStr = grupoarrStr.replaceAll("G_ROOT", "ROOT");
				}
				if (null != entidadarr2 && !"".equals(entidadarr2)
						&& entidadarr2.length() > 0) {
					entidadarrStr = entidadarr2.substring(1).toString();
				}
			}

			SearchController.logger.debug("grupoarr: " + grupoarrStr);
			if (tipo.equals(Y42bAgendaConstantes.AVD_SEARCH_TYPE_CONTACT)) {
				if (null != entidadarrStr && !"".equals(entidadarrStr)) {

					for (String id : entidadarrStr.split(",")) {
						String entidadId = "";
						String ide = "";
						if (id.lastIndexOf("#E") > -1) {
							int inicio = id.indexOf("#");
							entidadId = id.substring(inicio);
							ide = entidadId.replace("#E_E", "E");
							entidadarr2.append(",");
							entidadarr2.append(ide);
						}
					}
					entidadarrStr = entidadarr2.substring(1).toString();
				}
				SearchController.logger.debug("entidadarr: " + entidadarrStr);
			}
			// Preparar criterios de búsqueda en función del tipo de búsqueda:
			if (tipo.equals(Y42bAgendaConstantes.AVD_SEARCH_TYPE_ENTITY)) {
				String nombreEs = null;
				String nombreEu = null;

				if (locale.getLanguage()
						.equals(Y42bAgendaConstantes.CASTELLANO)) {
					nombreEs = nombre;
				} else {
					nombreEu = nombre;
				}

				/*
				 * Se inicializa la entidad de filtrado con todos los parámetros
				 * de la query
				 */

				entityFilter = new Entidad(null, nombreEs, nombreEu, activa,
						iskontsumogest, iskontsumonet, isofertaform,
						isconsultasweb, isnacional, observaciones, telefono,
						fax, email, url, usuario, password, usuultmod,
						fecultmod, noraPaisId, nombrePais, noraProvinciaId,
						nombreProvincia, noraMunicipioId, nombreMunicipio,
						noraLocalidadId, nombreLocalidad, noraCalleId,
						nombreCalleStr, noraCpId, nombreCp, noraPortalId,
						nombrePortal, codorg, compleDirec, tipoOrganismo,
						ambitoGeografico, cif);

			} else {
				/*
				 * Si se trata de una búsqueda de contactos, se inicializa la
				 * entidad de filtrado solo con los parámetros propios de la
				 * entidad.
				 */
				entityFilter = new Entidad(null, null, null, null,
						iskontsumogest, iskontsumonet, isofertaform,
						isconsultasweb, isnacional, null, null, null, null,
						null, null, null, null, null, null, null, null, null,
						null, null, null, null, null, null, null, null, null,
						null, codorg, null, null, null, null);

				/*
				 * Se inicializa el contacto de filtrado con el resto de
				 * parámetros de la query.
				 */
				contactFilter = new Contacto(null, nombre, null, telefono, fax,
						email, url, isnacional, usuultmod, fecultmod,
						nombrePais, noraProvinciaId, nombreProvincia,
						noraMunicipioId, nombreMunicipio, noraLocalidadId,
						nombreLocalidad, noraCalleId, nombreCalleStr, noraCpId,
						nombreCp, noraPortalId, nombrePortal, noraPaisId,
						compleDirec);

			}

			Date dateAfter = Y42bUtils.parseDate(fechaDesde, locale);
			Date dateBefore = Y42bUtils.parseDate(fechaHasta, locale);

			// Generar el listado de grupos (comun)
			if (null != grupoarrStr && !"".equals(grupoarrStr)) {
				Grupo grupo = null;
				for (String id : grupoarrStr.split(",")) {
					grupo = new Grupo();// NOPMD 2012/02/29 (IDA)
					grupo.setGrupoId(id);
					grupo.setActiva(Y42bAgendaConstantes.SI);
					grupos.add(grupo);
				}
			}

			// Generar el listado listado de etiquetas (comun)
			if (null != etiquetaarr && !"".equals(etiquetaarr)) {
				Etiqueta etiqueta = null;
				for (String id : etiquetaarr.split(",")) {
					etiqueta = new Etiqueta();// NOPMD 2012/02/29 (IDA)
					etiqueta.setEtiquetaId(id);
					etiquetas.add(etiqueta);
				}
			}

			// Generar el listado de entidades (solo contacto)
			if (tipo.equals(Y42bAgendaConstantes.AVD_SEARCH_TYPE_CONTACT)) {
				entidades = this.getContactEntities(entidadarrStr,
						entityFilter, grupos, etiquetas, tiporb);
			}

			// envio = null;
			// Generar envío
			envio = new Envio();
			envio.setSessionOid(request.getSession().getId());
			envio.setTipo(tipo);
			envio.setXmlimportado(Y42bAgendaConstantes.DB_FALSE);
			envio = this.envioService.add(envio);

			// En función del tipo de búsqueda, llamar al método adecuado
			if (tipo.equals(Y42bAgendaConstantes.AVD_SEARCH_TYPE_CONTACT)) {
				this.searchAndAddContactItems(entidades, contactFilter,
						dateAfter, dateBefore, grupos, etiquetas, envio);
			} else {
				this.searchAndAddEntityItems(entityFilter, dateAfter,
						dateBefore, grupos, etiquetas, envio, tiporb);

			}

			return envio;
		} catch (Exception e) {
			SearchController.logger.error("################ Error busqueda: "
					+ e.getMessage());
			throw new ResourceNotFoundException("No data Found.");
		}
	}

	/**
	 * Genera un envío desde un fichero xml de codigos de contactos o de
	 * entidades.
	 * 
	 * @param request
	 *            HttpServletRequest
	 * @param document
	 *            CodesParameter
	 * 
	 * @return El envio generado desde el xml de códigos.
	 */
	@ResponseBody()
	@RequestMapping(method = RequestMethod.POST)
	public Object search(@RequestBody() CodesParameter document,
			HttpServletRequest request) {
		try {
			String searchType = (document.getXml().indexOf("CONTACTOS") > 0) ? Y42bAgendaConstantes.AVD_SEARCH_TYPE_CONTACT
					: Y42bAgendaConstantes.AVD_SEARCH_TYPE_ENTITY;

			// 1) Realizamos el unmarshall del XML proporcionado.
			Object codeXMLs = null;
			if (searchType.equals(Y42bAgendaConstantes.AVD_SEARCH_TYPE_CONTACT)) {
				codeXMLs = Y42bJAXBFactory.unmarshal(CodesContacts.class,
						document.getXml());
			} else {
				codeXMLs = Y42bJAXBFactory.unmarshal(CodesEntities.class,
						document.getXml());
			}

			// 2) Creamos un nuevo envio siguiendo sus reglas de creación.
			Envio envio = new Envio();
			envio.setSessionOid(request.getSession().getId());
			envio.setTipo(searchType);
			envio.setXmlimportado(Y42bAgendaConstantes.DB_TRUE);
			envio = this.envioService.add(envio);

			// 3) Cargamos el xml de codigos del envio.
			if (searchType.equals(Y42bAgendaConstantes.AVD_SEARCH_TYPE_CONTACT)) {
				for (CodesContact xmlContact : ((CodesContacts) codeXMLs)
						.getContactos()) {
					envio = this.loadCodesContact(envio, xmlContact);
				}
			} else {
				for (CodesEntity xmlEntity : ((CodesEntities) codeXMLs)
						.getEntidades()) {
					envio = this.loadCodesEntity(envio, xmlEntity);
				}
			}
			envio.setMailingAsunto(" ");
			this.envioService.update(envio);

			return envio;
		} catch (Exception e) {
			throw new ResourceNotFoundException("No data Found.");
		}
	}

	/**
	 * Devuelve los items de resultado de busqueda con o sin paginacion
	 * dependiendo de la request.
	 * 
	 * @param envioId
	 *            String
	 * @param request
	 *            HttpServletRequest
	 * @return object
	 * @throws Exception
	 */
	@ResponseBody()
	@RequestMapping(value = "/items", method = RequestMethod.GET)
	public Object getResultItems(
			@RequestParam(value = "envioId", required = true) String envioId,
			HttpServletRequest request) {
		try {
			Envio envio = new Envio();
			envio.setEnvioId(envioId);
			Item item = new Item();
			item.setEnvio(envio);

			if (request.getHeader("JQGridModel") != null
					&& request.getHeader("JQGridModel").equals("true")) {
				Pagination pagination = new Pagination();
				pagination.setPage(Long.valueOf(request.getParameter("page")));
				pagination.setRows(Long.valueOf(request.getParameter("rows")));
				pagination.setSort(request.getParameter("sidx"));
				pagination.setAscDsc(request.getParameter("sord"));

				List<Item> items = this.itemService.findAll(item, pagination);

				if (items == null) {
					throw new Exception("No data Found.");
				}

				// Long total = Long.valueOf(items.size() + "");
				Long total = this.itemService.findAllCount(item);
				JQGridJSONModel data = new JQGridJSONModel();
				data.setPage(request.getParameter("page"));
				data.setRecords(total.intValue());
				data.setTotal(total, pagination.getRows());
				data.setRows(items);
				return data;

			} else {
				List<Item> items = this.itemService.findAll(item, null);
				if (items == null) {
					throw new Exception("No data Found.");
				}
				return items;
			}
		} catch (Exception e) {
			throw new ResourceNotFoundException("No data Found.");
		}
	}

	/**
	 * Load search element tree
	 * 
	 * @param estadoActivas
	 *            String
	 * @param hideEntities
	 *            String
	 * @param response
	 *            HttpServletResponse
	 * @throws IOException
	 *             IOException
	 */
	@RequestMapping(value = "/tree", method = RequestMethod.GET)
	public void getSearchTree(
			// @RequestParam(value = "showInactive", required = false) String
			// showInactive,
			@RequestParam(value = "estadoActivas", required = false) String estadoActivas,
			@RequestParam(value = "hideEntities", required = false) String hideEntities,
			HttpServletResponse response) throws IOException {
		response.setHeader("Cache-Control", "no-cache");
		response.setCharacterEncoding("ISO-8859-1");
		response.setContentType("text/html;charset=utf-8");

		PrintWriter out = response.getWriter();

		/*
		 * boolean mostrarNoActivas = Boolean.valueOf(showInactive);
		 * 
		 * Y42bTree arbol = this.arbolService.obtenerArbol(Boolean
		 * .valueOf(showInactive));
		 * 
		 * arbol.setMostrarNoActivas(mostrarNoActivas);
		 */

		Y42bTree arbol = this.arbolService.obtenerArbol(estadoActivas);

		arbol.setEstadoActivas(estadoActivas);

		arbol.setNodeActive(Y42bAgendaConstantes.GRUPO_RAIZ_ID);

		String json = "";
		List<String> selectedIdList = new ArrayList<String>();

		if ((Y42bAgendaConstantes.ARBOL_FALSE).equals(hideEntities)) {
			json = Y42bProcessTree.obtieneJsonArbol(arbol);
		} else {
			json = Y42bEntityGroupTree.obtieneJsonArbol(arbol, selectedIdList);
		}

		SearchController.logger
				.debug("******************************************");
		SearchController.logger.debug("Arbol--Total: ");
		SearchController.logger.debug(json);
		SearchController.logger
				.debug("******************************************");
		out.println(json);
		out.flush();
		out.close();
	}

	/**
	 * Method 'selectItem'
	 * 
	 * @param itemRef
	 *            String
	 * @param envioId
	 *            String
	 * @param response
	 *            HttpServletResponse
	 */
	@RequestMapping(value = "/select", method = RequestMethod.GET)
	public void selectItem(
			@RequestParam(value = "itemRef", required = false) String itemRef,
			@RequestParam(value = "envioId", required = false) String envioId,
			HttpServletResponse response) {
		try {
			Envio envio = new Envio();
			envio.setEnvioId(envioId);

			Item item = new Item();
			item.setItemRef(itemRef);
			item.setEnvio(envio);
			item = this.itemService.find(item);

			item.setSeleccionado(Y42bAgendaConstantes.DB_TRUE);
			this.itemService.update(item);
			response.setStatus(HttpServletResponse.SC_OK);

		} catch (ResourceNotFoundException er) {
			response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
			throw new ResourceNotFoundException(er.getMessage());

		} catch (Exception e) {
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			throw new ResourceNotFoundException("No data Found.");
		}
	}

	/**
	 * Method 'unselectItem'
	 * 
	 * @param itemRef
	 *            String
	 * @param envioId
	 *            String
	 * @param response
	 *            HttpServletResponse
	 */
	@RequestMapping(value = "/unselect", method = RequestMethod.GET)
	public void unselectItem(
			@RequestParam(value = "itemRef", required = false) String itemRef,
			@RequestParam(value = "envioId", required = false) String envioId,
			HttpServletResponse response) {
		try {
			Envio envio = new Envio();
			envio.setEnvioId(envioId);

			Item item = new Item();
			item.setItemRef(itemRef);
			item.setEnvio(envio);
			item = this.itemService.find(item);

			item.setSeleccionado(Y42bAgendaConstantes.DB_FALSE);
			this.itemService.update(item);
			response.setStatus(HttpServletResponse.SC_OK);

		} catch (ResourceNotFoundException er) {
			response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
			throw new ResourceNotFoundException(er.getMessage());

		} catch (Exception e) {
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			throw new ResourceNotFoundException("No data Found.");
		}
	}

	/**
	 * Method 'updateSeleccion' al paginar, ordenar, ...
	 * 
	 * @param envioId
	 *            String
	 * @param boolSeleccionado
	 *            boolean
	 * @param response
	 *            HttpServletResponse
	 */
	@RequestMapping(value = "/updateSeleccion/{envioId}/{boolSeleccionado}", method = RequestMethod.DELETE)
	public void eliminarSeleccionados(@PathVariable String envioId,
			@PathVariable boolean boolSeleccionado, HttpServletResponse response) {
		response.setContentType("text/javascript;charset=utf-8");
		response.setHeader("Pragma", "cache");
		response.setHeader("Expires", "0");
		response.setHeader("Cache-Control", "private");

		try {
			Envio envio = new Envio();
			envio.setEnvioId(envioId);

			String valorSeleccionado = "";
			if (boolSeleccionado) {
				valorSeleccionado = Y42bAgendaConstantes.DB_TRUE;
			} else {
				valorSeleccionado = Y42bAgendaConstantes.DB_FALSE;
			}

			Item item = new Item();
			item.setEnvio(envio);
			item.setSeleccionado(valorSeleccionado);

			this.itemService.updateSeleccion(item);

		} catch (ResourceNotFoundException er) {
			response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
			throw new ResourceNotFoundException(er.getMessage());

		} catch (Exception e) {
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			throw new ResourceNotFoundException("No data Found.");
		}
	}

	/**
	 * Method 'loadContactDetail'.
	 * 
	 * @param contactId
	 *            String
	 * @param model
	 *            Model
	 * 
	 * @return Model
	 */
	@RequestMapping(value = "contactDetail", method = RequestMethod.GET)
	public ModelAndView loadContactDetail(
			@RequestParam(value = "contactId", required = false) String contactId,
			Model model) {
		model.addAttribute("defaultLanguage",
				this.appConfiguration.get("y42bVistaWar.default.language"));
		model.addAttribute("defaultLayout",
				this.appConfiguration.get("y42bVistaWar.default.layout"));

		Contacto contact = new Contacto();
		contact.setContactoId(contactId);
		contact = this.contactService.find(contact);

		Etiqueta etiqueta = new Etiqueta();
		contact = this.contactService.findEtiquetaContacto(contact, etiqueta,
				null);

		/*
		 * Y42bLocalizacion loc = new Y42bLocalizacion(this.paisService,
		 * this.provinciaService, this.municipioService, this.localidadService,
		 * this.calleService);
		 * 
		 * Localizacion localizacion =new Localizacion();
		 * localizacion.setPaisId(contact.getNoraPaisId());
		 * localizacion.setProvinciaId(contact.getNoraProvinciaId());
		 * localizacion.setMunicipioId(contact.getNoraMunicipioId());
		 * localizacion.setLocalidadId(contact.getNoraLocalidadId());
		 * localizacion.setCalleId(contact.getNoraCalleId());
		 * 
		 * localizacion=loc.setLocalizacion(localizacion);
		 */

		// Etiquetas
		StringBuffer lstEt = new StringBuffer(Y42bAgendaConstantes.BUFFER_50);
		for (Etiqueta et : contact.getEtiquetas()) {
			lstEt.append(et.getNombre());
			lstEt.append(",");
		}
		StringBuffer etiquetasBuff = new StringBuffer("");
		String etiquetas = lstEt.toString();
		if (etiquetas.length() > 0) {
			etiquetas = etiquetas.substring(0, etiquetas.length() - 1);
		}

		etiquetasBuff.append("[");
		etiquetasBuff.append(etiquetas);
		etiquetasBuff.append("]");
		// fin etiquetas

		// model.addAttribute("pais",
		// contact.getNombrePais() != null ? contact.getNombrePais() : "");
		// model.addAttribute(
		// "provincia",
		// contact.getNombreProvincia() != null ? contact
		// .getNombreProvincia() : "");
		// model.addAttribute(
		// "municipio",
		// contact.getNombreMunicipio() != null ? contact
		// .getNombreMunicipio() : "");
		// model.addAttribute(
		// "localidad",
		// contact.getNombreLocalidad() != null ? contact
		// .getNombreLocalidad() : "");
		// model.addAttribute("calle",
		// contact.getNombreCalle() != null ? contact.getNombreCalle()
		// : "");
		model.addAttribute("contact", contact);
		model.addAttribute("etiquetas", etiquetasBuff.toString());
		return new ModelAndView("contactDetail", "model", model);
	}

	/**
	 * Method 'loadEntityDetail'.
	 * 
	 * @param model
	 *            Model
	 * @param entityId
	 *            String
	 * @return String
	 */
	@RequestMapping(value = "entityDetail", method = RequestMethod.GET)
	public ModelAndView loadEntityDetail(
			@RequestParam(value = "entityId", required = false) String entityId,
			Model model) {
		model.addAttribute("defaultLanguage",
				this.appConfiguration.get("y42bVistaWar.default.language"));
		model.addAttribute("defaultLayout",
				this.appConfiguration.get("y42bVistaWar.default.layout"));

		Entidad entity = new Entidad();
		entity.setEntidadId(entityId);
		entity = this.entityService.find(entity);

		Etiqueta etiqueta = new Etiqueta();
		entity = this.entityService.findEtiquetaEntidad(entity, etiqueta, null);

		/*
		 * Y42bLocalizacion loc = new Y42bLocalizacion(this.paisService,
		 * this.provinciaService, this.municipioService, this.localidadService,
		 * this.calleService);
		 * 
		 * Localizacion localizacion =new Localizacion();
		 * localizacion.setPaisId(entity.getNoraPaisId());
		 * localizacion.setProvinciaId(entity.getNoraProvinciaId());
		 * localizacion.setMunicipioId(entity.getNoraMunicipioId());
		 * localizacion.setLocalidadId(entity.getNoraLocalidadId());
		 * localizacion.setCalleId(entity.getNoraCalleId());
		 * 
		 * localizacion=loc.setLocalizacion(localizacion);
		 */

		// Etiquetas
		StringBuffer lstEt = new StringBuffer(Y42bAgendaConstantes.BUFFER_50);
		for (Etiqueta et : entity.getEtiquetas()) {
			lstEt.append(et.getNombre());
			lstEt.append(",");
		}
		StringBuffer etiquetasBuff = new StringBuffer("");
		String etiquetas = lstEt.toString();
		if (etiquetas.length() > 0) {
			etiquetas = etiquetas.substring(0, etiquetas.length() - 1);
		}

		etiquetasBuff.append("[");
		etiquetasBuff.append(etiquetas);
		etiquetasBuff.append("]");

		// fin etiquetas

		entity.setNombreEs(Y42bUtils.encodeHtmlTag(entity.getNombreEs()));
		entity.setNombreEu(Y42bUtils.encodeHtmlTag(entity.getNombreEu()));

		// model.addAttribute("pais", entity.getNombrePais());
		// model.addAttribute("provincia", entity.getNombreProvincia());
		// model.addAttribute("municipio", entity.getNombreMunicipio());
		// model.addAttribute("localidad", entity.getNombreLocalidad());
		// model.addAttribute("calle", entity.getNombreCalle());
		model.addAttribute("entity", entity);
		model.addAttribute("etiquetas", etiquetasBuff.toString());
		return new ModelAndView("entityDetail", "model", model);
	}

	/**
	 * Method 'loadSelectByCodes'.
	 * 
	 * @param model
	 *            Model
	 * @return String
	 */
	@RequestMapping(value = "selectByCodes", method = RequestMethod.GET)
	public ModelAndView loadSelectByCodes(Model model) {
		model.addAttribute("defaultLanguage",
				this.appConfiguration.get("y42bVistaWar.default.language"));
		model.addAttribute("defaultLayout",
				this.appConfiguration.get("y42bVistaWar.default.layout"));
		return new ModelAndView("selectByCodes", "model", model);
	}

	/**
	 * Method 'loadSendMail'.
	 * 
	 * @param model
	 *            Model
	 * @param envioId
	 *            String
	 * @return String
	 */
	@RequestMapping(value = "/sendMail/{envioId}", method = RequestMethod.GET)
	public ModelAndView loadSendMail(@PathVariable() String envioId, Model model) {

		model.addAttribute("defaultLanguage",
				this.appConfiguration.get("y42bVistaWar.default.language"));
		model.addAttribute("defaultLayout",
				this.appConfiguration.get("y42bVistaWar.default.layout"));
		model.addAttribute("senMailEnvioId", envioId);
		return new ModelAndView("sendMail", "model", model);
	}

	/**
	 * Method 'sendMail'.
	 * 
	 * @param mailForm
	 *            Object
	 */
	@RequestMapping(value = "sendMail", method = RequestMethod.POST)
	public void sendMail(Object mailForm) {
		try {
			SearchController.logger.info("sendMail execution completed.");
		} catch (Exception e) {
			throw new ResourceNotFoundException("No data Found.");
		}
	}

	/**
	 * Method 'getExcel'.
	 * 
	 * @param envioId
	 *            String
	 * @param tipoExcel
	 *            String
	 * @param mySession
	 *            HttpSession
	 * @param response
	 *            HttpServletResponse
	 */
	@RequestMapping(value = "/excel/{envioId}", method = RequestMethod.GET)
	public void getExcel(
			@PathVariable() String envioId,
			@RequestParam(value = "tipoExcel", required = false) String tipoExcel,
			HttpSession mySession, HttpServletResponse response) {
		try {
			response.setCharacterEncoding("ISO-8859-1");
			response.setHeader("Cache-Control", "no-cache");
			// response.setContentType("text/html");
			// response.setHeader("Content-type: application/octet-stream");
			response.setContentType("application/vnd.ms-excel");
			String nombre = "fichero.xls";
			response.setHeader("Content-Disposition", "attachment; filename=\""
					+ nombre + "\"");

			Envio envio = new Envio();
			envio.setEnvioId(envioId);
			envio = this.envioService.find(envio);
			envio.setFechaOperacion(Calendar.getInstance().getTime());
			envio.setTipoOperacion(Y42bAgendaConstantes.TIPO_OP_EXCEL);
			envio.setMailingAsunto(" ");
			this.envioService.update(envio);

			Item item = new Item();
			item.setEnvio(envio);
			item.setSeleccionado(Y42bAgendaConstantes.DB_TRUE);

			List<Item> items = this.itemService.findAll(item, null);
			Y42bExcelGenerator excelGen = new Y42bExcelGenerator(
					this.groupService, this.entityService, this.contactService,
					this.paisService, this.provinciaService,
					this.municipioService, this.localidadService,
					this.calleService);
			String xslString = excelGen.getExcel(envio, items, tipoExcel);
			logger.debug("********************EXCEL***********************************************************");
			logger.debug(xslString);
			PrintWriter out = response.getWriter();
			logger.debug("********************FIN EXCEL***********************************************************");
			out.println(xslString);
			out.flush();
			out.close();
			SearchController.logger.info("sendMail execution completed.");
		} catch (Exception e) {
			e.printStackTrace();
			throw new ResourceNotFoundException("No data Found.");
		}
	}

	/**
	 * Method 'getEnvelopeLabels'.
	 * 
	 * @param envioId
	 *            envioid
	 * @param envelopeType
	 *            env
	 * @param model
	 *            Model
	 */
	@RequestMapping(value = "envelopes", method = RequestMethod.GET)
	public void getEnvelopeLabels(
			@RequestParam(value = "envioId", required = false) String envioId,
			@RequestParam(value = "envelopeType", required = false) String envelopeType,
			Model model) {
		try {
			SearchController.logger.info("sendMail execution completed.");
		} catch (Exception e) {
			throw new ResourceNotFoundException("No data Found.");
		}
	}

	/**
	 * Loading Main tree de la lista de etiquetas para una determinada entidad
	 * 
	 * @param pEtiquetas
	 *            String
	 * @param response
	 *            HttpServletResponse
	 * @throws IOException
	 *             IOException
	 */
	@RequestMapping(value = "lista_etiquetas", method = RequestMethod.GET)
	public void showListaEtiquetas(
			@RequestParam(value = "etiquetas", required = false) String pEtiquetas,
			HttpServletResponse response) throws IOException {
		response.setHeader("Cache-Control", "no-cache");
		PrintWriter out = response.getWriter();

		List<String> selectedIdList = new ArrayList<String>();

		// Si entidadId = 0 se trata de un mantenimiento
		// Obtiene lista de etiquetas del sistema
		List<Etiqueta> lstEtiquetasCompletas = this.etiquetaService.findAll(
				null, null);

		// Obtiene lista de etiquetas y marca las etiquetas seleccionadas
		String etiquetas = "";
		if (pEtiquetas == null) {
			etiquetas = "";
		} else {
			etiquetas = pEtiquetas;
		}

		String[] arrEtiquetasSelect = etiquetas.split(",");
		for (int k = 0; k < arrEtiquetasSelect.length; k++) {
			selectedIdList.add(arrEtiquetasSelect[k]);
		}

		String json = Y42bEtiquetasTree.obtieneJsonArbol(lstEtiquetasCompletas,
				selectedIdList);
		out.println(json);

	}

	/**
	 * Method 'handle'.
	 * 
	 * @param e
	 *            ControlException
	 * @return String
	 */
	@ExceptionHandler()
	public @ResponseBody()
	String handle(ControlException e) {
		SearchController.logger.warn(e.getMessage());
		return e.getMessage();
	}

	/**
	 * Method 'getAppConfiguration'.
	 * 
	 * @return appConfiguration
	 */
	public Properties getAppConfiguration() {
		return this.appConfiguration;
	}

	/**
	 * Method 'setAppConfiguration'.
	 * 
	 * @param appConfiguration
	 *            Properties
	 * @return
	 */
	public void setAppConfiguration(Properties appConfiguration) {
		this.appConfiguration = appConfiguration;
	}

	// // PRIVATE METHODS // //

	/**
	 * Carga las entidades desde el xml y añade los items a la bbdd. Esta carga
	 * tiene dos restricciones:
	 * 
	 * a) Si el xml proporciona campos adicionales, estos podran estar
	 * informados o no en los registros de entrada, pero la relación CAMPO -
	 * NOMBRE CAMPO, debera mantenerse en todos los registros del documento XML.
	 * (No se puede dar que para un registro CAMPO1 se llame "atributo1" y para
	 * otro registro, CAMPO1 se llame "atributo2").
	 * 
	 * b) Los oid de Entidad o de Contacto proporcionados por los registros del
	 * documento XML, deben existir en la base de datos de organismos, si falla
	 * uno solo, el documentoXML se rechaza eliminando el envio.
	 * 
	 * @param envio
	 *            Envio
	 * @param xmlContact
	 *            CodesContact
	 * @return envio
	 * @throws Exception
	 *             Exception
	 */
	private Envio loadCodesContact(Envio envio, CodesContact xmlContact)
			throws Exception {

		if (!this.setFieldNames(envio, xmlContact)) {
			throw new Exception("Nombre de campo de registro invalido");
		}

		Contacto contact = new Contacto();
		contact.setContactoId(xmlContact.getCode());

		contact = this.contactService.find(contact);

		Item item = this.getItem(envio, contact, xmlContact);
		this.itemService.add(item);

		return envio;
	}

	/**
	 * Carga las entidades desde el xml y añade los items a la bbdd. Esta carga
	 * tiene dos restricciones:
	 * 
	 * a) Si el xml proporciona campos adicionales, estos podran estar
	 * informados o no en los registros de entrada, pero la relación CAMPO -
	 * NOMBRE CAMPO, debera mantenerse en todos los registros del documento XML.
	 * (No se puede dar que para un registro CAMPO1 se llame "atributo1" y para
	 * otro registro, CAMPO1 se llame "atributo2").
	 * 
	 * b) Los oid de Entidad o de Contacto proporcionados por los registros del
	 * documento XML, deben existir en la base de datos de organismos, si falla
	 * uno solo, el documentoXML se rechaza eliminando el envio.
	 * 
	 * @param envio
	 *            Envio
	 * @param xmlEntity
	 *            CodesEntity
	 * @return envio
	 * @throws Exception
	 *             Exception
	 */
	private Envio loadCodesEntity(Envio envio, CodesEntity xmlEntity)
			throws Exception {

		if (!this.setFieldNames(envio, xmlEntity)) {
			throw new Exception("Nombre de campo de registro invalido");
		}

		Entidad entity = new Entidad();
		entity.setEntidadId(xmlEntity.getCode());

		entity = this.entityService.find(entity);

		if (entity != null) {
			Item item = this.getItem(envio, entity, xmlEntity);
			this.itemService.add(item);
		}

		return envio;
	}

	/**
	 * Asigna los nombres de los campos del envio y comprueba que sean validos.
	 * 
	 * @param envio
	 *            Envio
	 * @param xmlContact
	 *            CodesContact
	 * @return true si la asignacion se ha llevado a cabo y validado
	 *         correctamente.
	 */
	private boolean setFieldNames(Envio envio, CodesContact xmlContact) {
		if (null == envio.getXmlnombrecampo1()
				&& null != xmlContact.getCampo1()) {
			envio.setXmlnombrecampo1(xmlContact.getCampo1().getName());
		} else if (null != xmlContact.getCampo1()
				&& !envio.getXmlnombrecampo1().equals(
						xmlContact.getCampo1().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo2()
				&& null != xmlContact.getCampo2()) {
			envio.setXmlnombrecampo2(xmlContact.getCampo2().getName());
		} else if (null != xmlContact.getCampo2()
				&& !envio.getXmlnombrecampo2().equals(
						xmlContact.getCampo2().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo3()
				&& null != xmlContact.getCampo3()) {
			envio.setXmlnombrecampo3(xmlContact.getCampo3().getName());
		} else if (null != xmlContact.getCampo3()
				&& !envio.getXmlnombrecampo3().equals(
						xmlContact.getCampo3().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo4()
				&& null != xmlContact.getCampo4()) {
			envio.setXmlnombrecampo4(xmlContact.getCampo4().getName());
		} else if (null != xmlContact.getCampo4()
				&& !envio.getXmlnombrecampo4().equals(
						xmlContact.getCampo4().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo5()
				&& null != xmlContact.getCampo5()) {
			envio.setXmlnombrecampo5(xmlContact.getCampo5().getName());
		} else if (null != xmlContact.getCampo5()
				&& !envio.getXmlnombrecampo5().equals(
						xmlContact.getCampo5().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo6()
				&& null != xmlContact.getCampo6()) {
			envio.setXmlnombrecampo6(xmlContact.getCampo6().getName());
		} else if (null != xmlContact.getCampo6()
				&& !envio.getXmlnombrecampo6().equals(
						xmlContact.getCampo6().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo7()
				&& null != xmlContact.getCampo7()) {
			envio.setXmlnombrecampo7(xmlContact.getCampo7().getName());
		} else if (null != xmlContact.getCampo7()
				&& !envio.getXmlnombrecampo7().equals(
						xmlContact.getCampo7().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo8()
				&& null != xmlContact.getCampo8()) {
			envio.setXmlnombrecampo8(xmlContact.getCampo8().getName());
		} else if (null != xmlContact.getCampo8()
				&& !envio.getXmlnombrecampo8().equals(
						xmlContact.getCampo8().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo9()
				&& null != xmlContact.getCampo9()) {
			envio.setXmlnombrecampo9(xmlContact.getCampo9().getName());
		} else if (null != xmlContact.getCampo9()
				&& !envio.getXmlnombrecampo9().equals(
						xmlContact.getCampo9().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo10()
				&& null != xmlContact.getCampo10()) {
			envio.setXmlnombrecampo10(xmlContact.getCampo10().getName());
		} else if (null != xmlContact.getCampo10()
				&& !envio.getXmlnombrecampo10().equals(
						xmlContact.getCampo10().getName())) {
			return false;
		}
		return true;
	}

	/**
	 * Asigna los nombres de los campos del envio y comprueba que sean validos.
	 * 
	 * @param envio
	 *            Envio
	 * @param xmlEntity
	 *            CodesEntity
	 * @return true si la asignacion se ha llevado a cabo y validado
	 *         correctamente.
	 */
	private boolean setFieldNames(Envio envio, CodesEntity xmlEntity) {
		if (null == envio.getXmlnombrecampo1() && null != xmlEntity.getCampo1()) {
			envio.setXmlnombrecampo1(xmlEntity.getCampo1().getName());
		} else if (null != xmlEntity.getCampo1()
				&& !envio.getXmlnombrecampo1().equals(
						xmlEntity.getCampo1().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo2() && null != xmlEntity.getCampo2()) {
			envio.setXmlnombrecampo2(xmlEntity.getCampo2().getName());
		} else if (null != xmlEntity.getCampo2()
				&& !envio.getXmlnombrecampo2().equals(
						xmlEntity.getCampo2().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo3() && null != xmlEntity.getCampo3()) {
			envio.setXmlnombrecampo3(xmlEntity.getCampo3().getName());
		} else if (null != xmlEntity.getCampo3()
				&& !envio.getXmlnombrecampo3().equals(
						xmlEntity.getCampo3().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo4() && null != xmlEntity.getCampo4()) {
			envio.setXmlnombrecampo4(xmlEntity.getCampo4().getName());
		} else if (null != xmlEntity.getCampo4()
				&& !envio.getXmlnombrecampo4().equals(
						xmlEntity.getCampo4().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo5() && null != xmlEntity.getCampo5()) {
			envio.setXmlnombrecampo5(xmlEntity.getCampo5().getName());
		} else if (null != xmlEntity.getCampo5()
				&& !envio.getXmlnombrecampo5().equals(
						xmlEntity.getCampo5().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo6() && null != xmlEntity.getCampo6()) {
			envio.setXmlnombrecampo6(xmlEntity.getCampo6().getName());
		} else if (null != xmlEntity.getCampo6()
				&& !envio.getXmlnombrecampo6().equals(
						xmlEntity.getCampo6().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo7() && null != xmlEntity.getCampo7()) {
			envio.setXmlnombrecampo7(xmlEntity.getCampo7().getName());
		} else if (null != xmlEntity.getCampo7()
				&& !envio.getXmlnombrecampo7().equals(
						xmlEntity.getCampo7().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo8() && null != xmlEntity.getCampo8()) {
			envio.setXmlnombrecampo8(xmlEntity.getCampo8().getName());
		} else if (null != xmlEntity.getCampo8()
				&& !envio.getXmlnombrecampo8().equals(
						xmlEntity.getCampo8().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo9() && null != xmlEntity.getCampo9()) {
			envio.setXmlnombrecampo9(xmlEntity.getCampo9().getName());
		} else if (null != xmlEntity.getCampo9()
				&& !envio.getXmlnombrecampo9().equals(
						xmlEntity.getCampo9().getName())) {
			return false;
		}

		if (null == envio.getXmlnombrecampo10()
				&& null != xmlEntity.getCampo10()) {
			envio.setXmlnombrecampo10(xmlEntity.getCampo10().getName());
		} else if (null != xmlEntity.getCampo10()
				&& !envio.getXmlnombrecampo10().equals(
						xmlEntity.getCampo10().getName())) {
			return false;
		}
		return true;
	}

	/**
	 * Generar item a partir de xml de contacto y contacto.
	 * 
	 * @param envio
	 *            Envio
	 * @param contact
	 *            Contacto
	 * @param xmlContact
	 *            CodesContact
	 * @return item
	 */
	private Item getItem(Envio envio, Contacto contact, CodesContact xmlContact) {
		Item item = new Item();
		item.setEnvio(envio);
		item.setItemRef(contact.getContactoId());
		item.setNombre(contact.getNombre());
		this.setLocation(item, contact.getIsnacional(),
				contact.getNombreLocalidad(), contact.getNombreProvincia(),
				contact.getNombrePais());
		item.setEmail(contact.getEmail());
		item.setTelefono(contact.getTelefono());
		item.setSeleccionado(Y42bAgendaConstantes.DB_TRUE);
		if (xmlContact.getCampo1() != null) {
			item.setXmlcampo1(xmlContact.getCampo1().getValue());
		}
		if (xmlContact.getCampo2() != null) {
			item.setXmlcampo2(xmlContact.getCampo2().getValue());
		}
		if (xmlContact.getCampo3() != null) {
			item.setXmlcampo3(xmlContact.getCampo3().getValue());
		}
		if (xmlContact.getCampo4() != null) {
			item.setXmlcampo4(xmlContact.getCampo4().getValue());
		}
		if (xmlContact.getCampo5() != null) {
			item.setXmlcampo5(xmlContact.getCampo5().getValue());
		}
		if (xmlContact.getCampo6() != null) {
			item.setXmlcampo6(xmlContact.getCampo6().getValue());
		}
		if (xmlContact.getCampo7() != null) {
			item.setXmlcampo7(xmlContact.getCampo7().getValue());
		}
		if (xmlContact.getCampo8() != null) {
			item.setXmlcampo8(xmlContact.getCampo8().getValue());
		}
		if (xmlContact.getCampo9() != null) {
			item.setXmlcampo9(xmlContact.getCampo9().getValue());
		}
		if (xmlContact.getCampo10() != null) {
			item.setXmlcampo10(xmlContact.getCampo10().getValue());
		}
		return item;
	}

	/**
	 * Generar item a partir de xml de entidad y entidad.
	 * 
	 * @param envio
	 *            Envio
	 * @param entity
	 *            Entidad
	 * @param xmlEntity
	 *            CodesEntity
	 * @return item
	 */
	private Item getItem(Envio envio, Entidad entity, CodesEntity xmlEntity) {
		Item item = new Item();
		item.setEnvio(envio);
		item.setItemRef(entity.getEntidadId());
		item.setNombre(entity.getNombreEs());
		this.setLocation(item, entity.getIsnacional(),
				entity.getNombreLocalidad(), entity.getNombreProvincia(),
				entity.getNombrePais());
		item.setEmail(entity.getEmail());
		item.setTelefono(entity.getTelefono());
		item.setSeleccionado(Y42bAgendaConstantes.DB_TRUE);
		if (xmlEntity.getCampo1() != null) {
			item.setXmlcampo1(xmlEntity.getCampo1().getValue());
		}
		if (xmlEntity.getCampo2() != null) {
			item.setXmlcampo2(xmlEntity.getCampo2().getValue());
		}
		if (xmlEntity.getCampo3() != null) {
			item.setXmlcampo3(xmlEntity.getCampo3().getValue());
		}
		if (xmlEntity.getCampo4() != null) {
			item.setXmlcampo4(xmlEntity.getCampo4().getValue());
		}
		if (xmlEntity.getCampo5() != null) {
			item.setXmlcampo5(xmlEntity.getCampo5().getValue());
		}
		if (xmlEntity.getCampo6() != null) {
			item.setXmlcampo6(xmlEntity.getCampo6().getValue());
		}
		if (xmlEntity.getCampo7() != null) {
			item.setXmlcampo7(xmlEntity.getCampo7().getValue());
		}
		if (xmlEntity.getCampo8() != null) {
			item.setXmlcampo8(xmlEntity.getCampo8().getValue());
		}
		if (xmlEntity.getCampo9() != null) {
			item.setXmlcampo9(xmlEntity.getCampo9().getValue());
		}
		if (xmlEntity.getCampo10() != null) {
			item.setXmlcampo10(xmlEntity.getCampo10().getValue());
		}
		return item;
	}

	/**
	 * Genera el listado de oid de entidades que cumplen con los criterios de
	 * búsqueda de entidades de la query junto con las proporcionadas
	 * directamente por el usuario.
	 * 
	 * @param entidadarr
	 *            String
	 * @param entityFilter
	 *            Entidad
	 * @param grupos
	 *            List<Grupo>
	 * @param etiquetas
	 *            List<Etiqueta>
	 * @param tiporb
	 *            String
	 * @return entidades
	 */
	private List<Entidad> getContactEntities(String entidadarr,
			Entidad entityFilter, List<Grupo> grupos, List<Etiqueta> etiquetas,
			String tiporb) {

		List<Entidad> entidades = new ArrayList<Entidad>();

		// Tratamiento del listado de entidades
		Set<String> inputEntidadIds = new HashSet<String>();
		if (null != entidadarr && !"".equals(entidadarr)) {
			for (String id : entidadarr.split(",")) {
				inputEntidadIds.add(id);
			}
		}

		// Obtener todas las entidades que cumplen los criterios de
		// entidades
		List<Entidad> result = this.entityService.advancedSearchAll(
				entityFilter, grupos, etiquetas, null, null, null, tiporb);

		SearchController.logger.debug("Entidades buscadas: " + result.size());

		// Filtrar entidades para que no haya duplicados

		for (Entidad entidad : result) {
			for (String id : inputEntidadIds) {
				if (entidad.getEntidadId().equalsIgnoreCase(id)) {
					entidades.add(entidad);
				}
			}
		}

		// JAVI
		// for (Entidad entidad : result) {
		// //inputEntidadIds.add(entidad.getEntidadId());
		// entidades.add(entidad);
		// }
		//
		// for (String id : inputEntidadIds) {
		// Entidad entidadd = new Entidad();//NOPMD 2012/02/29 (IDA)
		// entidadd.setEntidadId(id);
		// entidades.add(entidadd);
		// }

		return entidades;
	}

	/**
	 * Lleva a cabo la búsqueda y puebla la tabla de items con los resultados.
	 * 
	 * @param entidades
	 *            List<Entidad>
	 * @param contactFilter
	 *            Contacto
	 * @param fechaDesde
	 *            Date
	 * @param fechaHasta
	 *            Date
	 * @param grupos
	 *            List<Grupo>
	 * @param etiquetas
	 *            List<Etiqueta>
	 * @param envio
	 *            Envio
	 */
	private void searchAndAddContactItems(List<Entidad> entidades,
			Contacto contactFilter, Date fechaDesde, Date fechaHasta,
			List<Grupo> grupos, List<Etiqueta> etiquetas, Envio envio) {

		List<Contacto> results = new ArrayList<Contacto>();

		// Verificamos si tenemos entidad a la que debe pertenecer los
		// contactos.
		if (!entidades.isEmpty()) {
			results = this.contactService.advancedSearch(contactFilter,
					entidades, etiquetas, fechaDesde, fechaHasta, null);
		}

		// else {
		// /*
		// * Solo buscamos sin entidades, si no se pasan criterios de grupos y
		// * etiquetas de las entidades.
		// */
		// results = this.contactService.advancedSearch(contactFilter, null,
		// etiquetas, fechaDesde, fechaHasta, null);
		// }

		if (!results.isEmpty()) {
			// Generación de items de contactos
			Item item = new Item();
			for (Contacto contact : results) {
				// item = new Item();
				item.setEnvio(envio);
				item.setItemRef(contact.getContactoId());
				item.setNombre(contact.getNombre());
				this.setLocation(item, contact.getIsnacional(),
						contact.getNombreLocalidad(),
						contact.getNombreProvincia(), contact.getNombrePais());
				String provincia = contact.getNombreProvincia();
				String localidad = contact.getNombreLocalidad();
				String nombreLocalizacion = "";

				if (!(null == localidad || "".equals(localidad) || "null"
						.equals(localidad))) {
					if (!(null == provincia || "".equals(provincia) || "null"
							.equals(provincia))) {
						nombreLocalizacion = localidad + "(" + provincia + ")";
					} else {
						nombreLocalizacion = localidad;
					}
				}

				item.setNombreLocalizacion(nombreLocalizacion);
				item.setEmail(contact.getEmail());
				item.setTelefono(contact.getTelefono());
				item.setSeleccionado(Y42bAgendaConstantes.DB_FALSE);

				// obtener entidades del contacto
				Contacto contactoAux = new Contacto();
				contactoAux = this.contactService.findEntidadContacto(contact,
						new Entidad(), null);
				boolean valorActivo = false;
				// si alguna es activa el contacto sera activo
				List<Entidad> listaEntidades = contactoAux.getEntidads();
				if (!listaEntidades.isEmpty()) {
					for (Entidad entidad : listaEntidades) {
						if (entidad.getActiva().equalsIgnoreCase(
								Y42bAgendaConstantes.SI)) {
							valorActivo = true;
						}
					}
				}

				if (valorActivo) {
					item.setActiva(Y42bAgendaConstantes.SI);
				} else {
					item.setActiva(Y42bAgendaConstantes.NO);
				}

				this.itemService.add(item);
			}
		}
	}

	/**
	 * Lleva a cabo la búsqueda y puebla la tabla de items con los resultados.
	 * 
	 * @param entityFilter
	 *            Entidad
	 * @param fechaDesde
	 *            Date
	 * @param fechaHasta
	 *            Date
	 * @param grupos
	 *            List<Grupo>
	 * @param etiquetas
	 *            List<Etiqueta>
	 * @param envio
	 *            Envio
	 * @param tiporb
	 *            String
	 */
	private void searchAndAddEntityItems(Entidad entityFilter, Date fechaDesde,
			Date fechaHasta, List<Grupo> grupos, List<Etiqueta> etiquetas,
			Envio envio, String tiporb) {

		List<Entidad> results = null;
		results = this.entityService.advancedSearchAll(entityFilter, grupos,
				etiquetas, fechaDesde, fechaHasta, null, tiporb);

		// Generación de items de entidadades
		Locale locale = LocaleContextHolder.getLocale();

		Item item = new Item();
		for (Entidad entity : results) {
			// item = new Item();
			item.setEnvio(envio);
			item.setItemRef(entity.getEntidadId());
			if (locale.getLanguage().equals(Y42bAgendaConstantes.CASTELLANO)) {
				item.setNombre(entity.getNombreEs());
			} else {
				item.setNombre(entity.getNombreEu());
			}
			this.setLocation(item, entity.getIsnacional(),
					entity.getNombreLocalidad(), entity.getNombreProvincia(),
					entity.getNombrePais());

			String provincia = entity.getNombreProvincia();
			String localidad = entity.getNombreLocalidad();
			String nombreLocalizacion = "";

			if (!(null == localidad || "".equals(localidad) || "null"
					.equals(localidad))) {
				if (!(null == provincia || "".equals(provincia) || "null"
						.equals(provincia))) {
					nombreLocalizacion = localidad + "(" + provincia + ")";
				} else {
					nombreLocalizacion = localidad;
				}
			}
			item.setActiva(entity.getActiva());
			item.setNombreLocalizacion(nombreLocalizacion);
			item.setEmail(entity.getEmail());
			item.setTelefono(entity.getTelefono());
			item.setSeleccionado(Y42bAgendaConstantes.DB_FALSE);

			this.itemService.add(item);
		}
	}

	/**
	 * Establece el parametro de localizacion del item, con la informacion
	 * correspondiente.
	 * 
	 * @param item
	 *            Item
	 * @param isnacional
	 *            String
	 * @param nombreLocalidad
	 *            String
	 * @param nombreProvincia
	 *            String
	 * @param nombrePais
	 *            String
	 */
	private void setLocation(Item item, String isnacional,
			String nombreLocalidad, String nombreProvincia, String nombrePais) {
		if (Y42bAgendaConstantes.DB_TRUE.equals(isnacional)) {
			if (this.isValid(nombreProvincia) && this.isValid(nombreLocalidad)) {
				item.setNombreLocalizacion(nombreLocalidad + "\n"
						+ nombreProvincia);
			} else if (this.isValid(nombreProvincia)) {
				item.setNombreLocalizacion(nombreProvincia);
			} else if (this.isValid(nombreLocalidad)) {
				item.setNombreLocalizacion(nombreLocalidad);
			}
		} else {
			if (this.isValid(nombreLocalidad) && this.isValid(nombrePais)) {
				item.setNombreLocalizacion(nombreLocalidad + "\n" + nombrePais);
			} else if (this.isValid(nombreLocalidad)) {
				item.setNombreLocalizacion(nombreLocalidad);
			} else if (this.isValid(nombrePais)) {
				item.setNombreLocalizacion(nombrePais);
			}
		}
	}

	/**
	 * 
	 * @param string
	 *            String
	 * @return ""
	 */
	private boolean isValid(String string) {
		return (string != null && !"".equals(string));
	}
}