#592 create new doc

This commit is contained in:
Shinsuke Sugaya 2016-07-28 15:57:46 +09:00
parent d6f8f3f772
commit a2cee1cd29
7 changed files with 385 additions and 30 deletions

View file

@ -15,6 +15,7 @@
*/
package org.codelibs.fess.app.web.admin.searchlist;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -22,7 +23,6 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.core.misc.Pair;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.service.SearchService;
import org.codelibs.fess.app.web.CrudMode;
@ -216,14 +216,14 @@ public class AdminSearchlistAction extends FessAdminAction {
}
@Execute
public HtmlResponse createnew() {
public HtmlResponse createnew(final CreateForm form) {
saveToken();
return asHtml(path_AdminSearchlist_AdminSearchlistEditJsp).useForm(CreateForm.class, op -> {
op.setup(form -> {
form.initialize();
form.crudMode = CrudMode.CREATE;
});
form.initialize();
form.crudMode = CrudMode.CREATE;
getDoc(form).ifPresent(entity -> {
form.doc = fessConfig.convertToEditableDoc(entity);
});
return asEditHtml();
}
@Execute
@ -231,7 +231,7 @@ public class AdminSearchlistAction extends FessAdminAction {
validate(form, messages -> {}, () -> asListHtml());
final String docId = form.docId;
getDoc(form).ifPresent(entity -> {
form.doc = entity;
form.doc = fessConfig.convertToEditableDoc(entity);
form.id = (String) entity.remove(fessConfig.getIndexFieldId());
form.version = (Long) entity.remove(fessConfig.getIndexFieldVersion());
}).orElse(() -> {
@ -245,18 +245,28 @@ public class AdminSearchlistAction extends FessAdminAction {
public HtmlResponse create(final CreateForm form) {
verifyCrudMode(form.crudMode, CrudMode.CREATE);
validate(form, messages -> {}, () -> asEditHtml());
// TODO verify
if (!fessConfig.hasIndexRequiredFields(form.doc)) {
throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), () -> asEditHtml());
}
verifyToken(() -> asEditHtml());
getDoc(form).ifPresent(entity -> {
try {
// TODO save
saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
} catch (final Exception e) {
logger.error("Failed to add " + entity, e);
throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
() -> asEditHtml());
}
}).orElse(() -> {
getDoc(form).ifPresent(
entity -> {
try {
entity.putAll(fessConfig.convertToStorableDoc(form.doc));
final String newId = ComponentUtil.getCrawlingInfoHelper().generateId(entity);
entity.put(fessConfig.getIndexFieldId(), newId);
final String index = fessConfig.getIndexDocumentUpdateIndex();
final String type = fessConfig.getIndexDocumentType();
fessEsClient.store(index, type, entity);
saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
} catch (final Exception e) {
logger.error("Failed to add " + entity, e);
throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
() -> asEditHtml());
}
}).orElse(() -> {
throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), () -> asEditHtml());
});
return redirect(getClass());
@ -266,25 +276,25 @@ public class AdminSearchlistAction extends FessAdminAction {
public HtmlResponse update(final EditForm form) {
verifyCrudMode(form.crudMode, CrudMode.EDIT);
validate(form, messages -> {}, () -> asEditHtml());
// TODO verify
if (!fessConfig.hasIndexRequiredFields(form.doc)) {
throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.docId), () -> asEditHtml());
}
verifyToken(() -> asEditHtml());
getDoc(form).ifPresent(
entity -> {
try {
form.doc.entrySet().stream().map(e -> {
// TODO converter
return new Pair<>(e.getKey(), e.getValue());
}).forEach(p -> entity.put(p.getFirst(), p.getSecond()));
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;
entity.put(fessConfig.getIndexFieldId(), newId);
entity.remove(fessConfig.getIndexFieldVersion());
}
entity.put(fessConfig.getIndexFieldVersion(), form.version);
final String index = fessConfig.getIndexDocumentUpdateIndex();
final String type = fessConfig.getIndexDocumentType();
@ -318,8 +328,9 @@ public class AdminSearchlistAction extends FessAdminAction {
protected OptionalEntity<Map<String, Object>> getDoc(final CreateForm form) {
switch (form.crudMode) {
case CrudMode.CREATE:
// TODO
return OptionalEntity.empty();
Map<String, Object> entity = new HashMap<>();
entity.put(fessConfig.getIndexFieldDocId(), systemHelper.generateDocId(entity));
return OptionalEntity.of(entity);
case CrudMode.EDIT:
if (form instanceof EditForm) {
final String docId = ((EditForm) form).docId;

View file

@ -966,9 +966,12 @@ public class FessEsClient implements Client {
.actionGet(fessConfig.getIndexIndexTimeout());
} else {
// create or update
response =
client.prepareIndex(index, type, id).setSource(source).setRefresh(true).setOpType(OpType.INDEX).setVersion(version)
.execute().actionGet(fessConfig.getIndexIndexTimeout());
IndexRequestBuilder builder =
client.prepareIndex(index, type, id).setSource(source).setRefresh(true).setOpType(OpType.INDEX);
if (version != null && version.longValue() > 0) {
builder.setVersion(version);
}
response = builder.execute().actionGet(fessConfig.getIndexIndexTimeout());
}
return response.isCreated();
} catch (final ElasticsearchException e) {

View file

@ -352,6 +352,27 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
/** The key of the configuration. e.g. doc */
String INDEX_DOCUMENT_TYPE = "index.document.type";
/** The key of the configuration. e.g. lang,role,label,anchor */
String INDEX_ADMIN_ARRAY_FIELDS = "index.admin.array.fields";
/** The key of the configuration. e.g. expires,created,timestamp,last_modified */
String INDEX_ADMIN_DATE_FIELDS = "index.admin.date.fields";
/** The key of the configuration. e.g. */
String INDEX_ADMIN_INTEGER_FIELDS = "index.admin.integer.fields";
/** The key of the configuration. e.g. favorite_count,click_count */
String INDEX_ADMIN_LONG_FIELDS = "index.admin.long.fields";
/** The key of the configuration. e.g. boost */
String INDEX_ADMIN_FLOAT_FIELDS = "index.admin.float.fields";
/** The key of the configuration. e.g. */
String INDEX_ADMIN_DOUBLE_FIELDS = "index.admin.double.fields";
/** The key of the configuration. e.g. doc_id,url,title,role */
String INDEX_ADMIN_REQUIRED_FIELDS = "index.admin.required.fields";
/** The key of the configuration. e.g. 3m */
String INDEX_SEARCH_TIMEOUT = "index.search.timeout";
@ -1988,6 +2009,72 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
*/
String getIndexDocumentType();
/**
* Get the value for the key 'index.admin.array.fields'. <br>
* The value is, e.g. lang,role,label,anchor <br>
* comment: doc management
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getIndexAdminArrayFields();
/**
* Get the value for the key 'index.admin.date.fields'. <br>
* The value is, e.g. expires,created,timestamp,last_modified <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getIndexAdminDateFields();
/**
* Get the value for the key 'index.admin.integer.fields'. <br>
* The value is, e.g. <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getIndexAdminIntegerFields();
/**
* Get the value for the key 'index.admin.integer.fields' as {@link Integer}. <br>
* The value is, e.g. <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
* @throws NumberFormatException When the property is not integer.
*/
Integer getIndexAdminIntegerFieldsAsInteger();
/**
* Get the value for the key 'index.admin.long.fields'. <br>
* The value is, e.g. favorite_count,click_count <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getIndexAdminLongFields();
/**
* Get the value for the key 'index.admin.float.fields'. <br>
* The value is, e.g. boost <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getIndexAdminFloatFields();
/**
* Get the value for the key 'index.admin.double.fields'. <br>
* The value is, e.g. <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getIndexAdminDoubleFields();
/**
* Get the value for the key 'index.admin.double.fields' as {@link Integer}. <br>
* The value is, e.g. <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
* @throws NumberFormatException When the property is not integer.
*/
Integer getIndexAdminDoubleFieldsAsInteger();
/**
* Get the value for the key 'index.admin.required.fields'. <br>
* The value is, e.g. doc_id,url,title,role <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getIndexAdminRequiredFields();
/**
* Get the value for the key 'index.search.timeout'. <br>
* The value is, e.g. 3m <br>
@ -4540,6 +4627,42 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
return get(FessConfig.INDEX_DOCUMENT_TYPE);
}
public String getIndexAdminArrayFields() {
return get(FessConfig.INDEX_ADMIN_ARRAY_FIELDS);
}
public String getIndexAdminDateFields() {
return get(FessConfig.INDEX_ADMIN_DATE_FIELDS);
}
public String getIndexAdminIntegerFields() {
return get(FessConfig.INDEX_ADMIN_INTEGER_FIELDS);
}
public Integer getIndexAdminIntegerFieldsAsInteger() {
return getAsInteger(FessConfig.INDEX_ADMIN_INTEGER_FIELDS);
}
public String getIndexAdminLongFields() {
return get(FessConfig.INDEX_ADMIN_LONG_FIELDS);
}
public String getIndexAdminFloatFields() {
return get(FessConfig.INDEX_ADMIN_FLOAT_FIELDS);
}
public String getIndexAdminDoubleFields() {
return get(FessConfig.INDEX_ADMIN_DOUBLE_FIELDS);
}
public Integer getIndexAdminDoubleFieldsAsInteger() {
return getAsInteger(FessConfig.INDEX_ADMIN_DOUBLE_FIELDS);
}
public String getIndexAdminRequiredFields() {
return get(FessConfig.INDEX_ADMIN_REQUIRED_FIELDS);
}
public String getIndexSearchTimeout() {
return get(FessConfig.INDEX_SEARCH_TIMEOUT);
}

View file

@ -18,6 +18,7 @@ package org.codelibs.fess.mylasta.direction;
import static org.codelibs.core.stream.StreamUtil.stream;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
@ -39,6 +40,7 @@ import org.codelibs.core.misc.Tuple3;
import org.codelibs.fess.Constants;
import org.codelibs.fess.helper.PermissionHelper;
import org.codelibs.fess.mylasta.action.FessUserBean;
import org.codelibs.fess.taglib.FessFunctions;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.optional.OptionalThing;
import org.elasticsearch.action.search.SearchRequestBuilder;
@ -48,6 +50,18 @@ import org.lastaflute.web.util.LaRequestUtil;
public interface FessProp {
public static final String INDEX_ADMIN_ARRAY_FIELD_SET = "indexAdminArrayFieldSet";
public static final String INDEX_ADMIN_DATE_FIELD_SET = "indexAdminDateFieldSet";
public static final String INDEX_ADMIN_INTEGER_FIELD_SET = "indexAdminIntegerFieldSet";
public static final String INDEX_ADMIN_LONG_FIELD_SET = "indexAdminLongFieldSet";
public static final String INDEX_ADMIN_FLOAT_FIELD_SET = "indexAdminFloatFieldSet";
public static final String INDEX_ADMIN_DOUBLE_FIELD_SET = "indexAdminDoubleFieldSet";
public static final String OIC_DEFAULT_ROLES = "oicDefaultRoles";
public static final String OIC_DEFAULT_GROUPS = "oicDefaultGroups";
@ -1034,4 +1048,172 @@ public interface FessProp {
}
return array;
}
String getIndexAdminArrayFields();
public default Set<String> getIndexAdminArrayFieldSet() {
@SuppressWarnings("unchecked")
Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_ARRAY_FIELD_SET);
if (fieldSet == null) {
fieldSet =
stream(getIndexAdminArrayFields().split(",")).get(
stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim()).collect(Collectors.toSet()));
propMap.put(INDEX_ADMIN_ARRAY_FIELD_SET, fieldSet);
}
return fieldSet;
}
String getIndexAdminDateFields();
public default Set<String> getIndexAdminDateFieldSet() {
@SuppressWarnings("unchecked")
Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_DATE_FIELD_SET);
if (fieldSet == null) {
fieldSet =
stream(getIndexAdminDateFields().split(",")).get(
stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim()).collect(Collectors.toSet()));
propMap.put(INDEX_ADMIN_DATE_FIELD_SET, fieldSet);
}
return fieldSet;
}
String getIndexAdminIntegerFields();
public default Set<String> getIndexAdminIntegerFieldSet() {
@SuppressWarnings("unchecked")
Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_INTEGER_FIELD_SET);
if (fieldSet == null) {
fieldSet =
stream(getIndexAdminIntegerFields().split(",")).get(
stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim()).collect(Collectors.toSet()));
propMap.put(INDEX_ADMIN_INTEGER_FIELD_SET, fieldSet);
}
return fieldSet;
}
String getIndexAdminLongFields();
public default Set<String> getIndexAdminLongFieldSet() {
@SuppressWarnings("unchecked")
Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_LONG_FIELD_SET);
if (fieldSet == null) {
fieldSet =
stream(getIndexAdminLongFields().split(",")).get(
stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim()).collect(Collectors.toSet()));
propMap.put(INDEX_ADMIN_LONG_FIELD_SET, fieldSet);
}
return fieldSet;
}
String getIndexAdminFloatFields();
public default Set<String> getIndexAdminFloatFieldSet() {
@SuppressWarnings("unchecked")
Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_FLOAT_FIELD_SET);
if (fieldSet == null) {
fieldSet =
stream(getIndexAdminFloatFields().split(",")).get(
stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim()).collect(Collectors.toSet()));
propMap.put(INDEX_ADMIN_FLOAT_FIELD_SET, fieldSet);
}
return fieldSet;
}
String getIndexAdminDoubleFields();
public default Set<String> getIndexAdminDoubleFieldSet() {
@SuppressWarnings("unchecked")
Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_DOUBLE_FIELD_SET);
if (fieldSet == null) {
fieldSet =
stream(getIndexAdminDoubleFields().split(",")).get(
stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim()).collect(Collectors.toSet()));
propMap.put(INDEX_ADMIN_DOUBLE_FIELD_SET, fieldSet);
}
return fieldSet;
}
public default Map<String, Object> convertToEditableDoc(final Map<String, Object> source) {
final Set<String> arrayFieldSet = getIndexAdminArrayFieldSet();
final Set<String> dateFieldSet = getIndexAdminDateFieldSet();
final Set<String> integerFieldSet = getIndexAdminIntegerFieldSet();
final Set<String> longFieldSet = getIndexAdminLongFieldSet();
final Set<String> floatFieldSet = getIndexAdminFloatFieldSet();
final Set<String> doubleFieldSet = getIndexAdminDoubleFieldSet();
return source.entrySet().stream().map(e -> {
final String key = e.getKey();
Object value = e.getValue();
if (value instanceof String || value == null) {
return new Pair<String, Object>(key, value);
}
if (arrayFieldSet.contains(key)) {
if (value instanceof String[]) {
value = stream((String[]) value).get(stream -> stream.collect(Collectors.joining("\n")));
} else if (value instanceof List) {
@SuppressWarnings("unchecked")
final List<String> list = (List<String>) value;
value = list.stream().collect(Collectors.joining("\n"));
}
} else if (dateFieldSet.contains(key)) {
value = FessFunctions.formatDate((Date) value);
} else if (integerFieldSet.contains(key)) {
value = value.toString();
} else if (longFieldSet.contains(key)) {
value = value.toString();
} else if (floatFieldSet.contains(key)) {
value = value.toString();
} else if (doubleFieldSet.contains(key)) {
value = value.toString();
}
return new Pair<String, Object>(key, value);
}).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond));
}
public default Map<String, Object> convertToStorableDoc(final Map<String, Object> source) {
final Set<String> arrayFieldSet = getIndexAdminArrayFieldSet();
final Set<String> dateFieldSet = getIndexAdminDateFieldSet();
final Set<String> integerFieldSet = getIndexAdminIntegerFieldSet();
final Set<String> longFieldSet = getIndexAdminLongFieldSet();
final Set<String> floatFieldSet = getIndexAdminFloatFieldSet();
final Set<String> doubleFieldSet = getIndexAdminDoubleFieldSet();
return source
.entrySet()
.stream()
.map(e -> {
final String key = e.getKey();
Object value = e.getValue();
if (value == null) {
return new Pair<String, Object>(key, value);
}
if (arrayFieldSet.contains(key)) {
value =
stream(value.toString().split("\n")).get(
stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim()).collect(Collectors.toList()));
} else if (dateFieldSet.contains(key)) {
// TODO time zone
value = FessFunctions.parseDate(value.toString());
} else if (integerFieldSet.contains(key)) {
value = Integer.parseInt(value.toString());
} else if (longFieldSet.contains(key)) {
value = Long.parseLong(value.toString());
} else if (floatFieldSet.contains(key)) {
value = Float.parseFloat(value.toString());
} else if (doubleFieldSet.contains(key)) {
value = Double.parseDouble(value.toString());
}
return new Pair<String, Object>(key, value);
}).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond));
}
String getIndexAdminRequiredFields();
public default boolean hasIndexRequiredFields(final Map<String, Object> source) {
return stream(getIndexAdminRequiredFields().split(",")).get(
stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim()).allMatch(s -> source.containsKey(s)));
}
}

View file

@ -171,6 +171,15 @@ index.document.search.index=fess
index.document.update.index=fess
index.document.type=doc
# doc management
index.admin.array.fields=lang,role,label,anchor
index.admin.date.fields=expires,created,timestamp,last_modified
index.admin.integer.fields=
index.admin.long.fields=favorite_count,click_count
index.admin.float.fields=boost
index.admin.double.fields=
index.admin.required.fields=doc_id,url,title,role
# timeout
index.search.timeout=3m
index.scroll.search.timeout.timeout=3m

View file

@ -33,6 +33,12 @@
<h3 class="box-title">
<la:message key="labels.search_list_configuration" />
</h3>
<div class="btn-group pull-right">
<la:link href="/admin/searchlist/createnew?q=${f:u(q)}" styleClass="btn btn-success btn-xs">
<i class="fa fa-plus"></i>
<la:message key="labels.crud_link_create" />
</la:link>
</div>
</div>
<%-- Box Body --%>
<div class="box-body">

View file

@ -78,6 +78,20 @@
</la:info>
<la:errors property="_global" />
</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" />
</div>
</div>
<div class="form-group">
<label for="url" class="col-sm-3 control-label">url</label>
<div class="col-sm-9">
<la:errors property="doc.url" />
<la:text property="doc.url" styleClass="form-control" />
</div>
</div>
<div class="form-group">
<label for="title" class="col-sm-3 control-label">title</label>
<div class="col-sm-9">
@ -85,6 +99,13 @@
<la:text property="doc.title" styleClass="form-control" />
</div>
</div>
<div class="form-group">
<label for="role" class="col-sm-3 control-label">role</label>
<div class="col-sm-9">
<la:errors property="doc.role" />
<la:textarea property="doc.role" styleClass="form-control" />
</div>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">