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

org.molgenis.omx.protocolviewer.ProtocolViewerServiceImpl Maven / Gradle / Ivy

The newest version!
package org.molgenis.omx.protocolviewer;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.Part;

import org.apache.log4j.Logger;
import org.molgenis.catalog.Catalog;
import org.molgenis.catalog.CatalogItem;
import org.molgenis.catalog.CatalogMeta;
import org.molgenis.catalog.CatalogService;
import org.molgenis.catalog.UnknownCatalogException;
import org.molgenis.data.DataService;
import org.molgenis.data.Entity;
import org.molgenis.data.MolgenisDataAccessException;
import org.molgenis.data.Writable;
import org.molgenis.data.excel.ExcelWriter;
import org.molgenis.data.support.MapEntity;
import org.molgenis.framework.server.MolgenisSettings;
import org.molgenis.omx.auth.MolgenisUser;
import org.molgenis.omx.observ.ObservableFeature;
import org.molgenis.omx.observ.Protocol;
import org.molgenis.omx.utils.ProtocolUtils;
import org.molgenis.security.core.utils.SecurityUtils;
import org.molgenis.security.user.MolgenisUserService;
import org.molgenis.study.StudyDefinition;
import org.molgenis.study.UnknownStudyDefinitionException;
import org.molgenis.studymanager.StudyManagerService;
import org.molgenis.util.FileStore;
import org.molgenis.util.FileUploadUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

@Service
public class ProtocolViewerServiceImpl implements ProtocolViewerService
{
	private static final Logger logger = Logger.getLogger(ProtocolViewerServiceImpl.class);
	@Autowired
	@Qualifier("catalogService")
	private CatalogService catalogService;
	@Autowired
	private JavaMailSender mailSender;
	@Autowired
	private MolgenisSettings molgenisSettings;
	@Autowired
	private FileStore fileStore;
	@Autowired
	private StudyManagerService studyManagerService;
	@Autowired
	private MolgenisUserService molgenisUserService;
	@Autowired
	private DataService dataService;

	@Override
	@PreAuthorize("hasAnyRole('ROLE_SU', 'ROLE_PLUGIN_READ_PROTOCOLVIEWER')")
	@Transactional(readOnly = true)
	public Iterable getCatalogs()
	{
		return Iterables.filter(catalogService.getCatalogs(), new Predicate()
		{
			@Override
			public boolean apply(CatalogMeta catalogMeta)
			{
				try
				{
					return catalogService.isCatalogLoaded(catalogMeta.getId());
				}
				catch (UnknownCatalogException e)
				{
					logger.error(e);
					throw new RuntimeException(e);
				}
			}
		});
	}

	@Override
	@PreAuthorize("isAuthenticated() and hasAnyRole('ROLE_SU', 'ROLE_PLUGIN_READ_PROTOCOLVIEWER')")
	@Transactional(readOnly = true)
	public StudyDefinition getStudyDefinitionDraftForCurrentUser(String catalogId) throws UnknownCatalogException
	{
		List studyDefinitions = studyManagerService.getStudyDefinitions(SecurityUtils
				.getCurrentUsername());

		for (StudyDefinition studyDefinition : studyDefinitions)
		{
			if (studyDefinition.getStatus() == StudyDefinition.Status.DRAFT)
			{
				Catalog catalogOfStudyDefinition;
				try
				{
					catalogOfStudyDefinition = catalogService.getCatalogOfStudyDefinition(studyDefinition.getId());
				}
				catch (UnknownCatalogException e)
				{
					logger.error("", e);
					throw new RuntimeException(e);
				}
				catch (UnknownStudyDefinitionException e)
				{
					logger.error("", e);
					throw new RuntimeException(e);
				}

				if (catalogOfStudyDefinition.getId().equals(catalogId))
				{
					return studyDefinition;
				}
			}
		}

		return null;
	}

	@Override
	@PreAuthorize("isAuthenticated() and hasAnyRole('ROLE_SU', 'ROLE_PLUGIN_WRITE_PROTOCOLVIEWER')")
	@Transactional
	public StudyDefinition createStudyDefinitionDraftForCurrentUser(String catalogId) throws UnknownCatalogException
	{
		return studyManagerService.createStudyDefinition(SecurityUtils.getCurrentUsername(), catalogId);
	}

	@Override
	@PreAuthorize("isAuthenticated() and hasAnyRole('ROLE_SU', 'ROLE_PLUGIN_READ_PROTOCOLVIEWER')")
	@Transactional(readOnly = true)
	public List getStudyDefinitionsForCurrentUser()
	{
		String username = SecurityUtils.getCurrentUsername();
		return studyManagerService.getStudyDefinitions(username);
	}

