package org.ovirt.engine.ui.uicommonweb.models.autocomplete; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import org.ovirt.engine.core.compat.StringHelper; import org.ovirt.engine.core.searchbackend.ISyntaxChecker; import org.ovirt.engine.core.searchbackend.SyntaxChecker; import org.ovirt.engine.core.searchbackend.SyntaxContainer; import org.ovirt.engine.core.searchbackend.SyntaxError; import org.ovirt.engine.core.searchbackend.SyntaxObjectType; import org.ovirt.engine.ui.uicommonweb.StringConstants; import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel; import org.ovirt.engine.ui.uicompat.ObservableCollection; public class SearchSuggestModel extends SearchableListModel { private final String[] itemsToIgnore = { "monitor-desktop", //$NON-NLS-1$ SyntaxChecker.PAGE, SyntaxChecker.SORTBY, SyntaxChecker.SORTDIR_ASC, SyntaxChecker.SORTDIR_DESC}; //Exceptions that are potentially matched by items to ignore but are valid. private final List<String> exceptions = Arrays.asList("DESCRIPTION"); //$NON-NLS-1$ @Override public List getItems() { return (List) super.getItems(); } public void setItems(List value) { super.setItems(value); } private String privatePrefix; public String getPrefix() { return privatePrefix; } public void setPrefix(String value) { privatePrefix = value; } /** * Gets or sets an array specifying which options will be filtered out from suggestion. */ private String[] privateFilter; public String[] getFilter() { return privateFilter; } public void setFilter(String[] value) { privateFilter = value; } private String[] searchObjectFilter; public String[] getSearchObjectFilter() { return searchObjectFilter; } public void setSearchObjectFilter(String[] value) { searchObjectFilter = value; } public SearchSuggestModel() { setItems(new ObservableCollection<>()); setIsTimerDisabled(true); } @Override protected void searchStringChanged() { super.searchStringChanged(); getSearchCommand().execute(); } @Override protected void syncSearch() { super.syncSearch(); updateOptionsAsync(getPrefix() + getSearchString()); } public void updateOptionsAsync(String search) { getItems().clear(); ISyntaxChecker syntaxChecker = getConfigurator().getSyntaxChecker(); if (syntaxChecker == null) { return; } SyntaxContainer syntax = syntaxChecker.getCompletion(search); int lastHandledIndex = syntax.getLastHandledIndex(); String pf = search.substring(0, lastHandledIndex); String notHandled = search.substring(lastHandledIndex); String[] suggestedItems = syntax.getCompletionArray(); // Ensure that filtered search objects will invalidate the whole search query if (getSearchObjectFilter() != null && syntax.getState() != SyntaxObjectType.BEGIN) { for (String value : getSearchObjectFilter()) { if (pf.toLowerCase().equals(value.toLowerCase()) || pf.toLowerCase().startsWith(value.toLowerCase() + ":") || containsWithItemsToIgnore(pf)) { //$NON-NLS-1$ addSuggestItem("", SuggestItemPartType.Valid, search, SuggestItemPartType.Erroneous); //$NON-NLS-1$ return; } } } if (syntax.getError() == SyntaxError.NO_ERROR) { List<String> actualItems = new ArrayList<>(Arrays.asList(suggestedItems)); // Filter search object suggestions if (getSearchObjectFilter() != null && syntax.getState() == SyntaxObjectType.BEGIN) { for (String value : getSearchObjectFilter()) { for (String item : suggestedItems) { if (item.toLowerCase().equals(value.toLowerCase())) { actualItems.remove(item); } } } // Ensure that empty search suggestion list invalidates the search query if (actualItems.isEmpty()) { addSuggestItem("", SuggestItemPartType.Valid, search, SuggestItemPartType.Erroneous); //$NON-NLS-1$ return; } } for (String item : actualItems) { // Apply filter if (getFilter() != null) { boolean skipItem = false; for (String value : getFilter()) { if (Objects.equals(value.toLowerCase(), item.toLowerCase())) { skipItem = true; break; } } if (skipItem) { continue; } } String space = ""; //$NON-NLS-1$ if ((pf.length() > 0) && !pf.substring(pf.length() - 1, pf.length() - 1 + 1).equals(".") //$NON-NLS-1$ && !".".equals(item)) { //$NON-NLS-1$ space = StringConstants.SPACE; } // Patch: monitor-desktop if (!inItemsToIgnore(item)) { addSuggestItem(StringHelper.trimEnd(pf), SuggestItemPartType.Valid, space + item.trim(), SuggestItemPartType.New); } } } else { addSuggestItem(pf, SuggestItemPartType.Valid, notHandled, SuggestItemPartType.Erroneous); } } private boolean containsWithItemsToIgnore(String pf) { for (String item: itemsToIgnore) { if (pf.toUpperCase().contains(StringConstants.SPACE + item.trim().toUpperCase())) { for (String exception: exceptions) { if (pf.toUpperCase().contains(exception)) { return false; } } return true; } } return false; } private boolean inItemsToIgnore(String actualItem) { if (actualItem != null) { for (String item: itemsToIgnore) { if (item.equalsIgnoreCase(actualItem.trim())) { return true; } } } return false; } private void addSuggestItem(String firstPart, SuggestItemPartType firstPartType, String secondPart, SuggestItemPartType secondPartType) { SuggestItemPartModel tempVar = new SuggestItemPartModel(); tempVar.setPartString(firstPart); tempVar.setPartType(firstPartType); SuggestItemPartModel tempVar2 = new SuggestItemPartModel(); tempVar2.setPartString(secondPart); tempVar2.setPartType(secondPartType); ArrayList<SuggestItemPartModel> parts = new ArrayList<>(Arrays.asList(new SuggestItemPartModel[]{tempVar, tempVar2})); getItems().add(parts); } @Override protected void onSelectedItemChanged() { super.onSelectedItemChanged(); List selectedItem = (List) getSelectedItem(); if (selectedItem != null) { ArrayList<String> items = new ArrayList<>(); for (Object item : selectedItem) { SuggestItemPartModel i = (SuggestItemPartModel) item; items.add(i.getPartString()); } String searchString = StringHelper.join("", items.toArray(new String[] {})); //$NON-NLS-1$ // If there prefix exist, don't transfer it back as a part of search string. if (getPrefix() != null) { searchString = searchString.substring(getPrefix().length()); } setSearchString(searchString); } } @Override protected String getListName() { return "SearchSuggestModel"; //$NON-NLS-1$ } }