class MergeCaseServiceImpl implements MergeCaseService {

    @Override
    @Transactional
    public CaseFile mergeCases(Authentication auth, String ipAddress, MergeCaseOptions mergeCaseOptions)
            throws PipelineProcessException, MergeCaseFilesException, AcmUserActionFailedException, AcmCreateObjectFailedException,
            AcmAccessControlException
    {

        CaseFile source = caseFileDao.find(mergeCaseOptions.getSourceCaseFileId());
        if (source == null)
            throw new AcmCaseFileNotFound("Source Case File with id = " + mergeCaseOptions.getSourceCaseFileId() + " not found");
        if (hasBeenMerged(source))
            throw new MergeCaseFilesException("Source is already merged");
        CaseFile target = caseFileDao.find(mergeCaseOptions.getTargetCaseFileId());
        if (target == null)
            throw new AcmCaseFileNotFound("Target Case File with id = " + mergeCaseOptions.getTargetCaseFileId() + " not found");
        log.info("Going to merge {} into {}", source.getCaseNumber(), target.getCaseNumber());
        // merge details
        // String sourceDetails = StringUtils.isEmpty(source.getDetails()) ? "" : String.format(MERGE_TEXT_SEPPARATOR,
        // source.getTitle(), source.getCaseNumber()) + source.getDetails();
        // target.setDetails(!StringUtils.isEmpty(target.getDetails()) ?
        // target.getDetails() + sourceDetails :
        // sourceDetails);

        // merge folders and documents
        mergeFoldersAndDocuments(source, target);

        ObjectAssociation childObjectSource = new ObjectAssociation();
        childObjectSource.setAssociationType("REFERENCE");
        childObjectSource.setCategory("MERGED_TO");
        childObjectSource.setTargetId(target.getId());
        childObjectSource.setTargetType(target.getObjectType());
        childObjectSource.setTargetTitle(target.getTitle());
        childObjectSource.setTargetName(target.getCaseNumber());
        source.addChildObject(childObjectSource);

        ObjectAssociation childObjectTarget = new ObjectAssociation();
        childObjectTarget.setAssociationType("REFERENCE");
        childObjectTarget.setCategory("MERGED_FROM");
        childObjectTarget.setTargetId(source.getId());
        childObjectTarget.setTargetType(source.getObjectType());
        childObjectTarget.setTargetTitle(source.getTitle());
        childObjectTarget.setTargetName(source.getCaseNumber());
        target.addChildObject(childObjectTarget);

        source.setStatus("CLOSED");

        // set current user as assignee
        handleParticipants(auth, target);

        saveCaseService.saveCase(source, auth, ipAddress);
        target = saveCaseService.saveCase(target, auth, ipAddress);

        return target;
    }

}