From 3150cc081ae1bfda7895f04dc160cae673525cf7 Mon Sep 17 00:00:00 2001 From: Georgy Litvinov Date: Mon, 16 Sep 2024 13:59:18 +0200 Subject: [PATCH 01/22] Browse filter results --- .../vitro/webapp/dao/DisplayVocabulary.java | 1 + .../generators/ManagePageGenerator.java | 2 + .../utils/ProcessDataGetterN3Map.java | 28 +-- .../utils/ProcessDataGetterN3Utils.java | 14 +- ...ProcessSearchFilterValuesDataGetterN3.java | 157 +++++++++++++++++ .../controller/PagedSearchController.java | 74 ++++---- .../search/controller/SearchFilter.java | 49 ++++-- .../search/controller/SearchFiltering.java | 128 ++++++++------ .../utils/dataGetter/DataGetterUtils.java | 38 +++- .../SearchFilterValuesDataGetter.java | 164 ++++++++++++++++++ .../rdf/display/everytime/dataGetterLabels.n3 | 1 + .../firsttime/search_individuals_vitro.n3 | 29 +++- .../rdf/displayTbox/everytime/displayTBOX.n3 | 6 + .../firsttime/vitro_UiLabel.ttl | 25 +++ .../firsttime/vitro_UiLabel.ttl | 25 +++ .../firsttime/vitro_UiLabel.ttl | 24 +++ .../firsttime/vitro_UiLabel.ttl | 25 +++ .../firsttime/vitro_UiLabel.ttl | 25 +++ .../firsttime/vitro_UiLabel.ttl | 25 +++ .../firsttime/vitro_UiLabel.ttl | 26 +++ .../firsttime/vitro_UiLabel.ttl | 24 +++ .../webapp/js/menupage/pageManagementUtils.js | 17 +- .../js/menupage/processDataGetterUtils.js | 1 + ...cessSearchFilterValuesDataGetterContent.js | 44 +++++ .../menupage/browseSearchFilterValues.ftl | 104 +++++++++++ ...geManagement--browseSearchFilterValues.ftl | 41 +++++ .../pageManagement--contentTemplates.ftl | 1 + .../pageManagement--customDataScript.ftl | 1 + .../freemarker/edit/forms/pageManagement.ftl | 2 + 29 files changed, 969 insertions(+), 132 deletions(-) create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSearchFilterValuesDataGetterN3.java create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchFilterValuesDataGetter.java create mode 100644 webapp/src/main/webapp/js/menupage/processSearchFilterValuesDataGetterContent.js create mode 100644 webapp/src/main/webapp/templates/freemarker/body/menupage/browseSearchFilterValues.ftl create mode 100644 webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--browseSearchFilterValues.ftl diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java index 925d76364f..629cd06883 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java @@ -137,6 +137,7 @@ public class DisplayVocabulary { /* URI of property for Fixed HTML Generator */ public static final String FIXED_HTML_VALUE = DISPLAY_NS + "htmlValue"; + public static final String SEARCH_FILTER_VALUE = DISPLAY_NS + "searchFilter"; /* URI of property for Search Query Generator */ diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java index 9f259afa10..818defefc2 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java @@ -526,6 +526,8 @@ private void addRequiredPageData(VitroRequest vreq, Map data) { MenuManagementDataUtils.includeRequiredSystemData(vreq.getSession().getServletContext(), data); data.put("classGroup", new ArrayList()); data.put("classGroups", DataGetterUtils.getClassGroups(vreq)); + data.put("searchFilter", new ArrayList()); + data.put("searchFilters", DataGetterUtils.getSearchFilters(vreq)); //for search individuals data get getter data.put("classes", this.getAllVClasses(vreq)); data.put("availablePermissions", this.getAvailablePermissions(vreq)); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Map.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Map.java index b307eb0d8d..a919b27747 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Map.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Map.java @@ -7,29 +7,37 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ClassGroupPageData; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.IndividualsForClassesDataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchFilterValuesDataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchIndividualsDataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter; + /* * This class determines what n3 should be returned for a particular data getter and can be overwritten or extended in VIVO. */ public class ProcessDataGetterN3Map { private static final Log log = LogFactory.getLog(ProcessDataGetterN3Map.class); - private static HashMap dataGetterMap; + private static HashMap dataGetterMap; static { - dataGetterMap = new HashMap(); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessSparqlDataGetterN3"); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ClassGroupPageData", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessClassGroupDataGetterN3"); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.IndividualsForClassesDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessIndividualsForClassesDataGetterN3"); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessFixedHTMLN3"); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchIndividualsDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessSearchIndividualsDataGetterN3"); + dataGetterMap = new HashMap(); + dataGetterMap.put(SparqlQueryDataGetter.class.getCanonicalName(), ProcessSparqlDataGetterN3.class); + dataGetterMap.put(ClassGroupPageData.class.getCanonicalName(), ProcessClassGroupDataGetterN3.class); + dataGetterMap.put(SearchFilterValuesDataGetter.class.getCanonicalName(), ProcessSearchFilterValuesDataGetterN3.class); + dataGetterMap.put(IndividualsForClassesDataGetter.class.getCanonicalName(), ProcessIndividualsForClassesDataGetterN3.class); + dataGetterMap.put(FixedHTMLDataGetter.class.getCanonicalName(), ProcessFixedHTMLN3.class); + dataGetterMap.put(SearchIndividualsDataGetter.class.getCanonicalName(), ProcessSearchIndividualsDataGetterN3.class); } - public static HashMap getDataGetterTypeToProcessorMap() { + public static HashMap getDataGetterTypeToProcessorMap() { return dataGetterMap; } - public static void replaceDataGetterMap(HashMap newMap) { - dataGetterMap = new HashMap(); + public static void replaceDataGetterMap(HashMap newMap) { + dataGetterMap = new HashMap(); dataGetterMap.putAll(newMap); } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java index 0a40c447c3..96c0bb7c24 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java @@ -17,26 +17,26 @@ public class ProcessDataGetterN3Utils { private static final Log log = LogFactory.getLog(ProcessDataGetterN3Utils.class); public static ProcessDataGetterN3 getDataGetterProcessorN3(String dataGetterClass, ObjectNode jsonObject) { - HashMap map = ProcessDataGetterN3Map.getDataGetterTypeToProcessorMap(); + HashMap map = ProcessDataGetterN3Map.getDataGetterTypeToProcessorMap(); // if(map.containsKey(dataGetterClass)) { - String processorClass = map.get(dataGetterClass); + Class processorClass = map.get(dataGetterClass); try { ProcessDataGetterN3 pn = instantiateClass(processorClass, jsonObject); return pn; } catch(Exception ex) { log.error("Exception occurred in trying to get processor class for n3 for " + dataGetterClass, ex); return null; - } + } } + log.error(ProcessDataGetterN3Map.class.getSimpleName() + " doesn't contain processor class for n3 for " + dataGetterClass); return null; } - private static ProcessDataGetterN3 instantiateClass(String processorClass, ObjectNode jsonObject) { + private static ProcessDataGetterN3 instantiateClass(Class processorClass, ObjectNode jsonObject) { ProcessDataGetterN3 pn = null; try { - Class clz = Class.forName(processorClass); - Constructor[] ctList = clz.getConstructors(); + Constructor[] ctList = processorClass.getConstructors(); for (Constructor ct: ctList) { Class[] parameterTypes =ct.getParameterTypes(); if(parameterTypes.length > 0 && parameterTypes[0].isAssignableFrom(jsonObject.getClass())) { @@ -47,7 +47,7 @@ private static ProcessDataGetterN3 instantiateClass(String processorClass, Objec } } catch(Exception ex) { - log.error("Error occurred instantiating " + processorClass, ex); + log.error("Error occurred instantiating " + processorClass.getCanonicalName(), ex); } return pn; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSearchFilterValuesDataGetterN3.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSearchFilterValuesDataGetterN3.java new file mode 100644 index 0000000000..93bc1b9b6d --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSearchFilterValuesDataGetterN3.java @@ -0,0 +1,157 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils; + +import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.SEARCH_FILTER_VALUE; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.servlet.ServletContext; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchFilterValuesDataGetter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jena.ontology.OntModel; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Resource; + +//Returns the appropriate n3 based on data getter +public class ProcessSearchFilterValuesDataGetterN3 extends ProcessDataGetterAbstract { + private static String classType = "java:" + SearchFilterValuesDataGetter.class.getCanonicalName(); + public static String searchFilterVarBase = "filterUri"; + private Log log = LogFactory.getLog(ProcessSearchFilterValuesDataGetterN3.class); + + public ProcessSearchFilterValuesDataGetterN3() { + } + + public List retrieveN3Required(int counter) { + return retrieveN3ForTypeAndFilter(counter); + } + + public List retrieveN3Optional(int counter) { + return null; + } + + public List retrieveN3ForTypeAndFilter(int counter) { + String n3ForType = getN3ForTypePartial(counter); + String n3 = n3ForType + "; \n" + "<" + DisplayVocabulary.SEARCH_FILTER_VALUE + "> " + + getN3VarName(searchFilterVarBase, counter) + " ."; + List n3List = new ArrayList(); + n3List.add(getPrefixes() + n3); + return n3List; + } + + public String getN3ForTypePartial(int counter) { + String dataGetterVar = getDataGetterVar(counter); + String classTypeVar = getN3VarName(classTypeVarBase, counter); + String n3 = dataGetterVar + " a " + classTypeVar; + return n3; + } + + public List retrieveLiteralsOnForm(int counter) { + // no literals, just the class group URI + List literalsOnForm = new ArrayList(); + return literalsOnForm; + } + + public List retrieveUrisOnForm(int counter) { + List urisOnForm = new ArrayList(); + urisOnForm.add(getVarName("filterUri", counter)); + urisOnForm.add(getVarName(classTypeVarBase, counter)); + return urisOnForm; + } + + public List retrieveFields(int counter) { + List fields = new ArrayList(); + fields.add(new FieldVTwo().setName(getVarName("filterUri", counter))); + fields.add(new FieldVTwo().setName(getVarName(classTypeVarBase, counter))); + return fields; + } + + public List getLiteralVarNamesBase() { + return Arrays.asList(); + } + + public List getUriVarNamesBase() { + return Arrays.asList("filterUri", classTypeVarBase); + } + + public String getClassType() { + return classType; + } + + public void populateExistingValues(String dataGetterURI, int counter, OntModel queryModel) { + // First, put dataGetterURI within scope as well + this.populateExistingDataGetterURI(dataGetterURI, counter); + // Put in type + this.populateExistingClassType(this.getClassType(), counter); + // Sparql queries for values to be executed + // And then placed in the correct place/literal or uri + String querystr = getExistingValuesClassGroup(dataGetterURI); + QueryExecution qe = null; + try { + Query query = QueryFactory.create(querystr); + qe = QueryExecutionFactory.create(query, queryModel); + ResultSet results = qe.execSelect(); + while (results.hasNext()) { + QuerySolution qs = results.nextSolution(); + Resource classGroupResource = qs.getResource("filterUri"); + // Put both literals in existing literals + existingUriValues.put(this.getVarName(searchFilterVarBase, counter), + new ArrayList(Arrays.asList(classGroupResource.getURI()))); + } + } catch (Exception ex) { + log.error("Exception occurred in retrieving existing values with query " + querystr, ex); + } + } + + protected String getExistingValuesClassGroup(String dataGetterURI) { + String query = getSparqlPrefix() + "\n" + + "SELECT ?filterUri ?filterName WHERE {" + + "<" + dataGetterURI + "> <" + SEARCH_FILTER_VALUE + "> ?filterUri .\n" + + "?filterUri <" + VitroVocabulary.LABEL + "> ?filterName .\n" + + "}"; + return query; + } + + public ObjectNode getExistingValuesJSON(String dataGetterURI, OntModel queryModel, ServletContext context) { + ObjectNode jObject = new ObjectMapper().createObjectNode(); + jObject.put("dataGetterClass", classType); + jObject.put(classTypeVarBase, classType); + getExistingSearchFilters(dataGetterURI, jObject, queryModel); + return jObject; + } + + private void getExistingSearchFilters(String dataGetterURI, ObjectNode jObject, OntModel queryModel) { + String querystr = getExistingValuesClassGroup(dataGetterURI); + QueryExecution qe = null; + try { + Query query = QueryFactory.create(querystr); + qe = QueryExecutionFactory.create(query, queryModel); + ResultSet results = qe.execSelect(); + while (results.hasNext()) { + QuerySolution qs = results.nextSolution(); + Resource filterUri = qs.getResource("filterUri"); + Literal name = qs.getLiteral("filterName"); + jObject.put("searchFilterUri", filterUri.getURI()); + jObject.put("searchFilterName", name.getLexicalForm()); + } + } catch (Exception ex) { + log.error("Exception occurred in retrieving existing values with query " + querystr, ex); + } + } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java index 9596ed4838..128e91d4ba 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java @@ -76,7 +76,7 @@ public class PagedSearchController extends FreemarkerHttpServlet { public static final String PARAM_QUERY_TEXT = "querytext"; public static final String PARAM_QUERY_SORT_BY = "sort"; - protected static final Map> templateTable; + protected static final Map> templateTable = setupTemplateTable(); protected enum Format { HTML, @@ -90,10 +90,6 @@ protected enum Result { BAD_QUERY } - static { - templateTable = setupTemplateTable(); - } - /** * Overriding doGet from FreemarkerHttpController to do a page template (as opposed to body template) style output * for XML requests. @@ -134,8 +130,12 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro @Override protected ResponseValues processRequest(VitroRequest vreq) { - - // There may be other non-html formats in the future + Map> requestFilters = SearchFiltering.getRequestFilters(vreq); + return process(vreq, requestFilters); + } + + public static ResponseValues process(VitroRequest vreq, Map> requestFilters) { + // There may be other non-html formats in the future Format format = getFormat(vreq); boolean wasXmlRequested = Format.XML == format; boolean wasCSVRequested = Format.CSV == format; @@ -176,18 +176,12 @@ protected ResponseValues processRequest(VitroRequest vreq) { if (log.isDebugEnabled()) { log.debug(getSpentTime(startTime) + "ms spent before get sort configurations."); } - for (SearchFilter filter: filterConfigurationsByField.values()) { - filter.setInputText(SearchFiltering.getFilterInputText(vreq, filter.getId())); - filter.setRangeValues(SearchFiltering.getFilterRangeText(vreq, filter.getId())); - } - Map> requestFilters = SearchFiltering.getRequestFilters(vreq); - if (log.isDebugEnabled()) { - log.debug(getSpentTime(startTime) + "ms spent after getRequestFilters."); - } - SearchFiltering.setSelectedFilters(filterConfigurationsByField, requestFilters); + + SearchFiltering.setSelectedFilters(filterConfigurationsByField, requestFilters); if (log.isDebugEnabled()) { log.debug(getSpentTime(startTime) + "ms spent after setSelectedFilters."); - } + } + Map sortConfigurations = SearchFiltering.getSortConfigurations(vreq); if (log.isDebugEnabled()) { log.debug(getSpentTime(startTime) + "ms spent before get query configurations."); @@ -313,13 +307,13 @@ protected ResponseValues processRequest(VitroRequest vreq) { } catch (Throwable e) { return doSearchError(e, format); } - } + } - private long getSpentTime(long startTime) { + private static long getSpentTime(long startTime) { return (System.nanoTime() - startTime) / 1000000; } - private Object isEmptySearchFilters(Map filterConfigurationsByField) { + private static Object isEmptySearchFilters(Map filterConfigurationsByField) { for (SearchFilter filter : filterConfigurationsByField.values()) { if (filter.isSelected()) { return false; @@ -328,7 +322,7 @@ private Object isEmptySearchFilters(Map filterConfiguratio return true; } - private void addFacetCountersFromRequest(SearchResponse response, Map filtersByField, + private static void addFacetCountersFromRequest(SearchResponse response, Map filtersByField, VitroRequest vreq) { long startTime = System.nanoTime(); List resultfacetFields = response.getFacetFields(); @@ -389,7 +383,7 @@ public static String getQueryText(VitroRequest vreq) { return query; } - private int getHitsPerPage(VitroRequest vreq) { + private static int getHitsPerPage(VitroRequest vreq) { int hitsPerPage = DEFAULT_HITS_PER_PAGE; try { int hits = Integer.parseInt(vreq.getParameter(PARAM_HITS_PER_PAGE)); @@ -403,7 +397,7 @@ private int getHitsPerPage(VitroRequest vreq) { return hitsPerPage; } - private int getDocumentsNumber(VitroRequest vreq) { + private static int getDocumentsNumber(VitroRequest vreq) { int documentsNumber = DEFAULT_DOCUMENTS_NUMBER; try { documentsNumber = Integer.parseInt(vreq.getParameter(PARAM_DOCUMENTS_NUMBER)); @@ -417,7 +411,7 @@ private int getDocumentsNumber(VitroRequest vreq) { return documentsNumber; } - private int getStartIndex(VitroRequest vreq) { + private static int getStartIndex(VitroRequest vreq) { int startIndex = 0; try { startIndex = Integer.parseInt(vreq.getParameter(PARAM_START_INDEX)); @@ -428,7 +422,7 @@ private int getStartIndex(VitroRequest vreq) { return startIndex; } - private String getSnippet(SearchResultDocument doc, SearchResponse response) { + private static String getSnippet(SearchResultDocument doc, SearchResponse response) { String docId = doc.getStringValue(VitroSearchTermNames.DOCID); StringBuilder text = new StringBuilder(); Map>> highlights = response.getHighlighting(); @@ -441,8 +435,8 @@ private String getSnippet(SearchResultDocument doc, SearchResponse response) { return text.toString(); } - private SearchQuery getQuery(String queryText, int hitsPerPage, int startIndex, VitroRequest vreq, - Map filtersByField, Map sortOptions) { + private static SearchQuery getQuery(String queryText, int hitsPerPage, int startIndex, VitroRequest vreq, + Map filters, Map sortOptions) { // Lowercase the search term to support wildcard searches: The search engine // applies no text // processing to a wildcard search term. @@ -457,24 +451,22 @@ private SearchQuery getQuery(String queryText, int hitsPerPage, int startIndex, addDefaultVitroFacets(vreq, query); - SearchFiltering.addFacetFieldsToQuery(filtersByField, query); - - Map filtersById = SearchFiltering.getFiltersById(filtersByField); + SearchFiltering.addFacetFieldsToQuery(filters, query); - SearchFiltering.addFiltersToQuery(vreq, query, filtersById); + SearchFiltering.addFiltersToQuery(query, filters); log.debug("Query = " + query.toString()); return query; } - private void addDefaultVitroFacets(VitroRequest vreq, SearchQuery query) { + private static void addDefaultVitroFacets(VitroRequest vreq, SearchQuery query) { String[] facets = vreq.getParameterValues(FACETS); if (facets != null && facets.length > 0) { query.addFacetFields(facets); } } - private void addSortRules(VitroRequest vreq, SearchQuery query, Map sortOptions) { + private static void addSortRules(VitroRequest vreq, SearchQuery query, Map sortOptions) { String sortType = getSortType(vreq); if (sortOptions.isEmpty()) { return; @@ -495,7 +487,7 @@ private void addSortRules(VitroRequest vreq, SearchQuery query, Map sortOptions, Set appliedSortOptions) { if (conf == null || appliedSortOptions.contains(conf.getId())) { return; @@ -512,7 +504,7 @@ private void addSortField(VitroRequest vreq, SearchQuery query, SortConfiguratio } } - private String getSortType(VitroRequest vreq) { + private static String getSortType(VitroRequest vreq) { return vreq.getParameter(PARAM_QUERY_SORT_BY); } @@ -550,12 +542,12 @@ protected static List getPagingLinks(int startIndex, int hitsPerPage return pagingLinks; } - private String getPreviousPageLink(int startIndex, int hitsPerPage, String baseUrl, ParamMap params) { + private static String getPreviousPageLink(int startIndex, int hitsPerPage, String baseUrl, ParamMap params) { params.put(PARAM_START_INDEX, String.valueOf(startIndex - hitsPerPage)); return UrlBuilder.getUrl(baseUrl, params); } - private String getNextPageLink(int startIndex, int hitsPerPage, String baseUrl, ParamMap params) { + private static String getNextPageLink(int startIndex, int hitsPerPage, String baseUrl, ParamMap params) { params.put(PARAM_START_INDEX, String.valueOf(startIndex + hitsPerPage)); return UrlBuilder.getUrl(baseUrl, params); } @@ -577,13 +569,13 @@ protected static class PagingLink extends LinkTemplateModel { } } - private ExceptionResponseValues doSearchError(Throwable e, Format f) { + private static ExceptionResponseValues doSearchError(Throwable e, Format f) { Map body = new HashMap(); body.put("message", "Search failed: " + e.getMessage()); return new ExceptionResponseValues(getTemplate(f, Result.ERROR), body, e); } - private TemplateResponseValues doFailedSearch(String message, String querytext, Format f, VitroRequest vreq) { + private static TemplateResponseValues doFailedSearch(String message, String querytext, Format f, VitroRequest vreq) { Map body = new HashMap(); body.put("title", I18n.text(vreq, "search_for", querytext)); if (StringUtils.isEmpty(message)) { @@ -596,7 +588,7 @@ private TemplateResponseValues doFailedSearch(String message, String querytext, /** * Makes a message to display to user for a bad search term. */ - private String makeBadSearchMessage(String querytext, String exceptionMsg, VitroRequest vreq) { + private static String makeBadSearchMessage(String querytext, String exceptionMsg, VitroRequest vreq) { String rv = ""; try { // try to get the column in the search term that is causing the problems @@ -658,7 +650,7 @@ protected boolean isRequestedFormatCSV(VitroRequest req) { } } - protected Format getFormat(VitroRequest req) { + protected static Format getFormat(VitroRequest req) { if (req != null && req.getParameter("xml") != null && "1".equals(req.getParameter("xml"))) { return Format.XML; } else if (req != null && req.getParameter("csv") != null && "1".equals(req.getParameter("csv"))) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFilter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFilter.java index 8066c6424e..4f9a8cae5d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFilter.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFilter.java @@ -8,8 +8,10 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -40,15 +42,15 @@ public class SearchFilter { private boolean selected = false; private boolean input = false; private Map values = new LinkedHashMap<>(); - private boolean inputRegex = false; - private boolean facetsRequired; - + private boolean reverseFacetOrder; private String type = FILTER; private String rangeText = ""; private String rangeInput = ""; private boolean hidden = false; + private Optional locale; + private boolean multilingual; public String getRangeInput() { return rangeInput; @@ -62,8 +64,9 @@ public String getRangeText() { return rangeText; } - public SearchFilter(String id) { + public SearchFilter(String id, Optional locale) { this.id = id; + this.locale = locale; } public String getName() { @@ -87,6 +90,13 @@ public Integer getOrder() { } public String getField() { + if (multilingual) { + if (locale.isPresent()) { + return locale.get().toLanguageTag() + field; + } else { + return Locale.getDefault().toLanguageTag() + field; + } + } return field; } @@ -272,8 +282,8 @@ public void setToYear(String toYear) { public void sortValues() { List> list = new LinkedList<>(values.entrySet()); list.sort(new FilterValueComparator()); - values = list.stream() - .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> b, LinkedHashMap::new)); + values = list.stream().collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> b, + LinkedHashMap::new)); } public boolean isPublic() { @@ -286,15 +296,22 @@ public void setPublic(boolean isPublic) { private class FilterValueComparator implements Comparator> { public int compare(Entry obj1, Entry obj2) { - FilterValue filter1 = obj1.getValue(); - FilterValue filter2 = obj2.getValue(); - int result = filter1.getOrder().compareTo(filter2.getOrder()); + FilterValue first = obj1.getValue(); + FilterValue second = obj2.getValue(); + // sort by order first + int result = first.getOrder().compareTo(second.getOrder()); if (result == 0) { // order are equal, sort by name - return filter1.getName().toLowerCase().compareTo(filter2.getName().toLowerCase()); - } else { - return result; + result = first.getName().toLowerCase().compareTo(second.getName().toLowerCase()); + if (result == 0) { + // names are equal, sort by id + result = first.getId().toLowerCase().compareTo(second.getId().toLowerCase()); + } + if (reverseFacetOrder) { + result = -result; + } } + return result; } } @@ -331,4 +348,12 @@ public int getMoreLimit() { public void setMoreLimit(int moreLimit) { this.moreLimit = moreLimit; } + + public void setMulitlingual(boolean multilingual) { + this.multilingual = multilingual; + } + + public void setReverseFacetOrder(boolean reverseFacetOrder) { + this.reverseFacetOrder = reverseFacetOrder; + } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFiltering.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFiltering.java index a32e963a83..5e74a43b8a 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFiltering.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFiltering.java @@ -3,7 +3,6 @@ import static edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.ROLE_PUBLIC_URI; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; @@ -12,8 +11,10 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -54,7 +55,7 @@ public class SearchFiltering { + "PREFIX rdfs: \n" + "SELECT ?filter_id ?filter_type ?filter_label ?value_label ?value_id ?field_name ?public ?filter_order " + "?value_order (STR(?isUriReq) as ?isUri ) ?multivalued ?input ?regex ?facet ?min ?max ?role " - + "?value_public ?more_limit \n" + + "?value_public ?more_limit ?multilingual ?reverseFacetOrder\n" + "WHERE {\n" + " ?filter rdf:type search:Filter .\n" + " ?filter rdfs:label ?filter_label .\n" @@ -77,11 +78,16 @@ public class SearchFiltering { + " ?value search:public ?value_public .\n" + " }\n" + " }\n" + + " OPTIONAL {\n" + + " ?field search:isLanguageSpecific ?f_multilingual .\n" + + " BIND(?f_multilingual as ?bind_multilingual) .\n" + + " }\n" + " OPTIONAL {?field search:multivalued ?multivalued}\n" + " OPTIONAL {?filter search:isUriValues ?isUriReq }\n" + " OPTIONAL {?filter search:userInput ?input }\n" + " OPTIONAL {?filter search:userInputRegex ?regex }\n" + " OPTIONAL {?filter search:facetResults ?facet }\n" + + " OPTIONAL {?filter search:reverseFacetOrder ?reverseFacetOrder }\n" + " OPTIONAL {?filter search:from ?min }\n" + " OPTIONAL {?filter search:public ?public }\n" + " OPTIONAL {?filter search:to ?max }\n" @@ -92,6 +98,7 @@ public class SearchFiltering { + " }\n" + " BIND(coalesce(?filter_order_found, 0) as ?filter_order)\n" + " BIND(coalesce(?value_order_found, 0) as ?value_order)\n" + + " BIND(COALESCE(?bind_multilingual, false) as ?multilingual)\n" + "} ORDER BY ?filter_id ?filter_order ?value_order"; private static final String FILTER_GROUPS_QUERY = "" @@ -157,42 +164,15 @@ public class SearchFiltering { + " BIND(COALESCE(?bind_multilingual, false) as ?multilingual)\n" + "} ORDER BY ?sort_order ?label "; - protected static void addFiltersToQuery(VitroRequest vreq, SearchQuery query, - Map filterById) { - Enumeration paramNames = vreq.getParameterNames(); - while (paramNames.hasMoreElements()) { - String paramFilterName = paramNames.nextElement(); - if (!StringUtils.isBlank(paramFilterName) && paramFilterName.startsWith(SearchFiltering.FILTERS)) { - String[] filters = vreq.getParameterValues(paramFilterName); - if (filters != null && filters.length > 0) { - for (String filter : filters) { - String[] pair = filter.split(":", 2); - if (pair.length == 2) { - String name = pair[0].replace("\"", ""); - String value = pair[1].replace("\"", ""); - SearchFilter searchFilter = filterById.get(name); - if (searchFilter != null && searchFilter.getField() != null) { - query.addFilterQuery(searchFilter.getField() + ":\"" + value + "\""); - } - - } - } - } - - } - } - addPreconfiguredFiltersToQuery(query, filterById.values()); - } - - public static void addPreconfiguredFiltersToQuery(SearchQuery query, Collection collection) { - for (SearchFilter searchFilter : collection) { + protected static void addFiltersToQuery(SearchQuery query, Map filters) { + for (SearchFilter searchFilter : filters.values()) { if (searchFilter.isInput()) { SearchFiltering.addInputFilter(query, searchFilter); } else if (searchFilter.isRange()) { SearchFiltering.addRangeFilter(query, searchFilter); } for (FilterValue fv : searchFilter.getValues().values()) { - if (fv.isDefault()) { + if (fv.isDefault() || fv.getSelected()) { query.addFilterQuery(searchFilter.getField() + ":\"" + fv.getId() + "\""); } } @@ -204,32 +184,44 @@ public static Map> getRequestFilters(VitroRequest vreq) { Enumeration paramNames = vreq.getParameterNames(); while (paramNames.hasMoreElements()) { String paramFilterName = paramNames.nextElement(); - if (!StringUtils.isBlank(paramFilterName) && paramFilterName.startsWith(SearchFiltering.FILTERS)) { - String[] filters = vreq.getParameterValues(paramFilterName); - if (filters != null && filters.length > 0) { - for (String filter : filters) { + if (paramFilterName.startsWith(SearchFiltering.FILTERS)) { + String[] filterValues = vreq.getParameterValues(paramFilterName); + if (filterValues != null && filterValues.length > 0) { + for (String filter : filterValues) { String[] pair = filter.split(":", 2); if (pair.length == 2) { - String name = pair[0].replace("\"", ""); + String filterId = pair[0].replace("\"", ""); String value = pair[1].replace("\"", ""); - if (requestFilters.containsKey(name)) { - List list = requestFilters.get(name); + if (requestFilters.containsKey(filterId)) { + List list = requestFilters.get(filterId); list.add(value); } else { - requestFilters.put(name, new LinkedList(Arrays.asList(value))); + requestFilters.put(filterId, new LinkedList(Arrays.asList(value))); } } } } } + if (paramFilterName.startsWith(SearchFiltering.FILTER_RANGE)) { + String[] values = vreq.getParameterValues(paramFilterName); + if (values != null && values.length > 0) { + String filterId = paramFilterName.replace(SearchFiltering.FILTER_RANGE, ""); + requestFilters.put(filterId, new LinkedList(Arrays.asList(values[0]))); + } + } + if (paramFilterName.startsWith(SearchFiltering.FILTER_INPUT_PREFIX)) { + String[] values = vreq.getParameterValues(paramFilterName); + if (values != null && values.length > 0) { + String filterId = paramFilterName.replace(SearchFiltering.FILTER_INPUT_PREFIX, ""); + requestFilters.put(filterId, new LinkedList(Arrays.asList(values[0]))); + } + } } - return requestFilters; } public static Map readFilterConfigurations(Set currentRoles, VitroRequest vreq) { long startTime = System.nanoTime(); - Map filtersByField = new LinkedHashMap<>(); Model model; if (vreq != null) { @@ -258,8 +250,10 @@ public static Map readFilterConfigurations(Set cur if (filtersByField.containsKey(resultFieldName)) { filter = filtersByField.get(resultFieldName); } else { - filter = createSearchFilter(filtersByField, solution, resultFilterId, resultFieldName); + Optional locale = vreq != null ? Optional.of(vreq.getLocale()) : Optional.empty(); + filter = createSearchFilter(filtersByField, solution, resultFilterId, resultFieldName, locale); } + filter.setMulitlingual(solution.get("multilingual").asLiteral().getBoolean()); if (solution.get("value_id") == null) { continue; } @@ -292,7 +286,18 @@ public static Map readFilterConfigurations(Set cur public static void addDefaultFilters(SearchQuery query, Set currentRoles) { Map filtersByField = SearchFiltering.readFilterConfigurations(currentRoles, null); - SearchFiltering.addPreconfiguredFiltersToQuery( query, filtersByField.values()); + for (SearchFilter searchFilter : filtersByField.values()) { + if (searchFilter.isInput()) { + SearchFiltering.addInputFilter(query, searchFilter); + } else if (searchFilter.isRange()) { + SearchFiltering.addRangeFilter(query, searchFilter); + } + for (FilterValue fv : searchFilter.getValues().values()) { + if (fv.isDefault() || fv.getSelected()) { + query.addFilterQuery(searchFilter.getField() + ":\"" + fv.getId() + "\""); + } + } + } } public static Map sortFilters(Map filters) { @@ -408,9 +413,9 @@ public static Map getSortConfigurations(VitroRequest } private static SearchFilter createSearchFilter(Map filtersByField, - QuerySolution solution, String resultFilterId, String resultFieldName) { + QuerySolution solution, String resultFilterId, String resultFieldName, Optional locale) { SearchFilter filter; - filter = new SearchFilter(resultFilterId); + filter = new SearchFilter(resultFilterId, locale); filtersByField.put(resultFieldName, filter); filter.setName(solution.get("filter_label")); filter.setOrder(solution.get("filter_order")); @@ -450,6 +455,11 @@ private static SearchFilter createSearchFilter(Map filters filter.setFacetsRequired(facet.asLiteral().getBoolean()); } + RDFNode reverseFacetOrder = solution.get("reverseFacetOrder"); + if (reverseFacetOrder != null) { + filter.setReverseFacetOrder(reverseFacetOrder.asLiteral().getBoolean()); + } + RDFNode moreLimit = solution.get("more_limit"); if (moreLimit != null && moreLimit.isLiteral()) { filter.setMoreLimit(moreLimit.asLiteral().getInt()); @@ -472,8 +482,7 @@ private static void addInputFilter(SearchQuery query, SearchFilter searchFilter) } String searchText = searchFilter.getInputText(); if (searchFilter.isInputRegex()) { - searchText = searchText.replaceAll("([ )(:])", "\\\\$1") + "*"; - query.addFilterQuery(searchFilter.getField() + ":" + searchText); + query.addFilterQuery(searchFilter.getField() + ":/" + searchText + "/"); } else { query.addFilterQuery(searchFilter.getField() + ":\"" + searchText + "\""); } @@ -498,17 +507,26 @@ static String getFilterRangeText(VitroRequest vreq, String name) { return ""; } - public static void setSelectedFilters(Map filtersByField, - Map> requestFilters) { - for (SearchFilter filter : filtersByField.values()) { + public static void setSelectedFilters(Map filters, Map> requestFilters) { + for (SearchFilter filter : filters.values()) { if (requestFilters.containsKey(filter.getId())) { List requestValues = requestFilters.get(filter.getId()); if (!SearchFiltering.isEmptyValues(requestValues)) { filter.setSelected(true); - for (String requestValue : requestValues) { - if (filter.getValues().containsKey(requestValue)) { - FilterValue value = filter.getValue(requestValue); - value.setSelected(true); + if (filter.isRange()) { + filter.setRangeValues(requestValues.iterator().next()); + } else if (filter.isInput()) { + filter.setInputText(requestValues.iterator().next()); + } else { + for (String requestValue : requestValues) { + if (filter.getValues().containsKey(requestValue)) { + FilterValue value = filter.getValue(requestValue); + value.setSelected(true); + } else { + FilterValue value = new FilterValue(requestValue); + value.setSelected(true); + filter.addValue(value); + } } } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java index 2fc1a35ee1..1839cacfce 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java @@ -16,7 +16,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - +import org.apache.jena.ontology.OntModel; import org.apache.jena.query.Query; import org.apache.jena.query.QueryExecution; import org.apache.jena.query.QueryExecutionFactory; @@ -447,8 +447,38 @@ public static void getClassGroupForDataGetter(HttpServletRequest req, Map \n" + + "SELECT ?filterUri ?filterName WHERE {\n" + + " ?filterUri a search:Filter .\n" + + " ?filterUri search:facetResults true .\n" + + " ?filterUri <" + VitroVocabulary.LABEL + "> ?filterName .\n" + + "}"; + + public static Object getSearchFilters(VitroRequest vreq) { + OntModel model = vreq.getDisplayModel(); + List> filters = new ArrayList>(); + Query q = QueryFactory.create(searchFiltersQuery); + QuerySolutionMap bindings = new QuerySolutionMap(); + model.enterCriticalSection(Lock.READ); + try (QueryExecution qexec = QueryExecutionFactory.create(q, model, bindings);) { + ResultSet res = qexec.execSelect(); + while (res.hasNext()) { + QuerySolution sol = res.next(); + Resource uri = sol.getResource("filterUri"); + Literal name = sol.getLiteral("filterName"); + HashMap filter = new HashMap(); + filter.put("URI", uri.toString()); + filter.put("publicName", name.getLexicalForm()); + filters.add(filter); + } + } catch (Exception e) { + log.error(e, e); + } finally { + model.leaveCriticalSection(); + } + return filters; + } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchFilterValuesDataGetter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchFilterValuesDataGetter.java new file mode 100644 index 0000000000..a07eb81eb0 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchFilterValuesDataGetter.java @@ -0,0 +1,164 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ +package edu.cornell.mannlib.vitro.webapp.utils.dataGetter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletContext; + +import com.google.common.base.Optional; +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.search.controller.FilterValue; +import edu.cornell.mannlib.vitro.webapp.search.controller.PagedSearchController; +import edu.cornell.mannlib.vitro.webapp.search.controller.SearchFilter; +import edu.cornell.mannlib.vitro.webapp.search.controller.SearchFiltering; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.QuerySolutionMap; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.shared.Lock; +import org.apache.tika.utils.StringUtils; + +public class SearchFilterValuesDataGetter extends DataGetterBase implements DataGetter { + private static final String defaultTemplate = "browseSearchFilterValues.ftl"; + private static final String searchFilterUri = "<" + DisplayVocabulary.SEARCH_FILTER_VALUE + ">"; + private static final Log log = LogFactory.getLog(SearchFilterValuesDataGetter.class); + + String dataGetterURI; + String searchFilter; + VitroRequest vreq; + ServletContext context; + + /** + * Constructor with display model and data getter URI that will be called by reflection. + */ + public SearchFilterValuesDataGetter(VitroRequest vreq, Model displayModel, String dataGetterURI) { + this.configure(vreq, displayModel, dataGetterURI); + } + + @Override + public Map getData(Map pageData) { + Map responseMap = new HashMap<>(); + responseMap.putAll(vreq.getParameterMap()); + Map> requestFilters = Collections.emptyMap(); + Map defaultSearchResults = PagedSearchController.process(vreq, requestFilters).getMap(); + responseMap.put("filterGenericInfo", defaultSearchResults); + requestFilters = SearchFiltering.getRequestFilters(vreq); + Optional filterValue = Optional.absent(); + if (!isValidFilterValueProvided(requestFilters, defaultSearchResults)) { + // get first filter value from emptyRequestMap and apply it for next request. + filterValue = getFirstFilterValue(defaultSearchResults); + if (filterValue.isPresent()) { + requestFilters.put(searchFilter, new ArrayList(Arrays.asList(filterValue.get().getId()))); + } + } + responseMap.putAll(PagedSearchController.process(vreq, requestFilters).getMap()); + responseMap.put("searchFilter", this.searchFilter); + responseMap.put("bodyTemplate", defaultTemplate); + responseMap.put("languageAware", isLanguageAwarenessEnabled()); + return responseMap; + } + + private Boolean isLanguageAwarenessEnabled() { + ConfigurationProperties cp = ConfigurationProperties.getInstance(); + return Boolean.valueOf(cp.getProperty("RDFService.languageFilter", "false")); + } + + private boolean isValidFilterValueProvided(Map> requestFilters, + Map defaultSearchResults) { + String mainFilterValue = vreq.getParameter("filters_main"); + List requestedValues = requestFilters.get(searchFilter); + if (StringUtils.isBlank(mainFilterValue) || requestedValues == null || requestedValues.isEmpty() + || StringUtils.isBlank(requestedValues.iterator().next())) { + return false; + } + String requestedValue = requestedValues.iterator().next(); + try { + Map filterMap = (Map) defaultSearchResults.get("filters"); + SearchFilter f = filterMap.get(searchFilter); + Map values = f.getValues(); + if (values.containsKey(requestedValue)) { + return true; + } + } catch (Exception e) { + log.error(e, e); + } + return false; + } + + private Optional getFirstFilterValue(Map defaultSearchResults) { + try { + Map filterMap = (Map) defaultSearchResults.get("filters"); + SearchFilter f = filterMap.get(searchFilter); + Collection values = f.getValues().values(); + if (!values.isEmpty()) { + return Optional.of(values.iterator().next()); + } + } catch (Exception e) { + log.error(e, e); + } + return Optional.absent(); + } + + /** + * Configure this instance based on the URI and display model. + */ + protected void configure(VitroRequest vreq, Model displayModel, String dataGetterURI) { + if (vreq == null) { + throw new IllegalArgumentException("VitroRequest may not be null."); + } + if (displayModel == null) { + throw new IllegalArgumentException("Display Model may not be null."); + } + if (dataGetterURI == null) { + throw new IllegalArgumentException("PageUri may not be null."); + } + + this.vreq = vreq; + this.context = vreq.getSession().getServletContext(); + this.dataGetterURI = dataGetterURI; + + QuerySolutionMap initBindings = new QuerySolutionMap(); + initBindings.add("dataGetterURI", ResourceFactory.createResource(this.dataGetterURI)); + + Query configurationQuery = QueryFactory.create(dataGetterQuery); + displayModel.enterCriticalSection(Lock.READ); + try (QueryExecution qexec = QueryExecutionFactory.create(configurationQuery, displayModel, initBindings)) { + ResultSet res = qexec.execSelect(); + while (res.hasNext()) { + QuerySolution soln = res.next(); + this.searchFilter = soln.getLiteral("id").toString(); + } + } finally { + displayModel.leaveCriticalSection(); + } + } + + public static final String defaultVarNameForResults = "results"; + + /** + * Query to get search filter id for a given URI. + */ + private static final String dataGetterQuery = + "PREFIX display: <" + DisplayVocabulary.DISPLAY_NS + "> \n" + + "PREFIX search: \n" + + "SELECT ?id WHERE { \n" + + "?dataGetterURI " + searchFilterUri + " ?searchFilter .\n" + + "?searchFilter search:id ?id .\n" + + "}"; + +} diff --git a/home/src/main/resources/rdf/display/everytime/dataGetterLabels.n3 b/home/src/main/resources/rdf/display/everytime/dataGetterLabels.n3 index a53effd4fe..763f9773e9 100644 --- a/home/src/main/resources/rdf/display/everytime/dataGetterLabels.n3 +++ b/home/src/main/resources/rdf/display/everytime/dataGetterLabels.n3 @@ -6,6 +6,7 @@ @prefix rdfs: . rdfs:label "Class Group Page" . + rdfs:label "Search filter values" . rdfs:label "Browse Page" . rdfs:label "Class Group Page - Selected Classes" . rdfs:label "Sparql Query Results" . diff --git a/home/src/main/resources/rdf/display/firsttime/search_individuals_vitro.n3 b/home/src/main/resources/rdf/display/firsttime/search_individuals_vitro.n3 index 444c16e128..8c8767dc3c 100644 --- a/home/src/main/resources/rdf/display/firsttime/search_individuals_vitro.n3 +++ b/home/src/main/resources/rdf/display/firsttime/search_individuals_vitro.n3 @@ -4,7 +4,7 @@ @prefix rdfs: . :filter_group_search_filters a vitro-search:FilterGroup ; - vitro-search:contains :filter_category , :filter_type , :filter_querytext ; + vitro-search:contains :filter_category , :filter_type , :filter_querytext; vitro-search:id "main" ; vitro-search:order 1 ; vitro-search:public true . @@ -25,6 +25,27 @@ vitro-search:isUriValues true ; vitro-search:public true . +:filter_raw_label_regex + a vitro-search:Filter ; + rdfs:label "Label regular expression"@en-US ; + vitro-search:facetResults false ; + vitro-search:filterField :field_name_raw ; + vitro-search:id "raw_label_regex" ; + vitro-search:public true ; + vitro-search:userInput true ; + vitro-search:userInputRegex true . + +:filter_label_regex + a vitro-search:Filter ; + rdfs:label "Label regular expression"@en-US ; + vitro-search:facetResults false ; + vitro-search:filterField :field_label_display ; + vitro-search:id "label_regex" ; + vitro-search:public true ; + vitro-search:userInput true ; + vitro-search:userInputRegex true . + + :filter_querytext a vitro-search:Filter ; vitro-search:order 1 ; @@ -75,6 +96,11 @@ vitro-search:isLanguageSpecific true ; vitro-search:indexField "_label_sort" . +:field_label_display + a vitro-search:SearchField ; + vitro-search:isLanguageSpecific true ; + vitro-search:indexField "_label_display" . + :field_name_raw a vitro-search:SearchField ; vitro-search:indexField "nameRaw" . @@ -85,7 +111,6 @@ :field_type a vitro-search:SearchField ; vitro-search:indexField "type" ; - vitro-search:isLanguageSpecific true ; vitro-search:multivalued true . :field_querytext diff --git a/home/src/main/resources/rdf/displayTbox/everytime/displayTBOX.n3 b/home/src/main/resources/rdf/displayTbox/everytime/displayTBOX.n3 index e2764a5bc3..8b0d940d27 100644 --- a/home/src/main/resources/rdf/displayTbox/everytime/displayTBOX.n3 +++ b/home/src/main/resources/rdf/displayTbox/everytime/displayTBOX.n3 @@ -28,6 +28,8 @@ display:HomePage a owl:Class . display:ClassGroupPage a owl:Class . +display:SearchFilterValuesDataGetter a owl:Class . + display:IndividualsForClassesPage a owl:Class . display:InternalClassesPage a owl:Class . @@ -57,6 +59,10 @@ display:RequiredAction a owl:Class ; a owl:Class ; rdfs:comment "A data getter for a VClassGroup page" . + + a owl:Class ; + rdfs:comment "A data getter for a search filter values page" . + a owl:Class ; rdfs:comment "A data getter for a Fixed piece of HTML stored in RDF" . diff --git a/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl index e831d2b0e3..51619edbfa 100644 --- a/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@de-DE ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Ergebnisse der Suchfilterung durchsuchen"@de-DE ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Suchfilter auswählen"@de-DE ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl index 0c1d748f46..35ee25d903 100644 --- a/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:suppress_operation_for_unrelated_individuals_of_this_class.Vitro uil:hasApp "Vitro" ; uil:hasKey "suppress_operation_for_unrelated_individuals_of_this_class" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@en-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Browse search filter results"@en-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Select search filter"@en-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl index aedb481253..b94cb67717 100644 --- a/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,27 @@ uil-data:suppress_operation_for_unrelated_individuals_of_this_class.Vitro uil:hasApp "Vitro" ; uil:hasKey "suppress_operation_for_unrelated_individuals_of_this_class" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@en-US ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Browse search filter results"@en-US ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Select search filter"@en-US ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . diff --git a/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl index c9cb7f4aed..303592473d 100644 --- a/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,ñ,o,p,q,r,s,t,u,v,w,x,y,z"@es ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Explorar resultados de búsqueda filtrada"@es ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Seleccionar filtro de búsqueda"@es ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl index b763cd47ee..131843119e 100644 --- a/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@fr-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Parcourir les résultats de filtrage de recherche"@fr-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Sélectionner un filtre de recherche"@fr-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl index 08d1635612..54e805d4df 100644 --- a/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@pt-BR ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Navegar pelos resultados de filtragem de pesquisa"@pt-BR ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Selecionar filtro de pesquisa"@pt-BR ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl index f0c3143a74..7c34cf98ec 100644 --- a/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,29 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "а,б,в,г,д,е,ё,ж,з,и,ӣ,к,л,м,н,о,п,р,с,т,у,ф,х,ц,ч,ш,щ,э,ю,я"@ru-RU ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Отображение результатов поискового фильтра"@ru-RU ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Выберите фильтр"@ru-RU ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + + diff --git a/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl index 9ebf657aa1..4c3ac1edff 100644 --- a/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,27 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,č,ć,d,dž,đ,e,f,g,h,i,j,k,l,lj,m,n,nj,o,p,r,s,š,t,u,v,z,ž"@sr-Latn-RS ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Pregledajte rezultate filtriranja pretrage"@sr-Latn-RS ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Izaberite filter za pretragu"@sr-Latn-RS ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . diff --git a/webapp/src/main/webapp/js/menupage/pageManagementUtils.js b/webapp/src/main/webapp/js/menupage/pageManagementUtils.js index 99ed88d00d..66e04c2b9f 100644 --- a/webapp/src/main/webapp/js/menupage/pageManagementUtils.js +++ b/webapp/src/main/webapp/js/menupage/pageManagementUtils.js @@ -102,6 +102,7 @@ var pageManagementUtils = { //list of options this.contentTypeSelectOptions = $('select#typeSelect option'); this.classGroupSection = $("section#browseClassGroup"); + this.searchFilterSection = $("section#searchFilterValues"); this.sparqlQuerySection = $("section#sparqlQuery"); this.fixedHTMLSection = $("section#fixedHtml"); this.searchIndividualsSection = $("section#searchIndividuals"); @@ -145,6 +146,7 @@ var pageManagementUtils = { // $("section#pageDetails").hide(); this.headerBar.hide(); this.classGroupSection.hide(); + this.searchFilterSection.hide(); this.sparqlQuerySection.hide(); this.fixedHTMLSection.hide(); this.searchIndividualsSection.hide(); @@ -241,6 +243,7 @@ var pageManagementUtils = { pageManagementUtils.clearSourceTemplateValues(); pageManagementUtils.headerBar.hide(); pageManagementUtils.classGroupSection.hide(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.contentTypeSelectOptions.eq(0).prop('selected', 'selected'); @@ -283,6 +286,7 @@ var pageManagementUtils = { //Hide all sections pageManagementUtils.classGroupSection.hide(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.searchIndividualsSection.hide(); @@ -355,6 +359,7 @@ var pageManagementUtils = { pageManagementUtils.clearSourceTemplateValues(); if ( _this.contentTypeSelect.val() == "browseClassGroup" ) { pageManagementUtils.classGroupSection.show(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.searchIndividualsSection.hide(); @@ -362,7 +367,7 @@ var pageManagementUtils = { pageManagementUtils.headerBar.show(); $('div#selfContainedDiv').hide(); } - if ( _this.contentTypeSelect.val() == "fixedHtml" || _this.contentTypeSelect.val() == "sparqlQuery" || _this.contentTypeSelect.val() == "searchIndividuals") { + if ( _this.contentTypeSelect.val() == "fixedHtml" || _this.contentTypeSelect.val() == "sparqlQuery" || _this.contentTypeSelect.val() == "searchIndividuals" || _this.contentTypeSelect.val() == "searchFilterValues") { pageManagementUtils.classGroupSection.hide(); //if fixed html show that, otherwise show sparql results if ( _this.contentTypeSelect.val() == "fixedHtml" ) { @@ -370,17 +375,26 @@ var pageManagementUtils = { pageManagementUtils.fixedHTMLSection.show(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.searchIndividualsSection.hide(); + pageManagementUtils.searchFilterSection.hide(); } else if (_this.contentTypeSelect.val() == "sparqlQuery"){ pageManagementUtils.headerBar.text(pageManagementUtils.sparqlResults + " - "); pageManagementUtils.sparqlQuerySection.show(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.searchIndividualsSection.hide(); + pageManagementUtils.searchFilterSection.hide(); + } else if (_this.contentTypeSelect.val() == "searchFilterValues"){ + pageManagementUtils.headerBar.text(pageManagementUtils.browseSearchFilter + " - "); + pageManagementUtils.searchFilterSection.show(); + pageManagementUtils.sparqlQuerySection.hide(); + pageManagementUtils.fixedHTMLSection.hide(); + pageManagementUtils.searchIndividualsSection.hide(); } else { //search individuals pageManagementUtils.headerBar.text(pageManagementUtils.searchIndividuals + " - "); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.fixedHTMLSection.hide(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.searchIndividualsSection.show(); } @@ -390,6 +404,7 @@ var pageManagementUtils = { } if ( _this.contentTypeSelect.val() == "" ) { pageManagementUtils.classGroupSection.hide(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.searchIndividualsSection.hide(); diff --git a/webapp/src/main/webapp/js/menupage/processDataGetterUtils.js b/webapp/src/main/webapp/js/menupage/processDataGetterUtils.js index 6639480417..454698f715 100644 --- a/webapp/src/main/webapp/js/menupage/processDataGetterUtils.js +++ b/webapp/src/main/webapp/js/menupage/processDataGetterUtils.js @@ -7,6 +7,7 @@ //This will need to be overridden or extended, what have you.. in VIVO var processDataGetterUtils = { dataGetterProcessorMap:{"browseClassGroup": processClassGroupDataGetterContent, + "searchFilterValues": processSearchFilterValuesDataGetterContent, "sparqlQuery": processSparqlDataGetterContent, "fixedHtml":processFixedHTMLDataGetterContent, "individualsForClasses":processIndividualsForClassesDataGetterContent, diff --git a/webapp/src/main/webapp/js/menupage/processSearchFilterValuesDataGetterContent.js b/webapp/src/main/webapp/js/menupage/processSearchFilterValuesDataGetterContent.js new file mode 100644 index 0000000000..55e1855249 --- /dev/null +++ b/webapp/src/main/webapp/js/menupage/processSearchFilterValuesDataGetterContent.js @@ -0,0 +1,44 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +$.extend(this, i18nStringsBrowseSearchFilters); +//Process sparql data getter and provide a json object with the necessary information +//Depending on what is included here, a different type of data getter might be used +var processSearchFilterValuesDataGetterContent = { + dataGetterClass:null, + //can use this if expect to initialize from elsewhere + initProcessor:function(dataGetterClassInput) { + this.dataGetterClass = dataGetterClassInput; + }, + + processPageContentSection:function(pageContentSection) { + var searchFilter = pageContentSection.find("select[name='selectSearchFilter']").val(); + //query model should also be an input, ensure class group URI is saved as URI and not string + var returnObject = {filterUri:searchFilter, dataGetterClass:this.dataGetterClass}; + return returnObject; + }, + //For an existing set of content where form is already set, fill in the values + populatePageContentSection:function(existingContentObject, pageContentSection) { + let searchFilterValue = existingContentObject["searchFilterUri"]; + pageContentSection.find("select[name='selectSearchFilter']").val(searchFilterValue); + }, + + retrieveContentLabel:function() { + return i18nStringsBrowseSearchFilters.browseSearchFilter; + }, + retrieveAdditionalLabelText:function(existingContentObject) { + var label = ""; + var filterName = existingContentObject["searchFilterName"]; + if(filterName != null) { + label = filterName; + } + return label; + }, + //Validation on form submit: Check to see that filter has been selected + validateFormSubmission: function(pageContentSection, pageContentSectionLabel) { + var validationError = ""; + if (pageContentSection.find('select[name="selectSearchFilter"]').val() =='-1') { + validationError += pageContentSectionLabel + ": " + i18nStringsBrowseSearchFilters.supplySearchFilterValues + "
"; + } + return validationError; + } +} diff --git a/webapp/src/main/webapp/templates/freemarker/body/menupage/browseSearchFilterValues.ftl b/webapp/src/main/webapp/templates/freemarker/body/menupage/browseSearchFilterValues.ftl new file mode 100644 index 0000000000..b3f781c5bf --- /dev/null +++ b/webapp/src/main/webapp/templates/freemarker/body/menupage/browseSearchFilterValues.ftl @@ -0,0 +1,104 @@ +<#-- $This file is distributed under the terms of the license in LICENSE$ --> + +<#if filterGenericInfo.filters[searchFilter]??> + <#assign f = filterGenericInfo.filters[searchFilter]> + + + ${stylesheets.add('')} + +
+
+ +
+ <@printPagingLinks /> + <@filteredResults /> + <@printPagingLinks /> +
+
+
+ + +<#macro filteredResults> +
    + <#if individuals??> + <#list individuals as individual> +
  • + <@shortView uri=individual.uri viewContext="index" /> +
  • + + +
+ + + +<#macro filterFacets> +
    + <#assign selectedValue = "" > + <#list f.values?values as value> + <#if value.selected> + <#assign selectedValue = value.id > + + <#assign valueLabel = value.name > + <#if !(valueLabel?has_content)> + <#assign valueLabel = value.id > + +
  • + class="selected" >${valueLabel?html}(${value.count}) + +
  • + +
+ + + +<#macro alphabeticalIndexLinks> + <#if languageAware > + <#assign indexFilterName = "label_regex"> + <#else> + <#assign indexFilterName = "raw_label_regex"> + + <#if filters[indexFilterName]??> + <#assign indexFilter = filters[indexFilterName]> + + + + +<#macro printPagingLinks> + <#if (pagingLinks?? && pagingLinks?size > 0)> + + + diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--browseSearchFilterValues.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--browseSearchFilterValues.ftl new file mode 100644 index 0000000000..bdf3065d89 --- /dev/null +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--browseSearchFilterValues.ftl @@ -0,0 +1,41 @@ +<#-- $This file is distributed under the terms of the license in LICENSE$ --> +<#--Browse Search Filter Values Section--> +<#-----------Variable assignment--------------> +<#--Requires Menu action be defined in parent template--> + +<#assign searchFilter = pageData.searchFilter /> +<#assign searchFilters = pageData.searchFilters /> +<#-- some additional processing here which shows or hides the class group selection and classes based on initial action--> +<#assign selectFilterStyle = 'class="hidden"' /> +<#-- Reveal the class group and hide the class selects if adding a new menu item or editing an existing menu item with an empty class group (no classes)--> +<#-- Menu action needs to be sent from main template--> +<#if menuAction == "Add" || !searchFilter?has_content> + <#assign selectFilterStyle = " " /> + + +<#--HTML Portion--> +
+
+ + + +
+ + <#if menuAction == "Add"> + ${i18n().or} ${i18n().cancel_link} + +
+ + <#--Include JavaScript specific to the types of data getters related to this content--> +${scripts.add('')} diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--contentTemplates.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--contentTemplates.ftl index 891497e462..e2e8bed774 100644 --- a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--contentTemplates.ftl +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--contentTemplates.ftl @@ -4,3 +4,4 @@ <#include "pageManagement--sparqlQuery.ftl"> <#include "pageManagement--fixedHtml.ftl"> <#include "pageManagement--searchIndividuals.ftl"> +<#include "pageManagement--browseSearchFilterValues.ftl"> diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--customDataScript.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--customDataScript.ftl index ec6fed2251..cac9daf7a2 100644 --- a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--customDataScript.ftl +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--customDataScript.ftl @@ -10,6 +10,7 @@ scripts list.--> dataGetterLabelToURI:{ //maps labels to URIs "browseClassGroup": "java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ClassGroupPageData", + "searchFilterValues": "java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchFilterValuesDataGetter", "individualsForClasses": "java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.IndividualsForClassesDataGetter", "sparqlQuery":"java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter", "fixedHtml":"java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter", diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl index 550ae8b398..81172b6a32 100644 --- a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl @@ -79,6 +79,7 @@ - <#assign addDefaultOption = true> - <#list sorting as option> - <#if option.display> - <#if option.selected> - - <#assign addDefaultOption = false> - <#else> - - - - - <#if addDefaultOption> - - - - - + <#if sorting?has_content> +
+ +
+ <#macro printHits> -
- -
+
+ +
<#macro searchFormGroupTab group active > - <#if active> -
  • - <#else> -
  • - - ${group.label?html} -
  • + <#if active> +
  • + <#else> +
  • + + ${group.label?html} +
  • <#macro searchFormFilterTab filter assignedActive> - <#if filter.id == "querytext"> - <#-- skip query text filter --> - <#return> - -
  • - ${filter.name?html} -
  • + <#if filter.id == "querytext"> + <#-- skip query text filter --> + <#return> + +
  • + ${filter.name?html} +
  • <#macro printFilterValues filter assignedActive isEmptySearch> -
    - <#if filter.id == "querytext"> - <#-- skip query text filter --> - <#elseif filter.type == "RangeFilter"> - <@rangeFilter filter/> - <#else> - <#if filter.input> -
    - <@createUserInput filter /> -
    - - - <#assign valueNumber = 1> - <#assign additionalLabels = false> - <#list filter.values?values as v> - <#if !v.selected> - <#if filter.moreLimit = valueNumber - 1 > - <#assign additionalLabels = true> - ${i18n().paging_link_more} - - <#if user.loggedIn || v.publiclyAvailable> - <@getInput filter v getValueID(filter.id, valueNumber) valueNumber /> - ${getLabel(valueNumber, v, filter, additionalLabels)} - - - <#assign valueNumber = valueNumber + 1> - - - <#if additionalLabels > - ${i18n().display_less} - - -
    +
    + <#if filter.id == "querytext"> + <#-- skip query text filter --> + <#elseif filter.type == "RangeFilter"> + <@rangeFilter filter/> + <#else> + <#if filter.input> +
    + <@createUserInput filter /> +
    + + + <#assign valueNumber = 1> + <#assign additionalLabels = false> + <#list filter.values?values as v> + <#if !v.selected> + <#if filter.moreLimit = valueNumber - 1 > + <#assign additionalLabels = true> + ${i18n().paging_link_more} + + <#if user.loggedIn || v.publiclyAvailable> + <@getInput filter v getValueID(filter.id, valueNumber) valueNumber /> + <@getLabel valueNumber, v, filter, additionalLabels /> + + + <#assign valueNumber = valueNumber + 1> + + + <#if additionalLabels > + ${i18n().display_less} + + +
    <#macro rangeFilter filter> - <#assign min = filter.min > - <#assign max = filter.max > - <#assign from = filter.fromYear > - <#assign to = filter.toYear > - -
    -
    -
    - ${i18n().from} - <#if from?has_content> -
    ${from?html}
    - <#else> -
    ${min?html}
    - - ${i18n().to} - <#if to?has_content> -
    ${to?html}
    - <#else> -
    ${max?html}
    - - -
    -
    + <#assign min = filter.min > + <#assign max = filter.max > + <#assign from = filter.fromYear > + <#assign to = filter.toYear > + +
    +
    +
    + ${i18n().from} + <#if from?has_content> +
    ${from?html}
    + <#else> +
    ${min?html}
    + + ${i18n().to} + <#if to?has_content> +
    ${to?html}
    + <#else> +
    ${max?html}
    + + +
    +
    -<#function getSelectedLabel valueID value filter > - <#assign label = filter.name + " : " + value.name > - <#if !filter.localizationRequired> - <#assign label = filter.name + " : " + value.id > - - <#return "" /> - +<#macro getSelectedLabel valueID value filter > + <#assign label = filter.name + " : " + value.name > + <#if !filter.localizationRequired> + <#assign label = filter.name + " : " + value.id > + + + -<#function getLabel valueID value filter additional=false > - <#assign label = value.name > - <#assign additionalClass = "" > - <#if !filter.localizationRequired> - <#assign label = value.id > - - <#if additional=true> - <#assign additionalClass = "additional-search-options hidden-search-option" > - - <#return "" /> - +<#macro getLabel valueID value filter additional=false > + <#assign label = value.name > + <#assign additionalClass = "" > + <#if !filter.localizationRequired> + <#assign label = value.id > + + <#if additional=true> + <#assign additionalClass = "additional-search-options hidden-search-option" > + + + + <#macro userSelectedInput filter> - <#if filter.inputText?has_content> - - - <#assign from = filter.fromYear > - <#assign to = filter.toYear > - <#if from?has_content && to?has_content > - <#assign range = i18n().from + " " + from + " " + i18n().to + " " + to > - - + <#if filter.inputText?has_content> + + + <#assign from = filter.fromYear > + <#assign to = filter.toYear > + <#if from?has_content && to?has_content > + <#assign range = i18n().from + " " + from + " " + i18n().to + " " + to > + + <#macro createUserInput filter> - + <#macro getInput filter filterValue valueID valueNumber form="search-form"> - <#assign checked = "" > - <#assign class = "" > - <#if filterValue.selected> - <#assign checked = " checked=\"checked\" " > - <#assign class = "selected-input" > - - <#assign type = "checkbox" > - <#if !filter.multivalued> - <#assign type = "radio" > - - <#assign filterName = filter.id > - <#if filter.multivalued> - <#assign filterName = filterName + "_" + valueNumber > - - - + <#assign checked = "" > + <#assign class = "" > + <#if filterValue.selected> + <#assign checked = " checked=\"checked\" " > + <#assign class = "selected-input" > + + <#assign type = "checkbox" > + <#if !filter.multivalued> + <#assign type = "radio" > + + <#assign filterName = filter.id > + <#if filter.multivalued> + <#assign filterName = filterName + "_" + valueNumber > + + + <#function getValueID id number> - <#return id + "__" + number /> + <#return id + "__" + number /> <#function getValueLabel label count > - <#assign result = label > - ${label} - <#if count!=0> - <#assign result = result + " (" + count + ")" > - - <#return result /> + <#assign result = label > + ${label} + <#if count!=0> + <#assign result = result + " (" + count + ")" > + + <#return result /> ${stylesheets.add('', - '', + '', '')} ${headScripts.add('', - '', + '', '' )} diff --git a/webapp/src/main/webapp/templates/freemarker/page/partials/identity.ftl b/webapp/src/main/webapp/templates/freemarker/page/partials/identity.ftl index 5a70fcf9f2..303230e930 100644 --- a/webapp/src/main/webapp/templates/freemarker/page/partials/identity.ftl +++ b/webapp/src/main/webapp/templates/freemarker/page/partials/identity.ftl @@ -29,7 +29,7 @@