package alien4cloud.rest.suggestion; import java.util.List; import java.util.Set; import javax.annotation.Resource; import io.swagger.annotations.Api; import org.alien4cloud.tosca.model.types.AbstractToscaType; import org.alien4cloud.tosca.model.types.ArtifactType; import org.alien4cloud.tosca.model.types.CapabilityType; import org.alien4cloud.tosca.model.types.NodeType; import org.alien4cloud.tosca.model.types.RelationshipType; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.mapping.MappingBuilder; import org.elasticsearch.search.sort.SortOrder; import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.google.common.collect.Sets; import alien4cloud.dao.ElasticSearchDAO; import alien4cloud.dao.IGenericSearchDAO; import alien4cloud.dao.model.FetchContext; import alien4cloud.dao.model.GetMultipleDataResult; import alien4cloud.model.application.Application; import alien4cloud.model.common.Tag; import alien4cloud.rest.model.RestResponse; import alien4cloud.rest.model.RestResponseBuilder; import springfox.documentation.annotations.ApiIgnore; /** * Handle Suggestion requests. * * @author 'Igor Ngouagna' */ @RestController @RequestMapping({ "/rest/suggest", "/rest/v1/suggest", "/rest/latest/suggest" }) @Api public class SuggestionController { private static final int SUGGESTION_COUNT = 10; private static final String TAG_FIELD = "tags"; private static final String[] INDEXES = new String[] { ElasticSearchDAO.TOSCA_ELEMENT_INDEX, Application.class.getSimpleName().toLowerCase() }; private static final Class<?>[] CLASSES = new Class<?>[] { Application.class, NodeType.class, ArtifactType.class, CapabilityType.class, RelationshipType.class }; @Resource(name = "alien-es-dao") private IGenericSearchDAO dao; /** * Get suggestion for tags based on current tags defined on the components. * * @param tagName The name of the tag for which to get suggestion. * @param searchPrefix The current prefix for the tag suggestion. * @return A {@link RestResponse} that contains a list of suggestions for the tag key. */ @ApiIgnore @RequestMapping(value = "/tag/{tagName}/{searchPrefix}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize("isAuthenticated()") public RestResponse<String[]> tagSuggest(@PathVariable String tagName, @PathVariable String searchPrefix) { String suggestFieldPath = TAG_FIELD.concat(".").concat(tagName); GetMultipleDataResult searchResult = dao.suggestSearch(INDEXES, CLASSES, suggestFieldPath, searchPrefix, FetchContext.TAG_SUGGESTION, 0, SUGGESTION_COUNT); String[] types = searchResult.getTypes(); Set<String> tagsSuggestions = Sets.newHashSet(); for (int i = 0; i < types.length; i++) { List<Tag> tags; if (types[i].equals(MappingBuilder.indexTypeFromClass(Application.class))) { Application app = (Application) searchResult.getData()[i]; tags = app.getTags(); } else { AbstractToscaType indexedToscaElement = (AbstractToscaType) searchResult.getData()[i]; tags = indexedToscaElement.getTags(); } addSuggestedTag(tags, tagName, searchPrefix, tagsSuggestions); } return RestResponseBuilder.<String[]> builder().data(tagsSuggestions.toArray(new String[tagsSuggestions.size()])).build(); } private void addSuggestedTag(List<Tag> tags, String path, String searchPrefix, Set<String> tagsSuggestions) { for (Tag tag : tags) { String suggestion = ""; if (path.equals("name")) { suggestion = tag.getName(); } else if (path.equals("value")) { suggestion = tag.getValue(); } if (suggestion.startsWith(searchPrefix)) { tagsSuggestions.add(suggestion); } } } @ApiIgnore @RequestMapping(value = "/nodetypes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize("isAuthenticated()") public RestResponse<String[]> nodeTypeSuggest(@RequestParam("text") String searchText) { if (searchText == null || searchText.trim().isEmpty()) { return RestResponseBuilder.<String[]> builder().data(new String[0]).build(); } QueryBuilder queryOnText = QueryBuilders.regexpQuery("elementId", ".*?" + searchText + ".*"); // FIXME the way of getting the highest version of a component has changed // QueryBuilder queryOnHighest = QueryBuilders.termQuery("highestVersion", true); QueryBuilder query = QueryBuilders.boolQuery().must(queryOnText); return RestResponseBuilder.<String[]> builder() .data(dao.selectPath(dao.getIndexForType(NodeType.class), new String[] { MappingBuilder.indexTypeFromClass(NodeType.class) }, query, SortOrder.ASC, "elementId", 0, 10)) .build(); } }