1 /* 2 * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 package com.sun.hotspot.igv.view; 25 26 import com.sun.hotspot.igv.data.InputGraph; 27 import com.sun.hotspot.igv.data.InputNode; 28 import com.sun.hotspot.igv.data.Properties; 29 import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher; 30 import com.sun.hotspot.igv.data.services.InputGraphProvider; 31 import com.sun.hotspot.igv.util.LookupHistory; 32 import java.util.HashSet; 33 import java.util.List; 34 import java.util.Set; 35 import java.util.regex.Pattern; 36 import org.netbeans.spi.quicksearch.SearchProvider; 37 import org.netbeans.spi.quicksearch.SearchRequest; 38 import org.netbeans.spi.quicksearch.SearchResponse; 39 import org.openide.DialogDisplayer; 40 import org.openide.NotifyDescriptor; 41 import org.openide.NotifyDescriptor.Message; 42 43 /** 44 * 45 * @author Thomas Wuerthinger 46 */ 47 public class NodeQuickSearch implements SearchProvider { 48 49 private static final String DEFAULT_PROPERTY = "name"; 50 51 /** 52 * Method is called by infrastructure when search operation was requested. 53 * Implementors should evaluate given request and fill response object with 54 * apropriate results 55 * 56 * @param request Search request object that contains information what to search for 57 * @param response Search response object that stores search results. Note that it's important to react to return value of SearchResponse.addResult(...) method and stop computation if false value is returned. 58 */ 59 @Override evaluate(SearchRequest request, SearchResponse response)60 public void evaluate(SearchRequest request, SearchResponse response) { 61 String query = request.getText(); 62 if (query.trim().isEmpty()) { 63 return; 64 } 65 66 final String[] parts = query.split("=", 2); 67 68 String name; 69 String value; 70 71 if (parts.length == 1) { 72 name = DEFAULT_PROPERTY; 73 value = ".*" + Pattern.quote(parts[0]) + ".*"; 74 } else { 75 name = parts[0]; 76 value = parts[1]; 77 } 78 79 if (value.isEmpty()) { 80 value = ".*"; 81 } 82 83 final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class); 84 if (p != null && p.getGraph() != null) { 85 InputGraph matchGraph = p.getGraph(); 86 // Search the current graph 87 List<InputNode> matches = findMatches(name, value, p.getGraph(), response); 88 if (matches == null) { 89 // See if the it hits in a later graph 90 for (InputGraph graph : p.searchForward()) { 91 matches = findMatches(name, value, graph, response); 92 if (matches != null) { 93 matchGraph = graph; 94 break; 95 } 96 } 97 } 98 if (matches == null) { 99 // See if it hits in a earlier graph 100 for (InputGraph graph : p.searchBackward()) { 101 matches = findMatches(name, value, graph, response); 102 if (matches != null) { 103 matchGraph = graph; 104 break; 105 } 106 } 107 } 108 109 if (matches != null) { 110 final Set<InputNode> set = new HashSet<>(matches); 111 final InputGraph theGraph = p.getGraph() != matchGraph ? matchGraph : null; 112 response.addResult(new Runnable() { 113 @Override 114 public void run() { 115 final EditorTopComponent comp = EditorTopComponent.getActive(); 116 if (comp != null) { 117 if (theGraph != null) { 118 comp.getDiagramModel().selectGraph(theGraph); 119 } 120 comp.setSelectedNodes(set); 121 comp.requestActive(); 122 } 123 } 124 }, 125 "All " + matches.size() + " matching nodes (" + name + "=" + value + ")" + (theGraph != null ? " in " + theGraph.getName() : "") 126 ); 127 128 // Single matches 129 for (final InputNode n : matches) { 130 response.addResult(new Runnable() { 131 @Override 132 public void run() { 133 final EditorTopComponent comp = EditorTopComponent.getActive(); 134 if (comp != null) { 135 final Set<InputNode> tmpSet = new HashSet<>(); 136 tmpSet.add(n); 137 if (theGraph != null) { 138 comp.getDiagramModel().selectGraph(theGraph); 139 } 140 comp.setSelectedNodes(tmpSet); 141 comp.requestActive(); 142 } 143 } 144 }, 145 n.getProperties().get(name) + " (" + n.getId() + " " + n.getProperties().get("name") + ")" + (theGraph != null ? " in " + theGraph.getName() : "") 146 ); 147 } 148 } 149 } else { 150 System.out.println("no input graph provider!"); 151 } 152 } 153 findMatches(String name, String value, InputGraph inputGraph, SearchResponse response)154 private List<InputNode> findMatches(String name, String value, InputGraph inputGraph, SearchResponse response) { 155 try { 156 RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(name, value, Pattern.CASE_INSENSITIVE); 157 Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<>(inputGraph.getNodes()); 158 List<InputNode> matches = selector.selectMultiple(matcher); 159 return matches.size() == 0 ? null : matches; 160 } catch (Exception e) { 161 final String msg = e.getMessage(); 162 response.addResult(new Runnable() { 163 @Override 164 public void run() { 165 Message desc = new NotifyDescriptor.Message("An exception occurred during the search, " 166 + "perhaps due to a malformed query string:\n" + msg, 167 NotifyDescriptor.WARNING_MESSAGE); 168 DialogDisplayer.getDefault().notify(desc); 169 } 170 }, 171 "(Error during search)" 172 ); 173 } 174 return null; 175 } 176 } 177