package com.ejie.ab04b.control;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

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

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
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.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MultipartFile;

import com.ejie.ab04b.constantes.Constantes;
import com.ejie.ab04b.constantes.ConstantesDokusi;
import com.ejie.ab04b.constantes.TipoTramiteFlujo;
import com.ejie.ab04b.exception.AB04BException;
import com.ejie.ab04b.exception.ErrorGenericoException;
import com.ejie.ab04b.model.ComunicacionApertura;
import com.ejie.ab04b.model.ComunicacionPrl;
import com.ejie.ab04b.model.DocumentoAperturas;
import com.ejie.ab04b.model.DocumentoOS2;
import com.ejie.ab04b.model.DocumentoOS3;
import com.ejie.ab04b.model.OS2;
import com.ejie.ab04b.model.OS3;
import com.ejie.ab04b.model.TipoDocumento;
import com.ejie.ab04b.model.Tramite;
import com.ejie.ab04b.model.TramiteAperturas;
import com.ejie.ab04b.model.TramiteOS2;
import com.ejie.ab04b.model.TramiteOS3;
import com.ejie.ab04b.service.DocumentoAperturasService;
import com.ejie.ab04b.service.DocumentoOS2Service;
import com.ejie.ab04b.service.DocumentoOS3Service;
import com.ejie.ab04b.service.TipoDocumentoService;
import com.ejie.ab04b.service.TramiteAperturasService;
import com.ejie.ab04b.service.TramiteService;
import com.ejie.ab04b.service.dokusi.DokusiService;
import com.ejie.ab04b.service.pif.PifService;
import com.ejie.ab04b.util.PropertiesUtil;
import com.ejie.ab04b.util.Utilities;
import com.ejie.ab04b.util.seguridad.UtilSeguridad;
import com.ejie.t65.jaxb.beans.fsd.T65BDocumentType;
import com.ejie.t65.jaxb.beans.fsd.T65BStringListType;

/**
 * @author GFI-NORTE
 * 
 */
@Controller()
@RequestMapping(value = "/documentosController")
public class DocumentosController {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(DocumentosController.class);

	@Autowired()
	private DocumentoAperturasService documentoAperturasService;
	@Autowired()
	private DocumentoOS2Service documentoOS2Service;
	@Autowired()
	private DocumentoOS3Service documentoOS3Service;
	@Autowired()
	private TipoDocumentoService tipoDocumentoService;
	@Autowired()
	private TramiteService tramiteService;
	@Autowired()
	private TramiteAperturasService tramiteAperturaService;

	@Autowired()
	private DokusiService dokusiService;
	@Autowired()
	private PifService pifService;

	@Autowired()
	private Properties appConfiguration;

