package br.com.centralit.citsmart.rest.v3.operation;

import java.sql.Date;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.bind.JAXBException;

import org.apache.commons.lang.StringUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import br.com.centralit.bpm.dto.AtribuicaoFluxoDTO;
import br.com.centralit.bpm.negocio.ItemTrabalho;
import br.com.centralit.bpm.negocio.Tarefa;
import br.com.centralit.bpm.util.Enumerated.StatusWorkItem;
import br.com.centralit.citcorpore.bean.AcordoServicoContratoDTO;
import br.com.centralit.citcorpore.bean.AprovacaoSolicitacaoServicoDTO;
import br.com.centralit.citcorpore.bean.CategoriaServicoDTO;
import br.com.centralit.citcorpore.bean.ContratoDTO;
import br.com.centralit.citcorpore.bean.EmpregadoDTO;
import br.com.centralit.citcorpore.bean.GrupoDTO;
import br.com.centralit.citcorpore.bean.JustificativaSolicitacaoDTO;
import br.com.centralit.citcorpore.bean.OcorrenciaSolicitacaoDTO;
import br.com.centralit.citcorpore.bean.PesquisaSolicitacaoServicoDTO;
import br.com.centralit.citcorpore.bean.ServicoContratoDTO;
import br.com.centralit.citcorpore.bean.ServicoDTO;
import br.com.centralit.citcorpore.bean.SolicitacaoServicoDTO;
import br.com.centralit.citcorpore.bean.TabFederacaoDadosDTO;
import br.com.centralit.citcorpore.bean.UsuarioDTO;
import br.com.centralit.citcorpore.negocio.AcordoServicoContratoService;
import br.com.centralit.citcorpore.negocio.AprovacaoSolicitacaoServicoService;
import br.com.centralit.citcorpore.negocio.CategoriaServicoService;
import br.com.centralit.citcorpore.negocio.ContratoService;
import br.com.centralit.citcorpore.negocio.EmpregadoService;
import br.com.centralit.citcorpore.negocio.ExecucaoSolicitacaoServiceEjb;
import br.com.centralit.citcorpore.negocio.GrupoService;
import br.com.centralit.citcorpore.negocio.JustificativaSolicitacaoService;
import br.com.centralit.citcorpore.negocio.OcorrenciaSolicitacaoService;
import br.com.centralit.citcorpore.negocio.OcorrenciaSolicitacaoServiceEjb;
import br.com.centralit.citcorpore.negocio.ServicoContratoService;
import br.com.centralit.citcorpore.negocio.ServicoService;
import br.com.centralit.citcorpore.negocio.SolicitacaoServicoService;
import br.com.centralit.citcorpore.negocio.TabFederacaoDadosService;
import br.com.centralit.citcorpore.negocio.UsuarioService;
import br.com.centralit.citcorpore.util.Enumerados;
import br.com.centralit.citcorpore.util.Enumerados.OccurrenceCategory;
import br.com.centralit.citcorpore.util.Enumerados.OrigemOcorrencia;
import br.com.centralit.citcorpore.util.Enumerados.ServiceDemandType;
import br.com.centralit.citcorpore.util.Enumerados.ServiceRequestStatus;
import br.com.centralit.citcorpore.util.Enumerados.TipoServico;
import br.com.centralit.citcorpore.util.ParametroUtil;
import br.com.centralit.citsmart.rest.bean.RestDomainDTO;
import br.com.centralit.citsmart.rest.bean.RestLogDTO;
import br.com.centralit.citsmart.rest.bean.RestOperationDTO;
import br.com.centralit.citsmart.rest.bean.RestSessionDTO;
import br.com.centralit.citsmart.rest.operation.IRestOperation;
import br.com.centralit.citsmart.rest.schema.CtErrorLog;
import br.com.centralit.citsmart.rest.schema.CtMessage;
import br.com.centralit.citsmart.rest.schema.CtMessageResp;
import br.com.centralit.citsmart.rest.service.RestLogService;
import br.com.centralit.citsmart.rest.util.RestEnum;
import br.com.centralit.citsmart.rest.util.RestOperationUtil;
import br.com.centralit.citsmart.rest.util.RestUtil;
import br.com.centralit.citsmart.rest.v3.schema.CtApproval;
import br.com.centralit.citsmart.rest.v3.schema.CtCategory;
import br.com.centralit.citsmart.rest.v3.schema.CtContact;
import br.com.centralit.citsmart.rest.v3.schema.CtErrorGetList;
import br.com.centralit.citsmart.rest.v3.schema.CtErrorGetListResp;
import br.com.centralit.citsmart.rest.v3.schema.CtOccurrence;
import br.com.centralit.citsmart.rest.v3.schema.CtOccurrenceCreate;
import br.com.centralit.citsmart.rest.v3.schema.CtOccurrenceCreateResp;
import br.com.centralit.citsmart.rest.v3.schema.CtOccurrenceGetList;
import br.com.centralit.citsmart.rest.v3.schema.CtOccurrenceGetListResp;
import br.com.centralit.citsmart.rest.v3.schema.CtOrigin;
import br.com.centralit.citsmart.rest.v3.schema.CtRequest;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestCreate;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestCreateResp;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestGetById;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestGetByIdResp;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestGetList;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestGetListResp;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestUpdate;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestUpdateResp;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestUpdateStatus;
import br.com.centralit.citsmart.rest.v3.schema.CtRequestUpdateStatusResp;
import br.com.centralit.citsmart.rest.v3.schema.CtService;
import br.com.centralit.citsmart.rest.v3.schema.CtStatus;
import br.com.centralit.citsmart.rest.v3.schema.CtTask;
import br.com.centralit.citsmart.rest.v3.schema.StRequestPriority;
import br.com.centralit.citsmart.rest.v3.schema.StRequestType;
import br.com.citframework.excecao.LogicException;
import br.com.citframework.excecao.PersistenceException;
import br.com.citframework.excecao.ServiceException;
import br.com.citframework.integracao.TransactionControler;
import br.com.citframework.integracao.TransactionControlerImpl;
import br.com.citframework.service.ServiceLocator;
import br.com.citframework.util.Constantes;
import br.com.citframework.util.UtilDatas;
import br.com.citframework.util.UtilNumbersAndDecimals;
import br.com.citframework.util.UtilStrings;

/**
 * Implementação das operaçãos que respondem em {@code /service} da versão V3
 * REST
 *
 * @author carlos.alberto -
 *         <a href="mailto:carlos.alberto@centrait.com.br">carlos.
 *         alberto@centrait.com.br</a>
 * @since 07/09/2015
 *
 */
public class RESTOperation implements IRestOperation<CtMessage, CtMessageResp> {

	private Gson gson = null;

	private Gson getGson() {
		if (gson == null) {
			gson = new GsonBuilder().create();
		}
		return gson;
	}

    private static final Logger LOGGER = Logger.getLogger(RESTOperation.class.getName());

    protected static final String SOLICITACAOSERVICO = "SOLICITACAOSERVICO";
    protected static final String CONTRATO = "CONTRATO";
    protected static final String SERVICO = "SERVICO";
    protected static final String GRUPO = "GRUPO";
    protected static final String OCORRENCIASOLICITACAO = "OCORRENCIASOLICITACAO";

    @Override
    public CtMessageResp execute(final RestSessionDTO restSessionDto, final RestOperationDTO restOperationDto, final CtMessage message) throws JAXBException {
        return RestUtil.execute(this, restSessionDto, restOperationDto, message);
    }

    protected CtErrorGetListResp errorGetList(final RestSessionDTO restSession, final CtErrorGetList message, final RestOperationDTO restOperation) {
        final CtErrorGetListResp resp = new CtErrorGetListResp();

        if (!this.validateErrorGetList(restSession, message, resp)) {
        	return resp;
        }

        int size = message.getOperationList() != null ? message.getOperationList().size() : 0;
        String[] operations = new String[size];
        if (message.getOperationList() != null) {
        	int i = 0;
        	for (String operation : message.getOperationList()) {
				operations[i] = operation;
				i++;
			}
        }

        try {
			Collection<RestLogDTO> restLogs = this.getRestLogService().findErrorsByOperationAndDate(restSession.getPlatform()
																								  , new Date(message.getStartDate().getTimeInMillis())
																								  , new Date(message.getEndDate().getTimeInMillis())
																								  , operations);

			if (restLogs != null) {
				for (RestLogDTO restLog : restLogs) {
					CtErrorLog error = new CtErrorLog();

					error.setDateTime(UtilDatas.timestampToGregorianCalendar(restLog.getDateTime()));
					error.setExecutionId(restLog.getIdRestExecution().longValue());
					error.setLogId(restLog.getIdRestLog().longValue());
					error.setOperationDescription(restLog.getDescription());
					error.setOperationName(restLog.getName());
					error.setResultData(restLog.getResultData());
					error.setOrigin(restLog.getOrigin());
					error.setUuid(restLog.getUuid());

					resp.getErrors().add(error);
				}
			}
		} catch (PersistenceException e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}

        return resp;
    }

