소스 검색

fix #1221 Admin searchlist API update

Shinsuke Sugaya 8 년 전
부모
커밋
eed9a25300

+ 55 - 125
src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java

@@ -235,13 +235,12 @@ public class AdminSearchlistAction extends FessAdminAction {
     @Execute
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
-        final String docId = form.docId;
         getDoc(form).ifPresent(entity -> {
             form.doc = fessConfig.convertToEditableDoc(entity);
             form.id = (String) entity.remove(fessConfig.getIndexFieldId());
             form.version = (Long) entity.remove(fessConfig.getIndexFieldVersion());
         }).orElse(() -> {
-            throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, docId), () -> asListHtml());
+            throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), () -> asListHtml());
         });
         saveToken();
         return asEditHtml();
@@ -251,7 +250,7 @@ public class AdminSearchlistAction extends FessAdminAction {
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
-        validateCreateFields(form, v -> throwValidationError(v, () -> asEditHtml()));
+        validateFields(form, v -> throwValidationError(v, () -> asEditHtml()));
         verifyToken(() -> asEditHtml());
         getDoc(form).ifPresent(
                 entity -> {
@@ -280,31 +279,26 @@ public class AdminSearchlistAction extends FessAdminAction {
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
-        validateUpdateFields(form, v -> throwValidationError(v, () -> asEditHtml()));
-        logger.debug("DEBUG:::role" + form.doc.get("role"));
+        validateFields(form, v -> throwValidationError(v, () -> asEditHtml()));
         verifyToken(() -> asEditHtml());
         getDoc(form).ifPresent(
                 entity -> {
+                    final String index = fessConfig.getIndexDocumentUpdateIndex();
+                    final String type = fessConfig.getIndexDocumentType();
                     try {
                         entity.putAll(fessConfig.convertToStorableDoc(form.doc));
 
                         final String newId = ComponentUtil.getCrawlingInfoHelper().generateId(entity);
-                        String oldId = null;
-                        if (newId.equals(form.id)) {
-                            entity.put(fessConfig.getIndexFieldId(), form.id);
-                            entity.put(fessConfig.getIndexFieldVersion(), form.version);
-                        } else {
-                            oldId = form.id;
+                        final String oldId = (String) entity.get(fessConfig.getIndexFieldId());
+                        if (!newId.equals(oldId)) {
                             entity.put(fessConfig.getIndexFieldId(), newId);
-                            entity.remove(fessConfig.getIndexFieldVersion());
+                            final Long version = (Long) entity.remove(fessConfig.getIndexFieldVersion());
+                            if (version != null && oldId != null) {
+                                fessEsClient.delete(index, type, oldId, version);
+                            }
                         }
 
-                        final String index = fessConfig.getIndexDocumentUpdateIndex();
-                        final String type = fessConfig.getIndexDocumentType();
                         fessEsClient.store(index, type, entity);
-                        if (oldId != null) {
-                            fessEsClient.delete(index, type, oldId, form.version);
-                        }
                         saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
                     } catch (final Exception e) {
                         logger.error("Failed to update " + entity, e);
@@ -312,7 +306,7 @@ public class AdminSearchlistAction extends FessAdminAction {
                                 () -> asEditHtml());
                     }
                 }).orElse(() -> {
-            throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.docId), () -> asEditHtml());
+            throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), () -> asEditHtml());
         });
         return redirectWith(getClass(), moreUrl("search").params("q", URLUtil.encode(form.q, Constants.UTF_8)));
     }
