Changeset 1282 for trunk/autoquest-core-usageprofiles/src/main
- Timestamp:
- 07/30/13 09:38:43 (11 years ago)
- Location:
- trunk/autoquest-core-usageprofiles/src/main/java/de/ugoe/cs/autoquest/usageprofiles
- Files:
-
- 3 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/autoquest-core-usageprofiles/src/main/java/de/ugoe/cs/autoquest/usageprofiles/DefaultSymbolComparator.java
r1251 r1282 26 26 public class DefaultSymbolComparator<T> implements SymbolComparator<T> { 27 27 28 /** */ 28 /** 29 * default serial version UID 30 */ 29 31 private static final long serialVersionUID = 1L; 30 32 … … 42 44 } 43 45 44 /* (non-Javadoc)45 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolComparator#getBucketSearchOrder(Object)46 */47 @Override48 public int[] getBucketSearchOrder(T symbol) {49 if (symbol != null) {50 return new int[] { symbol.hashCode() };51 }52 else {53 return null;54 }55 }56 57 46 } -
trunk/autoquest-core-usageprofiles/src/main/java/de/ugoe/cs/autoquest/usageprofiles/SymbolComparator.java
r1251 r1282 29 29 * <p> 30 30 * compares two symbols and returns true, if the concrete comparison strategy sees both 31 * symbols as equal. The method must be commutative, i.e., 32 * <code>equals(symbol1, symbol2) == equals(symbol2, symbol1)</code>. 31 * symbols as equal. The method must be commutative and transitive, i.e., 32 * <code>equals(symbol1, symbol2) == equals(symbol2, symbol1)</code> and 33 * <code>if (equals(symbol1, symbol2) && equals(symbol2, symbol3)) then 34 * equals(symbol1, symbol3)</code>. 33 35 * </p> 34 36 * … … 39 41 */ 40 42 public boolean equals(T symbol1, T symbol2); 41 42 /** 43 * <p> 44 * returns a search order for buckets. This method can be used for optimizing a search for 45 * equal symbols. The client of this class can store symbols in buckets of similar symbols. 46 * Those buckets get an id denoted by an integer. The most appropriate bucket for a symbol is 47 * the first element in the array returned by this method. The symbol should therefore be put 48 * into that bucket. 49 * </p> 50 * <p> 51 * In case a search for an equal symbol shall be performed at the client side, the client 52 * checks the available buckets in the order given as return value of this method. All other 53 * buckets are searched afterwards. In this scenario it is ensured, that the equal symbol is 54 * found as soon as possible as the search always starts in the most appropriate bucket. 55 * However, the other buckets are searched, as well, if no equal symbol is found. Therefore, 56 * in the worst case, all buckets are searched. In the optimal case, the equal symbol is found 57 * in the first bucket. 58 * </p> 59 * <p> 60 * The returned array should contain different integers in each field. This allows a most 61 * efficient search. If an integer is repeated, it is up to the clien, if this is ignored. 62 * </p> 63 * 64 * @param symbol the symbol for which the bucket order is to be returned 65 * 66 * @return a search order for buckets as described 67 * 68 * @see SymbolMap 69 */ 70 public int[] getBucketSearchOrder(T symbol); 43 71 44 } -
trunk/autoquest-core-usageprofiles/src/main/java/de/ugoe/cs/autoquest/usageprofiles/SymbolMap.java
r1257 r1282 16 16 17 17 import java.io.Serializable; 18 import java.util.ArrayList;19 import java.util.Arrays;20 18 import java.util.Collection; 21 import java.util.HashMap;22 import java.util.Iterator;23 import java.util.LinkedList;24 import java.util.List;25 import java.util.Map;26 import java.util.Map.Entry;27 19 28 20 /** 29 21 * <p> 30 * This class is a data structure for holding symbols which is more efficient than a simple list. 31 * This data structure can be used with a comparator to adapt the effective list behavior and to 32 * define the equals strategy for comparing objects. After a certain size ({@link #MAX_LIST_SIZE}), 33 * the symbol map creates a symbol index consisting of buckets. This allows searching for symbols 34 * in a more efficient order as the search can start in the most appropriate of the internal 35 * buckets. 22 * This interface defines a data structure for holding symbols. Its implementations can be used to 23 * improve the performance of a trie by tuning its internal symbol storage management. 36 24 * </p> 37 25 * <p> 38 * The class is called a map, although it is not. It may contain the same element as separate keys. 39 * This implementation is done for performance improvements. If it is required to really assure, 40 * that a key exists only once, then each call to the {@link #addSymbol(Object, Object)} method 41 * should be done only, if the {@link #containsSymbol(Object)} method for the same symbol returns 42 * false. 26 * The interface is called a map, although it is not necessarily. It may contain the same element 27 * as separate keys. This is allowed for performance improvements. If it is required to really 28 * assure, that a key exists only once, then each call to the {@link #addSymbol(Object, Object)} 29 * method should be done only, if the {@link #containsSymbol(Object)} method for the same symbol 30 * returns false. 31 * </p> 32 * <p> 33 * Mapping a symbol to the value null is possible. In this case {@link #getValue(Object)} returns 34 * null for the symbol. But {@link #containsSymbol(Object)} returns true. 43 35 * </p> 44 36 * 45 * @ see SymbolComparator37 * @author Patrick Harms 46 38 * 47 * @author Patrick Harms 39 * @param <T> 40 * Type of the symbols that are stored 41 * @param <V> 42 * Type of the values associated with the symbols 43 * 44 * @see SymbolStrategy 48 45 */ 49 public class SymbolMap<K, V> implements Serializable { 50 51 /** 52 * <p> 53 * default serial version UID 54 * </p> 55 */ 56 private static final long serialVersionUID = 1L; 57 58 /** 59 * <p> 60 * the maximum number of symbols in this map which is still only treated as list instead of 61 * using buckets. 62 * </p> 63 */ 64 private static final int MAX_LIST_SIZE = 15; 65 66 /** 67 * <p> 68 * Comparator to be used for comparing the symbols with each other and to determine a bucket 69 * search order 70 * </p> 71 */ 72 private SymbolComparator<K> comparator; 73 74 /** 75 * <p> 76 * Internally maintained plain list of symbols and associated values 77 * </p> 78 */ 79 private List<Map.Entry<K, V>> symbolList; 80 81 /** 82 * <p> 83 * If the size of the map exceeds {@link #MAX_LIST_SIZE}, this is the symbol index using buckets 84 * for optimizing the search order. 85 * </p> 86 */ 87 private Map<Integer, List<Map.Entry<K, V>>> symbolBuckets; 88 89 /** 90 * <p> 91 * When using buckets, not any symbol may be associated a correct bucket by the used 92 * comparator. Therefore, we set a default bucket for all such symbols. This may change 93 * if the comparator defines the same bucket for a specific symbol. 94 * </p> 95 */ 96 private int defaultBucket = 0; 97 98 /** 99 * <p> 100 * Instantiates a symbol map with a comparator 101 * </p> 102 * 103 * @param comparator the comparator to use for comparing symbols and for determining bucket 104 * search orders 105 * 106 * @throws IllegalArgumentException if the provided comparator is null 107 */ 108 public SymbolMap(SymbolComparator<K> comparator) { 109 if (comparator == null) { 110 throw new IllegalArgumentException("comparator must not be null"); 111 } 112 113 this.comparator = comparator; 114 this.symbolList = new ArrayList<Map.Entry<K, V>>(); 115 } 116 117 /** 118 * <p> 119 * Copy constructure 120 * </p> 121 * 122 * @param otherMap the other map to be copied including its comparator 123 * 124 * @throws IllegalArgumentException if the provided other map is null 125 */ 126 public SymbolMap(SymbolMap<K, V> otherMap) { 127 if (otherMap == null) { 128 throw new IllegalArgumentException("otherMap must not be null"); 129 } 130 131 this.comparator = otherMap.comparator; 132 this.symbolList = new ArrayList<Map.Entry<K, V>>(otherMap.symbolList); 133 134 if (this.symbolList.size() > MAX_LIST_SIZE) { 135 createSymbolBuckets(); 136 } 137 } 46 public interface SymbolMap<K, V> extends Serializable { 138 47 139 48 /** … … 144 53 * @return as described 145 54 */ 146 public int size() { 147 return symbolList.size(); 148 } 55 public int size(); 149 56 150 57 /** … … 155 62 * @return as described 156 63 */ 157 public boolean isEmpty() { 158 return symbolList.isEmpty(); 159 } 64 public boolean isEmpty(); 160 65 161 66 /** … … 170 75 * @throws IllegalArgumentException if the provided symbol is null 171 76 */ 172 public boolean containsSymbol(K symbol) { 173 if (symbol == null) { 174 throw new IllegalArgumentException("symbol must not be null"); 175 } 176 177 return getEntry(symbol) != null; 178 } 77 public boolean containsSymbol(K symbol); 179 78 180 79 /** … … 191 90 * @throws IllegalArgumentException if the provided symbol is null 192 91 */ 193 public V getValue(K symbol) { 194 if (symbol == null) { 195 throw new IllegalArgumentException("symbol must not be null"); 196 } 197 198 Map.Entry<K, V> entry = getEntry(symbol); 199 200 if (entry != null) { 201 return entry.getValue(); 202 } 203 else { 204 return null; 205 } 206 } 92 public V getValue(K symbol); 207 93 208 94 /** … … 210 96 * Adds a symbol and an associated value to the map. If the value is null, the symbol is added, 211 97 * anyway and {@link #containsSymbol(Object)} will return true for that symbol. Adding the 212 * same symbol twice willproduce two entries. This is contradictory to typical map98 * same symbol twice may produce two entries. This is contradictory to typical map 213 99 * implementations. To prevent this, the {@link #containsSymbol(Object)} and 214 100 * {@link #removeSymbol(Object)} methods should be used to ensure map behavior. … … 222 108 * @throws IllegalArgumentException if the provided symbol is null 223 109 */ 224 public void addSymbol(K symbol, V value) { 225 if (symbol == null) { 226 throw new IllegalArgumentException("symbol must not be null"); 227 } 228 229 Map.Entry<K, V> entry = new SymbolMapEntry(symbol, value); 230 231 symbolList.add(entry); 232 233 if (symbolList.size() > MAX_LIST_SIZE) { 234 if (symbolBuckets == null) { 235 createSymbolBuckets(); 236 } 237 else { 238 addToSymbolBucket(entry); 239 } 240 } 241 } 110 public void addSymbol(K symbol, V value); 242 111 243 112 /** … … 253 122 * @throws IllegalArgumentException if the provided symbol is null 254 123 */ 255 public V removeSymbol(K symbol) { 256 if (symbol == null) { 257 throw new IllegalArgumentException("symbol must not be null"); 258 } 259 260 for (int i = 0; i < symbolList.size(); i++) { 261 if (comparator.equals(symbolList.get(i).getKey(), symbol)) { 262 // found the symbol. Remove it from the list, and if required, also from the map. 263 V value = symbolList.remove(i).getValue(); 264 265 if (symbolList.size() > MAX_LIST_SIZE) { 266 removeFromSymbolBuckets(symbol); 267 } 268 269 return value; 270 } 271 } 272 273 return null; 274 } 124 public V removeSymbol(K symbol); 275 125 276 126 /** … … 281 131 * @return as described 282 132 */ 283 public Collection<K> getSymbols() { 284 return new ReadOnlyCollectionFacade<K>(symbolList, new SymbolFacade()); 285 } 133 public Collection<K> getSymbols(); 286 134 287 135 /** … … 294 142 * @return as described 295 143 */ 296 public Collection<V> getValues() { 297 return new ReadOnlyCollectionFacade<V>(symbolList, new ValueFacade()); 298 } 144 public Collection<V> getValues(); 299 145 300 146 /** … … 303 149 * </p> 304 150 */ 305 public void clear() { 306 symbolList.clear(); 307 symbolBuckets = null; 308 } 151 public void clear(); 309 152 310 153 /* (non-Javadoc) … … 312 155 */ 313 156 @Override 314 public int hashCode() { 315 return symbolList.size(); 316 } 157 public int hashCode(); 317 158 318 159 /* (non-Javadoc) 319 160 * @see java.lang.Object#equals(java.lang.Object) 320 161 */ 321 @SuppressWarnings("unchecked")322 162 @Override 323 public boolean equals(Object obj) { 324 if (this == obj) { 325 return true; 326 } 327 else if (this.getClass().isInstance(obj)) { 328 SymbolMap<K, V> other = (SymbolMap<K, V>) obj; 329 330 return (symbolList.size() == other.symbolList.size()) && 331 (symbolList.containsAll(other.symbolList)); 332 } 333 else { 334 return false; 335 } 336 } 337 338 /** 339 * <p> 340 * Internally used to create symbol buckets in case the number of stored symbols increased 341 * above {@link #MAX_LIST_SIZE}. 342 * </p> 343 */ 344 private void createSymbolBuckets() { 345 //System.out.println("creating symbol buckets"); 346 symbolBuckets = new HashMap<Integer, List<Map.Entry<K, V>>>(); 347 348 for (Map.Entry<K, V> symbol : symbolList) { 349 addToSymbolBucket(symbol); 350 } 351 } 352 353 /** 354 * <p> 355 * Adds a symbol and its value to its corresponding bucket. The corresponding bucket is 356 * retrieved from the symbol comparator. It is the first element of the search order returned 357 * by the symbol comparator. If the comparator does not define a search order for the symbol 358 * the entry is added to the default bucket. If the comparator defines a bucket id 359 * identical to the default bucket id, the default bucket id is shifted to another value. 360 * </p> 361 */ 362 private void addToSymbolBucket(Map.Entry<K, V> symbolEntry) { 363 int bucketId = defaultBucket; 364 int[] bucketSearchOrder = comparator.getBucketSearchOrder(symbolEntry.getKey()); 365 366 if ((bucketSearchOrder != null) && (bucketSearchOrder.length > 0)) { 367 bucketId = bucketSearchOrder[0]; 368 369 if (bucketId == defaultBucket) { 370 setNewDefaultBucketId(); 371 } 372 } 373 374 List<Map.Entry<K, V>> list = symbolBuckets.get(bucketId); 375 376 if (list == null) { 377 list = new LinkedList<Map.Entry<K, V>>(); 378 symbolBuckets.put(bucketId, list); 379 } 380 381 list.add(symbolEntry); 382 } 383 384 /** 385 * <p> 386 * Removes the entry for a given symbol from the buckets. It uses the bucket search order 387 * defined by the symbol comparator to find the symbol as fast as possible. 388 * </p> 389 */ 390 private Map.Entry<K, V> removeFromSymbolBuckets(K symbol) { 391 int bucketId = defaultBucket; 392 int[] bucketSearchOrder = comparator.getBucketSearchOrder(symbol); 393 394 if ((bucketSearchOrder != null) && (bucketSearchOrder.length > 0)) { 395 bucketId = bucketSearchOrder[0]; 396 } 397 398 List<Map.Entry<K, V>> list = symbolBuckets.get(bucketId); 399 Map.Entry<K, V> result = null; 400 401 if (list != null) { 402 for (int i = 0; i < list.size(); i++) { 403 if (comparator.equals(list.get(i).getKey(), symbol)) { 404 result = list.remove(i); 405 break; 406 } 407 } 408 409 if (list.isEmpty()) { 410 symbolBuckets.remove(bucketId); 411 } 412 } 413 414 return result; 415 } 416 417 /** 418 * <p> 419 * Updates the default bucket id to a new one 420 * </p> 421 */ 422 private void setNewDefaultBucketId() { 423 int oldDefaultBucket = defaultBucket; 424 do { 425 defaultBucket += 1; 426 } 427 while (symbolBuckets.containsKey(defaultBucket)); 428 429 symbolBuckets.put(defaultBucket, symbolBuckets.get(oldDefaultBucket)); 430 } 431 432 /** 433 * <p> 434 * searches for the entry belonging to the given symbol. The method either uses the list if 435 * buckets are not used yet, or it uses the buckets and searches them in the order defined 436 * by the comparator. If the symbol isn't found and the comparator does not refer all buckets, 437 * then also the other buckets are searched for the symbol. 438 * </p> 439 */ 440 private Map.Entry<K, V> getEntry(K symbol) { 441 Map.Entry<K, V> entry = null; 442 if (symbolBuckets == null) { 443 entry = lookup(symbol, symbolList); 444 } 445 else { 446 int[] bucketSearchOrder = comparator.getBucketSearchOrder(symbol); 447 for (int bucketId : bucketSearchOrder) { 448 List<Map.Entry<K, V>> list = symbolBuckets.get(bucketId); 449 if (list != null) { 450 entry = lookup(symbol, list); 451 if (entry != null) { 452 break; 453 } 454 } 455 } 456 457 // try to search the other buckets 458 if (entry == null) { 459 Arrays.sort(bucketSearchOrder); 460 for (Map.Entry<Integer, List<Map.Entry<K, V>>> bucket : symbolBuckets.entrySet()) { 461 if (Arrays.binarySearch(bucketSearchOrder, bucket.getKey()) < 0) { 462 List<Map.Entry<K, V>> list = bucket.getValue(); 463 if (list != null) { 464 entry = lookup(symbol, list); 465 if (entry != null) { 466 break; 467 } 468 } 469 } 470 } 471 } 472 } 473 474 return entry; 475 } 476 477 /** 478 * <p> 479 * Convenience method to look up a symbol in a list of entries using the comparator. 480 * </p> 481 */ 482 private Map.Entry<K, V> lookup(K symbol, List<Map.Entry<K, V>> list) { 483 for (Map.Entry<K, V> candidate : list) { 484 if (comparator.equals(candidate.getKey(), symbol)) { 485 return candidate; 486 } 487 } 488 489 return null; 490 } 491 492 /** 493 * <p> 494 * Internally used data structure for storing symbol value pairs 495 * </p> 496 * 497 * @author Patrick Harms 498 */ 499 private class SymbolMapEntry implements Map.Entry<K, V> { 500 501 /** 502 * the symbol to map to a value 503 */ 504 private K symbol; 505 506 /** 507 * the value associated with the symbol 508 */ 509 private V value; 510 511 /** 512 * <p> 513 * Simple constructor for initializing the entry with a symbol and its associated value. 514 * </p> 515 */ 516 private SymbolMapEntry(K symbol, V value) { 517 super(); 518 this.symbol = symbol; 519 this.value = value; 520 } 521 522 /* (non-Javadoc) 523 * @see java.util.Map.Entry#getKey() 524 */ 525 @Override 526 public K getKey() { 527 return symbol; 528 } 529 530 /* (non-Javadoc) 531 * @see java.util.Map.Entry#getValue() 532 */ 533 @Override 534 public V getValue() { 535 return value; 536 } 537 538 /* (non-Javadoc) 539 * @see java.util.Map.Entry#setValue(java.lang.Object) 540 */ 541 @Override 542 public V setValue(V value) { 543 V oldValue = this.value; 544 this.value = value; 545 return oldValue; 546 } 547 548 /* (non-Javadoc) 549 * @see java.lang.Object#hashCode() 550 */ 551 @Override 552 public int hashCode() { 553 return symbol.hashCode(); 554 } 555 556 /* (non-Javadoc) 557 * @see java.lang.Object#equals(java.lang.Object) 558 */ 559 @SuppressWarnings("unchecked") 560 @Override 561 public boolean equals(Object obj) { 562 if (this == obj) { 563 return true; 564 } 565 else if (this.getClass().isInstance(obj)) { 566 SymbolMapEntry other = (SymbolMapEntry) obj; 567 return (symbol.equals(other.symbol) && 568 (value == null ? other.value == null : value.equals(other.value))); 569 } 570 else { 571 return false; 572 } 573 } 574 575 /* (non-Javadoc) 576 * @see java.lang.Object#toString() 577 */ 578 @Override 579 public String toString() { 580 return symbol + "=" + value; 581 } 582 583 } 584 585 /** 586 * <p> 587 * Used to create an efficient facade for accessing the internal list of entries either only 588 * for the symbols or only for the values. It is a default implementation of the collection 589 * interface. The entry facade provided to the constructor decides, if either the list 590 * accesses only the symbols or only the values. 591 * </p> 592 * 593 * @author Patrick Harms 594 */ 595 private class ReadOnlyCollectionFacade<TYPE> implements Collection<TYPE> { 596 597 /** 598 * the list facaded by this facade 599 */ 600 private List<Map.Entry<K, V>> list; 601 602 /** 603 * the facade to be used for the entries 604 */ 605 private EntryFacade<TYPE> entryFacade; 606 607 /** 608 * <p> 609 * Initializes the facade with the facaded list and the facade to be used for the entries 610 * </p> 611 */ 612 private ReadOnlyCollectionFacade(List<Map.Entry<K, V>> list, EntryFacade<TYPE> entryFacade) 613 { 614 this.list = list; 615 this.entryFacade = entryFacade; 616 } 617 618 /* (non-Javadoc) 619 * @see java.util.Collection#size() 620 */ 621 @Override 622 public int size() { 623 return list.size(); 624 } 625 626 /* (non-Javadoc) 627 * @see java.util.Collection#isEmpty() 628 */ 629 @Override 630 public boolean isEmpty() { 631 return list.isEmpty(); 632 } 633 634 /* (non-Javadoc) 635 * @see java.util.Collection#contains(java.lang.Object) 636 */ 637 @Override 638 public boolean contains(Object o) { 639 if (o == null) { 640 for (Map.Entry<K, V> entry : list) { 641 if (entryFacade.getFacadedElement(entry) == null) { 642 return true; 643 } 644 } 645 } 646 else { 647 for (Map.Entry<K, V> entry : list) { 648 if (o.equals(entryFacade.getFacadedElement(entry))) { 649 return true; 650 } 651 } 652 } 653 654 return false; 655 } 656 657 /* (non-Javadoc) 658 * @see java.util.Collection#toArray() 659 */ 660 @Override 661 public Object[] toArray() { 662 Object[] result = new Object[list.size()]; 663 664 for (int i = 0; i < list.size(); i++) { 665 result[i] = entryFacade.getFacadedElement(list.get(i)); 666 } 667 668 return result; 669 } 670 671 /* (non-Javadoc) 672 * @see java.util.Collection#toArray(T[]) 673 */ 674 @SuppressWarnings("unchecked") 675 @Override 676 public <T> T[] toArray(T[] a) { 677 T[] result = a; 678 679 for (int i = 0; i < list.size(); i++) { 680 result[i] = (T) entryFacade.getFacadedElement(list.get(i)); 681 } 682 683 return result; 684 } 685 686 /* (non-Javadoc) 687 * @see java.util.Collection#add(java.lang.Object) 688 */ 689 @Override 690 public boolean add(TYPE e) { 691 throw new UnsupportedOperationException("this collection is read only"); 692 } 693 694 /* (non-Javadoc) 695 * @see java.util.Collection#remove(java.lang.Object) 696 */ 697 @Override 698 public boolean remove(Object o) { 699 throw new UnsupportedOperationException("this collection is read only"); 700 } 701 702 /* (non-Javadoc) 703 * @see java.util.Collection#containsAll(java.util.Collection) 704 */ 705 @Override 706 public boolean containsAll(Collection<?> c) { 707 for (Object candidate : c) { 708 if (!contains(candidate)) { 709 return false; 710 } 711 } 712 713 return true; 714 } 715 716 /* (non-Javadoc) 717 * @see java.util.Collection#addAll(java.util.Collection) 718 */ 719 @Override 720 public boolean addAll(Collection<? extends TYPE> c) { 721 throw new UnsupportedOperationException("this collection is read only"); 722 } 723 724 /* (non-Javadoc) 725 * @see java.util.Collection#removeAll(java.util.Collection) 726 */ 727 @Override 728 public boolean removeAll(Collection<?> c) { 729 throw new UnsupportedOperationException("this collection is read only"); 730 } 731 732 /* (non-Javadoc) 733 * @see java.util.Collection#retainAll(java.util.Collection) 734 */ 735 @Override 736 public boolean retainAll(Collection<?> c) { 737 throw new UnsupportedOperationException("this collection is read only"); 738 } 739 740 /* (non-Javadoc) 741 * @see java.util.Collection#clear() 742 */ 743 @Override 744 public void clear() { 745 throw new UnsupportedOperationException("this collection is read only"); 746 } 747 748 /* (non-Javadoc) 749 * @see java.util.Collection#iterator() 750 */ 751 @Override 752 public Iterator<TYPE> iterator() { 753 return new ReadOnlyCollectionIteratorFacade<TYPE>(list.iterator(), entryFacade); 754 } 755 756 } 757 758 /** 759 * <p> 760 * Implementation of an iterator to facade an iterator on the internal list of symbol entries. 761 * </p> 762 * 763 * @author Patrick Harms 764 */ 765 private class ReadOnlyCollectionIteratorFacade<TYPE> implements Iterator<TYPE> { 766 767 /** 768 * the facaded iterator 769 */ 770 private Iterator<Map.Entry<K, V>> iterator; 771 772 /** 773 * the facade for the entries provided by the facaded iterator 774 */ 775 private EntryFacade<TYPE> entryFacade; 776 777 /** 778 * <p> 779 * initialized this facade with the facaded iterator and the entry facade to be used for 780 * the entries. 781 * </p> 782 */ 783 private ReadOnlyCollectionIteratorFacade(Iterator<Map.Entry<K, V>> iterator, 784 EntryFacade<TYPE> entryFacade) 785 { 786 this.iterator = iterator; 787 this.entryFacade = entryFacade; 788 } 789 790 /* (non-Javadoc) 791 * @see java.util.Iterator#hasNext() 792 */ 793 @Override 794 public boolean hasNext() { 795 return iterator.hasNext(); 796 } 797 798 /* (non-Javadoc) 799 * @see java.util.Iterator#next() 800 */ 801 @Override 802 public TYPE next() { 803 return entryFacade.getFacadedElement(iterator.next()); 804 } 805 806 /* (non-Javadoc) 807 * @see java.util.Iterator#remove() 808 */ 809 @Override 810 public void remove() { 811 throw new UnsupportedOperationException("this iterator is read only"); 812 } 813 814 } 815 816 /** 817 * <p> 818 * Used to facade symbol entries and to return only this part of an entry, that is relevant. 819 * </p> 820 * 821 * @author Patrick Harms 822 */ 823 private abstract class EntryFacade<T> { 824 825 /** 826 * <p> 827 * Returns only the part of an entry that is relevant or required. 828 * </p> 829 * 830 * @param entry of which the part shall be returned 831 * 832 * @return the part of the entry to be returned 833 */ 834 protected abstract T getFacadedElement(Entry<K, V> entry); 835 836 } 837 838 /** 839 * <p> 840 * Implementation of the entry facade returning the entries key, i.e. the symbol. 841 * </p> 842 * 843 * @author Patrick Harms 844 */ 845 private class SymbolFacade extends EntryFacade<K> { 846 847 /* (non-Javadoc) 848 * @see ReadOnlyCollectionIteratorFacade#getFacadedElement(Entry) 849 */ 850 @Override 851 protected K getFacadedElement(Entry<K, V> entry) { 852 return entry.getKey(); 853 } 854 } 855 856 /** 857 * <p> 858 * Implementation of the entry facade returning the entries value, i.e. the value associated to 859 * the symbol. 860 * </p> 861 * 862 * @author Patrick Harms 863 */ 864 private class ValueFacade extends EntryFacade<V> { 865 866 /* (non-Javadoc) 867 * @see ReadOnlyCollectionIteratorFacade#getFacadedElement(Entry) 868 */ 869 @Override 870 protected V getFacadedElement(Entry<K, V> entry) { 871 return entry.getValue(); 872 } 873 } 163 public boolean equals(Object obj); 874 164 875 165 } -
trunk/autoquest-core-usageprofiles/src/main/java/de/ugoe/cs/autoquest/usageprofiles/Trie.java
r1251 r1282 29 29 /** 30 30 * <p> 31 * This class implements a <it>trie</it>, i.e., a tree of sequences that the occurence of32 * subsequences up to a predefined length. This length is the trie order.31 * This class implements a <it>trie</it>, i.e., a tree of sequences that represents the occurrence 32 * of subsequences up to a predefined length. This length is the trie order. 33 33 * </p> 34 34 * … … 51 51 /** 52 52 * <p> 53 * Collection of all symbols occur ing in the trie.53 * Collection of all symbols occurring in the trie. 54 54 * </p> 55 55 */ … … 65 65 /** 66 66 * <p> 67 * Comparator to be used for comparing the symbols with each other68 * </p> 69 */ 70 private Symbol Comparator<T> comparator;71 72 /** 73 * <p> 74 * Con tructor. Creates a new Trie with a {@link DefaultSymbolComparator}.67 * Strategy for handling symbols, i.e., for comparing and storing them 68 * </p> 69 */ 70 private SymbolStrategy<T> strategy; 71 72 /** 73 * <p> 74 * Constructor. Creates a new trie with a {@link DefaultSymbolStrategy}. 75 75 * </p> 76 76 */ 77 77 public Trie() { 78 this(new DefaultSymbolComparator<T>()); 79 } 80 81 /** 82 * <p> 83 * Contructor. Creates a new Trie with that uses a specific {@link SymbolComparator}. 84 * </p> 85 */ 86 public Trie(SymbolComparator<T> comparator) { 87 this.comparator = comparator; 88 rootNode = new TrieNode<T>(comparator); 89 knownSymbols = new SymbolMap<T, T>(this.comparator); 90 } 91 92 /** 93 * <p> 94 * Copy-Constructor. Creates a new Trie as the copy of other. The other trie must not be null. 78 this(new DefaultSymbolStrategy<T>()); 79 } 80 81 /** 82 * <p> 83 * Constructor. Creates a new trie that uses a specific {@link SymbolStrategy}. 84 * </p> 85 * 86 * @param strategy 87 * strategy to be used for managing symbols 88 * 89 * @throws IllegalArgumentException 90 * if the strategy is null 91 */ 92 public Trie(SymbolStrategy<T> strategy) { 93 if (strategy == null) { 94 throw new IllegalArgumentException("strategy must not be null"); 95 } 96 this.strategy = strategy; 97 rootNode = new TrieNode<T>(strategy); 98 knownSymbols = strategy.createSymbolMap(); 99 } 100 101 /** 102 * <p> 103 * Copy-Constructor. Creates a new trie as the copy of other. The other trie must not be null. 95 104 * </p> 96 105 * 97 106 * @param other 98 * Trie that is copied 107 * trie that is copied 108 * 109 * @throws IllegalArgumentException 110 * if the other trie is null 99 111 */ 100 112 public Trie(Trie<T> other) { … … 103 115 } 104 116 rootNode = new TrieNode<T>(other.rootNode); 105 knownSymbols = new SymbolMap<T, T>(other.knownSymbols);106 comparator = other.comparator;107 } 108 109 /** 110 * <p> 111 * Returns a collection of all symbols occur ing in the trie.112 * </p> 113 * 114 * @return symbols occur ing in the trie117 strategy = other.strategy; 118 knownSymbols = strategy.copySymbolMap(other.knownSymbols); 119 } 120 121 /** 122 * <p> 123 * Returns a collection of all symbols occurring in the trie. 124 * </p> 125 * 126 * @return symbols occurring in the trie 115 127 */ 116 128 public Collection<T> getKnownSymbols() { … … 202 214 /** 203 215 * <p> 204 * Returns the number of occur ences of the given sequence.216 * Returns the number of occurrences of the given sequence. 205 217 * </p> 206 218 * 207 219 * @param sequence 208 * sequence whose number of occur ences is required209 * @return number of occur ences of the sequence220 * sequence whose number of occurrences is required 221 * @return number of occurrences of the sequence 210 222 */ 211 223 public int getCount(List<T> sequence) { … … 220 232 /** 221 233 * <p> 222 * Returns the number of occur ences of the given prefix and a symbol that follows it.<br>234 * Returns the number of occurrences of the given prefix and a symbol that follows it.<br> 223 235 * Convenience function to simplify usage of {@link #getCount(List)}. 224 236 * </p> … … 228 240 * @param follower 229 241 * suffix of the sequence 230 * @return number of occur ences of the sequence242 * @return number of occurrences of the sequence 231 243 * @see #getCount(List) 232 244 */ … … 326 338 * <p> 327 339 * used to recursively process the trie. The provided processor will be called for any path 328 * through the tr ee. The processor may abort the processing through returnsvalues of its340 * through the trie. The processor may abort the processing through return values of its 329 341 * {@link TrieProcessor#process(List, int)} method. 330 342 * </p> … … 348 360 * </p> 349 361 * 350 * @param context the context of the currently processed trie node, i.e. the prece eding362 * @param context the context of the currently processed trie node, i.e. the preceding 351 363 * symbols 352 364 * @param child the processed trie node … … 489 501 * <p> 490 502 * adds a new symbol to the collection of known symbols if this symbol is not already 491 * contained. The symbols are compared using the comparator.503 * contained. 492 504 * </p> 493 505 * … … 496 508 private void addToKnownSymbols(T symbol) { 497 509 if (!knownSymbols.containsSymbol(symbol)) { 498 knownSymbols.addSymbol(symbol, symbol);510 knownSymbols.addSymbol(symbol, null); 499 511 } 500 512 } … … 529 541 /** 530 542 * <p> 531 * Con tructor. Creates a new TrieVertex.543 * Constructor. Creates a new TrieVertex. 532 544 * </p> 533 545 * … … 635 647 */ 636 648 public void updateKnownSymbols() { 637 knownSymbols = new SymbolMap<T, T>(this.comparator);649 knownSymbols = strategy.createSymbolMap(); 638 650 for (TrieNode<T> node : rootNode.getChildren()) { 639 651 addToKnownSymbols(node.getSymbol()); … … 643 655 /** 644 656 * <p> 645 * Two Tries are defined as equal, if their {@link #rootNode}are equal.657 * Two tries are defined as equal, if their {@link #rootNode}s are equal. 646 658 * </p> 647 659 * -
trunk/autoquest-core-usageprofiles/src/main/java/de/ugoe/cs/autoquest/usageprofiles/TrieNode.java
r1251 r1282 29 29 * <p> 30 30 * This class implements a node of a trie. Each node is associated with a symbol and has a counter. 31 * The counter marks the number of occur ences of the sequence defined by the path from the root of31 * The counter marks the number of occurrences of the sequence defined by the path from the root of 32 32 * the trie to this node. 33 33 * </p> … … 50 50 /** 51 51 * <p> 52 * Counter for the number of occur ences of the sequence.52 * Counter for the number of occurrences of the sequence. 53 53 * </p> 54 54 */ … … 71 71 /** 72 72 * <p> 73 * Comparator to be used for comparing the symbols with each other74 * </p> 75 */ 76 private Symbol Comparator<T> comparator;73 * Strategy for handling symbols, i.e., for comparing and storing them 74 * </p> 75 */ 76 private SymbolStrategy<T> strategy; 77 77 78 78 /** … … 80 80 * Constructor. Creates a new TrieNode without a symbol associated.<br> 81 81 * <b>This constructor should only be used to create the root node of the trie!</b> 82 * The comparator used by the tree node will be a {@link DefaultSymbolComparator}.82 * The strategy used by the trie node will be a {@link DefaultSymbolStrategy}. 83 83 * </p> 84 84 */ 85 85 TrieNode() { 86 this(new DefaultSymbol Comparator<T>());86 this(new DefaultSymbolStrategy<T>()); 87 87 } 88 88 … … 90 90 * <p> 91 91 * Constructor. Creates a new TrieNode. The symbol must not be null. 92 * The comparator used by the tree node will be a {@link DefaultSymbolComparator}.92 * The strategy used by the trie node will be a {@link DefaultSymbolStrategy}. 93 93 * </p> 94 94 * 95 95 * @param symbol 96 96 * symbol associated with the trie node 97 * 98 * @throws IllegalArgumentException 99 * if the provided symbol is null 97 100 */ 98 101 TrieNode(T symbol) { 99 this(symbol, new DefaultSymbol Comparator<T>());102 this(symbol, new DefaultSymbolStrategy<T>()); 100 103 } 101 104 … … 103 106 * <p> 104 107 * Constructor. Creates a new TrieNode without a symbol associated using the provided 105 * comparator.<br>108 * strategy.<br> 106 109 * <b>This constructor should only be used to create the root node of the trie!</b> 107 * <br>The comparator must not be null. 108 * </p> 109 */ 110 TrieNode(SymbolComparator<T> comparator) { 111 if (comparator == null) { 112 throw new IllegalArgumentException("comparator must not be null!"); 113 } 114 this.comparator = comparator; 110 * <br>The strategy must not be null. 111 * </p> 112 * 113 * @param strategy 114 * the strategy used for comparing and storing symbols 115 * 116 * @throws IllegalArgumentException 117 * if the provided strategy is null 118 */ 119 TrieNode(SymbolStrategy<T> strategy) { 120 if (strategy == null) { 121 throw new IllegalArgumentException("strategy must not be null!"); 122 } 123 this.strategy = strategy; 115 124 this.symbol = null; 116 125 count = 0; 117 children = new SymbolMap<T, TrieNode<T>>(this.comparator);118 } 119 120 /** 121 * <p> 122 * Constructor. Creates a new TrieNode using the provided comparator. The symbol and the123 * comparatormust not be null.126 children = strategy.createSymbolMap(); 127 } 128 129 /** 130 * <p> 131 * Constructor. Creates a new TrieNode using the provided strategy. The symbol and the 132 * strategy must not be null. 124 133 * </p> 125 134 * 126 135 * @param symbol 127 136 * symbol associated with the trie node 128 */ 129 TrieNode(T symbol, SymbolComparator<T> comparator) { 137 * @param strategy 138 * the strategy used for comparing and storing symbols 139 * 140 * @throws IllegalArgumentException 141 * if the provided symbol or strategy is null 142 */ 143 TrieNode(T symbol, SymbolStrategy<T> strategy) { 130 144 if (symbol == null) { 131 145 throw new IllegalArgumentException … … 134 148 this.symbol = symbol; 135 149 136 if ( comparator== null) {137 throw new IllegalArgumentException(" comparatormust not be null!");138 } 139 this. comparator = comparator;150 if (strategy == null) { 151 throw new IllegalArgumentException("strategy must not be null!"); 152 } 153 this.strategy = strategy; 140 154 141 155 count = 0; 142 children = new SymbolMap<T, TrieNode<T>>(this.comparator);156 children = strategy.createSymbolMap(); 143 157 } 144 158 … … 148 162 * </p> 149 163 * 150 * @param other 164 * @param other the trie node to create the copy of 165 * 166 * @throws IllegalArgumentException 167 * if the provided node is null 151 168 */ 152 169 TrieNode(TrieNode<T> other) { … … 156 173 symbol = other.symbol; 157 174 count = other.count; 158 comparator = other.comparator;159 children = new SymbolMap<T, TrieNode<T>>(this.comparator);175 strategy = other.strategy; 176 children = strategy.createSymbolMap(); 160 177 161 178 for (TrieNode<T> child : other.children.getValues()) { … … 175 192 public void add(List<T> subsequence) { 176 193 if (!subsequence.isEmpty()) { 177 if (! comparator.equals(symbol, subsequence.get(0))) { // should be guaranteed by178 //the recursion/TrieRoot!194 if (!strategy.getSymbolComparator().equals(symbol, subsequence.get(0))) { 195 // should be guaranteed by the recursion/TrieRoot! 179 196 throw new AssertionError("Invalid trie operation!"); 180 197 } … … 201 218 /** 202 219 * <p> 203 * Returns the number of occur ences of the sequence represented by the node.204 * </p> 205 * 206 * @return number of occur ences of the sequence represented by the node220 * Returns the number of occurrences of the sequence represented by the node. 221 * </p> 222 * 223 * @return number of occurrences of the sequence represented by the node 207 224 */ 208 225 public int getCount() { … … 224 241 TrieNode<T> node = getChild(symbol); 225 242 if (node == null) { 226 node = new TrieNode<T>(symbol, comparator);243 node = new TrieNode<T>(symbol, strategy); 227 244 children.addSymbol(symbol, node); 228 245 } … … 283 300 /** 284 301 * <p> 285 * Returns a collection of all symbols that follow athis node, i.e., the symbols associated302 * Returns a collection of all symbols that follow this node, i.e., the symbols associated 286 303 * with the children of this node. 287 304 * </p> … … 399 416 /** 400 417 * <p> 401 * Recursive method sthat collects all nodes that are ancestors of leafs and stores them in the418 * Recursive method that collects all nodes that are ancestors of leafs and stores them in the 402 419 * set. 403 420 * </p> … … 457 474 * <p> 458 475 * Two TrieNodes are defined as equal, if their {@link #count}, {@link #symbol}, and 459 * {@link #children} are equal. For the comparison of their symbols the comparator is used. 476 * {@link #children} are equal. For the comparison of their symbols the comparator provided 477 * by the symbol management strategy is used. 460 478 * </p> 461 479 * … … 477 495 return count == otherNode.count && 478 496 symbol.getClass().isInstance(((TrieNode) other).symbol) && 479 comparator.equals(symbol, ((TrieNode<T>) other).symbol) &&497 strategy.getSymbolComparator().equals(symbol, ((TrieNode<T>) other).symbol) && 480 498 children.equals(((TrieNode) other).children); 481 499 }
Note: See TracChangeset
for help on using the changeset viewer.