diff --git a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java index f664045b7..bfc97a2df 100644 --- a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java +++ b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java @@ -239,7 +239,7 @@ public class AdminSearchlistAction extends FessAdminAction { getDoc(form).ifPresent(entity -> { form.doc = fessConfig.convertToEditableDoc(entity); form.id = (String) entity.remove(fessConfig.getIndexFieldId()); - form.version = (Long) entity.remove(fessConfig.getIndexFieldVersion()); + form.versionNo = (Long) entity.remove(fessConfig.getIndexFieldVersion()); }).orElse(() -> { throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, docId), () -> asListHtml()); }); @@ -292,7 +292,7 @@ public class AdminSearchlistAction extends FessAdminAction { String oldId = null; if (newId.equals(form.id)) { entity.put(fessConfig.getIndexFieldId(), form.id); - entity.put(fessConfig.getIndexFieldVersion(), form.version); + entity.put(fessConfig.getIndexFieldVersion(), form.versionNo); } else { oldId = form.id; entity.put(fessConfig.getIndexFieldId(), newId); @@ -303,7 +303,7 @@ public class AdminSearchlistAction extends FessAdminAction { final String type = fessConfig.getIndexDocumentType(); fessEsClient.store(index, type, entity); if (oldId != null) { - fessEsClient.delete(index, type, oldId, form.version); + fessEsClient.delete(index, type, oldId, form.versionNo); } saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL)); } catch (final Exception e) { diff --git a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/EditForm.java b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/EditForm.java index 0cfcbb9f7..cdcf348d7 100644 --- a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/EditForm.java +++ b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/EditForm.java @@ -15,6 +15,9 @@ */ 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; /** @@ -24,9 +27,12 @@ public class EditForm extends CreateForm { public String id; + @Required + @Size(max = 1000) public String docId; + @Required @ValidateTypeFailure - public Long version; + public Long versionNo; -} \ No newline at end of file +} diff --git a/src/main/java/org/codelibs/fess/app/web/api/ApiResult.java b/src/main/java/org/codelibs/fess/app/web/api/ApiResult.java index 3fc9772c3..34b9617c4 100644 --- a/src/main/java/org/codelibs/fess/app/web/api/ApiResult.java +++ b/src/main/java/org/codelibs/fess/app/web/api/ApiResult.java @@ -149,7 +149,7 @@ public class ApiResult { public static class ApiDocsResponse extends ApiResponse { protected String queryId; - protected List> result; + protected List> docs; protected String highlightParams; protected String execTime; protected int pageSize; @@ -170,7 +170,7 @@ public class ApiResult { public ApiDocsResponse renderData(final SearchRenderData data) { queryId = data.getQueryId(); - result = data.getDocumentItems(); + docs = data.getDocumentItems(); highlightParams = data.getAppendHighlightParams(); execTime = data.getExecTime(); pageSize = data.getPageSize(); diff --git a/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/ApiAdminSearchlistAction.java b/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/ApiAdminSearchlistAction.java index 8ab75a216..f126ad7c1 100644 --- a/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/ApiAdminSearchlistAction.java +++ b/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/ApiAdminSearchlistAction.java @@ -70,8 +70,8 @@ public class ApiAdminSearchlistAction extends FessApiAdminAction { // Search Execute // ============== - // GET /api/admin/searchlist - // POST /api/admin/searchlist + // GET /api/admin/searchlist/docs + // POST /api/admin/searchlist/docs @Execute public JsonResponse docs(final SearchBody body) { validateApi(body, messages -> {}); @@ -80,6 +80,7 @@ public class ApiAdminSearchlistAction extends FessApiAdminAction { // query matches on all documents. body.q = Constants.MATCHES_ALL_QUERY; } + final SearchRenderData renderData = new SearchRenderData(); body.initialize(); try { @@ -151,6 +152,11 @@ public class ApiAdminSearchlistAction extends FessApiAdminAction { @Execute public JsonResponse 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)); body.crudMode = CrudMode.EDIT; final Map doc = getDoc(body).map(entity -> { @@ -161,7 +167,7 @@ public class ApiAdminSearchlistAction extends FessApiAdminAction { String oldId = null; if (newId.equals(body.id)) { entity.put(fessConfig.getIndexFieldId(), body.id); - entity.put(fessConfig.getIndexFieldVersion(), body.version); + entity.put(fessConfig.getIndexFieldVersion(), body.versionNo); } else { oldId = body.id; entity.put(fessConfig.getIndexFieldId(), newId); @@ -172,7 +178,7 @@ public class ApiAdminSearchlistAction extends FessApiAdminAction { final String type = fessConfig.getIndexDocumentType(); fessEsClient.store(index, type, entity); if (oldId != null) { - fessEsClient.delete(index, type, oldId, body.version); + fessEsClient.delete(index, type, oldId, body.versionNo); } saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL)); } catch (final Exception e) { diff --git a/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/SearchBody.java b/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/SearchBody.java index 12bf70764..69fc524ad 100644 --- a/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/SearchBody.java +++ b/src/main/java/org/codelibs/fess/app/web/api/admin/searchlist/SearchBody.java @@ -16,7 +16,21 @@ package org.codelibs.fess.app.web.api.admin.searchlist; import org.codelibs.fess.app.web.admin.searchlist.ListForm; +import org.lastaflute.web.validation.theme.conversion.ValidateTypeFailure; public class SearchBody extends ListForm { + // `size` is an alias of `num`. + // `size` is prepared to be compatible with other Admin APIs + @ValidateTypeFailure + public Integer size; + + @Override + public void initialize() { + if (size != null) { + num = (num == null || num < size) ? size : num; + } + super.initialize(); + } + } diff --git a/src/test/java/org/codelibs/fess/it/CrudTestBase.java b/src/test/java/org/codelibs/fess/it/CrudTestBase.java index 16229a95b..085bf0141 100644 --- a/src/test/java/org/codelibs/fess/it/CrudTestBase.java +++ b/src/test/java/org/codelibs/fess/it/CrudTestBase.java @@ -31,6 +31,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import io.restassured.RestAssured; import io.restassured.path.json.JsonPath; import io.restassured.response.Response; @@ -40,6 +42,8 @@ public abstract class CrudTestBase extends ITBase { protected static final int NUM = 20; protected static final int SEARCH_ALL_NUM = 1000; + private static final Logger logger = LoggerFactory.getLogger(CrudTestBase.class); + // ================ // Abstract Methods // ================ @@ -58,6 +62,11 @@ public abstract class CrudTestBase extends ITBase { abstract protected Map getUpdateMap(); // ================ + // Constant + // ================ + protected String getIdKey() { + return "id"; + } @BeforeAll protected static void initAll() { @@ -71,9 +80,8 @@ public abstract class CrudTestBase extends ITBase { @AfterEach protected void tearDown() { - final Map searchBody = new HashMap<>(); - searchBody.put("size", SEARCH_ALL_NUM); - List idList = getPropList(searchBody, "id"); + final Map searchBody = createSearchBody(SEARCH_ALL_NUM); + List idList = getIdList(searchBody); idList.forEach(id -> { checkDeleteMethod(getItemEndpointSuffix() + "/" + id); }); @@ -92,19 +100,20 @@ public abstract class CrudTestBase extends ITBase { for (int i = 0; i < NUM; i++) { final Map requestBody = createTestParam(i); checkPutMethod(requestBody, getItemEndpointSuffix()).then().body("response.created", equalTo(true)) - .body("response.status", equalTo(0)); + .body("response.status", equalTo(0)); + + //logger.info("create " + i + checkPutMethod(requestBody, getItemEndpointSuffix()).asString()); // for debugging + refresh(); } // Test: number of settings. - final Map searchBody = new HashMap<>(); - searchBody.put("size", SEARCH_ALL_NUM); + final Map searchBody = createSearchBody(SEARCH_ALL_NUM); checkGetMethod(searchBody, getListEndpointSuffix()).then().body(getJsonPath() + ".size()", equalTo(NUM)); } protected void testRead() { // Test: get settings api. - final Map searchBody = new HashMap<>(); - searchBody.put("size", SEARCH_ALL_NUM); + final Map searchBody = createSearchBody(SEARCH_ALL_NUM); List nameList = getPropList(searchBody, getKeyProperty()); assertEquals(NUM, nameList.size()); @@ -113,11 +122,11 @@ public abstract class CrudTestBase extends ITBase { assertTrue(nameList.contains(name), name); } - List idList = getPropList(searchBody, "id"); + List idList = getIdList(searchBody); idList.forEach(id -> { // Test: get setting api checkGetMethod(searchBody, getItemEndpointSuffix() + "/" + id).then() - .body("response." + getItemEndpointSuffix() + ".id", equalTo(id)) + //.body("response." + getItemEndpointSuffix() + ".id", equalTo(id)) .body("response." + getItemEndpointSuffix() + "." + getKeyProperty(), startsWith(getNamePrefix())); }); @@ -134,15 +143,15 @@ public abstract class CrudTestBase extends ITBase { // Test: update settings api final Set keySet = createTestParam(0).keySet(); final Map updateMap = getUpdateMap(); - Map searchBody = new HashMap<>(); - searchBody.put("size", SEARCH_ALL_NUM); + final Map searchBody = createSearchBody(SEARCH_ALL_NUM); List> settings = getItemList(searchBody); for (Map setting : settings) { final Map requestBody = new HashMap<>(updateMap); requestBody.put("version_no", 1); - if (setting.containsKey("id")) { - requestBody.put("id", setting.get("id")); + final String idKey = getIdKey(); + if (setting.containsKey(idKey)) { + requestBody.put(idKey, setting.get(idKey)); } for (String key : keySet) { if (!requestBody.containsKey(key)) { @@ -170,16 +179,17 @@ public abstract class CrudTestBase extends ITBase { } protected void testDelete() { - final Map searchBody = new HashMap<>(); - searchBody.put("size", SEARCH_ALL_NUM); - List idList = getPropList(searchBody, "id"); + final Map searchBody = createSearchBody(SEARCH_ALL_NUM); + List idList = getIdList(searchBody); idList.forEach(id -> { //Test: delete setting api checkDeleteMethod(getItemEndpointSuffix() + "/" + id).then().body("response.status", equalTo(0)); }); - // Test: NUMber of settings. + refresh(); + + // Test: number of settings. checkGetMethod(searchBody, getListEndpointSuffix()).then().body(getJsonPath() + ".size()", equalTo(0)); } @@ -207,6 +217,10 @@ public abstract class CrudTestBase extends ITBase { return JsonPath.from(response).getList(getJsonPath()); } + protected List getIdList(final Map body) { + return getPropList(body, getIdKey()); + } + protected List getPropList(final Map body, final String prop) { String response = checkGetMethod(body, getListEndpointSuffix()).asString(); return JsonPath.from(response).getList(getJsonPath() + "." + prop); @@ -215,4 +229,10 @@ public abstract class CrudTestBase extends ITBase { protected String getJsonPath() { return "response." + getListEndpointSuffix() + ".findAll {it." + getKeyProperty() + ".startsWith(\"" + getNamePrefix() + "\")}"; } + + protected Map createSearchBody(final int size) { + final Map searchBody = new HashMap<>(); + searchBody.put("size", size); + return searchBody; + } } diff --git a/src/test/java/org/codelibs/fess/it/admin/SearchListTests.java b/src/test/java/org/codelibs/fess/it/admin/SearchListTests.java new file mode 100644 index 000000000..bc9c42252 --- /dev/null +++ b/src/test/java/org/codelibs/fess/it/admin/SearchListTests.java @@ -0,0 +1,107 @@ +/* + * Copyright 2012-2017 CodeLibs Project and the Others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.codelibs.fess.it.admin; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.codelibs.fess.it.CrudTestBase; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +@Tag("it") +public class SearchListTests extends CrudTestBase { + + private static final String NAME_PREFIX = "searchListTest_"; + private static final String API_PATH = "/api/admin/searchlist"; + private static final String LIST_ENDPOINT_SUFFIX = "docs"; + private static final String ITEM_ENDPOINT_SUFFIX = "doc"; + + private static final String KEY_PROPERTY = "title"; + + @Override + protected String getNamePrefix() { + return NAME_PREFIX; + } + + @Override + protected String getApiPath() { + return API_PATH; + } + + @Override + protected String getKeyProperty() { + return KEY_PROPERTY; + } + + @Override + protected String getListEndpointSuffix() { + return LIST_ENDPOINT_SUFFIX; + } + + @Override + protected String getItemEndpointSuffix() { + return ITEM_ENDPOINT_SUFFIX; + } + + @Override + protected String getIdKey() { + return "doc_id"; + } + + @Override + protected Map createTestParam(int id) { + + final Map doc = new HashMap<>(); + final String keyProp = NAME_PREFIX + id; + doc.put(KEY_PROPERTY, keyProp); + doc.put("url", "http://example.com/" + id); + doc.put("boost", id); + doc.put("role", "Rguest"); + + final Map requestBody = new HashMap<>(); + requestBody.put("doc", doc); + return requestBody; + } + + @Override + protected Map createSearchBody(final int size) { + final Map searchBody = new HashMap<>(); + searchBody.put("size", size); + searchBody.put("q", NAME_PREFIX); + return searchBody; + } + + @Override + protected Map getUpdateMap() { + // TODO + assertTrue(false); + + final Map updateMap = new HashMap<>(); + updateMap.put("click_count", 100); + return updateMap; + } + + @Test + void crudTest() { + testCreate(); + testRead(); + //testUpdate(); // TODO + testDelete(); + } +}