br.gov.jfrj.siga.ex.bl.ExCompetenciaBL.java Source code

Java tutorial

Introduction

Here is the source code for br.gov.jfrj.siga.ex.bl.ExCompetenciaBL.java

Source

/*******************************************************************************
 * Copyright (c) 2006 - 2011 SJRJ.
 * 
 *     This file is part of SIGA.
 * 
 *     SIGA is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     SIGA is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with SIGA.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package br.gov.jfrj.siga.ex.bl;

import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Set;

import org.hibernate.LockMode;

import br.gov.jfrj.siga.cp.CpSituacaoConfiguracao;
import br.gov.jfrj.siga.cp.CpTipoConfiguracao;
import br.gov.jfrj.siga.cp.bl.CpCompetenciaBL;
import br.gov.jfrj.siga.dp.CpMarca;
import br.gov.jfrj.siga.dp.CpMarcador;
import br.gov.jfrj.siga.dp.CpOrgaoUsuario;
import br.gov.jfrj.siga.dp.DpLotacao;
import br.gov.jfrj.siga.dp.DpPessoa;
import br.gov.jfrj.siga.dp.DpResponsavel;
import br.gov.jfrj.siga.dp.dao.CpDao;
import br.gov.jfrj.siga.ex.ExClassificacao;
import br.gov.jfrj.siga.ex.ExConfiguracao;
import br.gov.jfrj.siga.ex.ExDocumento;
import br.gov.jfrj.siga.ex.ExFormaDocumento;
import br.gov.jfrj.siga.ex.ExMobil;
import br.gov.jfrj.siga.ex.ExModelo;
import br.gov.jfrj.siga.ex.ExMovimentacao;
import br.gov.jfrj.siga.ex.ExNivelAcesso;
import br.gov.jfrj.siga.ex.ExPapel;
import br.gov.jfrj.siga.ex.ExTipoDocumento;
import br.gov.jfrj.siga.ex.ExTipoFormaDoc;
import br.gov.jfrj.siga.ex.ExTipoMovimentacao;
import br.gov.jfrj.siga.ex.ExVia;
import br.gov.jfrj.siga.hibernate.ExDao;

public class ExCompetenciaBL extends CpCompetenciaBL {

    public ExConfiguracaoBL getConf() {
        return (ExConfiguracaoBL) super.getConfiguracaoBL();
    }

    /**
     * Retorna se  possvel acessar o documento ao qual pertence o mbil
     * passado por parmetro. Considera se o documento ainda no foi assinado
     * (sendo ento considerado aberto; estando j assinado, retorna verdadeiro)
     * e se <i>uma das</i> seguintes condies  satisfeita:
     * <ul>
     * <li>Usurio  da lotao cadastrante do documento</li>
     * <li>Usurio  subscritor do documento</li>
     * <li>Usurio  titular do documento</li>
     * <li><i>podeMovimentar()</i>  verdadeiro para o usurio / mbil</li>
     * <li>Usurio  um dos cossignatrios do documento</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAcessarAberto(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob)
            throws Exception {
        if (mob == null)
            return false;
        if (!mob.doc().isAssinado() && !mob.doc().getLotaCadastrante().equivale(lotaTitular)
                && !titular.equivale(mob.doc().getTitular()) && !podeMovimentar(titular, lotaTitular, mob)) {
            return false;
        }
        return true;
    }

    /**
     * * Retorna se  possvel acessar um documento ao qual pertence o mbil
     * passado por parmetro. Considera se o documento est cancelado (no
     * estando cancelado, retorna verdadeiro) e se <i>uma das</i> seguintes
     * condies  satisfeita:
     * <ul>
     * <li>Usurio  da lotao cadastrante do documento</li>
     * <li>Usurio  subscritor do documento</li>
     * <li>Usurio  titular do documento</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarCancelado(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        if (mob == null)
            return false;
        if (mob.doc().isCancelado() && !mob.doc().getLotaCadastrante().equivale(lotaTitular)
                && !titular.equivale(mob.doc().getSubscritor()) && !titular.equivale(mob.doc().getTitular()))
            return false;
        return true;

    }

    /**
     * * Retorna se  possvel acessar um documento ao qual pertence o mbil
     * passado por parmetro. Considera se o documento est sem efeito (no
     * estando sem efeito, retorna verdadeiro) e se <i>uma das</i> seguintes
     * condies  satisfeita:
     * <ul>
     * <li>Usurio  da lotao cadastrante do documento</li>
     * <li>Usurio  subscritor do documento</li>
     * <li>Usurio  titular do documento</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarSemEfeito(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        if (mob == null)
            return false;
        if (mob.doc().isSemEfeito() && !mob.doc().getLotaCadastrante().equivale(lotaTitular)
                && !titular.equivale(mob.doc().getSubscritor()) && !titular.equivale(mob.doc().getTitular()))
            return false;
        return true;

    }

    /**
     * Retorna se  possvel acessar o documento ao qual pertence o mbil
     * passado por parmetro, analisando <i>podeAcessarAberto()</i>,
     * <i>podeAcessarCancelado()</i> e <i>podeAcessarPorNivel()</i>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAcessarDocumentoAntigo(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) throws Exception {

        if (mob.doc().getOrgaoUsuario() != null && mob.doc().getOrgaoUsuario().getIdOrgaoUsu() != null) {
            if (podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_ACESSAR,
                    mob.doc().getOrgaoUsuario())) {
                return true;
            }
        }

        for (DpPessoa autorizado : mob.doc().getSubscritorECosignatarios()) {
            if (titular.equivale(autorizado))
                return true;
        }

        if (pessoaTemPerfilVinculado(mob.doc(), titular, lotaTitular)) {
            return true;
        }

        return /*
               * podeAcessarPublico(titular, lotaTitular, mob) &&
               */podeAcessarAberto(titular, lotaTitular, mob) && podeAcessarPorNivel(titular, lotaTitular, mob)
                && podeAcessarCancelado(titular, lotaTitular, mob)
                && podeAcessarSemEfeito(titular, lotaTitular, mob);
    }

    public boolean podeAcessarDocumento(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        ExDocumento doc = mob.doc();
        if (doc.getDnmAcesso() == null) {
            Ex.getInstance().getBL().atualizarDnmAcesso(doc);
        }
        AcessoConsulta ac = new AcessoConsulta(titular == null ? 0L : titular.getIdInicial(),
                lotaTitular == null ? 0 : lotaTitular.getIdInicial(),
                titular == null ? 0L : titular.getOrgaoUsuario().getId(),
                lotaTitular == null ? 0L : lotaTitular.getOrgaoUsuario().getId());
        return ac.podeAcessar(doc.getDnmAcesso());
    }

    /**
     * Retorna se  possvel acessar documento reservado, considerando se o
     * documento  reservado entre lotaes (se no for, retorna verdadeiro) e
     * se <i>podeAcessarReservadoEntreLotacoes().</i>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarReservado(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        switch (mob.doc().getExNivelAcesso().getGrauNivelAcesso().intValue()) {
        case (int) ExNivelAcesso.NIVEL_RESERVADO_ENTRE_LOTACOES:
            return podeAcessarReservadoEntreLotacoes(titular, lotaTitular, mob);
        default:
            return true;
        }
    }

    /**
     * Retorna se  possvel acessar o documento a que pertence o mbil passado
     * por parmetro, considerando seu nvel de acesso, e tambm o seguinte:
     * <ul>
     * <li>Se h documento pai e usurio pode acess-lo <i>por nvel</i>,
     * retorna verdadeiro</li>
     * <li>Se o usurio tem perfil vinculado ao documento, retorna verdadeiro</li>
     * <li>Nos demais casos, retorna conforme a resposta de
     * <i>podeAcessarPorNivelN()</i>, dependendo do grau do nvel de acesso do
     * documento</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception 
     */
    public boolean podeAcessarPorNivel(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob)
            throws Exception {
        if (mob == null)
            return false;

        if (mob.doc().getExNivelAcesso() == null) {
            return true;
        }

        if (mob.getExMobilPai() != null && podeAcessarPorNivel(titular, lotaTitular, mob.getExMobilPai()))
            return true;

        if (pessoaTemPerfilVinculado(mob.doc(), titular, lotaTitular)) {
            return true;
        }

        // Verifica se o titular  subscritor de algum despacho do documento
        if (mob.doc().getSubscritorDespacho().contains(titular))
            return true;

        // Verifica se o titular  subscritor ou cosignatrio do documento
        if (mob.doc().getSubscritorECosignatarios().contains(titular))
            return true;

        // for (int k = numViaIniBusca; k <= numViaFimBusca; k++)
        switch (mob.doc().getExNivelAcesso().getGrauNivelAcesso().intValue()) {
        case (int) ExNivelAcesso.NIVEL_ACESSO_ENTRE_ORGAOS:
            return podeAcessarNivel20(titular, lotaTitular, mob);
        case (int) ExNivelAcesso.NIVEL_ACESSO_PUBLICO:
            return podeAcessarPublico(titular, lotaTitular, mob);
        case (int) ExNivelAcesso.NIVEL_ACESSO_PESSOA_SUB:
            return podeAcessarNivel30(titular, lotaTitular, mob);
        case (int) ExNivelAcesso.NIVEL_ACESSO_SUB_PESSOA:
            return podeAcessarNivel40(titular, lotaTitular, mob);
        case (int) ExNivelAcesso.NIVEL_ACESSO_ENTRE_LOTACOES:
            return podeAcessarNivel60(titular, lotaTitular, mob);
        case (int) ExNivelAcesso.NIVEL_ACESSO_PESSOAL:
            return podeAcessarNivel100(titular, lotaTitular, mob);
        default:
            return true;
        }
    }

    /**
     * Retorna se  possvel acessar documento pblico. Sempre verdade.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarPublico(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        return true;
    }

    /**
     * Retorna se  possvel acessar o documento que contm o mbil passado por
     * parmetro. No  checado o nvel de acesso. Presume-se que o documento
     * seja limitado ao rgo. <i>Uma das</i> seguintes condies tem de ser
     * satisfeita:
     * <ul>
     * <li>rgo a que pertence a lotao passada por parmetro tem de ser o
     * rgo da lotao cadastrante do documento</li>
     * <li>Usurio  o subscritor do documento, no importando de que rgo seja
     * </li>
     * <li>Usurio  o titular do documento, no importando de que rgo seja</li>
     * <li>Usurio  o destinatario do documento ou da lotao deste, no
     * importando de que rgo seja</li>
     * <li><i>jaEsteveNoOrgao()</i>  verdadeiro para esses parmetros</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarNivel20(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if ((lotaTitular.getOrgaoUsuario().equivale(mob.doc().getLotaCadastrante().getOrgaoUsuario()))
                || (mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular))
                || (mob.doc().getTitular() != null && mob.doc().getTitular().equivale(titular))
                || (mob.doc().getDestinatario() != null && mob.doc().getDestinatario().equivale(titular))
                || (mob.doc().getLotaDestinatario() != null
                        && mob.doc().getLotaDestinatario().equivale(lotaTitular))
                || (jaEsteveNoOrgao(mob.doc(), titular, lotaTitular)))
            return true;
        else
            return false;
    }

    /**
     * Retorna se um documento j esteve num rgo (TRF, JFRJ, JFES),
     * verificando se alguma movimentao de algum mbil do documento teve
     * lotao atendente pertencente ao rgo onde est a lotao passada por
     * parmetro ou se, tendo sido definida uma pessoa atendente para a
     * movimentao, o rgo a que a pessoa <i>pertencia*</i>  o rgo da
     * pessoa passada por parmetro. <br/>
     * * Rever o restante deste documento, se os verbos esto no tempo correto
     * 
     * @param doc
     * @param titular
     * @param lotaTitular
     * @return
     */
    public static boolean jaEsteveNoOrgao(ExDocumento doc, DpPessoa titular, DpLotacao lotaTitular) {
        // TODO Auto-generated method stub
        for (ExMobil m : doc.getExMobilSet()) {
            for (ExMovimentacao mov : m.getExMovimentacaoSet()) {
                if ((mov.getLotaResp() != null
                        && mov.getLotaResp().getOrgaoUsuario().equivale(lotaTitular.getOrgaoUsuario()))
                        || (mov.getResp() != null
                                && mov.getResp().getOrgaoUsuario().equivale(titular.getOrgaoUsuario())))
                    return true;
            }
        }
        return false;
    }

    /**
     * Retorna se  possvel acessar o documento que contm o mbil passado por
     * parmetro. No  checado o nvel de acesso. Presume-se que o documento
     * seja limitado de pessoa para subsecretaria. <i>Uma das</i> seguintes
     * condies tem de ser satisfeita:
     * <ul>
     * <li>Usurio  o prprio cadastrante do documento</li>
     * <li>Usurio  o subscritor do documento</li>
     * <li>Usurio  o titular do documento</li>
     * <li>Usurio pertence  subsecretaria da lotao destinatria do documento
     * </li>
     * <li><i>pessoaJaTeveAcesso()</i>  verdadeiro para esses parmetros</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarNivel30(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        DpLotacao subLotaTitular = getSubsecretaria(lotaTitular);
        DpLotacao subLotaDest = getSubsecretaria(mob.doc().getLotaDestinatario());

        if (titular.equivale(mob.doc().getCadastrante())
                || (mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular))
                || (mob.doc().getTitular() != null && mob.doc().getTitular().equivale(titular))
                || (subLotaTitular.equivale(subLotaDest)) || pessoaJaTeveAcesso(mob.doc(), titular, lotaTitular))
            return true;
        else
            return false;
    }

    /**
     * Retorna se  possvel acessar o documento que contm o mbil passado por
     * parmetro. No  checado o nvel de acesso. Presume-se que o documento
     * seja limitado de subsecretaria para pessoa. <i>Uma das</i> seguintes
     * condies tem de ser satisfeita:
     * <ul>
     * <li>Usurio pertence  subsecretaria da lotao cadastrante do documento</li>
     * <li>Usurio  o destinatrio do documento</li>
     * <li>Usurio  o subscritor do documento</li>
     * <li>Usurio  o titular do documento</li>
     * <li>Usurio  da lotao destinatria do documento, se no tiver sido
     * definida pessoa destinatria</li>
     * <li><i>pessoaJaTeveAcesso()</i>  verdadeiro para esses parmetros</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarNivel40(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        DpLotacao subLotaTitular = getSubsecretaria(lotaTitular);
        DpLotacao subLotaDoc = getSubsecretaria(mob.doc().getLotaCadastrante());

        if ((subLotaTitular.equivale(subLotaDoc))
                || (mob.doc().getDestinatario() != null && mob.doc().getDestinatario().equivale(titular))
                || (mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular))
                || (mob.doc().getTitular() != null && mob.doc().getTitular().equivale(titular))
                || (mob.doc().getDestinatario() == null && mob.doc().getLotaDestinatario() != null
                        && mob.doc().getLotaDestinatario().equivale(lotaTitular))
                || pessoaJaTeveAcesso(mob.doc(), titular, lotaTitular))
            return true;
        else
            return false;

    }

    /**
     * Retorna se  possvel acessar documento reservado entre lotaes, com
     * base em <i>podeAcessarPorNivel20()</i> e <i>podeAcessarPorNivel60().</i>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarReservadoEntreLotacoes(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {
        return podeAcessarNivel20(titular, lotaTitular, mob) && podeAcessarNivel60(titular, lotaTitular, mob);
    }

    /**
     * Retorna se  possvel acessar o documento que contm o mbil passado por
     * parmetro. No  checado o nvel de acesso. Presume-se que o documento
     * seja limitado entre lotaes. <i>Uma das</i> seguintes condies tem de
     * ser satisfeita:
     * <ul>
     * <li>Usurio  da lotao cadastrante do documento</li>
     * <li>Usurio  o subscritor do documento</li>
     * <li>Usurio  o titular do documento</li>
     * <li>Usurio pertence  subsecretaria da lotao destinatria do documento
     * </li>
     * <li>Usurio  da lotao destinatria do documento</li>
     * <li><i>jaPassouPor()</i>  verdadeiro para esses parmetros</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarNivel60(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if ((lotaTitular.equivale(mob.doc().getLotaCadastrante()))
                || (mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular))
                || (mob.doc().getTitular() != null && mob.doc().getTitular().equivale(titular))
                || (mob.doc().getLotaDestinatario() != null
                        && mob.doc().getLotaDestinatario().equivale(lotaTitular))
                || (jaPassouPor(mob.doc(), lotaTitular)))
            return true;
        else
            return false;
    }

    /**
     * Retorna se  possvel acessar o documento que contm o mbil passado por
     * parmetro. No  checado o nvel de acesso. Presume-se que o documento
     * seja limitado entre pessoas. <i>Uma das</i> seguintes condies tem de
     * ser satisfeita:
     * <ul>
     * <li>Usurio  o prprio cadastrante do documento</li>
     * <li>Usurio  o subscritor do documento</li>
     * <li>Usurio  o titular do documento</li>
     * <li>Usurio  o prprio destinatrio do documento</li>
     * <li>Usurio  da lotao destinatria do documento</li>
     * <li><i>pessoaJaTeveAcesso()</i>  verdadeiro para esses parmetros</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeAcessarNivel100(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (titular.equivale(mob.doc().getCadastrante())
                || (mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular))
                || (mob.doc().getTitular() != null && mob.doc().getTitular().equivale(titular))
                || (mob.doc().getDestinatario() != null && mob.doc().getDestinatario().equivale(titular))
                || pessoaJaTeveAcesso(mob.doc(), titular, lotaTitular))
            return true;
        else
            return false;
    }

    /**
     * Retorna se  possvel anexar arquivo a um mbil. As condies so as
     * seguintes:
     * <ul>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>Mbil no pode estar juntado</li>
      * <li>Mbil no pode estar arquivado</li>
     * <li>Volume no pode estar encerrado</li>
     * <li>Mbil tem de estar finalizado</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o mbil / usurio</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAnexarArquivo(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (mob.doc().isFinalizado())
            return !mob.isEmTransito() && !mob.isGeral() && !mob.isJuntado() && !mob.isArquivado()
                    && !mob.isSobrestado() && !mob.isVolumeEncerrado() && podeMovimentar(titular, lotaTitular, mob)
                    && !mob.doc().isSemEfeito()
                    && podePorConfiguracao(titular, lotaTitular, ExTipoMovimentacao.TIPO_MOVIMENTACAO_ANEXACAO,
                            CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR, null);

        if (mob.isGeral() && mob.doc().isProcesso())
            return false;

        return mob.isGeral();
    }

    /**
     * Retorna um configurao existente para a combinao dos dados passados
     * como parmetros, caso exista.
     * 
     * @param titularIniciador
     * @param lotaTitularIniciador
     * @param tipoConfig
     * @param procedimento
     * @param raia
     * @param tarefa
     * @return
     * @throws Exception
     */
    private ExConfiguracao preencherFiltroEBuscarConfiguracao(DpPessoa titularIniciador,
            DpLotacao lotaTitularIniciador, long tipoConfig, long tipoMov, ExTipoDocumento exTipoDocumento,
            ExTipoFormaDoc exTipoFormaDoc, ExFormaDocumento exFormaDocumento, ExModelo exModelo,
            ExClassificacao exClassificacao, ExVia exVia, ExNivelAcesso exNivelAcesso, ExPapel exPapel,
            CpOrgaoUsuario orgaoObjeto) {
        ExConfiguracao cfgFiltro = new ExConfiguracao();

        cfgFiltro.setCargo(titularIniciador.getCargo());
        cfgFiltro.setOrgaoUsuario(lotaTitularIniciador.getOrgaoUsuario());
        cfgFiltro.setFuncaoConfianca(titularIniciador.getFuncaoConfianca());
        cfgFiltro.setLotacao(lotaTitularIniciador);
        cfgFiltro.setDpPessoa(titularIniciador);
        cfgFiltro.setCpTipoConfiguracao(CpDao.getInstance().consultar(tipoConfig, CpTipoConfiguracao.class, false));
        if (cfgFiltro.getCpTipoConfiguracao() == null)
            throw new RuntimeException("No  permitido buscar uma configurao sem definir seu tipo.");
        if (tipoMov != 0)
            cfgFiltro
                    .setExTipoMovimentacao(CpDao.getInstance().consultar(tipoMov, ExTipoMovimentacao.class, false));
        cfgFiltro.setExTipoDocumento(exTipoDocumento);
        cfgFiltro.setExTipoFormaDoc(exTipoFormaDoc);
        cfgFiltro.setExFormaDocumento(exFormaDocumento);
        cfgFiltro.setExModelo(exModelo);
        cfgFiltro.setExClassificacao(exClassificacao);
        cfgFiltro.setExVia(exVia);
        cfgFiltro.setExNivelAcesso(exNivelAcesso);
        cfgFiltro.setExPapel(exPapel);
        cfgFiltro.setOrgaoObjeto(orgaoObjeto);

        ExConfiguracao cfg = (ExConfiguracao) getConfiguracaoBL().buscaConfiguracao(cfgFiltro, new int[] { 0 },
                null);

        // Essa linha  necessria porque quando recuperamos um objeto da classe
        // WfConfiguracao do TreeMap esttico que os armazena, este objeto est
        // detached, ou seja, no est conectado com a seo atual do hibernate.
        // Portanto, quando vamos acessar alguma propriedade dele que seja do
        // tipo LazyRead, obtemos um erro. O mtodo lock, attacha ele novamente
        // na seo atual.
        if (cfg != null)
            ExDao.getInstance().getSessao().lock(cfg, LockMode.NONE);

        return cfg;
    }

    /**
     * Verifica se uma pessoa ou lotao tem permisso em uma configurao
     * passada como parmetro.
     * 
     * @param titular
     * @param lotaTitular
     * @param tipoConfig
     * @param tipoMovimentacao
     *            - Configurao que ter a permisso verificada.
     * @return
     * @throws Exception
     */
    private Boolean podePorConfiguracao(DpPessoa titular, DpLotacao lotaTitular, long tipoMov, long tipoConfig,
            CpOrgaoUsuario orgaoObjeto) {
        CpSituacaoConfiguracao situacao;
        ExConfiguracao cfg = preencherFiltroEBuscarConfiguracao(titular, lotaTitular, tipoConfig, tipoMov, null,
                null, null, null, null, null, null, null, orgaoObjeto);

        if (cfg != null) {
            situacao = cfg.getCpSituacaoConfiguracao();
        } else {
            situacao = CpDao.getInstance().consultar(tipoConfig, CpTipoConfiguracao.class, false)
                    .getSituacaoDefault();

        }

        if (situacao != null && situacao.getIdSitConfiguracao() == CpSituacaoConfiguracao.SITUACAO_PODE)
            return true;
        return false;
    }

    private Boolean podePorConfiguracao(DpPessoa titular, DpLotacao lotaTitular, long tipoConfig) {
        return podePorConfiguracao(titular, lotaTitular, 0L, tipoConfig, null);
    }

    private Boolean podePorConfiguracao(DpPessoa titular, DpLotacao lotaTitular, long tipoConfig,
            CpOrgaoUsuario orgaoObjeto) throws Exception {
        return podePorConfiguracao(titular, lotaTitular, 0L, tipoConfig, orgaoObjeto);
    }

    /**
     * Retorna se  possvel fazer arquivamento corrente de um mbil, segundo as regras a
        
     * seguir:
     * <ul>
     * <li>Documento tem de estar assinado</li>
     * <li>Mbil tem de ser via ou geral de processo (caso em que se condidera a
     * situao do ltimo volume)</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>Mbil no pode estar juntado</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeArquivarCorrente(final DpPessoa titular, final DpLotacao lotaTitular, ExMobil mob) {

        if (!(mob.isVia() || mob.isGeralDeProcesso()) || mob.doc().isSemEfeito())
            return false;

        if (mob.isGeralDeProcesso() && mob.doc().isFinalizado())
            mob = mob.doc().getUltimoVolume();

        if (mob.doc().isEletronico() && (mob.temAnexosNaoAssinados() || mob.temDespachosNaoAssinados()))
            return false;

        return mob != null && mob.doc().isAssinado() && podeMovimentar(titular, lotaTitular, mob)
                && !mob.isArquivado() && !mob.isSobrestado() && !mob.isJuntado() && !mob.isEmTransito()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_ARQUIVAMENTO_CORRENTE,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel fazer sobrestar um mbil, segundo as
     * regras a seguir:
        
        
     * <ul>
     * <li>Documento tem de estar assinado</li>
     * <li>Mbil tem de ser via ou volume (no pode ser geral)</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>Mbil no pode estar juntado</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeSobrestar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!mob.doc().isAssinado())
            return false;

        final ExMovimentacao ultMovNaoCancelada = mob.getUltimaMovimentacaoNaoCancelada();

        return mob.doc().isFinalizado() && (mob.isVia() || mob.isVolume())
                && podeMovimentar(titular, lotaTitular, mob) && !mob.isArquivado() && !mob.isSobrestado()
                && !mob.isJuntado() && !mob.isEmTransito() && !mob.doc().isSemEfeito()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_SOBRESTAR, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel tornar um documento sem efeito, segundo as
     * regras a seguir:
        
        
     * <ul>
     * <li>Documento tem de estar assinado</li>
     * <li>Mbil tem de ser via ou volume (no pode ser geral)</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Mbil no pode estar juntado</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeTornarDocumentoSemEfeito(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {
        final ExMovimentacao ultMovNaoCancelada = mob.getUltimaMovimentacaoNaoCancelada();

        if (mob.doc().isSemEfeito())
            return false;

        if (!mob.doc().isEletronico() || !mob.doc().isAssinado())
            return false;

        if (mob.doc().getSubscritor() == null || !mob.doc().getSubscritor().equivale(titular))
            return false;

        //Verifica se o documento est com pedido de publicao no DJE ou BIE.
        if (mob.doc().isPublicacaoSolicitada() || mob.doc().isPublicacaoAgendada()
                || mob.doc().isPublicacaoBoletimSolicitada() || mob.doc().isBoletimPublicado()
                || mob.doc().isDJEPublicado())
            return false;

        //Verifica se o subscritor pode movimentar todos os mobils
        //E Tambm se algum documento diferente est apensado ou juntado a este documento

        for (ExMobil m : mob.doc().getExMobilSet()) {
            if (!m.isGeral()) {
                if (!podeMovimentar(titular, lotaTitular, m))
                    return false;

                if (m.isJuntado() || m.isApensado())
                    return false;

                if (m.temApensos())
                    return false;

                if (m.temDocumentosJuntados())
                    return false;
            }
        }

        return getConf().podePorConfiguracao(titular, lotaTitular,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_TORNAR_SEM_EFEITO, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel criar subprocesso, segundo as regras abaixo:
     * <ul>
     * <li>Documento tem de ser processo</li>
     * <li>Mbil no pode ser geral</li>
        
     * <li>Documento no pode ter um mbil pai</li>
     * <li>Documento no pode estar cancelado</li>
     * <li>Usurio tem de ter permisso para acessar o documento que contm o
     * mbil. <b> mesmo necessrio verificar isso?</b></li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao: Criar
     * Documento Filho</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeCriarSubprocesso(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        if (!mob.doc().isProcesso())
            return false;
        if (!mob.isGeral())
            return false;

        if (mob.doc().getExMobilPai() != null)
            return false;

        return !mob.doc().isCancelado() && !mob.doc().isSemEfeito() && !mob.isArquivado() && mob.doc().isAssinado()
                && podeAcessarDocumento(titular, lotaTitular, mob)
                && podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_CRIAR_DOC_FILHO);
    }

    /**
     * Retorna se  possvel criar um documento filho do mbil passado como
     * parmetro, de acordo com as regras:
     * <ul>
     * <li>Documento no pode estar cancelado</li>
     * <li>Volume no pode estar encerrado, pelo fato de documento filho
     * representar contedo agregado ao mbil</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeCriarDocFilho(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        return !mob.doc().isCancelado() && !mob.doc().isSemEfeito() && !mob.isVolumeEncerrado()
                && !mob.isArquivado() && podeMovimentar(titular, lotaTitular, mob)
                && podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_CRIAR_DOC_FILHO);
    }

    /**
     * Retorna se  possvel fazer simulao, com base na configurao de tipo
     * "Pode Simular Usurio"
     * 
     * @param titular
     * @param lotaTitular
     * @return
     * @throws Exception
     */
    public boolean podeSimularUsuario(final DpPessoa titular, final DpLotacao lotaTitular) throws Exception {
        return getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_SIMULAR_USUARIO);
    }

    /**
     * Retorna se  possvel mostrar o link para arquivamento intermedirio de
     * um mbil, de acordo com as condies a seguir:
     * <ul>
     * <li>Mbil tem de ser via ou geral de processo</li>
        
     * <li>Mbil tem de estar assinado</li>
     * <li>Mbil tem de estar arquivado corrente</li>
     * <li>PCTT tem de prever, para o mbil, tempo de permanncia no arquivo
     * intermedirio</li>
     * <li>Mbil no pode estar arquivado intermedirio nem permanente</li>
     * <li>Mbil no pode estar em edital de eliminao</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */

    public boolean podeBotaoArquivarIntermediario(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        if (!(mob.isVia() || mob.isGeralDeProcesso()) || mob.doc().isSemEfeito() || mob.isEliminado())
            return false;

        return mob != null && mob.doc().isAssinado() && mob.isArquivadoCorrente()
                && mob.temTemporalidadeIntermediario() && !mob.isArquivadoIntermediario()
                && !mob.isArquivadoPermanente() && !mob.isEmEditalEliminacao()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_ARQUIVAMENTO_INTERMEDIARIO,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel fazer o arquivamento intermedirio do mbil, ou
     * seja, se  possvel mostrar o link para movimentao e se, alm disso, o
     * mbil encontra-se na lotao titular ou  digital.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeArquivarIntermediario(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {
        return podeBotaoArquivarIntermediario(titular, lotaTitular, mob)
                && (lotaTitular.equivale(mob.getUltimaMovimentacaoNaoCancelada().getLotaResp())
                        || mob.doc().isEletronico());
    }

    /**
     * Retorna se  possvel exibir o link para arquivamento permanente de um
     * mbil, de acordo com as condies a seguir:
     * <ul>
     * <li>Mbil tem de ser via ou geral de processo</li>
     * <li>Mbil no pode estar sem efeito</li>
     * <li>Mbil tem de estar assinado</li>
     * <li>Mbil tem de estar arquivado corrente ou intermedirio; no pode ter
     * sido arquivado permanentemente</li>
     * <li>Tem de estar prevista guarda permanente, seja por PCTT ou por
     * indicao</li>
     * <li>Mbil no pode estar em edital de eliminao</li>
     * <li>Mbil no pode ter sido eliminado</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeBotaoArquivarPermanente(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        if (!(mob.isVia() || mob.isGeralDeProcesso()) || mob.doc().isSemEfeito() || mob.isEliminado())
            return false;

        return mob != null && mob.doc().isAssinado()
                && ((!mob.temTemporalidadeIntermediario() && mob.isArquivadoCorrente())
                        || mob.isArquivadoIntermediario())
                && !mob.isArquivadoPermanente() && mob.isDestinacaoGuardaPermanente() && !mob.isEmEditalEliminacao()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_ARQUIVAMENTO_PERMANENTE,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel fazer o arquivamento permanente do mbil, ou seja,
     * se  possvel mostrar o link para movimentao e se, alm disso, o mbil
     * encontra-se na lotao titular ou  digital.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeArquivarPermanente(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        return podeBotaoArquivarPermanente(titular, lotaTitular, mob)
                && (lotaTitular.equivale(mob.getUltimaMovimentacaoNaoCancelada().getLotaResp())
                        || mob.doc().isEletronico());
    }

    /*
     * Retorna se  possvel assinar digitalmente o documento a que pertence o
     * mbil passado por parmetro, conforme as seguintes condies:
     * <ul>
     * <li>Documento no pode ser processo interno importado</li>
     * <li>Usurio tem de ser cossignatrio do documento ou subscritor ou
     * [cadastrante, caso o documento seja externo], ou <i>podeMovimentar()</i>
     * tem de ser verdadeiro para o mbil / usurio</li>
     * <li>Documento tem de estar finalizado</li>
     * <li>Documento no pode estar cancelado</li>
     * <li>Documento no pode estar em algum arquivo nem eliminado</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAssinar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (mob.getDoc().isEletronico() && mob.getDoc().isAssinado())
            return false;

        if (mob.getExDocumento().isProcesso() && mob.getExDocumento().getExTipoDocumento()
                .getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_INTERNO_ANTIGO)
            return false;

        if (mob.isArquivado() || mob.isEliminado())
            return false;

        // cosignatario pode assinar depois que o subscritor j tiver assinado

        boolean isConsignatario = false;

        for (ExMovimentacao m : mob.doc().getMobilGeral().getExMovimentacaoSet()) {
            if (m.getExTipoMovimentacao()
                    .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_INCLUSAO_DE_COSIGNATARIO
                    && m.getExMovimentacaoCanceladora() == null
                    && (m.getSubscritor() != null && m.getSubscritor().equivale(titular))) {
                isConsignatario = true;
                break;
            }
        }

        boolean isCadastranteExterno = false;
        if (mob.doc().getExTipoDocumento().getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_EXTERNO
                && mob.doc().getCadastrante().equivale(titular))
            isCadastranteExterno = true;

        //condies para assinatura digital de cosignatrios em documentos fsicos 
        if ((mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular) || isConsignatario)
                && mob.doc().isFisico() && mob.doc().isFinalizado())
            return true;

        return ((mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular))

                || isCadastranteExterno
                || (isConsignatario && !mob.doc().isAssinado() && mob.doc().isAssinadoSubscritor())
                || podeMovimentar(titular, lotaTitular, mob))

                // && mob.doc().isEletronico() //Nato: Permitido assinar
                // digitalmente
                // doc em papel, a pedido do Dr Libonati.
                && (mob.doc().isFinalizado()) && !mob.doc().isCancelado() && !mob.doc().isSemEfeito()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_DIGITAL_DOCUMENTO,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /*
     * Retorna se  possvel assinar um documento com senha:
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAssinarComSenha(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob)
            throws Exception {

        ExTipoMovimentacao exTpMov = ExDao.getInstance().consultar(
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_COM_SENHA, ExTipoMovimentacao.class, false);

        return getConf().podePorConfiguracao(null, null, null, null, mob.doc().getExFormaDocumento(),
                mob.doc().getExModelo(), null, null, exTpMov, null, null, null, lotaTitular, titular, null,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /*
     * Retorna se pode autenticar um documento que s foi assinado com senha.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAutenticarDocumento(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExDocumento doc) {

        if (doc.isEletronico() && !doc.isAutenticado() && doc.temAssinaturasComSenha()) {
            return true;
        }

        return false;
    }

    /*
     * Retorna se pode autenticar uma movimentao que s foi assinada com senha.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAutenticarMovimentacao(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMovimentacao mov) {

        //No  necessrio autenticar movimentao de anexao pois o link para assinar/autenticar sempre est disponvel. 
        if (mov.getExTipoMovimentacao().getIdTpMov().equals(ExTipoMovimentacao.TIPO_MOVIMENTACAO_ANEXACAO))
            return false;

        if (mov.getExDocumento().isEletronico() && !mov.isAutenticada() && mov.temAssinaturasComSenha()) {
            return true;
        }

        return false;
    }

    /*
     * Retorna se  possvel assinar uma movimentao com senha:
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAssinarMovimentacaoComSenha(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMovimentacao mov) {

        ExTipoMovimentacao exTpMov = ExDao.getInstance().consultar(
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_MOVIMENTACAO_COM_SENHA, ExTipoMovimentacao.class,
                false);

        return getConf().podePorConfiguracao(null, null, null, null,
                mov.getExMobil().getExDocumento().getExFormaDocumento(),
                mov.getExMobil().getExDocumento().getExModelo(), null, null, exTpMov, null, null, null, lotaTitular,
                titular, null, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /*
     * Retorna se  possvel assinar movimentaes do mobil com senha:
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAssinarMovimentacaoComSenha(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) throws Exception {

        ExTipoMovimentacao exTpMov = ExDao.getInstance().consultar(
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_MOVIMENTACAO_COM_SENHA, ExTipoMovimentacao.class,
                false);

        return getConf().podePorConfiguracao(null, null, null, null, mob.getExDocumento().getExFormaDocumento(),
                mob.getExDocumento().getExModelo(), null, null, exTpMov, null, null, null, lotaTitular, titular,
                null, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /*
     * Retorna se  possvel assinar uma movimentao com senha:
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeConferirCopiaMovimentacaoComSenha(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMovimentacao mov) throws Exception {

        if (mov == null)
            return false;

        if (!mov.getExTipoMovimentacao().getIdTpMov().equals(ExTipoMovimentacao.TIPO_MOVIMENTACAO_ANEXACAO))
            return false;

        ExTipoMovimentacao exTpMov = ExDao.getInstance().consultar(
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_CONFERENCIA_COPIA_COM_SENHA, ExTipoMovimentacao.class, false);

        return getConf().podePorConfiguracao(null, null, null, null,
                mov.getExMobil().getExDocumento().getExFormaDocumento(),
                mov.getExMobil().getExDocumento().getExModelo(), null, null, exTpMov, null, null, null, lotaTitular,
                titular, null, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /*
     * Retorna se  possvel cpia de um movimentaes do mobil com senha:
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeConferirCopiaMovimentacaoComSenha(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) throws Exception {

        if (mob == null)
            return false;

        ExTipoMovimentacao exTpMov = ExDao.getInstance().consultar(
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_CONFERENCIA_COPIA_COM_SENHA, ExTipoMovimentacao.class, false);

        return getConf().podePorConfiguracao(null, null, null, null, mob.getExDocumento().getExFormaDocumento(),
                mob.getExDocumento().getExModelo(), null, null, exTpMov, null, null, null, lotaTitular, titular,
                null, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    public boolean podeSerSubscritor(final ExDocumento doc) throws Exception {

        if (doc.getExTipoDocumento().getIdTpDoc().equals(ExTipoDocumento.TIPO_DOCUMENTO_EXTERNO))
            return true;

        return podeSerSubscritor(doc.getTitular(), doc.getLotaTitular(), doc.getExModelo());
    }

    /**
     * Retorna se  possvel ser subscritor de um documento.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeSerSubscritor(final DpPessoa titular, final DpLotacao lotaTitular, final ExModelo mod)
            throws Exception {

        if (titular == null || mod == null)
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular, titular.getCargo(), titular.getFuncaoConfianca(),
                mod.getExFormaDocumento(), mod, ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_DIGITAL_DOCUMENTO,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel publicar o Boletim Interno que possui mob, segundo
     * as regras:
     * <ul>
     * <li>Documento tem de estar finalizado</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Documento tem de estar assinado</li>
     * <li>Documento no pode estar publicado</li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao:
     * Movimentar / Publicao Boletim</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podePublicar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob)
            throws Exception {
        return (mob.doc().isFinalizado()) && podeMovimentar(titular, lotaTitular, mob) && mob.doc().isAssinado()
                && !mob.doc().isBoletimPublicado() && !mob.doc().isSemEfeito() && !mob.doc().isEliminado()
                && !mob.isPendenteDeAnexacao()
                && getConf().podePorConfiguracao(titular, lotaTitular, mob.doc().getExModelo(),
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_PUBLICACAO_BOLETIM,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se uma pessoa j teve acesso a um documento. Para isso, verifica
     * se pessoa j foi atendente de alguma das movimentaes de qualquer mbil
     * do documento, caso a movimentao no tenha como atendente toda uma
     * lotao, ou se ela  da lotao atendente de alguma dessas movimentaes.
     * Se a movimentao em questo for uma redefinio de nvel de acesso,
     * verifica se foi o prprio usurio que cadastrou a redefinio.
     * <b>Documentar a razo dessas regras.</b>
     * 
     * @param doc
     * @param titular
     * @param lotaTitular
     * @return
     */
    public static boolean pessoaJaTeveAcesso(ExDocumento doc, DpPessoa titular, DpLotacao lotaTitular) {
        for (ExMobil m : doc.getExMobilSet()) {
            for (ExMovimentacao mov : m.getExMovimentacaoSet()) {
                if ((mov.getLotaResp() != null && mov.getLotaResp().equivale(lotaTitular) && mov.getResp() == null)
                        || (mov.getResp() != null && mov.getResp().equivale(titular)))
                    return true;
                if (mov.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_REDEFINICAO_NIVEL_ACESSO
                        && ((mov.getLotaCadastrante() != null && mov.getLotaCadastrante().equivale(lotaTitular)
                                && mov.getCadastrante() == null)
                                || (mov.getCadastrante() != null && mov.getCadastrante().equivale(titular))))
                    return true;

            }
        }
        return false;
    }

    /**
     * Retorna se uma pessoa/lotao est vinculada a um documento por meio de algum
     * perfil. Para isso, verifica cada movimentao no cancelada de vinculao
     * de perfil registrada no mbil geral do documento e analisa se a pessoa/lotao
     * passada por parmetro  <i>titular/lotaTitular</i> de alguma dessas movimentaes.
        
     * 
     * @param doc
     * @param titular
     * @param lotaTitular
     * @return
     */
    public static boolean pessoaTemPerfilVinculado(ExDocumento doc, DpPessoa titular, DpLotacao lotaTitular) {
        for (ExMovimentacao mov : doc.getMobilGeral().getExMovimentacaoSet()) {

            if (!mov.isCancelada() && mov.getExTipoMovimentacao()

                    .getIdTpMov().equals(ExTipoMovimentacao.TIPO_MOVIMENTACAO_VINCULACAO_PAPEL)) {

                if (mov.getSubscritor() != null) {
                    if (mov.getSubscritor().equivale(titular)) {
                        return true;
                    }
                } else {
                    if (mov.getLotaSubscritor().equivale(lotaTitular)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * Retorna se uma <i>lotao</i> j foi atendente em alguma movimentao
     * (mesmo cancelada) de algum mbil do documento passado por parmetro
     * 
     * @param doc
     * @param lota
     * @return
     */
    public static boolean jaPassouPor(ExDocumento doc, DpLotacao lota) {
        for (ExMobil m : doc.getExMobilSet()) {
            for (ExMovimentacao mov : m.getExMovimentacaoSet())
                if (mov.getLotaResp() != null && mov.getLotaResp().equivale(lota))
                    return true;
        }
        return false;
    }

    /**
     * Retorna se  possvel exibir a opo de criar via em documento.
     * <b>Verificar qual a utilidade desse mtodo</b>. Condies:
     * <ul>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>Tem de ser possvel criar via (<i>podeCriarVia()</i>)</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeBotaoCriarVia(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob)
            throws Exception {

        if (mob.doc().isSemEfeito() || mob.doc().isEliminado())
            return false;

        if (!mob.isEmTransito() && podeCriarVia(titular, lotaTitular, mob)
                && podeMovimentar(titular, lotaTitular, mob))
            // && (mob.doc().getNumUltimaViaNaoCancelada() == numVia))
            return true;

        return false;
    }

    /**
     * Retorna se  possvel desentranhar mbil de outro. Regras:
     * <ul>
     * <li>Mbil tem de ser via</li>
     * <li>Mbil tem de estar juntado externo ou interno (verifica-se juntada
     * interna pela existncia de mbil pai)</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>Mbil no pode estar cancelado</li>
     * <li>A no ser que o mbil esteja juntado externo, <i>podeMovimentar()</i>
     * tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Mbil tem de estar juntado. <b>Obs.: essa checagem no torna
     * desnecessrios os processamentos acima?</b></li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao:
     * Cancelar Juntada</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeCancelarJuntada(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        final ExMovimentacao ultMovNaoCancelada = mob.getUltimaMovimentacaoNaoCancelada();

        if (!mob.isVia())
            return false;

        if (ultMovNaoCancelada == null)
            return false;

        ExMobil mobPai = null;
        if (!mob.isJuntadoExterno()) {
            mobPai = mob.getExMobilPai();
            if (mobPai == null)
                return false;
        }

        if (mob.isEmTransito() || mob.isCancelada()
                || (!mob.isJuntadoExterno() && !podeMovimentar(titular, lotaTitular, mobPai)) || (!mob.isJuntado()))
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_CANCELAMENTO_JUNTADA,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel cancelar a ltima movimentao no cancelada do
     * mbil mob, segundo as regras abaixo.
     * <ul>
     * <li>ltima movimentao no cancelada do mbil no pode ser apensao nem
     * desapensao</li>
     * <li>ltima movimentao no cancelada do mbil no pode ser assinatura do
     * documento ou de movimentao</li>
     * <li>ltima movimentao no cancelada do mbil no pode ser recebimento</li>
     * <li>ltima movimentao no cancelada do mbil no pode ser incluso em
     * edital de eliminao</li>
     * <li>ltima movimentao no cancelada do mbil no pode ser atualizao
     * resultante de assinatura do documento ou de movimentao</li>
     * <li>ltima movimentao no cancelada do mbil no pode ser publicao do
     * Boletim nem notificao de publicao do Boletim</li>
     * <li>Se a ltima movimentao no cancelada for agendamento de publicao
     * direta no DJE, o usurio que tem permisso para atender pedidos de
     * publicao indireta pode cancelar, no importando se
     * <i>podeMovimentar()</i>  verdadeiro</li>
     * <li>Mbil no pode estar cancelado</li>
     * <li>Se a ltima movimentao j for um cancelamento, no permite cancelar
     * a ltima movimentao no cancelada, a no ser que a ltima movimentao
     * seja cancelamento de atualizao ou de recebimento transitrio</li>
     * <li>Apenas o usurio que seja da lotao cadastrante da ltima
     * movimentao no cancelada pode cancel-la, se for dos seguintes tipos:</li>
     * <ul>
     * <li>Transferncia</li>
     * <li>Transferncia Externa</li>
     * <li>Despacho Interno com Transferncia</li>
     * <li>Despacho com transferncia Externa</li>
     * <li>Despacho com Transferncia</li>
     * <li>Recebimento Transitrio</li>
     * <li>Recebimento</li>
     * <li><b>Registro de Assinatura do Documento (desnecessrio)</li>
     * <li>Assinatura Digital do Documento (desnecessrio)</b></li>
     * </ul>
     * <li>Excetuadas as condies acima, para cancelar a ltima movimentao
     * no cancelada do mbil o usurio ter de ser 1) o atendente da
     * movimentao, 2) o subscritor da movimentao, 3) o titular da
     * movimentao ou 4) da lotao cadastrante da movimentao</li> <li>Se
     * ltima movimentao no cancelada for de registro de assinatura, s deixa
     * cancelar se no houver alguma movimentao posterior em alguma das vias.
     * <b>Obs.: regra em desuso. Parece tambm haver erro no cdigo
     * (before(dt)?)</b></li> <li>No pode haver configurao impeditiva. Tipo
     * de configurao: Cancelar Movimentao</li> </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeCancelarMovimentacao(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        //No deixa cancelar movimentao de um mobil diferente de geral quando um documento est sem efeito.

        if (!mob.isGeral() && mob.doc().isSemEfeito())
            return false;

        if (mob.isEliminado())
            return false;

        final ExMovimentacao exUltMovNaoCanc = mob.getUltimaMovimentacaoNaoCancelada();
        final ExMovimentacao exUltMov = mob.getUltimaMovimentacao();
        if (exUltMov == null || exUltMovNaoCanc == null)
            return false;

        //S deixa cancelar movimentao de tornar documento sem efeito, se o titular for o subscritor do documento
        //Tambm no  permitido os cosignatrios cancelar essa movimentao
        if (mob.isGeral()
                && exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_TORNAR_SEM_EFEITO
                && !exUltMovNaoCanc.getSubscritor().equivale(titular))

            return false;

        // No deixa cancelar apensao ou desapensao
        if (exUltMovNaoCanc.getExTipoMovimentacao().getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_APENSACAO
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESAPENSACAO)
            return false;

        if (exUltMovNaoCanc.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_INCLUSAO_EM_EDITAL_DE_ELIMINACAO)
            return false;

        if (exUltMovNaoCanc.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_RECEBIMENTO)
            return false;

        if (exUltMovNaoCanc.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_PENDENCIA_DE_ANEXACAO)
            return false;

        // No deixa cancelar assinatura
        if (exUltMovNaoCanc.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_REGISTRO_ASSINATURA_DOCUMENTO
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_DIGITAL_DOCUMENTO
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_COM_SENHA
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_DIGITAL_MOVIMENTACAO
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_CONFERENCIA_COPIA_DOCUMENTO
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_MOVIMENTACAO_COM_SENHA
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_CONFERENCIA_COPIA_COM_SENHA)
            return false;

        // No deixa cancelar a atualizao (por enquanto, s ser resultar
        // da
        // assinatura)
        if (exUltMovNaoCanc.getExTipoMovimentacao().getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ATUALIZACAO
                && exUltMovNaoCanc.getExMovimentacaoRef() != null
                && (exUltMovNaoCanc.getExMovimentacaoRef().getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_REGISTRO_ASSINATURA_DOCUMENTO
                        || exUltMovNaoCanc.getExMovimentacaoRef().getExTipoMovimentacao()
                                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_DIGITAL_DOCUMENTO))
            return false;

        if (exUltMovNaoCanc.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_NOTIFICACAO_PUBL_BI
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_PUBLICACAO_BOLETIM
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_DISPONIBILIZACAO)
            return false;

        //No deixa cancelar juntada quando o documento est juntado a um expediente/processo que j sofreu outra movimentao
        if (exUltMovNaoCanc.getExTipoMovimentacao().getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_JUNTADA) {

            if (exUltMovNaoCanc.getExMobilRef().isArquivado())
                return false;

            ExMovimentacao ultimaMovimentacaoDaReferencia = exUltMovNaoCanc.getExMobilRef().getUltimaMovimentacao();

            if (ultimaMovimentacaoDaReferencia.getExTipoMovimentacao()
                    .getIdTpMov() != ExTipoMovimentacao.TIPO_MOVIMENTACAO_ANOTACAO
                    && ultimaMovimentacaoDaReferencia.getDtMov().after(exUltMovNaoCanc.getDtMov()))
                return false;

            //Verifica se o mobil de referncia j recebeu outras movimentaes depois da movimentao que vai ser cancelada.
            if (mob.doc().isEletronico() && exUltMovNaoCanc.getExMobilRef() != null
                    && exUltMovNaoCanc.getExMobilRef().doc().isNumeracaoUnicaAutomatica()) {

                for (ExMovimentacao movDoMobilRef : exUltMovNaoCanc.getExMobilRef().getCronologiaSet()) {
                    if (movDoMobilRef.getIdMov().equals(exUltMovNaoCanc.getIdMov()))
                        break;

                    if (!movDoMobilRef.isCancelada()
                            && movDoMobilRef.getExTipoMovimentacao()
                                    .getId() != ExTipoMovimentacao.TIPO_MOVIMENTACAO_REFERENCIA
                            && movDoMobilRef.getExTipoMovimentacao()
                                    .getId() != ExTipoMovimentacao.TIPO_MOVIMENTACAO_ANOTACAO
                            && movDoMobilRef.getDtIniMov().after(exUltMovNaoCanc.getDtIniMov()))
                        return false;
                }
            }
        }

        // Verifica se a ltima movimentao no cancelada  agendamento de
        // publicao no DJE
        if (exUltMovNaoCanc.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_AGENDAMENTO_DE_PUBLICACAO
                && podeAtenderPedidoPublicacao(titular, lotaTitular, mob))
            return true;

        // No deixa cancelar a mov se a via estiver cancelada ou h um
        // cancelamento imediatamente anterior, a no ser se este for
        // cancelamento de receb transitrio ou de atualizao
        if (mob.isCancelada()
                || (exUltMovNaoCanc.getIdMov() != exUltMov.getIdMov() && exUltMov.getExMovimentacaoRef() != null
                        && exUltMov.getExMovimentacaoRef().getExTipoMovimentacao()
                                .getIdTpMov() != ExTipoMovimentacao.TIPO_MOVIMENTACAO_RECEBIMENTO_TRANSITORIO
                        && exUltMov.getExMovimentacaoRef().getExTipoMovimentacao()
                                .getIdTpMov() != ExTipoMovimentacao.TIPO_MOVIMENTACAO_ATUALIZACAO)
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_CRIACAO)
            return false;
        // Essas s a lota do cadastrante pode cancelar
        else if (exUltMovNaoCanc.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_TRANSFERENCIA
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_TRANSFERENCIA_EXTERNA
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESPACHO_INTERNO_TRANSFERENCIA
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESPACHO_TRANSFERENCIA_EXTERNA
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESPACHO_TRANSFERENCIA
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_RECEBIMENTO_TRANSITORIO
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_REGISTRO_ASSINATURA_DOCUMENTO
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_DIGITAL_DOCUMENTO) {
            return exUltMovNaoCanc.getLotaCadastrante().equivale(lotaTitular);
        } else {
            if (exUltMovNaoCanc.getLotaResp() != null) {
                if (!exUltMovNaoCanc.getLotaResp().equivale(lotaTitular))
                    return false;
            } else if (exUltMovNaoCanc.getSubscritor() != null) {
                if (!exUltMovNaoCanc.getSubscritor().getLotacao().equivale(lotaTitular))
                    return false;
            } else if (exUltMovNaoCanc.getTitular() != null) {
                if (!exUltMovNaoCanc.getTitular().getLotacao().equivale(lotaTitular))
                    return false;
            } else {
                if (!exUltMovNaoCanc.getLotaCadastrante().equivale(lotaTitular))
                    return false;
            }
        }

        // Antes de deixar cancelar a assinatura, v antes se houve
        // movimentaes posteriores em qualquer via
        if (exUltMovNaoCanc.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_REGISTRO_ASSINATURA_DOCUMENTO) {
            Date dt = exUltMovNaoCanc.getDtIniMov();
            for (ExMobil m : mob.doc().getExMobilSet()) {
                ExMovimentacao move = m.getUltimaMovimentacaoNaoCancelada();
                if (move != null && move.getDtIniMov().before(dt)) {
                    return false;
                }
            }
        }

        //No deixa desfazer os antigos arquivamentos feitos em volume de processo
        if (exUltMovNaoCanc.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ARQUIVAMENTO_CORRENTE
                && !podeDesarquivarCorrente(titular, lotaTitular, mob)) {
            return false;

        }

        if (exUltMovNaoCanc.getExTipoMovimentacao().getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ANEXACAO
                && !podeCancelarAnexo(titular, lotaTitular, mob, exUltMovNaoCanc)) {
            return false;

        }

        return getConf().podePorConfiguracao(titular, lotaTitular,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_CANCELAMENTO_DE_MOVIMENTACAO,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel cancelar uma movimentao mov, segundo as regras
     * abaixo. <b>Mtodo em desuso?</b>
     * <ul>
     * <li>Movimentao no pode estar cancelada</li>
     * <li>Usurio tem de ser da lotao cadastrante da movimentao</li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao:
     * Cancelar Movimentao</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @param mov
     * @return
     * @throws Exception
     */
    public boolean podeCancelar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob,
            final ExMovimentacao mov) throws Exception {
        if (mov == null)
            return false;

        if (mob.isCancelada())
            return false;

        if (!mov.getLotaCadastrante().equivale(lotaTitular))
            return false;

        if (!mov.getLotaCadastrante().equivale(mov.getLotaResp()))
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular, mov.getIdTpMov(),
                CpTipoConfiguracao.TIPO_CONFIG_CANCELAR_MOVIMENTACAO);
    }

    /**
     * Retorna se  possvel cancelar a via mob, conforme estabelecido a seguir:
     * <ul>
     * <li>Mbil tem de ser via</li>
     * <li>Documento que contm a via no pode estar assinado</li>
     * <li>Via no pode estar cancelada</li>
     * <li>ltima movimentao no cancelada da via tem de ser a sua criao</li>
     * <li>No pode haver movimentaes canceladas posteriores  criao</li>
     * <li>Com relao  movimentao de criao (ltima movimentao no
     * cancelada), o usurio tem de ser 1) da lotao atendente da movimentao,
     * 2) o subscritor da movimentao, 3) o titular da movimentao ou 4) da
     * lotao cadastrante da movimentao</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeCancelarVia(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        if (!mob.isVia())
            return false;
        if (mob.getExDocumento().isAssinado())
            return false;
        final ExMovimentacao exUltMovNaoCanc = mob.getUltimaMovimentacaoNaoCancelada();
        final ExMovimentacao exUltMov = mob.getUltimaMovimentacao();
        if (mob.isCancelada()
                || exUltMovNaoCanc.getExTipoMovimentacao()
                        .getIdTpMov() != ExTipoMovimentacao.TIPO_MOVIMENTACAO_CRIACAO
                || exUltMovNaoCanc.getIdMov() != exUltMov.getIdMov())
            return false;
        else if (exUltMovNaoCanc.getLotaResp() != null) {
            if (!exUltMovNaoCanc.getLotaResp().equivale(lotaTitular))
                return false;
        } else if (exUltMovNaoCanc.getSubscritor() != null) {
            if (!exUltMovNaoCanc.getSubscritor().getLotacao().equivale(lotaTitular))
                return false;
        } else if (exUltMovNaoCanc.getTitular() != null) {
            if (!exUltMovNaoCanc.getTitular().getLotacao().equivale(lotaTitular))
                return false;
        } else {
            if (!exUltMovNaoCanc.getCadastrante().getLotacao().equivale(lotaTitular))
                return false;
        }

        //No  possvel cancelar a ltima via de um documento pois estava gerando erros nas marcas do mobil geral.
        boolean isUnicaViaNaoCancelada = true;
        for (ExMobil outroMobil : mob.getDoc().getExMobilSet()) {
            if (!outroMobil.isGeral() && !outroMobil.isCancelada()
                    && !outroMobil.getIdMobil().equals(mob.getIdMobil())) {
                isUnicaViaNaoCancelada = false;
                break;
            }
        }

        if (isUnicaViaNaoCancelada)
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_CANCELAR_VIA);
    }

    /**
     * Retorna se  possvel criar via para o documento que contm o mbil
     * passado por parmetro, de acordo com as seguintes condies:
     * <ul>
     * <li>Documento tem de ser expediente</li>
     * <li>Documento no pode ter pai, pois no  permitido criar vias em
     * documento filho</li>
     * <li>Nmero da ltima via no pode ser maior ou igual a 21</li>
     * <li>Documento tem de estar finalizado</li>
     * <li>Documento no pode ter sido eliminado</li>
     * <li>Documento tem de possuir alguma via no cancelada</li>
     * <li>Lotao do titular igual a do cadastrante ou a do subscritor ou 
        
     * o titular ser o prprio subscritor</li>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception 
     */
    public boolean podeCriarVia(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (mob.doc().isSemEfeito())
            return false;

        if (!mob.doc().isExpediente())
            return false;

        if (mob.doc().isEliminado())
            return false;

        if (mob.doc().getExMobilPai() != null && !mob.doc().isAssinado())
            return false;

        if (mob.doc().getNumUltimaVia() >= 21)
            return false;

        if (mob.isEmTransito())
            return false;

        if (mob.doc().getNumUltimaViaNaoCancelada() > 0 && mob.doc().isFinalizado()
                && (podeMovimentar(titular, lotaTitular, mob)
                        || mob.doc().getLotaCadastrante().equivale(lotaTitular)
                        || (mob.doc().getLotaSubscritor() != null
                                && mob.doc().getLotaSubscritor().equivale(lotaTitular))
                        || (mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular))) // subscritor  null para documentos externos            
        ) {

            return true;
        }

        return false;
    }

    /**
     * Retorna se  possvel criar volume para o documento que contm o mbil
     * passado por parmetro, de acordo com as seguintes condies:
     * <ul>
     * <li>Documento tem de ser processo</li>
     * <li>Processo tem de estar finalizado</li>
     * <li>ltimo volume tem de estar encerrado</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeCriarVolume(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!mob.doc().isProcesso())
            return false;

        if (mob.doc().getUltimoVolume() != null
                && (mob.doc().getUltimoVolume().isEmTransito() || mob.doc().getUltimoVolume().isSobrestado()))
            return false;

        if (mob.isArquivadoCorrente())
            return false;

        if (!podeMovimentar(titular, lotaTitular, mob))
            return false;

        if (!mob.doc().isAssinado())
            return false;

        if (mob.doc().isFinalizado() && mob.doc().getUltimoVolume().isVolumeEncerrado()) {

            if (mob.doc().isEletronico() && (mob.doc().getUltimoVolume().temAnexosNaoAssinados()
                    || mob.doc().getUltimoVolume().temDespachosNaoAssinados()))
                return false;

            return true;
        }

        return false;
    }

    /**
     * Retorna se  possvel encerrar um volume, dadas as seguintes condies:
     * <ul>
     * <li>Mbil tem de ser volume</li>
     * <li>Volume no pode estar encerrado</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>Mbil no pode estar spbrestado</li>
     * <li>Volume no pode estar em trnsito</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeEncerrarVolume(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!mob.isVolume())
            return false;

        if (mob.isVolumeEncerrado())
            return false;

        if (mob.isArquivado())
            return false;

        if (mob.isEmTransito())
            return false;

        if (!mob.doc().isAssinado())
            return false;

        if (mob.isSobrestado())
            return false;

        return podeMovimentar(titular, lotaTitular, mob) && getConf().podePorConfiguracao(titular, lotaTitular,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_ENCERRAMENTO_DE_VOLUME,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel reabrir um mbil, segundo as seguintes regras:
     * <ul>
     * <li>Mbil tem de ser via ou geral de processo.</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Mbil tem de estar arquivado corrente ou intermedirio, mas no permanentemente</li>
     * <li>Mbil no pode estar em edital de eliminao</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeDesarquivarCorrente(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!mob.isVia() && !mob.isGeralDeProcesso())
            return false;

        final ExMovimentacao ultMovNaoCancelada = mob.getUltimaMovimentacaoNaoCancelada();
        if (ultMovNaoCancelada == null)
            return false;
        return podeMovimentar(titular, lotaTitular, mob)
                && (mob.isArquivadoCorrente() || mob.isArquivadoIntermediario()) && !mob.isArquivadoPermanente()
                && !mob.isEmEditalEliminacao() && !mob.isEmTransito()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESARQUIVAMENTO_CORRENTE,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel reabrir um mbil, segundo as seguintes regras:
     * <ul>
     * <li>Mbil tem de ser via ou geral de processo.</li>
     * <li>Mbil tem de estar em arquivo intermedirio, no permanente</li>
     * <li>Mbil no pode estar em edital de eliminao</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeBotaoDesarquivarIntermediario(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        if (!mob.isVia() && !mob.isGeralDeProcesso())
            return false;

        final ExMovimentacao ultMovNaoCancelada = mob.getUltimaMovimentacaoNaoCancelada();
        if (ultMovNaoCancelada == null)
            return false;
        return (mob.isArquivadoIntermediario()) && !mob.isArquivadoPermanente() && !mob.isEmEditalEliminacao()
                && !mob.isEmTransito()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESARQUIVAMENTO_INTERMEDIARIO,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel fazer o desarquivamento intermedirio do mbil, ou
     * seja, se  possvel mostrar o link para movimentao e se, alm disso, o
     * mbil encontra-se na lotao titular ou  digital.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeDesarquivarIntermediario(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {
        return podeBotaoDesarquivarIntermediario(titular, lotaTitular, mob)
                && (lotaTitular.equivale(mob.getUltimaMovimentacaoNaoCancelada().getLotaResp())
                        || mob.doc().isEletronico());
    }

    /**
     * Retorna se  possvel desobrestar um mbil, segundo as seguintes regras:
     * <ul>
     * <li>Mbil tem de ser via ou volume. No pode ser geral</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Mbil tem de estar sobrestado</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeDesobrestar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!(mob.isVia() || mob.isVolume()))
            return false;
        final ExMovimentacao ultMovNaoCancelada = mob.getUltimaMovimentacaoNaoCancelada();
        if (ultMovNaoCancelada == null)
            return false;
        return podeMovimentar(titular, lotaTitular, mob) && (mob.isSobrestado())
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESOBRESTAR,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel fazer despacho no mbil, conforme as regras a
     * seguir:
     * <ul>
     * <li>Mbil no pode ter despacho pendente de assinatura</li>
     * <li>Mbil tem de ser via ou volume. No pode ser geral</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>Mbil no pode estar em edital de eliminao</li>
     * <li>Mbil tem de estar assinado ou ser externo. <b>Mas documento externo
     * no  cnsiderado assinado? <i>isAssinado</i> no deveria retornar
     * verdadeiro?</b></li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeDespachar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        return (mob.isVia() || mob.isVolume()) && !mob.isEmTransito() && podeMovimentar(titular, lotaTitular, mob)
                && !mob.isJuntado() && !mob.isArquivado() && !mob.isEmEditalEliminacao() && !mob.isSobrestado()
                && !mob.isPendenteDeAnexacao() && !mob.doc().isSemEfeito()
                && (mob.doc().isAssinado()
                        || (mob.doc().getExTipoDocumento().getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_EXTERNO)
                        || (mob.doc().isProcesso() && mob.doc().getExTipoDocumento()
                                .getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_INTERNO_ANTIGO))
                // && mob.doc().isAssinadoPorTodosOsSignatarios()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESPACHO, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel fazer download do contedo. Mtodo em desuso,
     * retornando sempre <i>false</i>.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeDownloadConteudo(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        return false;
    }

    /**
     * Retorna se  possvel duplicar o documento ue contm o mbil mob. Basta
     * no estar eliminado o documento e no haver configurao impeditiva, o
     * que significa que, tendo acesso a um documento no eliminado, qualquer
     * usurio pode duplic-lo.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeDuplicar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (podeAcessarDocumento(titular, lotaTitular, mob))
            return true;

        return !mob.isEliminado()
                && getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_DUPLICAR);
    }

    /**
     * Retorna se  possvel exibir informaes completas.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeExibirInformacoesCompletas(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {
        return true;
    }

    /**
     * Retorna se  possvel editar um documento, conforme as seguintes regras:
     * <ul>
     * <li>Se o documento for fsico, no pode estar finalizado</li>
     * <li>Documento no pode estar cancelado</li>
     * <li>Se o documento for digital, no pode estar assinado</li>
     * <li>Usurio tem de ser 1) da lotao cadastrante do documento,
     * 2)subscritor do documento ou 3) titular do documento</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeEditar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (mob.doc().isFinalizado() && !mob.doc().isEletronico())
            return false;
        if (mob.doc().isCancelado() || mob.doc().isSemEfeito())
            return false;
        if (mob.doc().isAssinado() || mob.doc().isEletronicoEPossuiPeloMenosUmaAssinaturaDigital()
                || mob.doc().isEletronicoEPossuiPeloMenosUmaAssinaturaComSenha())
            return false;
        if (!mob.doc().getLotaCadastrante().equivale(lotaTitular)
                && (mob.doc().getSubscritor() != null && !mob.doc().getSubscritor().equivale(titular))
                && (mob.doc().getTitular() != null && !mob.doc().getTitular().equivale(titular)))
            if (!mob.getExDocumento().temPerfil(titular, lotaTitular, ExPapel.PAPEL_GESTOR))
                return false;

        if (!getConf().podePorConfiguracao(titular, lotaTitular, mob.doc().getExFormaDocumento(),
                CpTipoConfiguracao.TIPO_CONFIG_CRIAR)
                && !getConf().podePorConfiguracao(titular, lotaTitular, mob.doc().getExModelo(),
                        CpTipoConfiguracao.TIPO_CONFIG_CRIAR))
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_EDITAR);

    }

    /**
     * Retorna se  possvel agendar publicao direta, de acordo com as
     * seguintes regras:
     * <ul>
     * <li>Documento tem de estar fechado</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Documento tem de estar assinado</li>
     * <li>No pode haver agendamento de publicao direta em aberto</li>
     * <li>No pode haver agendamento de publicao indireta em aberto</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>Mbil no pode estar eliminado</li>
     * <li>Nada  dito a respeito do Boletim Interno</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAgendarPublicacao(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!mob.doc().isFinalizado() || !mob.doc().isAssinado() || mob.doc().isPublicacaoAgendada()
                || mob.doc().isSemEfeito() || mob.doc().isEliminado() || mob.isArquivado())
            return false;

        if (mob.isPendenteDeAnexacao())
            return false;

        if (podeAtenderPedidoPublicacao(titular, lotaTitular, null))
            return true;

        return (!mob.doc().isPublicacaoSolicitada() && podeMovimentar(titular, lotaTitular, mob)
                && getConf().podePorConfiguracao(titular, lotaTitular, mob.doc().getExModelo(),
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_AGENDAMENTO_DE_PUBLICACAO,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR));

    }

    /**
     * Retorna se  possvel fazer o agendamento de publicao solicitada
     * indiretamente. Basta haver permisso para atender pedido de publicao e
     * estar com publicao indireta solicitada o documento a que pertence o
     * mbil passado por parmetro.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeRemeterParaPublicacaoSolicitada(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) throws Exception {
        if (mob.isPendenteDeAnexacao())
            return false;
        return mob.doc().isPublicacaoSolicitada() && podeAtenderPedidoPublicacao(titular, lotaTitular, mob);
    }

    /**
     * Retorna se  possvel solicitar publicao indireta no DJE, conforme as
     * regras a seguir:
     * <ul>
     * <li>No pode ser possvel agendar publicao direta</li>
     * <li>Documento tem de estar fechado (verificao desnecessria, visto que
     * abaixo se checa se est assinado)</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * <li>Documento tem de estar assinado</li>
     * <li>No pode haver outra solicitao de publicao no DJE em aberto</li>
     * <li>No pode pode haver solicitao de publicao no Boletim em aberto</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>Mbil no pode estar eliminado</li>
     * <li>No pode haver agendamento de publicao direta em aberto
     * <b>(verificao desnecessria?)</b></li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podePedirPublicacao(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (podeAgendarPublicacao(titular, lotaTitular, mob)) {
            return false;
        } else
            return (mob.doc().isFinalizado())
                    && (podeMovimentar(titular, lotaTitular, mob)
                            || podeAtenderPedidoPublicacao(titular, lotaTitular, mob))
                    && mob.doc().isAssinado() && !mob.doc().isPublicacaoSolicitada()
                    && !mob.doc().isPublicacaoBoletimSolicitada() && !mob.doc().isPublicacaoAgendada()
                    && !mob.doc().isSemEfeito() && !mob.doc().isEliminado() && !mob.isArquivado()
                    && getConf().podePorConfiguracao(titular, lotaTitular, mob.doc().getExModelo(),
                            ExTipoMovimentacao.TIPO_MOVIMENTACAO_PEDIDO_PUBLICACAO,
                            CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel utilizar o recurso Criar Anexo, com base nas
     * seguintes regras:
     * <ul>
     * <li>Documento tem de estar finalizado</li>
     * <li>Documento tem de ser interno produzido</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAnexarArquivoAlternativo(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        if (!mob.isGeral() && !mob.doc().isAssinado())
            return false;

        if (mob.isGeral() && mob.doc().isAssinado())
            return false;

        if (mob.doc().isExpediente() && mob.doc().getPai() != null)
            return false;

        if (mob.doc().isProcesso() && mob.isArquivadoCorrente())
            return false;

        if (mob.isArquivado())
            return false;

        if (mob.doc().isSemEfeito())
            return false;

        if (mob.isSobrestado())
            return false;

        if (mob.isJuntado())
            return false;

        final boolean podeMovimentar = podeMovimentar(titular, lotaTitular, mob);
        final boolean gerenteBIE = podeGerenciarPublicacaoBoletimPorConfiguracao(titular, lotaTitular, mob);
        final boolean gerenteDJE = podeAtenderPedidoPublicacao(titular, lotaTitular, mob);
        final boolean podePorConfigAgendar = getConf().podePorConfiguracao(titular, lotaTitular,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_AGENDAMENTO_DE_PUBLICACAO,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR)
                && getConf().podePorConfiguracao(mob.getExDocumento().getExModelo(),
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_AGENDAMENTO_DE_PUBLICACAO,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
        final boolean podePorConfigPedirPubl = getConf().podePorConfiguracao(titular, lotaTitular,
                mob.getExDocumento().getExModelo(), ExTipoMovimentacao.TIPO_MOVIMENTACAO_PEDIDO_PUBLICACAO,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
        final boolean podePorConfigAgendarBoletim = (getConf().podePorConfiguracao(titular, lotaTitular,
                mob.getExDocumento().getExModelo(),
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_AGENDAMENTO_DE_PUBLICACAO_BOLETIM,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR));

        return (mob.getExDocumento().isFinalizado())
                && (mob.getExDocumento().getExTipoDocumento()
                        .getIdTpDoc() != ExTipoDocumento.TIPO_DOCUMENTO_EXTERNO)
                && !mob.isEmTransito() && podeMovimentar;

    }

    /**
     * Retorna se  possvel, com base em configurao, utilizar a rotina de
     * atendimento de pedidos indiretos de publicao no DJE. No  utilizado o
     * parmetro mob.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAtenderPedidoPublicacao(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {
        return getConf().podePorConfiguracao(titular, lotaTitular,
                CpTipoConfiguracao.TIPO_CONFIG_ATENDER_PEDIDO_PUBLICACAO);
    }

    /**
     * Retorna se  possvel excluir o documento cujo mbil  o representado
     * pelo parmetro mob. As regras para o documento so as seguintes:
     * <ul>
     * <li>Documento no pode estar finalizado, seja fsico ou eletrnico</li>
     * <li>Lotao do usurio tem de ser a do cadastrante do documento</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param doc
     * @param numVia
     * @return
     * @throws Exception
     */
    public boolean podeExcluir(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (mob.doc().isFinalizado())
            return false;

        if (!mob.doc().getLotaCadastrante().equivale(lotaTitular))
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_EXCLUIR);
    }

    /**
     * Retorna se  possvel excluir uma movimentao de anexao, representada
     * por mov, conforme as regras a seguir:
     * <ul>
     * <li>Anexao no pode estar cancelada</li>   
     * <li>Anexo no pode estar assinado</li>
     * <li>Se o documento for fsico, no pode estar finalizado</li>
     * <li>Se o documento for eletrnico, no pode estar assinado</li>
     * <li>Lotao do usurio tem de ser a lotao cadastrante da movimentao</li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao: Excluir
     * Anexo</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @param mov
     * @return
     * @throws Exception
     */
    public boolean podeExcluirAnexo(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob,
            final ExMovimentacao mov) {

        if (mov.isCancelada())
            return false;

        if (mov.isAssinada())
            return false;

        if (mob.doc().isFinalizado() && !mob.doc().isEletronico()) {
            return false;
        }

        if (!(mov.getLotaCadastrante().equivale(lotaTitular)))
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_EXCLUIR_ANEXO);
    }

    /**
     * Retorna se  possvel excluir uma movimentao de Incluso de Cossignatrio 
     * <ul>
     * <li>No pode estar cancelada</li>   
     * <li>No pode estar assinado</li>
     * <li>Se o documento for fsico, no pode estar finalizado</li>
     * <li>No pode estar assinado</li>
     * <li>Lotao do usurio tem de ser a lotao cadastrante da movimentao</li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao: Excluir
     * Anexo</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @param mov
     * @return
     * @throws Exception
     */
    public boolean podeExcluirCosignatario(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob,
            final ExMovimentacao mov) {

        if (mov.isCancelada())
            return false;

        if (mov.isAssinada())
            return false;

        if (mob.doc().isFinalizado() && !mob.doc().isEletronico()) {
            return false;
        }

        if (!(mov.getLotaCadastrante().equivale(lotaTitular)))
            return false;

        if (mov.getExDocumento().isAssinado() || mob.doc().isEletronicoEPossuiPeloMenosUmaAssinaturaDigital()
                || mob.doc().isEletronicoEPossuiPeloMenosUmaAssinaturaComSenha())
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_EXCLUIR);
    }

    /**
     * Retorna se  possvel cancelar uma movimentao mov, de anexao de
     * arquivo. Regras:
     * <ul>
     * <li>Anexao no pode estar cancelada</li>   
     * <li>No pode mais ser possvel <i>excluir</i> a anexao</li>
     * <li>Se o documento for fsico, anexao no pode ter sido feita antes da
     * finalizao</li>
     * <li>Se o documento for digital, anexao no pode ter sido feita antes da
     * assinatura</li>   
     * <li>Lotao do usurio tem de ser a lotao cadastrante da movimentao</li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao:
     * Cancelar Movimentao</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @param mov
     * @return
     * @throws Exception
     */
    public boolean podeCancelarAnexo(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob,
            final ExMovimentacao mov) {

        if (mov.isCancelada())
            return false;

        if (podeExcluirAnexo(titular, lotaTitular, mob, mov))
            return false;

        Calendar calMov = new GregorianCalendar();
        Calendar cal2 = new GregorianCalendar();
        calMov.setTime(mov.getDtIniMov());

        if (mob.doc().isFinalizado() && !mob.doc().isEletronico()) {
            cal2.setTime(mob.doc().getDtFinalizacao());
            if (calMov.before(cal2))
                return false;
        }

        if (mob.doc().isAssinado() && mob.doc().getExTipoDocumento().getIdTpDoc() == 1
                && mob.doc().isEletronico()) {
            cal2.setTime(mob.doc().getDtAssinatura());
            if (calMov.before(cal2))
                return false;
        }

        if (!(mov.getLotaCadastrante().equivale(lotaTitular)))
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular, ExTipoMovimentacao.TIPO_MOVIMENTACAO_ANEXACAO,
                CpTipoConfiguracao.TIPO_CONFIG_CANCELAR_MOVIMENTACAO);
    }

    /**
     * Retorna se  possvel cancelar uma movimentao de vinculao de perfil,
     * passada atravs do parmetro mov. As regras so as seguintes:
     * <ul>
     * <li>Vinculao de perfil no pode estar cancelada</li>
     * <li>Lotao do usurio tem de ser a lotao cadastrante da movimentao</li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao:
     * Cancelar Movimentao</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @param mov
     * @return
     * @throws Exception
     */
    public boolean podeCancelarVinculacaoPapel(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob, final ExMovimentacao mov) {

        if (mov.isCancelada())
            return false;

        if ((mov.getSubscritor() != null && mov.getSubscritor().equivale(titular))
                || (mov.getSubscritor() == null && mov.getLotaSubscritor().equivale(lotaTitular)))
            return true;

        if ((mov.getCadastrante() != null && mov.getCadastrante().equivale(titular))
                || (mov.getCadastrante() == null && mov.getLotaCadastrante().equivale(lotaTitular)))
            return true;

        return getConf().podePorConfiguracao(titular, lotaTitular, mov.getIdTpMov(),
                CpTipoConfiguracao.TIPO_CONFIG_CANCELAR_MOVIMENTACAO);
    }

    /**
     * <b>(Quando  usado este mtodo?)</b> Retorna se  possvel cancelar
     * movimentao do tipo despacho, representada pelo parmetro mov. So estas
     * as regras:
     * <ul>
     * <li>Despacho no pode estar cancelado</li>
     * <li>Lotao do usurio tem de ser a lotao cadastrante do despacho</li>
     * <li>Despacho no pode estar assinado</li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao:
     * Cancelar Movimentao</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @param mov
     * @return
     * @throws Exception
     */
    public boolean podeCancelarDespacho(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob,
            final ExMovimentacao mov) {

        if (mov.isCancelada())
            return false;

        if (!(mov.getLotaCadastrante().equivale(lotaTitular)))
            return false;

        if (mov.isUltimaMovimentacao())
            return false;

        for (ExMovimentacao movAssinatura : mov.getExMobil().getExMovimentacaoSet()) {
            if (!movAssinatura.isCancelada() && (movAssinatura.getExTipoMovimentacao()
                    .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_DIGITAL_MOVIMENTACAO
                    || movAssinatura.getExTipoMovimentacao()
                            .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_ASSINATURA_MOVIMENTACAO_COM_SENHA)
                    && movAssinatura.getExMovimentacaoRef().getIdMov() == mov.getIdMov())
                return false;
        }

        return getConf().podePorConfiguracao(titular, lotaTitular, mov.getIdTpMov(),
                CpTipoConfiguracao.TIPO_CONFIG_CANCELAR_MOVIMENTACAO);
    }

    /**
     * Retorna se  possvel excluir anotao realizada no mbil, passada pelo
     * parmetro mov. As seguintes regras incidem sobre a movimentao a ser
     * excluda:
     * <ul>
     * <li>No pode estar cancelada</li>
     * <li>Lotao do usurio tem de ser a do cadastrante ou do subscritor
     * (responsvel) da movimentao</li>
     * <li>No pode haver configurao impeditiva. Tipo de configurao: Excluir
     * Anotao</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @param mov
     * @return
     * @throws Exception
     */
    public boolean podeExcluirAnotacao(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob,
            final ExMovimentacao mov) {

        if (mov.isCancelada())
            return false;

        //Verifica se foi a pessoa ou lotao que fez a anotao
        if (!mov.getCadastrante().getIdInicial().equals(titular.getIdInicial())
                && !mov.getSubscritor().getIdInicial().equals(titular.getIdInicial())
                && !mov.getLotaCadastrante().getIdInicial().equals(lotaTitular.getIdInicial())
                && !mov.getLotaSubscritor().getIdInicial().equals(lotaTitular.getIdInicial()))
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_EXCLUIR_ANOTACAO);
    }

    /**
     * Retorna se  possvel exibir todos os mbil's. Basta o documento estar
     * finalizado.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeExibirTodasVias(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        return (mob != null && mob.doc().isFinalizado());
    }

    /**
     * Retorna se  possvel fazer anotao no mbil. Basta o mbil no estar
     * eliminado, no estar em trnsito, no ser geral e no haver configurao
     * impeditiva, o que significa que, tendo acesso a um documento no
     * eliminado fora de trnsito, qualquer usurio pode fazer anotao.
        
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeFazerAnotacao(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        return (!mob.isEmTransitoInterno() && !mob.isEliminado() && !mob.isGeral())
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_ANOTACAO, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel vincular perfil ao documento. Basta no estar
     * eliminado o documento e no haver configurao impeditiva, o que
     * significa que, tendo acesso a um documento no eliminado, qualquer
     * usurio pode se cadastrar como interessado.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeFazerVinculacaoPapel(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        if (mob.doc().isCancelado() || mob.doc().isSemEfeito()

                || mob.isEliminado())
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_VINCULACAO_PAPEL, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel finalizar o documento ao qual o mbil passado por
     * parmetro pertence. So estas as regras:
     * <ul>
     * <li>Documento no pode estar finalizado</li>
     * <li>Se o documento for interno produzido, usurio tem de ser: 1) da
     * lotao cadastrante do documento, 2) o subscritor do documento ou 3) o
     * titular do documento. <b>Obs.: por que a origem do documento est sendo
     * considerada nesse caso?</b></li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeFinalizar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (mob.doc().isFinalizado())
            return false;
        if (lotaTitular.isFechada())
            return false;
        if (mob.isPendenteDeAnexacao())
            return false;
        if (mob.doc().getExTipoDocumento().getIdTpDoc() != 2 && mob.doc().getExTipoDocumento().getIdTpDoc() != 3)
            if (!mob.doc().getLotaCadastrante().equivale(lotaTitular)
                    && (mob.doc().getSubscritor() != null && !mob.doc().getSubscritor().equivale(titular))
                    && (mob.doc().getTitular() != null && !mob.doc().getTitular().equivale(titular))
                    && !mob.getExDocumento().temPerfil(titular, lotaTitular, ExPapel.PAPEL_GESTOR))
                return false;
        return getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_FINALIZAR);
    }

    /**
     * Retorna se  possvel que o usurio finalize o documento e assine
     * digitalmente numa nica operao. Os requisitos so os mesmos que tm de
     * ser cumpridos para se poder finalizar
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeFinalizarAssinar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob)
            throws Exception {
        return podeFinalizar(titular, lotaTitular, mob) && mob.doc().isEletronico();

    }

    /**
     * Retorna se  possvel incluir cossignatrio no documento que contm o
     * mbil passado por parmetro. O documento tem de atender as seguintes
     * condies:
     * <ul>
     * <li>No pode estar cancelado</li>
     * <li>Sendo documento fsico, no pode estar finalizado</li>
     * <li>Sendo documento digital, no pode estar assinado</li>
     * <li>Lotao do usurio tem de ser a lotao cadastrante do documento</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeIncluirCosignatario(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (mob.doc().isCancelado())
            return false;
        if (mob.doc().isFinalizado() && !mob.doc().isEletronico())
            return false;
        if (mob.doc().isAssinado() || mob.doc().isEletronicoEPossuiPeloMenosUmaAssinaturaDigital()
                || mob.doc().isEletronicoEPossuiPeloMenosUmaAssinaturaComSenha())
            return false;
        if (!mob.doc().getLotaCadastrante().equivale(lotaTitular))
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_INCLUSAO_DE_COSIGNATARIO,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel incluir o mbil em edital de eliminao, de acordo
     * com as condies a seguir:
     * <ul>
     * <li>Mbil tem de ser via ou geral de processo</li>
     * <li>Mbil tem de estar em arquivo corrente ou intermedirio</li>
     * <li>PCTT tem de prever, para o mbil, destinao final Eliminao</li>
     * <li>Mbil no pode estar arquivado permanentemente</li>
     * <li>Documento a que o mbil pertence tem de ser digital ou estar na
     * lotao titular</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeIncluirEmEditalEliminacao(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) throws Exception {

        if (!(mob.isVia() || mob.isGeralDeProcesso()) || mob.doc().isSemEfeito() || mob.isEliminado())
            return false;

        ExMobil mobVerif = mob;

        if (mob.isGeralDeProcesso())
            mobVerif = mob.doc().getUltimoVolume();

        return mobVerif != null && (mobVerif.isArquivadoCorrente() || mobVerif.isArquivadoIntermediario())
                && !mobVerif.isArquivadoPermanente() && mobVerif.isDestinacaoEliminacao()
                && (lotaTitular.equivale(mob.getUltimaMovimentacaoNaoCancelada().getLotaResp())
                        || mob.doc().isEletronico())
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_INCLUSAO_EM_EDITAL_DE_ELIMINACAO,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel junta este mbil a outro. Seguem as regras:
     * <ul>
     * <li>Mbil no pode estar cancelado</li>
     * <li>Volume no pode estar encerrado</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o mbil/usurio</li>
     * <li>Documento tem de estar assinado</li>
     * <li>Mbil no pode estar juntado <b>(mas pode ser juntado estando
     * apensado?)</b></li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeJuntar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!mob.isVia())
            return false;

        if (mob.isPendenteDeAnexacao())
            return false;

        return !mob.isCancelada() && !mob.isVolumeEncerrado() && !mob.isEmTransito()
                && podeMovimentar(titular, lotaTitular, mob)

                && mob.doc().isAssinado() && !mob.isJuntado() && !mob.isApensado() && !mob.isArquivado()
                && !mob.isSobrestado() && !mob.doc().isSemEfeito()
                && podePorConfiguracao(titular, lotaTitular, ExTipoMovimentacao.TIPO_MOVIMENTACAO_JUNTADA,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR, null);

        // return true;
    }

    /**
     * Retorna se  possvel apensar este mbil a outro, conforme as regras:
     * <ul>
     * <li>Mbil precisa ser via ou volume</li>
     * <li>Mbil no pode estar cancelado</li>
     * <li>Mbil no pode estar em trnsito <b>(o que  isEmTransito?)</b></li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o mbil/usurio</li>
     * <li>Documento tem de estar assinado</li>
     * <li>Mbil no pode estar juntado</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeApensar(DpPessoa titular, DpLotacao lotaTitular, ExMobil mob) {

        if (!mob.isVia() && !mob.isVolume())
            return false;

        return !mob.isCancelada() && !mob.doc().isSemEfeito() && !mob.isEmTransito()
                && podeMovimentar(titular, lotaTitular, mob) && mob.doc().isAssinado() && !mob.isApensado()
                && !mob.isJuntado() && !mob.isArquivado() && !mob.isSobrestado()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_APENSACAO, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel desapensar este mbil de outro, conforme as
     * seguintes condies para o mbil:
     * <ul>
     * <li>Precisa ser via ou volume</li>
     * <li>Precisa ter movimentao no cancelada</li>
     * <li>Precisa estar apensado</li>
     * <li>No pode estar em trnsito <b>(o que  isEmTransito?)</b></li>
     * <li>No pode estar cancelado</li>
     * <li>No pode estar em algum arquivo</li>
     * <li>No pode estar juntado <b>(mas pode ser juntado estando
     * apensado?)</b></li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o mbil/usurio</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeDesapensar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        final ExMovimentacao ultMovNaoCancelada = mob.getUltimaMovimentacaoNaoCancelada();

        if (!mob.isVia() && !mob.isVolume())
            return false;

        if (ultMovNaoCancelada == null)
            return false;

        if (mob.doc().isEletronico() && mob.isVolumeApensadoAoProximo())
            return false;

        if (!mob.isApensado() || mob.isEmTransito() || mob.isCancelada() || mob.isArquivado()
                || !podeMovimentar(titular, lotaTitular, mob) || mob.isJuntado())
            return false;

        return getConf().podePorConfiguracao(titular, lotaTitular,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESAPENSACAO, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se o usurio tem a permisso bsica para movimentar o documento.
     * Mtodo usado como premissa para vrias outras permisses de movimentao.
     * Regras:
     * <ul>
     * <li>Se mbil  geral, <i>podeMovimentar()</i> tem de ser verdadeiro para
     * algum mbil do mesmo documento</li>
     * <li>Mbil tem de ser geral, via ou volume</li>
     * <li>Mbil tem de de ter alguma movimentao no cancelada</li>
     * <li><b>Mbil no pode estar cancelado nem aberto</b></li>
     * <li>Usurio tem de ser da lotao atendente definida na ltima
     * movimentao no cancelada</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     */
    public boolean podeMovimentar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!podeSerMovimentado(mob))
            return false;

        if (mob.isGeral()) {
            for (ExMobil m : mob.doc().getExMobilSet()) {
                if (!m.isGeral() && podeMovimentar(titular, lotaTitular, m))
                    return true;
            }
            return false;
        }

        final ExMovimentacao exMov = mob.getUltimaMovimentacaoNaoCancelada();
        if (exMov == null) {
            return false;
        }

        /*
         * Orlando: Inclui a condio "&& !exMov.getResp().equivale(titular))"
         * no IF ,abaixo, para permitir que um usurio possa transferir quando
         * ele for o atendente do documento, mesmo que ele no esteja na lotao
            
         * do documento
         */

        if (exMov.getLotaResp() != null && !exMov.getLotaResp().equivale(lotaTitular)) {
            return false;
        }

        return getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    public boolean podeSerMovimentado(final ExMobil mob) {
        if (mob.doc().isSemEfeito())
            return false;

        if (mob.isGeral()) {
            for (ExMobil m : mob.doc().getExMobilSet()) {
                if (!m.isGeral() && podeSerMovimentado(m))
                    return true;
            }
            return false;
        }
        if (!mob.isVia() && !mob.isVolume())
            return false;

        final ExMovimentacao exMov = mob.getUltimaMovimentacaoNaoCancelada();
        if (exMov == null) {
            return false;
        }
        if (mob.isCancelada() || !mob.doc().isFinalizado())
            return false;

        return true;
    }

    /**
     * Retorna se o usurio tem  o atendente do documento. Regras:
     * <ul>
     * <li>Se mbil  geral, <i>isAtendente()</i> tem de ser verdadeiro para
     * algum mbil do mesmo documento</li>
     * <li>Mbil tem de ser geral, via ou volume</li>
     * <li>Mbil tem de de ter alguma movimentao no cancelada</li>
     * <li><b>Mbil no pode estar cancelado</b></li>
     * <li>Usurio tem de ser da lotao atendente definida na ltima
     * movimentao no cancelada, ou no documento se ainda no for finalizado.</li>
     * </ul>
     */
    public static boolean isAtendente(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob)
            throws Exception {
        if (mob.isGeral()) {
            for (ExMobil m : mob.doc().getExMobilSet()) {
                if (!m.isGeral() && isAtendente(titular, lotaTitular, m))
                    return true;
            }
            return false;
        }
        if (!mob.isVia() && !mob.isVolume())
            return false;

        final ExMovimentacao exMov = mob.getUltimaMovimentacaoNaoCancelada();
        if (exMov == null) {
            return false;
        }
        if (mob.isCancelada())
            return false;

        DpLotacao lot = exMov.getLotaResp();

        if (!mob.doc().isFinalizado())
            lot = mob.doc().getLotaCadastrante();

        if (lot != null && !lot.equivale(lotaTitular))
            // && !exMov.getCadastrante().getLotacao().equivale(lotaTitular))
            return false;

        return true;
    }

    public static DpResponsavel getAtendente(final ExMobil mob) throws Exception {
        if (mob.isGeral()) {
            for (ExMobil m : mob.doc().getExMobilSet()) {
                if (!m.isGeral() && getAtendente(m) != null)
                    return getAtendente(m);
            }
            return null;
        }
        if (!mob.isVia() && !mob.isVolume())
            return null;

        final ExMovimentacao exMov = mob.getUltimaMovimentacaoNaoCancelada();
        if (exMov == null) {
            return null;
        }
        if (mob.isCancelada())
            return null;

        if (!mob.doc().isFinalizado())
            return mob.doc().getLotaCadastrante();

        DpLotacao lot = exMov.getLotaResp();
        return lot;
    }

    /**
     * Retorna se  possvel refazer um documento. Tm de ser satisfeitas as
     * seguintes condies:
     * <ul>
     * <li>Documento tem de estar finalizado</li>
     * <li>Usurio tem de ser o subscritor ou o titular do documento ou ser da
     * lotao cadastrante do documento</li>
     * <li>Documento no pode estar assinado, a no ser que seja dos tipos
     * externo ou interno importado, que so naturalmente considerados
     * assinados. Porm, se for documento de um desses tipos, no pode haver pdf
     * anexado <b>(verificar por qu)</b></li>
     * <li>Documento tem de possuir via no cancelada ou volume no cancelado</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeRefazer(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        return (mob.doc().isFinalizado()) && ((mob.doc().getLotaCadastrante().equivale(lotaTitular)
                || (mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular))
                || (mob.doc().getTitular() != null && mob.doc().getTitular().equivale(titular)))
                && (!mob.doc().isAssinado()
                        || (mob.doc().getExTipoDocumento().getIdTpDoc() != 1L && !mob.doc().hasPDF()))
                && (mob.doc().getNumUltimaViaNaoCancelada() != 0
                        || (mob.doc().getUltimoVolume() != null && !mob.doc().getUltimoVolume().isCancelada())))
                && getConf().podePorConfiguracao(titular, lotaTitular, CpTipoConfiguracao.TIPO_CONFIG_REFAZER);
    }

    /**
     * Retorna se  possvel indicar um mbil para guarda permanente. Tm de ser
     * satisfeitas as seguintes condies:
     * <ul>
     * <li>Documento tem de estar assinado</li>
     * <li>Mbil tem de ser via ou geral de processo</li>
     * <li>Mbil no pode estar cancelado</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>Mbil no pode estar juntado</li>
     * <li>Mbil no pode ter sido j indicado para guarda permanente</li>
     * <li>Mbil no pode ter sido arquivado permanentemente nem eliminado</li>
     * <li>No pode haver configurao impeditiva</li>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeIndicarPermanente(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (mob.isPendenteDeAnexacao())
            return false;

        return (mob.doc().isAssinado() && (mob.isVia() || mob.isGeralDeProcesso()) && !mob.isCancelada()
                && !mob.isEmTransito() && !mob.isJuntado() && podeMovimentar(titular, lotaTitular, mob)
                && !mob.isindicadoGuardaPermanente() && !mob.isArquivadoPermanente() && !mob.isEmEditalEliminacao()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_INDICACAO_GUARDA_PERMANENTE,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR));
    }

    /**
     * Retorna se  possvel reclassificar um documento. Tm de ser satisfeitas
     * as seguintes condies:
     * <ul>
     * <li>Documento tem de estar assinado</li>
     * <li>Mbil tem de ser geral</li>
     * <li>Mbil no pode ter sido eliminado</li>
     * <li>Mbil no pode estar cancelado</li>
     * <li>No pode haver configurao impeditiva</li>
     ** 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeReclassificar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        return (mob.doc().isAssinado() && mob.isGeral() && !mob.isCancelada() && !mob.isEliminado()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_RECLASSIFICACAO,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR));
    }

    /**
     * Retorna se  possvel avaliar um documento. Tm de ser satisfeitas as
     * seguintes condies:
     * <ul>
     * <li>Documento tem de estar assinado</li>
     * <li>Mbil tem de ser geral</li>
     * <li>Mbil no pode ter sido eliminado</li>
     * <li>Mbil no pode estar cancelado</li>
     * <li>No pode haver configurao impeditiva</li>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAvaliar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        return (mob.doc().isAssinado() && mob.isGeral() && !mob.isCancelada() && !mob.isEliminado()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_AVALIACAO, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR));
    }

    /**
     * Retorna se  possvel reverter a indicao de um mbil para guarda
     * permanente. Tm de ser satisfeitas as seguintes condies:
     * <ul>
     * <li>Mbil tem de estar indicado para guarda permanente</li>
     * <li>Mbil tem de ser via ou geral de processo</li>
     * <li>Mbil no pode estar cancelado</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>Mbil no pode estar juntado</li>
     * <li>Mbil no pode ter sido arquivado permanentemente nem eliminado</li>
     * <li>No pode haver configurao impeditiva</li>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeReverterIndicacaoPermanente(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        return (mob.isindicadoGuardaPermanente() && (mob.isVia() || mob.isGeralDeProcesso()) && !mob.isJuntado()
                && !mob.isArquivadoPermanente() && !mob.isCancelada() && !mob.isEmTransito()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_REVERSAO_INDICACAO_GUARDA_PERMANENTE,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR));
    }

    /**
     * Retorna se  possvel retirar um mbil de edital de eliminao. Tm de
     * ser satisfeitas as seguintes condies:
     * <ul>
     * <li>Mbil no pode ter sido eliminado</li>
     * <li>Mbil tem de estar em edital de eliminao</li>
     * <li>Edital contendo o mbil precisa estar assinado</li>
     * <li>Pessoa a fazer a retirada tem de ser o subscritor ou titular do
     * edital</li>
     * <li>No pode haver configurao impeditiva</li>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeRetirarDeEditalEliminacao(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        if (mob.isEliminado())
            return false;

        ExMovimentacao movInclusao = mob.getUltimaMovimentacaoNaoCancelada(
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_INCLUSAO_EM_EDITAL_DE_ELIMINACAO,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_RETIRADA_DE_EDITAL_DE_ELIMINACAO);

        if (movInclusao == null)
            return false;

        ExDocumento edital = movInclusao.getExMobilRef().getExDocumento();

        if (!edital.isAssinado())
            return false;

        if (edital.getSubscritor() == null)
            return lotaTitular.equivale(edital.getLotaCadastrante());
        else
            return titular.equivale(edital.getSubscritor()) || titular.equivale(edital.getTitular());

    }

    /**
     * Retorna se a lotao ou pessoa tem permisso para receber documento
     * 
     * @param pessoa
     * @param lotacao   
     * @return
     * @throws Exception
     */
    public boolean podeReceberPorConfiguracao(final DpPessoa pessoa, final DpLotacao lotacao) {

        return getConf().podePorConfiguracao(pessoa, lotacao, ExTipoMovimentacao.TIPO_MOVIMENTACAO_RECEBIMENTO,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel receber o mbil. conforme as regras a seguir:
     * <ul>
     * <li>Mbil tem de ser via ou volume</li>
     * <li>Mbil no pode estar cancelado</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>Mbil tem de estar em trnsito</li>
     * <li>Lotao do usurio tem de ser a do atendente definido na ltima
     * movimentao</li>
     * <li>Se o mbil for eletrnico, no pode estar marcado como Despacho
     * pendente de assinatura, ou seja, mbil em que tenha havido despacho ou
     * despacho com transferncia no pode ser recebido antes de assinado o
     * despacho</li>
     * </ul>
     * <b>Obs.: Teoricamente, qualquer pessoa pode receber mbil transferido
     * para rgo externo</b>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeReceber(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        if (!(mob.isVia() || mob.isVolume()))
            return false;
        final ExMovimentacao exMov = mob.getUltimaMovimentacaoNaoCancelada();

        if (mob.isCancelada() || mob.isSobrestado() || (!mob.isEmTransito()))
            return false;
        else if (!mob.isEmTransitoExterno()) {
            if (!exMov.getLotaResp().equivale(lotaTitular))
                return false;
        }

        // Orlando: O IF abaixo foi includo para no permitir que o documento
        // seja recebido aps ter sido transferido para um rgo externo,
        // inclusive no caso de despacho com transferncia externa.
        if (mob.isEmTransitoExterno())
            return false;

        // Verifica se o despacho j est assinado, em caso de documentos
        // eletrnicos
        if (mob.doc().isEletronico()) {
            for (CpMarca marca : mob.getExMarcaSet()) {
                if (marca.getCpMarcador().getIdMarcador() == CpMarcador.MARCADOR_DESPACHO_PENDENTE_DE_ASSINATURA)
                    return false;
            }
        }

        return getConf().podePorConfiguracao(titular, lotaTitular, ExTipoMovimentacao.TIPO_MOVIMENTACAO_RECEBIMENTO,
                CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel receber o mbil eletronicamente, de acordo com as
     * regras a seguir, <b>que deveriam ser parecidas com as de podeReceber(),
     * para no haver incoerncia</b>:
     * <ul>
     * <li>Mbil tem de ser via ou volume</li>
     * <li>A ltima movimentao no cancelada do mbil no pode ser
     * transferncia externa <b>(regra falha, pois pode ser feita anotao)</b></li>
     * <li>Mbil no pode estar marcado como "Despacho pendente de assinatura",
     * ou seja, tendo havido despacho ou despacho com transferncia, este
     * precisa ter sido assinado para haver transferncia</li>
     * <li>Se houver pessoa atendente definida na ltima movimentao no
     * cancelada, o usurio tem de ser essa pessoa</li>
     * <li>No havendo pessoa atendente definida na ltima movimentao, apenas
     * lotao atendente, a lotao do usurio tem de ser essa</li>
     * <li>Documento tem de ser eletrnico <b>(melhor se fosse verificado no
     * incio)</b></li>
     * <li>Mbil tem de estar em trnsito <b>(melhor se fosse verificado no
     * incio)</b></li>
     * <li>No pode haver configurao impeditiva para recebimento (no para
     * recebimento eletrnico)</li>
     * </ul>
     * 
     * @param cadastrante
     * @param lotaCadastrante
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeReceberEletronico(DpPessoa cadastrante, DpLotacao lotaCadastrante, final ExMobil mob) {
        if (!(mob.isVia() || mob.isVolume()))
            return false;
        ExMovimentacao ultMov = mob.getUltimaMovimentacaoNaoCancelada();
        if (ultMov == null)
            return false;
        if (ultMov.getExTipoMovimentacao()
                .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_TRANSFERENCIA_EXTERNA
                || ultMov.getExTipoMovimentacao()
                        .getIdTpMov() == ExTipoMovimentacao.TIPO_MOVIMENTACAO_DESPACHO_TRANSFERENCIA_EXTERNA)
            return false;
        // Verifica se o despacho j est assinado
        for (CpMarca marca : mob.getExMarcaSet()) {
            if (marca.getCpMarcador().getIdMarcador() == CpMarcador.MARCADOR_DESPACHO_PENDENTE_DE_ASSINATURA)
                return false;
        }

        if ((ultMov.getResp() != null && !ultMov.getResp().equivale(cadastrante)) || (ultMov.getResp() == null
                && ultMov.getLotaResp() != null && !ultMov.getLotaResp().equivale(lotaCadastrante)))
            return false;
        if (!mob.doc().isEletronico() || !mob.isEmTransito())
            return false;
        return getConf().podePorConfiguracao(cadastrante, lotaCadastrante,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_RECEBIMENTO, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel vincular este mbil a outro, conforme as regras:
     * <ul>
     * <li>Mbil tem de ser via ou volume</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o mbil/usurio</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>Mbil no pode estar juntado</li>
     * <li>Mbil no pode estar cancelado</li>
     * <li>Mbil no pode ter sido eliminado</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeReferenciar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!(mob.isVia() || mob.isVolume()))
            return false;

        return !mob.isEmTransito() && podeMovimentar(titular, lotaTitular, mob) && !mob.isJuntado()
                && !mob.isEliminado() && !mob.doc().isCancelado() && !mob.doc().isSemEfeito()
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_REFERENCIA, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);

        // return true;
    }

    /**
     * Retorna se  possvel registrar assinatura manual de documento que contm
     * o mbil passado por parmetro. As regras so as seguintes:
     * <ul>
     * <li>Mbil tem de ser geral</li>
     * <li>No pode ser mbil de processo interno importado</li>
     * <li>No pode ser mbil de documento externo</li>
     * <li>Documento no pode estar cancelado</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro ou usurio tem de ser o
     * prprio subscritor ou titular do documento</li>
     * <li>Documento no pode ser eletrnico</li>
     * <li>Documento tem de estar finalizado</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>Mbil no pode ter sido eliminado</li>
     * <li>No pode haver configurao impeditiva</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeRegistrarAssinatura(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        if (!mob.isGeral())
            return false;
        if (mob.isArquivado() || mob.isEliminado())
            return false;
        if (mob.getExDocumento().isProcesso() && mob.getExDocumento().getExTipoDocumento()
                .getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_INTERNO_ANTIGO)
            return false;
        if (mob.doc().getExTipoDocumento().getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_EXTERNO
                || mob.doc().isCancelado())
            return false;
        return ((mob.doc().getSubscritor() != null && mob.doc().getSubscritor().equivale(titular))
                || (mob.doc().getTitular() != null && mob.doc().getTitular().equivale(titular))
                || podeMovimentar(titular, lotaTitular, mob))
                /*
                 * || (ultMovNaoCancelada .getExEstadoDoc().getIdEstadoDoc() ==
                 * ExEstadoDoc.ESTADO_DOC_EM_ANDAMENTO || ultMovNaoCancelada
                 * .getExEstadoDoc().getIdEstadoDoc() ==
                 * ExEstadoDoc.ESTADO_DOC_PENDENTE_DE_ASSINATURA)
                 */
                && !mob.doc().isEletronico()

                && (mob.doc().isFinalizado())
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_REGISTRO_ASSINATURA_DOCUMENTO,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel agendar publicao no Boletim.  necessrio que no
     * sejam ainda 17 horas e que <i>podeBotaoAgendarPublicacaoBoletim()</i>
     * seja verdadeiro para este mbil e usurio.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAgendarPublicacaoBoletim(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) throws Exception {

        GregorianCalendar agora = new GregorianCalendar();
        agora.setTime(new Date());
        return podeBotaoAgendarPublicacaoBoletim(titular, lotaTitular, mob) && agora.get(Calendar.HOUR_OF_DAY) < 17;
    }

    /**
     * Retorna se  possvel exibir a opo para agendar publicao no Boletim.
     * Seguem as regras:
     * <ul>
     * <li>Mbil no pode ser geral</li>
     * <li>Documento tem de estar finalizado</li>
     * <li>Documento tem de ser do tipo interno produzido</li>
     * <li><i>podeGerenciarPublicacaoBoletimPorConfiguracao()</i> ou
     * <i>podeMovimentar()</i>tem de ser verdadeiro para o usurio</li>
     * <li>Documento no pode j ter sido publicado em boletim</li>
     * <li>Publicao no boletim no pode ter sido j agendada para o documento</li>
     * <li>Documento tem de estar assinado</li>
     * <li>Documento no pode ter sido eliminado</li>
     * <li>Mbil no pode estar em algum arquivo</li>
     * <li>No pode haver configurao impeditiva</li>
     * 
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeBotaoAgendarPublicacaoBoletim(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {
        if (!mob.isGeral())
            return false;

        if (!mob.doc().isFinalizado())
            return false;
        if (mob.doc().isEliminado())
            return false;
        if (mob.doc().getExTipoDocumento().getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_EXTERNO)
            return false;
        if (mob.doc().getExTipoDocumento().getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_INTERNO_ANTIGO)
            return false;
        boolean gerente = podeGerenciarPublicacaoBoletimPorConfiguracao(titular, lotaTitular, mob);
        return (podeMovimentar(titular, lotaTitular, mob) || gerente)
                // && !mob.doc().isEletronico()
                && !mob.doc().isBoletimPublicado() && mob.doc().isAssinado()
                && !mob.doc().isPublicacaoBoletimSolicitada() && !mob.isArquivado()
                && (getConf().podePorConfiguracao(titular, lotaTitular, mob.doc().getExModelo(),
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_AGENDAMENTO_DE_PUBLICACAO_BOLETIM,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR) || gerente);
    }

    /**
     * Retorna se  possvel alterar o nvel de accesso do documento. 
     * necessrio apenas que o usurio possa acessar o documento e que no haja
     * configurao impeditiva. <b>Obs.: No  verificado se
     * <i>podeMovimentar()</i></b>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeRedefinirNivelAcesso(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        if (mob.doc().isBoletimPublicado() || mob.doc().isDJEPublicado()) {
            if (podeAtenderPedidoPublicacao(titular, lotaTitular, mob)
                    || podeGerenciarPublicacaoBoletimPorConfiguracao(titular, lotaTitular, mob))
                return true;

            return false;
        }

        return !mob.isEliminado() && podeAcessarDocumento(titular, lotaTitular, mob)
                && podeMovimentar(titular, lotaTitular, mob)
                && getConf().podePorConfiguracao(titular, lotaTitular,
                        ExTipoMovimentacao.TIPO_MOVIMENTACAO_REDEFINICAO_NIVEL_ACESSO,
                        CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    /**
     * Retorna se  possvel que algum mbil seja juntado a este, segundo as
     * seguintes regras:
     * <ul>
     * <li>No pode estar cancelado</li>
     * <li>Volume no pode estar encerrado</li>
     * <li>No pode estar em algum arquivo</li>
     * <li>No pode estar juntado</li>
     * <li>No pode estar em trnsito</li>
     * <li><i>podeMovimentar()</i> precisa retornar verdadeiro para ele</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeSerJuntado(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        return !mob.isCancelada() && !mob.isVolumeEncerrado() && mob.doc().isAssinado() && !mob.isJuntado()
                && !mob.isEmTransito() && !mob.isArquivado() && podeMovimentar(titular, lotaTitular, mob);
    }

    /**
     * Retorna se  possvel a uma lotao, com base em configurao, receber
     * mbil de documento no assinado. No  aqui verificado se o mbil est
     * realmente pendente de assinatura
     * 
     * @param pessoa
     * @param lotacao
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeReceberDocumentoSemAssinatura(final DpPessoa pessoa, final DpLotacao lotacao,
            final ExMobil mob) {
        return getConf().podePorConfiguracao(pessoa, lotacao,
                CpTipoConfiguracao.TIPO_CONFIG_RECEBER_DOC_NAO_ASSINADO);
    }

    /**
     * Retorna se  possvel fazer transferncia. As regras so as seguintes
     * para este mbil: <ul <li>Precisa ser via ou volume (no pode ser geral)</li>
     * <li>No pode estar em trnsito</li> <li>No pode estar juntado.</li> <li>
     * No pode estar em arquivo permanente.</li> <li><i>podeMovimentar()</i>
     * precisa retornar verdadeiro para ele</li> <li>No pode haver configurao
     * impeditiva</li> </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeTransferir(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (!podeSerTransferido(mob))
            return false;

        return podeMovimentar(titular, lotaTitular, mob) && getConf().podePorConfiguracao(titular, lotaTitular,
                ExTipoMovimentacao.TIPO_MOVIMENTACAO_TRANSFERENCIA, CpTipoConfiguracao.TIPO_CONFIG_MOVIMENTAR);
    }

    public boolean podeSerTransferido(final ExMobil mob) {
        if (mob.isPendenteDeAnexacao())
            return false;

        return (mob.isVia() || mob.isVolume()) && !mob.isEmTransito() && !mob.isJuntado() && !mob.isArquivado()
                && (mob.doc().isAssinado()
                        || (mob.doc().getExTipoDocumento().getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_EXTERNO)
                        || (mob.doc().isProcesso() && mob.doc().getExTipoDocumento()
                                .getIdTpDoc() == ExTipoDocumento.TIPO_DOCUMENTO_INTERNO_ANTIGO))
                && !mob.isEmEditalEliminacao() && !mob.isSobrestado() && !mob.doc().isSemEfeito()
                && podeSerMovimentado(mob);
        // return true;
    }

    /**
     * Retorna se  possvel fazer vinculao deste mobil a outro, conforme as
     * seguintes regras para <i>este</i> mbil:
     * <ul>
     * <li>Precisa ser via ou volume (no pode ser geral)</li>
     * <li>No pode estar em trnsito</li>
     * <li>No pode estar juntado.</li>
     * <li><i>podeMovimentar()</i> precisa retornar verdadeiro para ele</li>
     * </ul>
     * No  levada em conta, aqui, a situao do mobil ao qual se pertende
     * vincular.
     * 
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeVincular(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob)
            throws Exception {

        if (!(mob.isVia() || mob.isVolume()))
            return false;

        return !mob.isEmTransito() && podeMovimentar(titular, lotaTitular, mob) && !mob.isJuntado();

        // return true;

    }

    public boolean podeCancelarVinculacaoDocumento(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob, final ExMovimentacao mov) {

        if (mov.isCancelada())
            return false;

        if ((mov.getCadastrante() != null && mov.getCadastrante().equivale(titular))
                || (mov.getCadastrante() == null && mov.getLotaCadastrante().equivale(lotaTitular)))
            return true;

        if ((mov.getSubscritor() != null && mov.getSubscritor().equivale(titular))
                || (mov.getSubscritor() == null && mov.getLotaSubscritor().equivale(lotaTitular)))
            return true;

        if ((mov.getLotaSubscritor().equivale(lotaTitular)))
            return true;

        return getConf().podePorConfiguracao(titular, lotaTitular, mov.getIdTpMov(),
                CpTipoConfiguracao.TIPO_CONFIG_CANCELAR_MOVIMENTACAO);
    }

    /**
     * Retorna se  possvel visualizar impresso do mbil. Sempre retorna
     * <i>true</i>, a no ser que o documento esteja finalizado e o mobil em
     * questo no seja via ou volume. isso impede que se visualize impresso do
     * mobil geral aps a finalizao.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeVisualizarImpressao(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {
        if (!mob.isVia() && !mob.isVolume() && mob.doc().isFinalizado())

            return false;
        return !mob.isEliminado();/*
                                  * if ((mob.doc().getConteudo() == null ||
                                  * ExCompetenciaBL.viaCancelada(titular,
                                  * lotaTitular, doc, numVia))) return false;
                                      
                                  * return true;
                                  */
    }

    /**
     * Retorna se  possvel visualizar impresso do documento em questo e de
     * todos os filhos, com base na permisso para visualizao da impresso de
     * cada um dos filhos.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public boolean podeVisualizarImpressaoCompleta(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {
        Set<ExDocumento> filhos = mob.getExDocumentoFilhoSet();
        return podeVisualizarImpressao(titular, lotaTitular, mob) && filhos != null && filhos.size() > 0;
    }

    /*
     * public boolean podeAtenderPedidoPublicacaoPorConfiguracao( DpPessoa
     * titular, DpLotacao lotaTitular, final ExMobil mob) throws Exception { if
     * (lotaTitular == null) return false; return
     * getConf().podePorConfiguracao(titular, lotaTitular,
     * CpTipoConfiguracao.TIPO_CONFIG_ATENDER_PEDIDO_PUBLICACAO); }
     */

    /**
     * Retorna se  possvel, com base em configurao, utilizar rotina para
     * redefinio de permisses de publicao no DJE. No  utilizado o
     * parmetro mob. <b>Ateno: Mtodo em desuso.</b>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeDefinirPublicadoresPorConfiguracao(DpPessoa titular, DpLotacao lotaTitular,
            final ExMobil mob) throws Exception {
        if (lotaTitular == null)
            return false;
        return getConf().podePorConfiguracao(titular, lotaTitular,
                CpTipoConfiguracao.TIPO_CONFIG_DEFINIR_PUBLICADORES);

    }

    /**
     * Retorna se  possvel, com base em configurao, utilizar rotina para
     * redefinio de permisses de publicao no Boletim. No  utilizado o
     * parmetro mob.
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeGerenciarPublicacaoBoletimPorConfiguracao(DpPessoa titular, DpLotacao lotaTitular,
            final ExMobil mob) {
        if (lotaTitular == null)
            return false;
        return getConf().podePorConfiguracao(titular, lotaTitular,
                CpTipoConfiguracao.TIPO_CONFIG_GERENCIAR_PUBLICACAO_BOLETIM);
    }

    /**
     * Mtodo genrico que recebe funo por String e concatena com o mtodo de
     * checagem de permisso correspondente. Por exemplo, para a funo juntar,
     *  invocado <i>podeJuntar()</i>
     * 
     * @param funcao
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     */
    public static boolean testaCompetencia(final String funcao, final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {
        final Class[] classes = new Class[] { DpPessoa.class, DpLotacao.class, ExMobil.class };
        Boolean resposta = false;
        try {
            final Method method = ExCompetenciaBL.class.getDeclaredMethod(
                    "pode" + funcao.substring(0, 1).toUpperCase() + funcao.substring(1), classes);
            resposta = (Boolean) method.invoke(Ex.getInstance().getComp(),
                    new Object[] { titular, lotaTitular, mob });
        } catch (final Exception e) {
            e.printStackTrace();
        }

        return resposta.booleanValue();
    }

    /**
     * Mtodo genrico que recebe funo por String e concatena com o mtodo de
     * checagem de permisso correspondente. Por exemplo, para a funo
     * excluirAnexo,  invocado <i>podeExcluirAnexo()</i>
     * 
     * @param funcao
     * @param titular
     * @param lotaTitular
     * @param mob
     * @param mov
     * @return
     */
    public static boolean testaCompetenciaMov(final String funcao, final DpPessoa titular,
            final DpLotacao lotaTitular, final ExMobil mob, final ExMovimentacao mov) {
        final Class[] classes = new Class[] { DpPessoa.class, DpLotacao.class, ExMobil.class,
                ExMovimentacao.class };
        Boolean resposta = false;
        try {
            /*
             * final Method method = ExCompetenciaBL.class.getDeclaredMethod(
             * "pode" + funcao.substring(0, 1).toUpperCase() +
             * funcao.substring(1), classes);
             */
            ExCompetenciaBL comp = Ex.getInstance().getComp();
            final Method method = comp.getClass().getDeclaredMethod(
                    "pode" + funcao.substring(0, 1).toUpperCase() + funcao.substring(1), classes);

            resposta = (Boolean) method.invoke(comp, new Object[] { titular, lotaTitular, mob, mov });
        } catch (final Exception e) {
            e.printStackTrace();
        }

        return resposta.booleanValue();
    }

    /**
     * 
     */
    public boolean podeDesfazerCancelamentoDocumento(final DpPessoa titular, final DpLotacao lotaTitular,
            final ExMobil mob) {

        ExDocumento documento = mob.getDoc();

        if (documento.isEletronico() && documento.isCancelado()
                && (documento.getLotaCadastrante().equivale(lotaTitular)
                        || documento.getSubscritor().equivale(titular)))
            return true;

        return false;
    }

    /**
     * 
     */
    public boolean podeReiniciarNumeracao(ExDocumento doc) throws Exception {
        if (doc == null || doc.getOrgaoUsuario() == null || doc.getExFormaDocumento() == null)
            return false;

        return getConf().podePorConfiguracao(doc.getOrgaoUsuario(), doc.getExFormaDocumento(),
                CpTipoConfiguracao.TIPO_CONFIG_REINICIAR_NUMERACAO_TODO_ANO);
    }

    /**
        
        
     * Retorna se  possvel autuar um expediente, com base nas seguintes
     * regras:
     * <ul>
     * <li>Documento tem de ser expediente</li>
     * <li>Documento tem de estar assinado</li>
     * <li>Documento no pode estar sem efeito</li>
     * <li>Mbil no pode ser geral</li>
     * <li>Mbil no pode estar em edital de eliminao</li>
     * <li>Mbil no pode estar juntado</li>
     * <li>Mbil no pode estar apensado</li>
     * <li>Mbil no pode estar em trnsito</li>
     * <li>Mbil no pode estar arquivado permanentemente</li>
     * <li><i>podeMovimentar()</i> tem de ser verdadeiro para o usurio / mbil</li>
     * </ul>
     * 
     * @param titular
     * @param lotaTitular
     * @param mob
     * @return
     * @throws Exception
     */
    public boolean podeAutuar(final DpPessoa titular, final DpLotacao lotaTitular, final ExMobil mob) {

        if (mob.isPendenteDeAnexacao())
            return false;

        if (mob.doc().isSemEfeito())
            return false;

        if (mob.isEmEditalEliminacao() || mob.isArquivadoPermanente())
            return false;

        if (mob.isJuntado())
            return false;

        if (mob.isApensado())
            return false;

        if (mob.isArquivado())
            return false;

        if (mob.isSobrestado())
            return false;

        final boolean podeMovimentar = podeMovimentar(titular, lotaTitular, mob);

        return (!mob.isGeral() && mob.doc().isExpediente() && mob.doc().isAssinado() && !mob.isEmTransito()
                && podeMovimentar);

    }
}