<commit_before>/*
 * 
 */
package org.ihtsdo.otf.mapping.rest;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.log4j.Logger;
import org.ihtsdo.otf.mapping.helpers.FeedbackConversationList;
import org.ihtsdo.otf.mapping.helpers.FeedbackConversationListJpa;
import org.ihtsdo.otf.mapping.helpers.FeedbackEmailJpa;
import org.ihtsdo.otf.mapping.helpers.MapUserRole;
import org.ihtsdo.otf.mapping.helpers.PfsParameterJpa;
import org.ihtsdo.otf.mapping.helpers.SearchResult;
import org.ihtsdo.otf.mapping.helpers.SearchResultList;
import org.ihtsdo.otf.mapping.helpers.SearchResultListJpa;
import org.ihtsdo.otf.mapping.helpers.WorkflowAction;
import org.ihtsdo.otf.mapping.helpers.WorkflowStatus;
import org.ihtsdo.otf.mapping.jpa.FeedbackConversationJpa;
import org.ihtsdo.otf.mapping.jpa.MapRecordJpa;
import org.ihtsdo.otf.mapping.jpa.services.ContentServiceJpa;
import org.ihtsdo.otf.mapping.jpa.services.MappingServiceJpa;
import org.ihtsdo.otf.mapping.jpa.services.SecurityServiceJpa;
import org.ihtsdo.otf.mapping.jpa.services.WorkflowServiceJpa;
import org.ihtsdo.otf.mapping.model.FeedbackConversation;
import org.ihtsdo.otf.mapping.model.MapProject;
import org.ihtsdo.otf.mapping.model.MapRecord;
import org.ihtsdo.otf.mapping.model.MapUser;
import org.ihtsdo.otf.mapping.rf2.Concept;
import org.ihtsdo.otf.mapping.services.ContentService;
import org.ihtsdo.otf.mapping.services.MappingService;
import org.ihtsdo.otf.mapping.services.SecurityService;
import org.ihtsdo.otf.mapping.services.WorkflowService;
import org.ihtsdo.otf.mapping.workflow.TrackingRecord;
import org.ihtsdo.otf.mapping.workflow.WorkflowException;
import org.ihtsdo.otf.mapping.workflow.WorkflowExceptionJpa;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;

/**
 * The Workflow Services REST package.
 */
