/*
* Copyright 2014 - LAit SpA
*				 Realizzato da Icona Management srl su commessa LAit SpA
* Copyright 2015- LAit SpA
*                                                  Aggiornato da LAit SpA
*
* Concesso in licenza a norma dell'EUPL, versione 1.1 o
* successive dell'EUPL (la "Licenza")  non appena saranno
* approvate dalla Commissione europea;
* Non è possibile utilizzare l'opera salvo nel rispetto della Licenza.
* E' possibile ottenere una copia della Licenza al seguente indirizzo:
*
* http://ec.europa.eu/idabc/eupl
*
* Salvo diversamente indicato dalla legge applicabile o
* concordato per iscritto, il software distribuito secondo
* i termini della Licenza è distribuito "TAL QUALE",
* SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO,
* esplicite o implicite.
* Si veda la Licenza per la lingua specifica che disciplina
* le autorizzazioni e le limitazioni secondo i termini della
* Licenza.
*/
/**
 * 
 */
package it.laitspa.cpf.spring.sogei;

import it.gov.fatturapa.sdi.fatturapa.v1.AllegatiType;
import it.gov.fatturapa.sdi.fatturapa.v1.AltriDatiGestionaliType;
import it.gov.fatturapa.sdi.fatturapa.v1.AnagraficaType;
import it.gov.fatturapa.sdi.fatturapa.v1.CedentePrestatoreType;
import it.gov.fatturapa.sdi.fatturapa.v1.CessionarioCommittenteType;
import it.gov.fatturapa.sdi.fatturapa.v1.CodiceArticoloType;
import it.gov.fatturapa.sdi.fatturapa.v1.CondizioniPagamentoType;
import it.gov.fatturapa.sdi.fatturapa.v1.ContattiTrasmittenteType;
import it.gov.fatturapa.sdi.fatturapa.v1.ContattiType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiAnagraficiCedenteType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiAnagraficiCessionarioType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiAnagraficiRappresentanteType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiAnagraficiTerzoIntermediarioType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiAnagraficiVettoreType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiBeniServiziType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiBolloType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiCassaPrevidenzialeType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiDDTType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiDocumentiCorrelatiType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiGeneraliDocumentoType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiGeneraliType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiPagamentoType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiRiepilogoType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiRitenutaType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiSALType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiTrasmissioneType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiTrasportoType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiVeicoliType;
import it.gov.fatturapa.sdi.fatturapa.v1.DettaglioLineeType;
import it.gov.fatturapa.sdi.fatturapa.v1.DettaglioPagamentoType;
import it.gov.fatturapa.sdi.fatturapa.v1.FatturaElettronicaBodyType;
import it.gov.fatturapa.sdi.fatturapa.v1.FatturaElettronicaHeaderType;
import it.gov.fatturapa.sdi.fatturapa.v1.FatturaElettronicaType;
import it.gov.fatturapa.sdi.fatturapa.v1.FatturaPrincipaleType;
import it.gov.fatturapa.sdi.fatturapa.v1.IdFiscaleType;
import it.gov.fatturapa.sdi.fatturapa.v1.IndirizzoType;
import it.gov.fatturapa.sdi.fatturapa.v1.IscrizioneREAType;
import it.gov.fatturapa.sdi.fatturapa.v1.ModalitaPagamentoType;
import it.gov.fatturapa.sdi.fatturapa.v1.NaturaType;
import it.gov.fatturapa.sdi.fatturapa.v1.ObjectFactory;
import it.gov.fatturapa.sdi.fatturapa.v1.RappresentanteFiscaleType;
import it.gov.fatturapa.sdi.fatturapa.v1.RitenutaType;
import it.gov.fatturapa.sdi.fatturapa.v1.ScontoMaggiorazioneType;
import it.gov.fatturapa.sdi.fatturapa.v1.SoggettoEmittenteType;
import it.gov.fatturapa.sdi.fatturapa.v1.TerzoIntermediarioSoggettoEmittenteType;
import it.gov.fatturapa.sdi.fatturapa.v1.TipoCassaType;
import it.gov.fatturapa.sdi.fatturapa.v1.TipoCessionePrestazioneType;
import it.gov.fatturapa.sdi.fatturapa.v1.TipoScontoMaggiorazioneType;
import it.laitspa.cpf.model.sogei.anagrafica.AnagraficaSogei;
import it.laitspa.cpf.model.sogei.cassaprevidenziale.CassaPrevidenzialeSogei;
import it.laitspa.cpf.model.sogei.cedente.CedentePrestatoreSogei;
import it.laitspa.cpf.model.sogei.cedente.IscrizioneReaSogei;
import it.laitspa.cpf.model.sogei.cessionariocommittente.CessionarioCommittenteSogei;
import it.laitspa.cpf.model.sogei.codifica.CodificaArticoloSogei;
import it.laitspa.cpf.model.sogei.condizionepagamento.CondizionePagamentoSogei;
import it.laitspa.cpf.model.sogei.condizionepagamento.TipoCondizioniPagamentoSogei;
import it.laitspa.cpf.model.sogei.condizionepagamento.TipoModalitaPagamentoSogei;
import it.laitspa.cpf.model.sogei.contatto.ContattoSogei;
import it.laitspa.cpf.model.sogei.datogestionale.DatoGestionaleSogei;
import it.laitspa.cpf.model.sogei.documentoallegato.AllegatoDocumentoSogei;
import it.laitspa.cpf.model.sogei.documentoallegato.ContenutoAllegatoDocumentoSogei;
import it.laitspa.cpf.model.sogei.fattura.AllegatoFatturaSogei;
import it.laitspa.cpf.model.sogei.fattura.FatturaSogei;
import it.laitspa.cpf.model.sogei.fattura.FatturaSogeiDAO;
import it.laitspa.cpf.model.sogei.indirizzo.IndirizzoSogei;
import it.laitspa.cpf.model.sogei.inviofilesdi.InvioFileSdiDAO;
import it.laitspa.cpf.model.sogei.inviofilesdi.InvioFileSdiSogei;
import it.laitspa.cpf.model.sogei.regimefiscale.TipoRegimeFiscaleSogei;
import it.laitspa.cpf.model.sogei.riepilogo.RiepilogoFatturaSogei;
import it.laitspa.cpf.model.sogei.riferimentodocumento.RiferimentoDocumentoSogei;
import it.laitspa.cpf.model.sogei.riferimentolinea.RiferimentoLineaDocumentoSogei;
import it.laitspa.cpf.model.sogei.riga.RigaFatturaSogei;
import it.laitspa.cpf.model.sogei.ritenuta.RitenutaSogei;
import it.laitspa.cpf.model.sogei.sconto.ScontoSogei;
import it.laitspa.cpf.model.sogei.soggetto.SoggettoSogei;
import it.laitspa.cpf.model.sogei.soggetto.SoggettoSogeiDAO;
import it.laitspa.cpf.model.sogei.statofattura.StatoFatturaSogei;
import it.laitspa.cpf.model.sogei.statoinvio.StatoInvioSogei;
import it.laitspa.cpf.model.sogei.tipocassaprevidenziale.TipoCassaPrevidenzialeSogei;
import it.laitspa.cpf.model.sogei.tipofattura.TipoFatturaSogei;
import it.laitspa.cpf.model.sogei.tiponatura.TipoNaturaSogei;
import it.laitspa.cpf.model.sogei.tipoprestazione.TipoPrestazioneSogei;
import it.laitspa.cpf.model.sogei.tiporiferimentodocumento.TipoRiferimentoDocumentoSogei;
import it.laitspa.cpf.model.sogei.tiporitenuta.TipoRitenutaSogei;
import it.laitspa.cpf.model.sogei.tiposconto.TipoScontoSogei;
import it.laitspa.cpf.model.sogei.trasmissione.TrasmissioneSogei;
import it.laitspa.cpf.model.sogei.trasporto.TrasportoFatturaSogei;
import it.laitspa.cpf.util.exceptions.FacadeException;
import it.laitspa.cpf.util.log.LogUtils;
import it.laitspa.cpf.util.misc.DateUtils;
import it.laitspa.xsd.resolver.XmlMarshaller;

