/** * */ package com.github.podd.resources; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.openrdf.OpenRDFException; import org.openrdf.model.Model; import org.openrdf.model.impl.LinkedHashModel; import org.openrdf.rio.RDFFormat; import org.openrdf.rio.Rio; import org.openrdf.rio.UnsupportedRDFormatException; import org.restlet.data.MediaType; import org.restlet.data.Status; import org.restlet.representation.ByteArrayRepresentation; import org.restlet.representation.Representation; import org.restlet.representation.Variant; import org.restlet.resource.Get; import org.restlet.resource.ResourceException; import org.restlet.security.User; import org.semanticweb.owlapi.model.IRI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.ansell.restletutils.RestletUtilRole; import com.github.podd.exception.RepositoryNotFoundException; import com.github.podd.exception.SchemaManifestException; import com.github.podd.exception.UnmanagedArtifactIRIException; import com.github.podd.exception.UnmanagedArtifactVersionException; import com.github.podd.exception.UnmanagedSchemaIRIException; import com.github.podd.restlet.PoddAction; import com.github.podd.restlet.PoddWebServiceApplication; import com.github.podd.restlet.RestletUtils; import com.github.podd.utils.InferredOWLOntologyID; import com.github.podd.utils.PODD; import com.github.podd.utils.PoddObjectLabel; import com.github.podd.utils.PoddRoles; import com.github.podd.utils.PoddUser; import com.github.podd.utils.PoddWebConstants; /** * * @author kutila */ public class ArtifactRolesResourceImpl extends AbstractPoddResourceImpl { private final Logger log = LoggerFactory.getLogger(this.getClass()); /** * View the Edit Project Participants page in HTML */ @Get("html") public Representation getEditArtifactParticipantsHtml(final Representation entity) throws ResourceException { this.log.info("getArtifactRolesHtml"); // the artifact in which editing is requested final String artifactUri = this.getQuery().getFirstValue(PoddWebConstants.KEY_ARTIFACT_IDENTIFIER, true); if(artifactUri == null) { throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Artifact ID not submitted"); } this.log.info("requesting to edit Artifact Participants (HTML): {}", artifactUri); this.checkAuthentication(PoddAction.PROJECT_ROLE_EDIT, PODD.VF.createURI(artifactUri)); final User user = this.getRequest().getClientInfo().getUser(); this.log.info("authenticated user: {}", user); // validate artifact exists InferredOWLOntologyID ontologyID; try { ontologyID = this.getPoddArtifactManager().getArtifact(IRI.create(artifactUri)); } catch(final UnmanagedArtifactIRIException | UnmanagedSchemaIRIException e) { throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND, "Could not find the given artifact", e); } final Map<String, Object> dataModel = RestletUtils.getBaseDataModel(this.getRequest()); dataModel.put("contentTemplate", "projectParticipants.html.ftl"); dataModel.put("pageTitle", "Edit Project Participants"); try { dataModel.put("projectObject", this.getProjectDetails(ontologyID)); dataModel.put("piUri", PoddRoles.PROJECT_PRINCIPAL_INVESTIGATOR.getURI()); dataModel.put("adminUri", PoddRoles.PROJECT_ADMIN.getURI()); dataModel.put("memberUri", PoddRoles.PROJECT_MEMBER.getURI()); dataModel.put("observerUri", PoddRoles.PROJECT_OBSERVER.getURI()); final Collection<RestletUtilRole> nextRoles = new LinkedHashSet<>(); nextRoles.addAll(Arrays.asList(PoddRoles.PROJECT_PRINCIPAL_INVESTIGATOR, PoddRoles.PROJECT_ADMIN, PoddRoles.PROJECT_MEMBER, PoddRoles.PROJECT_OBSERVER)); final Map<RestletUtilRole, Collection<PoddUser>> roleUserMap = ((PoddWebServiceApplication)this.getApplication()).getRealm().getUsersForRole(nextRoles, ontologyID.getOntologyIRI().toOpenRDFURI()); // - add PI user label and identifier final Collection<PoddUser> piList = roleUserMap.get(PoddRoles.PROJECT_PRINCIPAL_INVESTIGATOR); if(piList != null && piList.size() == 1) { final PoddUser nextUser = piList.iterator().next(); dataModel.put("piLabel", nextUser.getUserLabel()); dataModel.put("piIdentifier", nextUser.getIdentifier()); } else { this.log.warn("Did not find Principal Investigator for artifact: {}", artifactUri); } // - add other Project Role participants dataModel.put("admins", roleUserMap.get(PoddRoles.PROJECT_ADMIN)); dataModel.put("members", roleUserMap.get(PoddRoles.PROJECT_MEMBER)); dataModel.put("observers", roleUserMap.get(PoddRoles.PROJECT_OBSERVER)); } catch(final UnmanagedSchemaIRIException | OpenRDFException | SchemaManifestException | UnsupportedRDFormatException | IOException | UnmanagedArtifactIRIException | UnmanagedArtifactVersionException | RepositoryNotFoundException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "Failed to populate data model", e); } dataModel.put("artifactUri", ontologyID.getOntologyIRI().toString()); return RestletUtils.getHtmlRepresentation( this.getPoddApplication().getPropertyUtil() .get(PoddWebConstants.PROPERTY_TEMPLATE_BASE, PoddWebConstants.DEFAULT_TEMPLATE_BASE), dataModel, MediaType.TEXT_HTML, this.getPoddApplication().getTemplateConfiguration()); } /** * View the Edit Project Participants data in RDF. */ @Get("rdf|rj|json|ttl") public Representation getEditArtifactParticipantsRdf(final Variant variant) throws ResourceException { this.log.info("getArtifactRolesHtml"); // the artifact in which editing is requested final String artifactUri = this.getQuery().getFirstValue(PoddWebConstants.KEY_ARTIFACT_IDENTIFIER, true); if(artifactUri == null) { throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Artifact ID not submitted"); } this.log.info("requesting to edit Artifact Participants (HTML): {}", artifactUri); this.checkAuthentication(PoddAction.PROJECT_ROLE_EDIT, PODD.VF.createURI(artifactUri)); final User user = this.getRequest().getClientInfo().getUser(); this.log.info("authenticated user: {}", user); // validate artifact exists InferredOWLOntologyID ontologyID; try { ontologyID = this.getPoddArtifactManager().getArtifact(IRI.create(artifactUri)); } catch(final UnmanagedArtifactIRIException | UnmanagedSchemaIRIException e) { throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND, "Could not find the given artifact", e); } final Collection<RestletUtilRole> nextRoles = new LinkedHashSet<>(); nextRoles.addAll(Arrays.asList(PoddRoles.PROJECT_PRINCIPAL_INVESTIGATOR, PoddRoles.PROJECT_ADMIN, PoddRoles.PROJECT_MEMBER, PoddRoles.PROJECT_OBSERVER)); final Map<RestletUtilRole, Collection<PoddUser>> roleUserMap = ((PoddWebServiceApplication)this.getApplication()).getRealm().getUsersForRole(nextRoles, ontologyID.getOntologyIRI().toOpenRDFURI()); final Map<RestletUtilRole, Collection<String>> mappings = this.translateMap(roleUserMap); final Model model = new LinkedHashModel(); PoddRoles.dumpRoleMappingsArtifact(mappings, model); // - prepare response final ByteArrayOutputStream output = new ByteArrayOutputStream(8096); final RDFFormat outputFormat = Rio.getWriterFormatForMIMEType(variant.getMediaType().getName(), RDFFormat.RDFXML); try { Rio.write(model, output, outputFormat); } catch(final OpenRDFException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "Could not create response"); } return new ByteArrayRepresentation(output.toByteArray(), MediaType.valueOf(outputFormat.getDefaultMIMEType())); } /** * Helper method to retrieve display details for Project Top Object. * * @param ontologyID * @return * @throws OpenRDFException * @throws UnmanagedSchemaIRIException * @throws IOException * @throws UnsupportedRDFormatException * @throws SchemaManifestException * @throws UnmanagedArtifactVersionException * @throws UnmanagedArtifactIRIException * @throws RepositoryNotFoundException */ private PoddObjectLabel getProjectDetails(final InferredOWLOntologyID ontologyID) throws OpenRDFException, UnmanagedSchemaIRIException, SchemaManifestException, UnsupportedRDFormatException, IOException, UnmanagedArtifactIRIException, UnmanagedArtifactVersionException, RepositoryNotFoundException { // find and set top-object of this artifact as the object to display final List<PoddObjectLabel> topObjectLabels = this.getPoddArtifactManager().getTopObjectLabels(Arrays.asList(ontologyID)); if(topObjectLabels == null || topObjectLabels.size() != 1) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "There should be only 1 top object"); } return topObjectLabels.get(0); } private Map<RestletUtilRole, Collection<String>> translateMap(final Map<RestletUtilRole, Collection<PoddUser>> input) { final ConcurrentMap<RestletUtilRole, Collection<String>> userList = new ConcurrentHashMap<>(); for(final Entry<RestletUtilRole, Collection<PoddUser>> nextEntry : input.entrySet()) { final RestletUtilRole nextRole = nextEntry.getKey(); Collection<String> nextRoles = new LinkedHashSet<String>(); final Collection<String> putIfAbsent = userList.putIfAbsent(nextRole, nextRoles); if(putIfAbsent != null) { nextRoles = putIfAbsent; } for(final PoddUser nextUser : nextEntry.getValue()) { nextRoles.add(nextUser.getIdentifier()); } } return userList; } }