	/**
	 * Descargar doc aperturas.
	 * 
	 * request HttpServletRequest response HttpServletResponse codDocumento Long
	 * oid String migrado String
	 * 
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @param codDocumento
	 *            the cod documento
	 * @param oid
	 *            the oid
	 * @param migrado
	 *            the migrado
	 */
	@RequestMapping(value = "/descargarDocAperturas", method = RequestMethod.GET)
	public void descargarDocAperturas(
			HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value = "codDocumento", required = false) Long codDocumento,
			@RequestParam(value = "oid", required = false) String oid,
			@RequestParam(value = "migrado", required = false) boolean migrado) {

		try {
			DocumentoAperturas documentoAperturas = new DocumentoAperturas();
			String modoAcceso = (String) request.getSession().getAttribute(
					ComunicacionAperturaController.ATTR_NAME_MODO_ACCESO);

			if (codDocumento != null) {

				if (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)) {
					documentoAperturas = this.documentoAperturasService
							.findTemp(new DocumentoAperturas(codDocumento));
				} else {
					documentoAperturas = this.documentoAperturasService
							.find(new DocumentoAperturas(codDocumento));
				}
			} else {

				if (oid == null && codDocumento == null) {
					throw new ErrorGenericoException(
							"Error en parametros de entrada");
				}

				documentoAperturas.setOidDokusi065(oid);
				documentoAperturas.setMigrado(migrado);

			}

			boolean temp = (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso));
			// recuperamos documento de dokusi/pif

			// copiamos el contenido del fichero a la response

			this.escribirFicheroEnResponse(response, documentoAperturas, temp);

		} catch (Exception e) {
			DocumentosController.LOGGER.error("ERROR al descargar fichero: "
					+ e.getCause());
		}
	}

	/**
	 * Recupera el binario de un fichero de PIF/Dokusi a partir de su
	 * codDocumento.
	 * 
	 * documento DocumentoAperturas temp boolean
	 * 
	 * @param documento
	 *            the documento
	 * @param temp
	 *            the temp T65BDocumentType
	 * @return the t 65 B document type
	 */
	private T65BDocumentType recuperaRutaPifFichero(
			DocumentoAperturas documento, boolean temp) {

		if (documento == null) {
			throw new ErrorGenericoException("documento no encontrado");
		}

		try {

			// pasamos ruta PIF para descargar el fichero de Dokusi
			documento.setRutaPif065(this.appConfiguration
					.getProperty(PropertiesUtil.PIF_RUTA_APP));

			return this.dokusiService.recuperarDocumento(UtilSeguridad
					.getInstance().getAuditUser(), documento,
					new T65BStringListType());
		} catch (Exception e) {
			throw new ErrorGenericoException(e.getMessage());
		}

	}

	/**
	 * Recupera el binario de un fichero de PIF/Dokusi a partir de su
	 * codDocumento.
	 * 
	 * documento DocumentoAperturas temp boolean
	 * 
	 * @param documento
	 *            the documento
	 * @param temp
	 *            the temp T65BDocumentType
	 * @return the t 65 B document type
	 */
	private T65BDocumentType recuperaRutaPifFicheroOS2(DocumentoOS2 documento,
			boolean temp) {

		if (documento == null) {
			throw new ErrorGenericoException("documento no encontrado");
		}

		try {

			// pasamos ruta PIF para descargar el fichero de Dokusi
			documento.setRutaPif094(this.appConfiguration
					.getProperty(PropertiesUtil.PIF_RUTA_APP));

			return this.dokusiService.recuperarDocumento(UtilSeguridad
					.getInstance().getAuditUser(), documento,
					new T65BStringListType());
		} catch (Exception e) {
			throw new ErrorGenericoException(e.getMessage());
		}

	}

	/**
	 * Descargar documento.
	 * 
	 * rutaFichero String
	 * 
	 * @param rutaFichero
	 *            the ruta fichero byte[]
	 * @return the byte[]
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */
	public byte[] descargarDocumento(String rutaFichero) throws AB04BException {

		try {
			byte[] ficheroBytes = null;

			try {
				InputStream fichero = pifService.downloadDocument(rutaFichero);
				ficheroBytes = IOUtils.toByteArray(fichero);
				fichero.close();
			} catch (Exception ex) {
				LOGGER.error("descargarDocumento: Error:" + ex.getMessage());
			}
			return ficheroBytes;
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	/**
	 * Descargar doc aperturas.
	 * 
	 * request HttpServletRequest response HttpServletResponse codDocumento Long
	 * oid String migrado String
	 * 
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @param codDocumento
	 *            the cod documento
	 * @param oid
	 *            the oid
	 * @param migrado
	 *            the migrado
	 */
	@RequestMapping(value = "/descargarDocOS2", method = RequestMethod.GET)
	public void descargarDocOS2(
			HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value = "codDocumento", required = false) Long codDocumento,
			@RequestParam(value = "oid", required = false) String oid,
			@RequestParam(value = "migrado", required = false) String migrado) {

		try {
			DocumentoOS2 documentoOS2 = new DocumentoOS2();
			String modoAcceso = (String) request.getSession().getAttribute(
					ComunicacionAperturaController.ATTR_NAME_MODO_ACCESO);

			if (codDocumento != null) {

				if (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)) {
					documentoOS2 = this.documentoOS2Service
							.findTemp(new DocumentoOS2(codDocumento));
				} else {
					documentoOS2 = this.documentoOS2Service
							.find(new DocumentoOS2(codDocumento));
				}
			} else {

				if (oid == null && codDocumento == null) {
					throw new ErrorGenericoException(
							"Error en parametros de entrada");
				}

				documentoOS2.setOidDokusi094(oid);
				// documentoAperturas.setMigrado(migrado);

			}

			boolean temp = (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso));
			// recuperamos documento de dokusi/pif

			// copiamos el contenido del fichero a la response

			this.escribirFicheroOS2EnResponse(response, documentoOS2, temp);

		} catch (Exception e) {
			DocumentosController.LOGGER.error("ERROR al descargar fichero: "
					+ e.getCause());
		}
	}

	/**
	 * Eliminar fichero.
	 * 
	 * request HttpServletRequest response HttpServletResponse codDocumento
	 * Integer
	 * 
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @param codDocumento
	 *            the cod documento Map<String, String>
	 * @return the map
	 */
	@RequestMapping(value = "/borrarFichero", method = RequestMethod.GET)
	public @ResponseBody()
	Map<String, String> eliminarFichero(
			HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value = "codDocumento", required = false) Long codDocumento) {

		Map<String, String> retorno = new HashMap<String, String>();

		String modoAcceso = (String) request.getSession().getAttribute(
				ComunicacionAperturaController.ATTR_NAME_MODO_ACCESO);

		boolean temp = (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso));

		try {
			this.documentoAperturasService.borrarDocumento(codDocumento, temp);
		} catch (Exception e) {
			retorno.put("mensajeError", e.getMessage());
		}

		return retorno;
	}

	/**
	 * Método para gestionar las subidas desde el componente rup-upload.
	 * 
	 * file MultipartFile idTipoDoc Long idTramite Long oidDokusi String modo
	 * String response HttpServletResponse request HttpServletRequest
	 * 
	 * @param file
	 *            the file
	 * @param idTipoDoc
	 *            the id tipo doc
	 * @param idTramite
	 *            the id tramite
	 * @param oidDokusi
	 *            the oid dokusi
	 * @param modo
	 *            the modo
	 * @param response
	 *            the response
	 * @param request
	 *            the request List<Map<String, Object>>
	 * @return the list
	 * @throws IOException
	 *             e
	 */
	@RequestMapping(value = "upload", method = RequestMethod.POST)
	public @ResponseBody()
	List<Map<String, Object>> add(
			@RequestParam(value = "files[]", required = false) MultipartFile file,
			@RequestParam(value = "idTipoDoc", required = false) Long idTipoDoc,
			@RequestParam(value = "idTramite", required = false) Long idTramite,
			@RequestParam(value = "oidDokusi", required = false) String oidDokusi,
			@RequestParam(value = "nombreFichero", required = false) String nombreFichero,
			@RequestParam(value = "modo", required = false) String modo,
			HttpServletResponse response, HttpServletRequest request)
			throws IOException {

		// comprobamos datos de entrada
		if ((file == null || file.getBytes() == null)
				&& StringUtils.isBlank(oidDokusi)) {
			// datos no llegan correctamente
			throw new ErrorGenericoException(
					"Error en los parametros de entrada");
		}
		if (idTipoDoc == null) {// || idTramite == null) {
			// datos no llegan correctamente
			throw new ErrorGenericoException(
					"Error en los parametros de entrada");
		}

		HttpSession session = request.getSession();
		String docType = (String) request.getSession().getAttribute("docType");
		// DocumentosController.LOGGER.info("docType " + docType);

		String modoAcceso = (String) request.getSession().getAttribute(
				ComunicacionAperturaController.ATTR_NAME_MODO_ACCESO);

		List<Map<String, Object>> filesMetaInfo = new ArrayList<Map<String, Object>>();

		// if(Constantes.OS2.equals(docType) || Constantes.OS3.equals(docType)){
		if (Constantes.OS2.equals(docType)) {
			DocumentoOS2 documentosTramiteAdd = new DocumentoOS2();
			TramiteOS2 tramiteOS2 = new TramiteOS2();
			ComunicacionPrl comunicacionPrl = new ComunicacionPrl();

			if (session != null) {
				comunicacionPrl = (ComunicacionPrl) session
						.getAttribute(ComunicacionPrlController.ATTR_NAME_COMUNICAPRL_OS2_DETALLE);

				tramiteOS2 = new TramiteOS2(null, null, new OS2(
						comunicacionPrl.getTeros(), comunicacionPrl.getAnoos(),
						comunicacionPrl.getNumos()));
			}

			documentosTramiteAdd.setTramiteOS2(tramiteOS2);
			documentosTramiteAdd.setTipoDocumento(this.tipoDocumentoService
					.find(new TipoDocumento(idTipoDoc)));
			documentosTramiteAdd
					.setOrigen094(Constantes.DOCUMENTO_ORIGEN_CIUDADANO);
			documentosTramiteAdd.setOidDokusi094(oidDokusi);

			if (file != null
					&& StringUtils.isNotBlank(file.getOriginalFilename())) {
				documentosTramiteAdd
						.setNombreDoc094(file.getOriginalFilename());
			} else if (nombreFichero != null
					&& StringUtils.isNotBlank(nombreFichero)) {
				documentosTramiteAdd.setNombreDoc094(nombreFichero);
			} else {
				StringBuilder sb = new StringBuilder(
						Constantes.NOMBRE_DOCUMENTO_ESCANEADO_DOKUSI);
				sb.append(new SimpleDateFormat("yyyyMMdd_HHmmss")
						.format(new Date()));
				sb.append(Constantes.SEPARADOR_PUNTO)
						.append(Constantes.EXT_PDF);
				documentosTramiteAdd.setNombreDoc094(sb.toString());
			}

			// podemos llegar al método desde una subida de adjunto o desde una
			// digitalizacion
			// en caso de adjunto hay que subir a PIF y dokusi y guardarlo bbdd
			// en caso de digitalizacion el fichero ya está en dokusi y tenemos
			// su
			// oid, con lo que solo tenemos que guardarlo en base de datos
			if (StringUtils.isBlank(oidDokusi)) {
				// documento origen ha llegado en formato electronico
				documentosTramiteAdd
						.setFormatoAport094(Constantes.FORMATO_APORTACION_ELECTRONICO);
				try {

					// subimos adjunto a pif
					DocumentoOS2 resultadoPIF = this.documentoOS2Service
							.subeFicheroPIF(IOUtils.toByteArray(file
									.getInputStream()), PropertiesUtil
									.getProperty(PropertiesUtil.PIF_RUTA_APP),
									documentosTramiteAdd.getNombreDoc094(),
									false);

					// subimos documento a dokusi
					documentosTramiteAdd.setRutaPif094(resultadoPIF
							.getRutaPif094());

				} catch (Exception ex) {
					throw new ErrorGenericoException(ex.getMessage());
				}
			} else {
				// documento origen ha llegado en formato papel
				documentosTramiteAdd
						.setFormatoAport094(Constantes.FORMATO_APORTACION_PAPEL);
			}

			//
			// guardamos fichero en base de datos
			//
			boolean temp = (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)
					|| Constantes.MODO_ACCESO_MANTENIMIENTO.equals(modoAcceso)
					|| Constantes.MODO_ACCESO_SUBSANACION.equals(modoAcceso) || Constantes.MODO_ACCESO_INSPECCION
					.equals(modoAcceso));
			if (temp) {
				documentosTramiteAdd.setTramiteOS2(tramiteOS2);
			}
			DocumentoOS2 documento = this.documentoOS2Service.add(
					documentosTramiteAdd, temp);

			// recuperamos información del fichero para componente upload de UDA
			filesMetaInfo.add(this.getFileReturnMap(documentosTramiteAdd
					.getNombreDoc094(), documento.getIdDocumento094()
					.intValue()));

		} else if (Constantes.OS3.equals(docType)) {
			DocumentoOS3 documentosTramiteAdd = new DocumentoOS3();
			TramiteOS3 tramiteOS3 = new TramiteOS3();
			ComunicacionPrl comunicacionPrl = new ComunicacionPrl();

			if (session != null) {
				comunicacionPrl = (ComunicacionPrl) session
						.getAttribute(ComunicacionPrlController.ATTR_NAME_COMUNICAPRL_OS3_DETALLE);

				tramiteOS3 = new TramiteOS3(null, null, new OS3(
						comunicacionPrl.getTeros(), comunicacionPrl.getAnoos(),
						comunicacionPrl.getNumos()));
			}

			documentosTramiteAdd.setTramiteOS3(tramiteOS3);
			documentosTramiteAdd.setTipoDocumento(this.tipoDocumentoService
					.find(new TipoDocumento(idTipoDoc)));
			documentosTramiteAdd
					.setOrigen097(Constantes.DOCUMENTO_ORIGEN_CIUDADANO);
			documentosTramiteAdd.setOidDokusi097(oidDokusi);

			if (file != null
					&& StringUtils.isNotBlank(file.getOriginalFilename())) {
				documentosTramiteAdd
						.setNombreDoc097(file.getOriginalFilename());
			} else if (nombreFichero != null
					&& StringUtils.isNotBlank(nombreFichero)) {
				documentosTramiteAdd.setNombreDoc097(nombreFichero);
			} else {
				StringBuilder sb = new StringBuilder(
						Constantes.NOMBRE_DOCUMENTO_ESCANEADO_DOKUSI);
				sb.append(new SimpleDateFormat("yyyyMMdd_HHmmss")
						.format(new Date()));
				sb.append(Constantes.SEPARADOR_PUNTO)
						.append(Constantes.EXT_PDF);
				documentosTramiteAdd.setNombreDoc097(sb.toString());
			}

			// podemos llegar al método desde una subida de adjunto o desde una
			// digitalizacion
			// en caso de adjunto hay que subir a PIF y dokusi y guardarlo bbdd
			// en caso de digitalizacion el fichero ya está en dokusi y tenemos
			// su
			// oid, con lo que solo tenemos que guardarlo en base de datos
			if (StringUtils.isBlank(oidDokusi)) {
				// documento origen ha llegado en formato electronico
				documentosTramiteAdd
						.setFormatoAport097(Constantes.FORMATO_APORTACION_ELECTRONICO);
				try {

					// subimos adjunto a pif
					DocumentoOS3 resultadoPIF = this.documentoOS3Service
							.subeFicheroPIF(IOUtils.toByteArray(file
									.getInputStream()), PropertiesUtil
									.getProperty(PropertiesUtil.PIF_RUTA_APP),
									documentosTramiteAdd.getNombreDoc097(),
									false);

					// subimos documento a dokusi
					documentosTramiteAdd.setRutaPif097(resultadoPIF
							.getRutaPif097());

				} catch (Exception ex) {
					throw new ErrorGenericoException(ex.getMessage());
				}
			} else {
				// documento origen ha llegado en formato papel
				documentosTramiteAdd
						.setFormatoAport097(Constantes.FORMATO_APORTACION_PAPEL);
			}

			//
			// guardamos fichero en base de datos
			//
			boolean temp = (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)
					|| Constantes.MODO_ACCESO_MANTENIMIENTO.equals(modoAcceso)
					|| Constantes.MODO_ACCESO_SUBSANACION.equals(modoAcceso) || Constantes.MODO_ACCESO_INSPECCION
					.equals(modoAcceso));
			if (temp) {
				documentosTramiteAdd.setTramiteOS3(tramiteOS3);
			}
			DocumentoOS3 documento = this.documentoOS3Service.add(
					documentosTramiteAdd, temp);

			// recuperamos información del fichero para componente upload de UDA
			filesMetaInfo.add(this.getFileReturnMap(documentosTramiteAdd
					.getNombreDoc097(), documento.getIdDocumento097()
					.intValue()));

		} else {
			// generamos objeto para guardar en base de datos
			DocumentoAperturas documentosTramiteAdd = new DocumentoAperturas();
			Tramite tipoTramiteApertura = new Tramite();
			TramiteAperturas tramiteApertura = new TramiteAperturas();
			ComunicacionApertura apertura = new ComunicacionApertura();

			if (session != null) {
				apertura = (ComunicacionApertura) session
						.getAttribute(ComunicacionAperturaController.ATTR_NAME_COMUNICAPERTURA_DETALLE);
			}

			if (Constantes.MODO_ACCESO_MANTENIMIENTO.equals(modoAcceso)) {

				tipoTramiteApertura = this.tramiteService
						.findByProceedingIdProcedureId(
								TipoTramiteFlujo.APERTURA.name(), Utilities
										.getInstance()
										.obtenerProcedureIdApertura());

				tramiteApertura = this.tramiteAperturaService
						.findLastTramiteByTipo(
								tipoTramiteApertura.getIdTramite089(), apertura);

				if (tramiteApertura != null) {
					tramiteApertura.setApertura(apertura);
					documentosTramiteAdd.setTramiteAperturas(tramiteApertura);

				} else {
					documentosTramiteAdd
							.setTramiteAperturas(new TramiteAperturas(idTramite));
				}
			} else if (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)
					|| Constantes.MODO_ACCESO_MANTENIMIENTO.equals(modoAcceso)
					|| Constantes.MODO_ACCESO_SUBSANACION.equals(modoAcceso)
					|| Constantes.MODO_ACCESO_INSPECCION.equals(modoAcceso)) {
				tramiteApertura.setApertura(apertura);
				documentosTramiteAdd.setTramiteAperturas(tramiteApertura);

			}
			documentosTramiteAdd.setTipoDocumento(this.tipoDocumentoService
					.find(new TipoDocumento(idTipoDoc)));
			documentosTramiteAdd
					.setOrigen065(Constantes.DOCUMENTO_ORIGEN_CIUDADANO);
			documentosTramiteAdd.setOidDokusi065(oidDokusi);

			/*
			 * Utilities.getInstance().obtenerExtensionFichero(
			 * doc.getRutaPif011()
			 */
			if (file != null
					&& StringUtils.isNotBlank(file.getOriginalFilename())) {
				documentosTramiteAdd
						.setNombreDoc065(file.getOriginalFilename());
			} else if (nombreFichero != null
					&& StringUtils.isNotBlank(nombreFichero)) {
				documentosTramiteAdd.setNombreDoc065(nombreFichero);
			} else {
				StringBuilder sb = new StringBuilder(
						Constantes.NOMBRE_DOCUMENTO_ESCANEADO_DOKUSI);
				sb.append(new SimpleDateFormat("yyyyMMdd_HHmmss")
						.format(new Date()));
				sb.append(Constantes.SEPARADOR_PUNTO)
						.append(Constantes.EXT_PDF);
				documentosTramiteAdd.setNombreDoc065(sb.toString());
			}

			// documentosTramiteAdd.setDokusiFormat(Constantes.EXT_PDFA);
			// documentosTramiteAdd.setDokusiFormat(Utilities.getInstance()
			// .obtenerExtensionFichero(
			// documentosTramiteAdd.getNombrefich011()));

			// podemos llegar al método desde una subida de adjunto o desde una
			// digitalizacion
			// en caso de adjunto hay que subir a PIF y dokusi y guardarlo bbdd
			// en caso de digitalizacion el fichero ya está en dokusi y tenemos
			// su
			// oid, con lo que solo tenemos que guardarlo en base de datos
			if (StringUtils.isBlank(oidDokusi)) {
				// documento origen ha llegado en formato electronico
				documentosTramiteAdd
						.setFormatoAport065(Constantes.FORMATO_APORTACION_ELECTRONICO);
				try {

					// subimos adjunto a pif
					DocumentoAperturas resultadoPIF = this.documentoAperturasService
							.subeFicheroPIF(IOUtils.toByteArray(file
									.getInputStream()), PropertiesUtil
									.getProperty(PropertiesUtil.PIF_RUTA_APP),
									documentosTramiteAdd.getNombreDoc065(),
									false);

					// subimos documento a dokusi
					/*
					 * documentosTramiteAdd.setNombreDoc065(resultadoPIF
					 * .getNombreDoc065());
					 */
					documentosTramiteAdd.setRutaPif065(resultadoPIF
							.getRutaPif065());

				} catch (Exception ex) {
					throw new ErrorGenericoException(ex.getMessage());
				}
			} else {
				// documento origen ha llegado en formato papel
				documentosTramiteAdd
						.setFormatoAport065(Constantes.FORMATO_APORTACION_PAPEL);
			}

			//
			// guardamos fichero en base de datos
			//
			boolean temp = (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)
					|| Constantes.MODO_ACCESO_MANTENIMIENTO.equals(modoAcceso)
					|| Constantes.MODO_ACCESO_SUBSANACION.equals(modoAcceso) || Constantes.MODO_ACCESO_INSPECCION
					.equals(modoAcceso));
			if (temp) {
				documentosTramiteAdd.setIdapetemp065(apertura.getIdape056());
			}
			DocumentoAperturas documento = this.documentoAperturasService.add(
					documentosTramiteAdd, temp);

			// recuperamos información del fichero para componente upload de UDA
			filesMetaInfo.add(this.getFileReturnMap(documentosTramiteAdd
					.getNombreDoc065(), documento.getIdDocumento065()
					.intValue()));
		}

		return filesMetaInfo;
	}

	/**
	 * descargar fichero desde el componente rupupload de UDA.
	 * 
	 * codDocumento Integer request HttpServletRequest response
	 * HttpServletResponse
	 * 
	 * @param codDocumento
	 *            the cod documento
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @throws IOException
	 *             e
	 */
	@RequestMapping(value = "upload", method = RequestMethod.GET)
	@ResponseStatus(value = HttpStatus.OK)
	public void download(
			@RequestParam(value = "codDocumento", required = false) Long codDocumento,
			HttpServletRequest request, HttpServletResponse response)
			throws IOException {

		String modoAcceso = (String) request.getSession().getAttribute(
				ComunicacionAperturaController.ATTR_NAME_MODO_ACCESO);

		String docType = (String) request.getSession().getAttribute("docType");

		boolean temp = (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)
				|| Constantes.MODO_ACCESO_MANTENIMIENTO.equals(modoAcceso)
				|| Constantes.MODO_ACCESO_SUBSANACION.equals(modoAcceso) || Constantes.MODO_ACCESO_INSPECCION
				.equals(modoAcceso));
		// recuperamos informacion del fichero de base de datos
		if (Constantes.OS2.equals(docType)) {
			DocumentoOS2 documento = this
					.recuperaFicheroOS2(codDocumento, temp);

			if (documento.getDatosFichero() != null) {

				String headerKey = "Content-Disposition";
				String headerValue = String.format(
						"attachment; filename=\"%s\"",
						documento.getNombreDoc094());
				response.setHeader(headerKey, headerValue);
				response.setContentType("application/force-download");

				FileCopyUtils.copy(documento.getDatosFichero(),
						response.getOutputStream());

				response.flushBuffer();

			} else {
				throw new ErrorGenericoException("Error descargando fichero");
			}
		} else if (Constantes.OS3.equals(docType)) {
			DocumentoOS3 documento = this
					.recuperaFicheroOS3(codDocumento, temp);

			if (documento.getDatosFichero() != null) {

				String headerKey = "Content-Disposition";
				String headerValue = String.format(
						"attachment; filename=\"%s\"",
						documento.getNombreDoc097());
				response.setHeader(headerKey, headerValue);
				response.setContentType("application/force-download");

				FileCopyUtils.copy(documento.getDatosFichero(),
						response.getOutputStream());

				response.flushBuffer();

			} else {
				throw new ErrorGenericoException("Error descargando fichero");
			}
		} else {
			DocumentoAperturas documento = this.recuperaFichero(codDocumento,
					temp);

			if (documento.getDatosFichero() != null) {

				String headerKey = "Content-Disposition";
				String headerValue = String.format(
						"attachment; filename=\"%s\"",
						documento.getNombreDoc065());
				response.setHeader(headerKey, headerValue);
				response.setContentType("application/force-download");

				FileCopyUtils.copy(documento.getDatosFichero(),
						response.getOutputStream());

				response.flushBuffer();

			} else {
				throw new ErrorGenericoException("Error descargando fichero");
			}
		}

	}

	/**
	 * Removes the.
	 * 
	 * codDocumento Integer request HttpServletRequest response
	 * HttpServletResponse
	 * 
	 * @param codDocumento
	 *            the cod documento
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 */
	@RequestMapping(value = "{codDocumento}", method = RequestMethod.DELETE)
	@ResponseStatus(value = HttpStatus.OK)
	public void remove(
			@RequestParam(value = "codDocumento", required = false) Long codDocumento,
			HttpServletRequest request, HttpServletResponse response) {

		String modoAcceso = (String) request.getSession().getAttribute(
				ComunicacionAperturaController.ATTR_NAME_MODO_ACCESO);

		String docType = (String) request.getSession().getAttribute("docType");
		boolean temp = (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)
				|| Constantes.MODO_ACCESO_MANTENIMIENTO.equals(modoAcceso)
				|| Constantes.MODO_ACCESO_SUBSANACION.equals(modoAcceso) || Constantes.MODO_ACCESO_INSPECCION
				.equals(modoAcceso));
		if (Constantes.OS2.equals(docType)) {
			DocumentoOS2 documento = new DocumentoOS2();

			if (temp) {
				documento = this.documentoOS2Service.findTemp(new DocumentoOS2(
						codDocumento));
			} else {
				documento = this.documentoOS2Service.find(new DocumentoOS2(
						codDocumento));
			}

			if (documento == null) {
				throw new ErrorGenericoException("Fichero no encontrado!");
			}

			// borramos de base de datos
			if (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)) {
				this.documentoOS2Service.removeTemp(new DocumentoOS2(
						codDocumento));
			} else {
				this.documentoOS2Service.remove(new DocumentoOS2(codDocumento));
			}
		} else if (Constantes.OS3.equals(docType)) {
			DocumentoOS3 documento = new DocumentoOS3();

			if (temp) {
				documento = this.documentoOS3Service.findTemp(new DocumentoOS3(
						codDocumento));
			} else {
				documento = this.documentoOS3Service.find(new DocumentoOS3(
						codDocumento));
			}

			if (documento == null) {
				throw new ErrorGenericoException("Fichero no encontrado!");
			}

			// borramos de base de datos
			if (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)) {
				this.documentoOS3Service.removeTemp(new DocumentoOS3(
						codDocumento));
			} else {
				this.documentoOS3Service.remove(new DocumentoOS3(codDocumento));
			}
		} else {
			DocumentoAperturas documento = new DocumentoAperturas();
			if (temp) {
				documento = this.documentoAperturasService
						.findTemp(new DocumentoAperturas(codDocumento));
			} else {
				documento = this.documentoAperturasService
						.find(new DocumentoAperturas(codDocumento));
			}

			if (documento == null) {
				throw new ErrorGenericoException("Fichero no encontrado!");
			}

			// borramos de base de datos
			if (Constantes.MODO_ACCESO_ALTA.equals(modoAcceso)) {
				this.documentoAperturasService
						.removeTemp(new DocumentoAperturas(codDocumento));
			} else {
				this.documentoAperturasService.remove(new DocumentoAperturas(
						codDocumento));
			}
		}

	}

	/**
	 * devuelve la estructura de datos del fichero para que lo pinte en la jsp
	 * el componente upload de UDA.
	 * 
	 * nombreFichero String codDocumento Integer
	 * 
	 * @param nombreFichero
	 *            the nombre fichero
	 * @param codDocumento
	 *            the cod documento Map Map
	 * @return the file return map
	 */
	private Map<String, Object> getFileReturnMap(String nombreFichero,
			Integer codDocumento) {
		Map<String, Object> mapaRetorno = new HashMap<String, Object>();
		mapaRetorno.put("url", "/" + Constantes.NOMBRE_WAR_APERTURAS
				+ "/documentosController/upload?codDocumento=" + codDocumento);
		mapaRetorno.put("name", nombreFichero);
		mapaRetorno.put("delete_url", "/" + Constantes.NOMBRE_WAR_APERTURAS
				+ "/documentosController/upload?codDocumento=" + codDocumento);
		mapaRetorno.put("delete_type", "DELETE");
		return mapaRetorno;
	}

	/**
	 * Recupera el binario de un fichero de PIF/Dokusi a partir de su
	 * codDocumento.
	 * 
	 * codDocumento Integer temp boolean
	 * 
	 * @param codDocumento
	 *            the cod documento
	 * @param temp
	 *            the temp DocumentosTramite
	 * @return the documento aperturas
	 */
	private DocumentoAperturas recuperaFichero(Long codDocumento, boolean temp) {

		// obtenemos ruta y nombre del fichero a partir del codDocumento
		DocumentoAperturas documento = new DocumentoAperturas();
		if (temp) {
			documento = this.documentoAperturasService
					.findTemp(new DocumentoAperturas(codDocumento));
		} else {
			documento = this.documentoAperturasService
					.find(new DocumentoAperturas(codDocumento));
		}

		if (documento == null) {
			throw new ErrorGenericoException("documento no encontrado");
		}

		try {
			StringBuffer rutaCompletaDescargaPIF = new StringBuffer();

			// si el documento esta en dokusi, lo descargamos de dokusi a PIF
			if (StringUtils.isNotBlank(documento.getOidDokusi065())) {

				// pasamos ruta PIF para descargar el fichero de Dokusi
				documento.setRutaPif065(PropertiesUtil
						.getProperty(PropertiesUtil.PIF_RUTA_APP)
				/*
				 * + L61bGeneralUtils.generateUID() + "-" +
				 * documento.getNombrefich011()
				 */);

				// tipo de documento (pdfa)
				if (!documento.getOrigen065().equals(
						Constantes.DOCUMENTO_ORIGEN_CIUDADANO)) {
					documento.setDokusiFormat(Constantes.EXT_PDFA);
				}

				// Si es documento digitalizado, forzamos su descarga en formato
				// pdfa (ya que si no lo hace en .papel y no funciona)
				if (Constantes.FORMATO_APORTACION_PAPEL.equals(documento
						.getFormatoAport065())) {
					documento.setDokusiFormat(ConstantesDokusi.FORMATO_PDFA);
				}

				T65BDocumentType fichero = this.dokusiService
						.recuperarDocumento(UtilSeguridad.getInstance()
								.getAuditUser(), documento,
								new T65BStringListType());
				// la descarga de dokusi lo deja en una zona de PIF
				rutaCompletaDescargaPIF.append(fichero.getContent().getPifId());
			} else {
				// si el documento no esta en dokusi, obtenemos su ruta PIF del
				// registro de base de datos
				/*
				 * rutaCompletaDescargaPIF.append(PropertiesUtil
				 * .getProperty(PropertiesUtil.PIF_RUTA_APP));
				 */
				rutaCompletaDescargaPIF.append(documento.getRutaPif065());
			}

			// descargamos fichero de ruta PIF
			documento.setDatosFichero(this.documentoAperturasService
					.descargarDocumento(rutaCompletaDescargaPIF.toString()));
		} catch (Exception e) {
			throw new ErrorGenericoException(e.getMessage());
		}

		return documento;
	}

	/**
	 * Recupera el binario de un fichero de PIF/Dokusi a partir de su
	 * codDocumento.
	 * 
	 * codDocumento Integer temp boolean
	 * 
	 * @param codDocumento
	 *            the cod documento
	 * @param temp
	 *            the temp DocumentosTramite
	 * @return the documento os2
	 */

	private DocumentoOS2 recuperaFicheroOS2(Long codDocumento, boolean temp) {

		// obtenemos ruta y nombre del fichero a partir del codDocumento
		DocumentoOS2 documento = new DocumentoOS2();
		if (temp) {
			documento = this.documentoOS2Service.findTemp(new DocumentoOS2(
					codDocumento));
		} else {
			documento = this.documentoOS2Service.find(new DocumentoOS2(
					codDocumento));
		}

		if (documento == null) {
			throw new ErrorGenericoException("documento no encontrado");
		}

		try {
			StringBuffer rutaCompletaDescargaPIF = new StringBuffer();

			// si el documento esta en dokusi, lo descargamos de dokusi a PIF
			if (StringUtils.isNotBlank(documento.getOidDokusi094())) {

				// pasamos ruta PIF para descargar el fichero de Dokusi
				documento.setRutaPif094(PropertiesUtil
						.getProperty(PropertiesUtil.PIF_RUTA_APP));

				// tipo de documento (pdfa)
				if (documento.getOrigen094() != null
						&& !documento.getOrigen094().equals(
								Constantes.DOCUMENTO_ORIGEN_CIUDADANO)) {
					documento.setDokusiFormat(Constantes.EXT_PDFA);
				}

				// Si es documento digitalizado, forzamos su descarga en formato
				// pdfa (ya que si no lo hace en .papel y no funciona)
				if (Constantes.FORMATO_APORTACION_PAPEL.equals(documento
						.getFormatoAport094())) {
					documento.setDokusiFormat(ConstantesDokusi.FORMATO_PDFA);
				}

				T65BDocumentType fichero = this.dokusiService
						.recuperarDocumento(UtilSeguridad.getInstance()
								.getAuditUser(), documento,
								new T65BStringListType());
				// la descarga de dokusi lo deja en una zona de PIF
				rutaCompletaDescargaPIF.append(fichero.getContent().getPifId());
			} else {
				// si el documento no esta en dokusi, obtenemos su ruta PIF del
				// registro de base de datos

				rutaCompletaDescargaPIF.append(documento.getRutaPif094());
			}

			// descargamos fichero de ruta PIF
			documento.setDatosFichero(this.documentoOS2Service
					.descargarDocumento(rutaCompletaDescargaPIF.toString()));
		} catch (Exception e) {
			throw new ErrorGenericoException(e.getMessage());
		}

		return documento;
	}

	/**
	 * Recupera el binario de un fichero de PIF/Dokusi a partir de su
	 * codDocumento.
	 * 
	 * codDocumento Integer temp boolean
	 * 
	 * @param codDocumento
	 *            the cod documento
	 * @param temp
	 *            the temp DocumentosTramite
	 * @return the documento os3
	 */

	private DocumentoOS3 recuperaFicheroOS3(Long codDocumento, boolean temp) {

		// obtenemos ruta y nombre del fichero a partir del codDocumento
		DocumentoOS3 documento = new DocumentoOS3();
		if (temp) {
			documento = this.documentoOS3Service.findTemp(new DocumentoOS3(
					codDocumento));
		} else {
			documento = this.documentoOS3Service.find(new DocumentoOS3(
					codDocumento));
		}

		if (documento == null) {
			throw new ErrorGenericoException("documento no encontrado");
		}

		try {
			StringBuffer rutaCompletaDescargaPIF = new StringBuffer();

			// si el documento esta en dokusi, lo descargamos de dokusi a PIF
			if (StringUtils.isNotBlank(documento.getOidDokusi097())) {

				// pasamos ruta PIF para descargar el fichero de Dokusi
				documento.setRutaPif097(PropertiesUtil
						.getProperty(PropertiesUtil.PIF_RUTA_APP));

				// tipo de documento (pdfa)
				if (documento.getOrigen097() != null
						&& !documento.getOrigen097().equals(
								Constantes.DOCUMENTO_ORIGEN_CIUDADANO)) {
					documento.setDokusiFormat(Constantes.EXT_PDFA);
				}

				// Si es documento digitalizado, forzamos su descarga en formato
				// pdfa (ya que si no lo hace en .papel y no funciona)
				if (Constantes.FORMATO_APORTACION_PAPEL.equals(documento
						.getFormatoAport097())) {
					documento.setDokusiFormat(ConstantesDokusi.FORMATO_PDFA);
				}

				T65BDocumentType fichero = this.dokusiService
						.recuperarDocumento(UtilSeguridad.getInstance()
								.getAuditUser(), documento,
								new T65BStringListType());
				// la descarga de dokusi lo deja en una zona de PIF
				rutaCompletaDescargaPIF.append(fichero.getContent().getPifId());
			} else {
				// si el documento no esta en dokusi, obtenemos su ruta PIF del
				// registro de base de datos

				rutaCompletaDescargaPIF.append(documento.getRutaPif097());
			}

			// descargamos fichero de ruta PIF
			documento.setDatosFichero(this.documentoOS3Service
					.descargarDocumento(rutaCompletaDescargaPIF.toString()));
		} catch (Exception e) {
			throw new ErrorGenericoException(e.getMessage());
		}

		return documento;
	}

	/**
	 * Escribir fichero en response.
	 * 
	 * response HttpServletResponse documentoAperturas DocumentoAperturas temp
	 * boolean
	 * 
	 * @param response
	 *            the response
	 * @param documentoAperturas
	 *            the documento aperturas
	 * @param temp
	 *            the temp
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */
	private void escribirFicheroEnResponse(HttpServletResponse response,
			DocumentoAperturas documentoAperturas, boolean temp)
			throws AB04BException {

		try {
			T65BDocumentType fichero = this.recuperaRutaPifFichero(
					documentoAperturas, temp);

			byte[] bytes = descargarDocumento(fichero.getContent().getPifId());

			if (documentoAperturas.getOidDokusi065() == null) {
				String headerKey = "Content-Disposition";
				String headerValue = String.format(
						"attachment; filename=\"%s\"",
						documentoAperturas.getNombreDoc065());
				response.setHeader(headerKey, headerValue);
				response.setContentType("application/force-download");

			} else {
				if (fichero.getContent().getFormat().getMimeType()
						.indexOf("html") != -1) {
					response.setContentType("text/html;charset=ISO-8859-1");
					response.setCharacterEncoding("ISO-8859-1");
				} else {
					response.setContentType(fichero.getContent().getFormat()
							.getMimeType());
				}

				response.setHeader("content-disposition", "inline; filename=\""
						+ documentoAperturas.getOidDokusi065() + "."
						+ fichero.getContent().getFormat().getExtension()
						+ "\"");

			}

			response.getOutputStream().write(bytes);
			response.flushBuffer();
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	/**
	 * Escribir fichero en response.
	 * 
	 * response HttpServletResponse documentoOS2 DocumentoOS2 temp boolean
	 * 
	 * @param response
	 *            the response
	 * @param documentoOS2
	 *            the documento os2
	 * @param temp
	 *            the temp
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */
	private void escribirFicheroOS2EnResponse(HttpServletResponse response,
			DocumentoOS2 documentoOS2, boolean temp) throws AB04BException {

		try {
			T65BDocumentType fichero = this.recuperaRutaPifFicheroOS2(
					documentoOS2, temp);

			byte[] bytes = descargarDocumento(fichero.getContent().getPifId());

			if (documentoOS2.getOidDokusi094() == null) {
				String headerKey = "Content-Disposition";
				String headerValue = String.format(
						"attachment; filename=\"%s\"",
						documentoOS2.getNombreDoc094());
				response.setHeader(headerKey, headerValue);
				response.setContentType("application/force-download");

			} else {
				if (fichero.getContent().getFormat().getMimeType()
						.indexOf("html") != -1) {
					response.setContentType("text/html;charset=ISO-8859-1");
					response.setCharacterEncoding("ISO-8859-1");
				} else {
					response.setContentType(fichero.getContent().getFormat()
							.getMimeType());
				}

				response.setHeader("content-disposition", "inline; filename=\""
						+ documentoOS2.getOidDokusi094() + "."
						+ fichero.getContent().getFormat().getExtension()
						+ "\"");

			}

			response.getOutputStream().write(bytes);
			response.flushBuffer();
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

}
