1 16 package org.apache.commons.chain.impl; 17 18 19 import java.beans.IntrospectionException ; 20 import java.beans.Introspector ; 21 import java.beans.PropertyDescriptor ; 22 import java.lang.reflect.Method ; 23 import java.util.AbstractCollection ; 24 import java.util.AbstractSet ; 25 import java.util.Collection ; 26 import java.util.HashMap ; 27 import java.util.Iterator ; 28 import java.util.Map ; 29 import java.util.Set ; 30 import org.apache.commons.chain.Context; 31 32 33 50 51 public class ContextBase extends HashMap implements Context { 52 53 54 56 57 60 public ContextBase() { 61 62 super(); 63 initialize(); 64 65 } 66 67 68 81 public ContextBase(Map map) { 82 83 super(map); 84 initialize(); 85 putAll(map); 86 87 } 88 89 90 92 93 99 private Map descriptors = null; 100 101 102 105 private PropertyDescriptor [] pd = null; 106 107 108 113 private static Object singleton; 114 115 static { 116 117 singleton = new Object () { 118 public boolean equals(Object object) { 119 return (false); 120 } 121 }; 122 123 } 124 125 126 130 private static Object [] zeroParams = new Object [0]; 131 132 133 135 136 140 public void clear() { 141 142 if (descriptors == null) { 143 super.clear(); 144 } else { 145 Iterator keys = keySet().iterator(); 146 while (keys.hasNext()) { 147 Object key = keys.next(); 148 if (!descriptors.containsKey(key)) { 149 keys.remove(); 150 } 151 } 152 } 153 154 } 155 156 157 165 public boolean containsValue(Object value) { 166 167 if (descriptors == null) { 169 return (super.containsValue(value)); 170 } 171 172 else if (super.containsValue(value)) { 174 return (true); 175 } 176 177 for (int i = 0; i < pd.length; i++) { 179 if (pd[i].getReadMethod() != null) { 180 Object prop = readProperty(pd[i]); 181 if (value == null) { 182 if (prop == null) { 183 return (true); 184 } 185 } else if (value.equals(prop)) { 186 return (true); 187 } 188 } 189 } 190 return (false); 191 192 } 193 194 195 202 public Set entrySet() { 203 204 return (new EntrySetImpl()); 205 206 } 207 208 209 226 public Object get(Object key) { 227 228 if (descriptors == null) { 230 return (super.get(key)); 231 } 232 233 if (key != null) { 235 PropertyDescriptor descriptor = 236 (PropertyDescriptor ) descriptors.get(key); 237 if (descriptor != null) { 238 if (descriptor.getReadMethod() != null) { 239 return (readProperty(descriptor)); 240 } else { 241 return (null); 242 } 243 } 244 } 245 246 return (super.get(key)); 248 249 } 250 251 252 257 public boolean isEmpty() { 258 259 if (descriptors == null) { 261 return (super.isEmpty()); 262 } 263 264 return (super.size() <= descriptors.size()); 266 267 } 268 269 270 277 public Set keySet() { 278 279 280 return (super.keySet()); 281 282 } 283 284 285 298 public Object put(Object key, Object value) { 299 300 if (descriptors == null) { 302 return (super.put(key, value)); 303 } 304 305 if (key != null) { 307 PropertyDescriptor descriptor = 308 (PropertyDescriptor ) descriptors.get(key); 309 if (descriptor != null) { 310 Object previous = null; 311 if (descriptor.getReadMethod() != null) { 312 previous = readProperty(descriptor); 313 } 314 writeProperty(descriptor, value); 315 return (previous); 316 } 317 } 318 319 return (super.put(key, value)); 321 322 } 323 324 325 338 public void putAll(Map map) { 339 340 Iterator pairs = map.entrySet().iterator(); 341 while (pairs.hasNext()) { 342 Map.Entry pair = (Map.Entry ) pairs.next(); 343 put(pair.getKey(), pair.getValue()); 344 } 345 346 } 347 348 349 359 public Object remove(Object key) { 360 361 if (descriptors == null) { 363 return (super.remove(key)); 364 } 365 366 if (key != null) { 368 PropertyDescriptor descriptor = 369 (PropertyDescriptor ) descriptors.get(key); 370 if (descriptor != null) { 371 throw new UnsupportedOperationException 372 ("Local property '" + key + "' cannot be removed"); 373 } 374 } 375 376 return (super.remove(key)); 378 379 } 380 381 382 389 public Collection values() { 390 391 return (new ValuesImpl()); 392 393 } 394 395 396 398 399 408 private void eliminate(String name) { 409 410 int j = -1; 411 for (int i = 0; i < pd.length; i++) { 412 if (name.equals(pd[i].getName())) { 413 j = i; 414 break; 415 } 416 } 417 if (j < 0) { 418 throw new IllegalArgumentException ("Property '" + name 419 + "' is not present"); 420 } 421 PropertyDescriptor [] results = new PropertyDescriptor [pd.length - 1]; 422 System.arraycopy(pd, 0, results, 0, j); 423 System.arraycopy(pd, j + 1, results, j, pd.length - (j + 1)); 424 pd = results; 425 426 } 427 428 429 433 private Iterator entriesIterator() { 434 435 return (new EntrySetIterator()); 436 437 } 438 439 440 446 private Map.Entry entry(Object key) { 447 448 if (containsKey(key)) { 449 return (new MapEntryImpl(key, get(key))); 450 } else { 451 return (null); 452 } 453 454 } 455 456 457 468 private void initialize() { 469 470 try { 472 pd = Introspector.getBeanInfo 473 (getClass()).getPropertyDescriptors(); 474 } catch (IntrospectionException e) { 475 pd = new PropertyDescriptor [0]; } 477 eliminate("class"); eliminate("empty"); 480 if (pd.length > 0) { 482 descriptors = new HashMap (); 483 for (int i = 0; i < pd.length; i++) { 484 descriptors.put(pd[i].getName(), pd[i]); 485 super.put(pd[i].getName(), singleton); 486 } 487 } 488 489 } 490 491 492 503 private Object readProperty(PropertyDescriptor descriptor) { 504 505 try { 506 Method method = descriptor.getReadMethod(); 507 if (method == null) { 508 throw new UnsupportedOperationException 509 ("Property '" + descriptor.getName() 510 + "' is not readable"); 511 } 512 return (method.invoke(this, zeroParams)); 513 } catch (Exception e) { 514 throw new UnsupportedOperationException 515 ("Exception reading property '" + descriptor.getName() 516 + "': " + e.getMessage()); 517 } 518 519 } 520 521 522 532 private boolean remove(Map.Entry entry) { 533 534 Map.Entry actual = entry(entry.getKey()); 535 if (actual == null) { 536 return (false); 537 } else if (!entry.equals(actual)) { 538 return (false); 539 } else { 540 remove(entry.getKey()); 541 return (true); 542 } 543 544 } 545 546 547 551 private Iterator valuesIterator() { 552 553 return (new ValuesIterator()); 554 555 } 556 557 558 571 private void writeProperty(PropertyDescriptor descriptor, Object value) { 572 573 try { 574 Method method = descriptor.getWriteMethod(); 575 if (method == null) { 576 throw new UnsupportedOperationException 577 ("Property '" + descriptor.getName() 578 + "' is not writeable"); 579 } 580 method.invoke(this, new Object [] { value }); 581 } catch (Exception e) { 582 throw new UnsupportedOperationException 583 ("Exception writing property '" + descriptor.getName() 584 + "': " + e.getMessage()); 585 } 586 587 } 588 589 590 592 593 597 private class EntrySetImpl extends AbstractSet { 598 599 public void clear() { 600 ContextBase.this.clear(); 601 } 602 603 public boolean contains(Object obj) { 604 if (!(obj instanceof Map.Entry )) { 605 return (false); 606 } 607 Map.Entry entry = (Map.Entry ) obj; 608 Entry actual = ContextBase.this.entry(entry.getKey()); 609 if (actual != null) { 610 return (actual.equals(entry)); 611 } else { 612 return (false); 613 } 614 } 615 616 public boolean isEmpty() { 617 return (ContextBase.this.isEmpty()); 618 } 619 620 public Iterator iterator() { 621 return (ContextBase.this.entriesIterator()); 622 } 623 624 public boolean remove(Object obj) { 625 if (obj instanceof Map.Entry ) { 626 return (ContextBase.this.remove((Map.Entry ) obj)); 627 } else { 628 return (false); 629 } 630 } 631 632 public int size() { 633 return (ContextBase.this.size()); 634 } 635 636 } 637 638 639 643 private class EntrySetIterator implements Iterator { 644 645 Map.Entry entry = null; 646 private Iterator keys = ContextBase.this.keySet().iterator(); 647 648 public boolean hasNext() { 649 return (keys.hasNext()); 650 } 651 652 public Object next() { 653 entry = ContextBase.this.entry(keys.next()); 654 return (entry); 655 } 656 657 public void remove() { 658 ContextBase.this.remove(entry); 659 } 660 661 } 662 663 664 668 private class MapEntryImpl implements Map.Entry { 669 670 MapEntryImpl(Object key, Object value) { 671 this.key = key; 672 this.value = value; 673 } 674 675 private Object key; 676 private Object value; 677 678 public boolean equals(Object obj) { 679 if (obj == null) { 680 return (false); 681 } else if (!(obj instanceof Map.Entry )) { 682 return (false); 683 } 684 Map.Entry entry = (Map.Entry ) obj; 685 if (key == null) { 686 return (entry.getKey() == null); 687 } 688 if (key.equals(entry.getKey())) { 689 if (value == null) { 690 return (entry.getValue() == null); 691 } else { 692 return (value.equals(entry.getValue())); 693 } 694 } else { 695 return (false); 696 } 697 } 698 699 public Object getKey() { 700 return (this.key); 701 } 702 703 public Object getValue() { 704 return (this.value); 705 } 706 707 public int hashCode() { 708 return (((key == null) ? 0 : key.hashCode()) 709 ^ ((value == null) ? 0 : value.hashCode())); 710 } 711 712 public Object setValue(Object value) { 713 Object previous = this.value; 714 ContextBase.this.put(this.key, value); 715 this.value = value; 716 return (previous); 717 } 718 719 720 } 721 722 723 727 private class ValuesImpl extends AbstractCollection { 728 729 public void clear() { 730 ContextBase.this.clear(); 731 } 732 733 public boolean contains(Object obj) { 734 if (!(obj instanceof Map.Entry )) { 735 return (false); 736 } 737 Map.Entry entry = (Map.Entry ) obj; 738 return (ContextBase.this.containsValue(entry.getValue())); 739 } 740 741 public boolean isEmpty() { 742 return (ContextBase.this.isEmpty()); 743 } 744 745 public Iterator iterator() { 746 return (ContextBase.this.valuesIterator()); 747 } 748 749 public boolean remove(Object obj) { 750 if (obj instanceof Map.Entry ) { 751 return (ContextBase.this.remove((Map.Entry ) obj)); 752 } else { 753 return (false); 754 } 755 } 756 757 public int size() { 758 return (ContextBase.this.size()); 759 } 760 761 } 762 763 764 768 private class ValuesIterator implements Iterator { 769 770 Map.Entry entry = null; 771 private Iterator keys = ContextBase.this.keySet().iterator(); 772 773 public boolean hasNext() { 774 return (keys.hasNext()); 775 } 776 777 public Object next() { 778 entry = ContextBase.this.entry(keys.next()); 779 return (entry.getValue()); 780 } 781 782 public void remove() { 783 ContextBase.this.remove(entry); 784 } 785 786 } 787 788 789 } 790 | Popular Tags |