package com.ejie.ad74a.dao.comun;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.ad74a.model.comun.Calle;
import com.ejie.ad74a.model.comun.Localidad;
import com.ejie.ad74a.model.comun.Municipio;
import com.ejie.ad74a.model.comun.Pais;
import com.ejie.ad74a.model.comun.Portal;
import com.ejie.ad74a.model.comun.Provincia;
import com.ejie.ad74a.model.comun.Tramo;
import com.ejie.ad74a.util.UtilSQL;
import com.ejie.ad74a.util.comun.Utilidades;
import com.ejie.ad74a.util.constantes.Constantes;

/**
 * Ab3711s00DaoImpl generated by UDA, 09-may-2019 10:05:02.
 * 
 * @author UDA
 */

@Repository
@Transactional
public class NoraDaoImpl implements NoraDao {

	private JdbcTemplate jdbcTemplate;

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

	/**
	 * Method use to set the datasource.
	 *
	 * @param dataSource DataSource
	 * @return
	 */
	@Resource
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}

	private RowMapper<Provincia> rwMapProvincia = new RowMapper<Provincia>() {
		public Provincia mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new Provincia(resultSet.getString("ID"), resultSet.getString("DS_C"), resultSet.getString("DS_E"),
					resultSet.getString("AUTONOMIA_ID"));
		}
	};

	private RowMapper<Municipio> rwMapMunicipio = new RowMapper<Municipio>() {
		public Municipio mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new Municipio(resultSet.getString("CODMUNICIPIO"), resultSet.getString("DESCRIPCION"),
					resultSet.getString("CODPROVINCIA"));
		}
	};

	private RowMapper<Municipio> rwMapMunicipioConProv = new RowMapper<Municipio>() {
		public Municipio mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new Municipio(resultSet.getString("ID"), resultSet.getString("DESCRIPCION"),
					resultSet.getString("PROVINCIA_ID"));
		}
	};

	private RowMapper<Localidad> rwMapLocalidad = new RowMapper<Localidad>() {

		public Localidad mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new Localidad(resultSet.getString("CODPROVINCIA"), resultSet.getString("CODMUNICIPIO"),
					UtilSQL.getLong(resultSet, "CODLOCALIDAD"), resultSet.getString("DESCRIPCION"));
		}
	};

	private RowMapper<Calle> rwMapCalle = new RowMapper<Calle>() {
		/*
		 * public Combo mapRow(ResultSet resultSet, int rowNum) throws SQLException {
		 * return new Combo(resultSet.getString("IDCALLE"),
		 * resultSet.getString("DESCRIPCION"), resultSet.getString("DESCRIPCION")); }
		 */
		public Calle mapRow(ResultSet resultSet, int rowNum) throws SQLException {

			Calle calle = new Calle(resultSet.getString("CODPROVINCIA"), resultSet.getString("CODMUNICIPIO"),
					UtilSQL.getLong(resultSet, "CODCALLE"), UtilSQL.getLong(resultSet, "IDCALLE"),
					resultSet.getString("DESCRIPCION"), resultSet.getString("TIPOVIA"),
					resultSet.getString("TIPOVIAID"), null);

			if (UtilDAO.hasColumn(resultSet, "LOCALIDADID") && null != resultSet.getObject("LOCALIDADID")) {
				calle.setCodLocalidad(resultSet.getString("LOCALIDADID"));
			}

			if (UtilDAO.hasColumn(resultSet, "NOMBRECALLE") && null != resultSet.getObject("NOMBRECALLE")) {
				calle.setCalleTxt(resultSet.getString("NOMBRECALLE"));
			}

			return calle;

		}
	};

	private RowMapper<Portal> rwMapPortal = new RowMapper<Portal>() {
		public Portal mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new Portal(UtilSQL.getLong(resultSet, "CODPORTAL"), resultSet.getString("BLOQUE"),
					UtilSQL.getLong(resultSet, "NUMERO"), resultSet.getString("BIS"),
					UtilSQL.getLong(resultSet, "CODCALLE"), UtilSQL.getLong(resultSet, "CODLOCALIDAD"),
					resultSet.getString("CODPOSTAL"), resultSet.getBigDecimal("CODTRAMO"));
		}
	};

	private RowMapper<Pais> rwMapPais = new RowMapper<Pais>() {
		public Pais mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			return new Pais(resultSet.getString("IDPAIS"), resultSet.getString("DESCRIPCION"),
					resultSet.getString("DESCRIPCIONEU"));
		}
	};

	/**
	 * Provincia de España
	 */
	@Transactional(readOnly = true)
	public List<Provincia> findAllProvincias() {
		StringBuilder sql = new StringBuilder("SELECT ID, DS_C,DS_E, AUTONOMIA_ID FROM T17_PROVINCIA ORDER BY DS_O");
		return (List<Provincia>) this.jdbcTemplate.query(sql.toString(), this.rwMapProvincia);
	}

	/**
	 * Provincia del pais vasco
	 */
	@Transactional(readOnly = true)
	public List<Provincia> findProvinciasCAP() {
		StringBuilder sql = new StringBuilder(
				"SELECT ID, DS_C,DS_E, AUTONOMIA_ID FROM T17_PROVINCIA WHERE (ID='01' OR ID='48' OR ID='20')");
		return (List<Provincia>) this.jdbcTemplate.query(sql.toString(), this.rwMapProvincia);
	}

	/**
	 * Todas las provincias menos las del pais vasco
	 * 
	 * @return List<Provincia>
	 */
	@Transactional(readOnly = true)
	public List<Provincia> findAllProvinciasNoCAP() {
		StringBuilder sql = new StringBuilder(
				"SELECT ID, DS_C,DS_E, AUTONOMIA_ID FROM T17_PROVINCIA WHERE ID NOT IN ('01','48','20')");
		return (List<Provincia>) this.jdbcTemplate.query(sql.toString(), this.rwMapProvincia);
	}

	/**
	 * Todas las provincias
	 */
	public List<Provincia> findAllProvincias(Provincia filterProvincia) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder("SELECT ID, DS_C,DS_E, AUTONOMIA_ID FROM T17_PROVINCIA ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(filterProvincia);
		StringBuilder where = new StringBuilder(" WHERE 1=1 ");
		where.append(mapaWhere.get("query"));
		query.append(where);

		List<?> params = (List<?>) mapaWhere.get("params");

		return (List<Provincia>) this.jdbcTemplate.query(query.toString(), this.rwMapProvincia, params.toArray());
	}

	/**
	 * Devuelve una lista de localidades con el codigo de provincia, el codigo de
	 * municipio, el codigo de localidad y la descripcion para el codigo postal que
	 * se pasa por parametro
	 */
	@Transactional(readOnly = true)
	public List<Localidad> findByCodPostal(String codPostal) {
		List<Object> params = new ArrayList<Object>();
		StringBuilder query = new StringBuilder(
				"SELECT T1.PROVINCIA_ID CODPROVINCIA, T1.MUNICIPIO_ID CODMUNICIPIO, T1.ID CODLOCALIDAD, T1.DS_O DESCRIPCION FROM T17_LOCALIDAD T1 ");
		query.append(" INNER JOIN T17_PROVINCIA T2 ON (T1.PROVINCIA_ID = T2.ID) ");
		query.append(" INNER JOIN T17_MUNICIPIO T3 ON (T1.MUNICIPIO_ID = T3.ID AND T3.PROVINCIA_ID = T2.ID) ");
		query.append(" INNER JOIN T17_PORTAL T4 ON (T1.ID = T4.LOCALIDAD_ID)");

		query.append(" WHERE T4.CODIGO_POSTAL LIKE ? ESCAPE  '\\'");
		params.add("%" + codPostal + "%");
		query.append(" GROUP BY T1.PROVINCIA_ID, T1.MUNICIPIO_ID, T1.ID, T1.DS_O ");

		return this.jdbcTemplate.query(query.toString(), this.rwMapLocalidad, params.toArray());
	}

	/**
	 * Devuelve una lista con los municipios que hay en una provincia y con un
	 * codigo postal
	 * 
	 * @param municipio Municipio
	 * @return List
	 */
	@Transactional(readOnly = true)
	public List<Municipio> findAllMunicipios(Municipio municipio) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder(
				"SELECT T1.PROVINCIA_ID CODPROVINCIA, T1.ID CODMUNICIPIO, T1.DS_O DESCRIPCION FROM t17_MUNICIPIO T1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(municipio);
		StringBuilder where = new StringBuilder(" WHERE 1=1 ");
		where.append(mapaWhere.get("query"));
		query.append(where);
		query.append(" ORDER BY DESCRIPCION ");
		List<?> params = (List<?>) mapaWhere.get("params");

		return this.jdbcTemplate.query(query.toString(), this.rwMapMunicipio, params.toArray());
	};

	/**
	 * Devuelve la lista de Localidad en funcion de la Calle
	 * 
	 * @param tramo Tramo
	 * @return List<Localidad>
	 */
	@Transactional(readOnly = true)
	public List<Localidad> findAllLocalidadesCalle(Tramo tramo) {
		StringBuilder query = new StringBuilder(
				"SELECT DISTINCT (t3.ID) CODLOCALIDAD, t3.DS_O DESCRIPCION, t3.PROVINCIA_ID CODPROVINCIA, t3.MUNICIPIO_ID CODMUNICIPIO");
		query.append(" FROM T17_TRAMO t1, T17_CALLE t2, T17_LOCALIDAD t3 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereLikeMap(tramo, true, null);
		StringBuilder where = new StringBuilder(" WHERE 1=1 AND t1.CALLE_ID = t2.ID AND t1.LOCALIDAD_ID = t3.ID ");
		where.append(mapaWhere.get("query"));
		query.append(where);

		query.append(" ORDER BY DESCRIPCION ");

		List<?> params = (List<?>) mapaWhere.get("params");

		return this.jdbcTemplate.query(query.toString(), this.rwMapLocalidad, params.toArray());
	}

	/**
	 * Finds a List of rows in the Localidad table.
	 * 
	 * @param localidad Localidad
	 * @return List
	 */
	@Transactional(readOnly = true)
	public List<Localidad> findAllLocalidades(Localidad localidad) {
		StringBuilder query = new StringBuilder(
				"SELECT T1.PROVINCIA_ID CODPROVINCIA, T1.MUNICIPIO_ID CODMUNICIPIO, T1.ID CODLOCALIDAD, T1.DS_O DESCRIPCION FROM T17_LOCALIDAD T1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(localidad);
		StringBuilder where = new StringBuilder(" WHERE 1=1 ");
		where.append(mapaWhere.get("query"));
		query.append(where);

		List<?> params = (List<?>) mapaWhere.get("params");

		return this.jdbcTemplate.query(query.toString(), this.rwMapLocalidad, params.toArray());
	}

	@Transactional(readOnly = true)
	public List<Localidad> findAllLocalidadesCambioDomic(Localidad localidad) {
		StringBuilder query = new StringBuilder(
				"SELECT T1.PROVINCIA_ID CODPROVINCIA, T1.MUNICIPIO_ID CODMUNICIPIO, T1.ID CODLOCALIDAD, T1.DS_O DESCRIPCION FROM T17_LOCALIDAD T1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMapCambioDomic(localidad);
		StringBuilder where = new StringBuilder(" WHERE 1=1 ");
		where.append(mapaWhere.get("query"));
		query.append(where);

		List<?> params = (List<?>) mapaWhere.get("params");

		return this.jdbcTemplate.query(query.toString(), this.rwMapLocalidad, params.toArray());
	}

	/**
	 * Obtenemos todas las calles de una provincia municipio
	 */
	@Transactional(readOnly = true)
	public List<Calle> findAllCallesProvMuni(Calle calle) {
		StringBuilder query = new StringBuilder(
				"SELECT DISTINCT(t1.ID) IDCALLE, t1.PROVINCIA_ID CODPROVINCIA, t1.MUNICIPIO_ID CODMUNICIPIO, t1.CALLE_COD CODCALLE, t1.TIPO_VIA || ' ' || t1.DS_O DESCRIPCION, t1.DS_O NOMBRECALLE, t1.TIPO_VIA TIPOVIA, t1.TIPO_VIA_ID TIPOVIAID");
		query.append(" FROM T17_CALLE t1");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(calle, false);
		if (!mapaWhere.get("query").toString().trim().isEmpty()) {
			StringBuilder where = new StringBuilder(" WHERE 1=1 ");
			where.append(mapaWhere.get("query"));
			query.append(where);
		}
		List<?> params = (List<?>) mapaWhere.get("params");
		
		query.append(" ORDER BY NOMBRECALLE ");


		return this.jdbcTemplate.query(query.toString(), this.rwMapCalle, params.toArray());
	}
	
	/**
	 * Obtenemos todas las calles de una localidad
	 */
	@Transactional(readOnly = true)
	public List<Calle> findAllCallesLocalidad(Tramo tramo) {
		StringBuilder query = new StringBuilder(
				"SELECT DISTINCT(t2.ID) IDCALLE, t2.PROVINCIA_ID CODPROVINCIA, t2.MUNICIPIO_ID CODMUNICIPIO, t2.CALLE_COD CODCALLE, t2.TIPO_VIA || ' ' || t2.DS_O DESCRIPCION, t2.DS_O NOMBRECALLE, t2.TIPO_VIA TIPOVIA, t2.TIPO_VIA_ID TIPOVIAID, t1.LOCALIDAD_ID  LOCALIDADID ");
		query.append(" FROM T17_TRAMO t1, T17_CALLE t2, T17_LOCALIDAD t3 ");

		String queryaux = "SELECT DISTINCT TIPO_VIA_ID, TIPO_VIA FROM T17_CALLE ";

		List<String> tiposCalle = new ArrayList<String>();
		List<Map<String, Object>> rows = jdbcTemplate.queryForList(queryaux);
		for (Map row : rows) {
			String tipo_via = row.get("TIPO_VIA").toString().toUpperCase();

			tiposCalle.add(row.get("TIPO_VIA_ID").toString().toUpperCase());
			tiposCalle.add(tipo_via.substring(0, tipo_via.indexOf("/")));
			tiposCalle.add(tipo_via.substring(tipo_via.indexOf("/") + 1));
		}

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereLikeMap(tramo, true, tiposCalle);
		StringBuilder where = new StringBuilder(" WHERE 1=1 AND t1.CALLE_ID = t2.ID AND t1.LOCALIDAD_ID = t3.ID ");
		where.append(mapaWhere.get("query"));
		query.append(where);

		query.append(" ORDER BY NOMBRECALLE ");

		List<?> params = (List<?>) mapaWhere.get("params");

		return this.jdbcTemplate.query(query.toString(), this.rwMapCalle, params.toArray());
	}

	/**
	 * 
	 */
	@Transactional(readOnly = true)
	public List<Calle> findAllCalles(Calle calle) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder(
				"SELECT t1.PROVINCIA_ID CODPROVINCIA, t1.MUNICIPIO_ID CODMUNICIPIO, t1.ID CODCALLE, t1.CALLE_COD IDCALLE , t1.TIPO_VIA || ' ' || t1.DS_O DESCRIPCION, t1.TIPO_VIA TIPOVIA, t1.TIPO_VIA_ID TIPOVIAID  FROM T17_CALLE T1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(calle, false);
		if (!mapaWhere.get("query").toString().trim().isEmpty()) {
			StringBuilder where = new StringBuilder(" WHERE 1=1 ");
			where.append(mapaWhere.get("query"));
			query.append(where);
		}
		List<?> params = (List<?>) mapaWhere.get("params");

		return this.jdbcTemplate.query(query.toString(), this.rwMapCalle, params.toArray());
	}

	@Transactional(readOnly = true)
	public List<Calle> findAllCallesCambioDomic(Calle calle) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder(
				"SELECT t1.PROVINCIA_ID CODPROVINCIA, t1.MUNICIPIO_ID CODMUNICIPIO, t1.ID CODCALLE, t1.CALLE_COD IDCALLE , t1.TIPO_VIA || ' ' || t1.DS_O DESCRIPCION, t1.TIPO_VIA TIPOVIA, t1.TIPO_VIA_ID TIPOVIAID  FROM T17_CALLE T1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMapCambioDomic(calle, false);
		if (!mapaWhere.get("query").toString().trim().isEmpty()) {
			StringBuilder where = new StringBuilder(" WHERE 1=1 ");
			where.append(mapaWhere.get("query"));
			query.append(where);
		}
		List<?> params = (List<?>) mapaWhere.get("params");

		return this.jdbcTemplate.query(query.toString(), this.rwMapCalle, params.toArray());
	}

	@Transactional(readOnly = true)
	public List<Calle> findAllCallesNisae(Calle calle) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder(
				"SELECT t1.PROVINCIA_ID CODPROVINCIA, t1.MUNICIPIO_ID CODMUNICIPIO, t1.ID IDCALLE, t1.CALLE_COD CODCALLE , t1.TIPO_VIA || ' ' || t1.DS_O DESCRIPCION, t1.TIPO_VIA TIPOVIA, t1.TIPO_VIA_ID TIPOVIAID  FROM T17_CALLE T1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMapNisae(calle, false);
		if (!mapaWhere.get("query").toString().trim().isEmpty()) {
			StringBuilder where = new StringBuilder(" WHERE 1=1 ");
			where.append(mapaWhere.get("query"));
			query.append(where);
		}
		List<?> params = (List<?>) mapaWhere.get("params");

		return this.jdbcTemplate.query(query.toString(), this.rwMapCalle, params.toArray());
	}

	/**
	 * 
	 */
	@Transactional(readOnly = true)
	public Portal findPortal(Portal portal) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder(
				"SELECT t1.ID CODPORTAL, t1.BLOQUE BLOQUE, t1.NUMERO NUMERO, t1.BIS BIS, t1.CALLE_ID CODCALLE, t1.LOCALIDAD_ID CODLOCALIDAD, t1.CODIGO_POSTAL CODPOSTAL, t1.TRAMO_ID CODTRAMO FROM T17_PORTAL t1 ");
		// WHERE
		query.append(" WHERE t1.ID = ? ");
		List<Portal> portalList = this.jdbcTemplate.query(query.toString(), this.rwMapPortal, portal.getCodPortal());
		return (Portal) DataAccessUtils.uniqueResult(portalList);
	}

	/**
	 * 
	 */
	@Transactional(readOnly = true)
	public List<Portal> findAllPortales(Portal portal) {
		StringBuilder query = new StringBuilder(
				"SELECT t1.ID CODPORTAL, t1.BLOQUE BLOQUE, t1.NUMERO NUMERO, t1.BIS BIS, t1.CALLE_ID CODCALLE, t1.LOCALIDAD_ID CODLOCALIDAD, t1.CODIGO_POSTAL CODPOSTAL, t1.TRAMO_ID CODTRAMO FROM T17_PORTAL t1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(portal);
		StringBuilder where = new StringBuilder(" WHERE 1=1 ");
		where.append(mapaWhere.get("query"));
		query.append(where);

		List<?> params = (List<?>) mapaWhere.get("params");

		query.append(" ORDER BY NUMERO ASC, BIS ASC, BLOQUE ASC ");

		return this.jdbcTemplate.query(query.toString(), this.rwMapPortal, params.toArray());
	}

	@Transactional(readOnly = true)
	public List<Portal> findAllPortalesNisae(Portal portal) {
		StringBuilder query = new StringBuilder(
				"SELECT t1.ID CODPORTAL, t1.BLOQUE BLOQUE, t1.NUMERO NUMERO, t1.BIS BIS, t1.CALLE_ID CODCALLE, t1.LOCALIDAD_ID CODLOCALIDAD, t1.CODIGO_POSTAL CODPOSTAL, t1.TRAMO_ID CODTRAMO FROM T17_PORTAL t1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMapNisae(portal);
		StringBuilder where = new StringBuilder(" WHERE 1=1 ");
		where.append(mapaWhere.get("query"));
		query.append(where);

		List<?> params = (List<?>) mapaWhere.get("params");

		query.append(" ORDER BY NUMERO ASC, BIS ASC, BLOQUE ASC ");

		return this.jdbcTemplate.query(query.toString(), this.rwMapPortal, params.toArray());
	}

	/**
	 * Finds a List of rows in the Pais table.
	 * 
	 * @param pais Pais
	 * @return List
	 */
	@Transactional(readOnly = true)
	public List<Pais> findAllPaises(Pais pais) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder(
				"SELECT T1.ID IDPAIS, T1.DS_O DESCRIPCION, T1.DS_E DESCRIPCIONEU FROM T17_PAIS T1 ");

		// Where clause & Params
		Map<String, ?> mapaWhere = this.getWhereMap(pais);
		StringBuilder where = new StringBuilder(" WHERE 1=1 ");
		where.append(mapaWhere.get("query"));
		query.append(where);

		List<?> params = (List<?>) mapaWhere.get("params");

		return (List<Pais>) this.jdbcTemplate.query(query.toString(), this.rwMapPais, params.toArray());
	};

	/**
	 * Get Pais by codPais
	 * 
	 * @param codPais BigDecimal
	 * @return Pais
	 */
	@Transactional(readOnly = true)
	public Pais findPais(BigDecimal codPais) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder(
				"SELECT t1.ID IDPAIS, t1.DS_O DESCRIPCION, T1.DS_E DESCRIPCIONEU FROM T17_PAIS t1 ");
		// WHERE
		query.append(" WHERE t1.ID = ? ");
		List<Pais> paisList = this.jdbcTemplate.query(query.toString(), this.rwMapPais, codPais.toString());
		return (Pais) DataAccessUtils.uniqueResult(paisList);
	}

	/**
	 * Get Provincia by codprovincia
	 * 
	 * @param codprovincia BigDecimal
	 * @return Provincia
	 */
	@Transactional(readOnly = true)
	public Provincia findProvincia(BigDecimal codprovincia) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder(
				"SELECT t1.ID, t1.DS_C,t1.DS_E, t1.AUTONOMIA_ID FROM T17_PROVINCIA t1 ");
		// WHERE
		query.append(" WHERE t1.ID = ? ");
		List<Provincia> provinciaList = this.jdbcTemplate.query(query.toString(), this.rwMapProvincia, codprovincia);
		return (Provincia) DataAccessUtils.uniqueResult(provinciaList);
	}

	@Transactional(readOnly = true)
	public Municipio findMunicipio(Municipio municipio) {
		return findMunicipioConProv(municipio);
	}

	@Transactional(readOnly = true)
	public Municipio findMunicipioConProv(Municipio municipio) {
		// SELECT - FROM
		StringBuilder query = new StringBuilder(
				"SELECT t1.ID, t1.DS_O DESCRIPCION, t1.PROVINCIA_ID FROM T17_MUNICIPIO t1 ");
		// WHERE
		query.append(" WHERE t1.ID = ? AND t1.PROVINCIA_ID = ? ");
		List<Municipio> municipioList = this.jdbcTemplate.query(query.toString(), this.rwMapMunicipioConProv,
				Long.parseLong(municipio.getCodMunicipio()), Long.parseLong(municipio.getCodProvincia()));
		return DataAccessUtils.uniqueResult(municipioList);
	}

	/**
	 * Returns a map with the needed value to create the conditions to filter by the
	 * Municipio entity
	 * 
	 * @param municipio Municipio Bean with the criteria values to filter by.
	 * @return Map created with two keys key query stores the sql query syntax key
	 *         params stores the parameter values to be used in the condition
	 *         sentence.
	 */
	private Map<String, ?> getWhereMap(Municipio municipio) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (municipio != null) {
			if (municipio.getCodMunicipio() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.ID", municipio.getCodMunicipio());
			}
			if (municipio.getDescripcion() != null && !"".equals(municipio.getDescripcion().trim())) {
				UtilSQL.createFilterLikeSQL(where, params, "T1.DS_O", municipio.getDescripcion(), false);
			}
			if (municipio.getCodProvincia() != null && !"".equals(municipio.getCodProvincia().trim())) {
				UtilSQL.createFilterSQL(where, params, "T1.PROVINCIA_ID", municipio.getCodProvincia(), false);
			}

			// Sólo aplicamos este filtro para las provincias CAV
			if (municipio.getCodPostal() != null && !"".equals(municipio.getCodPostal())
					&& municipio.getCodPostal().matches("[0][1]\\d{3}|[2][0]\\d{3}|[4][8]\\d{3}")) {
				where.append(
						" AND T1.ID IN (SELECT T2.ID FROM T17_MUNICIPIO T2 INNER JOIN T17_LOCALIDAD T3 ON (T3.MUNICIPIO_ID = T2.ID AND T2.PROVINCIA_ID = T3.PROVINCIA_ID) ");
				where.append(
						" INNER JOIN T17_PORTAL T4 ON (T3.ID = T4.LOCALIDAD_ID) WHERE T4.CODIGO_POSTAL LIKE ? ESCAPE  '\\'");
				params.add("%" + municipio.getCodPostal() + "%");

				if (municipio.getCodProvincia() != null) {
					UtilSQL.createFilterSQL(where, params, "T2.PROVINCIA_ID", municipio.getCodProvincia());
				}

				where.append(")");
			}

		}

		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	/**
	 * Returns a map with the needed value to create the conditions to filter by the
	 * Tramo entity
	 * 
	 * @param tramo      Tramo Bean with the criteria values to filter by.
	 * @param startsWith Boolean
	 * @return Map created with two keys key query stores the sql query syntax key
	 *         params stores the parameter values to be used in the condition
	 *         sentence.
	 */
	private Map<String, Object> getWhereLikeMap(Tramo tramo, Boolean startsWith, List<String> tiposCalle) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (tramo != null) {
			if (tramo.getCodTramo() != null) {
				UtilSQL.createFilterLikeSQL(where, params, "t1.ID", tramo.getCodTramo(), startsWith);
			}
			if (tramo.getCodPostal() != null) {
				UtilSQL.createFilterLikeSQL(where, params, "t1.CODIGO_POSTAL", tramo.getCodPostal(), startsWith);
			}
			if (tramo.getCalle() != null && !Utilidades.isEmptyNumber(tramo.getCalle().getCodCalle())) {
				UtilSQL.createFilterLikeSQL(where, params, "t1.CALLE_ID", tramo.getCalle().getCodCalle(), startsWith);
			}
			// if (tramo.getCalle() != null &&
			// !Utilities.isEmpty(tramo.getCalle().getDescripcion())) {
			// // Se busca tanto por la via en castellano o en euskera, por la
			// // acortación de la via (CL, AV, ..), por la calle y por el
			// // codigo de la calle la primera vez
			// String descripcion = tramo.getCalle().getDescripcion();
			//
			// // Si la descripcion esta compuesta por numeros es que le
			// // estamos pasando el codigo de la calle para que la primera vez
			// // busque por ese codigo.
			// if (!descripcion.matches("[0-9]+")) {
			//
			// String via = "";
			// String calle = descripcion.substring(descripcion.indexOf(" ") +
			// 1);
			//
			// String idiomaLocal =
			// LocaleContextHolder.getLocale().getLanguage();
			//
			// if (tiposCalle.contains(calle.toUpperCase())) {
			// via = calle;
			// if (via.length() > 2) {
			// where.append(" AND UPPER(t2.TIPO_VIA) like ? ESCAPE '\\' ");
			// } else {
			// where.append(" AND UPPER(t2.TIPO_VIA_ID) like ? ESCAPE '\\' ");
			// }
			// params.add("%" + via.toUpperCase() + "%");
			// } else {
			// if (descripcion.indexOf("/") != -1 &&
			// idiomaLocal.equals(Constantes.LOCALE_EU.toString())) {
			// via = descripcion.substring(0, descripcion.indexOf("/"));
			// } else if (descripcion.indexOf("/") != -1
			// && idiomaLocal.equals(Constantes.LOCALE_ES.toString())) {
			// via = descripcion.substring(descripcion.indexOf("/") + 1,
			// descripcion.indexOf(" "));
			// } else if (descripcion.indexOf("/") == -1) {
			// if (descripcion.indexOf(" ") != -1) {
			// via = descripcion.substring(0, descripcion.indexOf(" "));
			// if (via.length() > 2) {
			// where.append(" AND UPPER(t2.TIPO_VIA) like ? ESCAPE '\\' ");
			// } else {
			// where.append(" AND UPPER(t2.TIPO_VIA_ID) like ? ESCAPE '\\' ");
			// }
			// params.add("%" + via.toUpperCase() + "%");
			// }
			// }
			//
			// if (idiomaLocal.equals(Constantes.LOCALE_ES.toString())) {
			// where.append("AND UPPER(t2.DS_O) like ? ESCAPE '\\' ");
			// } else {
			// where.append("AND UPPER(t2.DS_E) like ? ESCAPE '\\' ");
			// }
			// params.add("%" + calle.toUpperCase() + "%");
			// }
			//
			// } else {
			// where.append(" AND t1.CALLE_ID = ? ");
			// params.add(descripcion.toUpperCase());
			// }
			// }
			if (tramo.getLocalidad() != null) {
				if (!Utilidades.isEmptyNumber(tramo.getLocalidad().getCodLocalidad())) {
					UtilSQL.createFilterLikeSQL(where, params, "t1.LOCALIDAD_ID",
							tramo.getLocalidad().getCodLocalidad(), startsWith);
				}
				if (!Utilidades.isEmpty(tramo.getLocalidad().getCodProvincia())) {
					UtilSQL.createFilterLikeSQL(where, params, "t3.PROVINCIA_ID",
							tramo.getLocalidad().getCodProvincia(), startsWith);
				}
				if (!Utilidades.isEmpty(tramo.getLocalidad().getCodMunicipio())) {
					UtilSQL.createFilterLikeSQL(where, params, "t3.MUNICIPIO_ID",
							tramo.getLocalidad().getCodMunicipio(), startsWith);
				}
			}
		}

		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	/**
	 * Returns a map with the needed value to create the conditions to filter by the
	 * Localidad entity
	 * 
	 * @param localidad Localidad Bean with the criteria values to filter by.
	 * @return Map created with two keys key query stores the sql query syntax key
	 *         params stores the parameter values to be used in the condition
	 *         sentence.
	 */
	private Map<String, ?> getWhereMap(Localidad localidad) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (localidad != null) {
			if (localidad.getCodLocalidad() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.ID", localidad.getCodLocalidad());
			}
			if (localidad.getCodMunicipio() != null && !"".equals(localidad.getCodMunicipio().trim())) {
				UtilSQL.createFilterSQL(where, params, "T1.MUNICIPIO_ID", localidad.getCodMunicipio());
			}
			if (localidad.getCodProvincia() != null && !"".equals(localidad.getCodProvincia().trim())) {
				UtilSQL.createFilterSQL(where, params, "T1.PROVINCIA_ID", localidad.getCodProvincia());
			}
			if (localidad.getDescripcion() != null && !"".equals(localidad.getDescripcion().trim())) {
				UtilSQL.createFilterLikeSQL(where, params, "T1.DS_O", localidad.getDescripcion(), false);
			}
		}

		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	private Map<String, ?> getWhereMapCambioDomic(Localidad localidad) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (localidad != null) {
			if (localidad.getCodLocalidad() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.ID", Long.valueOf(localidad.getCodLocalidad()));
			}
			if (localidad.getCodMunicipio() != null && !"".equals(localidad.getCodMunicipio().trim())) {
				UtilSQL.createFilterSQL(where, params, "T1.MUNICIPIO_ID", Long.valueOf(localidad.getCodMunicipio()));
			}
			if (localidad.getCodProvincia() != null && !"".equals(localidad.getCodProvincia().trim())) {
				UtilSQL.createFilterSQL(where, params, "T1.PROVINCIA_ID", Long.valueOf(localidad.getCodProvincia()));
			}
			if (localidad.getDescripcion() != null && !"".equals(localidad.getDescripcion().trim())) {
				UtilSQL.createFilterLikeSQL(where, params, "T1.DS_O", localidad.getDescripcion(), false);
			}
		}

		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	/**
	 * 
	 * @param calle
	 * @param startsWith
	 * @return
	 */
	private Map<String, ?> getWhereMap(Calle calle, Boolean startsWith) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (calle != null) {
			if (calle.getCodCalle() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.ID", calle.getCodCalle());
			}
			if (calle.getCodProvincia() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.PROVINCIA_ID", calle.getCodProvincia());
			}
			if (calle.getCodMunicipio() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.MUNICIPIO_ID", calle.getCodMunicipio());
			}
			/**
			 * Para la calle filtramos las descripcion siempre con LIKE
			 */
			if (calle.getDescripcion() != null) {
				// UtilSQL.createFilterLikeSQL(where, params, "UPPER(T1.DS_O)",
				// calle.getDescripcion().toUpperCase(),startsWith);
				where.append(" AND UPPER(T1.DS_O) like ? ESCAPE  '\\'");
				if (!startsWith) {
					params.add("%" + calle.getDescripcion().toUpperCase() + "%");
				}
				where.append(" AND T1.DS_O IS NOT NULL");
			}
			if (calle.getIdTipoVia() != null && !Utilidades.isEmpty(calle.getIdTipoVia())) {
				UtilSQL.createFilterSQL(where, params, "T1.TIPO_VIA_ID", calle.getIdTipoVia());
			}
			/**
			 * Para la calle en autocomplete las descripcion siempre con LIKE
			 */
			if (calle.getCalleTxt() != null) {
				where.append(" AND UPPER(t1.TIPO_VIA || ' ' || t1.DS_O) like ? ESCAPE  '\\'");
				params.add("%" + calle.getCalleTxt().toUpperCase() + "%");
				where.append(" AND T1.DS_O IS NOT NULL");
			}
		}
		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	private Map<String, ?> getWhereMapCambioDomic(Calle calle, Boolean startsWith) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (calle != null) {
			if (calle.getCodCalle() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.ID", Long.valueOf(calle.getCodCalle()));
			}
			if (calle.getCodProvincia() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.PROVINCIA_ID", Long.valueOf(calle.getCodProvincia()));
			}
			if (calle.getCodMunicipio() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.MUNICIPIO_ID", Long.valueOf(calle.getCodMunicipio()));
			}
			/**
			 * Para la calle filtramos las descripcion siempre con LIKE
			 */
			if (calle.getDescripcion() != null) {
				// UtilSQL.createFilterLikeSQL(where, params, "UPPER(T1.DS_O)",
				// calle.getDescripcion().toUpperCase(),startsWith);
				where.append(" AND UPPER(T1.DS_O) like ? ESCAPE  '\\'");
				if (!startsWith) {
					params.add("%" + calle.getDescripcion().toUpperCase() + "%");
				}
				where.append(" AND T1.DS_O IS NOT NULL");
			}
			if (calle.getIdTipoVia() != null && !Utilidades.isEmpty(calle.getIdTipoVia())) {
				UtilSQL.createFilterSQL(where, params, "T1.TIPO_VIA_ID", calle.getIdTipoVia());
			}

		}
		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	private Map<String, ?> getWhereMapNisae(Calle calle, Boolean startsWith) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (calle != null) {
			if (calle.getCodCalle() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.CALLE_COD", calle.getCodCalle());
			}
			if (calle.getCodProvincia() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.PROVINCIA_ID", calle.getCodProvincia());
			}
			if (calle.getCodMunicipio() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.MUNICIPIO_ID", calle.getCodMunicipio());
			}
			/**
			 * Para la calle filtramos las descripcion siempre con LIKE
			 */
			if (calle.getDescripcion() != null) {
				// UtilSQL.createFilterLikeSQL(where, params, "UPPER(T1.DS_O)",
				// calle.getDescripcion().toUpperCase(),startsWith);
				where.append(" AND UPPER(T1.DS_O) like ? ESCAPE  '\\'");
				if (!startsWith) {
					params.add("%" + calle.getDescripcion().toUpperCase() + "%");
				}
				where.append(" AND T1.DS_O IS NOT NULL");
			}
			if (calle.getIdTipoVia() != null && !Utilidades.isEmpty(calle.getIdTipoVia())) {
				UtilSQL.createFilterSQL(where, params, "T1.TIPO_VIA_ID", calle.getIdTipoVia());
			}

		}
		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	/**
	 * 
	 * @param portal
	 * @return
	 */
	private Map<String, ?> getWhereMap(Portal portal) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (portal != null) {
			if (portal.getCodPortal() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.ID", portal.getCodPortal());
			}
			if (portal.getBloque() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.BLOQUE", portal.getBloque());
			}
			if (portal.getNumero() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.NUMERO", portal.getNumero());
			}
			if (portal.getNumeroString() != null) {
				UtilSQL.createFilterLikeSQL(where, params, "t1.NUMERO", portal.getNumeroString(), true, false);
			}
			if (portal.getBis() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.BIS", portal.getBis());
			}
			if (portal.getCodCalle() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.CALLE_ID", portal.getCodCalle());
			}
			if (portal.getCodLocalidad() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.LOCALIDAD_ID", portal.getCodLocalidad());
			}
			if (portal.getCodPostal() != null) {
				UtilSQL.createFilterSQL(where, params, "TRIM(t1.CODIGO_POSTAL)", portal.getCodPostal());
			}
			if (portal.getCodTramo() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.TRAMO_ID", portal.getCodTramo());
			}
		}

		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	private Map<String, ?> getWhereMapNisae(Portal portal) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (portal != null) {
			if (portal.getCodPortal() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.ID", portal.getCodPortal());
			}
			if (portal.getBloque() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.BLOQUE", portal.getBloque());
			}
			if (portal.getNumero() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.NUMERO", portal.getNumero());
			}
			if (portal.getNumeroString() != null) {
				UtilSQL.createFilterLikeSQL(where, params, "t1.NUMERO", portal.getNumeroString(), true, false);
			}
			if (portal.getBis() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.BIS", portal.getBis());
			}
			if (portal.getCodCalle() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.CALLE_ID", portal.getCodCalle());
			}
			if (portal.getCodLocalidad() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.LOCALIDAD_ID", portal.getCodLocalidad());
			}
			if (portal.getCodPostal() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.CODIGO_POSTAL", portal.getCodPostal());
			}
			if (portal.getCodTramo() != null) {
				UtilSQL.createFilterSQL(where, params, "t1.TRAMO_ID", portal.getCodTramo());
			}
		}

		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	/**
	 * Returns a map with the needed value to create the conditions to filter by the
	 * Localidad entity
	 * 
	 * @param localidad Localidad Bean with the criteria values to filter by.
	 * @return Map created with two keys key query stores the sql query syntax key
	 *         params stores the parameter values to be used in the condition
	 *         sentence.
	 */
	private Map<String, ?> getWhereMap(Pais pais) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (pais != null) {
			if (pais.getCodPais() != null) {
				UtilSQL.createFilterSQL(where, params, "T1.ID", pais.getCodPais());
			}
			if (pais.getDescripcion() != null && !"".equals(pais.getDescripcion().trim())) {
				UtilSQL.createFilterLikeSQL(where, params, "T1.DS_O", pais.getDescripcion(), false);
			}
		}

		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	/**
	 * Returns a map with the needed value to create the conditions to filter by the
	 * Provincia entity
	 * 
	 * @param provincia Provincia Bean with the criteria values to filter by.
	 * @return Map created with two keys key query stores the sql query syntax key
	 *         params stores the parameter values to be used in the condition
	 *         sentence.
	 */
	private Map<String, ?> getWhereMap(Provincia provincia) {

		StringBuilder where = new StringBuilder(Constantes.STRING_BUILDER_INIT);
		List<Object> params = new ArrayList<Object>();

		if (provincia != null) {
			if (provincia.getCodProvincia() != null) {
				UtilSQL.createFilterSQL(where, params, "ID", provincia.getCodProvincia());
			}
			if (provincia.getDescProvincia() != null && !"".equals(provincia.getDescProvincia().trim())) {
				UtilSQL.createFilterLikeSQL(where, params, "DS_O", provincia.getDescProvincia(), false);
			}
			if (provincia.getCodAutonomia() != null && !"".equals(provincia.getCodAutonomia().trim())) {
				UtilSQL.createFilterLikeSQL(where, params, "AUTONOMIA_ID", provincia.getCodAutonomia(), false);
			}
		}

		Map<String, Object> mapWhere = new HashMap<String, Object>();
		mapWhere.put("query", where);
		mapWhere.put("params", params);

		return mapWhere;
	}

	@Override
	public String getCp(String idPortal) {
		StringBuilder query = new StringBuilder("SELECT CODIGO_POSTAL FROM T17_PORTAL WHERE ID = ?");
		List<Object> params = new ArrayList<Object>();
		params.add(idPortal);
		return this.jdbcTemplate.queryForObject(query.toString(), params.toArray(), String.class);
	}
}
