class CaseFileEventListener implements ApplicationListener<AcmObjectHistoryEvent> {

    @Override
    public void onApplicationEvent(AcmObjectHistoryEvent event)
    {
        if (event != null)
        {
            AcmObjectHistory acmObjectHistory = (AcmObjectHistory) event.getSource();

            boolean isCaseFile = checkExecution(acmObjectHistory.getObjectType());

            if (isCaseFile)
            {
                // Converter for JSON string to Object
                AcmUnmarshaller converter = getObjectConverter().getJsonUnmarshaller();

                String jsonUpdatedCaseFile = acmObjectHistory.getObjectString();
                CaseFile updatedCaseFile = converter.unmarshall(jsonUpdatedCaseFile, CaseFile.class);

                AcmAssignment acmAssignment = createAcmAssignment(updatedCaseFile);

                AcmObjectHistory acmObjectHistoryExisting = getAcmObjectHistoryService().getAcmObjectHistory(updatedCaseFile.getId(),
                        CaseFileConstants.OBJECT_TYPE);

                if (acmObjectHistoryExisting != null)
                {

                    String json = acmObjectHistoryExisting.getObjectString();
                    CaseFile existing = converter.unmarshall(json, CaseFile.class);

                    if (existing != null)
                    {
                        acmAssignment.setOldAssignee(ParticipantUtils.getAssigneeIdFromParticipants(existing.getParticipants()));

                        if (isPriorityChanged(existing, updatedCaseFile))
                        {
                            getCaseFileEventUtility().raiseCaseFileModifiedEvent(updatedCaseFile, event.getIpAddress(), "priority.changed");
                        }

                        if (isDetailsChanged(existing, updatedCaseFile))
                        {
                            getCaseFileEventUtility().raiseCaseFileModifiedEvent(updatedCaseFile, event.getIpAddress(), "details.changed");
                        }

                        String title = existing.getTitle();
                        String updatedTitle = updatedCaseFile.getTitle();
                        if (!Objects.equals(title, updatedTitle))
                        {
                            getCaseFileEventUtility().raiseCaseFileModifiedEvent(updatedCaseFile, event.getIpAddress(), "title.changed",
                                    "Case File Title changed from " + title + " to " + updatedTitle);
                        }

                        String owningGroup = ParticipantUtils.getOwningGroupIdFromParticipants(existing.getParticipants());
                        String updatedOwningGroup = ParticipantUtils.getOwningGroupIdFromParticipants(updatedCaseFile.getParticipants());
                        if (!Objects.equals(owningGroup, updatedOwningGroup))
                        {
                            AcmParticipant updatedParticipant = updatedCaseFile.getParticipants().stream()
                                    .filter(p -> "owning group".equals(p.getParticipantType())).findFirst().orElse(null);
                            getCaseFileEventUtility().raiseParticipantsModifiedInCaseFile(updatedParticipant, updatedCaseFile,
                                    event.getIpAddress(), "changed",
                                    "Owning Group Changed from " + owningGroup + " to " + updatedOwningGroup);
                        }

                        checkParticipants(existing, updatedCaseFile, event.getIpAddress());

                        if (isStatusChanged(existing, updatedCaseFile))
                        {
                            String calId = updatedCaseFile.getContainer().getCalendarFolderId();
                            if (shouldDeleteOnClose() && calId != null && caseFileStatusClosed.contains(updatedCaseFile.getStatus()))
                            {

                                // delete shared calendar if case closed
                                Optional<AcmOutlookUser> user = calendarAdminService
                                        .getEventListenerOutlookUser(CaseFileConstants.OBJECT_TYPE);
                                // if integration is not enabled the user will be null.
                                if (user.isPresent())
                                {
                                    getCalendarService().deleteFolder(user.get(), updatedCaseFile.getContainer(),
                                            DeleteMode.MoveToDeletedItems);
                                    folderCreatorDao.deleteObjectReference(updatedCaseFile.getId(), updatedCaseFile.getObjectType());
                                }
                            }
                            getCaseFileEventUtility().raiseCaseFileModifiedEvent(updatedCaseFile, event.getIpAddress(), "status.changed",
                                        "from " + existing.getStatus() + " to " + updatedCaseFile.getStatus());

                        }
                    }
                }

                if (isAssigneeChanged(acmAssignment))
                {
                    // Save assignment change in the database
                    AcmAssignment assignmentSaved = getAcmAssignmentDao().save(acmAssignment);

                    // Raise an event
                    getAcmObjectHistoryEventPublisher().publishAssigneeChangeEvent(assignmentSaved, event.getUserId(),
                            event.getIpAddress());
                }
            }
        }
    }

}