import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.xml.bind.JAXBElement;

import org.hibernate.Session;

/**
 * @author andrea
 * 
 */
public class SogeiRicezioneLoader
  extends SogeiLoaderImpl
{

  public SogeiRicezioneLoader(Session session, InvioFileSdiSogei flussoSogei,
      List<FatturaElettronicaType> fatture)
  {
    super(session, flussoSogei, fatture);
  }

  /*
   * (non-Javadoc)
   * 
   * @see it.laitspa.cpf.spring.sogei.SogeiLoader#loadSogei()
   */
  @Override
  public boolean loadSogei()
  {

    StatoInvioSogei statoFlusso = flussoSogei.getStatoInvio();
    InvioFileSdiDAO idao = new InvioFileSdiDAO(session);

    Iterator<FatturaElettronicaType> i_fatture = fatture.iterator();
    int index = 0;
    while(i_fatture.hasNext())
    {
      LogUtils.info(getClass(), "Processing flux n. " + ++index + " for flux id " + flussoSogei.getCodice());
      
      FatturaElettronicaType fattura = i_fatture.next();
      i_fatture.remove();
      
      FatturaElettronicaHeaderType header_fattura = fattura.getFatturaElettronicaHeader();
      
      
      // <DatiTrasmissione>
      //
      TrasmissioneSogei trasmissione = null;
      if(statoFlusso.getCodice().equals(StatoInvioSogei.RICEVUTO))
        trasmissione = createTrasmissione(session, now, flussoSogei, header_fattura);
      else
        trasmissione = idao.retrieveTrasmissioneForFlux(flussoSogei.getCodice());

      // <CedentePrestatore>
      //
      CedentePrestatoreType ctype = header_fattura.getCedentePrestatore();
      CedentePrestatoreSogei cedente =
          createCedentePrestatore(session, now, header_fattura, trasmissione, ctype);

      // Retrieve SoggettoEmittente if present.
      //
      SoggettoSogei emittente = null;
      SoggettoSogeiDAO sdao = new SoggettoSogeiDAO(session);
      if(cedente != null)
      {
        AnagraficaSogei anagrafica = cedente.getAnagrafica();
        emittente =
            sdao.retrieveByPivaOrCF(anagrafica.getNazione(),
                anagrafica.getCodiceIdentificativoFiscale(), anagrafica.getCodiceFiscale());
      }

      // <CessionarioCommittente>
      //
      CessionarioCommittenteType cctype = header_fattura.getCessionarioCommittente();
      CessionarioCommittenteSogei cessionarioCommittente =
          createCessionarioCommittente(session, now, trasmissione, cctype);

      // Retrieve Committente
      //
      SoggettoSogei committente = sdao.retrieveByCodiceIpa(trasmissione.getCodiceDestinatario());
      if(committente == null)
      {
        // Retrieve from Anagrafica
        //
        AnagraficaSogei anagrafica = cessionarioCommittente.getAnagrafica();
        if(anagrafica != null)
          committente =
              sdao.retrieveByPivaOrCF(anagrafica.getNazione(),
                  anagrafica.getCodiceIdentificativoFiscale(), anagrafica.getCodiceFiscale());
      }

      // Check what i need based on type of flux!
      //
      // Save invoice state.
      //
      StatoFatturaSogei statoFatturaSogei = null;

      if(statoFlusso.getCodice().equals(StatoInvioSogei.RICEVUTO))
      {
        statoFatturaSogei =
            (StatoFatturaSogei)session.load(StatoFatturaSogei.class, StatoFatturaSogei.RICEVUTA);

        // Committente must be present.
        //
        if(committente == null)
        {
          LogUtils
              .error(
                  getClass(),
                  "Is not possible to retrieve Committente from Codice IPA or <CessionarioCommittente> element for id "
                      + flussoSogei.getIdentificativo());
          return false;
        }
        else
        {
          trasmissione.setSoggettoCessionario(committente);
          session.update(trasmissione);
        }

        // Emittente can be nullable
        //
        if(emittente != null)
        {
          trasmissione.setSoggettoCedente(emittente);
          session.update(trasmissione);
        }

      }
      else if(statoFlusso.getCodice().equals(StatoInvioSogei.INVIATO))
      {

        statoFatturaSogei =
            (StatoFatturaSogei)session.load(StatoFatturaSogei.class, StatoFatturaSogei.INVIATA);

        if(emittente == null)
        {
          LogUtils.error(getClass(),
              "Is not possible to retrieve Emittente from <CedentePrestatore> element for id "
                  + flussoSogei.getIdentificativo());
          return false;
        }

        /*
         * Already present in serialize via form.
         * 
         * TipoSoggettoSogei tipoSoggetto = (TipoSoggettoSogei)
         * session.load(TipoSoggettoSogei.class, TipoSoggettoSogei.EMITTENTE);
         * SoggettoTrasmissioneSogei trasmissioneSoggetto = new
         * SoggettoTrasmissioneSogei();
         * trasmissioneSoggetto.setSoggetto(emittente);
         * trasmissioneSoggetto.setTipoSoggetto(tipoSoggetto);
         * trasmissioneSoggetto.setTrasmissione(trasmissione);
         * session.save(trasmissioneSoggetto);
         */
      }

      // <TerzoIntermediarioOSoggettoEmittente>
      //
      TerzoIntermediarioSoggettoEmittenteType stype =
          header_fattura.getTerzoIntermediarioOSoggettoEmittente();
      if(stype != null)
      {
        createTerzoIntermediario(session, now, cedente, stype);
        session.update(cedente);
      }

      // Iterate on body children of invoice
      //
      List<FatturaElettronicaBodyType> invoices = fattura.getFatturaElettronicaBody();
      Iterator<FatturaElettronicaBodyType> ir = invoices.iterator();
      FatturaSogeiDAO fdao = new FatturaSogeiDAO(session);
      while(ir.hasNext())
      {
        FatturaElettronicaBodyType body = ir.next();
        DatiGeneraliType datigenerali = body.getDatiGenerali();

        // <DatiGeneraliDocumento>
        //
        DatiGeneraliDocumentoType datidocumento = datigenerali.getDatiGeneraliDocumento();
        String numeroFattura = datidocumento.getNumero();
        Date dataFattura = DateUtils.toDate(datidocumento.getData());
        String divisa = datidocumento.getDivisa();

        TipoFatturaSogei tipoFattura =
            (TipoFatturaSogei)fdao.getItemByDescrizione("TipoFatturaSogei", "label", datidocumento
                .getTipoDocumento().value());

        if(tipoFattura == null)
          throw new FacadeException("Is not possible to decode TipoDocumento element "
              + datidocumento.getTipoDocumento().value());

        // Check for double insertion.
        //
        AnagraficaSogei anagraficaCedente = cedente.getAnagrafica();
        FatturaSogei already_invoice =
            fdao.retrieveFattura(numeroFattura, dataFattura, tipoFattura.getCodice(),
                anagraficaCedente.getNazione(), anagraficaCedente.getCodiceIdentificativoFiscale());

        if(already_invoice != null)
        {
          // Retrieve existing trasmissione.
          //
          if(statoFlusso.getCodice().equals(StatoInvioSogei.RICEVUTO))
          {
            TrasmissioneSogei already_trasmissione = already_invoice.getDatiTrasmissione();
            if(emittente != null)
            {
              // Check if present in trasmissione.
              //
              LogUtils.info(getClass(),
                  "Check for emittente already registered in existing trasmissione.");
              if(!fdao.isSoggettoPresentInTransmission(emittente.getCodice(),
                  already_trasmissione.getCodice()))
              {
                already_trasmissione.setSoggettoCedente(emittente);
                session.update(already_trasmissione);
              }
            }

            // I received something that is already present in system, but isn't
            // a confirming flux!
            //
            // Check for committente and switch state if needed.
            //
            LogUtils.info(getClass(),
                "Check for cessionario committente already registered in existing trasmissione.");
            if(!fdao.isSoggettoPresentInTransmission(committente.getCodice(),
                already_trasmissione.getCodice()))
            {
              already_trasmissione.setSoggettoCessionario(committente);
              session.update(already_trasmissione);
            }

            // Upgrade to received state.
            //
            StatoFatturaSogei statoF = already_invoice.getStato();
            if(statoF.getCodice().equals(StatoFatturaSogei.IMMESSA)
                || statoF.getCodice().equals(StatoFatturaSogei.INVIATA))
            {
              already_invoice.setStato(statoFatturaSogei);
              session.update(already_invoice);
            }
            
            
            // Notify scarto!
            //
            SogeiServiceWrapper sw = new SogeiServiceWrapper(session);
            sw.notificaEsitoCommittente(numeroFattura, dataFattura, flussoSogei.getCodice(),
                Boolean.FALSE, "Invoice already present.");
          }



          continue;
        }

        FatturaSogei i_fattura = new FatturaSogei();
        i_fattura.setInvio(flussoSogei);
        i_fattura.setDataFattura(dataFattura);
        i_fattura.setNumeroFattura(numeroFattura);
        i_fattura.setStato(statoFatturaSogei);
        i_fattura.setDatiTrasmissione(trasmissione);
        i_fattura.setDivisa(divisa);
        i_fattura.setTipoFattura(tipoFattura);
        session.save(i_fattura);

        // <DatiRitenuta>
        //
        DatiRitenutaType rtype = datidocumento.getDatiRitenuta();
        if(rtype != null)
        {
          RitenutaSogei ritenuta = createRitenuta(fdao, i_fattura, rtype);
          if(ritenuta != null)
            session.save(ritenuta);
        }

        // <DatiBollo>
        //
        DatiBolloType btype = datidocumento.getDatiBollo();
        if(btype != null)
        {
          i_fattura.setImportoBollo(btype.getImportoBollo());
          i_fattura.setNumeroBollo(btype.getBolloVirtuale().value());
          session.update(i_fattura);
        }

        // <DatiCassaPrevidenziale>
        //
        List<DatiCassaPrevidenzialeType> casse = datidocumento.getDatiCassaPrevidenziale();
        Iterator<DatiCassaPrevidenzialeType> cr = casse.iterator();
        while(cr.hasNext())
        {
          DatiCassaPrevidenzialeType cassatype = cr.next();
          CassaPrevidenzialeSogei c_prev = createCassaPrevidenziale(fdao, cassatype);
          if(c_prev != null)
          {
            c_prev.setFattura(i_fattura);
            session.save(c_prev);
          }
        }

        // <ScontoMaggiorazione>
        //
        List<ScontoMaggiorazioneType> sconti = datidocumento.getScontoMaggiorazione();
        Iterator<ScontoMaggiorazioneType> scr = sconti.iterator();
        while(scr.hasNext())
        {
          ScontoMaggiorazioneType sc_type = scr.next();
          ScontoSogei sconto = createScontoMaggiorazione(fdao, sc_type);
          if(sconto != null)
          {
            sconto.setFattura(i_fattura);
            session.save(sconto);
          }
        }

        i_fattura.setImportoTotale(datidocumento.getImportoTotaleDocumento());
        i_fattura.setImportoArrotondamento(datidocumento.getArrotondamento());
        i_fattura.setCausale((datidocumento.getCausale() != null && !datidocumento.getCausale().isEmpty())?datidocumento.getCausale().get(0):"");

        Boolean flagArt73 = Boolean.FALSE;
        if(datidocumento.getArt73() != null && datidocumento.getArt73().value().equals("SI"))
          flagArt73 = Boolean.TRUE;
        i_fattura.setFlagArt73(flagArt73);

        // <NormaDiRiferimento>
        //
        i_fattura.setNormativaRiferimento("");

        // <FatturaPrincipale>
        //
        FatturaPrincipaleType f_main = datigenerali.getFatturaPrincipale();
        if(f_main != null)
        {
          i_fattura.setNumeroFatturaPrincipale(f_main.getNumeroFatturaPrincipale());
          i_fattura.setDataFatturaPrincipale(DateUtils.toDate(f_main.getDataFatturaPrincipale()));
        }
        session.update(i_fattura);

        // <DatiOrdineAcquisto>
        //
        List<DatiDocumentiCorrelatiType> l_doc = datigenerali.getDatiOrdineAcquisto();
        TipoRiferimentoDocumentoSogei tipoDocumentoRif =
            (TipoRiferimentoDocumentoSogei)session.load(TipoRiferimentoDocumentoSogei.class,
                TipoRiferimentoDocumentoSogei.ORDINE);
        Iterator<DatiDocumentiCorrelatiType> i_doc = l_doc.iterator();
        while(i_doc.hasNext())
        {
          DatiDocumentiCorrelatiType r_doc = i_doc.next();
          createAndSaveRiferimentoDocumento(session, i_fattura, tipoDocumentoRif, r_doc);
        }

        // <DatiContratto>
        //
        l_doc = datigenerali.getDatiContratto();
        tipoDocumentoRif =
            (TipoRiferimentoDocumentoSogei)session.load(TipoRiferimentoDocumentoSogei.class,
                TipoRiferimentoDocumentoSogei.CONTRATTO);
        i_doc = l_doc.iterator();
        while(i_doc.hasNext())
        {
          DatiDocumentiCorrelatiType r_doc = i_doc.next();
          createAndSaveRiferimentoDocumento(session, i_fattura, tipoDocumentoRif, r_doc);
        }

        // <DatiConvenzione>
        //
        l_doc = datigenerali.getDatiConvenzione();
        tipoDocumentoRif =
            (TipoRiferimentoDocumentoSogei)session.load(TipoRiferimentoDocumentoSogei.class,
                TipoRiferimentoDocumentoSogei.CONVENZIONE);
        i_doc = l_doc.iterator();
        while(i_doc.hasNext())
        {
          DatiDocumentiCorrelatiType r_doc = i_doc.next();
          createAndSaveRiferimentoDocumento(session, i_fattura, tipoDocumentoRif, r_doc);
        }

        // <DatiRicezione>
        //
        l_doc = datigenerali.getDatiRicezione();
        tipoDocumentoRif =
            (TipoRiferimentoDocumentoSogei)session.load(TipoRiferimentoDocumentoSogei.class,
                TipoRiferimentoDocumentoSogei.DOCUMENTO_DI_RICEZIONE);
        i_doc = l_doc.iterator();
        while(i_doc.hasNext())
        {
          DatiDocumentiCorrelatiType r_doc = i_doc.next();
          createAndSaveRiferimentoDocumento(session, i_fattura, tipoDocumentoRif, r_doc);
        }

        // <DatiFattureCollegate>
        //
        l_doc = datigenerali.getDatiFattureCollegate();
        tipoDocumentoRif =
            (TipoRiferimentoDocumentoSogei)session.load(TipoRiferimentoDocumentoSogei.class,
                TipoRiferimentoDocumentoSogei.FATTURE);
        i_doc = l_doc.iterator();
        while(i_doc.hasNext())
        {
          DatiDocumentiCorrelatiType r_doc = i_doc.next();
          createAndSaveRiferimentoDocumento(session, i_fattura, tipoDocumentoRif, r_doc);
        }

        // <DatiSAL>
        //
        List<DatiSALType> l_sal = datigenerali.getDatiSAL();
        tipoDocumentoRif =
            (TipoRiferimentoDocumentoSogei)session.load(TipoRiferimentoDocumentoSogei.class,
                TipoRiferimentoDocumentoSogei.SAL);
        Iterator<DatiSALType> i_sal = l_sal.iterator();
        while(i_sal.hasNext())
        {
          DatiSALType r_doc = i_sal.next();
          createAndSaveRiferimentoDocumento(session, i_fattura, tipoDocumentoRif, r_doc);
        }

        // <DatiDDT>
        //
        List<DatiDDTType> l_ddt = datigenerali.getDatiDDT();
        tipoDocumentoRif =
            (TipoRiferimentoDocumentoSogei)session.load(TipoRiferimentoDocumentoSogei.class,
                TipoRiferimentoDocumentoSogei.DDT);
        Iterator<DatiDDTType> i_ddt = l_ddt.iterator();
        while(i_ddt.hasNext())
        {
          DatiDDTType r_doc = i_ddt.next();
          createAndSaveRiferimentoDocumento(session, i_fattura, tipoDocumentoRif, r_doc);
        }

        // <DatiTrasporto>
        //
        DatiTrasportoType tr_type = datigenerali.getDatiTrasporto();
        createAndSaveTrasporto(session, now, i_fattura, tr_type);

        session.update(i_fattura);
        LogUtils.info(getClass(), "FatturaSogei successfully updated.");

        // <DatiBeniServizi>
        //
        DatiBeniServiziType d_body = body.getDatiBeniServizi();
        List<DettaglioLineeType> l_lines = d_body.getDettaglioLinee();
        Iterator<DettaglioLineeType> i_lines = l_lines.iterator();
        int i = 0;
        while(i_lines.hasNext())
        {
          i++;
          DettaglioLineeType line = i_lines.next();
          createAndSaveRiga(session, fdao, i_fattura, line);
          LogUtils.info(getClass(), "Riga " + i + " successfully saved.");
        }

        // <DatiRiepilogo>
        //
        List<DatiRiepilogoType> l_riep = d_body.getDatiRiepilogo();
        Iterator<DatiRiepilogoType> i_riep = l_riep.iterator();
        i = 0;
        while(i_riep.hasNext())
        {
          i++;
          DatiRiepilogoType line = i_riep.next();
          createAndSaveRiepilogoFattura(session, fdao, i_fattura, line);
          LogUtils.info(getClass(), "DatiRiepilogo " + i + " successfully saved.");
        }

        // <DatiVeicolo>
        //
        DatiVeicoliType v_type = body.getDatiVeicoli();
        if(v_type != null)
        {
          i_fattura.setDataImmatricolazioneVeicolo(DateUtils.toDate(v_type.getData()));
          i_fattura.setTotalePercorso(v_type.getTotalePercorso());
        }

        // <DatiPagamento>
        //
        List<DatiPagamentoType> l_pag = body.getDatiPagamento();
        Iterator<DatiPagamentoType> i_pag = l_pag.iterator();
        i = 0;
        while(i_pag.hasNext())
        {
          i++;
          DatiPagamentoType p_type = i_pag.next();
          createAndSavePagamento(session, i_fattura, fdao, p_type);
          LogUtils.info(getClass(), "DatiPagamentoType " + i + " successfully read.");
        }

        // <Allegati>
        //
        List<AllegatiType> l_att = body.getAllegati();
        Iterator<AllegatiType> i_att = l_att.iterator();
        i = 0;
        while(i_att.hasNext())
        {
          i++;
          AllegatiType a_type = i_att.next();
          createAndSaveAllegato(session, i_fattura, a_type);
          LogUtils.info(getClass(), "AllegatiType " + i + " successfully read.");
        }

        session.update(i_fattura);

        // Unmarshalling: testing purpose
        //
        byte[] xml = null;
        try
        {
          ObjectFactory obf = new ObjectFactory();
          FatturaElettronicaType fake_fattura = obf.createFatturaElettronicaType();
          fake_fattura.setFatturaElettronicaHeader(header_fattura);
          fake_fattura.getFatturaElettronicaBody().add(body);
          fake_fattura.setVersione(fattura.getVersione());

          JAXBElement<FatturaElettronicaType> fake_document =
              obf.createFatturaElettronica(fake_fattura);
          XmlMarshaller<FatturaElettronicaType> fm = new XmlMarshaller<FatturaElettronicaType>();
          ByteArrayOutputStream bos = new ByteArrayOutputStream();

          fm.writeDocument(fake_document, bos);
          xml = bos.toByteArray();
        }
        catch(Exception e)
        {
          LogUtils.error(getClass(), "Can't build single invoice object.", e);
        }
        // Create allegato: testing purpose
        //
        if(xml != null)
        {
          AllegatoFatturaSogei af = new AllegatoFatturaSogei();
          af.setDatafile(xml);
          af.setFattura(i_fattura);
          session.save(af);
        }

      }
    }
    
    return true;
  }

  private void createAndSaveAllegato(Session session, FatturaSogei i_fattura, AllegatiType a_type)
  {
    AllegatoDocumentoSogei a_item = new AllegatoDocumentoSogei();
    a_item.setNomeAllegato(a_type.getNomeAttachment());
    a_item.setDescrizioneAllegato(a_type.getDescrizioneAttachment());
    a_item.setFormatoAllegato(a_type.getFormatoAttachment());
    a_item.setAlgoritmoCompressione(a_type.getAlgoritmoCompressione());

    ContenutoAllegatoDocumentoSogei contenuto = new ContenutoAllegatoDocumentoSogei();
    contenuto.setDatafile(a_type.getAttachment());
    session.save(contenuto);

    a_item.setContenuto(contenuto);
    a_item.setFattura(i_fattura);

    session.save(a_item);
  }

  private void createAndSavePagamento(Session session, FatturaSogei i_fattura,
      FatturaSogeiDAO fdao, DatiPagamentoType p_type)
  {
    CondizioniPagamentoType cp_type = p_type.getCondizioniPagamento();
    TipoCondizioniPagamentoSogei tipoPagamento =
        (TipoCondizioniPagamentoSogei)fdao.getItemByDescrizione("TipoCondizioniPagamentoSogei",
            "label", cp_type.value());

    if(tipoPagamento == null)
      throw new FacadeException("Is not possible to decode CondizioniPagamentoType element "
          + cp_type.value());

    List<DettaglioPagamentoType> dp_list = p_type.getDettaglioPagamento();
    Iterator<DettaglioPagamentoType> dp_iter = dp_list.iterator();
    int j = 0;
    while(dp_iter.hasNext())
    {
      j++;

      DettaglioPagamentoType p_item = dp_iter.next();

      CondizionePagamentoSogei pagamento = new CondizionePagamentoSogei();
      pagamento.setTipoCondizionePagamento(tipoPagamento);

      ModalitaPagamentoType md_type = p_item.getModalitaPagamento();
      TipoModalitaPagamentoSogei modalitaPagamento =
          (TipoModalitaPagamentoSogei)fdao.getItemByDescrizione("TipoModalitaPagamentoSogei",
              "label", md_type.value());

      if(modalitaPagamento == null)
        throw new FacadeException("Is not possible to decode ModalitaPagamentoType element "
            + md_type.value());

      pagamento.setTipoModalitaPagamento(modalitaPagamento);

      pagamento.setBeneficiario(p_item.getBeneficiario());
      pagamento.setDataRiferimentoTerminiPagamento(DateUtils.toDate(p_item
          .getDataRiferimentoTerminiPagamento()));
      pagamento.setNumeroGiorniPagamento(p_item.getGiorniTerminiPagamento());
      pagamento
          .setDataScadenzaTerminiPagamento(DateUtils.toDate(p_item.getDataScadenzaPagamento()));
      pagamento.setImportoPagamento(p_item.getImportoPagamento());
      pagamento.setCodiceUfficioPostale(p_item.getCodUfficioPostale());
      pagamento.setCognomeQuietanzante(p_item.getCognomeQuietanzante());
      pagamento.setNomeQuietanzante(p_item.getNomeQuietanzante());
      pagamento.setCodicefiscaleQuietanzante(p_item.getCFQuietanzante());
      pagamento.setTitoloQuietanzante(p_item.getTitoloQuietanzante());
      pagamento.setIstitutoFinanziario(p_item.getIstitutoFinanziario());
      pagamento.setCodiceIban(p_item.getIBAN());
      pagamento.setCodiceAbi(p_item.getABI());
      pagamento.setCodiceCab(p_item.getCAB());
      pagamento.setCodiceBic(p_item.getBIC());
      pagamento.setImportoScontoPagamentoAnticipato(p_item.getScontoPagamentoAnticipato());
      pagamento.setDataLimiteScontoPagamentoAnticipato(DateUtils.toDate(p_item
          .getDataLimitePagamentoAnticipato()));

      pagamento.setImportoPenalePagamentoRitardato(p_item.getPenalitaPagamentiRitardati());
      pagamento.setDataDecorrenzaPenale(DateUtils.toDate(p_item.getDataDecorrenzaPenale()));
      pagamento.setCodicePagamento(p_item.getCodicePagamento());

      pagamento.setFattura(i_fattura);

      session.save(pagamento);

      LogUtils.info(getClass(), "CondizionePagamentoSogei " + j + " successfully saved.");
    }
  }

  private void createAndSaveRiepilogoFattura(Session session, FatturaSogeiDAO fdao,
      FatturaSogei i_fattura, DatiRiepilogoType line)
  {
    RiepilogoFatturaSogei r = new RiepilogoFatturaSogei();
    r.setImportoAliquota(line.getAliquotaIVA());
    r.setImportoArrotondamento(line.getArrotondamento());
    r.setImportoImponibile(line.getImponibileImporto());
    r.setImportoImposta(line.getImposta());
    r.setImportoSpeseAccessorie(line.getSpeseAccessorie());
    r.setRiferimentoNormativo(line.getRiferimentoNormativo());
    if(line.getEsigibilitaIVA() != null)
      r.setTipoEsigibilita(line.getEsigibilitaIVA().value());

    NaturaType t_natura = line.getNatura();
    if(t_natura != null)
    {
      TipoNaturaSogei natura =
          (TipoNaturaSogei)fdao.getItemByDescrizione("TipoNaturaSogei", "label", t_natura.value());

      if(natura == null)
        throw new FacadeException("Is not possible to decode NaturaType element "
            + t_natura.value());

      r.setTipoNatura(natura);
    }

    r.setFattura(i_fattura);
    session.save(r);
  }

  private void createAndSaveRiga(Session session, FatturaSogeiDAO fdao, FatturaSogei i_fattura,
      DettaglioLineeType line)
  {
    RigaFatturaSogei riga = new RigaFatturaSogei();
    riga.setFattura(i_fattura);

    riga.setNumeroProgressivo(line.getNumeroLinea());

    // <TipoCessionePrestazione>
    //
    TipoCessionePrestazioneType tipoCessione = line.getTipoCessionePrestazione();
    if(tipoCessione != null)
    {
      TipoPrestazioneSogei tipoPrestazione =
          (TipoPrestazioneSogei)fdao.getItemByDescrizione("TipoPrestazioneSogei", "label",
              tipoCessione.value());

      if(tipoPrestazione == null)
        throw new FacadeException("Is not possible to decode TipoCessionePrestazioneType element "
            + tipoCessione.value());

      riga.setTipoPrestazione(tipoPrestazione);
    }

    riga.setDescrizione(line.getDescrizione());
    riga.setQuantita(line.getQuantita());
    riga.setUnitaMisura(line.getUnitaMisura());
    riga.setDataInizioPeriodo(DateUtils.toDate(line.getDataInizioPeriodo()));
    riga.setDataFinePeriodo(DateUtils.toDate(line.getDataFinePeriodo()));
    riga.setImportoUnitario(line.getPrezzoUnitario());
    riga.setImportoTotale(line.getPrezzoTotale());
    riga.setAliquotaIva(line.getAliquotaIVA());

    Boolean flagRitenuta = Boolean.FALSE;
    if(line.getRitenuta() != null && line.getRitenuta().value().equals("SI"))
      flagRitenuta = Boolean.TRUE;

    riga.setFlagRitenuta(flagRitenuta);

    NaturaType t_natura = line.getNatura();
    if(t_natura != null)
    {
      TipoNaturaSogei tipoNatura =
          (TipoNaturaSogei)fdao.getItemByDescrizione("TipoNaturaSogei", "label", t_natura.value());
      riga.setTipoNatura(tipoNatura);
    }
    riga.setRiferimentoNormativo(line.getRiferimentoAmministrazione());

    session.save(riga);

    // <CodiceArticolo>
    //
    List<CodiceArticoloType> l_codici = line.getCodiceArticolo();
    Iterator<CodiceArticoloType> i_codici = l_codici.iterator();
    while(i_codici.hasNext())
    {
      CodiceArticoloType t_codice = i_codici.next();
      CodificaArticoloSogei codifica = new CodificaArticoloSogei();
      codifica.setCodiceCodifica(t_codice.getCodiceTipo());
      codifica.setValoreCodifica(t_codice.getCodiceValore());
      codifica.setRiga(riga);
      session.save(codifica);
    }

    // <ScontoMaggiorazione>
    //
    List<ScontoMaggiorazioneType> l_sconti = line.getScontoMaggiorazione();
    Iterator<ScontoMaggiorazioneType> i_sconti = l_sconti.iterator();
    while(i_sconti.hasNext())
    {
      ScontoMaggiorazioneType sconto_type = i_sconti.next();
      ScontoSogei sconto = createScontoMaggiorazione(fdao, sconto_type);
      sconto.setRiga(riga);
      session.save(sconto);
    }

    // <AltriDatiGestionali>
    //
    List<AltriDatiGestionaliType> l_altri = line.getAltriDatiGestionali();
    Iterator<AltriDatiGestionaliType> i_altri = l_altri.iterator();
    while(i_altri.hasNext())
    {
      AltriDatiGestionaliType dato_type = i_altri.next();
      DatoGestionaleSogei dato = new DatoGestionaleSogei();
      dato.setCodiceTipoDato(dato_type.getTipoDato());
      dato.setRiferimentoNumerico(dato_type.getRiferimentoNumero());
      dato.setRiferimentoTestuale(dato_type.getRiferimentoTesto());
      dato.setRiferimentoTemporale(DateUtils.toDate(dato_type.getRiferimentoData()));
      dato.setRiga(riga);
      session.save(dato);
    }
  }

  private void createAndSaveTrasporto(Session session, Date now, FatturaSogei i_fattura,
      DatiTrasportoType tr_type)
  {
    if(tr_type != null)
    {
      TrasportoFatturaSogei trasporto = new TrasportoFatturaSogei();
      DatiAnagraficiVettoreType actype = tr_type.getDatiAnagraficiVettore();
      if(actype != null)
      {
        AnagraficaSogei atrasporto = new AnagraficaSogei();
        trasporto.setAnagrafica(atrasporto);

        atrasporto.setDataCreazione(now);
        atrasporto.setNazione(actype.getIdFiscaleIVA().getIdPaese());
        atrasporto.setCodiceIdentificativoFiscale(actype.getIdFiscaleIVA().getIdCodice());

        // <CodiceFiscale>
        //
        atrasporto.setCodiceFiscale(actype.getCodiceFiscale());

        // <Anagrafica>
        //
        AnagraficaType atype = actype.getAnagrafica();
        atrasporto.setDenominazione(atype.getDenominazione());
        atrasporto.setCognome(atype.getCognome());
        atrasporto.setNome(atype.getNome());
        atrasporto.setDescrizioneCodiceEori(atype.getCodEORI());
        atrasporto.setDescrizioneTitolare(atype.getTitolo());
        session.save(atrasporto);

        trasporto.setAnagrafica(atrasporto);
        trasporto.setNumeroLicenza(actype.getNumeroLicenzaGuida());
      }

      trasporto.setMezzoTrasporto(tr_type.getMezzoTrasporto());
      trasporto.setCausale(tr_type.getCausaleTrasporto());
      trasporto.setNumeroColli(tr_type.getNumeroColli());
      trasporto.setDescrizione(tr_type.getDescrizione());
      trasporto.setUnitaMisura(tr_type.getUnitaMisuraPeso());
      trasporto.setPesoLordo(tr_type.getPesoLordo());
      trasporto.setPesoNetto(tr_type.getPesoNetto());

      trasporto.setDataRitiro(DateUtils.toDate(tr_type.getDataOraRitiro()));
      trasporto.setDataTrasporto(DateUtils.toDate(tr_type.getDataInizioTrasporto()));
      trasporto.setDataConsegna(DateUtils.toDate(tr_type.getDataOraConsegna()));
      trasporto.setTipoResa(tr_type.getTipoResa());

      // <IndirizzoResa>
      //
      IndirizzoType itype = tr_type.getIndirizzoResa();
      if(itype != null)
      {
        IndirizzoSogei indirizzoResa = new IndirizzoSogei();
        indirizzoResa.setCap(itype.getCAP());
        indirizzoResa.setNumeroCivico(itype.getNumeroCivico());
        indirizzoResa.setIndirizzo(itype.getIndirizzo());
        indirizzoResa.setComune(itype.getComune());
        indirizzoResa.setProvincia(itype.getProvincia());
        indirizzoResa.setNazione(itype.getNazione());
        indirizzoResa.setDataCreazione(now);

        trasporto.setIndirizzoResa(indirizzoResa);
        session.save(indirizzoResa);
      }

      trasporto.setFattura(i_fattura);
      session.save(trasporto);
    }
  }

  private void createAndSaveRiferimentoDocumento(Session session, FatturaSogei i_fattura,
      TipoRiferimentoDocumentoSogei tipoDocumentoRif, DatiDDTType r_doc)
  {
    RiferimentoDocumentoSogei rif_doc = new RiferimentoDocumentoSogei();
    rif_doc.setTipoRiferimento(tipoDocumentoRif);
    rif_doc.setNumeroDocumento(r_doc.getNumeroDDT());
    rif_doc.setDataDocumento(DateUtils.toDate(r_doc.getDataDDT()));
    rif_doc.setFattura(i_fattura);

    session.save(rif_doc);

    List<Integer> riferimenti_linea = r_doc.getRiferimentoNumeroLinea();
    for(Integer rif : riferimenti_linea)
    {
      RiferimentoLineaDocumentoSogei rif_linea = new RiferimentoLineaDocumentoSogei();
      rif_linea.setRiferimentoLineaDocumento(rif);
      rif_linea.setRiferimentoDocumento(rif_doc);
      session.save(rif_linea);
    }
  }

  private void createAndSaveRiferimentoDocumento(Session session, FatturaSogei i_fattura,
      TipoRiferimentoDocumentoSogei tipoDocumentoRif, DatiSALType r_doc)
  {
    RiferimentoDocumentoSogei rif_doc = new RiferimentoDocumentoSogei();
    rif_doc.setTipoRiferimento(tipoDocumentoRif);
    rif_doc.setRiferimentoFase(r_doc.getRiferimentoFase());
    rif_doc.setFattura(i_fattura);

    session.save(rif_doc);
  }

  private void createAndSaveRiferimentoDocumento(Session session, FatturaSogei i_fattura,
      TipoRiferimentoDocumentoSogei tipoDocumentoRif, DatiDocumentiCorrelatiType r_doc)
  {
    RiferimentoDocumentoSogei rif_doc = new RiferimentoDocumentoSogei();
    rif_doc.setTipoRiferimento(tipoDocumentoRif);
    rif_doc.setNumeroDocumento(r_doc.getIdDocumento());
    rif_doc.setDataDocumento(DateUtils.toDate(r_doc.getData()));
    rif_doc.setNumeroLineaDocumento(r_doc.getNumItem());
    rif_doc.setCodiceCommessaConvenzione(r_doc.getCodiceCommessaConvenzione());
    rif_doc.setNumeroCig(r_doc.getCodiceCIG());
    rif_doc.setNumeroCup(r_doc.getCodiceCUP());
    rif_doc.setFattura(i_fattura);

    session.save(rif_doc);

    List<Integer> riferimenti_linea = r_doc.getRiferimentoNumeroLinea();
    for(Integer rif : riferimenti_linea)
    {
      RiferimentoLineaDocumentoSogei rif_linea = new RiferimentoLineaDocumentoSogei();
      rif_linea.setRiferimentoLineaDocumento(rif);
      rif_linea.setRiferimentoDocumento(rif_doc);
      session.save(rif_linea);
    }
  }

  private ScontoSogei createScontoMaggiorazione(FatturaSogeiDAO fdao,
      ScontoMaggiorazioneType sc_type)
  {
    ScontoSogei sconto = new ScontoSogei();

    // <Tipo>
    //
    TipoScontoMaggiorazioneType t_type = sc_type.getTipo();
    TipoScontoSogei tipoSconto =
        (TipoScontoSogei)fdao.getItemByDescrizione("TipoScontoSogei", "label", t_type.value());

    if(tipoSconto == null)
      throw new FacadeException("Is not possible to decode TipoScontoMaggiorazioneType element "
          + t_type.value());

    sconto.setTipoSconto(tipoSconto);
    sconto.setImporto(sc_type.getImporto());
    sconto.setImportoAliquota(sc_type.getPercentuale());
    return sconto;
  }

  private CassaPrevidenzialeSogei createCassaPrevidenziale(FatturaSogeiDAO fdao,
      DatiCassaPrevidenzialeType cassatype)
  {
    CassaPrevidenzialeSogei c_prev = new CassaPrevidenzialeSogei();

    // <TipoCassa>
    //
    TipoCassaType type = cassatype.getTipoCassa();
    TipoCassaPrevidenzialeSogei tipoCassa =
        (TipoCassaPrevidenzialeSogei)fdao.getItemByDescrizione("TipoCassaPrevidenzialeSogei",
            "label", type.value());

    if(tipoCassa == null)
      throw new FacadeException("Is not possible to decode TipoCassaType element " + type.value());

    c_prev.setTipoCassa(tipoCassa);
    c_prev.setImportoAliquota(cassatype.getAliquotaIVA());
    c_prev.setImportoAliquotaCassa(cassatype.getAlCassa());
    c_prev.setImportoContributoCassa(cassatype.getImportoContributoCassa());
    c_prev.setImportoImponibileCassa(cassatype.getImponibileCassa());

    Boolean flagRitenuta = Boolean.FALSE;
    RitenutaType rrtype = cassatype.getRitenuta();
    if(rrtype != null && rrtype.value().equals("SI"))
      flagRitenuta = Boolean.TRUE;
    c_prev.setFlagRitenuta(flagRitenuta);

    // <Natura>
    //
    TipoNaturaSogei tipoNatura = null;
    NaturaType n_type = cassatype.getNatura();
    if(n_type != null)
    {
      tipoNatura =
          (TipoNaturaSogei)fdao.getItemByDescrizione("TipoNaturaSogei", "label", n_type.value());

      if(tipoNatura == null)
        throw new FacadeException("Is not possible to decode NaturaType element " + n_type.value());
    }

    c_prev.setTipoNatura(tipoNatura);
    c_prev.setRiferimentoAmministrativo(cassatype.getRiferimentoAmministrazione());
    return c_prev;
  }

  private RitenutaSogei createRitenuta(FatturaSogeiDAO fdao, FatturaSogei i_fattura,
      DatiRitenutaType rtype)
  {
    RitenutaSogei ritenuta = new RitenutaSogei();

    // <TipoRitenuta>
    //
    TipoRitenutaSogei tipoRitenuta =
        (TipoRitenutaSogei)fdao.getItemByDescrizione("TipoRitenutaSogei", "label", rtype
            .getTipoRitenuta().value());

    if(tipoRitenuta == null)
      throw new FacadeException("Is not possible to decode TipoRitenuta element "
          + rtype.getTipoRitenuta().value());

    ritenuta.setTipoRitenuta(tipoRitenuta);
    ritenuta.setImportoAliquota(rtype.getAliquotaRitenuta());
    ritenuta.setImportoRitenuta(rtype.getImportoRitenuta());
    ritenuta.setCausale(rtype.getCausalePagamento().value());
    ritenuta.setFattura(i_fattura);
    return ritenuta;
  }

  private TrasmissioneSogei createTrasmissione(Session session, Date now,
      InvioFileSdiSogei flussoSogei, FatturaElettronicaHeaderType header_fattura)
  {
    DatiTrasmissioneType dt = header_fattura.getDatiTrasmissione();

    // Create Trasmissione.
    //
    TrasmissioneSogei trasmissione = new TrasmissioneSogei();
    trasmissione.setCodiceDestinatario(flussoSogei.getCodiceDestinatario());
    trasmissione.setInvio(flussoSogei);

    // <IdTrasmittente>
    //
    IdFiscaleType idTrasmittente = dt.getIdTrasmittente();
    trasmissione.setNazione(idTrasmittente.getIdPaese());
    trasmissione.setCodiceIdentificativoFiscale(idTrasmittente.getIdCodice());

    trasmissione.setProgressivoInvio(dt.getProgressivoInvio());
    trasmissione.setFormatoTrasmissione(dt.getFormatoTrasmissione().value());

    // <ContattiTrasmittente>
    //
    ContattiTrasmittenteType contatti = dt.getContattiTrasmittente();
    if(contatti != null)
    {
      ContattoSogei contatto = new ContattoSogei();
      contatto.setDataCreazione(now);
      contatto.setEmail(contatti.getEmail());
      contatto.setNumeroTelefono(contatti.getTelefono());
      session.save(contatto);
      trasmissione.setContattoTrasmittente(contatto);
    }

    // <SoggettoEmittente>
    //
    SoggettoEmittenteType se = header_fattura.getSoggettoEmittente();
    if(se != null)
      trasmissione.setSoggettoEmittente(se.value());

    session.save(trasmissione);
    return trasmissione;
  }

  private void createTerzoIntermediario(Session session, Date now, CedentePrestatoreSogei cedente,
      TerzoIntermediarioSoggettoEmittenteType stype)
  {
    DatiAnagraficiTerzoIntermediarioType acctype = stype.getDatiAnagrafici();

    AnagraficaSogei aterzointermediario = new AnagraficaSogei();
    aterzointermediario.setDataCreazione(now);
    if(acctype.getIdFiscaleIVA() != null)
    {
      aterzointermediario.setNazione(acctype.getIdFiscaleIVA().getIdPaese());
      aterzointermediario.setCodiceIdentificativoFiscale(acctype.getIdFiscaleIVA().getIdCodice());
    }

    // <CodiceFiscale>
    //
    aterzointermediario.setCodiceFiscale(acctype.getCodiceFiscale());

    // <Anagrafica>
    //
    AnagraficaType atype = acctype.getAnagrafica();
    aterzointermediario.setDenominazione(atype.getDenominazione());
    aterzointermediario.setCognome(atype.getCognome());
    aterzointermediario.setNome(atype.getNome());
    aterzointermediario.setDescrizioneCodiceEori(atype.getCodEORI());
    aterzointermediario.setDescrizioneTitolare(atype.getTitolo());
    session.save(aterzointermediario);
    cedente.setIntermediario(aterzointermediario);
  }

  private CedentePrestatoreSogei createCedentePrestatore(Session session, Date now,
      FatturaElettronicaHeaderType header_fattura, TrasmissioneSogei trasmissione,
      CedentePrestatoreType ctype)
  {
    FatturaSogeiDAO fdao = new FatturaSogeiDAO(session);

    CedentePrestatoreSogei cedente = new CedentePrestatoreSogei();
    cedente.setTrasmissione(trasmissione);

    DatiAnagraficiCedenteType actype = ctype.getDatiAnagrafici();

    AnagraficaSogei acedente = new AnagraficaSogei();
    cedente.setAnagrafica(acedente);

    acedente.setDataCreazione(now);
    acedente.setNazione(actype.getIdFiscaleIVA().getIdPaese());
    acedente.setCodiceIdentificativoFiscale(actype.getIdFiscaleIVA().getIdCodice());

    flussoSogei.setPrestatoreCedente(acedente.getCodiceIdentificativoFiscale());
    session.update(flussoSogei);

    // <CodiceFiscale>
    //
    acedente.setCodiceFiscale(actype.getCodiceFiscale());

    // <Anagrafica>
    //
    AnagraficaType atype = actype.getAnagrafica();
    acedente.setDenominazione(atype.getDenominazione());
    acedente.setCognome(atype.getCognome());
    acedente.setNome(atype.getNome());
    acedente.setDescrizioneCodiceEori(atype.getCodEORI());
    acedente.setDescrizioneTitolare(atype.getTitolo());
    session.save(acedente);

    cedente.setDescrizioneAlbo(actype.getAlboProfessionale());
    cedente.setProvinciaAlbo(actype.getProvinciaAlbo());
    cedente.setDescrizioneNumeroIscrizioneAlbo(actype.getNumeroIscrizioneAlbo());
    cedente.setDataIscrizioneAlbo(DateUtils.toDate(actype.getDataIscrizioneAlbo()));

    TipoRegimeFiscaleSogei tipoRegime =
        (TipoRegimeFiscaleSogei)fdao.getItemByDescrizione("TipoRegimeFiscaleSogei", "label", actype
            .getRegimeFiscale().value());
    cedente.setRegimeFiscale(tipoRegime);

    // <Sede>
    //
    IndirizzoSogei indirizzoSede = new IndirizzoSogei();
    IndirizzoType itype = ctype.getSede();
    if(itype != null)
    {
      indirizzoSede.setCap(itype.getCAP());
      indirizzoSede.setNumeroCivico(itype.getNumeroCivico());
      indirizzoSede.setIndirizzo(itype.getIndirizzo());
      indirizzoSede.setComune(itype.getComune());
      indirizzoSede.setProvincia(itype.getProvincia());
      indirizzoSede.setNazione(itype.getNazione());
      indirizzoSede.setDataCreazione(now);

      cedente.setIndirizzoSede(indirizzoSede);
      session.save(indirizzoSede);
    }

    // <StabileOrganizzazione>
    //
    IndirizzoSogei indirizzoStabile = new IndirizzoSogei();
    itype = ctype.getStabileOrganizzazione();
    if(itype != null)
    {
      indirizzoStabile.setCap(itype.getCAP());
      indirizzoStabile.setNumeroCivico(itype.getNumeroCivico());
      indirizzoStabile.setIndirizzo(itype.getIndirizzo());
      indirizzoStabile.setComune(itype.getComune());
      indirizzoStabile.setProvincia(itype.getProvincia());
      indirizzoStabile.setNazione(itype.getNazione());
      indirizzoStabile.setDataCreazione(now);

      cedente.setIndirizzoStabile(indirizzoStabile);
      session.save(indirizzoStabile);
    }

    // <IscrizioneRea>
    //
    IscrizioneReaSogei iscrizioneRea = new IscrizioneReaSogei();
    IscrizioneREAType irea = ctype.getIscrizioneREA();
    if(irea != null)
    {
      iscrizioneRea.setDataCreazione(now);
      if(irea.getSocioUnico() != null)
        iscrizioneRea.setDescrizioneCodiceSoci(irea.getSocioUnico().value());

      iscrizioneRea.setDescrizioneStatoLiquidazione(irea.getStatoLiquidazione().value());
      iscrizioneRea.setUfficio(irea.getUfficio());
      iscrizioneRea.setImportoCapitaleSociale(irea.getCapitaleSociale());
      iscrizioneRea.setNumeroRea(irea.getNumeroREA());

      session.save(iscrizioneRea);

      cedente.setIscrizioneRea(iscrizioneRea);
    }

    // <Contatti>
    //
    ContattiType cctType = ctype.getContatti();
    if(cctType != null)
    {
      ContattoSogei contatto = new ContattoSogei();
      contatto.setDataCreazione(now);
      contatto.setEmail(cctType.getEmail());
      contatto.setNumeroTelefono(cctType.getTelefono());
      contatto.setNumeroFax(cctType.getFax());

      session.save(contatto);
      cedente.setContatto(contatto);
    }

    // <RiferimentoAmministrazione>
    //
    cedente.setRiferimentoAmministrazione(ctype.getRiferimentoAmministrazione());

    // <RappresentanteFiscale>
    //
    RappresentanteFiscaleType rftype = header_fattura.getRappresentanteFiscale();
    if(rftype != null)
    {

      AnagraficaSogei rfanagrafica = new AnagraficaSogei();
      DatiAnagraficiRappresentanteType arftype = rftype.getDatiAnagrafici();

      rfanagrafica.setDataCreazione(now);
      rfanagrafica.setNazione(arftype.getIdFiscaleIVA().getIdPaese());
      rfanagrafica.setCodiceIdentificativoFiscale(arftype.getIdFiscaleIVA().getIdCodice());

      // <CodiceFiscale>
      //
      rfanagrafica.setCodiceFiscale(arftype.getCodiceFiscale());

      // <Anagrafica>
      //
      atype = arftype.getAnagrafica();
      rfanagrafica.setDenominazione(atype.getDenominazione());
      rfanagrafica.setCognome(atype.getCognome());
      rfanagrafica.setNome(atype.getNome());
      rfanagrafica.setDescrizioneCodiceEori(atype.getCodEORI());
      rfanagrafica.setDescrizioneTitolare(atype.getTitolo());

      session.save(rfanagrafica);
      cedente.setRappresentanteFiscale(rfanagrafica);
    }
    session.save(cedente);
    return cedente;
  }

  private CessionarioCommittenteSogei createCessionarioCommittente(Session session, Date now,
      TrasmissioneSogei trasmissione, CessionarioCommittenteType cctype)
  {
    AnagraficaType atype;
    IndirizzoType itype;
    CessionarioCommittenteSogei cessionario = new CessionarioCommittenteSogei();
    cessionario.setTrasmissione(trasmissione);

    DatiAnagraficiCessionarioType acctype = cctype.getDatiAnagrafici();

    AnagraficaSogei acessionario = new AnagraficaSogei();
    cessionario.setAnagrafica(acessionario);

    acessionario.setDataCreazione(now);

    // <CodiceFiscale>
    //
    acessionario.setCodiceFiscale(acctype.getCodiceFiscale());
    flussoSogei.setCessionarioCommittente(acessionario.getCodiceFiscale());

    if(acctype.getIdFiscaleIVA() != null)
    {
      acessionario.setNazione(acctype.getIdFiscaleIVA().getIdPaese());
      acessionario.setCodiceIdentificativoFiscale(acctype.getIdFiscaleIVA().getIdCodice());
      flussoSogei.setCessionarioCommittente(acessionario.getCodiceIdentificativoFiscale());
    }

    session.update(flussoSogei);

    // <Anagrafica>
    //
    atype = acctype.getAnagrafica();
    acessionario.setDenominazione(atype.getDenominazione());
    acessionario.setCognome(atype.getCognome());
    acessionario.setNome(atype.getNome());
    acessionario.setDescrizioneCodiceEori(atype.getCodEORI());
    acessionario.setDescrizioneTitolare(atype.getTitolo());
    session.save(acessionario);

    // <Sede>
    //
    IndirizzoSogei indirizzoSedeCessionario = new IndirizzoSogei();
    itype = cctype.getSede();
    if(itype != null)
    {
      indirizzoSedeCessionario.setCap(itype.getCAP());
      indirizzoSedeCessionario.setNumeroCivico(itype.getNumeroCivico());
      indirizzoSedeCessionario.setIndirizzo(itype.getIndirizzo());
      indirizzoSedeCessionario.setComune(itype.getComune());
      indirizzoSedeCessionario.setProvincia(itype.getProvincia());
      indirizzoSedeCessionario.setNazione(itype.getNazione());
      indirizzoSedeCessionario.setDataCreazione(now);

      cessionario.setIndirizzoSede(indirizzoSedeCessionario);
      session.save(indirizzoSedeCessionario);
    }
    session.save(cessionario);

    return cessionario;
  }

}
