Explorar o código

fix #405 : customizable default label/sort value

Shinsuke Sugaya %!s(int64=9) %!d(string=hai) anos
pai
achega
89e09ca567

+ 2 - 0
src/main/java/org/codelibs/fess/Constants.java

@@ -111,6 +111,8 @@ public class Constants extends CoreLibConstants {
 
     public static final String DEFAULT_LABEL_VALUE_PROPERTY = "label.value";
 
+    public static final String DEFAULT_SORT_VALUE_PROPERTY = "sort.value";
+
     public static final String LOGIN_REQUIRED_PROPERTY = "login.required";
 
     public static final String IGNORE_FAILURE_TYPE_PROPERTY = "failure.ignoretype";

+ 3 - 15
src/main/java/org/codelibs/fess/app/service/SearchService.java

@@ -51,9 +51,6 @@ import org.elasticsearch.action.bulk.BulkResponse;
 import org.elasticsearch.action.update.UpdateRequestBuilder;
 import org.elasticsearch.action.update.UpdateResponse;
 import org.elasticsearch.index.query.QueryBuilders;
-import org.elasticsearch.search.sort.SortBuilder;
-import org.elasticsearch.search.sort.SortBuilders;
-import org.elasticsearch.search.sort.SortOrder;
 import org.lastaflute.taglib.function.LaFunctions;
 
 public class SearchService {
@@ -101,18 +98,9 @@ public class SearchService {
                         fessConfig.getIndexDocumentSearchIndex(),
                         fessConfig.getIndexDocumentType(),
                         searchRequestBuilder -> {
-                            if (StringUtil.isNotBlank(sortField)) {
-                                final String[] sort = sortField.split("\\.");
-                                final SortBuilder sortBuilder = SortBuilders.fieldSort(sort[0]);
-                                if ("asc".equals(sort[1])) {
-                                    sortBuilder.order(SortOrder.ASC);
-                                } else if ("desc".equals(sort[1])) {
-                                    sortBuilder.order(SortOrder.DESC);
-                                }
-                                searchRequestBuilder.addSort(sortBuilder);
-                            }
-                            return SearchConditionBuilder.builder(searchRequestBuilder).query(query).offset(pageStart).size(pageSize)
-                                    .facetInfo(params.getFacetInfo()).geoInfo(params.getGeoInfo())
+                            return SearchConditionBuilder.builder(searchRequestBuilder)
+                                    .query(StringUtil.isBlank(sortField) ? query : query + " sort:" + sortField).offset(pageStart)
+                                    .size(pageSize).facetInfo(params.getFacetInfo()).geoInfo(params.getGeoInfo())
                                     .responseFields(queryHelper.getResponseFields()).administrativeAccess(params.isAdministrativeAccess())
                                     .build();
                         }, (searchRequestBuilder, execTime, searchResponse) -> {

+ 1 - 1
src/main/java/org/codelibs/fess/app/web/RootAction.java

@@ -44,7 +44,7 @@ public class RootAction extends FessSearchAction {
 
         return asHtml(path_IndexJsp).useForm(SearchForm.class, op -> {
             op.setup(form -> {
-                buildLabelParams(form.fields);
+                buildFormParams(form);
             });
         }).renderWith(
                 data -> {

+ 4 - 2
src/main/java/org/codelibs/fess/app/web/admin/general/AdminGeneralAction.java

@@ -124,7 +124,8 @@ public class AdminGeneralAction extends FessAdminAction {
         updateProperty(Constants.USER_INFO_PROPERTY, getCheckboxValue(form.userInfo));
         updateProperty(Constants.USER_FAVORITE_PROPERTY, getCheckboxValue(form.userFavorite));
         updateProperty(Constants.WEB_API_JSON_PROPERTY, getCheckboxValue(form.webApiJson));
-        updateProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, form.defaultLabelValue);
+        fessConfig.setDefaultLabelValue(form.defaultLabelValue);
+        fessConfig.setDefaultSortValue(form.defaultSortValue);
         updateProperty(Constants.APPEND_QUERY_PARAMETER_PROPERTY, getCheckboxValue(form.appendQueryParameter));
         updateProperty(Constants.IGNORE_FAILURE_TYPE_PROPERTY, form.ignoreFailureType);
         updateProperty(Constants.FAILURE_COUNT_THRESHOLD_PROPERTY, form.failureCountThreshold.toString());
@@ -163,7 +164,8 @@ public class AdminGeneralAction extends FessAdminAction {
         form.userInfo = systemProperties.getProperty(Constants.USER_INFO_PROPERTY, Constants.TRUE);
         form.userFavorite = systemProperties.getProperty(Constants.USER_FAVORITE_PROPERTY, Constants.FALSE);
         form.webApiJson = systemProperties.getProperty(Constants.WEB_API_JSON_PROPERTY, Constants.TRUE);
-        form.defaultLabelValue = systemProperties.getProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, StringUtil.EMPTY);
+        form.defaultLabelValue = fessConfig.getDefaultLabelValue();
+        form.defaultSortValue = fessConfig.getDefaultSortValue();
         form.appendQueryParameter = systemProperties.getProperty(Constants.APPEND_QUERY_PARAMETER_PROPERTY, Constants.FALSE);
         form.ignoreFailureType =
                 systemProperties.getProperty(Constants.IGNORE_FAILURE_TYPE_PROPERTY, Constants.DEFAULT_IGNORE_FAILURE_TYPE);

+ 3 - 0
src/main/java/org/codelibs/fess/app/web/admin/general/EditForm.java

@@ -62,6 +62,9 @@ public class EditForm implements Serializable {
     @Size(max = 1000)
     public String defaultLabelValue;
 
+    @Size(max = 1000)
+    public String defaultSortValue;
+
     @Size(max = 10)
     public String appendQueryParameter;
 

+ 21 - 17
src/main/java/org/codelibs/fess/app/web/base/FessSearchAction.java

@@ -15,7 +15,6 @@
  */
 package org.codelibs.fess.app.web.base;
 
-import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
@@ -134,25 +133,22 @@ public abstract class FessSearchAction extends FessBaseAction {
         return false;
     }
 
-    protected void buildLabelParams(final Map<String, String[]> fields) {
+    protected void buildFormParams(final SearchForm form) {
+        if (form.facet == null) {
+            form.facet = queryHelper.getDefaultFacetInfo();
+        }
+
+        if (form.geo == null) {
+            form.geo = queryHelper.getDefaultGeoInfo();
+        }
+
         // label
         final List<Map<String, String>> labelTypeItems = labelTypeHelper.getLabelTypeItemList();
 
-        if (!labelTypeItems.isEmpty() && !fields.containsKey(FessSearchAction.LABEL_FIELD)) {
-            final String defaultLabelValue = systemProperties.getProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, StringUtil.EMPTY);
-            if (StringUtil.isNotBlank(defaultLabelValue)) {
-                final String[] values = defaultLabelValue.split("\n");
-                if (values != null && values.length > 0) {
-                    final List<String> list = new ArrayList<String>(values.length);
-                    for (final String value : values) {
-                        if (StringUtil.isNotBlank(value)) {
-                            list.add(value);
-                        }
-                    }
-                    if (!list.isEmpty()) {
-                        fields.put(FessSearchAction.LABEL_FIELD, list.toArray(new String[list.size()]));
-                    }
-                }
+        if (!labelTypeItems.isEmpty() && !form.fields.containsKey(FessSearchAction.LABEL_FIELD)) {
+            final String[] defaultLabelValues = fessConfig.getDefaultLabelValues(getUserBean());
+            if (defaultLabelValues.length > 0) {
+                form.fields.put(FessSearchAction.LABEL_FIELD, defaultLabelValues);
             }
         }
 
@@ -163,6 +159,14 @@ public abstract class FessSearchAction extends FessBaseAction {
             }
         }
         request.setAttribute(Constants.LABEL_VALUE_MAP, labelMap);
+
+        // sort
+        if (StringUtil.isBlank(form.sort)) {
+            String[] defaultSortValues = fessConfig.getDefaultSortValues(getUserBean());
+            if (defaultSortValues.length > 0) {
+                form.sort = String.join(",", defaultSortValues);
+            }
+        }
     }
 
     protected void buildInitParams() {

+ 1 - 1
src/main/java/org/codelibs/fess/app/web/help/HelpAction.java

@@ -47,7 +47,7 @@ public class HelpAction extends FessSearchAction {
 
         return asHtml(path_HelpJsp).useForm(SearchForm.class, op -> {
             op.setup(form -> {
-                buildLabelParams(form.fields);
+                buildFormParams(form);
             });
         }).renderWith(data -> {
             buildInitParams();

+ 1 - 12
src/main/java/org/codelibs/fess/app/web/search/SearchAction.java

@@ -118,8 +118,7 @@ public class SearchAction extends FessSearchAction {
         }
 
         try {
-            updateSearchParams(form);
-            buildLabelParams(form.fields);
+            buildFormParams(form);
             form.lang = searchService.getLanguages(request, form);
             request.setAttribute(Constants.REQUEST_LANGUAGES, form.lang);
             final WebRenderData renderData = new WebRenderData();
@@ -173,16 +172,6 @@ public class SearchAction extends FessSearchAction {
         return doSearch(form);
     }
 
-    protected void updateSearchParams(final SearchForm form) {
-        if (form.facet == null) {
-            form.facet = queryHelper.getDefaultFacetInfo();
-        }
-
-        if (form.geo == null) {
-            form.geo = queryHelper.getDefaultGeoInfo();
-        }
-    }
-
     protected String getDisplayQuery(final SearchForm form, final List<Map<String, String>> labelTypeItems) {
         final StringBuilder buf = new StringBuilder(100);
         buf.append(form.q);

+ 4 - 2
src/main/java/org/codelibs/fess/helper/QueryHelper.java

@@ -69,6 +69,8 @@ import org.lastaflute.web.util.LaRequestUtil;
 
 public class QueryHelper implements Serializable {
 
+    protected static final String SCORE_SORT_VALUE = "score";
+
     protected static final long serialVersionUID = 1L;
 
     protected static final String SCORE_FIELD = "score";
@@ -182,7 +184,7 @@ public class QueryHelper implements Serializable {
         }
         if (supportedSortFields == null) {
             supportedSortFields =
-                    new String[] { fessConfig.getIndexFieldCreated(), fessConfig.getIndexFieldContentLength(),
+                    new String[] { SCORE_SORT_VALUE, fessConfig.getIndexFieldCreated(), fessConfig.getIndexFieldContentLength(),
                             fessConfig.getIndexFieldLastModified(), fessConfig.getIndexFieldTimestamp(),
                             fessConfig.getIndexFieldClickCount(), fessConfig.getIndexFieldFavoriteCount() };
         }
@@ -419,7 +421,7 @@ public class QueryHelper implements Serializable {
             } else {
                 sortOrder = SortOrder.ASC;
             }
-            context.addSorts(SortBuilders.fieldSort(sortField).order(sortOrder));
+            context.addSorts(SortBuilders.fieldSort(SCORE_SORT_VALUE.equals(sortField) ? "_score" : sortField).order(sortOrder));
             return null;
         } else if (INURL_FIELD.equals(field)) {
             return QueryBuilders.wildcardQuery(fessConfig.getIndexFieldUrl(), "*" + text + "*").boost(termQuery.getBoost());

+ 6 - 0
src/main/java/org/codelibs/fess/mylasta/action/FessLabels.java

@@ -587,6 +587,9 @@ public class FessLabels extends ActionMessages {
     /** The key of the message: -- Results per page -- */
     public static final String LABELS_search_result_select_num = "{labels.search_result_select_num}";
 
+    /** The key of the message: Score */
+    public static final String LABELS_search_result_sort_score_desc = "{labels.search_result_sort_score_desc}";
+
     /** The key of the message: Date (ascending) */
     public static final String LABELS_search_result_sort_created_asc = "{labels.search_result_sort_created_asc}";
 
@@ -956,6 +959,9 @@ public class FessLabels extends ActionMessages {
     /** The key of the message: Default Label Value */
     public static final String LABELS_default_label_value = "{labels.default_label_value}";
 
+    /** The key of the message: Default Sort Value */
+    public static final String LABELS_default_sort_value = "{labels.default_sort_value}";
+
     /** The key of the message: Append Params to URL */
     public static final String LABELS_append_query_param_enabled = "{labels.append_query_param_enabled}";
 

+ 102 - 0
src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java

@@ -31,13 +31,23 @@ import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.misc.Pair;
 import org.codelibs.core.misc.Tuple3;
 import org.codelibs.fess.Constants;
+import org.codelibs.fess.mylasta.action.FessUserBean;
 import org.codelibs.fess.util.ComponentUtil;
 import org.codelibs.fess.util.StreamUtil;
+import org.dbflute.optional.OptionalThing;
 import org.lastaflute.job.LaJob;
 import org.lastaflute.job.subsidiary.ConcurrentExec;
 
 public interface FessProp {
 
+    public static final String GROUP_VALUE_PREFIX = "group:";
+
+    public static final String ROLE_VALUE_PREFIX = "role:";
+
+    public static final String DEFAULT_SORT_VALUES = "defaultSortValues";
+
+    public static final String DEFAULT_LABEL_VALUES = "defaultLabelValues";
+
     public static final String QUERY_LANGUAGE_MAPPING = "queryLanguageMapping";
 
     public static final String CRAWLER_METADATA_NAME_MAPPING = "crawlerMetadataNameMapping";
@@ -90,6 +100,98 @@ public interface FessProp {
         setSystemProperty(key, Integer.toString(value));
     }
 
+    public default String[] getDefaultSortValues(final OptionalThing<FessUserBean> userBean) {
+        @SuppressWarnings("unchecked")
+        Map<String, String> map = (Map<String, String>) propMap.get(DEFAULT_SORT_VALUES);
+        if (map == null) {
+            String value = getSystemProperty(Constants.DEFAULT_SORT_VALUE_PROPERTY);
+            if (StringUtil.isBlank(value)) {
+                map = Collections.emptyMap();
+            } else {
+                map = StreamUtil.of(value.split("\n")).filter(s -> StringUtil.isNotBlank(s)).map(s -> {
+                    final String[] pair = s.split("=");
+                    if (pair.length == 1) {
+                        return new Pair<>(StringUtil.EMPTY, pair[0].trim());
+                    } else if (pair.length == 2) {
+                        return new Pair<>(pair[1].trim(), pair[0].trim());
+                    }
+                    return null;
+                }).filter(o -> o != null).collect(Collectors.toMap(Pair::getFirst, d -> d.getSecond()));
+            }
+            propMap.put(DEFAULT_SORT_VALUES, map);
+        }
+        return map
+                .entrySet()
+                .stream()
+                .map(e -> {
+                    final String key = e.getKey();
+                    if (StringUtil.isEmpty(key)) {
+                        return e.getValue();
+                    }
+                    if (userBean.map(
+                            user -> StreamUtil.of(user.getRoles()).anyMatch(s -> key.equals(ROLE_VALUE_PREFIX + s))
+                                    || StreamUtil.of(user.getGroups()).anyMatch(s -> key.equals(GROUP_VALUE_PREFIX + s))).orElse(false)) {
+                        return e.getValue();
+                    }
+                    return null;
+                }).filter(s -> StringUtil.isNotBlank(s)).toArray(n -> new String[n]);
+    }
+
+    public default void setDefaultSortValue(final String value) {
+        setSystemProperty(Constants.DEFAULT_SORT_VALUE_PROPERTY, value);
+        propMap.remove(DEFAULT_SORT_VALUES);
+    }
+
+    public default String getDefaultSortValue() {
+        return getSystemProperty(Constants.DEFAULT_SORT_VALUE_PROPERTY, StringUtil.EMPTY);
+    }
+
+    public default String[] getDefaultLabelValues(final OptionalThing<FessUserBean> userBean) {
+        @SuppressWarnings("unchecked")
+        Map<String, String> map = (Map<String, String>) propMap.get(DEFAULT_LABEL_VALUES);
+        if (map == null) {
+            String value = getSystemProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY);
+            if (StringUtil.isBlank(value)) {
+                map = Collections.emptyMap();
+            } else {
+                map = StreamUtil.of(value.split("\n")).filter(s -> StringUtil.isNotBlank(s)).map(s -> {
+                    final String[] pair = s.split("=");
+                    if (pair.length == 1) {
+                        return new Pair<>(StringUtil.EMPTY, pair[0].trim());
+                    } else if (pair.length == 2) {
+                        return new Pair<>(pair[1].trim(), pair[0].trim());
+                    }
+                    return null;
+                }).filter(o -> o != null).collect(Collectors.toMap(Pair::getFirst, d -> d.getSecond()));
+            }
+            propMap.put(DEFAULT_LABEL_VALUES, map);
+        }
+        return map
+                .entrySet()
+                .stream()
+                .map(e -> {
+                    final String key = e.getKey();
+                    if (StringUtil.isEmpty(key)) {
+                        return e.getValue();
+                    }
+                    if (userBean.map(
+                            user -> StreamUtil.of(user.getRoles()).anyMatch(s -> key.equals(ROLE_VALUE_PREFIX + s))
+                                    || StreamUtil.of(user.getGroups()).anyMatch(s -> key.equals(GROUP_VALUE_PREFIX + s))).orElse(false)) {
+                        return e.getValue();
+                    }
+                    return null;
+                }).filter(s -> StringUtil.isNotBlank(s)).toArray(n -> new String[n]);
+    }
+
+    public default void setDefaultLabelValue(final String value) {
+        setSystemProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, value);
+        propMap.remove(DEFAULT_LABEL_VALUES);
+    }
+
+    public default String getDefaultLabelValue() {
+        return getSystemProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, StringUtil.EMPTY);
+    }
+
     public default void setLoginRequired(final boolean value) {
         setSystemPropertyAsBoolean(Constants.LOGIN_REQUIRED_PROPERTY, value);
     }

+ 2 - 0
src/main/resources/fess_label.properties

@@ -189,6 +189,7 @@ labels.search_title=Fess
 labels.search_popular_word_word=Popular Words: 
 labels.search_result_select_sort=-- Sort --
 labels.search_result_select_num=-- Results per page --
+labels.search_result_sort_score_desc=Score
 labels.search_result_sort_created_asc=Date (ascending)
 labels.search_result_sort_created_desc=Date (descending)
 labels.search_result_sort_content_length_asc=Size (ascending)
@@ -315,6 +316,7 @@ labels.user_info_enabled=User Logging
 labels.user_favorite_enabled=Favorite Logging
 labels.web_api_json_enabled=JSON Response
 labels.default_label_value=Default Label Value
+labels.default_sort_value=Default Sort Value
 labels.append_query_param_enabled=Append Params to URL
 labels.login_required=Login Required
 labels.ignore_failure_type=Excluded Failure Type

+ 2 - 0
src/main/resources/fess_label_en.properties

@@ -189,6 +189,7 @@ labels.search_title=Fess
 labels.search_popular_word_word=Popular Words: 
 labels.search_result_select_sort=-- Sort --
 labels.search_result_select_num=-- Results per page --
+labels.search_result_sort_score_desc=Score
 labels.search_result_sort_created_asc=Date (ascending)
 labels.search_result_sort_created_desc=Date (descending)
 labels.search_result_sort_content_length_asc=Size (ascending)
@@ -315,6 +316,7 @@ labels.user_info_enabled=User Logging
 labels.user_favorite_enabled=Favorite Logging
 labels.web_api_json_enabled=JSON Response
 labels.default_label_value=Default Label Value
+labels.default_sort_value=Default Sort Value
 labels.append_query_param_enabled=Append Params to URL
 labels.login_required=Login Required
 labels.ignore_failure_type=Excluded Failure Type

+ 2 - 0
src/main/resources/fess_label_ja.properties

@@ -184,6 +184,7 @@ labels.search_title = Fess
 labels.search_popular_word_word = \u4eba\u6c17\u30ef\u30fc\u30c9: 
 labels.search_result_select_sort = -  \u30bd\u30fc\u30c8  -
 labels.search_result_select_num = - \u8868\u793a\u4ef6\u6570 -
+labels.search_result_sort_score_desc=\u30b9\u30b3\u30a2\u9806
 labels.search_result_sort_created_asc = \u65e5\u4ed8 (\u6607\u9806) 
 labels.search_result_sort_created_desc = \u65e5\u4ed8 (\u964d\u9806) 
 labels.search_result_sort_content_length_asc = \u30b5\u30a4\u30ba (\u6607\u9806) 
@@ -310,6 +311,7 @@ labels.user_info_enabled = \u30e6\u30fc\u30b6\u30ed\u30b0
 labels.user_favorite_enabled = \u304a\u6c17\u306b\u5165\u308a\u30ed\u30b0
 labels.web_api_json_enabled = JSON\u30ec\u30b9\u30dd\u30f3\u30b9
 labels.default_label_value = \u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30e9\u30d9\u30eb\u5024
+labels.default_sort_value = \u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30bd\u30fc\u30c8\u5024
 labels.append_query_param_enabled = \u691c\u7d22\u30d1\u30e9\u30e1\u30fc\u30bf\u306e\u8ffd\u52a0
 labels.login_required = \u30ed\u30b0\u30a4\u30f3\u304c\u5fc5\u8981
 labels.ignore_failure_type = \u9664\u5916\u3059\u308b\u30a8\u30e9\u30fc\u306e\u7a2e\u985e

+ 9 - 0
src/main/webapp/WEB-INF/view/admin/general/admin_general.jsp

@@ -66,6 +66,15 @@
 												styleClass="form-control" />
 										</div>
 									</div>
+									<div class="form-group">
+										<label for="defaultSortValue" class="col-sm-3 control-label"><la:message
+												key="labels.default_sort_value" /></label>
+										<div class="col-sm-9">
+											<la:errors property="defaultSortValue" />
+											<la:textarea property="defaultSortValue"
+												styleClass="form-control" />
+										</div>
+									</div>
 									<div class="form-group">
 										<label for="popularWord" class="col-sm-3 control-label"><la:message
 												key="labels.popular_word_word_enabled" /></label>

+ 3 - 0
src/main/webapp/WEB-INF/view/header.jsp

@@ -76,6 +76,9 @@ ${fe:facetForm()}${fe:geoForm()}
 						<option value="">
 							<la:message key="labels.search_result_select_sort" />
 						</option>
+						<la:option value="score.desc">
+							<la:message key="labels.search_result_sort_score_desc" />
+						</la:option>
 						<la:option value="created.asc">
 							<la:message key="labels.search_result_sort_created_asc" />
 						</la:option>

+ 3 - 0
src/main/webapp/WEB-INF/view/index.jsp

@@ -137,6 +137,9 @@
 											<option value="">
 												<la:message key="labels.search_result_select_sort" />
 											</option>
+											<la:option value="score.desc">
+												<la:message key="labels.search_result_sort_score_desc" />
+											</la:option>
 											<la:option value="created.asc">
 												<la:message key="labels.search_result_sort_created_asc" />
 											</la:option>

+ 2 - 0
src/main/webapp/WEB-INF/view/search.jsp

@@ -28,6 +28,8 @@
 						href="#searchOptions" class="label label-primary"
 						data-toggle="control-options"> <c:if test="${empty sort}">
 								<la:message key="labels.searchoptions_score" />
+							</c:if> <c:if test="${sort=='score.desc'}">
+								<la:message key="labels.searchoptions_score" />
 							</c:if> <c:if test="${sort=='created.asc'}">
 								<la:message key="labels.search_result_sort_created_asc" />
 							</c:if> <c:if test="${sort=='created.desc'}">