All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.aem.formsndocuments.rnc.ReviewManagementServiceImpl Maven / Gradle / Ivy

/***************************************************************************
 * ADOBE CONFIDENTIAL
 * ___________________
 *
 *  Copyright 2013 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
package com.adobe.aem.formsndocuments.rnc;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.ValueFormatException;

import com.adobe.aem.formsndocuments.util.FMUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.base.util.AccessControlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.aem.formsndocuments.exception.FormsNDocumentsException;
import com.adobe.aem.formsndocuments.util.RnCUtil;
import com.adobe.granite.resourceresolverhelper.ResourceResolverHelper;
import com.adobe.granite.taskmanagement.Task;
import com.adobe.granite.taskmanagement.TaskManager;
import com.adobe.granite.taskmanagement.TaskManagerException;
import com.adobe.granite.workflow.exec.Status;
import com.adobe.aemforms.fm.exception.FormsMgrException;
import com.adobe.aem.formsndocuments.util.FMConstants;
import javax.jcr.security.Privilege;

/**
 * The ReviewManagementService is the service which provides
 * functionality to support Review Management.
 * 
 * @author sakarora
 */
@Component(immediate = true)
@Service(value = ReviewManagementService.class)
public class ReviewManagementServiceImpl implements ReviewManagementService {
	private static final String REVIEW_CONTAINER_PATH = "/jcr:content/reviewcontainer";
    private static final String REVIEW_GROUPS_PATH = "forms/rnc";
	private static final String METADATA_PATH = "/jcr:content/metadata";
	private static final String EVERYONE = "everyone";
	private static final String REMOVED_REVIEWERS = "removedReviewers";
	private static final String ADDED_REVIEWERS = "addedReviewers";
	private static final String MIXIN_MODIFY = "mix:lastModified";
	private static final String MIXIN_ACESS = "rep:AccessControllable";
	private static final String NT_UNSTRUCTURED = "nt:unstructured";

	@Reference(referenceInterface = SlingRepository.class)
	SlingRepository slingRepository;

	@Reference(referenceInterface = ResourceResolverHelper.class)
	ResourceResolverHelper resourceResolverHelper;

	@Reference(referenceInterface = ResourceResolverFactory.class)
	ResourceResolverFactory resourceResolverFactory;

	private static Logger logger = LoggerFactory
			.getLogger(ReviewManagementServiceImpl.class);

	private void createReviewContainer(String assetPath, String initiatorId, Session session,
			ResourceResolver resourceResolver) throws FormsNDocumentsException {
		logger.trace("Entering createReviewContainer.");
		try {
			Node asset = RnCUtil.checkNodeExistance(assetPath, resourceResolver);
			UserManager um = resourceResolver.adaptTo(UserManager.class);
			// If review container is not present i.e. when review is Created for first time then,
			// Add reviewcontainer & reviewtasks node and deny jcr:all permission to forms-users group.
			if (!asset.hasNode(REVIEW_CONTAINER_PATH.substring(1))) {
				// Create reviewcontainer node
				Node reviewContainer = asset.addNode(REVIEW_CONTAINER_PATH.substring(1),
						FMConstants.SLING_FOLDER_NODETYPE);
				reviewContainer.addMixin(MIXIN_MODIFY);

				// Create reviewtasks node
				Node reviewTasks = asset.addNode(RnCUtil.REVIEW_TASKS_PATH.substring(1),
						FMConstants.SLING_FOLDER_NODETYPE);
				reviewTasks.addMixin(MIXIN_MODIFY);

				// Deny jcr:all permission to everyone on reviewtasks node.
				Authorizable formsUserAuth = um.getAuthorizable(EVERYONE);
				AccessControlUtil.replaceAccessControlEntry(session, assetPath + RnCUtil.REVIEW_TASKS_PATH,
						formsUserAuth.getPrincipal(), new String[] {}, new String[] { Privilege.JCR_ALL },
						new String[] {}, null);

				// Provide required permission to service user.
				Authorizable serviceUserAuth = um.getAuthorizable(session.getUserID());
				AccessControlUtil.replaceAccessControlEntry(session, assetPath + RnCUtil.REVIEW_TASKS_PATH,
						serviceUserAuth.getPrincipal(), new String[]{ Privilege.JCR_READ, Privilege.JCR_VERSION_MANAGEMENT, 
						FMConstants.CRX_REPLICATE_PRIVILEGE, FMConstants.REP_WRITE_PRIVILEGE, Privilege.JCR_MODIFY_ACCESS_CONTROL, 
						Privilege.JCR_READ_ACCESS_CONTROL }, new String[]{}, new String[]{}, null);
			}
			// Provide jcr:read & rep:write permission to review initiator on reviewtasks node whenever review is initiated.
			Authorizable initiatorAuth = um.getAuthorizable(initiatorId);
			AccessControlUtil.replaceAccessControlEntry(session, assetPath + RnCUtil.REVIEW_TASKS_PATH,
					initiatorAuth.getPrincipal(), new String[] { Privilege.JCR_READ, FMConstants.REP_WRITE_PRIVILEGE },
					new String[] {}, new String[] {}, null);
			session.save();

		} catch (RepositoryException e) {
			logger.error("Exception while creating review container for asset "
					+ assetPath , e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_022, args);
		}
		logger.trace("Exiting createReviewContainer.");
	}

