1 19 20 21 package org.netbeans.modules.search; 22 23 24 import java.util.*; 25 import org.netbeans.modules.search.types.FullTextType; 26 import org.openide.ErrorManager; 27 import org.openide.nodes.Node; 28 import org.openidex.search.DataObjectSearchGroup; 29 import org.openidex.search.SearchGroup; 30 import org.openidex.search.SearchType; 31 32 33 39 public final class ResultModel { 40 41 42 private static final int COUNT_LIMIT = 500; 43 44 private static final int DETAILS_COUNT_LIMIT = 5000; 45 46 private static final String DEF_SEARCH_TYPES_PACKAGE 47 = "org.netbeans.modules.search.types"; private static final String FULLTEXT_SEARCH_TYPE 49 = "FullTextType"; 51 52 private final long creationTime; 53 54 55 private int size = 0; 56 57 private int totalDetailsCount = 0; 58 60 private ResultTreeModel treeModel; 61 62 private ResultView resultView; 63 64 69 private boolean limitReached = false; 70 71 72 private List<SearchType> searchTypeList; 73 74 75 private SearchGroup searchGroup; 76 77 83 private final boolean isDataObjectSearchGroup; 84 88 final boolean defaultSearchTypesOnly; 89 90 final boolean fullTextOnly; 91 92 final FullTextType fullTextSearchType; 93 94 final String replaceString; 95 96 final boolean searchAndReplace; 97 98 final List<MatchingObject> matchingObjects 99 = new ArrayList<MatchingObject>(); 100 101 102 private String finishMessage; 103 104 105 public ResultModel(List<SearchType> searchTypeList, 106 SearchGroup searchGroup, 107 String replaceString) { 108 this.searchTypeList = searchTypeList; 109 this.searchGroup = searchGroup; 110 this.replaceString = replaceString; 111 this.searchAndReplace = (replaceString != null); 112 113 isDataObjectSearchGroup 114 = (searchGroup.getClass() == DataObjectSearchGroup.class); 115 boolean hasNonDefaultSearchType = false; 116 FullTextType fullTextType = null; 117 for (SearchType searchType : searchGroup.getSearchTypes()) { 118 Class searchTypeClass = searchType.getClass(); 119 String searchTypeName = searchTypeClass.getName(); 120 if (searchTypeClass == FullTextType.class) { 121 fullTextType = (FullTextType) searchType; 122 } else if (!searchTypeName.startsWith(DEF_SEARCH_TYPES_PACKAGE)) { 123 hasNonDefaultSearchType = true; 124 } 125 if (hasNonDefaultSearchType && (fullTextType != null)) { 126 break; 127 } 128 } 129 defaultSearchTypesOnly = !hasNonDefaultSearchType; 130 fullTextSearchType = fullTextType; 131 fullTextOnly = (searchAndReplace || defaultSearchTypesOnly) 132 && (fullTextSearchType != null); 133 134 creationTime = System.currentTimeMillis(); 135 } 136 137 139 long getCreationTime() { 140 return creationTime; 141 } 142 143 148 void setObserver(ResultTreeModel observer) { 149 this.treeModel = observer; 150 } 151 152 157 void setObserver(ResultView observer) { 158 this.resultView = observer; 159 } 160 161 165 void close() { 166 if ((matchingObjects != null) && !matchingObjects.isEmpty()) { 167 for (MatchingObject matchingObj : matchingObjects) { 168 matchingObj.cleanup(); 169 } 170 } 171 172 if (searchTypeList != null){ 173 for (SearchType searchType : searchTypeList) { 174 179 if (searchType instanceof org.netbeans.modules.search.types.FullTextType) { 181 ((org.netbeans.modules.search.types.FullTextType)searchType) 182 .destroy(); 183 } 184 } 185 searchTypeList.clear(); 186 searchTypeList = null; 187 } 188 189 194 searchGroup = null; 195 } 196 197 204 synchronized boolean objectFound(Object object) { 205 MatchingObject matchingObject = new MatchingObject(this, object); 206 if (matchingObjects.add(matchingObject) == false) { 207 return true; 208 } 209 210 assert limitReached == false; 211 assert treeModel != null; 212 assert resultView != null; 213 214 totalDetailsCount += getDetailsCount(matchingObject); 215 216 treeModel.objectFound(matchingObject, size++); 217 resultView.objectFound(matchingObject, totalDetailsCount); 218 219 return size < COUNT_LIMIT && totalDetailsCount < DETAILS_COUNT_LIMIT; 220 } 221 222 224 public void objectBecameInvalid(MatchingObject matchingObj) { 225 226 227 228 int index = matchingObjects.indexOf(matchingObj); 229 assert index != -1; 230 231 treeModel.objectBecameInvalid(matchingObj); 232 } 233 234 236 synchronized int getTotalDetailsCount() { 237 return totalDetailsCount; 238 } 239 240 242 synchronized MatchingObject[] getMatchingObjects() { 243 return matchingObjects.toArray( 244 new MatchingObject[matchingObjects.size()]); 245 } 246 247 249 synchronized Object [] getFoundObjects() { 250 Object [] foundObjects = new Object [matchingObjects.size()]; 251 int index = 0; 252 for (MatchingObject matchingObj : matchingObjects) { 253 foundObjects[index++] = matchingObj.object; 254 } 255 return foundObjects; 256 } 257 258 public void run() { 259 260 } 261 262 264 boolean hasDetails() { 265 return totalDetailsCount != 0; } 267 268 278 Boolean canHaveDetails() { 279 Boolean ret; 280 if (fullTextSearchType != null) { 281 ret = Boolean.TRUE; 282 } else if (defaultSearchTypesOnly) { 283 ret = Boolean.FALSE; 284 } else { 285 ret = null; 286 } 287 return ret; 288 } 289 290 296 297 private MatchingObject infoCacheMatchingObject; 298 private Boolean infoCacheHasDetails; 299 private int infoCacheDetailsCount; 300 private Node[] infoCacheDetailNodes; 301 private final Node[] EMPTY_NODES_ARRAY = new Node[0]; 302 303 305 private void prepareCacheFor(MatchingObject matchingObject) { 306 if (matchingObject != infoCacheMatchingObject) { 307 infoCacheHasDetails = null; 308 infoCacheDetailsCount = -1; 309 infoCacheDetailNodes = null; 310 infoCacheMatchingObject = matchingObject; 311 } 312 } 313 314 316 boolean hasDetails(MatchingObject matchingObject) { 317 prepareCacheFor(matchingObject); 318 if (infoCacheHasDetails != null) { 319 return infoCacheHasDetails.booleanValue(); 320 } 321 322 boolean hasDetails = hasDetailsReal(matchingObject); 323 infoCacheHasDetails = Boolean.valueOf(hasDetails); 324 325 assert (infoCacheHasDetails == Boolean.TRUE) 326 || (infoCacheHasDetails == Boolean.FALSE); 327 return hasDetails; 328 } 329 330 332 private boolean hasDetailsReal(MatchingObject matchingObject) { 333 boolean ret; 334 if (fullTextSearchType != null) { 335 ret = true; 336 } else if (defaultSearchTypesOnly) { 337 ret = false; 338 } else { 339 ret = false; 340 final Object foundObject = matchingObject.object; 341 for (SearchType searchType : searchGroup.getSearchTypes()) { 342 Node[] detailNodes = searchType.getDetails(foundObject); 343 if ((detailNodes != null) && (detailNodes.length != 0)) { 344 ret = true; 345 break; 346 } 347 } 348 } 349 return ret; 350 } 351 352 354 int getDetailsCount(MatchingObject matchingObject) { 355 prepareCacheFor(matchingObject); 356 if (infoCacheDetailsCount == -1) { 357 infoCacheDetailsCount = getDetailsCountReal(matchingObject); 358 if (infoCacheDetailsCount == 0) { 359 infoCacheDetailNodes = EMPTY_NODES_ARRAY; 360 } 361 } 362 363 assert infoCacheDetailsCount >= 0; 364 return infoCacheDetailsCount; 365 } 366 367 374 private int getDetailsCountReal(MatchingObject matchingObject) { 375 if (defaultSearchTypesOnly) { 376 return (fullTextSearchType != null) 377 ? fullTextSearchType.getDetailsCount(matchingObject.object) 378 : 0; 379 } 380 381 int count = 0; 382 final Object foundObject = matchingObject.object; 383 for (SearchType searchType : searchGroup.getSearchTypes()) { 384 if (searchType == fullTextSearchType) { 385 count += fullTextSearchType.getDetailsCount(foundObject); 386 } else { 387 Node[] detailNodes = searchType.getDetails(foundObject); 388 count += (detailNodes != null) ? detailNodes.length : 0; 389 } 390 } 391 return count; 392 } 393 394 399 Node[] getDetails(MatchingObject matchingObject) { 400 prepareCacheFor(matchingObject); 401 Node[] detailNodes; 402 if (infoCacheDetailNodes == null) { 403 detailNodes = getDetailsReal(matchingObject); 404 infoCacheDetailNodes = (detailNodes != null) 405 ? detailNodes 406 : EMPTY_NODES_ARRAY; 407 infoCacheDetailsCount = infoCacheDetailNodes.length; 408 } else { 409 detailNodes = (infoCacheDetailNodes != EMPTY_NODES_ARRAY) 410 ? infoCacheDetailNodes 411 : null; 412 } 413 414 assert (infoCacheDetailNodes != null) 415 && ((infoCacheDetailNodes == EMPTY_NODES_ARRAY) 416 || (infoCacheDetailNodes.length > 0)); 417 assert (detailNodes == null) || (detailNodes.length > 0); 418 return detailNodes; 419 } 420 421 426 private Node[] getDetailsReal(MatchingObject matchingObject) { 427 if (defaultSearchTypesOnly) { 428 return (fullTextSearchType != null) 429 ? fullTextSearchType.getDetails(matchingObject.object) 430 : null; 431 } 432 433 Node[] nodesTotal = null; 434 final Object foundObject = matchingObject.object; 435 for (SearchType searchType : searchGroup.getSearchTypes()) { 436 Node[] detailNodes = searchType.getDetails(foundObject); 437 if ((detailNodes == null) || (detailNodes.length == 0)) { 438 continue; 439 } 440 if (nodesTotal == null) { 441 nodesTotal = detailNodes; 442 } else { 443 Node[] oldNodesTotal = nodesTotal; 444 nodesTotal = new Node[nodesTotal.length + detailNodes.length]; 445 System.arraycopy(oldNodesTotal, 0, 446 nodesTotal, 0, 447 oldNodesTotal.length); 448 System.arraycopy(detailNodes, 0, 449 nodesTotal, oldNodesTotal.length, 450 detailNodes.length); 451 } 452 } 453 return nodesTotal; 454 } 455 456 458 synchronized int size() { 459 return size; 460 } 461 462 464 boolean isEmpty() { 465 return size == 0; 466 } 467 468 469 SearchGroup getSearchGroup() { 470 return searchGroup; 471 } 472 473 474 List getEnabledSearchTypes() { 475 return searchTypeList; 476 } 477 478 484 SearchType[] getQueriedSearchTypes() { 485 return searchGroup.getSearchTypes(); 486 } 487 488 490 boolean wasLimitReached() { 491 return limitReached; 492 } 493 494 495 void searchException(RuntimeException ex) { 496 ErrorManager.Annotation[] annotations = ErrorManager.getDefault().findAnnotations(ex); 497 for (int i = 0; i < annotations.length; i++) { 498 ErrorManager.Annotation annotation = annotations[i]; 499 if (annotation.getSeverity() == ErrorManager.USER) { 500 finishMessage = annotation.getLocalizedMessage(); 501 if (finishMessage != null) return; 502 } 503 } 504 finishMessage = ex.getLocalizedMessage(); 505 } 506 507 509 String getExceptionMsg() { 510 return finishMessage; 511 } 512 513 } 514 | Popular Tags |