@@ -320,107 +314,41 @@ public class AdminSearchlistAction extends FessAdminAction {
     // ===================================================================================
     //                                                                       Validation
     //                                                                           =========
-    public static void validateCreateFields(final CreateForm form, final Consumer<VaMessenger<FessMessages>> throwError) {
-        final FessConfig fessConfig = ComponentUtil.getFessConfig();
-
-        if (!fessConfig.validateIndexRequiredFields(form.doc)) {
-            final List<String> invalidRequiredFields = fessConfig.invalidIndexRequiredFields(form.doc);
-            final String invalids = String.join(", doc.", invalidRequiredFields);
-
-            throwError.accept(messages -> {
-                messages.addErrorsCrudFailedToCreateCrudTable("doc.", "Required: {doc." + invalids + "}");
-            });
-        }
-
-        if (!fessConfig.validateIndexArrayFields(form.doc)) {
-            final List<String> invalidArrayFields = fessConfig.invalidIndexArrayFields(form.doc);
-            final String invalids = String.join(", doc.", invalidArrayFields);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudFailedToCreateCrudTable("doc.", "Must be Array: {doc." + invalids + "}");
-            });
-        }
-        if (!fessConfig.validateIndexDateFields(form.doc)) {
-            final List<String> invalidDateFields = fessConfig.invalidIndexDateFields(form.doc);
-            final String invalids = String.join(", doc.", invalidDateFields);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudFailedToCreateCrudTable("doc.", "Must be Date: {doc." + invalids + "}");
-            });
-        }
-        if (!fessConfig.validateIndexIntegerFields(form.doc)) {
-            final List<String> invalidIntegerFields = fessConfig.invalidIndexIntegerFields(form.doc);
-            final String invalids = String.join(", doc.", invalidIntegerFields);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudFailedToCreateCrudTable("doc.", "Must be Integer: {doc." + invalids + "}");
-            });
-        }
-        if (!fessConfig.validateIndexLongFields(form.doc)) {
-            final List<String> invalidLongFields = fessConfig.invalidIndexLongFields(form.doc);
-            final String invalids = String.join(", doc.", invalidLongFields);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudFailedToCreateCrudTable("doc.", "Must be Long: {doc." + invalids + "}");
-            });
-        }
-        if (!fessConfig.validateIndexFloatFields(form.doc)) {
-            final List<String> invalidFloatFields = fessConfig.invalidIndexFloatFields(form.doc);
-            final String invalids = String.join(", doc.", invalidFloatFields);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudFailedToCreateCrudTable("doc.", "Must be Float: {doc." + invalids + "}");
-            });
-        }
-        if (!fessConfig.validateIndexDoubleFields(form.doc)) {
-            final List<String> invalidDoubleFields = fessConfig.invalidIndexDoubleFields(form.doc);
-            final String invalids = String.join(", doc.", invalidDoubleFields);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudFailedToCreateCrudTable("doc.", "Must be Double: {doc." + invalids + "}");
-            });
-        }
-    }
-
-    public static void validateUpdateFields(final EditForm form, final Consumer<VaMessenger<FessMessages>> throwError) {
+    public static void validateFields(final CreateForm form, final Consumer<VaMessenger<FessMessages>> throwError) {
         final FessConfig fessConfig = ComponentUtil.getFessConfig();
 
-        if (!fessConfig.validateIndexRequiredFields(form.doc)) {
-            final List<String> invalidRequiredFields = fessConfig.invalidIndexRequiredFields(form.doc);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudCouldNotFindCrudTable("doc." + invalidRequiredFields.get(0), form.docId);
-            });
-        }
+        try {
+            if (!fessConfig.validateIndexRequiredFields(form.doc)) {
+                throwError.accept(messages -> fessConfig.invalidIndexRequiredFields(form.doc).stream().map(s -> "doc." + s)
+                        .forEach(s -> messages.addErrorsPropertyRequired(s, s)));
+            }
 
-        if (!fessConfig.validateIndexArrayFields(form.doc)) {
-            final List<String> invalidArrayFields = fessConfig.invalidIndexArrayFields(form.doc);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudCouldNotFindCrudTable("doc." + invalidArrayFields.get(0), form.docId);
-            });
-        }
-        if (!fessConfig.validateIndexDateFields(form.doc)) {
-            final List<String> invalidDateFields = fessConfig.invalidIndexDateFields(form.doc);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudCouldNotFindCrudTable("doc." + invalidDateFields.get(0), form.docId);
-            });
-        }
-        if (!fessConfig.validateIndexIntegerFields(form.doc)) {
-            final List<String> invalidIntegerFields = fessConfig.invalidIndexIntegerFields(form.doc);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudCouldNotFindCrudTable("doc." + invalidIntegerFields.get(0), form.docId);
-            });
-        }
-        if (!fessConfig.validateIndexLongFields(form.doc)) {
-            final List<String> invalidLongFields = fessConfig.invalidIndexLongFields(form.doc);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudCouldNotFindCrudTable("doc." + invalidLongFields.get(0), form.docId);
-            });
-        }
-        if (!fessConfig.validateIndexFloatFields(form.doc)) {
-            final List<String> invalidFloatFields = fessConfig.invalidIndexFloatFields(form.doc);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudCouldNotFindCrudTable("doc." + invalidFloatFields.get(0), form.docId);
-            });
-        }
-        if (!fessConfig.validateIndexDoubleFields(form.doc)) {
-            final List<String> invalidDoubleFields = fessConfig.invalidIndexDoubleFields(form.doc);
-            throwError.accept(messages -> {
-                messages.addErrorsCrudCouldNotFindCrudTable("doc." + invalidDoubleFields.get(0), form.docId);
-            });
+            if (!fessConfig.validateIndexArrayFields(form.doc)) {
+                throwError.accept(messages -> fessConfig.invalidIndexArrayFields(form.doc).stream().map(s -> "doc." + s)
+                        .forEach(s -> messages.addErrorsPropertyRequired(s, s)));
+            }
+            if (!fessConfig.validateIndexDateFields(form.doc)) {
+                throwError.accept(messages -> fessConfig.invalidIndexDateFields(form.doc).stream().map(s -> "doc." + s)
+                        .forEach(s -> messages.addErrorsPropertyTypeDate(s, s)));
+            }
+            if (!fessConfig.validateIndexIntegerFields(form.doc)) {
+                throwError.accept(messages -> fessConfig.invalidIndexIntegerFields(form.doc).stream().map(s -> "doc." + s)
+                        .forEach(s -> messages.addErrorsPropertyTypeInteger(s, s)));
+            }
+            if (!fessConfig.validateIndexLongFields(form.doc)) {
+                throwError.accept(messages -> fessConfig.invalidIndexLongFields(form.doc).stream().map(s -> "doc." + s)
+                        .forEach(s -> messages.addErrorsPropertyTypeLong(s, s)));
+            }
+            if (!fessConfig.validateIndexFloatFields(form.doc)) {
+                throwError.accept(messages -> fessConfig.invalidIndexFloatFields(form.doc).stream().map(s -> "doc." + s)
+                        .forEach(s -> messages.addErrorsPropertyTypeFloat(s, s)));
+            }
+            if (!fessConfig.validateIndexDoubleFields(form.doc)) {
+                throwError.accept(messages -> fessConfig.invalidIndexDoubleFields(form.doc).stream().map(s -> "doc." + s)
+                        .forEach(s -> messages.addErrorsPropertyTypeDouble(s, s)));
+            }
+        } catch (final Exception e) {
+            throwError.accept(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, e.getMessage()));
         }
     }
 