    protected boolean validateErrorGetList(final RestSessionDTO restSession, final CtErrorGetList message, CtErrorGetListResp resp) {
        if (message == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "cargaWebService.parametrosEntradaNaoInformado")));
            return false;
        }
        if (message.getStartDate() == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "cargaWebService.dataInicialNaoInformada")));
            return false;
        }
        if (message.getEndDate() == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "cargaWebService.dataFinalNaoInformada")));
            return false;
        }

        return true;
    }

    protected CtRequestCreateResp createRequest(final RestSessionDTO restSession, final CtRequestCreate message, final RestOperationDTO restOperation) {
        final CtRequestCreateResp resp = new CtRequestCreateResp();

        final Map<String, RestDomainDTO> mapParam = RestUtil.getRestParameterService(restSession).findParameters(restSession, restOperation);
        if (mapParam == null || mapParam.isEmpty()) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.params.not.registered")));
            return resp;
        }

        final String idOrigem = ParametroUtil.getValorParametroCitSmartHashMap(Enumerados.ParametroSistema.ORIGEM_PADRAO_SOLICITACAO, "").trim();
        if (StringUtils.isBlank(idOrigem)) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.treatment.id.not.parametrized")));
            return resp;
        }

        final CtRequest sourceRequest = message.getSourceRequest();

        if (!this.validateCreate(restSession, sourceRequest, resp)) {
        	return resp;
        }

        ServiceDemandType tipoDemandaServico  = null;

		String obs = RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.incidenteCriado").concat(" ");
        String idTipoDemanda = null;
        if (sourceRequest.getType().equals(StRequestType.R)) {
            idTipoDemanda = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_REQUEST_ID);
			obs = RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.requisicaoCriado").concat(" ");
        } else {
            idTipoDemanda = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_INCIDENT_ID);
        }
        if (idTipoDemanda != null) {
        	tipoDemandaServico = ServiceDemandType.fromId(Integer.valueOf(idTipoDemanda));
        }
        
        if (tipoDemandaServico == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, sourceRequest.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.tipoDemandaIndefinido"))));
            return resp;
        }

        final boolean synchronize = message.getSynchronize() == null ? false : message.getSynchronize();

        ContratoDTO contrato = null;
		try {
			contrato = this.findContract(restSession, sourceRequest.getContractID(), mapParam, true, synchronize);
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}
        if (contrato == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, sourceRequest.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.contract.default.not.parametrized"))));
            return resp;
        }

        GrupoDTO grupoAtual = null;
    	try {
			grupoAtual = this.findGroup(restSession, sourceRequest.getGroupId(), mapParam, true, synchronize);
        } catch (final Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            return resp;
        }

        ServicoDTO servico = null;
		try {
			servico = this.findService(restSession, sourceRequest.getService(), tipoDemandaServico, mapParam, synchronize, true);
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}
        if (servico == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, sourceRequest.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.service.default.not.parametrized"))));
            return resp;
        }

        ServicoContratoDTO servicoContrato = null;
        try {
            servicoContrato = this.findContractService(restSession, contrato, servico, grupoAtual, mapParam, synchronize);
        } catch (final Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            return resp;
        }
        if (servicoContrato == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, sourceRequest.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.service.not.related"))));
            return resp;
        }

        EmpregadoDTO empregado = null;
        try {
            empregado = this.findEmployee(restSession, sourceRequest, synchronize);
        } catch (final Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
        }
        if (empregado == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, sourceRequest.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.user.notfound"))));
            return resp;
        }

        String impacto = "B";
        if (sourceRequest.getImpact() != null) {
        	if (sourceRequest.getImpact().equals(StRequestPriority.H)) {
                impacto = "A";
            } else if (sourceRequest.getImpact().equals(StRequestPriority.M)) {
                impacto = "M";
            }
        }

        String urgencia = "B";
        if (sourceRequest.getUrgency() != null) {
        	if (sourceRequest.getUrgency().equals(StRequestPriority.H)) {
                urgencia = "A";
            } else if (sourceRequest.getUrgency().equals(StRequestPriority.M)) {
                urgencia = "M";
            }
        }

        SolicitacaoServicoDTO solicitacaoDto = new SolicitacaoServicoDTO();
        solicitacaoDto.setUsuarioDto(restSession.getUser());
        solicitacaoDto.setIdContrato(Integer.valueOf(contrato.getIdContrato()));
        solicitacaoDto.setIdOrigem(Integer.valueOf(idOrigem));
        solicitacaoDto.setIdServico(Integer.valueOf(servico.getIdServico()));
        solicitacaoDto.setIdSolicitante(empregado.getIdEmpregado());
        solicitacaoDto.setIdTipoDemandaServico(tipoDemandaServico.getId());
        solicitacaoDto.setIdUnidade(empregado.getIdUnidade());
        solicitacaoDto.setImpacto(impacto);
        solicitacaoDto.setUrgencia(urgencia);
        solicitacaoDto.setIdGrupoNivel1(servicoContrato.getIdGrupoNivel1());
        solicitacaoDto.setIdGrupoAtual(grupoAtual != null ? grupoAtual.getIdGrupo() : servicoContrato.getIdGrupoExecutor());
		solicitacaoDto.setIdStatus(ServiceRequestStatus.IN_PROGRESS.getId());

        solicitacaoDto.setNomecontato(sourceRequest.getContact().getName());
        solicitacaoDto.setEmailcontato(sourceRequest.getContact().getEmail());
        solicitacaoDto.setTelefonecontato(sourceRequest.getContact().getPhoneNumber());
        solicitacaoDto.setEnviaEmailCriacao("S");
        solicitacaoDto.setEnviaEmailAcoes("N");
        solicitacaoDto.setEnviaEmailFinalizacao("S");

		obs = obs.concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.porServicoRest")).concat(" ");
        String defaultDescription = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_DEFAULT_DESCRIPTION);
        if (defaultDescription != null) {
        	obs = defaultDescription;
        }

		obs = obs.concat(". ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.numeroOrigem")).concat(": ").concat(sourceRequest.getNumberOrigin()).concat(" - ").concat(this.getOrigin(restSession)).concat("<br>");
        int q = obs.trim().length();
        for (int i = 1; i <= q; i++) {
			obs += "=";
		}
		obs = obs.concat("<br>");

        String descricao = obs + sourceRequest.getDescription();
        solicitacaoDto.setDescricao(descricao);
        solicitacaoDto.setRegistroexecucao("");
        solicitacaoDto.setCodigoExterno(sourceRequest.getNumberOrigin());

        solicitacaoDto.setObservacao(obs);

        if (!UtilStrings.isNullOrEmpty(sourceRequest.getLinkedNumber())) {
        	try {
				SolicitacaoServicoDTO solicitacaoRelacionada = this.findRequest(restSession, sourceRequest.getLinkedNumber(), null);
				if (solicitacaoRelacionada != null) {
					solicitacaoDto.setIdSolicitacaoPai(solicitacaoRelacionada.getIdSolicitacaoServico());
				}
			} catch (Exception e) {
	            LOGGER.log(Level.SEVERE, e.getMessage(), e);
	            resp.setError(RestOperationUtil.buildSimpleError(e));
	            return resp;
			}
        }

        TransactionControler tc = new TransactionControlerImpl(Constantes.getValue("DATABASE_ALIAS"));
		try {
			tc.start();

            solicitacaoDto = (SolicitacaoServicoDTO) this.getSolicitacaoServicoService().create(solicitacaoDto, tc, true, true, true);

            this.updateSLA(sourceRequest, solicitacaoDto, tc);

            solicitacaoDto = this.getSolicitacaoServicoService().restoreAll(solicitacaoDto.getIdSolicitacaoServico(), tc);

            ItemTrabalho itemTrabalho = null;
			if (sourceRequest.getCurrentTask() != null && sourceRequest.getCurrentTask().getStatus().getCode().equals(StatusWorkItem.EXECUTED.getId())) {
	    		try {
	    			itemTrabalho = this.findTask(sourceRequest.getCurrentTask(), solicitacaoDto, null);
	    		} catch (Exception e1) {
	    		}
            }

    		if (itemTrabalho != null) {
    			new ExecucaoSolicitacaoServiceEjb().executa(solicitacaoDto, itemTrabalho.getIdItemTrabalho(), "E", tc);
    		}

        	this.buildCorrelation(restSession, SOLICITACAOSERVICO, sourceRequest.getNumberOrigin(), solicitacaoDto.getIdSolicitacaoServico().toString(), tc);

			resp.setRequest(this.buildOutputRequest(restSession, solicitacaoDto, true, tc));

            tc.commit();
		} catch (Exception e) {
			this.rollbackTransaction(tc);

			LOGGER.log(Level.SEVERE, e.getMessage(), e);
			resp.setError(RestOperationUtil.buildSimpleError(sourceRequest.getNumberOrigin().concat(" -> "), e));
            return resp;
		} finally {
			try {
				tc.close();
			} catch (PersistenceException e) {
				e.printStackTrace();
			}
		}

        return resp;
    }

    protected CtRequestUpdateResp updateRequest(final RestSessionDTO restSession, final CtRequestUpdate message, final RestOperationDTO restOperation) {
        final CtRequestUpdateResp resp = new CtRequestUpdateResp();

        final Map<String, RestDomainDTO> mapParam = RestUtil.getRestParameterService(restSession).findParameters(restSession, restOperation);
        if (mapParam == null || mapParam.isEmpty()) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.params.not.registered")));
            return resp;
        }

        final CtRequest request = message.getRequest();

        if (!this.validateUpdate(restSession, request, resp)) {
        	return resp;
        }

        SolicitacaoServicoDTO solicitacaoServico = null;
        try {
        	solicitacaoServico = this.findRequest(restSession, request.getNumberOrigin(), request.getNumber());
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}
        if (solicitacaoServico == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.solicitacaoNaoCadastrada"))));
            return null;
        }

        ContratoDTO contrato = new ContratoDTO();
        contrato.setIdContrato(solicitacaoServico.getIdContrato());
        try {
			contrato = this.getContratoService().restore(contrato);
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}
        if (contrato == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.contratoNaoLocalizado"))));
            return resp;
        }

        final boolean synchronize = message.getSynchronize() == null ? false : message.getSynchronize();

        ServiceDemandType tipoDemandaServico = ServiceDemandType.fromId(solicitacaoServico.getIdTipoDemandaServico());

        if (tipoDemandaServico == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.tipoDemandaIndefinido"))));
            return resp;
        }

        GrupoDTO grupoAtual = null;
    	try {
			grupoAtual = this.findGroup(restSession, request.getGroupId(), mapParam, false, synchronize);
        } catch (final Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            return resp;
        }

        ServicoDTO servico = null;
		try {
			servico = this.findService(restSession, request.getService(), tipoDemandaServico, mapParam, synchronize, false);
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}

        ServicoContratoDTO servicoContrato = null;
		if (servico != null) {
	        try {
	            servicoContrato = this.findContractService(restSession, contrato, servico, grupoAtual, mapParam, synchronize);
    		} catch (Exception e) {
                LOGGER.log(Level.SEVERE, e.getMessage(), e);
                resp.setError(RestOperationUtil.buildSimpleError(e));
                return resp;
    		}
	        if (servicoContrato == null) {
				resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.service.not.related"))));
	            return resp;
	        }
		}

        EmpregadoDTO empregado = null;
        try {
            empregado = this.findEmployee(restSession, request, synchronize);
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}

        String impacto = solicitacaoServico.getImpacto();
        if (request.getImpact() != null) {
			if (request.getImpact().equals(StRequestPriority.H)) {
                impacto = "A";
            } else if (request.getImpact() != null && request.getImpact().equals(StRequestPriority.M)) {
                impacto = "M";
			} else if (request.getImpact() != null && request.getImpact().equals(StRequestPriority.L)) {
				impacto = "B";
            }
        }

        String urgencia = solicitacaoServico.getUrgencia();
        if (request.getUrgency() != null) {
			if (request.getUrgency().equals(StRequestPriority.H)) {
                urgencia = "A";
			} else if (request.getUrgency() != null && request.getUrgency().equals(StRequestPriority.M)) {
                urgencia = "M";
			} else if (request.getUrgency() != null && request.getUrgency().equals(StRequestPriority.L)) {
				urgencia = "B";
			}
        }

        String allowChangeUser = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_CHANGE_USER);
        String allowChangeGroup = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_CHANGE_GROUP);
        String allowChangeService = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_CHANGE_SERVICE);

        boolean reclassificacao = "S".equalsIgnoreCase(UtilStrings.nullToVazio(allowChangeService)) && servicoContrato != null && servicoContrato.getIdServicoContrato().longValue() != solicitacaoServico.getIdServicoContrato().longValue();

        solicitacaoServico.setReclassificar(reclassificacao ? "S" : "N");

        if ("S".equalsIgnoreCase(UtilStrings.nullToVazio(allowChangeService)) && servico != null) {
        	solicitacaoServico.setIdServico(Integer.valueOf(servico.getIdServico()));
            solicitacaoServico.setIdGrupoNivel1(servicoContrato.getIdGrupoNivel1());
            solicitacaoServico.setIdGrupoAtual(servicoContrato.getIdGrupoExecutor());
            solicitacaoServico.setIdTipoDemandaServico(servico.getIdTipoDemandaServico());
            solicitacaoServico.setIdServicoContrato(servicoContrato.getIdServicoContrato());
        }

        if ("S".equalsIgnoreCase(UtilStrings.nullToVazio(allowChangeUser)) && empregado != null) {
        	solicitacaoServico.setIdSolicitante(empregado.getIdEmpregado());
        	solicitacaoServico.setIdUnidade(empregado.getIdUnidade());
        }

        solicitacaoServico.setImpacto(impacto);
        solicitacaoServico.setUrgencia(urgencia);
        if ("S".equalsIgnoreCase(UtilStrings.nullToVazio(allowChangeGroup)) && grupoAtual != null) {
            solicitacaoServico.setIdGrupoAtual(grupoAtual.getIdGrupo());
        }

        if (request.getContact() != null) {
        	if (request.getContact().getName() != null) {
        		solicitacaoServico.setNomecontato(request.getContact().getName());
        	}
        	if (request.getContact().getEmail() != null) {
        		solicitacaoServico.setEmailcontato(request.getContact().getEmail());
        	}
        	if (request.getContact().getPhoneNumber() != null) {
        		solicitacaoServico.setTelefonecontato(request.getContact().getPhoneNumber());
        	}
        }

        if (!UtilStrings.isNullOrEmpty(request.getDescription())) {
        	solicitacaoServico.setDescricao(request.getDescription());
        }

        try {
            solicitacaoServico = (SolicitacaoServicoDTO) this.getSolicitacaoServicoService().updateInfo(solicitacaoServico);
            this.updateSLA(request, solicitacaoServico, null);

            solicitacaoServico = this.getSolicitacaoServicoService().restoreAll(solicitacaoServico.getIdSolicitacaoServico());

			resp.setRequest(this.buildOutputRequest(restSession, solicitacaoServico, true, null));
        } catch (final Exception e) {
        	e.printStackTrace();
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(request.getNumberOrigin().concat(" -> "),e));
            return resp;
        }

        return resp;
    }

    protected CtRequestUpdateStatusResp updateStatus(final RestSessionDTO restSession, final CtRequestUpdateStatus message, final RestOperationDTO restOperation) {
        final CtRequestUpdateStatusResp resp = new CtRequestUpdateStatusResp();

        if (!this.validateUpdateStatus(restSession, message, resp)) {
        	return resp;
        }

        final Map<String, RestDomainDTO> mapParam = RestUtil.getRestParameterService(restSession).findParameters(restSession, restOperation);
        if (mapParam == null || mapParam.isEmpty()) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.params.not.registered")));
            return resp;
        }

        final String idJustificativa = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_DEFAULT_REASON_ID);
        if (StringUtils.isBlank(idJustificativa)) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.justificativaPadraoSituacaoIndefinida")));
            return resp;
        }

        SolicitacaoServicoDTO solicitacaoServico = null;
        try {
        	solicitacaoServico = this.findRequest(restSession, message.getNumberOrigin(), message.getNumber());
        } catch (final Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return null;
        }
        if (solicitacaoServico == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.solicitacaoNaoCadastrada")));
            return null;
        }

		ServiceRequestStatus situacaoAtual = ServiceRequestStatus.fromId(solicitacaoServico.getIdStatus());
        ServiceRequestStatus novaSituacao  = ServiceRequestStatus.valueOf(message.getStatus().getCode());
        if (!situacaoAtual.equals(novaSituacao)) {
        	try{
	        	if (novaSituacao.equals(ServiceRequestStatus.SUSPENDED)) {
	            	solicitacaoServico.setIdJustificativa(Integer.valueOf(idJustificativa));
	            	solicitacaoServico.setComplementoJustificativa(message.getStatus().getDetails());
	        		this.getSolicitacaoServicoService().suspende(restSession.getUser(), solicitacaoServico);
	        	}else if (novaSituacao.equals(ServiceRequestStatus.REOPENED)) {
	            	solicitacaoServico.setIdJustificativa(Integer.valueOf(idJustificativa));
	            	solicitacaoServico.setComplementoJustificativa(message.getStatus().getDetails());
	        		this.getSolicitacaoServicoService().reabre(restSession.getUser(), solicitacaoServico);
	        	}else if (situacaoAtual.equals(ServiceRequestStatus.SUSPENDED) && novaSituacao.equals(ServiceRequestStatus.IN_PROGRESS)) {
	            	solicitacaoServico.setIdJustificativa(Integer.valueOf(idJustificativa));
	            	solicitacaoServico.setComplementoJustificativa(message.getStatus().getDetails());
	        		this.getSolicitacaoServicoService().reativa(restSession.getUser(), solicitacaoServico);
	        	}else if ((situacaoAtual.equals(ServiceRequestStatus.IN_PROGRESS) || situacaoAtual.equals(ServiceRequestStatus.SOLVED) || situacaoAtual.equals(ServiceRequestStatus.REOPENED) )
	        		   && (novaSituacao.equals(ServiceRequestStatus.CANCELED) || novaSituacao.equals(ServiceRequestStatus.CLOSED) || novaSituacao.equals(ServiceRequestStatus.SOLVED))) {

					// Início - Murilo Gabriel Rodrigues - Encerra as execuções da solicitação que estão em andamento
					if (!novaSituacao.equals(ServiceRequestStatus.SOLVED)) {
						new ExecucaoSolicitacaoServiceEjb().encerra(solicitacaoServico, null);
					}
					// Fim

					solicitacaoServico.setIdStatus(novaSituacao.getId());
	            	solicitacaoServico.setResposta(message.getStatus().getDetails());
	            	this.getSolicitacaoServicoService().updateInfo(solicitacaoServico);
	        	}
	        } catch (final Exception e) {
	        	e.printStackTrace();
	            LOGGER.log(Level.SEVERE, e.getMessage(), e);
	            resp.setError(RestOperationUtil.buildSimpleError(e));
	            return resp;
	        }
        }

        try{
	        solicitacaoServico = this.getSolicitacaoServicoService().restoreAll(solicitacaoServico.getIdSolicitacaoServico());
			resp.setRequest(this.buildOutputRequest(restSession, solicitacaoServico, true, null));
	    } catch (final Exception e) {
	    	e.printStackTrace();
	        LOGGER.log(Level.SEVERE, e.getMessage(), e);
	        resp.setError(RestOperationUtil.buildSimpleError(e));
	        return resp;
	    }

        return resp;
    }

    protected CtRequestGetListResp getByUser(final RestSessionDTO restSession, final CtRequestGetList message, final RestOperationDTO restOperation) {
        final CtRequestGetListResp resp = new CtRequestGetListResp();

	    if (message == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.parametroConsultaNaoInformado")));
            return resp;
        }
        if (UtilStrings.isNullOrEmpty(message.getUserID())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.usuarioConsultaNaoInformado")));
            return resp;
        }

        EmpregadoDTO empregado = null;
        UsuarioDTO usuario = null;
        try {
    		usuario = this.getUsuarioService().restoreByLogin(message.getUserID());
    		if (usuario != null) {
    			empregado = this.getEmpregadoService().restoreByIdEmpregado(usuario.getIdEmpregado());
    		}
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}

        if (empregado == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.user.notfound")));
            return resp;
        }

        ServicoDTO servico = null;
        try {
        	servico = this.findService(restSession, message.getService(), null, null, false, false);
        } catch (final Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            return resp;
        }

        boolean allAttributes = message.getAllAttributes() != null ? message.getAllAttributes() : false;

        List<Integer> groupList = this.buildGroupList(message);
        List<Integer> contractList = this.buildContractList(message);
        List<ServiceRequestStatus> statusList = this.buildStatusList(message);

        for (Integer contractID : contractList) {
            for (Integer groupID : groupList) {
	            for (ServiceRequestStatus status : statusList) {

	                PesquisaSolicitacaoServicoDTO pesquisaSolicitacao = new PesquisaSolicitacaoServicoDTO();
	                pesquisaSolicitacao.setIdSolicitante(empregado.getIdEmpregado());
	               	pesquisaSolicitacao.setDataInicio(message.getStartDate() != null ? new Date(message.getStartDate().getTimeInMillis()) : null);
	               	pesquisaSolicitacao.setDataFim(message.getEndDate() != null ? new Date(message.getEndDate().getTimeInMillis()) : null);
	               	pesquisaSolicitacao.setIdContrato(contractID);
	               	pesquisaSolicitacao.setIdGrupoAtual(groupID);
	               	pesquisaSolicitacao.setIdServico(servico != null ? servico.getIdServico() : null);
					pesquisaSolicitacao.setIdStatus(status != null ? status.getId() : null);
	               	pesquisaSolicitacao.setPalavraChave(message.getDescription());

	               	try {
						List<SolicitacaoServicoDTO> list = this.getSolicitacaoServicoService().listPesquisaAvancadaRelatorio(pesquisaSolicitacao);
	        			if (list != null) {
	        				for (SolicitacaoServicoDTO solicitacaoServico : list) {
	        					solicitacaoServico.setGrupoAtual(solicitacaoServico.getSiglaGrupo());
	        					solicitacaoServico.setDemanda(solicitacaoServico.getNomeTipoDemandaServico());

	        					if (allAttributes) {
	        						solicitacaoServico = this.getSolicitacaoServicoService().restoreAll(solicitacaoServico.getIdSolicitacaoServico());
	        				}

	        					solicitacaoServico.setUsuarioDto(usuario);
								resp.getRequests().add(this.buildOutputRequest(restSession, solicitacaoServico, allAttributes, null));
	        			}
	        			}
	        		} catch (Exception e) {
	        			e.printStackTrace();
	                    LOGGER.log(Level.SEVERE, e.getMessage(), e);
	                    resp.setError(RestOperationUtil.buildSimpleError(e));
	                    return resp;
	        		}
	    		}
            }
		}


        return resp;
    }

    protected CtRequestGetByIdResp getById(final RestSessionDTO restSession, final CtRequestGetById message, final RestOperationDTO restOperation) {
        final CtRequestGetByIdResp resp = new CtRequestGetByIdResp();

	    if (message == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.parametroConsultaNaoInformado")));
            return resp;
        }
        if (UtilStrings.isNullOrEmpty(message.getNumberOrigin()) && UtilStrings.isNullOrEmpty(message.getNumber())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.numeroSolicitacaoNaoInformado")));
            return resp;
        }

        SolicitacaoServicoDTO solicitacaoServico = null;
        try {
        	solicitacaoServico = this.findRequest(restSession, message.getNumberOrigin(), message.getNumber());
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}
        if (solicitacaoServico == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.solicitacaoNaoCadastrada")));
            return null;
        }

        try {
			resp.setRequest(this.buildOutputRequest(restSession, solicitacaoServico, true, null));
        } catch (final Exception e) {
        	e.printStackTrace();
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
        }

        return resp;
    }

	protected CtOccurrenceGetListResp listOccurrences(final RestSessionDTO restSession, final CtOccurrenceGetList message, final RestOperationDTO restOperation) {
        final CtOccurrenceGetListResp resp = new CtOccurrenceGetListResp();

        if (UtilStrings.isNullOrEmpty(message.getRequestNumberOrigin()) && UtilStrings.isNullOrEmpty(message.getRequestNumber())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.numeroSolicitacaoNaoInformado")));
            return resp;
        }

        SolicitacaoServicoDTO solicitacaoServico = null;
        try {
        	solicitacaoServico = this.findRequest(restSession, message.getRequestNumberOrigin(), message.getRequestNumber());
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}
        if (solicitacaoServico == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.solicitacaoNaoCadastrada")));
            return null;
        }

        try {
        	Collection<OcorrenciaSolicitacaoDTO> ocorrencias = this.getOcorrenciaSolicitacaoService().findByIdSolicitacaoServico(solicitacaoServico.getIdSolicitacaoServico());
        	if (ocorrencias != null && !ocorrencias.isEmpty()) {
        		String requestNumberOrigin = solicitacaoServico.getCodigoExterno();
        		if (requestNumberOrigin == null) {
        			TabFederacaoDadosDTO federacaoDados = this.findCorrelation(restSession, SOLICITACAOSERVICO, solicitacaoServico.getIdSolicitacaoServico().toString());
        			requestNumberOrigin = federacaoDados != null ? federacaoDados.getChaveOriginal() : null;
        		}

        		for (OcorrenciaSolicitacaoDTO ocorrencia : ocorrencias) {
        			TabFederacaoDadosDTO federacaoDados = this.findCorrelation(restSession, OCORRENCIASOLICITACAO, ocorrencia.getIdOcorrencia().toString());
					resp.getOccurrences().add(this.buildOccurrence(restSession, ocorrencia, federacaoDados != null ? federacaoDados.getChaveOriginal() : ocorrencia.getIdOcorrencia().toString(), requestNumberOrigin, false));
				}
        	}
        } catch (final Exception e) {
        	e.printStackTrace();
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
        }

        return resp;
    }

	protected CtOccurrenceCreateResp createOccurrence(final RestSessionDTO restSession, final CtOccurrenceCreate message, final RestOperationDTO restOperation) {
        final CtOccurrenceCreateResp resp = new CtOccurrenceCreateResp();

        if (!this.validateCreateOccurrence(restSession, message, resp)) {
        	return resp;
        }

        final Map<String, RestDomainDTO> mapParam = RestUtil.getRestParameterService(restSession).findParameters(restSession, restOperation);
        if (mapParam == null || mapParam.isEmpty()) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.params.not.registered")));
            return resp;
        }

        final String idJustificativa = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_DEFAULT_REASON_ID);
        if (StringUtils.isBlank(idJustificativa)) {
			resp.setError(RestOperationUtil.buildError(RestEnum.PARAM_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.justificativaPadraoSituacaoIndefinida")));
            return resp;
        }

        OccurrenceCategory categoria = message.getOccurrence().getCategory() != null ? OccurrenceCategory.valueOf(message.getOccurrence().getCategory().getCode()) : null;

        SolicitacaoServicoDTO solicitacaoServico = null;
        try {
        	solicitacaoServico = this.findRequest(restSession, message.getRequestNumberOrigin(), message.getRequestNumber());
		} catch (Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return resp;
		}
        if (solicitacaoServico == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, message.getRequestNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.solicitacaoNaoCadastrada"))));
            return resp;
        }

        CtOccurrence occurrence = message.getOccurrence();

        UsuarioDTO usuario = null;
        UsuarioDTO usuarioOriginal = null;
        if (occurrence.getUserID() != null) {
	        try {
	    		usuario = this.getUsuarioService().restoreByLogin(occurrence.getUserID());
			} catch (Exception e) {
	            LOGGER.log(Level.SEVERE, e.getMessage(), e);
	            resp.setError(RestOperationUtil.buildSimpleError(e));
	            return resp;
			}
        }
        if (usuario != null) {
        	usuarioOriginal = usuario;
        }else{
        	usuario = restSession.getUser();

        	String login = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_DEFAULT_USER_CAPTURE);
        	if (!UtilStrings.isNullOrEmpty(login)) {
		        try{
		        	usuarioOriginal = this.getUsuarioService().restoreByLogin(login);
				} catch (Exception e) {
		            LOGGER.log(Level.SEVERE, e.getMessage(), e);
		            resp.setError(RestOperationUtil.buildSimpleError(e));
		            return resp;
				}
        	}
        }

        OrigemOcorrencia origem = OrigemOcorrencia.OUTROS;
        if (message.getOccurrence().getOrigin() != null && OrigemOcorrencia.find(message.getOccurrence().getOrigin().getCode()) != null) {
        	origem = OrigemOcorrencia.find(message.getOccurrence().getOrigin().getCode());
        }

        CtRequest originRequest = occurrence.getRequest();

        ItemTrabalho itemTrabalho = null;
		try {
			itemTrabalho = this.findTask(occurrence.getTask(), solicitacaoServico, null);
		} catch (Exception e1) {
		}

        boolean reclassificacao = originRequest != null && (categoria.equals(OccurrenceCategory.SLA_CHANGE) || categoria.equals(OccurrenceCategory.RECLASSIFICATION));
        boolean suspensao = originRequest != null && solicitacaoServico.emAtendimento() && categoria.equals(OccurrenceCategory.REQUEST_SUSPENSION);
        boolean reativacao = originRequest != null && solicitacaoServico.suspensa() && categoria.equals(OccurrenceCategory.REQUEST_REACTIVATION);
        boolean encerramento = originRequest != null && solicitacaoServico.emAtendimento() && categoria.equals(OccurrenceCategory.REQUEST_CLOSING);
        boolean reabertura = originRequest != null && solicitacaoServico.encerrada() && categoria.equals(OccurrenceCategory.REQUEST_REOPENING);
		boolean captura = usuarioOriginal != null && itemTrabalho != null && categoria.equals(OccurrenceCategory.REGISTRATION_EXECUTION) && occurrence.getTask().getStatus().getCode().equals(StatusWorkItem.IN_PROGRESS.getId());
		boolean execucao = itemTrabalho != null && categoria.equals(OccurrenceCategory.REGISTRATION_EXECUTION) && occurrence.getTask().getStatus().getCode().equals(StatusWorkItem.EXECUTED.getId());
        boolean aprovacao = execucao && occurrence.getTask() != null && occurrence.getTask().getApproval() != null;

        boolean direcionamento = false;

        GrupoDTO grupoAtual = null;
        if (originRequest != null && categoria.equals(OccurrenceCategory.REQUEST_DIRECTION)) {
        	try {
    			grupoAtual = this.findGroup(restSession, originRequest.getGroupId().toString(), mapParam, false, true);
            } catch (final Exception e) {
                LOGGER.log(Level.SEVERE, e.getMessage(), e);
                return resp;
            }
        	direcionamento = grupoAtual != null && (solicitacaoServico.getIdGrupoAtual() == null || !solicitacaoServico.getIdGrupoAtual().equals(grupoAtual.getIdGrupo()));
        }

		TransactionControler tc = new TransactionControlerImpl(Constantes.getValue("DATABASE_ALIAS"));
		try {
	    	tc.start();
			if (reclassificacao) {
				solicitacaoServico.setSlaACombinar(originRequest.isDefinedSLA() ? "N" : "S");
		    	if (originRequest.getEndSLA() != null) {
		    		solicitacaoServico.setDataHoraLimite(UtilDatas.calendarToTimestamp(originRequest.getEndSLA()));
		    	}
		    	this.updateDeadLine(originRequest, solicitacaoServico);
		    	this.getSolicitacaoServicoService().updateInfo(solicitacaoServico, tc, false);

	    		resp.setOccurrence(this.synchronizeLastOcurrence(restSession, occurrence.getNumberOrigin(), solicitacaoServico, new OccurrenceCategory[]{OccurrenceCategory.SLA_CHANGE, OccurrenceCategory.RECLASSIFICATION}, tc));
			}else if (suspensao){
            	solicitacaoServico.setIdJustificativa(Integer.valueOf(idJustificativa));
            	solicitacaoServico.setComplementoJustificativa(occurrence.getReason());
            	new ExecucaoSolicitacaoServiceEjb().suspende(usuario, solicitacaoServico, tc);

	    		resp.setOccurrence(this.synchronizeLastOcurrence(restSession, occurrence.getNumberOrigin(), solicitacaoServico, new OccurrenceCategory[]{OccurrenceCategory.REQUEST_SUSPENSION}, tc));
			}else if (reativacao) {
            	solicitacaoServico.setIdJustificativa(Integer.valueOf(idJustificativa));
            	solicitacaoServico.setComplementoJustificativa(occurrence.getReason());
            	new ExecucaoSolicitacaoServiceEjb().reativa(usuario, solicitacaoServico, tc);

	    		resp.setOccurrence(this.synchronizeLastOcurrence(restSession, occurrence.getNumberOrigin(), solicitacaoServico, new OccurrenceCategory[]{OccurrenceCategory.REQUEST_REACTIVATION}, tc));
        	}else if (encerramento && !execucao && !captura) {
    			new ExecucaoSolicitacaoServiceEjb().encerra(solicitacaoServico, tc);

				try {
					solicitacaoServico.setIdStatus(Integer.valueOf(originRequest.getStatus().getCode()));
				} catch (Exception e) {
				}
            	solicitacaoServico.setResposta(originRequest.getStatus().getDetails());
            	this.getSolicitacaoServicoService().updateInfo(solicitacaoServico, tc, false);

	    		resp.setOccurrence(this.synchronizeLastOcurrence(restSession, occurrence.getNumberOrigin(), solicitacaoServico, new OccurrenceCategory[]{OccurrenceCategory.REQUEST_CLOSING}, tc));
        	}else if (reabertura) {
            	solicitacaoServico.setIdJustificativa(Integer.valueOf(idJustificativa));
            	solicitacaoServico.setComplementoJustificativa(occurrence.getReason());
            	new ExecucaoSolicitacaoServiceEjb().reabre(usuario, solicitacaoServico, tc);

	    		resp.setOccurrence(this.synchronizeLastOcurrence(restSession, occurrence.getNumberOrigin(), solicitacaoServico, new OccurrenceCategory[]{OccurrenceCategory.REQUEST_REACTIVATION}, tc));
        	}else if (direcionamento) {
        		solicitacaoServico.setUsuarioDto(usuario);
        		solicitacaoServico.setIdGrupoAtual(grupoAtual.getIdGrupo());

    			new ExecucaoSolicitacaoServiceEjb().direcionaAtendimento(solicitacaoServico, tc);

	    		resp.setOccurrence(this.synchronizeLastOcurrence(restSession, occurrence.getNumberOrigin(), solicitacaoServico, new OccurrenceCategory[]{OccurrenceCategory.REQUEST_DIRECTION}, tc));
        	}else if (captura) {
        		solicitacaoServico.setUsuarioDto(usuarioOriginal);
        		solicitacaoServico.setIdTarefa(itemTrabalho.getIdItemTrabalho());
        		new ExecucaoSolicitacaoServiceEjb().executa(solicitacaoServico, itemTrabalho.getIdItemTrabalho(), br.com.centralit.bpm.util.Enumerated.ACTION_START, tc);

	    		resp.setOccurrence(this.synchronizeLastOcurrence(restSession, occurrence.getNumberOrigin(), solicitacaoServico, new OccurrenceCategory[]{OccurrenceCategory.REGISTRATION_EXECUTION}, tc));
        	}else if (execucao) {
        		solicitacaoServico.setUsuarioDto(usuario);
        		solicitacaoServico.setIdTarefa(itemTrabalho.getIdItemTrabalho());
				try {
					solicitacaoServico.setIdStatus(Integer.valueOf(originRequest.getStatus().getCode()));
				} catch (Exception e) {
				}
            	solicitacaoServico.setResposta(originRequest.getStatus().getDetails());
            	solicitacaoServico.setAcaoFluxo(br.com.centralit.bpm.util.Enumerated.ACTION_EXECUTE);

            	if (aprovacao) {
	                AprovacaoSolicitacaoServicoDTO aprovacaoDto = new AprovacaoSolicitacaoServicoDTO();
	                aprovacaoDto.setAprovacao(occurrence.getTask().getApproval().isApproved() ? "A" : "N");
	                aprovacaoDto.setComplementoJustificativa(occurrence.getTask().getApproval().getReasonComplement());

	                this.getAprovacaoSolicitacaoServicoService().update(tc, solicitacaoServico, aprovacaoDto);
            	}

            	this.getSolicitacaoServicoService().updateInfo(solicitacaoServico, tc, false);

	    		resp.setOccurrence(this.synchronizeLastOcurrence(restSession, occurrence.getNumberOrigin(), solicitacaoServico, new OccurrenceCategory[]{OccurrenceCategory.REGISTRATION_EXECUTION}, tc));
	    	}else{
    			occurrence = this.createOcurrence(restSession, usuario, occurrence, solicitacaoServico, origem, categoria, null, tc);
    			resp.setOccurrence(occurrence);
        	}

			tc.commit();
		} catch (Exception e) {
			this.rollbackTransaction(tc);

			LOGGER.log(Level.SEVERE, e.getMessage(), e);
			resp.setError(RestOperationUtil.buildSimpleError(message.getRequestNumberOrigin().concat(" -> "), e));
            return resp;
		} finally {
			try {
				tc.close();
			} catch (PersistenceException e) {
				e.printStackTrace();
			}
		}

        return resp;
    }

	protected CtRequest buildOutputRequest(RestSessionDTO restSession, SolicitacaoServicoDTO solicitacao, final boolean complete, TransactionControler tc) throws Exception {
		UsuarioDTO usuario = solicitacao.getUsuarioDto() == null
								? solicitacao.getIdSolicitante() != null ? this.getUsuarioService().restoreByIdEmpregado(solicitacao.getIdSolicitante()) : null
								: solicitacao.getUsuarioDto();

        final CtRequest request = new CtRequest();

        request.setNumber(solicitacao.getIdSolicitacaoServico().toString());
        request.setNumberOrigin(solicitacao.getCodigoExterno());
        request.setDescription(!UtilStrings.isNullOrEmpty(solicitacao.getDescricaoSemFormatacao()) ? solicitacao.getDescricaoSemFormatacao() : "");
        request.setStartDateTime(UtilDatas.timestampToGregorianCalendar(solicitacao.getDataHoraInicio()));
        request.setStartSLA(UtilDatas.timestampToGregorianCalendar(solicitacao.getDataHoraInicioSLA()));
        request.setDeadline(solicitacao.getPrazoEmSegundos());
        request.setDefinedSLA(!UtilStrings.nullToVazio(solicitacao.getSlaACombinar()).equalsIgnoreCase("S"));
		if (solicitacao.getDataHoraLimite() != null) {
			request.setEndSLA(UtilDatas.timestampToGregorianCalendar(solicitacao.getDataHoraLimite()));
		}
        request.setGroupId(solicitacao.getGrupoAtual());
        request.setUserID(usuario != null ? usuario.getLogin() : null);
        request.setLinkedNumber(solicitacao.getIdSolicitacaoPai() != null ? solicitacao.getIdSolicitacaoPai().toString() : null);

        if (solicitacao.getImpacto() != null) {
            request.setImpact(StRequestPriority.L);
        	if (solicitacao.getImpacto().equals("M")) {
        		request.setImpact(StRequestPriority.M);
        	}
        	if (solicitacao.getImpacto().equals("A")) {
        		request.setImpact(StRequestPriority.H);
        	}
        }

        if (solicitacao.getUrgencia() != null) {
            request.setUrgency(StRequestPriority.L);
        	if (solicitacao.getUrgencia().equals("M")) {
        		request.setUrgency(StRequestPriority.M);
        	}
        	if (solicitacao.getUrgencia().equals("A")) {
        		request.setUrgency(StRequestPriority.H);
        	}
        }

        if (UtilStrings.isNullOrEmpty(solicitacao.getDemanda())) {
        	if (solicitacao.getIdTipoDemandaServico() != null) {
        		ServiceDemandType tipoDemandaServico = ServiceDemandType.fromId(solicitacao.getIdTipoDemandaServico());

   				if (tipoDemandaServico != null) {
   		            request.setType(tipoDemandaServico.getClassification().equalsIgnoreCase(TipoServico.SERVICO_INCIDENTE.getIdentificador()) ?  StRequestType.I : StRequestType.R);
   				}
            }
        }else{
            request.setType(solicitacao.getDemanda().toUpperCase().indexOf("INCIDENTE") >= 0 ? StRequestType.I : StRequestType.R);
        }

        final CtStatus status = new CtStatus();
		status.setCode(ServiceRequestStatus.fromId(solicitacao.getIdStatus()).getId().toString());
		status.setName(RestUtil.i18nMessage(restSession, ServiceRequestStatus.fromId(solicitacao.getIdStatus()).getI18NKey()));
        request.setStatus(status);

        if (complete) {
           	status.setDetails(solicitacao.getResposta());

           	if (solicitacao.getIdServico() != null) {
           		ServicoDTO servico = new ServicoDTO();
           		servico.setIdServico(solicitacao.getIdServico());
           		servico = this.getServicoService().restore(servico);
           		if (servico != null) {
		           	final CtService serviceDest = new CtService();
			        serviceDest.setCode(solicitacao.getIdServico().toString());
			        serviceDest.setName(solicitacao.getNomeServico());

					CategoriaServicoDTO categoria = this.findServiceCategory(servico.getIdCategoriaServico(), null, request.getType().toString(), false);
			        if (categoria != null) {
			        	final CtCategory category = new CtCategory();
			        	category.setCode(categoria.getIdCategoriaServico().toString());
			        	category.setName(categoria.getNomeCategoriaServico());
			        	serviceDest.setCategory(category);
			        }
			        request.setService(serviceDest);
	           	}
           	}

	        final CtContact contactDest = new CtContact();
	        contactDest.setName(solicitacao.getNomecontato());
	        contactDest.setEmail(solicitacao.getEmailcontato());
	        contactDest.setPhoneNumber(solicitacao.getTelefonecontato());

	        request.setContractID(solicitacao.getIdContrato() != null ? solicitacao.getIdContrato().toString() : null);
	        request.setContact(contactDest);

        	request.setCurrentTask(this.buildCurrentTask(solicitacao, tc));
        }

        return request;
	}

	protected CtOccurrence createOcurrence(final RestSessionDTO restSession, final UsuarioDTO usuario, final CtOccurrence occurrence, final SolicitacaoServicoDTO solicitacaoServico, final OrigemOcorrencia origem, final OccurrenceCategory categoria, final JustificativaSolicitacaoDTO justificativa, TransactionControler tc) throws Exception {
    	String description = occurrence.getDescription();
		if (!UtilStrings.isNullOrEmpty(occurrence.getNumberOrigin()) ) {
			description = description.concat(" (").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.idOrigem")).concat(": ").concat(occurrence.getNumberOrigin()).concat(" - ").concat(this.getOrigin(restSession))
					.concat(")");
		}
		OcorrenciaSolicitacaoDTO ocorrencia = OcorrenciaSolicitacaoServiceEjb.create(solicitacaoServico, null, "", origem, categoria, "", description, usuario, 0, justificativa, tc);

		if (occurrence.getDate() != null) {
			this.getOcorrenciaSolicitacaoService().updateDataHora(ocorrencia, UtilDatas.calendarToDate(occurrence.getDate()), occurrence.getHour(), tc);
		}

		if (!UtilStrings.isNullOrEmpty(occurrence.getNumberOrigin()) ) {
			this.buildCorrelation(restSession, OCORRENCIASOLICITACAO, occurrence.getNumberOrigin(), ocorrencia.getIdOcorrencia().toString(), tc);
			ocorrencia.setCodigoExterno(occurrence.getNumberOrigin());

			this.getOcorrenciaSolicitacaoService().updateNotNull(ocorrencia, tc);
		}

		return this.buildOccurrence(restSession, ocorrencia, occurrence.getNumberOrigin(), null, false);
	}

	protected CtOccurrence synchronizeLastOcurrence(RestSessionDTO restSession, String numberOrigin, final SolicitacaoServicoDTO solicitacaoServico, final OccurrenceCategory[] categorias, TransactionControler tc) throws Exception {
		OcorrenciaSolicitacaoDTO ocorrencia = null;

		if (categorias != null) {
			int i = 0;
			while (ocorrencia == null && i < categorias.length) {
				Integer categoria = categorias[i].getId();
				ocorrencia = this.getOcorrenciaSolicitacaoService().findUltimoByIdSolicitacaoAndCategoria(solicitacaoServico.getIdSolicitacaoServico(), categoria, tc);
				i++;
			}
		}

		if (ocorrencia != null) {
			if (!UtilStrings.isNullOrEmpty(numberOrigin) && ocorrencia.getDescricao().indexOf(" (ID origem") < 0) {
		    	String descr = ocorrencia.getDescricao();
				descr = descr.concat(" (").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.idOrigem")).concat(numberOrigin).concat(" - ").concat(this.getOrigin(restSession)).concat(")");
		    	ocorrencia.setDescricao(descr);
		    	this.getOcorrenciaSolicitacaoService().updateNotNull(ocorrencia, tc);
			}

			if (!UtilStrings.isNullOrEmpty(numberOrigin) ) {
				this.buildCorrelation(restSession, OCORRENCIASOLICITACAO, numberOrigin, ocorrencia.getIdOcorrencia().toString(), tc);

				ocorrencia.setCodigoExterno(numberOrigin);
				this.getOcorrenciaSolicitacaoService().updateNotNull(ocorrencia, tc);
			}

			return this.buildOccurrence(restSession, ocorrencia, UtilStrings.isNullOrEmpty(numberOrigin) ? ocorrencia.getIdOcorrencia().toString() : numberOrigin, null, false);
		}else{
			return null;
		}
	}

	protected CtTask buildCurrentTask(SolicitacaoServicoDTO solicitacao, TransactionControler tc) throws Exception {
    	CtTask currentTask = null;

    	Collection<AtribuicaoFluxoDTO> tarefas = this.getSolicitacaoServicoService().findTarefasDisponiveis(solicitacao, tc);
        if (tarefas != null && !tarefas.isEmpty()) {
        	AtribuicaoFluxoDTO tarefa = ((List<AtribuicaoFluxoDTO>) tarefas).get(0);

        	currentTask = new CtTask();
			currentTask.setNumber(UtilNumbersAndDecimals.nullToZero(tarefa.getIdItemTrabalho()).longValue());
			currentTask.setElementId(UtilNumbersAndDecimals.nullToZero(tarefa.getIdElemento()).longValue());
        	currentTask.setName(tarefa.getDescricao());
        	currentTask.setStartDateTime(UtilDatas.timestampToGregorianCalendar(tarefa.getDataHora()));
        	currentTask.setGroupId(tarefa.getGrupo());
        	currentTask.setUserId(tarefa.getUsuario());

        	CtStatus taskStatus = new CtStatus();
			taskStatus.setCode(tarefa.getIdStatus().toString());
			taskStatus.setName(StatusWorkItem.chaveFromId(tarefa.getIdStatus()));
        	currentTask.setStatus(taskStatus);
        }
    	return currentTask;
	}

	protected ItemTrabalho findTask(CtTask task, SolicitacaoServicoDTO solicitacao, TransactionControler tc) throws Exception {
		ItemTrabalho theTask = null;

		if (solicitacao != null && task != null && !UtilStrings.isNullOrEmpty(task.getName())) {
	    	Collection<AtribuicaoFluxoDTO> tarefas = this.getSolicitacaoServicoService().findTarefasDisponiveis(solicitacao, tc);
	        if (tarefas != null && !tarefas.isEmpty()) {
	        	for (AtribuicaoFluxoDTO atribuicaoFluxo : tarefas) {
					if (atribuicaoFluxo.getDescricao().equalsIgnoreCase(task.getName())) {
			    		ItemTrabalho itemTrabalho = this.getSolicitacaoServicoService().getItemTrabalho(atribuicaoFluxo.getIdItemTrabalho());
			    		if (itemTrabalho != null && itemTrabalho instanceof Tarefa) {
			    			theTask = itemTrabalho;
			    			break;
			    		}
					}
				}
	        }
		}
    	return theTask;
	}

	protected void buildApproval(final ItemTrabalho itemTrabalho, final CtTask task) throws Exception {
		AprovacaoSolicitacaoServicoDTO aprovacaoSolicitacaoServico = this.getAprovacaoSolicitacaoServicoService().findByIdTarefa(itemTrabalho.getIdItemTrabalho());
		if (aprovacaoSolicitacaoServico != null) {
			JustificativaSolicitacaoDTO justificativa = null;
			if (aprovacaoSolicitacaoServico.getIdJustificativa() != null) {
				justificativa = new JustificativaSolicitacaoDTO();
				justificativa.setIdJustificativa(aprovacaoSolicitacaoServico.getIdJustificativa());
				justificativa = this.getJustificativaSolicitacaoService().restore(justificativa);
			}

			UsuarioDTO usuario = this.getUsuarioService().restoreByIdEmpregado(aprovacaoSolicitacaoServico.getIdResponsavel());
			String aprovacao = UtilStrings.nullToVazio(aprovacaoSolicitacaoServico.getAprovacao());

			CtApproval approval = new CtApproval();
			approval.setApproved(aprovacao.equalsIgnoreCase("S") || aprovacao.equalsIgnoreCase("A"));
			approval.setReason(justificativa != null ? justificativa.getDescricaoJustificativa() : null);
			approval.setReasonComplement(aprovacaoSolicitacaoServico.getComplementoJustificativa());
			approval.setUserId(usuario != null ? usuario.getLogin() : null);

			task.setApproval(approval);
		}
	}

	protected CtOccurrence buildOccurrence(RestSessionDTO restSession, OcorrenciaSolicitacaoDTO ocorrencia, String numberOrigin, String requestNumberOrigin, boolean buildData) throws Exception {
    	if (ocorrencia == null) {
    		return null;
    	}

    	CtOccurrence requestLog = new CtOccurrence();

		String code = OccurrenceCategory.OTHERS.getId().toString();
		String name = OccurrenceCategory.OTHERS.getI18NKey();
		if (!UtilNumbersAndDecimals.isNullOrZeroOrEmpty(ocorrencia.getIdOccurrenceCategory())) {
			code = OccurrenceCategory.fromId(ocorrencia.getIdOccurrenceCategory()).getId().toString();
			name = OccurrenceCategory.fromId(ocorrencia.getIdOccurrenceCategory()).getI18NKey();
    	}

    	CtCategory category = new CtCategory();
    	category.setCode(code);
    	category.setName(name);

    	CtOrigin origin = new CtOrigin();
    	origin.setCode(OrigemOcorrencia.find(ocorrencia.getOrigem()) != null ? OrigemOcorrencia.find(ocorrencia.getOrigem()).name() : null);
    	origin.setName(OrigemOcorrencia.find(ocorrencia.getOrigem()) != null ? OrigemOcorrencia.find(ocorrencia.getOrigem()).getDescricao() : null);

    	requestLog.setRequestNumber(ocorrencia.getIdSolicitacaoServico().toString());
    	requestLog.setRequestNumberOrigin(requestNumberOrigin);
    	requestLog.setCategory(category);
    	requestLog.setDate(UtilDatas.dateToCalendar(ocorrencia.getDataregistro()));
    	requestLog.setHour(ocorrencia.getHoraregistro());
    	requestLog.setNumber(ocorrencia.getIdOcorrencia().toString());
    	requestLog.setNumberOrigin(numberOrigin);
    	requestLog.setOrigin(origin);
    	requestLog.setReason(ocorrencia.getComplementoJustificativa());
    	requestLog.setUserID(ocorrencia.getRegistradopor());
    	requestLog.setDescription(UtilStrings.nullToVazio(ocorrencia.getDescricao()));

    	if (buildData) {
	    	SolicitacaoServicoDTO solicitacaoOrigem = this.buildRequestFromJson(ocorrencia.getDadosSolicitacao());
	    	if (solicitacaoOrigem != null) {
				requestLog.setRequest(this.buildOutputRequest(restSession, solicitacaoOrigem, true, null));
	    	}
    	}

    	if (ocorrencia.getIdItemTrabalho() !=  null) {
    		ItemTrabalho itemTrabalho = this.getSolicitacaoServicoService().getItemTrabalho(ocorrencia.getIdItemTrabalho());
    		if (itemTrabalho != null && itemTrabalho instanceof Tarefa) {
            	CtTask task = new CtTask();
            	task.setNumber(itemTrabalho.getIdItemTrabalho().longValue());
            	task.setElementId(itemTrabalho.getIdElemento().longValue());
            	task.setName(itemTrabalho.getDocumentacao());
            	task.setStartDateTime(itemTrabalho.getItemTrabalhoDto().getDataHoraCriacao() == null ? null : UtilDatas.timestampToGregorianCalendar(itemTrabalho.getItemTrabalhoDto().getDataHoraCriacao()));
            	task.setEndDateTime(itemTrabalho.getItemTrabalhoDto().getDataHoraFinalizacao() == null ? null : UtilDatas.timestampToGregorianCalendar(itemTrabalho.getItemTrabalhoDto().getDataHoraFinalizacao()));

            	CtStatus taskStatus = new CtStatus();
            	taskStatus.setCode(itemTrabalho.getSituacao().name());
				taskStatus.setName(itemTrabalho.getSituacao().getI18NKey());
            	task.setStatus(taskStatus);

            	this.buildApproval(itemTrabalho, task);

            	requestLog.setTask(task);
    		}
    	}

    	return requestLog;
	}

	protected boolean validateCreate(final RestSessionDTO restSession, final CtRequest request, CtRequestCreateResp resp) {
        if (request == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.dadosSolicitacaoOrigemNaoInformados")));
            return false;
        }
        if (UtilStrings.isNullOrEmpty(request.getNumberOrigin())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.numeroSolicitacaoOrigemNaoInformados")));
            return false;
        }

        try {
            if (this.findRequest(restSession, request.getNumberOrigin(), null) != null) {
				resp.setError(
						RestOperationUtil.buildError(RestEnum.INPUT_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.solicitacaoServicoJaCadastradaComNumeroOrigem"))));
                return false;
            }
        } catch (final Exception e) {
            LOGGER.log(Level.SEVERE, e.getMessage(), e);
            resp.setError(RestOperationUtil.buildSimpleError(e));
            return false;
        }

        if (UtilStrings.isNullOrEmpty(request.getDescription())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.description.solicitation.not.informed"))));
            return false;
        }

        if (request.getType() == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.tipoSolicitacaoNaoInformada"))));
            return false;
        }

        if (UtilStrings.isNullOrEmpty(request.getUserID())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.usuarioSolicitanteNaoInformada"))));
            return false;
        }

        if (request.getContact() == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.contatoNaoInformado"))));
            return false;
        }
        if (UtilStrings.isNullOrEmpty(request.getContact().getEmail()) || UtilStrings.isNullOrEmpty(request.getContact().getName()) || UtilStrings.isNullOrEmpty(request.getContact().getPhoneNumber())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, request.getNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.dadosContratoNaoInformado"))));
            return false;
        }

        return true;
    }

    protected boolean validateUpdate(RestSessionDTO restSession, CtRequest request, CtRequestUpdateResp resp) {
	    if (request == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.dadosSolicitacaoOrigemNaoInformados")));
            return false;
        }
        if (UtilStrings.isNullOrEmpty(request.getNumber()) && UtilStrings.isNullOrEmpty(request.getNumberOrigin())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.numeroSolicitacaoNaoInformado")));
            return false;
        }

        return true;
	}

    protected boolean validateUpdateStatus(RestSessionDTO restSession, CtRequestUpdateStatus message, CtRequestUpdateStatusResp resp) {
	    if (message == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.dadosSolicitacaoOrigemNaoInformados")));
            return false;
        }
        if (UtilStrings.isNullOrEmpty(message.getNumber()) &&  UtilStrings.isNullOrEmpty(message.getNumberOrigin())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.numeroSolicitacaoNaoInformado")));
            return false;
        }
	    if (message.getStatus() == null || UtilStrings.isNullOrEmpty(message.getStatus().getCode())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.situacaoNaoInformada")));
            return false;
        }
	    if (Enumerados.ServiceRequestStatus.valueOf(message.getStatus().getCode()) == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.situacaoNaoCadastrada")));
            return false;
        }

        return true;
	}

	protected boolean validateCreateOccurrence(RestSessionDTO restSession, CtOccurrenceCreate message, CtOccurrenceCreateResp resp) {
	    if (message == null || message.getOccurrence() == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.dadosNaoInformados")));
            return false;
        }
        if (UtilStrings.isNullOrEmpty(message.getRequestNumber()) &&  UtilStrings.isNullOrEmpty(message.getRequestNumberOrigin())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.numeroSolicitacaoNaoInformado")));
            return false;
        }
	    if (message.getOccurrence().getCategory() == null || UtilStrings.isNullOrEmpty(message.getOccurrence().getCategory().getCode())) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, message.getRequestNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.categoriaDaOcorrenciaNaoInformada"))));
            return false;
        }
	    if (OccurrenceCategory.valueOf(message.getOccurrence().getCategory().getCode()) == null) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, message.getRequestNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.categoriaDaOcorrenciaNaoCadastrada"))));
            return false;
	    }
	    OccurrenceCategory categoria = OccurrenceCategory.valueOf(message.getOccurrence().getCategory().getCode());
	    boolean valido = true;
	    for (int i = 0; i < categoriasNaoPermitidas.length; i++) {
			if (categoriasNaoPermitidas[i].equals(categoria)) {
				valido = false;
				break;
			}
		}
	    if (!valido) {
			resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR, message.getRequestNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.categoriaDaOcorrenciaNaoPermitida"))));
            return false;
	    }
	    /*
		 * if (message.getOccurrence().getOrigin() != null &&
		 * !UtilStrings.isNullOrEmpty(message.getOccurrence().getOrigin().
		 * getCode())) { if
		 * (OrigemOcorrencia.find(message.getOccurrence().getOrigin().getCode())
		 * == null) {
		 * resp.setError(RestOperationUtil.buildError(RestEnum.INPUT_ERROR,
		 * "Origem da ocorrência não cadastrada")); return false; } }
		 */
	    if (!UtilStrings.isNullOrEmpty(message.getOccurrence().getNumberOrigin()) ) {
	        try {
	            if (this.findOccurrence(restSession, message.getOccurrence().getNumberOrigin()) != null) {
					resp.setError(
							RestOperationUtil.buildError(RestEnum.INPUT_ERROR, message.getRequestNumberOrigin().concat(" -> ").concat(RestUtil.i18nMessage(restSession, "rest.service.mobile.operation.categoriaDaOcorrenciaJaCadastrada"))));
	                return false;
	            }
	        } catch (final Exception e) {
	            LOGGER.log(Level.SEVERE, e.getMessage(), e);
	            resp.setError(RestOperationUtil.buildSimpleError(e));
	            return false;
	        }
	    }

        return true;
	}

	protected void updateDeadLine(CtRequest request, SolicitacaoServicoDTO solicitacaoDto) {
    	if (request.getDeadline() > 0) {
    		long timeMillis = request.getDeadline() * 1000;
    		int days = new Double(timeMillis / 86400000).intValue();
    		double hours = new Double((timeMillis - days * 86400000) / 3600000);
    		double minutes = new Double((timeMillis - hours * 3600000) / 60000);

    		solicitacaoDto.setPrazoHH(days * 24 + new Double(UtilNumbersAndDecimals.setRound(hours, 2)).intValue());
    		solicitacaoDto.setPrazoMM(new Double(UtilNumbersAndDecimals.setRound(minutes, 2)).intValue());
    	}
	}

	protected void updateSLA(CtRequest request, SolicitacaoServicoDTO solicitacaoDto, TransactionControler tc) throws Exception {
	    if (request.getStartDateTime() != null || request.getStartSLA() != null || request.getEndSLA() != null || request.getDeadline() > 0) {
	    	solicitacaoDto.setSlaACombinar("N");
	    	if (request.getStartDateTime() != null) {
	    		solicitacaoDto.setDataHoraSolicitacao(UtilDatas.calendarToTimestamp(request.getStartDateTime()));
	    		solicitacaoDto.setDataHoraInicio(UtilDatas.calendarToTimestamp(request.getStartDateTime()));
	    	}
	    	if (request.getStartSLA() != null) {
	    		solicitacaoDto.setDataHoraInicioSLA(UtilDatas.calendarToTimestamp(request.getStartSLA()));
	    	}
	    	if (request.getEndSLA() != null) {
	    		solicitacaoDto.setDataHoraLimite(UtilDatas.calendarToTimestamp(request.getEndSLA()));
	    	}
	    	this.updateDeadLine(request, solicitacaoDto);

	    	this.getSolicitacaoServicoService().updateNotNull(solicitacaoDto, tc);
	    }
	}

	protected String getOrigin(final RestSessionDTO restSession) {
		return UtilStrings.isNullOrEmpty(restSession.getPlatform()) ? restSession.getUser().getLogin() : restSession.getPlatform();
	}

    protected TabFederacaoDadosDTO buildCorrelation(RestSessionDTO restSession, String table, String fromKey, String toKey, TransactionControler tc) throws Exception {
    	TabFederacaoDadosDTO federacaoDados = new TabFederacaoDadosDTO();
    	federacaoDados.setOrigem(this.getOrigin(restSession));
    	federacaoDados.setNomeTabela(table.toUpperCase());
    	federacaoDados.setChaveOriginal(fromKey);
    	federacaoDados.setChaveFinal(toKey);
    	federacaoDados.setUuid(restSession.getUuid());
    	federacaoDados.setUltAtualiz(UtilDatas.getDataHoraAtual());

    	return this.getFederacaoDadosService().createOrUpdate(federacaoDados, tc);
	}

    @SuppressWarnings("unchecked")
	protected TabFederacaoDadosDTO findCorrelation(RestSessionDTO restSession, String table, String fromKey) throws Exception {
    	TabFederacaoDadosDTO result = null;

    	if (!UtilStrings.isNullOrEmpty(fromKey)) {
    		Collection<TabFederacaoDadosDTO> col = this.getFederacaoDadosService().findByChaveOriginal(this.getOrigin(restSession), table, fromKey);
    		if (col != null) {
    			for (TabFederacaoDadosDTO tabFederacaoDados : col) {
					if (UtilNumbersAndDecimals.isInteger(tabFederacaoDados.getChaveFinal())) {
						if (Long.parseLong(tabFederacaoDados.getChaveFinal()) > 0) {
							result = tabFederacaoDados;
							break;
						}
					}
				}
    		}
    	}

    	return result;
	}

	protected ContratoDTO findContract(final RestSessionDTO restSession, final String contractId, Map<String, RestDomainDTO> mapParam, final boolean findDefault, final boolean synchronize) throws Exception {
    	String idContrato = null;

    	if (!UtilStrings.isNullOrEmpty(contractId)) {
    		if (synchronize) {
	    		TabFederacaoDadosDTO federacaoDados = this.findCorrelation(restSession, CONTRATO, contractId);
	        	if (federacaoDados != null) {
	        		idContrato = federacaoDados.getChaveFinal();
	        	}
    		}else{
    			idContrato = contractId;
    		}
    	}

    	if (idContrato == null && findDefault) {
        	idContrato = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_CONTRACT_ID);
    	}

    	if (idContrato != null) {
    		ContratoDTO contrato = new ContratoDTO();
    		contrato.setIdContrato(Integer.valueOf(idContrato));
    		return this.getContratoService().restore(contrato);
    	}

    	return null;
    }

	protected GrupoDTO findGroup(final RestSessionDTO restSession, final String groupId, Map<String, RestDomainDTO> mapParam, final boolean findDefault, final boolean synchronize) throws Exception {
    	String idGrupo = null;

    	if (!UtilStrings.isNullOrEmpty(groupId)) {
    		if (synchronize) {
	    		TabFederacaoDadosDTO federacaoDados = this.findCorrelation(restSession, GRUPO, groupId);
	        	if (federacaoDados != null) {
	        		idGrupo = federacaoDados.getChaveFinal();
	        	}
    		}else{
    			idGrupo = groupId;
    		}
    	}

    	if (idGrupo == null && findDefault) {
        	idGrupo = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_DEFAULT_GROUP_ID);
    	}

    	if (idGrupo != null) {
    		return this.getGrupoService().listGrupoById(Integer.parseInt(idGrupo));
    	}

    	return null;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
	protected ServicoDTO findService(final RestSessionDTO restSession, final CtService service, ServiceDemandType tipoDemandaServico, Map<String, RestDomainDTO> mapParam, final boolean synchronize, final boolean findDefault) throws Exception {
    	String idServico = null;

        if (service != null) {
        	if (!UtilStrings.isNullOrEmpty(service.getCode())) {
        		TabFederacaoDadosDTO federacaoDados = this.findCorrelation(restSession, SERVICO, service.getCode());
            	if (federacaoDados != null) {
            		idServico = federacaoDados.getChaveFinal();
            	}else{
            		idServico = null;
            	}
            }
        	if (idServico == null && !UtilStrings.isNullOrEmpty(service.getName())) {
            	Collection<ServicoDTO> col = this.getServicoService().findByNomeAndContratoAndTipoDemandaAndCategoria(tipoDemandaServico.getId(), null, null, service.getName());
            	if (col != null && !col.isEmpty()) {
    				return (ServicoDTO) ((List) col).get(0);
            	}else if (synchronize) {
                    return this.createService(restSession, tipoDemandaServico, mapParam, service);
            	}
            }
        }

    	if (idServico == null && !synchronize && findDefault) {
    		idServico = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_DEFAULT_SERVICE_ID);
    	}

    	if (idServico != null) {
			return this.getServicoService().findByIdServico(Integer.valueOf(idServico));
    	}

    	return null;
    }

	protected ServicoContratoDTO findContractService(final RestSessionDTO restSession, final ContratoDTO contract, final ServicoDTO service, GrupoDTO grupo, Map<String, RestDomainDTO> mapParam, boolean synchronize) throws Exception {
		ServicoContratoDTO servicoContrato = this.getServicoContratoService().findByIdContratoAndIdServico(contract.getIdContrato(), service.getIdServico());
		if (servicoContrato == null && synchronize) {
			servicoContrato = new ServicoContratoDTO();
			servicoContrato.setIdServico(service.getIdServico());
			servicoContrato.setIdContrato(contract.getIdContrato());
			servicoContrato.setDataInicio(UtilDatas.getDataAtual());
			servicoContrato.setIdGrupoNivel1(Integer.valueOf(ParametroUtil.getValorParametroCitSmartHashMap(Enumerados.ParametroSistema.ID_GRUPO_PADRAO_NIVEL1, "").trim()));
			servicoContrato.setIdCalendario(Integer.valueOf(ParametroUtil.getValorParametroCitSmartHashMap(Enumerados.ParametroSistema.ID_CALENDARIO_PADRAO, "1").trim()));
			servicoContrato.setIdGrupoExecutor(grupo != null ? grupo.getIdGrupo() : null);
			servicoContrato = this.getServicoContratoService().create(servicoContrato);

			AcordoServicoContratoDTO acordoServicoContrato = new AcordoServicoContratoDTO();
			acordoServicoContrato.setIdAcordoNivelServico(Integer.valueOf(RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_DEFAULT_SLA)));
			acordoServicoContrato.setIdServicoContrato(servicoContrato.getIdServicoContrato());
			acordoServicoContrato.setDataInicio(UtilDatas.getDataAtual());
			acordoServicoContrato.setHabilitado("A");

			List<ServicoContratoDTO> listaServicoContrato = new ArrayList<ServicoContratoDTO>();
			listaServicoContrato.add(servicoContrato);
			acordoServicoContrato.setListaServicoContrato(listaServicoContrato);

			this.getAcordoServicoContratoService().create(acordoServicoContrato);
		}

		return servicoContrato;
	}

	protected CategoriaServicoDTO findServiceCategory(Integer id, String name, String categoryType, boolean synchronize) throws Exception {
    	CategoriaServicoDTO categoriaServico = null;
    	if (id != null) {
    		categoriaServico = new CategoriaServicoDTO();
    		categoriaServico.setIdCategoriaServico(id);
    		categoriaServico = this.getCategoriaServicoService().restore(categoriaServico);
    	}else if (!UtilStrings.isNullOrEmpty(name)) {
	    	List<CategoriaServicoDTO> list = this.getCategoriaServicoService().findByNomeCategoria(name);
	    	if (list != null && !list.isEmpty()) {
	    		return list.get(0);
	    	}else if (synchronize){
	    		categoriaServico = new CategoriaServicoDTO();
	    		categoriaServico.setIdEmpresa(Integer.valueOf(1));
	    		categoriaServico.setNomeCategoriaServico(name);
	    		categoriaServico.setNomeCategoriaServicoConcatenado(name);
	    		categoriaServico.setDataInicio(UtilDatas.getDataAtual());
				categoriaServico.setTipoCategoria(categoryType);
	    		categoriaServico = this.getCategoriaServicoService().create(categoriaServico);
	    		return categoriaServico;
	    	}
    	}

    	return categoriaServico;
	}

    protected SolicitacaoServicoDTO findRequest(final RestSessionDTO restSession, final String numberOrigin, final String number) throws Exception {
    	SolicitacaoServicoDTO result = null;

    	if (UtilStrings.isNullOrEmpty(number) && !UtilStrings.isNullOrEmpty(numberOrigin)) {
	    	TabFederacaoDadosDTO federacaoDados = this.findCorrelation(restSession, SOLICITACAOSERVICO, numberOrigin);
	    	if (federacaoDados != null) {
	    		Integer id = Integer.valueOf(federacaoDados.getChaveFinal());
	    		if (id > 0) {
	    			result = this.getSolicitacaoServicoService().restoreAll(id);
	    		}
	    	}
    	}else if (!UtilStrings.isNullOrEmpty(number)) {
    		result = this.getSolicitacaoServicoService().restoreAll(Integer.valueOf(number));
    	}

    	return result;
    }

    protected OcorrenciaSolicitacaoDTO findOccurrence(final RestSessionDTO restSession, final String numberOrigin) throws Exception {
    	OcorrenciaSolicitacaoDTO result = null;

    	if (!UtilStrings.isNullOrEmpty(numberOrigin)) {
	    	TabFederacaoDadosDTO federacaoDados = this.findCorrelation(restSession, OCORRENCIASOLICITACAO, numberOrigin);
	    	if (federacaoDados != null) {
	    		Integer id = Integer.valueOf(federacaoDados.getChaveFinal());
	    		if (id > 0) {
	    			result = this.getOcorrenciaSolicitacaoService().findByIdOcorrencia(id);
	    		}
	    	}
    	}

    	return result;
    }

	protected EmpregadoDTO createEmployee(final RestSessionDTO restSession, final CtContact contact) throws LogicException, ServiceException {
		EmpregadoDTO empregado = new EmpregadoDTO();
    	empregado.setNome(contact.getName());
    	empregado.setTelefone(contact.getPhoneNumber());
    	empregado.setEmail(contact.getEmail());
    	empregado.setNome(contact.getName());
    	empregado.setIdUnidade(restSession.getDptoId());
    	empregado.setIdSituacaoFuncional(Integer.valueOf("1"));

    	empregado = this.getEmpregadoService().create(empregado);

    	return empregado;
	}

	protected UsuarioDTO createUser(final String login, final EmpregadoDTO empregado) throws LogicException, ServiceException {
		UsuarioDTO usuario = new UsuarioDTO();
		usuario.setIdUnidade(empregado.getIdUnidade());
		usuario.setAcessoCitsmart("N");
		usuario.setEmail(empregado.getEmail());
		usuario.setIdEmpregado(empregado.getIdEmpregado());
		usuario.setIdEmpresa(Integer.parseInt("1"));
		usuario.setNomeUsuario(empregado.getNome());
		usuario.setLogin(login);
		usuario.setStatus("A");
		usuario.setLdap("N");

		usuario = this.getUsuarioService().create(usuario);
		return usuario;
	}


	protected ServicoDTO createService(RestSessionDTO restSession, ServiceDemandType tipoDemandaServico, Map<String, RestDomainDTO> mapParam, CtService service) throws Exception {
		CategoriaServicoDTO categoriaServico = null;
    	if (service.getCategory() != null && !UtilStrings.isNullOrEmpty(service.getCategory().getName())) {
			categoriaServico = this.findServiceCategory(null, service.getCategory().getName(), tipoDemandaServico.getClassification(), true);
    	}else {
    		String idCategoria = RestUtil.getRestParameterService(restSession).getParamValue(mapParam, RestEnum.PARAM_DEFAULT_CATEGORY_ID);
        	if (!UtilStrings.isNullOrEmpty(idCategoria)) {
				categoriaServico = this.findServiceCategory(Integer.valueOf(idCategoria), null, tipoDemandaServico.getClassification(), true);
        	}
    	}

    	if (categoriaServico == null) {
			throw new LogicException("rest.service.mobile.operation.categoriaServicoNaoInformada");
		}

		ServicoDTO servico = new ServicoDTO();
		servico.setIdCategoriaServico(categoriaServico.getIdCategoriaServico());
		servico.setIdSituacaoServico(Integer.valueOf(1));
		servico.setIdTipoServico(Integer.valueOf(1));
		servico.setIdEmpresa(Integer.valueOf(1));
		servico.setNomeServico(service.getName());
		servico.setDetalheServico(service.getName());
		servico.setIdTipoDemandaServico(tipoDemandaServico.getId());
		servico = this.getServicoService().create(servico);

		if (!UtilStrings.isNullOrEmpty(service.getCode())) {
			this.buildCorrelation(restSession, SERVICO, service.getCode(), servico.getIdServico().toString(), null);
		}

		return servico;
	}

	protected EmpregadoDTO findEmployee(final RestSessionDTO restSession, final CtRequest request, final boolean synchronize) throws LogicException, ServiceException {
		EmpregadoDTO empregado = null;
		if (!UtilStrings.isNullOrEmpty(request.getUserID())) {
	        empregado = RestUtil.getEmpregadoByLogin(request.getUserID());
	        if (empregado == null && synchronize) {
	        	empregado = this.createEmployee(restSession, request.getContact());

	        	UsuarioDTO usuario = this.getUsuarioService().restoreByLogin(request.getUserID());
	        	if (usuario == null) {
	        		usuario = this.createUser(request.getUserID(), empregado);
	        	}else{
	        		usuario.setIdEmpregado(empregado.getIdEmpregado());
	        		this.getUsuarioService().updateNotNull(usuario);
	        	}
	        }
		}

        return empregado;
    }

    protected List<Integer> buildGroupList(CtRequestGetList message) {
        List<Integer> groupList = new ArrayList<Integer>();
        if (message.getGroupList() != null && !message.getGroupList().isEmpty()) {
        	GrupoDTO grupoFind = new GrupoDTO();
        	grupoFind.setIdGrupo(0);
        	for (String groupID : message.getGroupList()) {
        		grupoFind.setSigla(groupID);
				try {
					GrupoDTO grupo = this.getGrupoService().restoreBySigla(grupoFind);
	        		if (grupo != null) {
	        			groupList.add(grupo.getIdGrupo());
	        		}
	        	} catch (PersistenceException e) {
					e.printStackTrace();
				}
			}
        }
        if (groupList.isEmpty()) {
        	groupList.add(null);
        }

        return groupList;
	}

    protected List<Integer> buildContractList(CtRequestGetList message) {
        List<Integer> contractList = new ArrayList<Integer>();
        if (message.getContractID() != null) {
        	contractList.add(Integer.valueOf(message.getContractID()));
        }
        if (message.getContractList() != null && !message.getContractList().isEmpty()) {
        	for (String contractID : message.getContractList()) {
            	contractList.add(Integer.valueOf(contractID));
			}
        }
        if (contractList.isEmpty()) {
        	contractList.add(null);
        }

        return contractList;
	}

    protected List<ServiceRequestStatus> buildStatusList(CtRequestGetList message) {
        List<ServiceRequestStatus> statusList = new ArrayList<ServiceRequestStatus>();
        if (message.getStatus() != null && !UtilStrings.isNullOrEmpty(message.getStatus().getCode())) {
        	ServiceRequestStatus status = ServiceRequestStatus.valueOf(message.getStatus().getCode());
        	if (status != null) {
        		statusList.add(status);
        	}
        }
        if (message.getStatusList() != null && !message.getStatusList().isEmpty()) {
        	for (String statusCode : message.getStatusList()) {
            	ServiceRequestStatus status = ServiceRequestStatus.valueOf(statusCode);
            	if (status != null) {
            		statusList.add(status);
            	}
			}
        }
        if (statusList.isEmpty()) {
        	statusList.add(null);
        }

        return statusList;
	}

    protected SolicitacaoServicoDTO buildRequestFromJson(final String json) {
        SolicitacaoServicoDTO solicitacao = null;
        if (!UtilStrings.isNullOrEmpty(json)) {
			try {
				solicitacao = this.getGson().fromJson(json, SolicitacaoServicoDTO.class);
			} catch (final Exception e) {
			}
        }

        return solicitacao;
    }

    private OccurrenceCategory[] categoriasNaoPermitidas = new OccurrenceCategory[]{OccurrenceCategory.CREATION
    																				 ,OccurrenceCategory.SLA_START
    																				 ,OccurrenceCategory.SLA_SUSPENSION
    																				 ,OccurrenceCategory.SLA_REACTIVATION};

    private SolicitacaoServicoService solicitacaoServicoService;
    private ServicoService servicoService;
    private ServicoContratoService servicoContratoService;
    private TabFederacaoDadosService federacaoDadosService;
    private EmpregadoService empregadoService;
    private UsuarioService usuarioService;
    private ContratoService contratoService;
    private CategoriaServicoService categoriaServicoService;
    private AcordoServicoContratoService acordoServicoContratoService;
    private GrupoService grupoService;
    private OcorrenciaSolicitacaoService ocorrenciaSolicitacaoService;
    private AprovacaoSolicitacaoServicoService aprovacaoSolicitacaoServicoService;
    private JustificativaSolicitacaoService justificativaSolicitacaoService;
    private RestLogService restLogService;

    protected RestLogService getRestLogService() {
        if (restLogService == null) {
            try {
            	restLogService = (RestLogService) ServiceLocator.getInstance().getService(RestLogService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return restLogService;
    }

    protected SolicitacaoServicoService getSolicitacaoServicoService() {
        if (solicitacaoServicoService == null) {
            try {
            	solicitacaoServicoService = (SolicitacaoServicoService) ServiceLocator.getInstance().getService(SolicitacaoServicoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return solicitacaoServicoService;
    }

    protected ServicoService getServicoService() {
        if (servicoService == null) {
            try {
            	servicoService = (ServicoService) ServiceLocator.getInstance().getService(ServicoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return servicoService;
    }

    protected ServicoContratoService getServicoContratoService() {
        if (servicoContratoService == null) {
            try {
            	servicoContratoService = (ServicoContratoService) ServiceLocator.getInstance().getService(ServicoContratoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return servicoContratoService;
    }

    protected TabFederacaoDadosService getFederacaoDadosService() {
        if (federacaoDadosService == null) {
            try {
            	federacaoDadosService = (TabFederacaoDadosService) ServiceLocator.getInstance().getService(TabFederacaoDadosService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return federacaoDadosService;
    }

    protected EmpregadoService getEmpregadoService() {
        if (empregadoService == null) {
            try {
            	empregadoService = (EmpregadoService) ServiceLocator.getInstance().getService(EmpregadoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return empregadoService;
    }

    protected UsuarioService getUsuarioService() {
        if (usuarioService == null) {
            try {
            	usuarioService = (UsuarioService) ServiceLocator.getInstance().getService(UsuarioService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return usuarioService;
    }

    protected ContratoService getContratoService() {
        if (contratoService == null) {
            try {
            	contratoService = (ContratoService) ServiceLocator.getInstance().getService(ContratoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return contratoService;
    }

    protected CategoriaServicoService getCategoriaServicoService() {
        if (categoriaServicoService == null) {
            try {
            	categoriaServicoService = (CategoriaServicoService) ServiceLocator.getInstance().getService(CategoriaServicoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return categoriaServicoService;
    }

    protected AcordoServicoContratoService getAcordoServicoContratoService() {
        if (acordoServicoContratoService == null) {
            try {
            	acordoServicoContratoService = (AcordoServicoContratoService) ServiceLocator.getInstance().getService(AcordoServicoContratoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return acordoServicoContratoService;
    }

    protected GrupoService getGrupoService() {
        if (grupoService == null) {
            try {
            	grupoService = (GrupoService) ServiceLocator.getInstance().getService(GrupoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return grupoService;
    }

    protected OcorrenciaSolicitacaoService getOcorrenciaSolicitacaoService() {
        if (ocorrenciaSolicitacaoService == null) {
            try {
            	ocorrenciaSolicitacaoService = (OcorrenciaSolicitacaoService) ServiceLocator.getInstance().getService(OcorrenciaSolicitacaoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return ocorrenciaSolicitacaoService;
    }

    private AprovacaoSolicitacaoServicoService getAprovacaoSolicitacaoServicoService() {
        if (aprovacaoSolicitacaoServicoService == null) {
            try {
            	aprovacaoSolicitacaoServicoService = (AprovacaoSolicitacaoServicoService) ServiceLocator.getInstance().getService(AprovacaoSolicitacaoServicoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return aprovacaoSolicitacaoServicoService;
    }

    private JustificativaSolicitacaoService getJustificativaSolicitacaoService() {
        if (justificativaSolicitacaoService == null) {
            try {
            	justificativaSolicitacaoService = (JustificativaSolicitacaoService) ServiceLocator.getInstance().getService(JustificativaSolicitacaoService.class, null);
            } catch (final ServiceException e) {
                RestUtil.handleServiceException(LOGGER, e);
            }
        }
        return justificativaSolicitacaoService;
    }

    protected void rollbackTransaction(final TransactionControler tc)  {
        if (tc != null) {
            try {
                if (tc.isStarted()) { // Se estiver startada, entao faz roolback.
                    tc.rollback();
                }

                tc.closeQuietly();
            } catch (final Exception e) {
            	LOGGER.log(Level.SEVERE, e.getMessage(), e);
            }
        }
    }

}