/* *------------------------------------------------------------------------------ * Copyright (C) 2006-2015 University of Dundee. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.agents.util.finder; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.openmicroscopy.shoola.util.CommonsLangUtils; import org.openmicroscopy.shoola.agents.dataBrowser.view.SearchComponent; import org.openmicroscopy.shoola.agents.util.SelectionWizard; import org.openmicroscopy.shoola.agents.util.ViewerSorter; import org.openmicroscopy.shoola.agents.util.ui.UserManagerDialog; import org.openmicroscopy.shoola.env.LookupNames; import omero.gateway.SecurityContext; import omero.gateway.model.SearchResultCollection; import omero.gateway.model.SearchParameters; import omero.gateway.model.SearchScope; import org.openmicroscopy.shoola.env.ui.UserNotifier; import org.openmicroscopy.shoola.util.ui.IconManager; import org.openmicroscopy.shoola.util.ui.UIUtilities; import org.openmicroscopy.shoola.util.ui.search.GroupContext; import org.openmicroscopy.shoola.util.ui.search.SearchContext; import org.openmicroscopy.shoola.util.ui.search.SearchHelp; import org.openmicroscopy.shoola.util.ui.search.SearchUtil; import omero.gateway.model.DataObject; import omero.gateway.model.DatasetData; import omero.gateway.model.ExperimenterData; import omero.gateway.model.GroupData; import omero.gateway.model.ImageData; import omero.gateway.model.PlateData; import omero.gateway.model.ProjectData; import omero.gateway.model.ScreenData; import omero.gateway.model.TagAnnotationData; import omero.gateway.model.WellData; /** * The class actually managing the search. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * @since OME3.0 */ public class AdvancedFinder extends SearchComponent implements Finder, PropertyChangeListener { /** The default title of the notification message. */ private static final String TITLE = "Search"; /** Reference to the component handling data. */ private FinderLoader loader; /** One of the constants defined by this class. */ private int state; /** Collection of selected users. */ private Map<Long, ExperimenterData> users; /** The collection of tags. */ private Collection tags; /** Host the result per group.*/ private SearchResultCollection results = new SearchResultCollection(); /** The identifier of the group.*/ private long groupId; /** The components used to sort the nodes.*/ private ViewerSorter sorter; /** The display mode e.g. Experimenter/Group.*/ private int displayMode; /** * Determines the scope of the search. * * @param value The value to convert. * @return See above. */ private SearchScope convertScope(int value) { switch (value) { case SearchContext.TEXT_ANNOTATION: return SearchScope.ANNOTATION; case SearchContext.TAGS: return SearchScope.ANNOTATION; case SearchContext.URL_ANNOTATION: return SearchScope.ANNOTATION; case SearchContext.FILE_ANNOTATION: return SearchScope.ANNOTATION; case SearchContext.NAME: return SearchScope.NAME; case SearchContext.DESCRIPTION: return SearchScope.DESCRIPTION; case SearchContext.ANNOTATION: return SearchScope.ANNOTATION; default: return null; } } /** * Determines the type of the search. * * @param value The value to convert. * @return See above. */ private Class<? extends DataObject> convertType(int value) { switch (value) { case SearchContext.DATASETS: return DatasetData.class; case SearchContext.PROJECTS: return ProjectData.class; case SearchContext.IMAGES: return ImageData.class; case SearchContext.SCREENS: return ScreenData.class; case SearchContext.PLATES: return PlateData.class; case SearchContext.WELLS: return WellData.class; default: return null; } } /** * Converts the UI context into a context to search for. * * @param ctx The value to convert. */ private void handleSearchContext(SearchContext ctx) { String query = ctx.getQuery(); UserNotifier un = FinderFactory.getRegistry().getUserNotifier(); Timestamp start = ctx.getStartTime(); Timestamp end = ctx.getEndTime(); if (start != null && end != null && start.after(end)) { un.notifyInfo(TITLE, "The selected time interval is not valid."); return; } if (CommonsLangUtils.isEmpty(query) && start == null && end == null) { un.notifyInfo(TITLE, "Please enter a term to search for " + "or a valid time interval."); return; } List<Integer> context = ctx.getContext(); if (context == null || context.size() == 0) { context = new ArrayList<Integer>(); context.add(SearchContext.CUSTOMIZED); } Set<SearchScope> scope = new HashSet<SearchScope>(); Iterator i = context.iterator(); SearchScope v; while (i.hasNext()) { v = convertScope((Integer) i.next()); if (v != null) scope.add(v); } List<Class<? extends DataObject>> types = new ArrayList<Class<? extends DataObject>>(); i = ctx.getType().iterator(); Class<? extends DataObject> k; while (i.hasNext()) { k = convertType((Integer) i.next()); if (k != null) types.add(k); } SearchParameters searchContext = new SearchParameters(scope, types, query); searchContext.setTimeInterval(start, end, ctx.getTimeType()); searchContext.setUserId(ctx.getSelectedOwner()); SecurityContext secCtx; if (ctx.getSelectedGroup() == GroupContext.ALL_GROUPS_ID) { secCtx = new SecurityContext( FinderFactory.getUserDetails().getGroupId()); searchContext.setGroupId(SearchParameters.ALL_GROUPS_ID); } else { secCtx = new SecurityContext(ctx.getSelectedGroup()); searchContext.setGroupId(ctx.getSelectedGroup()); } loader = new AdvancedFinderLoader(this, secCtx, searchContext); loader.load(); state = Finder.SEARCH; setSearchEnabled(-1); } /** Loads the tags. */ private void loadTags() { if (tags == null) { List<SecurityContext> l = new ArrayList<SecurityContext>(); Iterator<GroupData> i = groups.iterator(); while (i.hasNext()) { l.add(new SecurityContext(i.next().getId())); } TagsLoader loader = new TagsLoader(this, l); loader.load(); } else setExistingTags(tags); } /** * Handles the selection. * * @param selected The selected tags. */ private void handleTagsSelection(Collection selected) { List<String> toAdd = new ArrayList<String>(); if (selected == null || selected.size() == 0) { setTerms(toAdd); return; } Iterator i = selected.iterator(); TagAnnotationData tag; String value; while (i.hasNext()) { tag = (TagAnnotationData) i.next(); value = tag.getTagValue(); if (value.contains(SearchUtil.SPACE_SEPARATOR)) { toAdd.add(SearchUtil.QUOTE_SEPARATOR+value+ SearchUtil.QUOTE_SEPARATOR); } else toAdd.add(value); } setTerms(toAdd); } /** * Creates a new instance. * * @param groups The available groups. */ AdvancedFinder(Collection<GroupData> groups) { //sort displayMode = LookupNames.EXPERIMENTER_DISPLAY; sorter = new ViewerSorter(); List<GroupData> l = sorter.sort(groups); initialize(l); addPropertyChangeListener(SEARCH_PROPERTY, this); addPropertyChangeListener(CANCEL_SEARCH_PROPERTY, this); users = new HashMap<Long, ExperimenterData>(); } /** * Brings up the <code>Help</code> dialog. * @see #help(String) */ protected void help(String url) { if (CommonsLangUtils.isBlank(url)) return; SearchHelp help = new SearchHelp(FinderFactory.getRefFrame(), url); UIUtilities.centerAndShow(help); if (help.hasError()) { FinderFactory.getRegistry().getUserNotifier() .notifyError( "Could not open web browser", "Please open your web browser and go to page: " + url); } } /** * Implemented as specified by {@link Finder} I/F * @see Finder#cancel() */ public void cancel() { if (loader != null) loader.cancel(); results.clear(); state = DISCARDED; } /** * Implemented as specified by {@link Finder} I/F * @see Finder#getState() */ public int getState() { return state; } /** * Implemented as specified by {@link Finder} I/F * @see Finder#dispose() */ public void dispose() { setSearchEnabled(-1); setVisible(false); cancel(); } /** * Implemented as specified by {@link Finder} I/F * @see Finder#setStatus(String, boolean) */ public void setStatus(String text, boolean status) { if (text == null) text = ""; setSearchEnabled(text, status); } /** * Implemented as specified by {@link Finder} I/F * @see Finder#setResult(SearchResultCollection) */ public void setResult(SearchResultCollection result) { if (result.isError()) { String msg = ""; switch (result.getError()) { case SearchResultCollection.GENERAL_ERROR: msg = "Invalid search expression"; break; case SearchResultCollection.TOO_MANY_RESULTS_ERROR: msg = "Too many results, please refine your search criteria."; break; case SearchResultCollection.TOO_MANY_CLAUSES: msg = "Please try to narrow down your query. The wildcard matched too many terms."; break; } UserNotifier un = FinderFactory.getRegistry().getUserNotifier(); un.notifyError("Search error", msg); setSearchEnabled(-1); return; } results = result; setSearchEnabled(result.size()); firePropertyChange(RESULTS_FOUND_PROPERTY, null, results); } /** * Implemented as specified by {@link Finder} I/F * @see Finder#setExistingTags(Collection) */ public void setExistingTags(Collection tags) { this.tags = tags; if (tags == null || tags.size() == 0) { UserNotifier un = FinderFactory.getRegistry().getUserNotifier(); un.notifyInfo("Existing Tags", "No existing tags to search by."); return; } IconManager icons = IconManager.getInstance(); String title = "Filter By Tags"; String text = "Select the Tags to filter by."; Collection selected = new ArrayList<TagAnnotationData>(); Iterator i = tags.iterator(); TagAnnotationData tag; List<String> l = getTerms(); Collection available = new ArrayList<TagAnnotationData>(); while (i.hasNext()) { tag = (TagAnnotationData) i.next(); if (l.contains(tag.getTagValue())) selected.add(tag); else available.add(tag); } SelectionWizard wizard = new SelectionWizard( FinderFactory.getRefFrame(), available, selected, TagAnnotationData.class, false, FinderFactory.getUserDetails()); wizard.setGroups(groups); wizard.setTitle(title, text, icons.getIcon(IconManager.TAG_48)); wizard.addPropertyChangeListener(this); UIUtilities.centerAndShow(wizard); } /** * Sets the current tags. * * @param groupId The identifier of the group. */ public void setCurrentGroup(long groupId) { if (this.groupId == groupId) return; this.groupId = groupId; tags = null; } /** * Resets the component after switching users. * * @param groups The collection of groups to handle. */ public void reset(Collection<GroupData> groups) { sorter = new ViewerSorter(); this.groups = sorter.sort(groups); users.clear(); results.clear(); if (tags != null) tags.clear(); tags = null; groupsContext.clear(); addResult(null, true); uiDelegate.reset(); } /** * Sets the display mode e.g. Group Display * * @param displayMode The value to set. */ public void setDisplayMode(int displayMode) { this.displayMode = displayMode; } /** * Reacts to the property fired by the <code>SearchComponent</code> * @see PropertyChangeListener#propertyChange(PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent evt) { String name = evt.getPropertyName(); if (SEARCH_PROPERTY.equals(name)) { SearchContext ctx = (SearchContext) evt.getNewValue(); if (ctx == null) return; handleSearchContext(ctx); } else if (CANCEL_SEARCH_PROPERTY.equals(name)) { cancel(); } else if (UserManagerDialog.USER_SWITCH_PROPERTY.equals(name)) { Map m = (Map) evt.getNewValue(); if (m == null) return; Iterator i = m.keySet().iterator(); List<ExperimenterData> l; ExperimenterData exp; Iterator<ExperimenterData> j; while (i.hasNext()) { l = (List<ExperimenterData>) m.get(i.next()); j = l.iterator(); while (j.hasNext()) { exp = j.next(); users.put(exp.getId(), exp); } //uiValue += value; } //setUserString(uiValue); } else if (SelectionWizard.SELECTED_ITEMS_PROPERTY.equals(name)) { Map m = (Map) evt.getNewValue(); if (m == null || m.size() != 1) return; Set set = m.entrySet(); Entry entry; Iterator i = set.iterator(); Class type; while (i.hasNext()) { entry = (Entry) i.next(); type = (Class) entry.getKey(); handleTagsSelection( (Collection) entry.getValue()); } } } }