@@ -445,15 +373,17 @@ public class AdminSearchlistAction extends FessAdminAction {
             entity.put(fessConfig.getIndexFieldDocId(), systemHelper.generateDocId(entity));
             return OptionalEntity.of(entity);
         case CrudMode.EDIT:
-            if (form instanceof EditForm) {
-                final String docId = ((EditForm) form).docId;
-                if (StringUtil.isNotBlank(docId)) {
-                    return fessEsClient.getDocument(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(),
-                            builder -> {
-                                builder.setQuery(QueryBuilders.termQuery(fessConfig.getIndexFieldDocId(), docId));
-                                return true;
-                            });
-                }
+            final String docId;
+            if (form.doc != null) {
+                docId = (String) form.doc.get(fessConfig.getIndexFieldDocId());
+            } else {
+                docId = null;
+            }
+            if (StringUtil.isNotBlank(docId)) {
+                return fessEsClient.getDocument(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(), builder -> {
+                    builder.setQuery(QueryBuilders.termQuery(fessConfig.getIndexFieldDocId(), docId));
+                    return true;
+                });
             }
             break;
         default:

+ 0 - 2
src/main/java/org/codelibs/fess/app/web/admin/searchlist/CreateForm.java

@@ -17,7 +17,6 @@ package org.codelibs.fess.app.web.admin.searchlist;
 
 import java.util.Map;
 
-import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
 import org.lastaflute.web.validation.theme.conversion.ValidateTypeFailure;
 
 /**
@@ -28,7 +27,6 @@ public class CreateForm {
     @ValidateTypeFailure
     public Integer crudMode;
 
-    @Required
     public Map<String, Object> doc;
 
     public String q;

+ 0 - 7
src/main/java/org/codelibs/fess/app/web/admin/searchlist/EditForm.java

@@ -15,9 +15,6 @@
  */
 package org.codelibs.fess.app.web.admin.searchlist;
 
-import javax.validation.constraints.Size;
-
-import org.lastaflute.web.validation.Required;
 import org.lastaflute.web.validation.theme.conversion.ValidateTypeFailure;
 
 /**
@@ -27,10 +24,6 @@ public class EditForm extends CreateForm {
 
     public String id;
 
-    @Required
-    @Size(max = 1000)
-    public String docId;
-
     @ValidateTypeFailure
     public Long version;
 

+ 14 - 21
src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/ApiAdminSearchlistAction.java

@@ -16,8 +16,7 @@
 package org.codelibs.fess.app.web.api.admin.searchlist;
 
 import static org.codelibs.fess.app.web.admin.searchlist.AdminSearchlistAction.getDoc;
-import static org.codelibs.fess.app.web.admin.searchlist.AdminSearchlistAction.validateCreateFields;
-import static org.codelibs.fess.app.web.admin.searchlist.AdminSearchlistAction.validateUpdateFields;
+import static org.codelibs.fess.app.web.admin.searchlist.AdminSearchlistAction.validateFields;
 
 import java.util.Map;
 
@@ -102,7 +101,7 @@ public class ApiAdminSearchlistAction extends FessApiAdminAction {
         return null; // ignore
     }
 
-    // GET /api/admin/searchlist/doc/{id}
+    // GET /api/admin/searchlist/doc/{doc_id}
     @Execute
     public JsonResponse<ApiResult> get$doc(final String id) {
         return asJson(new ApiDocResponse()
@@ -122,7 +121,7 @@ public class ApiAdminSearchlistAction extends FessApiAdminAction {
         if (body.doc == null) {
             throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, "doc is required"));
         }
-        validateCreateFields(body, v -> throwValidationErrorApi(v));
+        validateFields(body, v -> throwValidationErrorApi(v));
         body.crudMode = CrudMode.CREATE;
         final Map<String, Object> doc = getDoc(body).map(entity -> {
             try {
@@ -152,34 +151,28 @@ public class ApiAdminSearchlistAction extends FessApiAdminAction {
     @Execute
     public JsonResponse<ApiResult> post$doc(final EditBody body) {
         validateApi(body, messages -> {});
-
         if (body.doc == null) {
             throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, "doc is required"));
         }
-
-        validateUpdateFields(body, v -> throwValidationErrorApi(v));
+        validateFields(body, v -> throwValidationErrorApi(v));
         body.crudMode = CrudMode.EDIT;
         final Map<String, Object> doc = getDoc(body).map(entity -> {
+            final String index = fessConfig.getIndexDocumentUpdateIndex();
+            final String type = fessConfig.getIndexDocumentType();
             try {
                 entity.putAll(fessConfig.convertToStorableDoc(body.doc));
 
                 final String newId = ComponentUtil.getCrawlingInfoHelper().generateId(entity);
-                String oldId = null;
-                if (newId.equals(body.id)) {
-                    entity.put(fessConfig.getIndexFieldId(), body.id);
-                    entity.put(fessConfig.getIndexFieldVersion(), body.version);
-                } else {
-                    oldId = body.id;
+                final String oldId = (String) entity.get(fessConfig.getIndexFieldId());
+                if (!newId.equals(oldId)) {
                     entity.put(fessConfig.getIndexFieldId(), newId);
-                    entity.remove(fessConfig.getIndexFieldVersion());
+                    final Number version = (Number) entity.remove(fessConfig.getIndexFieldVersion());
+                    if (version != null && oldId != null) {
+                        fessEsClient.delete(index, type, oldId, version.longValue());
+                    }
                 }
 
-                final String index = fessConfig.getIndexDocumentUpdateIndex();
-                final String type = fessConfig.getIndexDocumentType();
                 fessEsClient.store(index, type, entity);
-                if (oldId != null) {
-                    fessEsClient.delete(index, type, oldId, body.version);
-                }
                 saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
             } catch (final Exception e) {
                 logger.error("Failed to update " + entity, e);
@@ -187,14 +180,14 @@ public class ApiAdminSearchlistAction extends FessApiAdminAction {
             }
             return entity;
         }).orElseGet(() -> {
-            throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, body.id));
+            throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, body.doc.toString()));
             return null;
         });
         return asJson(new ApiUpdateResponse().id(doc.get(fessConfig.getIndexFieldDocId()).toString()).created(false).status(Status.OK)
                 .result());
     }
 
-    // DELETE /api/admin/searchlist/doc/{id}
+    // DELETE /api/admin/searchlist/doc/{doc_id}
     @Execute
     public JsonResponse<ApiResult> delete$doc(final String id) {
         try {

+ 0 - 1
src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/EditBody.java

@@ -18,5 +18,4 @@ package org.codelibs.fess.app.web.api.admin.searchlist;
 import org.codelibs.fess.app.web.admin.searchlist.EditForm;
 
 public class EditBody extends EditForm {
-
 }

+ 3 - 2
src/main/java/org/codelibs/fess/es/client/FessEsClient.java

@@ -1049,10 +1049,11 @@ public class FessEsClient implements Client {
         @SuppressWarnings("unchecked")
         final Map<String, Object> source = obj instanceof Map ? (Map<String, Object>) obj : BeanUtil.copyBeanToNewMap(obj);
         final String id = (String) source.remove(fessConfig.getIndexFieldId());
-        final Long version = (Long) source.remove(fessConfig.getIndexFieldVersion());
+        final Number version = (Number) source.remove(fessConfig.getIndexFieldVersion());
         IndexResponse response;
         try {
             if (id == null) {
+                // TODO throw Exception in next release
                 // create
                 response =
                         client.prepareIndex(index, type).setSource(new DocMap(source)).setRefreshPolicy(RefreshPolicy.IMMEDIATE)
@@ -1063,7 +1064,7 @@ public class FessEsClient implements Client {
                         client.prepareIndex(index, type, id).setSource(new DocMap(source)).setRefreshPolicy(RefreshPolicy.IMMEDIATE)
                                 .setOpType(OpType.INDEX);
                 if (version != null && version.longValue() > 0) {
-                    builder.setVersion(version);
+                    builder.setVersion(version.longValue());
                 }
                 response = builder.execute().actionGet(fessConfig.getIndexIndexTimeout());
             }

+ 108 - 0
src/main/java/org/codelibs/fess/mylasta/action/FessMessages.java

@@ -362,6 +362,24 @@ public class FessMessages extends FessLabels {
     /** The key of the message: Could not find the data({0}). */
     public static final String ERRORS_crud_could_not_find_crud_table = "{errors.crud_could_not_find_crud_table}";
 
+    /** The key of the message: {0} is required. */
+    public static final String ERRORS_property_required = "{errors.property_required}";
+
+    /** The key of the message: {0} should be numeric. */
+    public static final String ERRORS_property_type_integer = "{errors.property_type_integer}";
+
+    /** The key of the message: {0} should be numeric. */
+    public static final String ERRORS_property_type_long = "{errors.property_type_long}";
+
+    /** The key of the message: {0} should be numeric. */
+    public static final String ERRORS_property_type_float = "{errors.property_type_float}";
+
+    /** The key of the message: {0} should be numeric. */
+    public static final String ERRORS_property_type_double = "{errors.property_type_double}";
+
+    /** The key of the message: {0} should be date. */
+    public static final String ERRORS_property_type_date = "{errors.property_type_date}";
+
     /** The key of the message: Updated parameters. */
     public static final String SUCCESS_update_crawler_params = "{success.update_crawler_params}";
 
@@ -2088,6 +2106,96 @@ public class FessMessages extends FessLabels {
         return this;
     }
 
+    /**
+     * Add the created action message for the key 'errors.property_required' with parameters.
+     * <pre>
+     * message: {0} is required.
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @param arg0 The parameter arg0 for message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addErrorsPropertyRequired(String property, String arg0) {
+        assertPropertyNotNull(property);
+        add(property, new UserMessage(ERRORS_property_required, arg0));
+        return this;
+    }
+
+    /**
+     * Add the created action message for the key 'errors.property_type_integer' with parameters.
+     * <pre>
+     * message: {0} should be numeric.
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @param arg0 The parameter arg0 for message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addErrorsPropertyTypeInteger(String property, String arg0) {
+        assertPropertyNotNull(property);
+        add(property, new UserMessage(ERRORS_property_type_integer, arg0));
+        return this;
+    }
+
+    /**
+     * Add the created action message for the key 'errors.property_type_long' with parameters.
+     * <pre>
+     * message: {0} should be numeric.
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @param arg0 The parameter arg0 for message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addErrorsPropertyTypeLong(String property, String arg0) {
+        assertPropertyNotNull(property);
+        add(property, new UserMessage(ERRORS_property_type_long, arg0));
+        return this;
+    }
+
+    /**
+     * Add the created action message for the key 'errors.property_type_float' with parameters.
+     * <pre>
+     * message: {0} should be numeric.
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @param arg0 The parameter arg0 for message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addErrorsPropertyTypeFloat(String property, String arg0) {
+        assertPropertyNotNull(property);
+        add(property, new UserMessage(ERRORS_property_type_float, arg0));
+        return this;
+    }
+
+    /**
+     * Add the created action message for the key 'errors.property_type_double' with parameters.
+     * <pre>
+     * message: {0} should be numeric.
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @param arg0 The parameter arg0 for message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addErrorsPropertyTypeDouble(String property, String arg0) {
+        assertPropertyNotNull(property);
+        add(property, new UserMessage(ERRORS_property_type_double, arg0));
+        return this;
+    }
+
+    /**
+     * Add the created action message for the key 'errors.property_type_date' with parameters.
+     * <pre>
+     * message: {0} should be date.
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @param arg0 The parameter arg0 for message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addErrorsPropertyTypeDate(String property, String arg0) {
+        assertPropertyNotNull(property);
+        add(property, new UserMessage(ERRORS_property_type_date, arg0));
+        return this;
+    }
+
     /**
      * Add the created action message for the key 'success.update_crawler_params' with parameters.
      * <pre>

+ 7 - 0
src/main/resources/fess_message.properties

@@ -145,6 +145,13 @@ errors.crud_failed_to_update_crud_table=Failed to update the data. ({0})
 errors.crud_failed_to_delete_crud_table=Failed to delete the data. ({0})
 errors.crud_could_not_find_crud_table=Could not find the data({0}).
 
+errors.property_required={0} is required.
+errors.property_type_integer={0} should be numeric.
+errors.property_type_long={0} should be numeric.
+errors.property_type_float={0} should be numeric.
+errors.property_type_double={0} should be numeric.
+errors.property_type_date={0} should be date.
+
 success.update_crawler_params=Updated parameters.
 success.delete_doc_from_index=Started a process to delete the document from index.
 success.crawling_info_delete_all=Deleted session data.

+ 7 - 0
src/main/resources/fess_message_en.properties

@@ -141,6 +141,13 @@ errors.crud_failed_to_update_crud_table=Failed to update the data. ({0})
 errors.crud_failed_to_delete_crud_table=Failed to delete the data. ({0})
 errors.crud_could_not_find_crud_table=Could not find the data({0}).
 
+errors.property_required={0} is required.
+errors.property_type_integer={0} should be numeric.
+errors.property_type_long={0} should be numeric.
+errors.property_type_float={0} should be numeric.
+errors.property_type_double={0} should be numeric.
+errors.property_type_date={0} should be date.
+
 success.update_crawler_params=Updated parameters.
 success.delete_doc_from_index=Started a process to delete the document from index.
 success.crawling_info_delete_all=Deleted session data.

+ 7 - 0
src/main/resources/fess_message_ja.properties

@@ -134,6 +134,13 @@ errors.failed_to_read_request_file=\u30ea\u30af\u30a8\u30b9\u30c8\u30d5\u30a1\u3
 errors.invalid_header_for_request_file=\u30d8\u30c3\u30c0\u30fc\u884c\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093: {0}
 errors.could_not_delete_logged_in_user=\u30ed\u30b0\u30a4\u30f3\u3057\u3066\u3044\u308b\u30e6\u30fc\u30b6\u30fc\u306f\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002
 
+errors.property_required={0}\u306f\u5fc5\u9808\u3067\u3059\u3002
+errors.property_type_integer={0}\u306f\u6570\u5024\u3067\u3059\u3002
+errors.property_type_long={0}\u306f\u6570\u5024\u3067\u3059\u3002
+errors.property_type_float={0}\u306f\u6570\u5024\u3067\u3059\u3002
+errors.property_type_double={0}\u306f\u6570\u5024\u3067\u3059\u3002
+errors.property_type_date={0}\u306f\u65e5\u4ed8\u3067\u3059\u3002
+
 success.update_crawler_params = \u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002
 success.delete_doc_from_index = \u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u304b\u3089\u6587\u66f8\u3092\u524a\u9664\u3059\u308b\u30d7\u30ed\u30bb\u30b9\u3092\u958b\u59cb\u3057\u307e\u3057\u305f\u3002
 success.crawling_info_delete_all = \u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u3092\u524a\u9664\u3057\u307e\u3057\u305f\u3002

+ 1 - 1
src/main/webapp/WEB-INF/view/admin/searchlist/admin_searchlist.jsp

@@ -93,7 +93,7 @@
 														</div>
 														<div class="body col-sm-2 text-right">
 															<la:message key="labels.doc_score" />${f:h(doc.score)}<br>
-															<la:link href="/admin/searchlist/edit?crudMode=2&amp;docId=${f:u(doc.doc_id)}&amp;q=${f:u(q)}"
+															<la:link href="/admin/searchlist/edit?crudMode=2&amp;doc.doc_id=${f:u(doc.doc_id)}&amp;q=${f:u(q)}"
 																styleClass="btn btn-xs btn-warning">
 																<i class="fa fa-pencil"></i>
 																<la:message key="labels.crud_button_update" />

+ 8 - 20
src/main/webapp/WEB-INF/view/admin/searchlist/admin_searchlist_edit.jsp

@@ -28,7 +28,6 @@
 					<la:hidden property="crudMode" />
 					<la:hidden property="q" />
 					<c:if test="${crudMode==2}">
-						<la:hidden property="docId" />
 						<la:hidden property="id" />
 						<la:hidden property="version" />
 					</c:if>
@@ -78,16 +77,19 @@
 										</la:info>
 										<la:errors property="_global" />
 									</div>
+									<c:if test="${crudMode==2}">
+									<div class="form-group">
+										<label for="doc_id" class="col-sm-3 control-label">_id</label>
+										<div class="col-sm-9">${f:h(id)}</div>
+									</div>
 									<div class="form-group">
 										<label for="doc_id" class="col-sm-3 control-label">doc_id</label>
 										<div class="col-sm-9">
-											<la:errors property="doc.doc_id" />
-											<la:text property="doc.doc_id" styleClass="form-control"
-												required="required" data-validation="custom"
-												data-validation-regexp="^([a-z0-9]+)$"
-												data-validation-help="[a-z] or [0-9]" />
+											${f:h(doc.doc_id)}
+											<la:hidden property="doc.doc_id"/>
 										</div>
 									</div>
+									</c:if>
 									<div class="form-group">
 										<label for="url" class="col-sm-3 control-label">url</label>
 										<div class="col-sm-9">
@@ -130,13 +132,6 @@
 											<la:textarea property="doc.label" styleClass="form-control" />
 										</div>
 									</div>
-									<div class="form-group">
-										<label for="version" class="col-sm-3 control-label">version</label>
-										<div class="col-sm-9">
-											<la:errors property="doc.version" />
-											<la:text property="doc.version" styleClass="form-control" />
-										</div>
-									</div>
 									<div class="form-group">
 										<label for="lang" class="col-sm-3 control-label">lang</label>
 										<div class="col-sm-9">
@@ -221,13 +216,6 @@
 											<la:text property="doc.config_id" styleClass="form-control" />
 										</div>
 									</div>
-									<div class="form-group">
-										<label for="_id" class="col-sm-3 control-label">_id</label>
-										<div class="col-sm-9">
-											<la:errors property="doc._id" />
-											<la:text property="doc._id" styleClass="form-control" />
-										</div>
-									</div>
 									<div class="form-group">
 										<label for="parent_id" class="col-sm-3 control-label">parent_id</label>
 										<div class="col-sm-9">

+ 1 - 1
src/test/java/org/codelibs/fess/it/CrudTestBase.java

@@ -83,7 +83,7 @@ public abstract class CrudTestBase extends ITBase {
         final Map<String, Object> searchBody = createSearchBody(SEARCH_ALL_NUM);
         int count = 0;
         List<String> idList = getIdList(searchBody);
-        while(idList.size() > 0 && count < NUM) {
+        while (idList.size() > 0 && count < NUM) {
             final String id = idList.get(0);
             checkDeleteMethod(getItemEndpointSuffix() + "/" + id.toString());
             refresh();