	private String createReviewNode(String assetPath, String reviewId,
			String reviewGroupId, Session session,
			ResourceResolver resourceResolver) throws FormsNDocumentsException {
		logger.trace("Entering createReviewNode.");
		try {
			Node asset = RnCUtil
					.checkNodeExistance(assetPath, resourceResolver);
			reviewId = reviewId.replace("\"", "_");
			String reviewNodePath = REVIEW_CONTAINER_PATH.substring(1) + "/"
					+ reviewId;
			Node reviewContainer = asset.addNode(reviewNodePath,
					NT_UNSTRUCTURED);
			reviewContainer.addMixin(MIXIN_MODIFY);
			reviewContainer.addMixin(MIXIN_ACESS);

			UserManager um = resourceResolver.adaptTo(UserManager.class);

			// Deny write permission to everyone.
			Authorizable everyoneAuth = um.getAuthorizable(EVERYONE);
			AccessControlUtil.replaceAccessControlEntry(session, assetPath
							+ "/" + reviewNodePath, everyoneAuth.getPrincipal(),
					new String[] {}, new String[] { FMConstants.REP_WRITE_PRIVILEGE },
					new String[] {}, null);

			// Provide write permission to review group.
			Authorizable reviewGrpAuth = um.getAuthorizable(reviewGroupId);
			AccessControlUtil.replaceAccessControlEntry(session, assetPath
					+ "/" + reviewNodePath, reviewGrpAuth.getPrincipal(),
					new String[] { FMConstants.REP_WRITE_PRIVILEGE }, new String[] {},
					new String[] {}, null);

			// Provide write permission to service user.
			Authorizable serviceUserAuth = um.getAuthorizable(session.getUserID());
			AccessControlUtil.replaceAccessControlEntry(session, assetPath
							+ "/" + reviewNodePath, serviceUserAuth.getPrincipal(),
					new String[]{ FMConstants.REP_WRITE_PRIVILEGE }, new String[]{},
					new String[]{}, null);

		} catch (RepositoryException e) {
			logger.error("Exception while creating review node for asset "
					+ assetPath + " exception: " , e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_009, args);
		}
		logger.trace("Exiting createReviewNode.");
		return reviewId;
	}