	@Override
	@PreAuthorize("isAuthenticated() and hasAnyRole('ROLE_SU', 'ROLE_PLUGIN_READ_PROTOCOLVIEWER')")
	@Transactional(readOnly = true)
	public StudyDefinition getStudyDefinitionForCurrentUser(Integer id) throws UnknownStudyDefinitionException
	{
		MolgenisUser user = molgenisUserService.getUser(SecurityUtils.getCurrentUsername());
		StudyDefinition studyDefinition = studyManagerService.getStudyDefinition(id.toString());

		if (!studyDefinition.getAuthorEmail().endsWith(user.getEmail()))
		{
			throw new MolgenisDataAccessException("Access denied to study definition [" + id + "]");
		}
		return studyDefinition;
	}

	@Override
	@PreAuthorize("isAuthenticated() and hasAnyRole('ROLE_SU', 'ROLE_PLUGIN_WRITE_PROTOCOLVIEWER')")
	@Transactional(rollbackFor =
	{ MessagingException.class, IOException.class, UnknownCatalogException.class, UnknownStudyDefinitionException.class })
	public void submitStudyDefinitionDraftForCurrentUser(String studyName, Part requestForm, String catalogId)
			throws MessagingException, IOException, UnknownCatalogException, UnknownStudyDefinitionException
	{
		if (studyName == null) throw new IllegalArgumentException("study name is null");
		if (requestForm == null) throw new IllegalArgumentException("request form is null");

		StudyDefinition studyDefinition = getStudyDefinitionDraftForCurrentUser(catalogId);
		if (studyDefinition == null) throw new UnknownStudyDefinitionException("no study definition draft for user");

		Iterable catalogItems = studyDefinition.getItems();
		if (catalogItems == null || !catalogItems.iterator().hasNext())
		{
			throw new IllegalArgumentException("feature list is null or empty");
		}

		String appName = molgenisSettings.getProperty("app.name", "MOLGENIS");
		long timestamp = System.currentTimeMillis();

		String originalFileName = FileUploadUtils.getOriginalFileName(requestForm);
		String extension = StringUtils.getFilenameExtension(originalFileName);
		String fileName = appName + "-request_" + timestamp + "." + extension;
		File orderFile = fileStore.store(requestForm.getInputStream(), fileName);

		// update study definition
		studyDefinition.setName(studyName);
		studyDefinition.setRequestProposalForm(fileName);
		studyManagerService.updateStudyDefinition(studyDefinition);

		// submit study definition
		studyManagerService.submitStudyDefinition(studyDefinition.getId(), catalogId);

		// create excel attachment for study data request
		String variablesFileName = appName + "-request_" + timestamp + "-variables.xls";
		InputStream variablesIs = createStudyDefinitionXlsStream(studyDefinition);
		File variablesFile = fileStore.store(variablesIs, variablesFileName);

		// send order confirmation to user and admin
		MolgenisUser molgenisUser = molgenisUserService.getUser(SecurityUtils.getCurrentUsername());
		MimeMessage message = mailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);
		helper.setTo(molgenisUser.getEmail());
		helper.setBcc(molgenisUserService.getSuEmailAddresses().toArray(new String[]
		{}));
		helper.setSubject("Submission confirmation from " + appName);
		helper.setText(createOrderConfirmationEmailText(appName));
		helper.addAttachment(fileName, new FileSystemResource(orderFile));
		helper.addAttachment(variablesFileName, new FileSystemResource(variablesFile));
		mailSender.send(message);
	}

	@Override
	@PreAuthorize("isAuthenticated() and hasAnyRole('ROLE_SU', 'ROLE_PLUGIN_WRITE_PROTOCOLVIEWER')")
	@Transactional(rollbackFor = UnknownCatalogException.class)
	public void addToStudyDefinitionDraftForCurrentUser(String resourceUri, String catalogId)
			throws UnknownCatalogException
	{
		final Catalog catalog = catalogService.getCatalog(catalogId);

		List catalogItemIds = getCatalogItemIds(resourceUri);

		StudyDefinition studyDefinition = getStudyDefinitionDraftForCurrentUser(catalogId);
		if (studyDefinition == null)
		{
			studyDefinition = createStudyDefinitionDraftForCurrentUser(catalogId);
		}

		Iterable catalogItems = Iterables.transform(catalogItemIds, new Function()
		{
			@Override
			public CatalogItem apply(String catalogItemId)
			{
				return catalog.findItem(catalogItemId);
			}
		});
		studyDefinition.setItems(Iterables.concat(studyDefinition.getItems(), catalogItems));

		try
		{
			studyManagerService.updateStudyDefinition(studyDefinition);
		}
		catch (UnknownStudyDefinitionException e)
		{
			logger.error("", e);
			throw new RuntimeException(e);
		}
	}

	@Override
	@PreAuthorize("isAuthenticated() and hasAnyRole('ROLE_SU', 'ROLE_PLUGIN_WRITE_PROTOCOLVIEWER')")
	@Transactional(rollbackFor = UnknownCatalogException.class)
	public void removeFromStudyDefinitionDraftForCurrentUser(String resourceUri, String catalogId)
			throws UnknownCatalogException
	{
		final Catalog catalog = catalogService.getCatalog(catalogId);

		final Set catalogItemIds = new HashSet(getCatalogItemIds(resourceUri));

		StudyDefinition studyDefinition = getStudyDefinitionDraftForCurrentUser(catalogId);
		if (studyDefinition == null)
		{
			studyDefinition = createStudyDefinitionDraftForCurrentUser(catalogId);
		}

		// verify that items to remove are part of this catalog
		for (String catalogItemId : catalogItemIds)
			catalog.findItem(catalogItemId);

		Iterable newCatalogItems = Iterables.filter(studyDefinition.getItems(),
				new Predicate()
				{
					@Override
					public boolean apply(CatalogItem catalogItem)
					{
						return !catalogItemIds.contains(catalogItem.getId());
					}
				});
		studyDefinition.setItems(newCatalogItems);

		try
		{
			if (Iterables.isEmpty(newCatalogItems))
			{
				// TOD remove StudyDefinition, empty item list is invalid according to the xsd
			}
			else
			{
				studyManagerService.updateStudyDefinition(studyDefinition);
			}
		}
		catch (UnknownStudyDefinitionException e)
		{
			logger.error("", e);
			throw new RuntimeException(e);
		}
	}

	@Override
	@PreAuthorize("isAuthenticated() and hasAnyRole('ROLE_SU', 'ROLE_PLUGIN_READ_PROTOCOLVIEWER')")
	@Transactional(rollbackFor =
	{ IOException.class, UnknownCatalogException.class })
	public void createStudyDefinitionDraftXlsForCurrentUser(OutputStream outputStream, String catalogId)
			throws IOException, UnknownCatalogException
	{
		StudyDefinition studyDefinition = getStudyDefinitionDraftForCurrentUser(catalogId);
		if (studyDefinition == null) return;
		writeStudyDefinitionXls(studyDefinition, outputStream);
	}

	private String createOrderConfirmationEmailText(String appName)
	{
		StringBuilder strBuilder = new StringBuilder();
		strBuilder.append("Dear Researcher,\n\n");
		strBuilder.append("Thank you for submitting to ").append(appName)
				.append(", attached are the details of your submission.\n");
		strBuilder.append("The ").append(appName)
				.append(" Research Office will contact you upon receiving your application.\n\n");
		strBuilder.append("Sincerely,\n");
		strBuilder.append(appName);
		return strBuilder.toString();
	}

	private InputStream createStudyDefinitionXlsStream(StudyDefinition studyDefinition) throws IOException
	{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try
		{
			writeStudyDefinitionXls(studyDefinition, bos);
			return new ByteArrayInputStream(bos.toByteArray());
		}
		finally
		{
			bos.close();
		}
	}

	private void writeStudyDefinitionXls(StudyDefinition studyDefinition, OutputStream outputStream) throws IOException
	{
		if (studyDefinition == null) return;

		// write excel file
		List header = Arrays.asList("Id", "Variable", "Description");

		List catalogItems = Lists.newArrayList(studyDefinition.getItems());
		if (catalogItems != null)
		{
			Collections.sort(catalogItems, new Comparator()
			{
				@Override
				public int compare(CatalogItem feature1, CatalogItem feature2)
				{
					return feature1.getId().compareTo(feature2.getId());
				}
			});
		}

		ExcelWriter excelWriter = new ExcelWriter(outputStream);
		try
		{
			Writable writable = excelWriter.createWritable("Variables", header);
			try
			{
				if (catalogItems != null)
				{
					for (CatalogItem catalogItem : catalogItems)
					{
						Entity entity = new MapEntity();
						entity.set(header.get(0), catalogItem.getId());
						entity.set(header.get(1), catalogItem.getName());
						entity.set(header.get(2), catalogItem.getDescription());
						writable.add(entity);
					}
				}
			}
			finally
			{
				writable.close();
			}
		}
		finally
		{
			excelWriter.close();
		}
	}

	/**
	 * 
	 * @param resourceUri
	 *            e.g. /api/v1/protocol/123
	 * @return
	 */
	private List getCatalogItemIds(String resourceUri)
	{
		String[] tokens = resourceUri.split("/");
		String entityName = tokens[tokens.length - 2];
		String entityId = tokens[tokens.length - 1];
		if (ObservableFeature.ENTITY_NAME.equalsIgnoreCase(entityName))
		{
			return Arrays. asList(entityId);
		}
		else if (Protocol.ENTITY_NAME.equalsIgnoreCase(entityName))
		{
			Protocol rootProtocol = dataService
					.findOne(Protocol.ENTITY_NAME, Integer.valueOf(entityId), Protocol.class);
			List featureIds = new ArrayList();
			for (Protocol protocol : ProtocolUtils.getProtocolDescendants(rootProtocol))
			{
				for (ObservableFeature feature : protocol.getFeatures())
					featureIds.add(feature.getId().toString());
			}
			return featureIds;
		}
		else
		{
			throw new IllegalArgumentException("invalid entity name [" + entityName + "]");
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy