Specify document search parameter as HTTP params (#722)

This commit is contained in:
Julien Kirch 2023-10-19 18:34:04 +02:00 committed by GitHub
parent f9b5a5212d
commit 04c43ebf7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 1086 additions and 358 deletions

View File

@ -87,7 +87,7 @@ public class DocumentDao {
} }
EntityManager em = ThreadLocalContext.get().getEntityManager(); EntityManager em = ThreadLocalContext.get().getEntityManager();
StringBuilder sb = new StringBuilder("select distinct d.DOC_ID_C, d.DOC_TITLE_C, d.DOC_DESCRIPTION_C, d.DOC_SUBJECT_C, d.DOC_IDENTIFIER_C, d.DOC_PUBLISHER_C, d.DOC_FORMAT_C, d.DOC_SOURCE_C, d.DOC_TYPE_C, d.DOC_COVERAGE_C, d.DOC_RIGHTS_C, d.DOC_CREATEDATE_D, d.DOC_UPDATEDATE_D, d.DOC_LANGUAGE_C, "); StringBuilder sb = new StringBuilder("select distinct d.DOC_ID_C, d.DOC_TITLE_C, d.DOC_DESCRIPTION_C, d.DOC_SUBJECT_C, d.DOC_IDENTIFIER_C, d.DOC_PUBLISHER_C, d.DOC_FORMAT_C, d.DOC_SOURCE_C, d.DOC_TYPE_C, d.DOC_COVERAGE_C, d.DOC_RIGHTS_C, d.DOC_CREATEDATE_D, d.DOC_UPDATEDATE_D, d.DOC_LANGUAGE_C, d.DOC_IDFILE_C,");
sb.append(" (select count(s.SHA_ID_C) from T_SHARE s, T_ACL ac where ac.ACL_SOURCEID_C = d.DOC_ID_C and ac.ACL_TARGETID_C = s.SHA_ID_C and ac.ACL_DELETEDATE_D is null and s.SHA_DELETEDATE_D is null) shareCount, "); sb.append(" (select count(s.SHA_ID_C) from T_SHARE s, T_ACL ac where ac.ACL_SOURCEID_C = d.DOC_ID_C and ac.ACL_TARGETID_C = s.SHA_ID_C and ac.ACL_DELETEDATE_D is null and s.SHA_DELETEDATE_D is null) shareCount, ");
sb.append(" (select count(f.FIL_ID_C) from T_FILE f where f.FIL_DELETEDATE_D is null and f.FIL_IDDOC_C = d.DOC_ID_C) fileCount, "); sb.append(" (select count(f.FIL_ID_C) from T_FILE f where f.FIL_DELETEDATE_D is null and f.FIL_IDDOC_C = d.DOC_ID_C) fileCount, ");
sb.append(" u.USE_USERNAME_C "); sb.append(" u.USE_USERNAME_C ");
@ -121,6 +121,7 @@ public class DocumentDao {
documentDto.setCreateTimestamp(((Timestamp) o[i++]).getTime()); documentDto.setCreateTimestamp(((Timestamp) o[i++]).getTime());
documentDto.setUpdateTimestamp(((Timestamp) o[i++]).getTime()); documentDto.setUpdateTimestamp(((Timestamp) o[i++]).getTime());
documentDto.setLanguage((String) o[i++]); documentDto.setLanguage((String) o[i++]);
documentDto.setFileId((String) o[i++]);
documentDto.setShared(((Number) o[i++]).intValue() > 0); documentDto.setShared(((Number) o[i++]).intValue() > 0);
documentDto.setFileCount(((Number) o[i++]).intValue()); documentDto.setFileCount(((Number) o[i++]).intValue());
documentDto.setCreator((String) o[i]); documentDto.setCreator((String) o[i]);

View File

@ -19,7 +19,7 @@ public class DocumentCriteria {
/** /**
* Search query. * Search query.
*/ */
private String search; private String simpleSearch;
/** /**
* Full content search query. * Full content search query.
@ -96,12 +96,12 @@ public class DocumentCriteria {
this.targetIdList = targetIdList; this.targetIdList = targetIdList;
} }
public String getSearch() { public String getSimpleSearch() {
return search; return simpleSearch;
} }
public void setSearch(String search) { public void setSimpleSearch(String search) {
this.search = search; this.simpleSearch = search;
} }
public String getFullSearch() { public String getFullSearch() {

View File

@ -276,9 +276,8 @@ public class LuceneIndexingHandler implements IndexingHandler {
criteriaList.add("(a.ACL_ID_C is not null or a2.ACL_ID_C is not null)"); criteriaList.add("(a.ACL_ID_C is not null or a2.ACL_ID_C is not null)");
} }
parameterMap.put("targetIdList", criteria.getTargetIdList()); parameterMap.put("targetIdList", criteria.getTargetIdList());
if (!Strings.isNullOrEmpty(criteria.getSimpleSearch()) || !Strings.isNullOrEmpty(criteria.getFullSearch())) {
if (!Strings.isNullOrEmpty(criteria.getSearch()) || !Strings.isNullOrEmpty(criteria.getFullSearch())) { documentSearchMap = search(criteria.getSimpleSearch(), criteria.getFullSearch());
documentSearchMap = search(criteria.getSearch(), criteria.getFullSearch());
if (documentSearchMap.isEmpty()) { if (documentSearchMap.isEmpty()) {
// If the search doesn't find any document, the request should return nothing // If the search doesn't find any document, the request should return nothing
documentSearchMap.put(UUID.randomUUID().toString(), null); documentSearchMap.put(UUID.randomUUID().toString(), null);
@ -413,14 +412,14 @@ public class LuceneIndexingHandler implements IndexingHandler {
/** /**
* Fulltext search in files and documents. * Fulltext search in files and documents.
* *
* @param searchQuery Search query on metadatas * @param simpleSearchQuery Search query on metadatas
* @param fullSearchQuery Search query on all fields * @param fullSearchQuery Search query on all fields
* @return Map of document IDs as key and highlight as value * @return Map of document IDs as key and highlight as value
* @throws Exception e * @throws Exception e
*/ */
private Map<String, String> search(String searchQuery, String fullSearchQuery) throws Exception { private Map<String, String> search(String simpleSearchQuery, String fullSearchQuery) throws Exception {
// The fulltext query searches in all fields // The fulltext query searches in all fields
searchQuery = searchQuery + " " + fullSearchQuery; String searchQuery = simpleSearchQuery + " " + fullSearchQuery;
// Build search query // Build search query
Analyzer analyzer = new StandardAnalyzer(); Analyzer analyzer = new StandardAnalyzer();

View File

@ -68,7 +68,7 @@ public class PaginatedLists {
} }
/** /**
* Executes a query and returns the data of the currunt page. * Executes a query and returns the data of the current page.
* *
* @param paginatedList Paginated list object containing parameters, and into which results are added by side effects * @param paginatedList Paginated list object containing parameters, and into which results are added by side effects
* @param queryParam Query parameters * @param queryParam Query parameters
@ -83,18 +83,6 @@ public class PaginatedLists {
return q.getResultList(); return q.getResultList();
} }
/**
* Executes a paginated request with 2 native queries (one to count the number of results, and one to return the page).
*
* @param paginatedList Paginated list object containing parameters, and into which results are added by side effects
* @param queryParam Query parameters
* @return List of results
*/
public static <E> List<Object[]> executePaginatedQuery(PaginatedList<E> paginatedList, QueryParam queryParam) {
executeCountQuery(paginatedList, queryParam);
return executeResultQuery(paginatedList, queryParam);
}
/** /**
* Executes a paginated request with 2 native queries (one to count the number of results, and one to return the page). * Executes a paginated request with 2 native queries (one to count the number of results, and one to return the page).
* *

View File

@ -30,7 +30,7 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
*/ */
public abstract class BaseTransactionalTest extends BaseTest { public abstract class BaseTransactionalTest extends BaseTest {
@Before @Before
public void setUp() throws Exception { public void setUp() {
// Initialize the entity manager // Initialize the entity manager
EntityManager em = EMF.get().createEntityManager(); EntityManager em = EMF.get().createEntityManager();
ThreadLocalContext context = ThreadLocalContext.get(); ThreadLocalContext context = ThreadLocalContext.get();
@ -40,7 +40,8 @@ public abstract class BaseTransactionalTest extends BaseTest {
} }
@After @After
public void tearDown() throws Exception { public void tearDown() {
ThreadLocalContext.get().getEntityManager().getTransaction().rollback();
} }
protected User createUser(String userName) throws Exception { protected User createUser(String userName) throws Exception {

View File

@ -64,6 +64,10 @@ public abstract class BaseJerseyTest extends JerseyTest {
*/ */
private Wiser wiser; private Wiser wiser;
public String adminToken() {
return clientUtil.login("admin", "admin", false);
}
@Override @Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException { protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new ExternalTestContainerFactory(); return new ExternalTestContainerFactory();

View File

@ -1,7 +1,5 @@
package com.sismics.docs.rest.resource; package com.sismics.docs.rest.resource;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.sismics.docs.core.constant.AclType; import com.sismics.docs.core.constant.AclType;
import com.sismics.docs.core.constant.ConfigType; import com.sismics.docs.core.constant.ConfigType;
@ -36,10 +34,10 @@ import com.sismics.docs.core.util.DocumentUtil;
import com.sismics.docs.core.util.FileUtil; import com.sismics.docs.core.util.FileUtil;
import com.sismics.docs.core.util.MetadataUtil; import com.sismics.docs.core.util.MetadataUtil;
import com.sismics.docs.core.util.PdfUtil; import com.sismics.docs.core.util.PdfUtil;
import com.sismics.docs.core.util.TagUtil;
import com.sismics.docs.core.util.jpa.PaginatedList; import com.sismics.docs.core.util.jpa.PaginatedList;
import com.sismics.docs.core.util.jpa.PaginatedLists; import com.sismics.docs.core.util.jpa.PaginatedLists;
import com.sismics.docs.core.util.jpa.SortCriteria; import com.sismics.docs.core.util.jpa.SortCriteria;
import com.sismics.docs.rest.util.DocumentSearchCriteriaUtil;
import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ClientException;
import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.rest.exception.ServerException; import com.sismics.rest.exception.ServerException;
@ -57,6 +55,7 @@ import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.FormParam; import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.HEAD;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT; import jakarta.ws.rs.PUT;
@ -69,11 +68,6 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.joda.time.format.DateTimeParser;
import javax.mail.Message; import javax.mail.Message;
import javax.mail.MessagingException; import javax.mail.MessagingException;
@ -103,20 +97,6 @@ import java.util.UUID;
@Path("/document") @Path("/document")
public class DocumentResource extends BaseResource { public class DocumentResource extends BaseResource {
protected static final DateTimeParser YEAR_PARSER = DateTimeFormat.forPattern("yyyy").getParser();
protected static final DateTimeParser MONTH_PARSER = DateTimeFormat.forPattern("yyyy-MM").getParser();
protected static final DateTimeParser DAY_PARSER = DateTimeFormat.forPattern("yyyy-MM-dd").getParser();
private static final DateTimeFormatter DAY_FORMATTER = new DateTimeFormatter(null, DAY_PARSER);
private static final DateTimeFormatter MONTH_FORMATTER = new DateTimeFormatter(null, MONTH_PARSER);
private static final DateTimeFormatter YEAR_FORMATTER = new DateTimeFormatter(null, YEAR_PARSER);
private static final DateTimeParser[] DATE_PARSERS = new DateTimeParser[]{
YEAR_PARSER,
MONTH_PARSER,
DAY_PARSER};
private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder().append( null, DATE_PARSERS).toFormatter();
/** /**
* Returns a document. * Returns a document.
* *
@ -124,8 +104,8 @@ public class DocumentResource extends BaseResource {
* @apiName GetDocument * @apiName GetDocument
* @apiGroup Document * @apiGroup Document
* @apiParam {String} id Document ID * @apiParam {String} id Document ID
* @apiParam {String} share Share ID * @apiParam {String} [share] Share ID
* @apiParam {Booleans} files If true includes files information * @apiParam {Boolean} [files] If true includes files information
* @apiSuccess {String} id ID * @apiSuccess {String} id ID
* @apiSuccess {String} title Title * @apiSuccess {String} title Title
* @apiSuccess {String} description Description * @apiSuccess {String} description Description
@ -147,6 +127,7 @@ public class DocumentResource extends BaseResource {
* @apiSuccess {String} coverage Coverage * @apiSuccess {String} coverage Coverage
* @apiSuccess {String} rights Rights * @apiSuccess {String} rights Rights
* @apiSuccess {String} creator Username of the creator * @apiSuccess {String} creator Username of the creator
* @apiSuccess {String} file_id Main file ID
* @apiSuccess {Boolean} writable True if the document is writable by the current user * @apiSuccess {Boolean} writable True if the document is writable by the current user
* @apiSuccess {Object[]} acls List of ACL * @apiSuccess {Object[]} acls List of ACL
* @apiSuccess {String} acls.id ID * @apiSuccess {String} acls.id ID
@ -205,15 +186,17 @@ public class DocumentResource extends BaseResource {
throw new NotFoundException(); throw new NotFoundException();
} }
JsonObjectBuilder document = Json.createObjectBuilder() JsonObjectBuilder document = createDocumentObjectBuilder(documentDto)
.add("id", documentDto.getId()) .add("creator", documentDto.getCreator())
.add("title", documentDto.getTitle()) .add("coverage", JsonUtil.nullable(documentDto.getCoverage()))
.add("description", JsonUtil.nullable(documentDto.getDescription())) .add("file_count", documentDto.getFileCount())
.add("create_date", documentDto.getCreateTimestamp()) .add("format", JsonUtil.nullable(documentDto.getFormat()))
.add("update_date", documentDto.getUpdateTimestamp()) .add("identifier", JsonUtil.nullable(documentDto.getIdentifier()))
.add("language", documentDto.getLanguage()) .add("publisher", JsonUtil.nullable(documentDto.getPublisher()))
.add("shared", documentDto.getShared()) .add("rights", JsonUtil.nullable(documentDto.getRights()))
.add("file_count", documentDto.getFileCount()); .add("source", JsonUtil.nullable(documentDto.getSource()))
.add("subject", JsonUtil.nullable(documentDto.getSubject()))
.add("type", JsonUtil.nullable(documentDto.getType()));
List<TagDto> tagDtoList = null; List<TagDto> tagDtoList = null;
if (principal.isAnonymous()) { if (principal.isAnonymous()) {
@ -227,27 +210,9 @@ public class DocumentResource extends BaseResource {
.setTargetIdList(getTargetIdList(null)) // No tags for shares .setTargetIdList(getTargetIdList(null)) // No tags for shares
.setDocumentId(documentId), .setDocumentId(documentId),
new SortCriteria(1, true)); new SortCriteria(1, true));
JsonArrayBuilder tags = Json.createArrayBuilder(); document.add("tags", createTagsArrayBuilder(tagDtoList));
for (TagDto tagDto : tagDtoList) {
tags.add(Json.createObjectBuilder()
.add("id", tagDto.getId())
.add("name", tagDto.getName())
.add("color", tagDto.getColor()));
}
document.add("tags", tags);
} }
// Below is specific to GET /document/id
document.add("subject", JsonUtil.nullable(documentDto.getSubject()));
document.add("identifier", JsonUtil.nullable(documentDto.getIdentifier()));
document.add("publisher", JsonUtil.nullable(documentDto.getPublisher()));
document.add("format", JsonUtil.nullable(documentDto.getFormat()));
document.add("source", JsonUtil.nullable(documentDto.getSource()));
document.add("type", JsonUtil.nullable(documentDto.getType()));
document.add("coverage", JsonUtil.nullable(documentDto.getCoverage()));
document.add("rights", JsonUtil.nullable(documentDto.getRights()));
document.add("creator", documentDto.getCreator());
// Add ACL // Add ACL
AclUtil.addAcls(document, documentId, getTargetIdList(shareId)); AclUtil.addAcls(document, documentId, getTargetIdList(shareId));
@ -330,7 +295,6 @@ public class DocumentResource extends BaseResource {
* @apiParam {String} id Document ID * @apiParam {String} id Document ID
* @apiParam {String} share Share ID * @apiParam {String} share Share ID
* @apiParam {Boolean} metadata If true, export metadata * @apiParam {Boolean} metadata If true, export metadata
* @apiParam {Boolean} comments If true, export comments
* @apiParam {Boolean} fitimagetopage If true, fit the images to pages * @apiParam {Boolean} fitimagetopage If true, fit the images to pages
* @apiParam {Number} margin Margin around the pages, in millimeter * @apiParam {Number} margin Margin around the pages, in millimeter
* @apiSuccess {String} pdf The whole response is the PDF file * @apiSuccess {String} pdf The whole response is the PDF file
@ -342,7 +306,6 @@ public class DocumentResource extends BaseResource {
* @param documentId Document ID * @param documentId Document ID
* @param shareId Share ID * @param shareId Share ID
* @param metadata Export metadata * @param metadata Export metadata
* @param comments Export comments
* @param fitImageToPage Fit images to page * @param fitImageToPage Fit images to page
* @param marginStr Margins * @param marginStr Margins
* @return Response * @return Response
@ -353,7 +316,6 @@ public class DocumentResource extends BaseResource {
@PathParam("id") String documentId, @PathParam("id") String documentId,
@QueryParam("share") String shareId, @QueryParam("share") String shareId,
final @QueryParam("metadata") Boolean metadata, final @QueryParam("metadata") Boolean metadata,
final @QueryParam("comments") Boolean comments,
final @QueryParam("fitimagetopage") Boolean fitImageToPage, final @QueryParam("fitimagetopage") Boolean fitImageToPage,
@QueryParam("margin") String marginStr) { @QueryParam("margin") String marginStr) {
authenticate(); authenticate();
@ -395,17 +357,34 @@ public class DocumentResource extends BaseResource {
} }
/** /**
* Returns all documents. * Returns all documents, if a parameter is considered invalid, the search result will be empty.
* *
* @api {get} /document/list Get documents * @api {get} /document/list Get documents
* @apiName GetDocumentList * @apiName GetDocumentList
* @apiGroup Document * @apiGroup Document
* @apiParam {String} limit Total number of documents to return *
* @apiParam {String} offset Start at this index * @apiParam {String} [limit] Total number of documents to return (default is <code>10</code>)
* @apiParam {Number} sort_column Column index to sort on * @apiParam {String} [offset] Start at this index (default is <code>0</code>)
* @apiParam {Boolean} asc If true, sort in ascending order * @apiParam {Number} [sort_column] Column index to sort on
* @apiParam {String} search Search query (see "Document search syntax" on the top of the page for explanations) * @apiParam {Boolean} [asc] If <code>true</code> sorts in ascending order
* @apiParam {Booleans} files If true includes files information * @apiParam {String} [search] Search query (see "Document search syntax" on the top of the page for explanations) when the input is entered by a human.
* @apiParam {Boolean} [files] If <code>true</code> includes files information
*
* @apiParam {String} [search[after]] The document must have been created after or at the value moment, accepted format is <code>yyyy-MM-dd</code>
* @apiParam {String} [search[before]] The document must have been created before or at the value moment, accepted format is <code>yyyy-MM-dd</code>
* @apiParam {String} [search[by]] The document must have been created by the specified creator's username with an exact match, the user must not be deleted
* @apiParam {String} [search[full]] Used as a search criteria for all fields including the document's files content, several comma-separated values can be specified and the document must match any of them
* @apiParam {String} [search[lang]] The document must be of the specified language (example: <code>en</code>)
* @apiParam {String} [search[mime]] The document must be of the specified mime type (example: <code>image/png</code>)
* @apiParam {String} [search[simple]] Used as a search criteria for all fields except the document's files content, several comma-separated values can be specified and the document must match any of them
* @apiParam {Boolean} [search[shared]] If <code>true</code> the document must be shared, else it is ignored
* @apiParam {String} [search[tag]] The document must contain a tag or a child of a tag that starts with the value, case is ignored, several comma-separated values can be specified and the document must match all tag filters
* @apiParam {String} [search[nottag]] The document must not contain a tag or a child of a tag that starts with the value, case is ignored, several comma-separated values can be specified and the document must match all tag filters
* @apiParam {String} [search[title]] The document's title must be the value, several comma-separated values can be specified and the document must match any of the titles
* @apiParam {String} [search[uafter]] The document must have been updated after or at the value moment, accepted format is <code>yyyy-MM-dd</code>
* @apiParam {String} [search[ubefore]] The document must have been updated before or at the value moment, accepted format is <code>yyyy-MM-dd</code>
* @apiParam {String} [search[workflow]] If the value is <code>me</code> the document must have an active route, for other values the criteria is ignored
*
* @apiSuccess {Number} total Total number of documents * @apiSuccess {Number} total Total number of documents
* @apiSuccess {Object[]} documents List of documents * @apiSuccess {Object[]} documents List of documents
* @apiSuccess {String} documents.id ID * @apiSuccess {String} documents.id ID
@ -431,6 +410,7 @@ public class DocumentResource extends BaseResource {
* @apiSuccess {String} documents.files.mimetype MIME type * @apiSuccess {String} documents.files.mimetype MIME type
* @apiSuccess {String} documents.files.create_date Create date (timestamp) * @apiSuccess {String} documents.files.create_date Create date (timestamp)
* @apiSuccess {String[]} suggestions List of search suggestions * @apiSuccess {String[]} suggestions List of search suggestions
*
* @apiError (client) ForbiddenError Access denied * @apiError (client) ForbiddenError Access denied
* @apiError (server) SearchError Error searching in documents * @apiError (server) SearchError Error searching in documents
* @apiPermission user * @apiPermission user
@ -452,7 +432,23 @@ public class DocumentResource extends BaseResource {
@QueryParam("sort_column") Integer sortColumn, @QueryParam("sort_column") Integer sortColumn,
@QueryParam("asc") Boolean asc, @QueryParam("asc") Boolean asc,
@QueryParam("search") String search, @QueryParam("search") String search,
@QueryParam("files") Boolean files) { @QueryParam("files") Boolean files,
@QueryParam("search[after]") String searchCreatedAfter,
@QueryParam("search[before]") String searchCreatedBefore,
@QueryParam("search[by]") String searchBy,
@QueryParam("search[full]") String searchFull,
@QueryParam("search[lang]") String searchLang,
@QueryParam("search[mime]") String searchMime,
@QueryParam("search[shared]") Boolean searchShared,
@QueryParam("search[simple]") String searchSimple,
@QueryParam("search[tag]") String searchTag,
@QueryParam("search[nottag]") String searchTagNot,
@QueryParam("search[title]") String searchTitle,
@QueryParam("search[uafter]") String searchUpdatedAfter,
@QueryParam("search[ubefore]") String searchUpdatedBefore,
@QueryParam("search[searchworkflow]") String searchWorkflow
) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -464,7 +460,28 @@ public class DocumentResource extends BaseResource {
PaginatedList<DocumentDto> paginatedList = PaginatedLists.create(limit, offset); PaginatedList<DocumentDto> paginatedList = PaginatedLists.create(limit, offset);
List<String> suggestionList = Lists.newArrayList(); List<String> suggestionList = Lists.newArrayList();
SortCriteria sortCriteria = new SortCriteria(sortColumn, asc); SortCriteria sortCriteria = new SortCriteria(sortColumn, asc);
DocumentCriteria documentCriteria = parseSearchQuery(search);
List<TagDto> allTagDtoList = tagDao.findByCriteria(new TagCriteria().setTargetIdList(getTargetIdList(null)), null);
DocumentCriteria documentCriteria = DocumentSearchCriteriaUtil.parseSearchQuery(search, allTagDtoList);
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
searchBy,
searchCreatedAfter,
searchCreatedBefore,
searchFull,
searchLang,
searchMime,
searchShared,
searchSimple,
searchTag,
searchTagNot,
searchTitle,
searchUpdatedAfter,
searchUpdatedBefore,
searchWorkflow,
allTagDtoList);
documentCriteria.setTargetIdList(getTargetIdList(null)); documentCriteria.setTargetIdList(getTargetIdList(null));
try { try {
AppContext.getInstance().getIndexingHandler().findByCriteria(paginatedList, suggestionList, documentCriteria, sortCriteria); AppContext.getInstance().getIndexingHandler().findByCriteria(paginatedList, suggestionList, documentCriteria, sortCriteria);
@ -488,13 +505,6 @@ public class DocumentResource extends BaseResource {
List<TagDto> tagDtoList = tagDao.findByCriteria(new TagCriteria() List<TagDto> tagDtoList = tagDao.findByCriteria(new TagCriteria()
.setTargetIdList(getTargetIdList(null)) .setTargetIdList(getTargetIdList(null))
.setDocumentId(documentDto.getId()), new SortCriteria(1, true)); .setDocumentId(documentDto.getId()), new SortCriteria(1, true));
JsonArrayBuilder tags = Json.createArrayBuilder();
for (TagDto tagDto : tagDtoList) {
tags.add(Json.createObjectBuilder()
.add("id", tagDto.getId())
.add("name", tagDto.getName())
.add("color", tagDto.getColor()));
}
Long filesCount; Long filesCount;
Collection<File> filesOfDocument = null; Collection<File> filesOfDocument = null;
@ -506,20 +516,13 @@ public class DocumentResource extends BaseResource {
filesCount = filesCountByDocument.getOrDefault(documentDto.getId(), 0L); filesCount = filesCountByDocument.getOrDefault(documentDto.getId(), 0L);
} }
JsonObjectBuilder documentObjectBuilder = Json.createObjectBuilder() JsonObjectBuilder documentObjectBuilder = createDocumentObjectBuilder(documentDto)
.add("id", documentDto.getId())
.add("highlight", JsonUtil.nullable(documentDto.getHighlight()))
.add("file_id", JsonUtil.nullable(documentDto.getFileId()))
.add("title", documentDto.getTitle())
.add("description", JsonUtil.nullable(documentDto.getDescription()))
.add("create_date", documentDto.getCreateTimestamp())
.add("update_date", documentDto.getUpdateTimestamp())
.add("language", documentDto.getLanguage())
.add("shared", documentDto.getShared())
.add("active_route", documentDto.isActiveRoute()) .add("active_route", documentDto.isActiveRoute())
.add("current_step_name", JsonUtil.nullable(documentDto.getCurrentStepName())) .add("current_step_name", JsonUtil.nullable(documentDto.getCurrentStepName()))
.add("highlight", JsonUtil.nullable(documentDto.getHighlight()))
.add("file_count", filesCount) .add("file_count", filesCount)
.add("tags", tags); .add("tags", createTagsArrayBuilder(tagDtoList));
if (Boolean.TRUE == files) { if (Boolean.TRUE == files) {
JsonArrayBuilder filesArrayBuilder = Json.createArrayBuilder(); JsonArrayBuilder filesArrayBuilder = Json.createArrayBuilder();
for (File fileDb : filesOfDocument) { for (File fileDb : filesOfDocument) {
@ -567,188 +570,44 @@ public class DocumentResource extends BaseResource {
@FormParam("sort_column") Integer sortColumn, @FormParam("sort_column") Integer sortColumn,
@FormParam("asc") Boolean asc, @FormParam("asc") Boolean asc,
@FormParam("search") String search, @FormParam("search") String search,
@FormParam("files") Boolean files) { @FormParam("files") Boolean files,
return list(limit, offset, sortColumn, asc, search, files); @FormParam("search[after]") String searchCreatedAfter,
} @FormParam("search[before]") String searchCreatedBefore,
@FormParam("search[by]") String searchBy,
/** @FormParam("search[full]") String searchFull,
* Parse a query according to the specified syntax, eg.: @FormParam("search[lang]") String searchLang,
* tag:assurance tag:other before:2012 after:2011-09 shared:yes lang:fra thing @FormParam("search[mime]") String searchMime,
* @FormParam("search[shared]") Boolean searchShared,
* @param search Search query @FormParam("search[simple]") String searchSimple,
* @return DocumentCriteria @FormParam("search[tag]") String searchTag,
*/ @FormParam("search[nottag]") String searchTagNot,
private DocumentCriteria parseSearchQuery(String search) { @FormParam("search[title]") String searchTitle,
DocumentCriteria documentCriteria = new DocumentCriteria(); @FormParam("search[uafter]") String searchUpdatedAfter,
if (Strings.isNullOrEmpty(search)) { @FormParam("search[ubefore]") String searchUpdatedBefore,
return documentCriteria; @FormParam("search[searchworkflow]") String searchWorkflow
} ) {
return list(
TagDao tagDao = new TagDao(); limit,
List<TagDto> allTagDtoList = tagDao.findByCriteria(new TagCriteria().setTargetIdList(getTargetIdList(null)), null); offset,
UserDao userDao = new UserDao(); sortColumn,
asc,
String[] criteriaList = search.split(" +"); search,
List<String> query = new ArrayList<>(); files,
List<String> fullQuery = new ArrayList<>(); searchCreatedAfter,
for (String criteria : criteriaList) { searchCreatedBefore,
String[] params = criteria.split(":"); searchBy,
if (params.length != 2 || Strings.isNullOrEmpty(params[0]) || Strings.isNullOrEmpty(params[1])) { searchFull,
// This is not a special criteria, do a fulltext search on it searchLang,
fullQuery.add(criteria); searchMime,
continue; searchShared,
} searchSimple,
String paramName = params[0]; searchTag,
String paramValue = params[1]; searchTagNot,
searchTitle,
switch (paramName) { searchUpdatedAfter,
case "tag": searchUpdatedBefore,
case "!tag": searchWorkflow
// New tag criteria );
List<TagDto> tagDtoList = TagUtil.findByName(paramValue, allTagDtoList);
if (tagDtoList.isEmpty()) {
// No tag found, the request must return nothing
documentCriteria.getTagIdList().add(Lists.newArrayList(UUID.randomUUID().toString()));
} else {
List<String> tagIdList = Lists.newArrayList();
for (TagDto tagDto : tagDtoList) {
tagIdList.add(tagDto.getId());
List<TagDto> childrenTagDtoList = TagUtil.findChildren(tagDto, allTagDtoList);
for (TagDto childrenTagDto : childrenTagDtoList) {
tagIdList.add(childrenTagDto.getId());
}
}
if (paramName.startsWith("!")) {
documentCriteria.getExcludedTagIdList().add(tagIdList);
} else {
documentCriteria.getTagIdList().add(tagIdList);
}
}
break;
case "after":
case "before":
case "uafter":
case "ubefore":
// New date span criteria
try {
boolean isUpdated = paramName.startsWith("u");
DateTime date = DATE_FORMATTER.parseDateTime(paramValue);
if (paramName.endsWith("before")) {
if (isUpdated) documentCriteria.setUpdateDateMax(date.toDate());
else documentCriteria.setCreateDateMax(date.toDate());
} else {
if (isUpdated) documentCriteria.setUpdateDateMin(date.toDate());
else documentCriteria.setCreateDateMin(date.toDate());
}
} catch (IllegalArgumentException e) {
// Invalid date, returns no documents
documentCriteria.setCreateDateMin(new Date(0));
documentCriteria.setCreateDateMax(new Date(0));
}
break;
case "uat":
case "at":
// New specific date criteria
boolean isUpdated = params[0].startsWith("u");
try {
switch (paramValue.length()) {
case 10: {
DateTime date = DATE_FORMATTER.parseDateTime(params[1]);
if (isUpdated) {
documentCriteria.setUpdateDateMin(date.toDate());
documentCriteria.setUpdateDateMax(date.plusDays(1).minusSeconds(1).toDate());
} else {
documentCriteria.setCreateDateMin(date.toDate());
documentCriteria.setCreateDateMax(date.plusDays(1).minusSeconds(1).toDate());
}
break;
}
case 7: {
DateTime date = MONTH_FORMATTER.parseDateTime(params[1]);
if (isUpdated) {
documentCriteria.setUpdateDateMin(date.toDate());
documentCriteria.setUpdateDateMax(date.plusMonths(1).minusSeconds(1).toDate());
} else {
documentCriteria.setCreateDateMin(date.toDate());
documentCriteria.setCreateDateMax(date.plusMonths(1).minusSeconds(1).toDate());
}
break;
}
case 4: {
DateTime date = YEAR_FORMATTER.parseDateTime(params[1]);
if (isUpdated) {
documentCriteria.setUpdateDateMin(date.toDate());
documentCriteria.setUpdateDateMax(date.plusYears(1).minusSeconds(1).toDate());
} else {
documentCriteria.setCreateDateMin(date.toDate());
documentCriteria.setCreateDateMax(date.plusYears(1).minusSeconds(1).toDate());
}
break;
} default: {
// Invalid format, returns no documents
documentCriteria.setCreateDateMin(new Date(0));
documentCriteria.setCreateDateMax(new Date(0));
}
}
} catch (IllegalArgumentException e) {
// Invalid date, returns no documents
documentCriteria.setCreateDateMin(new Date(0));
documentCriteria.setCreateDateMax(new Date(0));
}
break;
case "shared":
// New shared state criteria
documentCriteria.setShared(paramValue.equals("yes"));
break;
case "lang":
// New language criteria
if (Constants.SUPPORTED_LANGUAGES.contains(paramValue)) {
documentCriteria.setLanguage(paramValue);
} else {
// Unsupported language, returns no documents
documentCriteria.setLanguage(UUID.randomUUID().toString());
}
break;
case "mime":
// New mime type criteria
documentCriteria.setMimeType(paramValue);
break;
case "by":
// New creator criteria
User user = userDao.getActiveByUsername(paramValue);
if (user == null) {
// This user doesn't exist, return nothing
documentCriteria.setCreatorId(UUID.randomUUID().toString());
} else {
// This user exists, search its documents
documentCriteria.setCreatorId(user.getId());
}
break;
case "workflow":
// New shared state criteria
documentCriteria.setActiveRoute(paramValue.equals("me"));
break;
case "simple":
// New simple search criteria
query.add(paramValue);
break;
case "full":
// New fulltext search criteria
fullQuery.add(paramValue);
break;
case "title":
// New title criteria
documentCriteria.getTitleList().add(paramValue);
break;
default:
fullQuery.add(criteria);
break;
}
}
documentCriteria.setSearch(Joiner.on(" ").join(query));
documentCriteria.setFullSearch(Joiner.on(" ").join(fullQuery));
return documentCriteria;
} }
/** /**
@ -904,7 +763,7 @@ public class DocumentResource extends BaseResource {
* @apiParam {String[]} [relations] List of related documents ID * @apiParam {String[]} [relations] List of related documents ID
* @apiParam {String[]} [metadata_id] List of metadata ID * @apiParam {String[]} [metadata_id] List of metadata ID
* @apiParam {String[]} [metadata_value] List of metadata values * @apiParam {String[]} [metadata_value] List of metadata values
* @apiParam {String} language Language * @apiParam {String} [language] Language
* @apiParam {Number} [create_date] Create date (timestamp) * @apiParam {Number} [create_date] Create date (timestamp)
* @apiSuccess {String} id Document ID * @apiSuccess {String} id Document ID
* @apiError (client) ForbiddenError Access denied or document not writable * @apiError (client) ForbiddenError Access denied or document not writable
@ -1215,4 +1074,27 @@ public class DocumentResource extends BaseResource {
relationDao.updateRelationList(documentId, documentIdSet); relationDao.updateRelationList(documentId, documentIdSet);
} }
} }
private JsonObjectBuilder createDocumentObjectBuilder(DocumentDto documentDto) {
return Json.createObjectBuilder()
.add("create_date", documentDto.getCreateTimestamp())
.add("description", JsonUtil.nullable(documentDto.getDescription()))
.add("file_id", JsonUtil.nullable(documentDto.getFileId()))
.add("id", documentDto.getId())
.add("language", documentDto.getLanguage())
.add("shared", documentDto.getShared())
.add("title", documentDto.getTitle())
.add("update_date", documentDto.getUpdateTimestamp());
}
private static JsonArrayBuilder createTagsArrayBuilder(List<TagDto> tagDtoList) {
JsonArrayBuilder tags = Json.createArrayBuilder();
for (TagDto tagDto : tagDtoList) {
tags.add(Json.createObjectBuilder()
.add("id", tagDto.getId())
.add("name", tagDto.getName())
.add("color", tagDto.getColor()));
}
return tags;
}
} }

View File

@ -67,8 +67,8 @@ public class FileResource extends BaseResource {
* This resource accepts only multipart/form-data. * This resource accepts only multipart/form-data.
* @apiName PutFile * @apiName PutFile
* @apiGroup File * @apiGroup File
* @apiParam {String} id Document ID * @apiParam {String} [id] Document ID
* @apiParam {String} previousFileId ID of the file to replace by this new version * @apiParam {String} [previousFileId] ID of the file to replace by this new version
* @apiParam {String} file File data * @apiParam {String} file File data
* @apiSuccess {String} status Status OK * @apiSuccess {String} status Status OK
* @apiSuccess {String} id File ID * @apiSuccess {String} id File ID
@ -390,8 +390,8 @@ public class FileResource extends BaseResource {
* @api {get} /file/list Get files * @api {get} /file/list Get files
* @apiName GetFileList * @apiName GetFileList
* @apiGroup File * @apiGroup File
* @apiParam {String} id Document ID * @apiParam {String} [id] Document ID
* @apiParam {String} share Share ID * @apiParam {String} [share] Share ID
* @apiSuccess {Object[]} files List of files * @apiSuccess {Object[]} files List of files
* @apiSuccess {String} files.id ID * @apiSuccess {String} files.id ID
* @apiSuccess {String} files.processing True if the file is currently processing * @apiSuccess {String} files.processing True if the file is currently processing
@ -497,7 +497,6 @@ public class FileResource extends BaseResource {
* @apiName DeleteFile * @apiName DeleteFile
* @apiGroup File * @apiGroup File
* @apiParam {String} id File ID * @apiParam {String} id File ID
* @apiParam {String} share Share ID
* @apiSuccess {String} status Status OK * @apiSuccess {String} status Status OK
* @apiError (client) ForbiddenError Access denied * @apiError (client) ForbiddenError Access denied
* @apiError (client) NotFound File or document not found * @apiError (client) NotFound File or document not found

View File

@ -0,0 +1,318 @@
package com.sismics.docs.rest.util;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.sismics.docs.core.constant.Constants;
import com.sismics.docs.core.dao.UserDao;
import com.sismics.docs.core.dao.criteria.DocumentCriteria;
import com.sismics.docs.core.dao.dto.TagDto;
import com.sismics.docs.core.model.jpa.User;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.joda.time.format.DateTimeParser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
public class DocumentSearchCriteriaUtil {
private static final DateTimeParser YEAR_PARSER = DateTimeFormat.forPattern("yyyy").getParser();
private static final DateTimeParser MONTH_PARSER = DateTimeFormat.forPattern("yyyy-MM").getParser();
private static final DateTimeParser DAY_PARSER = DateTimeFormat.forPattern("yyyy-MM-dd").getParser();
private static final DateTimeParser[] DATE_PARSERS = new DateTimeParser[]{
YEAR_PARSER,
MONTH_PARSER,
DAY_PARSER};
private static final DateTimeFormatter YEAR_FORMATTER = new DateTimeFormatter(null, YEAR_PARSER);
private static final DateTimeFormatter MONTH_FORMATTER = new DateTimeFormatter(null, MONTH_PARSER);
private static final DateTimeFormatter DAY_FORMATTER = new DateTimeFormatter(null, DAY_PARSER);
private static final DateTimeFormatter DATES_FORMATTER = new DateTimeFormatterBuilder().append(null, DATE_PARSERS).toFormatter();
private static final String PARAMETER_WITH_MULTIPLE_VALUES_SEPARATOR = ",";
private static final String WORKFLOW_ME = "me";
/**
* Parse a query according to the specified syntax, eg.:
* tag:assurance tag:other before:2012 after:2011-09 shared:yes lang:fra thing
*
* @param search Search query
* @param allTagDtoList List of tags
* @return DocumentCriteria
*/
public static DocumentCriteria parseSearchQuery(String search, List<TagDto> allTagDtoList) {
DocumentCriteria documentCriteria = new DocumentCriteria();
if (Strings.isNullOrEmpty(search)) {
return documentCriteria;
}
String[] criteriaList = search.split(" +");
List<String> simpleQuery = new ArrayList<>();
List<String> fullQuery = new ArrayList<>();
for (String criteria : criteriaList) {
String[] params = criteria.split(":");
if (params.length != 2 || Strings.isNullOrEmpty(params[0]) || Strings.isNullOrEmpty(params[1])) {
// This is not a special criteria, do a fulltext search on it
fullQuery.add(criteria);
continue;
}
String paramName = params[0];
String paramValue = params[1];
switch (paramName) {
case "tag":
case "!tag":
parseTagCriteria(documentCriteria, paramValue, allTagDtoList, paramName.startsWith("!"));
break;
case "after":
case "before":
case "uafter":
case "ubefore":
parseDateCriteria(documentCriteria, paramValue, DATES_FORMATTER, paramName.startsWith("u"), paramName.endsWith("before"));
break;
case "uat":
case "at":
parseDateAtCriteria(documentCriteria, paramValue, params[0].startsWith("u"));
break;
case "shared":
documentCriteria.setShared(paramValue.equals("yes"));
break;
case "lang":
parseLangCriteria(documentCriteria, paramValue);
break;
case "mime":
documentCriteria.setMimeType(paramValue);
break;
case "by":
parseByCriteria(documentCriteria, paramValue);
break;
case "workflow":
documentCriteria.setActiveRoute(paramValue.equals(WORKFLOW_ME));
break;
case "simple":
simpleQuery.add(paramValue);
break;
case "full":
fullQuery.add(paramValue);
break;
case "title":
documentCriteria.getTitleList().add(paramValue);
break;
default:
fullQuery.add(criteria);
break;
}
}
documentCriteria.setSimpleSearch(Joiner.on(" ").join(simpleQuery));
documentCriteria.setFullSearch(Joiner.on(" ").join(fullQuery));
return documentCriteria;
}
/**
* Fill the document criteria with various possible parameters
*
* @param documentCriteria structure to be filled
* @param searchBy author
* @param searchCreatedAfter creation moment after
* @param searchCreatedBefore creation moment before
* @param searchFull full search
* @param searchLang lang
* @param searchMime mime type
* @param searchShared share state
* @param searchSimple search in
* @param searchTag tags or parent tags
* @param searchNotTag tags or parent tags to ignore
* @param searchTitle title
* @param searchUpdatedAfter update moment after
* @param searchUpdatedBefore update moment before
* @param searchWorkflow exiting workflow
* @param allTagDtoList list of existing tags
*/
public static void addHttpSearchParams(
DocumentCriteria documentCriteria,
String searchBy,
String searchCreatedAfter,
String searchCreatedBefore,
String searchFull,
String searchLang,
String searchMime,
Boolean searchShared,
String searchSimple,
String searchTag,
String searchNotTag,
String searchTitle,
String searchUpdatedAfter,
String searchUpdatedBefore,
String searchWorkflow,
List<TagDto> allTagDtoList
) {
if (searchBy != null) {
parseByCriteria(documentCriteria, searchBy);
}
if (searchCreatedAfter != null) {
parseDateCriteria(documentCriteria, searchCreatedAfter, DAY_FORMATTER, false, false);
}
if (searchCreatedBefore != null) {
parseDateCriteria(documentCriteria, searchCreatedBefore, DAY_FORMATTER, false, true);
}
if (searchFull != null) {
documentCriteria.setFullSearch(Joiner.on(" ").join(searchFull.split(PARAMETER_WITH_MULTIPLE_VALUES_SEPARATOR)));
}
if (searchLang != null) {
parseLangCriteria(documentCriteria, searchLang);
}
if (searchMime != null) {
documentCriteria.setMimeType(searchMime);
}
if ((searchShared != null) && searchShared) {
documentCriteria.setShared(true);
}
if (searchSimple != null) {
documentCriteria.setSimpleSearch(Joiner.on(" ").join(searchSimple.split(PARAMETER_WITH_MULTIPLE_VALUES_SEPARATOR)));
}
if (searchTitle != null) {
documentCriteria.getTitleList().addAll(Arrays.asList(searchTitle.split(PARAMETER_WITH_MULTIPLE_VALUES_SEPARATOR)));
}
if (searchTag != null) {
for (String tag : searchTag.split(PARAMETER_WITH_MULTIPLE_VALUES_SEPARATOR)) {
parseTagCriteria(documentCriteria, tag, allTagDtoList, false);
}
}
if (searchNotTag != null) {
for (String tag : searchNotTag.split(PARAMETER_WITH_MULTIPLE_VALUES_SEPARATOR)) {
parseTagCriteria(documentCriteria, tag, allTagDtoList, true);
}
}
if (searchUpdatedAfter != null) {
parseDateCriteria(documentCriteria, searchUpdatedAfter, DAY_FORMATTER, true, false);
}
if (searchUpdatedBefore != null) {
parseDateCriteria(documentCriteria, searchUpdatedBefore, DAY_FORMATTER, true, true);
}
if ((WORKFLOW_ME.equals(searchWorkflow))) {
documentCriteria.setActiveRoute(true);
}
}
private static void parseDateCriteria(DocumentCriteria documentCriteria, String value, DateTimeFormatter formatter, boolean isUpdated, boolean isBefore) {
try {
DateTime date = formatter.parseDateTime(value);
if (isBefore) {
if (isUpdated) {
documentCriteria.setUpdateDateMax(date.toDate());
} else {
documentCriteria.setCreateDateMax(date.toDate());
}
} else {
if (isUpdated) {
documentCriteria.setUpdateDateMin(date.toDate());
} else {
documentCriteria.setCreateDateMin(date.toDate());
}
}
} catch (IllegalArgumentException e) {
// Invalid date, returns no documents
documentCriteria.setCreateDateMin(new Date(0));
documentCriteria.setCreateDateMax(new Date(0));
}
}
private static void parseDateAtCriteria(DocumentCriteria documentCriteria, String value, boolean isUpdated) {
try {
switch (value.length()) {
case 10: {
DateTime date = DATES_FORMATTER.parseDateTime(value);
if (isUpdated) {
documentCriteria.setUpdateDateMin(date.toDate());
documentCriteria.setUpdateDateMax(date.plusDays(1).minusSeconds(1).toDate());
} else {
documentCriteria.setCreateDateMin(date.toDate());
documentCriteria.setCreateDateMax(date.plusDays(1).minusSeconds(1).toDate());
}
break;
}
case 7: {
DateTime date = MONTH_FORMATTER.parseDateTime(value);
if (isUpdated) {
documentCriteria.setUpdateDateMin(date.toDate());
documentCriteria.setUpdateDateMax(date.plusMonths(1).minusSeconds(1).toDate());
} else {
documentCriteria.setCreateDateMin(date.toDate());
documentCriteria.setCreateDateMax(date.plusMonths(1).minusSeconds(1).toDate());
}
break;
}
case 4: {
DateTime date = YEAR_FORMATTER.parseDateTime(value);
if (isUpdated) {
documentCriteria.setUpdateDateMin(date.toDate());
documentCriteria.setUpdateDateMax(date.plusYears(1).minusSeconds(1).toDate());
} else {
documentCriteria.setCreateDateMin(date.toDate());
documentCriteria.setCreateDateMax(date.plusYears(1).minusSeconds(1).toDate());
}
break;
}
default: {
// Invalid format, returns no documents
documentCriteria.setCreateDateMin(new Date(0));
documentCriteria.setCreateDateMax(new Date(0));
}
}
} catch (IllegalArgumentException e) {
// Invalid date, returns no documents
documentCriteria.setCreateDateMin(new Date(0));
documentCriteria.setCreateDateMax(new Date(0));
}
}
private static void parseTagCriteria(DocumentCriteria documentCriteria, String value, List<TagDto> allTagDtoList, boolean exclusion) {
List<TagDto> tagDtoList = TagUtil.findByName(value, allTagDtoList);
if (tagDtoList.isEmpty()) {
// No tag found, the request must return nothing
documentCriteria.getTagIdList().add(Lists.newArrayList(UUID.randomUUID().toString()));
} else {
List<String> tagIdList = Lists.newArrayList();
for (TagDto tagDto : tagDtoList) {
tagIdList.add(tagDto.getId());
List<TagDto> childrenTagDtoList = TagUtil.findChildren(tagDto, allTagDtoList);
for (TagDto childrenTagDto : childrenTagDtoList) {
tagIdList.add(childrenTagDto.getId());
}
}
if (exclusion) {
documentCriteria.getExcludedTagIdList().add(tagIdList);
} else {
documentCriteria.getTagIdList().add(tagIdList);
}
}
}
private static void parseLangCriteria(DocumentCriteria documentCriteria, String value) {
// New language criteria
if (Constants.SUPPORTED_LANGUAGES.contains(value)) {
documentCriteria.setLanguage(value);
} else {
// Unsupported language, returns no documents
documentCriteria.setLanguage(UUID.randomUUID().toString());
}
}
private static void parseByCriteria(DocumentCriteria documentCriteria, String value) {
User user = new UserDao().getActiveByUsername(value);
if (user == null) {
// This user doesn't exist, return nothing
documentCriteria.setCreatorId(UUID.randomUUID().toString());
} else {
// This user exists, search its documents
documentCriteria.setCreatorId(user.getId());
}
}
}

View File

@ -1,8 +1,9 @@
package com.sismics.docs.core.util; package com.sismics.docs.rest.util;
import com.sismics.docs.core.dao.dto.TagDto; import com.sismics.docs.core.dao.dto.TagDto;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -39,10 +40,10 @@ public class TagUtil {
* @return List of filtered tags * @return List of filtered tags
*/ */
public static List<TagDto> findByName(String name, List<TagDto> allTagDtoList) { public static List<TagDto> findByName(String name, List<TagDto> allTagDtoList) {
List<TagDto> tagDtoList = new ArrayList<>();
if (name.isEmpty()) { if (name.isEmpty()) {
return tagDtoList; return Collections.emptyList();
} }
List<TagDto> tagDtoList = new ArrayList<>();
name = name.toLowerCase(); name = name.toLowerCase();
for (TagDto tagDto : allTagDtoList) { for (TagDto tagDto : allTagDtoList) {
if (tagDto.getName().toLowerCase().startsWith(name)) { if (tagDto.getName().toLowerCase().startsWith(name)) {

View File

@ -50,11 +50,11 @@ curl -i -X POST -H "Cookie: auth_token=64085630-2ae6-415c-9a92-4b22c107eaa4" htt
## Document search syntax ## Document search syntax
The `/api/document/list` endpoint use a String `search` parameter. The `/api/document/list` endpoint use a String `search` parameter, useful when the query is entered by a human.
This parameter is split in segments using the space character (the other whitespace characters are not considered). This parameter is split in segments using the space character (the other whitespace characters are not considered).
If a segment contains exactly one colon (`:`), it will used as a field criteria (see bellow). If a segment contains exactly one colon (`:`), it will be used as a field criteria (see bellow).
In other cases (zero or more than one colon), the segment will be used as a search criteria for all fields including the document's files content. In other cases (zero or more than one colon), the segment will be used as a search criteria for all fields including the document's files content.
### Search fields ### Search fields
@ -69,7 +69,7 @@ If a search `VALUE` is considered invalid, the search result will be empty.
* `at:VALUE`: the document must have been created at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd` (for `yyyy` it must be the same year, for `yyyy-MM` the same month, for `yyyy-MM-dd` the same day) * `at:VALUE`: the document must have been created at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd` (for `yyyy` it must be the same year, for `yyyy-MM` the same month, for `yyyy-MM-dd` the same day)
* `before:VALUE`: the document must have been created before or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd` * `before:VALUE`: the document must have been created before or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd`
* `uafter:VALUE`: the document must have been last updated after or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd` * `uafter:VALUE`: the document must have been last updated after or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd`
* `at:VALUE`: the document must have been updated at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd` (for `yyyy` it must be the same year, for `yyyy-MM` the same month, for `yyyy-MM-dd` the same day) * `uat:VALUE`: the document must have been updated at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd` (for `yyyy` it must be the same year, for `yyyy-MM` the same month, for `yyyy-MM-dd` the same day)
* `ubefore:VALUE`: the document must have been updated before or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd` * `ubefore:VALUE`: the document must have been updated before or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd`
* Language * Language
* `lang:VALUE`: the document must be of the specified language (example: `en`) * `lang:VALUE`: the document must be of the specified language (example: `en`)

View File

@ -0,0 +1,41 @@
package com.sismics.docs.rest;
import com.sismics.docs.core.dao.UserDao;
import com.sismics.docs.core.model.jpa.User;
import com.sismics.util.context.ThreadLocalContext;
import com.sismics.util.jpa.EMF;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityTransaction;
import org.junit.After;
import org.junit.Before;
public abstract class BaseTransactionalTest {
@Before
public void setUp() {
// Initialize the entity manager
EntityManager em = EMF.get().createEntityManager();
ThreadLocalContext context = ThreadLocalContext.get();
context.setEntityManager(em);
em.getTransaction().begin();
}
@After
public void tearDown() {
ThreadLocalContext.get().getEntityManager().getTransaction().rollback();
}
protected User createUser(String userName) throws Exception {
UserDao userDao = new UserDao();
User user = new User();
user.setUsername(userName);
user.setPassword("12345678");
user.setEmail("toto@docs.com");
user.setRoleId("admin");
user.setStorageQuota(100_000L);
userDao.create(user, userName);
return user;
}
}

View File

@ -28,7 +28,7 @@ public class TestAppResource extends BaseJerseyTest {
@Test @Test
public void testAppResource() { public void testAppResource() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Check the application info // Check the application info
JsonObject json = target().path("/app").request() JsonObject json = target().path("/app").request()
@ -86,7 +86,7 @@ public class TestAppResource extends BaseJerseyTest {
@Test @Test
public void testLogResource() { public void testLogResource() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Check the logs (page 1) // Check the logs (page 1)
JsonObject json = target().path("/app/log") JsonObject json = target().path("/app/log")
@ -120,7 +120,7 @@ public class TestAppResource extends BaseJerseyTest {
@Test @Test
public void testGuestLogin() { public void testGuestLogin() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Try to login as guest // Try to login as guest
Response response = target().path("/user/login").request() Response response = target().path("/user/login").request()
@ -185,7 +185,7 @@ public class TestAppResource extends BaseJerseyTest {
@Test @Test
public void testSmtpConfiguration() { public void testSmtpConfiguration() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Get SMTP configuration // Get SMTP configuration
JsonObject json = target().path("/app/config_smtp").request() JsonObject json = target().path("/app/config_smtp").request()
@ -224,7 +224,7 @@ public class TestAppResource extends BaseJerseyTest {
@Test @Test
public void testInbox() { public void testInbox() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Create a tag // Create a tag
JsonObject json = target().path("/tag").request() JsonObject json = target().path("/tag").request()
@ -365,7 +365,7 @@ public class TestAppResource extends BaseJerseyTest {
// new LdifFileLoader(directoryService.getAdminSession(), new File(Resources.getResource("test.ldif").getFile()), null).execute(); // new LdifFileLoader(directoryService.getAdminSession(), new File(Resources.getResource("test.ldif").getFile()), null).execute();
// //
// // Login admin // // Login admin
// String adminToken = clientUtil.login("admin", "admin", false); // String adminToken = adminToken();
// //
// // Get the LDAP configuration // // Get the LDAP configuration
// JsonObject json = target().path("/app/config_ldap").request() // JsonObject json = target().path("/app/config_ldap").request()

View File

@ -273,6 +273,7 @@ public class TestDocumentResource extends BaseJerseyTest {
Assert.assertFalse(relations.getJsonObject(0).getBoolean("source")); Assert.assertFalse(relations.getJsonObject(0).getBoolean("source"));
Assert.assertEquals("My super title document 2", relations.getJsonObject(0).getString("title")); Assert.assertEquals("My super title document 2", relations.getJsonObject(0).getString("title"));
Assert.assertFalse(json.containsKey("files")); Assert.assertFalse(json.containsKey("files"));
Assert.assertEquals(file1Id, json.getString("file_id"));
// Get document 2 // Get document 2
json = target().path("/document/" + document2Id).request() json = target().path("/document/" + document2Id).request()
@ -285,6 +286,7 @@ public class TestDocumentResource extends BaseJerseyTest {
Assert.assertTrue(relations.getJsonObject(0).getBoolean("source")); Assert.assertTrue(relations.getJsonObject(0).getBoolean("source"));
Assert.assertEquals("My super title document 1", relations.getJsonObject(0).getString("title")); Assert.assertEquals("My super title document 1", relations.getJsonObject(0).getString("title"));
Assert.assertFalse(json.containsKey("files")); Assert.assertFalse(json.containsKey("files"));
Assert.assertEquals(file1Id, json.getString("file_id"));
// Create a tag // Create a tag
json = target().path("/tag").request() json = target().path("/tag").request()
@ -818,7 +820,7 @@ public class TestDocumentResource extends BaseJerseyTest {
@Test @Test
public void testCustomMetadata() { public void testCustomMetadata() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Login metadata1 // Login metadata1
clientUtil.createUser("metadata1"); clientUtil.createUser("metadata1");

View File

@ -25,7 +25,7 @@ public class TestGroupResource extends BaseJerseyTest {
@Test @Test
public void testGroupResource() { public void testGroupResource() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Create group hierarchy // Create group hierarchy
clientUtil.createGroup("g1"); clientUtil.createGroup("g1");

View File

@ -22,7 +22,7 @@ public class TestMetadataResource extends BaseJerseyTest {
@Test @Test
public void testMetadataResource() { public void testMetadataResource() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Get all metadata with admin // Get all metadata with admin
JsonObject json = target().path("/metadata") JsonObject json = target().path("/metadata")

View File

@ -22,7 +22,7 @@ public class TestRouteModelResource extends BaseJerseyTest {
@Test @Test
public void testRouteModelResource() { public void testRouteModelResource() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Login routeModel1 // Login routeModel1
clientUtil.createUser("routeModel1"); clientUtil.createUser("routeModel1");

View File

@ -27,7 +27,7 @@ public class TestRouteResource extends BaseJerseyTest {
String route1Token = clientUtil.login("route1"); String route1Token = clientUtil.login("route1");
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Change SMTP configuration to target Wiser // Change SMTP configuration to target Wiser
target().path("/app/config_smtp").request() target().path("/app/config_smtp").request()
@ -364,7 +364,7 @@ public class TestRouteResource extends BaseJerseyTest {
@Test @Test
public void testTagActions() { public void testTagActions() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Create an Approved tag // Create an Approved tag
JsonObject json = target().path("/tag").request() JsonObject json = target().path("/tag").request()

View File

@ -27,7 +27,7 @@ public class TestThemeResource extends BaseJerseyTest {
@Test @Test
public void testThemeResource() throws Exception { public void testThemeResource() throws Exception {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Get the stylesheet anonymously // Get the stylesheet anonymously
String stylesheet = target().path("/theme/stylesheet").request() String stylesheet = target().path("/theme/stylesheet").request()

View File

@ -37,7 +37,7 @@ public class TestUserResource extends BaseJerseyTest {
clientUtil.createUser("alice"); clientUtil.createUser("alice");
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// List all users // List all users
json = target().path("/user/list") json = target().path("/user/list")
@ -250,7 +250,7 @@ public class TestUserResource extends BaseJerseyTest {
clientUtil.createUser("admin_user1"); clientUtil.createUser("admin_user1");
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Check admin information // Check admin information
JsonObject json = target().path("/user").request() JsonObject json = target().path("/user").request()
@ -336,7 +336,7 @@ public class TestUserResource extends BaseJerseyTest {
@Test @Test
public void testTotp() { public void testTotp() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Create totp1 user // Create totp1 user
clientUtil.createUser("totp1"); clientUtil.createUser("totp1");
@ -425,7 +425,7 @@ public class TestUserResource extends BaseJerseyTest {
@Test @Test
public void testResetPassword() throws Exception { public void testResetPassword() throws Exception {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Change SMTP configuration to target Wiser // Change SMTP configuration to target Wiser
target().path("/app/config_smtp").request() target().path("/app/config_smtp").request()

View File

@ -26,7 +26,7 @@ public class TestVocabularyResource extends BaseJerseyTest {
String vocabulary1Token = clientUtil.login("vocabulary1"); String vocabulary1Token = clientUtil.login("vocabulary1");
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Get coverage vocabularies entries // Get coverage vocabularies entries
JsonObject json = target().path("/vocabulary/coverage").request() JsonObject json = target().path("/vocabulary/coverage").request()

View File

@ -24,7 +24,7 @@ public class TestWebhookResource extends BaseJerseyTest {
@Test @Test
public void testWebhookResource() { public void testWebhookResource() {
// Login admin // Login admin
String adminToken = clientUtil.login("admin", "admin", false); String adminToken = adminToken();
// Login webhook1 // Login webhook1
clientUtil.createUser("webhook1"); clientUtil.createUser("webhook1");

View File

@ -0,0 +1,492 @@
package com.sismics.docs.rest.util;
import com.sismics.docs.core.dao.TagDao;
import com.sismics.docs.core.dao.criteria.DocumentCriteria;
import com.sismics.docs.core.dao.criteria.TagCriteria;
import com.sismics.docs.core.dao.dto.TagDto;
import com.sismics.docs.core.model.jpa.Tag;
import com.sismics.docs.core.model.jpa.User;
import com.sismics.docs.rest.BaseTransactionalTest;
import com.sismics.util.mime.MimeType;
import org.apache.poi.ss.formula.functions.T;
import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class TestDocumentSearchCriteriaUtil extends BaseTransactionalTest {
@Test
public void testHttpParamsBy() throws Exception {
User user = createUser("user1");
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
"user1",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
Assert.assertEquals(documentCriteria.getCreatorId(), user.getId());
documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
"missing",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
Assert.assertNotNull(documentCriteria.getCreatorId());
}
@Test
public void testHttpParamsCreatedAfter() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
"2022-03-27",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
Assert.assertEquals(documentCriteria.getCreateDateMin(), new DateTime(2022, 3, 27, 0, 0, 0).toDate());
}
@Test
public void testHttpParamsCreatedBefore() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
"2022-03-27",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
Assert.assertEquals(documentCriteria.getCreateDateMax(), new DateTime(2022, 3, 27, 0, 0, 0).toDate());
}
@Test
public void testHttpParamsFull() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
"full",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
Assert.assertEquals(documentCriteria.getFullSearch(), "full");
}
@Test
public void testHttpParamsLang() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
"fra",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
Assert.assertEquals(documentCriteria.getLanguage(), "fra");
documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
"unknown",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
Assert.assertNotNull(documentCriteria.getLanguage());
Assert.assertNotEquals(documentCriteria.getLanguage(), "unknown");
}
@Test
public void testHttpParamsMime() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
MimeType.IMAGE_GIF,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
Assert.assertEquals(documentCriteria.getMimeType(), MimeType.IMAGE_GIF);
}
@Test
public void testHttpParamsShared() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
true,
null,
null,
null,
null,
null,
null,
null,
null
);
Assert.assertTrue(documentCriteria.getShared());
}
@Test
public void testHttpParamsSimple() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
null,
"simple",
null,
null,
null,
null,
null,
null,
null
);
Assert.assertEquals(documentCriteria.getSimpleSearch(), "simple");
}
@Test
public void testHttpParamsTag() throws Exception {
TagDao tagDao = new TagDao();
User user = createUser("user1");
Tag tag1 = new Tag();
tag1.setName("tag1");
tag1.setColor("#bbb");
tag1.setUserId(user.getId());
tagDao.create(tag1, user.getId());
Tag tag2 = new Tag();
tag2.setName("tag2");
tag2.setColor("#bbb");
tag2.setUserId(user.getId());
tagDao.create(tag2, user.getId());
Tag tag3 = new Tag();
tag3.setName("tag3");
tag3.setColor("#bbb");
tag3.setUserId(user.getId());
tag3.setParentId(tag2.getId());
tagDao.create(tag3, user.getId());
DocumentCriteria documentCriteria = new DocumentCriteria();
List<TagDto> allTagDtoList = tagDao.findByCriteria(new TagCriteria(), null);
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
null,
null,
"tag1",
null,
null,
null,
null,
null,
allTagDtoList
);
Assert.assertEquals(documentCriteria.getTagIdList(), List.of(Collections.singletonList(tag1.getId())));
documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
null,
null,
"tag2",
null,
null,
null,
null,
null,
allTagDtoList
);
Assert.assertEquals(documentCriteria.getTagIdList(), List.of(List.of(tag2.getId(), tag3.getId())));
}
@Test
public void testHttpParamsNotTag() throws Exception {
TagDao tagDao = new TagDao();
User user = createUser("user1");
Tag tag1 = new Tag();
tag1.setName("tag1");
tag1.setColor("#bbb");
tag1.setUserId(user.getId());
tagDao.create(tag1, user.getId());
Tag tag2 = new Tag();
tag2.setName("tag2");
tag2.setColor("#bbb");
tag2.setUserId(user.getId());
tagDao.create(tag2, user.getId());
Tag tag3 = new Tag();
tag3.setName("tag3");
tag3.setColor("#bbb");
tag3.setUserId(user.getId());
tag3.setParentId(tag2.getId());
tagDao.create(tag3, user.getId());
DocumentCriteria documentCriteria = new DocumentCriteria();
List<TagDto> allTagDtoList = tagDao.findByCriteria(new TagCriteria(), null);
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
null,
null,
null,
"tag1",
null,
null,
null,
null,
allTagDtoList
);
Assert.assertEquals(documentCriteria.getExcludedTagIdList(), List.of(Collections.singletonList(tag1.getId())));
documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
null,
null,
null,
"tag2",
null,
null,
null,
null,
allTagDtoList
);
Assert.assertEquals(documentCriteria.getExcludedTagIdList(), List.of(List.of(tag2.getId(), tag3.getId())));
}
@Test
public void testHttpParamsTitle() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
"title1,title2",
null,
null,
null,
null
);
Assert.assertEquals(documentCriteria.getTitleList(), Arrays.asList(new String[]{"title1", "title2"}));
}
@Test
public void testHttpParamsUpdatedAfter() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
"2022-03-27",
null,
null,
null
);
Assert.assertEquals(documentCriteria.getUpdateDateMin(), new DateTime(2022, 3, 27, 0, 0, 0).toDate());
}
@Test
public void testHttpParamsUpdatedBefore() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
"2022-03-27",
null,
null
);
Assert.assertEquals(documentCriteria.getUpdateDateMax(), new DateTime(2022, 3, 27, 0, 0, 0).toDate());
}
@Test
public void testHttpParamsWorkflow() {
DocumentCriteria documentCriteria = new DocumentCriteria();
DocumentSearchCriteriaUtil.addHttpSearchParams(
documentCriteria,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
"me",
null
);
Assert.assertTrue(documentCriteria.getActiveRoute());
}
}