	private Task addReviewerTask(String reviewProjectId, String reviewName,
			String deadline, String reviewer, String assetPath,
			String reviewGroupId, String reviewDescription, ResourceResolver bundleResourceResolver,
			ResourceResolver resourceResolver) throws FormsNDocumentsException {
		logger.trace("Entering addReviewerTask.");
		Task task = null;
		try {
			task = RnCUtil.createTask(reviewProjectId, reviewName, deadline,
					reviewer, assetPath, reviewDescription, bundleResourceResolver, resourceResolver);
		} catch (TaskManagerException e) {
			logger.error("Exception while creating Task " , e);
			Object[] args=null;
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_006, args);
		}
		logger.trace("Exiting addReviewerTask.");
		return task;
	}

	private void removeReviewerTask(String reviewProjectName, String reviewer,
			String reviewGroupId, String reviewInitiator,
			ResourceResolver resourceResolver) throws FormsNDocumentsException {
		logger.trace("Entering removeReviewerTask.");
		if (reviewProjectName == null || reviewer == null
				|| reviewGroupId == null) {
			return;
		}
		if (reviewProjectName.isEmpty() || reviewer.isEmpty()
				|| reviewGroupId.isEmpty()) {
			return;
		}
		try {
			TaskManager taskManager = resourceResolver
					.adaptTo(TaskManager.class);
			Task task = taskManager.getTask(reviewProjectName, true);
			if (task != null) {
				List subTaskList = task.getSubTasks();
				if (subTaskList != null) {
					for (Task subTask : subTaskList) {
						String assignee = subTask.getCurrentAssignee();
						if (assignee.equals(reviewer)
								&& !Status.COMPLETE.equals(subTask.getStatus())) {
							taskManager.terminateTask(subTask.getId());
						}
					}
				}
			}

		} catch (TaskManagerException e) {
			logger.error("Exception while terminating Task " , e);
			Object[] args=null;
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_007, args);
		}
		logger.trace("Exiting removeReviewerTask.");
	}

	private void addAssetReviewInfo(String assetPath, String reviewName,
			String reviewDescription, String reviewProjectId,
			String deadline, String reviewGroup, String reviewId,
			ResourceResolver resourceResolver) throws FormsNDocumentsException {
		logger.trace("Entering addAssetReviewInfo.");
		try {
			Node asset = RnCUtil.getNode(assetPath + METADATA_PATH,
					resourceResolver);
			if (asset == null) {
				return;
			}
			String initiatorId = resourceResolverHelper.getResourceResolverAs(
					Session.class).getUserID();
			Node review = RnCUtil.getNode(assetPath + REVIEW_CONTAINER_PATH
					+ "/" + reviewId, resourceResolver);
			asset.setProperty(RnCUtil.UNDER_REVIEW, true);
			asset.setProperty(RnCUtil.REVIEW_ID, reviewId);
			asset.setProperty(RnCUtil.REVIEW_INITIATOR, initiatorId);

			review.setProperty(RnCUtil.REVIEW_PROJECT_NAME, reviewProjectId);
			review.setProperty(RnCUtil.REVIEW_NAME, reviewName);
			review.setProperty(RnCUtil.REVIEW_ID, reviewId);
			review.setProperty(RnCUtil.REVIEW_INITIATOR, initiatorId);
			review.setProperty(RnCUtil.REVIEW_DESCRIPTION, reviewDescription);
			review.setProperty(RnCUtil.REVIEW_GROUP, reviewGroup);
			review.setProperty(RnCUtil.REVIEW_DEADLINE, deadline);
		} catch (RepositoryException e) {
			logger.error("Exception while setting Review state " , e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_010, args);
		}
		logger.trace("Exiting addAssetReviewInfo.");
	}

	private void removeAssetReviewInfo(String assetPath,
			ResourceResolver resourceResolver) throws FormsNDocumentsException {
		logger.trace("Entering addAssetReviewInfo.");
		try {
			Node asset = RnCUtil.getNode(assetPath + METADATA_PATH,
					resourceResolver);
			if (asset == null) {
				return;
			}

			asset.setProperty(RnCUtil.UNDER_REVIEW, false);

			String reviewId = "";
			if (asset.hasProperty(RnCUtil.REVIEW_ID)) {
				reviewId = asset.getProperty(RnCUtil.REVIEW_ID).getString();
				asset.getProperty(RnCUtil.REVIEW_ID).remove();
			}
			if (asset.hasProperty(RnCUtil.REVIEW_INITIATOR)) {
				asset.getProperty(RnCUtil.REVIEW_INITIATOR).remove();
			}

			Node review = RnCUtil.getNode(assetPath + REVIEW_CONTAINER_PATH
					+ "/" + reviewId, resourceResolver);
			if (review != null && review.hasProperty(RnCUtil.REVIEW_GROUP)) {
				review.getProperty(RnCUtil.REVIEW_GROUP).remove();
			}

		} catch (RepositoryException e) {
			logger.error("Exception while clearing review state " , e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_011, args);
		}
		logger.trace("Exiting addAssetReviewInfo.");
	}

	private void cleanUpPermissions(String assetPath,
			String reviewGroup, String reviewID, ResourceResolver bundleResourceResolver,
			ResourceResolver currentResourceResolver) throws FormsNDocumentsException {
		logger.trace("Entering cleanUpPermissions.");
		try {
			String reviewContainerPath = assetPath + REVIEW_CONTAINER_PATH + "/"
					+ reviewID;
			Node reviewContainerNode = RnCUtil.getNode(reviewContainerPath, currentResourceResolver);
			if (reviewContainerNode == null) {
				// First Review no comments node, implies no permissions
				// applied, so return.
				return;
			}

			UserManager um = bundleResourceResolver.adaptTo(UserManager.class);
			Authorizable authorizable = um.getAuthorizable(EVERYONE);
            Session bundleSession = bundleResourceResolver.adaptTo(Session.class);

			AccessControlUtil.replaceAccessControlEntry(bundleSession, reviewContainerPath,
					authorizable.getPrincipal(), new String[] {},
					new String[] {}, new String[] { FMConstants.REP_WRITE_PRIVILEGE },
					null);

			authorizable = um.getAuthorizable(reviewGroup);
			AccessControlUtil.replaceAccessControlEntry(bundleSession, reviewContainerPath,
					authorizable.getPrincipal(), new String[] {},
					new String[] {}, new String[] { FMConstants.REP_WRITE_PRIVILEGE },
					null);

			if(reviewContainerNode.hasProperty(RnCUtil.REVIEW_INITIATOR)) {
				String initiatorId = reviewContainerNode.getProperty(RnCUtil.REVIEW_INITIATOR).getString();
				// Remove read & write permission of review initiator from reviewtasks node.
				Authorizable initiatorAuth = um.getAuthorizable(initiatorId);
				AccessControlUtil.replaceAccessControlEntry(bundleSession,
						assetPath + RnCUtil.REVIEW_TASKS_PATH, initiatorAuth.getPrincipal(),
						new String[] {}, new String[] {}, new String[] {Privilege.JCR_READ, FMConstants.REP_WRITE_PRIVILEGE}, null);
			}
		} catch (RepositoryException e) {
			logger.error("Exception while removing permissions on comments node for asset "
					+ assetPath , e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_016, args);
		}
		logger.trace("Exiting cleanUpPermissions.");
	}

	private Map> getReviewersDiff(String[] newList,
			String reviewerGroupId, ResourceResolver bundleResourceResolver)
			throws FormsNDocumentsException {
		logger.trace("Entering getReviewersDiff.");
		Map> reviewerDiff = new HashMap>();
		List reviewersList = new ArrayList();
		List removedReviewers = new ArrayList();
		List addedReviewers = new ArrayList();
		try {
			UserManager um = bundleResourceResolver.adaptTo(UserManager.class);
			Group reviewGroup = (Group) um.getAuthorizable(reviewerGroupId);
			Iterator iterator = reviewGroup.getDeclaredMembers();
			while (iterator.hasNext()) {
				String id = iterator.next().getID();
				reviewersList.add(id);
			}
			for (String id : reviewersList) {
				if (!RnCUtil.isInArray(id, newList)) {
					removedReviewers.add(id);
				}
			}
			for (String id : newList) {
				if (!reviewersList.contains(id)) {
					addedReviewers.add(id);
				}
			}
			reviewerDiff.put(REMOVED_REVIEWERS, removedReviewers);
			reviewerDiff.put(ADDED_REVIEWERS, addedReviewers);
		} catch (RepositoryException e) {
			logger.error("Exception while retrieving group members for group "
					+ reviewerGroupId , e);
			Object[] args = { reviewerGroupId };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_017, args);
		}
		logger.trace("Exiting getReviewersDiff.");
		return reviewerDiff;
	}

    public boolean isUnderReview(ResourceResolver resourceResolver, String assetPath)
            throws FormsNDocumentsException {

		if (resourceResolver != null) {
			try {

				Node asset = RnCUtil.getNode(assetPath + METADATA_PATH,
						resourceResolver);

				if (asset.hasProperty(RnCUtil.UNDER_REVIEW) &&
						asset.getProperty(RnCUtil.UNDER_REVIEW).getBoolean())
					return true;
			} catch (ValueFormatException e){
				logger.error("Illegal Review State.  " , e);
				Object[] args=null;
				throw new FormsNDocumentsException(
						FormsNDocumentsException.ERROR_AEM_FMG_700_008, args);
			} catch (RepositoryException e) {
				logger.error("Exception while retrieving bundle context " , e);
				Object[] args = { e.getMessage() };
				throw new FormsNDocumentsException(
						FormsNDocumentsException.ERROR_AEM_FMG_700_005, args);
			}
		}

        return false;
    }

	/**
	 * {@inheritDoc}
	 */
	public Map fetchReviewInfo(ResourceResolver resourceResolver, String assetPath)
			throws FormsNDocumentsException {
		logger.trace("Entering fetchReviewInfo.");
		RnCUtil.checkAssetPathArgument(assetPath);
		Map reviewInfo = new HashMap();

		try {
			if (resourceResolver != null) {

				// This check ensures, the person fetching the review information has
				// access to the asset.
				Node asset = RnCUtil.checkNodeExistance(assetPath + METADATA_PATH,
						resourceResolver);


				if (!isUnderReview(resourceResolver, assetPath)) {
					logger.error(" Asset " + assetPath
							+ " is currently not under review.");
					Object[] args = { assetPath };
					throw new FormsNDocumentsException(
							FormsNDocumentsException.ERROR_AEM_FMG_700_019, args);
				}

				String reviewId = "";
				if (asset.hasProperty(RnCUtil.REVIEW_ID)) {
					reviewId = asset.getProperty(RnCUtil.REVIEW_ID).getString();
					reviewInfo.put(RnCUtil.REVIEW_ID, reviewId);
				}

				Node review = RnCUtil.checkNodeExistance(assetPath
						+ REVIEW_CONTAINER_PATH + "/" + reviewId, resourceResolver);

				if (review.hasProperty(RnCUtil.REVIEW_PROJECT_NAME)) {
					reviewInfo.put(RnCUtil.REVIEW_PROJECT_NAME,
							review.getProperty(RnCUtil.REVIEW_PROJECT_NAME)
									.getString());
				}

				if (review.hasProperty(RnCUtil.REVIEW_NAME)) {
					reviewInfo.put(RnCUtil.REVIEW_NAME,
							review.getProperty(RnCUtil.REVIEW_NAME).getString());
				}

				if (review.hasProperty(RnCUtil.REVIEW_INITIATOR)) {
					reviewInfo.put(RnCUtil.REVIEW_INITIATOR,
							review.getProperty(RnCUtil.REVIEW_INITIATOR)
									.getString());
				}

				if (review.hasProperty(RnCUtil.REVIEW_DESCRIPTION)) {
					reviewInfo.put(RnCUtil.REVIEW_DESCRIPTION,
							review.getProperty(RnCUtil.REVIEW_DESCRIPTION)
									.getString());
				}

				if (review.hasProperty(RnCUtil.REVIEW_GROUP)) {
					reviewInfo.put(RnCUtil.REVIEW_GROUP,
							review.getProperty(RnCUtil.REVIEW_GROUP).getString());
				}

				if (review.hasProperty(RnCUtil.REVIEW_DEADLINE)) {
					reviewInfo
							.put(RnCUtil.REVIEW_DEADLINE,
									review.getProperty(RnCUtil.REVIEW_DEADLINE)
											.getString());
				}
			}
		} catch (FormsNDocumentsException e) {
			throw e;
		} catch (ValueFormatException e) {
			logger.error("Illegal Review State.  " , e);
			Object[] args=null;
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_008, args);
		} catch (RepositoryException e) {
			logger.error("Exception while retrieving bundle context " , e);
			Object[] args = { e.getMessage() };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_005, args);
		}
		logger.trace("Exiting fetchReviewInfo.");
		return reviewInfo;
	}

	/**
	 * {@inheritDoc}
	 */
	public void beginReview(String reviewName, String reviewDescription,
			String deadline, String[] reviewers, String assetPath)
			throws FormsNDocumentsException {
		logger.trace("Entering beginReview.");
		Session bundleSession = null;
		ResourceResolver bundleResourceResolver = null;
		try {
			// bundleSession is first used to check the validity of the
			// reviewers passed and then used for creating review (creates
			// review node, creates review project and review tasks, creates a
			// new review group and add reviewers to it, applies ACL to review
			// node, add review information).
			bundleSession = FMUtils.getFnDServiceUserSession(slingRepository);
			bundleResourceResolver = RnCUtil.getResourceResolver(bundleSession,
					resourceResolverFactory);
			RnCUtil.checkAssetPathArgument(assetPath);
			RnCUtil.checkCreateReviewArguments(reviewName, reviewers, deadline,
					bundleResourceResolver);

            ResourceResolver resourceResolver = resourceResolverHelper
					.getResourceResolver();
			String initiatorId = resourceResolverHelper.getResourceResolverAs(
					Session.class).getUserID();
			createReviewContainer(assetPath, initiatorId, bundleSession,
						bundleResourceResolver);
			String underReviewProp = METADATA_PATH.substring(1) + "/"
					+ RnCUtil.UNDER_REVIEW;
			Node asset = RnCUtil
					.checkNodeExistance(assetPath, resourceResolver);
			if (asset.hasProperty(underReviewProp)
					&& asset.getProperty(underReviewProp).getBoolean()) {
				logger.error(" Asset "
						+ assetPath
						+ " is already under review, can not start a new review.");
				Object[] args = { assetPath };
				throw new FormsNDocumentsException(
						FormsNDocumentsException.ERROR_AEM_FMG_700_003, args);
			}
			Task task = RnCUtil.createProject(reviewName, assetPath, deadline,
					initiatorId, bundleResourceResolver, resourceResolver);

            String reviewProjectID = task.getId();
            String reviewProjectName = task.getName();
			Group reviewGroup = RnCUtil.createGroup(reviewProjectName + "_" + System.currentTimeMillis(), REVIEW_GROUPS_PATH,
                        bundleResourceResolver);
			String reviewGroupId = reviewGroup.getID();
			RnCUtil.addUserToGroup(initiatorId, reviewGroupId,
					bundleResourceResolver);
			String reviewId = createReviewNode(assetPath, reviewProjectName,
					reviewGroupId, bundleSession, bundleResourceResolver);
			addAssetReviewInfo(assetPath, reviewName, reviewDescription,
                    reviewProjectID, deadline, reviewGroupId, reviewId,
					bundleResourceResolver);
			for (String reviewer : reviewers) {
				addReviewerTask(reviewProjectID, reviewName, deadline, reviewer,
                        assetPath, reviewGroupId, reviewDescription, bundleResourceResolver,
                        resourceResolver);
                RnCUtil.addUserToGroup(reviewer, reviewGroupId, bundleResourceResolver);
			}
			bundleSession.save();
		} catch (RepositoryException e) {
			logger.error("Exception while creation of review " , e);
			Object[] args=null;
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_004, args);
		} catch (LoginException e) {
			logger.error("Exception while retrieving bundle context " , e);
			Object[] args = { e.getMessage() };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_005, args);
		} catch (TaskManagerException e) {
			logger.error("Exception while creation of Task " , e);
			Object[] args=null;
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_006, args);
		} finally {
			if (bundleResourceResolver != null) {
				bundleResourceResolver.close();
			}
			if (bundleSession != null) {
				bundleSession.logout();
			}
		}
		logger.trace("Exiting beginReview.");
	}

	/**
	 * {@inheritDoc}
	 */
	public void endReview(String assetPath) throws FormsNDocumentsException {
		logger.trace("Entering endReview.");
		RnCUtil.checkAssetPathArgument(assetPath);
		String reviewProjectName;
		String reviewID;
		ResourceResolver currentResourceResolver = resourceResolverHelper.getResourceResolver();
		String currentUserID = currentResourceResolver.getUserID();

		RnCUtil.checkNodeExistance(assetPath, currentResourceResolver);

		Map reviewInfo = fetchReviewInfo(currentResourceResolver, assetPath);
		// check for initiator ensures that only the initiator is able to take further actions to end review.
		if (!currentUserID.equals(reviewInfo.get(RnCUtil.REVIEW_INITIATOR))) {
			logger.error(" Current User " + currentUserID + " is not the initiator of review for asset " + assetPath + " , and only initiator can end the review.");
			Object[] args = { currentUserID, assetPath };
			throw new FormsNDocumentsException(FormsNDocumentsException.ERROR_AEM_FMG_700_020, args);
		}
		reviewProjectName = reviewInfo.get(RnCUtil.REVIEW_PROJECT_NAME);
		reviewID = reviewInfo.get(RnCUtil.REVIEW_ID);

		ResourceResolver bundleResourceResolver = null;
		try {
			RnCUtil.terminateProjectActiveTasks(reviewProjectName, currentResourceResolver);
			removeAssetReviewInfo(assetPath, currentResourceResolver);
			currentResourceResolver.commit();

			// bundle session is used for ending review (terminates review
			// tasks, completes review project, removes review group ACL,
			// deletes review group, update review information)
			bundleResourceResolver = FMUtils.getFnDServiceUserResourceResolver(resourceResolverFactory);
			cleanUpPermissions(assetPath, reviewInfo.get(RnCUtil.REVIEW_GROUP), reviewID, bundleResourceResolver, currentResourceResolver);
			RnCUtil.removeGroup(reviewInfo.get(RnCUtil.REVIEW_GROUP), bundleResourceResolver);
			bundleResourceResolver.commit();

		} catch (RepositoryException e) {
			logger.error("Exception while ending review " , e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_012, args);
		} catch (LoginException e) {
			logger.error("Exception while retrieving bundle context " , e);
			Object[] args = { e.getMessage() };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_005, args);
		} catch (TaskManagerException e) {
			logger.error("Exception while terminating task " , e);
			Object[] args=null;
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_007, args);
		} catch (PersistenceException e) {
			logger.error("Exception while saving the updated review state " , e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_012, args);
		} finally {
			if (bundleResourceResolver != null) {
				bundleResourceResolver.close();
			}
		}

		logger.trace("Exiting endReview.");
	}

	/**
	 * {@inheritDoc}
	 */
	public void updateReview(String assetPath, String reviewDescription,
			String deadline, String[] reviewers)
			throws FormsNDocumentsException {
		logger.trace("Entering updateReview.");
		ResourceResolver bundleResourceResolver = null;
		try {
			// bundleSession is first used to check the validity of the reviewers passed and then used for updating review
			// (terminates/completes review tasks as per addition and removal of reviewers, updates review group, update review information).
			bundleResourceResolver = FMUtils.getFnDServiceUserResourceResolver(resourceResolverFactory);
			ResourceResolver currentResourceResolver = resourceResolverHelper.getResourceResolver();

			RnCUtil.checkUpdateReviewArguments(reviewers, deadline,	bundleResourceResolver);

			RnCUtil.checkNodeExistance(assetPath, currentResourceResolver);

			// check for initiator ensures that only the initiator is able to
			// take further actions to update the review.
			String currentUserID = currentResourceResolver.getUserID();
			Map reviewInfo = fetchReviewInfo(currentResourceResolver, assetPath);
			if (!currentUserID.equals(reviewInfo.get(RnCUtil.REVIEW_INITIATOR))) {
				logger.error(" Current User " + currentUserID + " is not the initiator of review for asset " + assetPath + " , and only initiator can end the review.");
				Object[] args = { currentUserID, assetPath };
				throw new FormsNDocumentsException(FormsNDocumentsException.ERROR_AEM_FMG_700_020, args);
			}

			Node reviewNode = RnCUtil.getNode(assetPath + REVIEW_CONTAINER_PATH + "/" + reviewInfo.get(RnCUtil.REVIEW_ID), currentResourceResolver);
			if (reviewNode == null) {
				Object[] args = { reviewInfo.get(RnCUtil.REVIEW_ID), assetPath };
				throw new FormsNDocumentsException(FormsNDocumentsException.ERROR_AEM_FMG_700_023, args);
			}

			if (reviewDescription != null && !reviewDescription.equals(reviewInfo.get(RnCUtil.REVIEW_DESCRIPTION))) {
				RnCUtil.updateProjectDescription(reviewInfo.get(RnCUtil.REVIEW_PROJECT_NAME), reviewDescription, currentResourceResolver);
				reviewNode.setProperty(RnCUtil.REVIEW_DESCRIPTION, reviewDescription);
			} else {
				reviewDescription = reviewInfo.get(RnCUtil.REVIEW_DESCRIPTION);
			}

			if (deadline != null && !deadline.equals(reviewInfo.get(RnCUtil.REVIEW_DEADLINE))) {
				RnCUtil.updateProjectDeadline(reviewInfo.get(RnCUtil.REVIEW_PROJECT_NAME), deadline, currentResourceResolver);
				reviewNode.setProperty(RnCUtil.REVIEW_DEADLINE, deadline);
			} else {
				deadline = reviewInfo.get(RnCUtil.REVIEW_DEADLINE);
			}

			Map> reviewersDiff = getReviewersDiff(reviewers, reviewInfo.get(RnCUtil.REVIEW_GROUP),	bundleResourceResolver);
			List removedReviewers = reviewersDiff.get(REMOVED_REVIEWERS);
			List addedReviewers = reviewersDiff.get(ADDED_REVIEWERS);

			for (String reviewer : removedReviewers) {
				removeReviewerTask(reviewInfo.get(RnCUtil.REVIEW_PROJECT_NAME),	reviewer, reviewInfo.get(RnCUtil.REVIEW_GROUP),	reviewInfo.get(RnCUtil.REVIEW_INITIATOR), currentResourceResolver);
				// Ignore removing of initiator from group.
				if (!reviewer.equals(reviewInfo.get(RnCUtil.REVIEW_INITIATOR))) {
					RnCUtil.removeUserFromGroup(reviewer, reviewInfo.get(RnCUtil.REVIEW_GROUP), bundleResourceResolver);
				}
			}

			for (String reviewer : addedReviewers) {
				addReviewerTask(reviewInfo.get(RnCUtil.REVIEW_PROJECT_NAME), reviewInfo.get(RnCUtil.REVIEW_NAME), deadline, reviewer, assetPath, reviewInfo.get(RnCUtil.REVIEW_GROUP), reviewDescription, bundleResourceResolver, currentResourceResolver);
				RnCUtil.addUserToGroup(reviewer, reviewInfo.get(RnCUtil.REVIEW_GROUP), bundleResourceResolver);
			}

			bundleResourceResolver.commit();
			currentResourceResolver.commit();
		} catch (RepositoryException e) {
			logger.error("Exception while updating review " , e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_013, args);
		} catch (LoginException e) {
			logger.error("Exception while retrieving bundle context " , e);
			Object[] args = { e.getMessage() };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_005, args);
		} catch (TaskManagerException e) {
			logger.error("Exception while updating review state " , e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_014, args);
		} catch (PersistenceException e) {
			logger.error("Exception while saving the updated review state ", e);
			Object[] args = { assetPath };
			throw new FormsNDocumentsException(
					FormsNDocumentsException.ERROR_AEM_FMG_700_014, args);
		} finally {
			if (bundleResourceResolver != null) {
				bundleResourceResolver.close();
			}
		}
		logger.trace("Exiting updateReview.");
	}

	@Override
	public void cleanReview(String assetPath, Session currentSession,
			boolean updateReviewProperties) throws FormsMgrException {
		logger.trace("Entering cleanReview.");
		RnCUtil.checkAssetPathArgument(assetPath);
		String reviewProjectName;
		String reviewID;
        ResourceResolver currentResourceResolver = FMUtils.getResourceResolver(resourceResolverFactory, currentSession);

		RnCUtil.checkNodeExistance(assetPath, currentResourceResolver);
		Map reviewInfo = fetchReviewInfo(currentResourceResolver, assetPath);
		reviewProjectName = reviewInfo.get(RnCUtil.REVIEW_PROJECT_NAME);
		reviewID = reviewInfo.get(RnCUtil.REVIEW_ID);

		ResourceResolver bundleResourceResolver = null;
		try {
            bundleResourceResolver = FMUtils.getFnDServiceUserResourceResolver(resourceResolverFactory);

            /* The following condition helps define what tasks need to be executed
               before an asset is being published and should not be executed before it is being deleted.*/
			if (updateReviewProperties) {
                try {
				    RnCUtil.terminateProjectActiveTasks(reviewProjectName,
                        bundleResourceResolver);
                } catch (Exception e) {
                    logger.error("Exception while terminating task " , e);
                }
                try {
					removeAssetReviewInfo(assetPath, bundleResourceResolver);
				} catch (Exception e) {
					logger.error("Exception while setting asset review state " , e);
				}
				try {
					cleanUpPermissions(assetPath,
							reviewInfo.get(RnCUtil.REVIEW_GROUP), reviewID,
                            bundleResourceResolver, currentResourceResolver);
				} catch (Exception e) {
					logger.error("Exception while removing review ACL " , e);
				}
			}

			try {
				RnCUtil.removeGroup(reviewInfo.get(RnCUtil.REVIEW_GROUP),
						bundleResourceResolver);
			} catch (Exception e) {
				logger.error("Exception while removing temporary review group " , e);
			}

            bundleResourceResolver.commit();

		} catch (Exception e) {
			logger.error("Exception while retrieving bundle context " , e);
		} finally {
			if (bundleResourceResolver !=null ){
				bundleResourceResolver.close();
			}
		}
		logger.trace("Exiting cleanReview.");
	}

    public ResourceResolver getFnDServiceUserResourceResolver() {
        ResourceResolver serviceResourceResolver = null;
        try {
            serviceResourceResolver = FMUtils.getFnDServiceUserResourceResolver(resourceResolverFactory);
        } catch (LoginException e) {
            logger.error("Error while retrieving service session for system user 'fd-service'", e);
        }

        return serviceResourceResolver;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy