001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package plugins.kernel.searchprovider; 020 021import icy.plugin.PluginDescriptor; 022import icy.util.StringUtil; 023 024import java.util.ArrayList; 025import java.util.List; 026 027/** 028 * @author Stephane 029 */ 030public class PluginSearchResultProducerHelper 031{ 032 public static class SearchWord 033 { 034 public final String word; 035 public final boolean mandatory; 036 public final boolean reject; 037 038 public SearchWord(String word) 039 { 040 super(); 041 042 if (word.startsWith("+")) 043 { 044 mandatory = true; 045 reject = false; 046 if (word.length() > 1) 047 this.word = word.substring(1); 048 else 049 this.word = ""; 050 } 051 else if (word.startsWith("+")) 052 { 053 mandatory = false; 054 reject = true; 055 if (word.length() > 1) 056 this.word = word.substring(1); 057 else 058 this.word = ""; 059 } 060 else 061 { 062 mandatory = false; 063 reject = false; 064 this.word = word; 065 } 066 } 067 068 public boolean isEmpty() 069 { 070 return StringUtil.isEmpty(word); 071 } 072 073 public int length() 074 { 075 return word.length(); 076 } 077 } 078 079 public static List<SearchWord> getSearchWords(String text) 080 { 081 final List<String> words = StringUtil.split(text); 082 final List<SearchWord> result = new ArrayList<SearchWord>(); 083 084 for (String w : words) 085 { 086 final SearchWord sw = new SearchWord(w); 087 if (!sw.isEmpty()) 088 result.add(sw); 089 } 090 091 return result; 092 } 093 094 public static boolean getShortSearch(List<SearchWord> words) 095 { 096 return (words.size() == 1) && (words.get(0).length() <= 2); 097 } 098 099 public static int searchInPlugin(PluginDescriptor plugin, List<SearchWord> words) 100 { 101 final boolean startWithOnly = PluginSearchResultProducerHelper.getShortSearch(words); 102 int result = 0; 103 104 // search for all word 105 for (SearchWord sw : words) 106 { 107 final int r = searchInPlugin(plugin, sw.word, startWithOnly); 108 109 // mandatory word not found ? --> reject 110 if ((r == 0) && sw.mandatory) 111 return 0; 112 // reject word found ? --> reject 113 else if ((r > 0) && sw.reject) 114 return 0; 115 116 result += r; 117 } 118 119 // return score 120 return result; 121 } 122 123 public static int searchInPlugin(PluginDescriptor plugin, String word, boolean startWithOnly) 124 { 125 if (plugin.getPluginClass() != null) 126 { 127 // we don't want abstract nor interface nor bundled plugin in results list 128 if (plugin.isAbstract() || plugin.isInterface()) 129 return 0; 130 // we don't want bundled plugin which are not actionable 131 if (plugin.isBundled() && !plugin.isActionable()) 132 return 0; 133 } 134 135 final String wordlc = word.toLowerCase(); 136 final String name = plugin.getName().toLowerCase(); 137 int ind; 138 139 ind = name.indexOf(wordlc); 140 if (ind >= 0) 141 { 142 // plugin name start with keyword --> highest priority result 143 if (ind == 0) 144 return 10; 145 // plugin name has a word starting by keyword --> high priority result 146 else if (name.charAt(ind - 1) == ' ') 147 return 9; 148 // don't allow partial match for short search 149 else if (startWithOnly) 150 return 0; 151 // name contains keyword --> high/medium priority result 152 else 153 return 8; 154 } 155 156 // more search... 157 if (!startWithOnly) 158 { 159 final String description = plugin.getDescription().toLowerCase(); 160 161 ind = description.indexOf(wordlc); 162 if (ind >= 0) 163 { 164 // plugin description start with keyword --> medium 165 if (ind == 0) 166 return 5; 167 // plugin description has a word starting by keyword --> medium/low priority result 168 else if (description.charAt(ind - 1) == ' ') 169 return 4; 170 // description contains keyword --> lowest priority 171 else 172 return 1; 173 } 174 } 175 176 // not found 177 return 0; 178 } 179}