Coverage Summary for Class: FilterMenu (org.kitodo.production.filters)
Class |
Method, %
|
Line, %
|
FilterMenu |
22,2%
(6/27)
|
15,5%
(20/129)
|
FilterMenu$1 |
0%
(0/1)
|
0%
(0/1)
|
Total |
21,4%
(6/28)
|
15,4%
(20/130)
|
/*
* (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/
package org.kitodo.production.filters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.faces.context.FacesContext;
import org.kitodo.production.enums.FilterPart;
import org.kitodo.production.enums.FilterString;
import org.kitodo.production.forms.CurrentTaskForm;
import org.kitodo.production.forms.ProcessForm;
import org.kitodo.production.forms.UserForm;
import org.kitodo.production.services.ServiceManager;
import org.kitodo.production.services.data.FilterService;
public class FilterMenu {
private static final int MAX_SUGGESTIONS = 15;
private static final List<FilterString> processCategories = Arrays.asList(
FilterString.TASK,
FilterString.TASKINWORK,
FilterString.TASKLOCKED,
FilterString.TASKOPEN,
FilterString.TASKDONE,
FilterString.PROJECT,
FilterString.ID,
FilterString.PARENTPROCESSID,
FilterString.PROCESS,
FilterString.BATCH,
FilterString.PROPERTY
);
private static final List<FilterString> taskCategories = Arrays.asList(
FilterString.TASK,
FilterString.TASKINWORK,
FilterString.TASKOPEN,
FilterString.PROJECT,
FilterString.ID,
FilterString.PROCESS,
FilterString.BATCH,
FilterString.PROPERTY
);
private static final List<String> userCategories = Arrays.asList(
"id:",
"name:",
"surname:",
"login:",
"ldapLogin:",
"active:",
"deleted:",
"location:",
"metadataLanguage:",
"withMassDownload:",
"configProductionDateShow:",
"tableSize:",
"language:"
);
private ProcessForm processForm = null;
private CurrentTaskForm taskForm = null;
private UserForm userForm = null;
private List<Suggestion> suggestions;
private final List<ParsedFilter> parsedFilters;
private String filterInEditMode;
/**
* Constructor of filter menu for processes.
*
* @param processForm instance of ProcessForm
*/
public FilterMenu(ProcessForm processForm) {
this.processForm = processForm;
suggestions = createSuggestionsForProcessCategory("");
parsedFilters = new ArrayList<>();
}
/**
* Constructor of filter menu for tasks.
*
* @param taskForm instance of CurrentTaskForm
*/
public FilterMenu(CurrentTaskForm taskForm) {
this.taskForm = taskForm;
suggestions = createSuggestionsForTaskCategory("");
parsedFilters = new ArrayList<>();
}
/**
* Constructor of filter menu for users.
*
* @param userForm instance of UserForm
*/
public FilterMenu(UserForm userForm) {
this.userForm = userForm;
suggestions = createSuggestionsForUserCategory("");
parsedFilters = new ArrayList<>();
}
/**
* Get list of suggestions.
*
* @return List of suggestion objects
*/
public List<Suggestion> getSuggestions() {
return suggestions;
}
/**
* Create suggestions based on a String passed from a {@code <p:remoteCommand/>}.
*/
public void updateSuggestions() {
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
updateSuggestions(params.get("input"));
}
/**
* Create suggestions based on the given input string.
*
* @param input String to get suggestions for
*/
public void updateSuggestions(String input) {
// remove quotation marks and minus
String strippedInput = input.replaceAll("^[\"-]+|\"$", "");
// determine the last part of the input
int lastColonIndex = strippedInput.lastIndexOf(":");
if (lastColonIndex == -1) {
// category should be suggested
if (Objects.nonNull(processForm)) {
suggestions = createSuggestionsForProcessCategory(input);
} else if (Objects.nonNull(taskForm)) {
suggestions = createSuggestionsForTaskCategory(input);
} else if (Objects.nonNull(userForm)) {
suggestions = createSuggestionsForUserCategory(input);
}
} else {
// at least one colon in the input string
String lastPart = input.substring(lastColonIndex + 1);
Pattern patternNextCategory = Pattern.compile("(?<= \\| )\\w?$");
Matcher matcherNextCategory = patternNextCategory.matcher(lastPart);
if (Objects.nonNull(processForm)) {
if (matcherNextCategory.find()) {
// strings ends with " | "
suggestions = createSuggestionsForProcessCategory(matcherNextCategory.group());
} else {
// process value should be suggested
Pattern patternPreviousCategory = Pattern.compile("\\w+:(?!.*:)");
Matcher matcherPreviousCategory = patternPreviousCategory.matcher(input);
String category = matcherPreviousCategory.find() ? matcherPreviousCategory.group() : "";
suggestions = createSuggestionsForProcessValue(checkFilterCategory(category, processCategories), lastPart);
}
} else if (Objects.nonNull(taskForm)) {
if (matcherNextCategory.find()) {
// strings ends with " | "
suggestions = createSuggestionsForTaskCategory(matcherNextCategory.group());
} else {
// process/task value should be suggested
Pattern patternPreviousCategory = Pattern.compile("\\w+:(?!.*:)");
Matcher matcherPreviousCategory = patternPreviousCategory.matcher(input);
String category = matcherPreviousCategory.find() ? matcherPreviousCategory.group() : "";
suggestions = createSuggestionsForTaskValue(checkFilterCategory(category, taskCategories), lastPart);
}
} else if (Objects.nonNull(userForm)) {
if (matcherNextCategory.find()) {
// strings ends with " | "
suggestions = createSuggestionsForUserCategory(matcherNextCategory.group());
}
}
}
}
private List<Suggestion> filterSuggestionsForCategory(String input, List<FilterString> suggestions) {
return suggestions.stream()
.filter(filterString -> filterString.getFilterEnglish().startsWith(input.toLowerCase())
|| filterString.getFilterGerman().startsWith(input.toLowerCase()))
.map(filterString -> new Suggestion(input, filterString.getFilterEnglish(), FilterPart.CATEGORY))
.collect(Collectors.toList());
}
private List<Suggestion> createSuggestionsForProcessCategory(String input) {
return filterSuggestionsForCategory(input, processCategories);
}
private List<Suggestion> createSuggestionsForTaskCategory(String input) {
return filterSuggestionsForCategory(input, taskCategories);
}
private List<Suggestion> createSuggestionsForProcessValue(FilterString category, String input) {
List<Suggestion> suggestions = new ArrayList<>();
if (Objects.isNull(category)) {
return suggestions;
}
FilterService filterService = ServiceManager.getFilterService();
switch (category) {
case TASK:
case TASKINWORK:
case TASKLOCKED:
case TASKOPEN:
case TASKDONE:
case TASKDONETITLE:
suggestions.addAll(createStringSuggestionsMatchingInput(input, filterService.initStepTitles(), FilterPart.VALUE));
break;
case PROJECT:
suggestions.addAll(createStringSuggestionsMatchingInput(input, filterService.initProjects(), FilterPart.VALUE));
break;
case PROPERTY:
suggestions.addAll(createStringSuggestionsMatchingInput(input,
filterService.initProcessPropertyTitles(), FilterPart.VALUE));
break;
default:
// Do nothing
break;
}
return suggestions;
}
private List<Suggestion> createSuggestionsForTaskValue(FilterString category, String input) {
List<Suggestion> suggestions = new ArrayList<>();
if (Objects.isNull(category)) {
return suggestions;
}
FilterService filterService = ServiceManager.getFilterService();
switch (category) {
case TASK:
case TASKINWORK:
case TASKOPEN:
suggestions.addAll(createStringSuggestionsMatchingInput(input, filterService.initStepTitles(), FilterPart.VALUE));
break;
case PROJECT:
suggestions.addAll(createStringSuggestionsMatchingInput(input, filterService.initProjects(), FilterPart.VALUE));
break;
case PROPERTY:
suggestions.addAll(createStringSuggestionsMatchingInput(input,
filterService.initProcessPropertyTitles(), FilterPart.VALUE));
break;
default:
// Do nothing
break;
}
return suggestions;
}
private List<Suggestion> createSuggestionsForUserCategory(String input) {
return createStringSuggestionsMatchingInput(input, userCategories, FilterPart.CATEGORY);
}
private List<Suggestion> createStringSuggestionsMatchingInput(String input, List<String> suggestions, FilterPart filterPart) {
return suggestions.stream()
.filter(suggestion -> suggestion.startsWith(input))
.limit(MAX_SUGGESTIONS)
.map(suggestion -> new Suggestion(input, suggestion, filterPart))
.collect(Collectors.toList());
}
/**
* Check if the category passed as String matches a FilterString.
*
* @param categoryInput as String
* @return FilterString matching the given String
*/
private FilterString checkFilterCategory(String categoryInput, List<FilterString> categories) {
return categories.stream()
.filter(f -> f.getFilterGerman().equals(categoryInput.toLowerCase())
|| f.getFilterEnglish().equals(categoryInput.toLowerCase()))
.findFirst().orElse(null);
}
/**
* Get parsedFilters.
*
* @return value of parsedFilters
*/
public List<ParsedFilter> getParsedFilters() {
return parsedFilters;
}
/**
* Get filterInEditMode.
*
* @return value of filterInEditMode
*/
public String getFilterInEditMode() {
return filterInEditMode;
}
/**
* Set filterInEditMode.
*
* @param filterInEditMode as java.lang.String
*/
public void setFilterInEditMode(String filterInEditMode) {
this.filterInEditMode = filterInEditMode;
}
public void addParsedFilter(String plainFilter) {
parsedFilters.add(new ParsedFilter(plainFilter));
}
/**
* Remove the given filter from the list of ParsedFilters.
* This method does not take care of the actual plain filter used for filtering.
*
* @param filterToBeRemoved as ParsedFilter object
*/
public void removeParsedFilter(ParsedFilter filterToBeRemoved) {
parsedFilters.remove(filterToBeRemoved);
}
/**
* Parse the given filter string.
* The given string is split into separate filters before being transformed into ParsedFilter objects.
*
* @param filterString String containing one or multiple filters
*/
public void parseFilters(String filterString) {
parsedFilters.clear();
List<String> plainFilters = List.of(filterString.split(" ?\"| (?=\\|)|(?<=\\|) "));
for (String plainFilter : plainFilters) {
if (plainFilter.replaceAll("\\s", "").length() > 0) {
parsedFilters.add(new ParsedFilter(plainFilter));
}
}
}
/**
* Submit the entered filters and apply them.
*/
public void submitFilters() {
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
filterInEditMode = params.get("input");
if (filterInEditMode.length() > 0) {
addParsedFilter(filterInEditMode);
filterInEditMode = "";
updateSuggestions("");
}
updateFilters();
}
/**
* Remove the given filter.
*
* @param filterToBeRemoved as ParsedFilter object
*/
public void removeFilter(ParsedFilter filterToBeRemoved) {
removeParsedFilter(filterToBeRemoved);
updateFilters();
}
/**
* Remove the filter passed in the request.
* The filter can be passed as plain filter string from a {@code <p:remoteCommand/>} as request parameter.
*/
public void removeFilter() {
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
removeFilter(new ParsedFilter(params.get("plainFilter")));
}
/**
* Build plain filter string from parsed filters and set filter in form class.
*/
public void updateFilters() {
StringBuilder newFilter = new StringBuilder();
for (ParsedFilter parsedFilter : parsedFilters) {
if (newFilter.length() > 0) {
newFilter.append(" ");
}
newFilter.append(parsedFilter.getPlainFilter());
}
if (Objects.nonNull(processForm)) {
processForm.setFilter(newFilter.toString());
} else if (Objects.nonNull(taskForm)) {
taskForm.setFilter(newFilter.toString());
} else if (Objects.nonNull(userForm)) {
userForm.setFilter(newFilter.toString());
}
}
}