package org.molgenis.data.mapper.controller; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import org.apache.commons.lang3.StringUtils; import org.molgenis.data.DataService; import org.molgenis.data.Entity; import org.molgenis.data.UnknownEntityException; import org.molgenis.data.mapper.data.request.AddTagRequest; import org.molgenis.data.mapper.data.request.AutoTagRequest; import org.molgenis.data.mapper.data.request.GetOntologyTermRequest; import org.molgenis.data.mapper.data.request.RemoveTagRequest; import org.molgenis.data.meta.model.Attribute; import org.molgenis.data.meta.model.EntityType; import org.molgenis.data.meta.model.EntityTypeMetadata; import org.molgenis.data.semantic.Relation; import org.molgenis.data.semanticsearch.semantic.Hit; import org.molgenis.data.semanticsearch.semantic.OntologyTag; import org.molgenis.data.semanticsearch.service.OntologyTagService; import org.molgenis.data.semanticsearch.service.SemanticSearchService; import org.molgenis.ontology.core.model.Ontology; import org.molgenis.ontology.core.model.OntologyTerm; import org.molgenis.ontology.core.service.OntologyService; import org.molgenis.ui.MolgenisPluginController; import org.molgenis.util.ErrorMessageResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.List; import java.util.Map; import java.util.Optional; import static com.google.common.collect.Lists.newArrayList; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.elasticsearch.common.collect.ImmutableSet.of; import static org.molgenis.data.mapper.controller.TagWizardController.URI; import static org.molgenis.data.meta.model.EntityTypeMetadata.ENTITY_TYPE_META_DATA; @Controller @RequestMapping(URI) public class TagWizardController extends MolgenisPluginController { private static final Logger LOG = LoggerFactory.getLogger(TagWizardController.class); public static final String ID = "tagwizard"; public static final String URI = MolgenisPluginController.PLUGIN_URI_PREFIX + ID; private static final String VIEW_TAG_WIZARD = "view-tag-wizard"; @Autowired private DataService dataService; @Autowired private OntologyService ontologyService; @Autowired private OntologyTagService ontologyTagService; @Autowired private SemanticSearchService semanticSearchService; public TagWizardController() { super(URI); } /** * Displays on tag wizard button press * * @param target The target entity name * @param model the model * @return name of the tag wizard view */ @RequestMapping public String viewTagWizard(@RequestParam(required = false, value = "selectedTarget") String target, Model model) { List<String> entityNames = dataService.findAll(ENTITY_TYPE_META_DATA) .map(e -> e.getString(EntityTypeMetadata.FULL_NAME)).collect(toList()); if (StringUtils.isEmpty(target)) { Optional<String> findFirst = entityNames.stream().findFirst(); if (findFirst.isPresent()) { target = findFirst.get(); } } if (StringUtils.isEmpty(target)) { throw new UnknownEntityException("There are no entities available!"); } List<Ontology> ontologies = ontologyService.getOntologies(); EntityType emd = dataService.getEntityType(target); List<Attribute> attributes = newArrayList(emd.getAttributes()); Map<String, Multimap<Relation, OntologyTerm>> taggedAttributes = attributes.stream() .collect(toMap((x -> x.getName()), (x -> ontologyTagService.getTagsForAttribute(emd, x)))); model.addAttribute("entity", emd); model.addAttribute("entityNames", entityNames); model.addAttribute("attributes", attributes); model.addAttribute("ontologies", ontologies); model.addAttribute("taggedAttributes", taggedAttributes); model.addAttribute("relations", Relation.values()); return VIEW_TAG_WIZARD; } /** * Add a tag for a single attribute * * @param request the {@link AddTagRequest} containing the entityName, attributeName, relationIRI and ontologyTermIRIs */ @RequestMapping(method = RequestMethod.POST, value = "/tagattribute") public @ResponseBody OntologyTag addTagAttribute(@Valid @RequestBody AddTagRequest request) { return ontologyTagService .addAttributeTag(request.getEntityName(), request.getAttributeName(), request.getRelationIRI(), request.getOntologyTermIRIs()); } /** * Delete a single tag * * @param request the {@link RemoveTagRequest} containing entityName, attributeName, relationIRI and ontologyTermIRI */ @RequestMapping(method = RequestMethod.POST, value = "/deletesingletag") public @ResponseBody void deleteSingleTag(@Valid @RequestBody RemoveTagRequest request) { ontologyTagService .removeAttributeTag(request.getEntityName(), request.getAttributeName(), request.getRelationIRI(), request.getOntologyTermIRI()); } /** * Clears all tags from every attribute in the current target entity * * @param entityName The name of the {@link Entity} */ @RequestMapping(method = RequestMethod.POST, value = "/clearalltags") public @ResponseBody void clearAllTags(@RequestParam String entityName) { ontologyTagService.removeAllTagsFromEntity(entityName); } /** * Automatically tags all attributes in the current entity using Lucene lexical matching. Stores the tags in the * OntologyTag Repository. * * @param request containing the entityName and selected ontology identifiers * @return A {@link Map} containing Attribute name and a Map of Tag iri and label */ @RequestMapping(method = RequestMethod.POST, value = "/autotagattributes") public @ResponseBody Map<String, OntologyTag> autoTagAttributes(@Valid @RequestBody AutoTagRequest request) { Map<Attribute, Hit<OntologyTerm>> autoGeneratedTags = semanticSearchService .findTags(request.getEntityName(), request.getOntologyIds()); return ontologyTagService.tagAttributesInEntity(request.getEntityName(), Maps.transformValues(autoGeneratedTags, hit -> hit.getResult())); } /** * Returns ontology terms based on a search term and a selected ontology * * @param request Containing ontology identifiers and a search term * @return A {@link List} of {@link OntologyTerm}s */ @RequestMapping(method = RequestMethod.POST, value = "/getontologyterms") public @ResponseBody List<OntologyTerm> getAllOntologyTerms(@Valid @RequestBody GetOntologyTermRequest request) { return ontologyService.findOntologyTerms(request.getOntologyIds(), of(request.getSearchTerm()), 100); } @ExceptionHandler(RuntimeException.class) @ResponseBody @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ErrorMessageResponse handleRuntimeException(RuntimeException e) { LOG.error(e.getMessage(), e); return new ErrorMessageResponse(new ErrorMessageResponse.ErrorMessage( "An error occurred. Please contact the administrator.<br />Message:" + e.getMessage())); } }