@Path("/workflow")
@Api(value = "/workflow", description = "Operations supporting workflow")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class WorkflowServiceRest extends RootServiceRest {

	/** The security service. */
	private SecurityService securityService;

	/**
	 * Instantiates an empty {@link WorkflowServiceRest}.
	 */
	public WorkflowServiceRest() throws Exception {
		securityService = new SecurityServiceJpa();
	}

	/**
	 * Compute workflow.
	 * 
	 * @param mapProjectId
	 *            the map project id
	 * @param authToken
	 */
	@POST
	@Path("/project/id/{id:[0-9][0-9]*}/compute")
	@ApiOperation(value = "Compute workflow for project", notes = "Destroys and recomputes the current workflow status from existing map records for a map project.  No mapping data is modified.")
	public void computeWorkflow(
			@ApiParam(value = "Map Project id", required = true) @PathParam("id") Long mapProjectId,
			@ApiParam(value = "Authorization token", required = true) @HeaderParam("Authorization") String authToken) {

		Logger.getLogger(WorkflowServiceRest.class).info(
				"RESTful call (Workflow): /project/id/"
						+ mapProjectId.toString() + "/compute");

		String userName = "";
		String project = "";

		try {
			// authorize call
			userName = securityService.getUsernameForToken(authToken);
			MapUserRole role = securityService.getMapProjectRoleForToken(
					authToken, mapProjectId);
			if (!role.hasPrivilegesOf(MapUserRole.ADMINISTRATOR))
				throw new WebApplicationException(
						Response.status(401)
								.entity("User does not have permissions to compute workflow.")
								.build());

			MappingService mappingService = new MappingServiceJpa();
			MapProject mapProject = mappingService.getMapProject(mapProjectId);
			project = mapProject.getName();
			mappingService.close();
			WorkflowService workflowService = new WorkflowServiceJpa();
			workflowService.computeWorkflow(mapProject);
			workflowService.close();
			return;
		} catch (Exception e) {
			handleException(e, "trying to compute workflow", userName, project,
					"");
		}
	}

	/**
	 * Finds available concepts for the specified map project and user.
	 * 
	 * @param mapProjectId
	 *            the map project id
	 * @param userName
	 *            the username
	 * @param query
	 * @param pfsParameter
	 *            the paging parameter
	 * @param authToken
	 * @return the search result list
	 */
	@POST
	@Path("/project/id/{id:[0-9][0-9]*}/user/id/{userName}/query/{query}/availableConcepts")
	@ApiOperation(value = "Find available concepts", notes = "Returns a paged list of work available to a specialist or lead for the specified map project.", response = SearchResultList.class)
	@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	public SearchResultList findAvailableConcepts(
			@ApiParam(value = "Id of map project", required = true) @PathParam("id") Long mapProjectId,
			@ApiParam(value = "Id of map user", required = true) @PathParam("userName") String userName,
			@ApiParam(value = "Lucene query string", required = true) @PathParam("query") String query,
			@ApiParam(value = "Paging/filtering/sorting parameter object", required = true) PfsParameterJpa pfsParameter,
			@ApiParam(value = "Authorization token", required = true) @HeaderParam("Authorization") String authToken) {

		Logger.getLogger(WorkflowServiceRest.class).info(
				"RESTful call (Workflow): /project/id/"
						+ mapProjectId.toString() + "/user/id/" + userName
						+ "/availableConcepts" + " with PfsParameter: " + "\n"
						+ "     Index/Results = "
						+ Integer.toString(pfsParameter.getStartIndex()) + "/"
						+ Integer.toString(pfsParameter.getMaxResults()) + "\n"
						+ "     Sort field    = " + pfsParameter.getSortField()
						+ "     Filter String = "
						+ pfsParameter.getQueryRestriction());

		String project = "";
		String user = "";

		try {
			System.out.println("Authorizing at: " + System.currentTimeMillis()
					/ 1000);

			// authorize call
			MapUserRole role = securityService.getMapProjectRoleForToken(
					authToken, mapProjectId);
			if (!role.hasPrivilegesOf(MapUserRole.SPECIALIST))
				throw new WebApplicationException(
						Response.status(401)
								.entity("User does not have permissions to find available work.")
								.build());

			System.out.println("Retrieving objects at "
					+ System.currentTimeMillis() / 1000);

			// retrieve the project and user
			MappingService mappingService = new MappingServiceJpa();
			MapProject mapProject = mappingService.getMapProject(mapProjectId);
			project = mapProject.getName();
			MapUser mapUser = mappingService.getMapUser(userName);
			user = mapUser.getUserName();
			mappingService.close();

			System.out.println("Getting available work at "
					+ System.currentTimeMillis() / 1000);

			// retrieve the workflow tracking records
			WorkflowService workflowService = new WorkflowServiceJpa();
			SearchResultList results = workflowService.findAvailableWork(
					mapProject, mapUser, query, pfsParameter);
			workflowService.close();

			// Check that all concepts referenced here are active (and thus have
			// a tree position)
			// This is a temporary fix, which will be removed once a more robust
			// solution to scope concepts is found
			// SEE MAP-862
			SearchResultList revisedResults = new SearchResultListJpa();
			ContentService contentService = new ContentServiceJpa();
			for (SearchResult result : results.getIterable()) {
				Concept c = contentService.getConcept(
						result.getTerminologyId(), result.getTerminology(),
						result.getTerminologyVersion());
				if (c.isActive() == true) {
					revisedResults.addSearchResult(result);
				} else {
					Logger.getLogger(WorkflowServiceJpa.class).warn(
							"Skipping inactive concept "
									+ result.getTerminologyId());
				}
			}

			results = revisedResults;

			System.out.println("Done at " + System.currentTimeMillis() / 1000);

			return results;
		} catch (Exception e) {
			handleException(e, "trying to find available work", user, project,
					"");
			return null;
		}
	}

	/**
	 * Finds assigned concepts for the specified map project and user.
	 * <commit_msg>minor bug fix in restful services<commit_after>/*
 * 
 */
package org.ihtsdo.otf.mapping.rest;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.log4j.Logger;
import org.ihtsdo.otf.mapping.helpers.FeedbackConversationList;
import org.ihtsdo.otf.mapping.helpers.FeedbackConversationListJpa;
import org.ihtsdo.otf.mapping.helpers.FeedbackEmailJpa;
import org.ihtsdo.otf.mapping.helpers.MapUserRole;
import org.ihtsdo.otf.mapping.helpers.PfsParameterJpa;
import org.ihtsdo.otf.mapping.helpers.SearchResult;
import org.ihtsdo.otf.mapping.helpers.SearchResultList;
import org.ihtsdo.otf.mapping.helpers.SearchResultListJpa;
import org.ihtsdo.otf.mapping.helpers.WorkflowAction;
import org.ihtsdo.otf.mapping.helpers.WorkflowStatus;
import org.ihtsdo.otf.mapping.jpa.FeedbackConversationJpa;
import org.ihtsdo.otf.mapping.jpa.MapRecordJpa;
import org.ihtsdo.otf.mapping.jpa.services.ContentServiceJpa;
import org.ihtsdo.otf.mapping.jpa.services.MappingServiceJpa;
import org.ihtsdo.otf.mapping.jpa.services.SecurityServiceJpa;
import org.ihtsdo.otf.mapping.jpa.services.WorkflowServiceJpa;
import org.ihtsdo.otf.mapping.model.FeedbackConversation;
import org.ihtsdo.otf.mapping.model.MapProject;
import org.ihtsdo.otf.mapping.model.MapRecord;
import org.ihtsdo.otf.mapping.model.MapUser;
import org.ihtsdo.otf.mapping.rf2.Concept;
import org.ihtsdo.otf.mapping.services.ContentService;
import org.ihtsdo.otf.mapping.services.MappingService;
import org.ihtsdo.otf.mapping.services.SecurityService;
import org.ihtsdo.otf.mapping.services.WorkflowService;
import org.ihtsdo.otf.mapping.workflow.TrackingRecord;
import org.ihtsdo.otf.mapping.workflow.WorkflowException;
import org.ihtsdo.otf.mapping.workflow.WorkflowExceptionJpa;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;

/**
 * The Workflow Services REST package.
 */
@Path("/workflow")
@Api(value = "/workflow", description = "Operations supporting workflow")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class WorkflowServiceRest extends RootServiceRest {

	/** The security service. */
	private SecurityService securityService;

	/**
	 * Instantiates an empty {@link WorkflowServiceRest}.
	 */
	public WorkflowServiceRest() throws Exception {
		securityService = new SecurityServiceJpa();
	}

	/**
	 * Compute workflow.
	 * 
	 * @param mapProjectId
	 *            the map project id
	 * @param authToken
	 */
	@POST
	@Path("/project/id/{id:[0-9][0-9]*}/compute")
	@ApiOperation(value = "Compute workflow for project", notes = "Destroys and recomputes the current workflow status from existing map records for a map project.  No mapping data is modified.")
	public void computeWorkflow(
			@ApiParam(value = "Map Project id", required = true) @PathParam("id") Long mapProjectId,
			@ApiParam(value = "Authorization token", required = true) @HeaderParam("Authorization") String authToken) {

		Logger.getLogger(WorkflowServiceRest.class).info(
				"RESTful call (Workflow): /project/id/"
						+ mapProjectId.toString() + "/compute");

		String userName = "";
		String project = "";

		try {
			// authorize call
			userName = securityService.getUsernameForToken(authToken);
			MapUserRole role = securityService.getMapProjectRoleForToken(
					authToken, mapProjectId);
			if (!role.hasPrivilegesOf(MapUserRole.ADMINISTRATOR))
				throw new WebApplicationException(
						Response.status(401)
								.entity("User does not have permissions to compute workflow.")
								.build());

			MappingService mappingService = new MappingServiceJpa();
			MapProject mapProject = mappingService.getMapProject(mapProjectId);
			project = mapProject.getName();
			mappingService.close();
			WorkflowService workflowService = new WorkflowServiceJpa();
			workflowService.computeWorkflow(mapProject);
			workflowService.close();
			return;
		} catch (Exception e) {
			handleException(e, "trying to compute workflow", userName, project,
					"");
		}
	}

	/**
	 * Finds available concepts for the specified map project and user.
	 * 
	 * @param mapProjectId
	 *            the map project id
	 * @param userName
	 *            the username
	 * @param query
	 * @param pfsParameter
	 *            the paging parameter
	 * @param authToken
	 * @return the search result list
	 */
	@POST
	@Path("/project/id/{id:[0-9][0-9]*}/user/id/{userName}/query/{query}/availableConcepts")
	@ApiOperation(value = "Find available concepts", notes = "Returns a paged list of work available to a specialist or lead for the specified map project.", response = SearchResultList.class)
	@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	public SearchResultList findAvailableConcepts(
			@ApiParam(value = "Id of map project", required = true) @PathParam("id") Long mapProjectId,
			@ApiParam(value = "Id of map user", required = true) @PathParam("userName") String userName,
			@ApiParam(value = "Lucene query string", required = true) @PathParam("query") String query,
			@ApiParam(value = "Paging/filtering/sorting parameter object", required = true) PfsParameterJpa pfsParameter,
			@ApiParam(value = "Authorization token", required = true) @HeaderParam("Authorization") String authToken) {

		Logger.getLogger(WorkflowServiceRest.class).info(
				"RESTful call (Workflow): /project/id/"
						+ mapProjectId.toString() + "/user/id/" + userName
						+ "/availableConcepts" + " with PfsParameter: " + "\n"
						+ "     Index/Results = "
						+ Integer.toString(pfsParameter.getStartIndex()) + "/"
						+ Integer.toString(pfsParameter.getMaxResults()) + "\n"
						+ "     Sort field    = " + pfsParameter.getSortField()
						+ "     Filter String = "
						+ pfsParameter.getQueryRestriction());

		String project = "";
		String user = "";

		try {
			System.out.println("Authorizing at: " + System.currentTimeMillis()
					/ 1000);

			// authorize call
			MapUserRole role = securityService.getMapProjectRoleForToken(
					authToken, mapProjectId);
			if (!role.hasPrivilegesOf(MapUserRole.SPECIALIST))
				throw new WebApplicationException(
						Response.status(401)
								.entity("User does not have permissions to find available work.")
								.build());

			System.out.println("Retrieving objects at "
					+ System.currentTimeMillis() / 1000);

			// retrieve the project and user
			MappingService mappingService = new MappingServiceJpa();
			MapProject mapProject = mappingService.getMapProject(mapProjectId);
			project = mapProject.getName();
			MapUser mapUser = mappingService.getMapUser(userName);
			user = mapUser.getUserName();
			mappingService.close();

			System.out.println("Getting available work at "
					+ System.currentTimeMillis() / 1000);

			// retrieve the workflow tracking records
			WorkflowService workflowService = new WorkflowServiceJpa();
			SearchResultList results = workflowService.findAvailableWork(
					mapProject, mapUser, query, pfsParameter);
			workflowService.close();

			// Check that all concepts referenced here are active (and thus have
			// a tree position)
			// This is a temporary fix, which will be removed once a more robust
			// solution to scope concepts is found
			// SEE MAP-862
			SearchResultList revisedResults = new SearchResultListJpa();
			ContentService contentService = new ContentServiceJpa();
			for (SearchResult result : results.getIterable()) {
				
				
				Concept c = contentService.getConcept(
						result.getTerminologyId(), mapProject.getSourceTerminology(),
						mapProject.getSourceTerminologyVersion());
				if (c.isActive() == true) {
					revisedResults.addSearchResult(result);
				} else {
					Logger.getLogger(WorkflowServiceJpa.class).warn(
							"Skipping inactive concept "
									+ result.getTerminologyId());
				}
			}

			results = revisedResults;

			System.out.println("Done at " + System.currentTimeMillis() / 1000);

			return results;
		} catch (Exception e) {
			handleException(e, "trying to find available work", user, project,
					"");
			return null;
		}
	}

	/**
	 * Finds assigned concepts for the specified map project and user.
	 * 
{'fraction_non_alphanumeric': 0.11455541312201376, 'fraction_numerical': 0.004078778697121548, 'mean_word_length': 4.239010989010989, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2894182', 'n_tokens_mistral': 5947, 'n_tokens_neox': 5207, 'n_words': 1137}