1 19 20 package org.netbeans.modules.schema2beans; 21 22 import java.util.*; 23 import java.io.*; 24 import java.beans.*; 25 26 import java.lang.reflect.*; 28 29 import org.w3c.dom.*; 30 31 32 48 public class BeanProp implements BaseProperty { 49 50 51 static class GroupProp { 60 ArrayList group; 61 62 public GroupProp(BeanProp prop) { 63 this.group = new ArrayList(); 64 this.add(prop); 65 } 66 67 void add(BeanProp prop) { 68 this.group.add(prop); 69 } 70 71 BeanProp[] list() { 72 int size = this.group.size(); 73 BeanProp[] ret = new BeanProp[size]; 74 for (int i=0; i<size; i++) { 75 ret[i] = (BeanProp)this.group.get(i); 76 } 77 return ret; 78 } 79 } 80 81 static class Action { 86 public static final int ADD = 1; 87 public static final int REMOVE = 2; 88 89 int action; 90 92 93 public Action(int action) { 94 this.action = action; 95 } 97 98 public Action(int action, java.beans.PropertyChangeEvent event) { 99 this(action); 100 } 102 103 public String toString() { 104 if (this.action == ADD) 105 return "add"; else 107 return "remove"; } 109 } 110 111 static boolean handleEvents = false; 117 static boolean handleVetoEvents = false; 118 119 120 124 class EventMgr { 125 class Evt { 126 PropertyChangeEvent event; 127 boolean propagate; 128 129 public Evt(PropertyChangeEvent evt, boolean p) { 130 this.event = evt; 131 this.propagate = p; 132 } 133 } 134 135 private int delayed; 136 private BeanProp bp; 137 ArrayList events; 138 139 public EventMgr(BeanProp bp) { 140 this.bp = bp; 141 this.delayed = 0; 142 this.events = new ArrayList(2); 143 } 144 145 boolean isDelayed() { 146 return (this.delayed > 0); 147 } 148 149 void delay() { 150 if (useEvents()) 151 this.delayed++; 152 } 153 154 void addEvent(PropertyChangeEvent e, boolean propagate) { 155 if (useEvents()) { 156 if (this.isDelayed()) { 157 this.events.add(new Evt(e, propagate)); 158 } else { 159 this.bp.notifyInternal(e, propagate); 160 } 161 } 162 } 163 164 void fireEvents() { 165 if (useEvents()) { 166 if (this.delayed == 0) 167 return; 168 169 this.delayed--; 170 171 if (this.delayed == 0) { 172 int size = this.events.size(); 173 if (size > 0) { 174 for (int i=0; i<size; i++) { 175 Evt e = (Evt)this.events.get(i); 176 this.bp.notifyInternal(e.event, e.propagate); 177 } 178 this.events.clear(); 179 } 180 } 181 } 182 } 183 } 184 185 static class InternalEvent { 186 static final int CHANGED = 1; 187 static final int VETOABLE = 2; 188 189 int type; 190 Object obj; 191 192 public InternalEvent(int type, Object obj) { 193 this.type = type; 194 this.obj = obj; 195 } 196 197 PropertyChangeEvent getPropertyChangeEvent() { 198 return (PropertyChangeEvent)this.obj; 199 } 200 } 201 202 private static final int OP_SETTER_SETARRAY = 1; 208 private static final int OP_SETTER_SETELT = 2; 209 private static final int OP_SETTER_ADD = 4; 210 private static final int OP_SETTER_REMOVE = 8; 211 212 public String dtdName; 214 215 public String beanName; 217 public int type; 218 219 public Class propClass; 222 223 ArrayList bindings; 225 226 ArrayList knownValues; 227 228 ArrayList attributes; 230 231 BaseBean bean; 233 234 PropertyChangeSupport changeListeners; 235 VetoableChangeSupport vetoableListeners; 236 237 EventMgr eventMgr; 238 239 boolean isRoot; 240 241 private int order; 254 255 GroupProp group; 263 264 265 public BeanProp(BaseBean bean, String dtdName, String beanName, 266 int type, Class propClass) { 267 this(bean, dtdName, beanName, type, propClass, 10); 268 } 269 270 public BeanProp(BaseBean bean, String dtdName, String beanName, 271 int type, Class propClass, int initialCapacity) { 272 this.dtdName = dtdName; 274 this.beanName = beanName; 275 this.type = type; 276 this.propClass = propClass; 277 this.bean = bean; 278 if (initialCapacity >= 0) { 279 this.bindings = new ArrayList(initialCapacity); 280 this.attributes = new ArrayList(initialCapacity); 281 } 282 this.changeListeners = null; 283 this.vetoableListeners = null; 284 this.knownValues = null; 285 this.isRoot = false; 286 this.order = 0; 287 this.eventMgr = new EventMgr(this); 288 this.group = null; 289 } 290 291 public BeanProp(BaseBean bean, String dtdName, String beanName, 292 int type, Class propClass, boolean isRoot) { 293 this(bean, dtdName, beanName, type, propClass, isRoot, 10); 294 } 295 296 public BeanProp(BaseBean bean, String dtdName, String beanName, 297 int type, Class propClass, boolean isRoot, int initialCapacity) { 298 this(bean, dtdName, beanName, type, propClass, initialCapacity); 299 this.isRoot = isRoot; 300 } 301 302 308 public void initialize() { 309 if (Common.isSequenceOr(this.type)) { 317 BeanProp previousProp = null; 320 321 if (this.order > 1) { 322 previousProp = this.bean.beanProp(this.order-1); 323 } 324 325 if ((previousProp != null) && (previousProp.group != null)) { 326 previousProp.group.add(this); 328 this.group = previousProp.group; 329 } 330 331 if (this.group == null) { 332 this.group = new GroupProp(this); 333 } 334 } 335 } 336 337 boolean useEvents() { 338 return handleEvents; 339 } 340 341 boolean useVetoEvents() { 342 return handleVetoEvents; 343 } 344 345 void setOrder(int order) { 346 this.order = order; 347 } 348 349 public Class getPropClass() { 350 return this.propClass; 351 } 352 353 public int getType() { 354 return this.type; 355 } 356 357 public String getBeanName() { 358 return this.beanName; 359 } 360 361 public BaseBean getBean() { 362 return this.bean; 363 } 364 365 public BaseBean getParent() { 366 return this.getBean(); 367 } 368 369 NodeFactory getNodeFactory() { 370 return this.bean.graphManager().getNodeFactory(); 371 } 372 373 Node getParentNode() { 374 if (this.isRoot) { 376 return null; 377 } 378 379 Node n = null; 380 DOMBinding b = this.bean.domBinding(); 381 382 if (b != null) { 383 n = b.getNode(); 384 } 385 386 if (n == null) { 387 throw new IllegalStateException (Common.getMessage("ParentNodeCantBeNull_msg")); 388 } else { 389 return n; 390 } 391 } 392 393 Node getFollowingSibling(DOMBinding binding) { 403 BeanProp bp = null; 404 int next = this.order+1; 405 406 bp = this.bean.beanProp(next++); 407 408 while (bp != null) { 410 boolean found = false; 411 int size = bp.size(); 412 413 for (int i=0; i<size; i++) { 415 DOMBinding b = bp.getBinding(i); 416 if ((b != null) && (b.getNode() != null)) { 417 found = true; 418 break; 419 } 420 } 421 422 if (found) 423 break; 424 425 bp = this.bean.beanProp(next++); 426 } 427 428 if (bp != null) { 429 if (Common.isArray(bp.type)) { 430 int size = bp.size(); 437 for (int i=0; i<size; i++) { 438 DOMBinding b1 = bp.getBinding(i); 439 if (b1 != null) { 440 boolean found = false; 441 Node n1 = b1.getNode(); 442 Node p = n1.getPreviousSibling(); 443 while (p instanceof Text) 445 p = p.getPreviousSibling(); 446 447 for (int j=0; j<size; j++) 449 if ( i != j) { 450 DOMBinding b2 = bp.getBinding(j); 451 452 if ((b2 != null) && (b2.getNode() == p)) { 453 found = true; 455 break; 456 } 457 } 458 459 if (!found) { 461 return n1; 462 } 463 } 464 } 465 } 466 else { 467 return bp.getBinding(0).getNode(); 469 } 470 } 471 472 return null; 473 } 474 475 476 DOMBinding getBinding(int index) { 477 return (DOMBinding)this.bindings.get(index); 478 } 479 480 protected int bindingsSize() { 481 return bindings.size(); 482 } 483 484 489 public Object getValue(int index) { 490 if (!Common.isArray(this.type)) { 491 if ((index > 0) || (this.bindingsSize() == 0)) 493 return null; 494 } 495 if (bindingsSize() == 0) { 496 return null; 498 } 500 DOMBinding b = (DOMBinding)this.bindings.get(index); 501 502 if (b != null) 503 return b.getValue(this); 504 else 505 return null; 506 } 507 508 509 515 public Object getValueById(int id) { 516 int size = this.bindingsSize(); 517 for (int i=0; i<size; i++) { 518 DOMBinding b = (DOMBinding)this.bindings.get(i); 519 520 if (b.id == id) 521 return b.getValue(this); 522 } 523 return null; 524 } 525 526 530 public int indexToId(int index) { 531 if (index>=0 && index<this.bindingsSize()) { 532 DOMBinding b = (DOMBinding)this.bindings.get(index); 533 if (b != null) 534 return b.id; 535 } 536 return -1; 537 } 538 539 543 public int idToIndex(int id) { 544 int size = this.bindingsSize(); 545 for (int i=0; i<size; i++) { 546 DOMBinding b = (DOMBinding)this.bindings.get(i); 547 548 if ((b != null) && (b.id == id)) 549 return i; 550 } 551 return -1; 552 } 553 554 protected Object [] getObjectArray(int extraElements) { 559 int size = this.bindingsSize(); 560 Object a = 561 Array.newInstance(this.propClass, 562 ((size+extraElements>=0)?(size+extraElements):size)); 563 564 int i=0; 566 try { 567 if (extraElements >= 0) { 568 for (i=0; i<size; i++) 569 Array.set(a, i, this.getValue(i)); 570 } 571 } catch(IllegalArgumentException e) { 572 e.printStackTrace(); 573 System.err.println("bean: " + this.getName() + "dtdname: " + 574 this.getDtdName() + 575 "class: " + this.getPropertyClass()); 576 Object o = this.getValue(i); 577 if (o != null) 578 System.err.println("elt: " + o.toString() + " - " + 579 o.getClass()); 580 else 581 System.err.println("elt is null for index " + i); 582 583 try { 584 this.getBean().write(System.err); 585 System.err.println(this.getBean().dumpDomNode()); 586 } catch (java.io.IOException e2) { 587 } 588 throw e; 589 } 590 591 return (Object [])a; 592 } 593 594 595 599 public Object [] getValues() { 600 if (!Common.isArray(this.type)) 601 throw new IllegalStateException (Common. 602 getMessage("NotIndexedProperty_msg")); 603 604 return this.getObjectArray(0); 605 } 606 607 611 public void setValue(Object [] value) { 612 if (Common.isVetoable(this.type) && useVetoEvents()) { 613 this.raiseVetoableEvent(value, 0, OP_SETTER_SETARRAY); 614 615 } 618 619 DOMBinding b; 623 int newSize = 0; 624 int size = this.bindingsSize(); 625 boolean found; 626 boolean skipNew[] = null; 627 int i, j; 628 boolean changed = false; Object oldValue = null; 630 631 if (useEvents()) { 632 oldValue = Array.newInstance(this.propClass, size); 633 } 634 635 this.eventMgr.delay(); 637 638 if (value != null) { 639 newSize = value.length; 640 skipNew = new boolean[newSize]; 641 Arrays.fill(skipNew, false); 643 } 644 645 for (i=0; i<size; i++) { 647 DOMBinding d = (DOMBinding)this.bindings.get(i); 648 if (d != null) 649 d.posDOM = i; 650 } 651 652 for (i=0; i<size; i++) { 653 found = false; 654 Object o = this.getValue(i); 655 if (o == null) 656 continue; 657 658 for (j=0; j<newSize; j++) 660 if (!skipNew[j]) { 661 if (value[j] == null) 662 continue; 663 if (o == value[j]) { 664 found = true; 665 break; 666 } 667 } 668 669 if (!found) { 671 for (j=0; j<newSize; j++) 672 if (!skipNew[j]) { 673 if (value[j] == null) 674 continue; 675 if (o.equals(value[j])) { 676 found = true; 677 break; 678 } 679 } 680 } 681 682 if (!found) { 683 if (useEvents()) { 685 if (Common.isBean(this.type)) 686 Array.set(oldValue, i, ((BaseBean)o).clone()); 687 else 688 Array.set(oldValue, i, o); 689 690 changed = true; 691 } 692 this.removeElement(i, false); 693 } 694 else { 695 if (useEvents()) { 697 Array.set(oldValue, i, o); 698 if (i != j) 699 changed = true; 700 } 701 skipNew[j] = true; 702 b = (DOMBinding)this.bindings.get(i); 703 b.pos = j; 705 } 706 } 707 708 for (i=0; i<newSize; i++) 710 if (!skipNew[i]) { 711 if (value[i] != null) { 712 int idx = this.setElement(0, value[i], true); 714 b = (DOMBinding)this.bindings.get(idx); 715 b.pos = i; 717 b.posDOM = idx; 719 changed = true; 720 } 721 } 722 723 ArrayList newBindings = new ArrayList(newSize); 725 for (i=0; i<newSize; i++) 726 newBindings.add(null); 727 newBindings.ensureCapacity(newSize+1); 728 size = this.bindingsSize(); 729 for (i=0; i<size; i++) { 730 b = (DOMBinding)this.bindings.get(i); 731 if (b != null) { 732 newBindings.set(b.pos, b); 733 } 734 } 735 this.bindings = newBindings; 737 738 if (changed && this.bean.binding != null) { 739 PropertyChangeEvent e = this.createEvent(this.bean.binding, 741 oldValue, value, null); 742 this.notifyInternal(e, true); 743 } 744 745 if (changed) { 749 for (i=0; i<newSize; i++) { 750 DOMBinding d1 = (DOMBinding)this.bindings.get(i); 751 if (d1 == null) 752 continue; 753 754 DOMBinding db = null; 755 756 int min = d1.posDOM; 758 for (j=i+1; j<newSize; j++) { 759 DOMBinding d2 = (DOMBinding)this.bindings.get(j); 760 if (d2.posDOM < min) { 761 min = d2.posDOM; 762 db = d2; 763 } 764 } 765 if (db != null) 767 d1.moveBefore(this, db.getNode()); 768 } 769 } 770 771 this.eventMgr.fireEvents(); 773 } 774 775 778 public void setValue(int index, Object value) { 779 if (Common.isVetoable(this.type) && useVetoEvents()) { 780 this.raiseVetoableEvent(value, index, OP_SETTER_SETELT); 782 783 } 786 787 this.setElement(index, value, false); 788 } 789 790 793 public int addValue(Object value) { 794 if (Common.isVetoable(this.type) && useVetoEvents()) { 795 this.raiseVetoableEvent(value, 0, OP_SETTER_ADD); 797 798 } 801 802 return this.setElement(0, value, true); 803 } 804 805 814 public int removeValue(Object value) { 815 if (Common.isVetoable(this.type) && useVetoEvents()) { 816 this.raiseVetoableEvent(value, 0, OP_SETTER_REMOVE); 818 819 } 822 823 824 int size = this.bindingsSize(); 825 int index = -1; 826 827 for (int i=0; (i<size) && (index == -1); i++) { 828 DOMBinding b = (DOMBinding)this.bindings.get(i); 829 if (b != null) { 830 Object o = b.getValue(this); 831 if ((o!=null) && (o == value)) 832 index = i; 833 } 834 } 835 836 for (int i=0; (i<size) && (index == -1); i++) { 837 DOMBinding b = (DOMBinding)this.bindings.get(i); 838 if (b != null) { 839 Object o = b.getValue(this); 840 if ((o!=null) && (o.equals(value))) 841 index = i; 842 } 843 } 844 845 if (index != -1) 846 this.removeElement(index, true); 847 else 848 index = 0; 849 850 return index; 851 } 852 853 public void removeValue(int index) { 854 if (index >= this.bindingsSize() && 855 Common.isVetoable(this.type) && useVetoEvents()) { 856 857 DOMBinding b = (DOMBinding)this.bindings.get(index); 858 if (b != null) { 859 Object value = b.getValue(this); 860 861 this.raiseVetoableEvent(value, 0, OP_SETTER_REMOVE); 863 } 864 865 } 868 869 this.removeElement(index, true); 870 } 871 872 private void checkParams(int index, Object value, boolean add) { 874 if (add) { 875 if (value == null) 876 throw new IllegalArgumentException (Common. 877 getMessage("CannotAddNullValue_msg")); 878 } 879 else { 880 if (!Common.isArray(this.type)) { 881 if (index > 0) 882 throw new IllegalArgumentException (Common. 883 getMessage("InvalidIndexForTypeProperty_msg")); 884 } 885 else { 886 if ((index < 0) || (index >= this.bindingsSize())) 887 throw new IndexOutOfBoundsException (); 888 } 889 } 890 } 891 892 906 protected int setElement(int index, Object value, boolean add) { 907 this.checkParams(index, value, add); 908 909 if ((value != null) && Common.isBean(this.type) 910 && ((BaseBean)value).hasDomNode()) { 911 Document doc1 = null; 912 Document doc2 = null; 913 DOMBinding domBinding1 = ((BaseBean)value).domBinding(); 914 DOMBinding domBinding2 = bean.domBinding(); 915 if (domBinding1 != null && domBinding2 != null) { 918 Node node1 = domBinding1.getNode(); 919 Node node2 = domBinding2.getNode(); 920 if (node1 != null && node2 != null) { 923 doc1 = node1.getOwnerDocument(); 924 doc2 = node2.getOwnerDocument(); 925 } 926 } 927 if (doc1 != null && doc1 == doc2) { 931 throw new IllegalArgumentException (Common. 938 getMessage("CannotInsertElementAlreadyInGraph_msg")); 939 } 940 } 941 942 957 958 if (DDLogFlags.debug) { 959 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 960 DDLogFlags.DBG_BLD, 1, DDLogFlags.SETVALUE, 961 this.dtdName + "[" + index + "] - " + 962 (value==null?"null":value.toString())); 963 } 964 965 979 this.eventMgr.delay(); 981 982 if (value != null) { 983 if (Common.isBean(this.type) && !add) 985 this.removeElement(index, false); 986 987 DOMBinding b = null; 988 boolean empty = true; 989 Object oldValue = null; 990 991 if (!add) { 992 empty = (this.bindingsSize() == 0); 993 if (!empty) 994 b = (DOMBinding)this.bindings.get(index); 995 } 996 997 if (b == null) { 998 b = new DOMBinding(); 1004 b.register(this, value); 1005 b.setDefaultAttributeValues(this); 1006 } 1007 1008 if (add) 1009 index = this.bindingsSize(); 1010 1011 if (empty) 1012 this.bindings.add(b); 1013 else 1014 this.bindings.set(index, b); 1015 1016 if (DDLogFlags.debug) { 1017 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1018 DDLogFlags.DBG_BLD, 1, DDLogFlags.NEWBIND, 1019 this.dtdName + "[" + (empty?0:index) + "]"); 1020 } 1021 1022 oldValue = b.setValue(this, value); 1023 1024 if (this.bean.hasDomNode()) { 1033 b.syncNodes(this, new Action(Action.ADD)); 1034 } 1035 else { 1036 if (DDLogFlags.debug) { 1037 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1038 DDLogFlags.DBG_BLD, 1, DDLogFlags.CACHING, 1039 this.dtdName); 1040 } 1041 } 1042 1043 b.notifyBeansForChange(oldValue, value, null); 1048 1049 if (Common.isBean(this.type) && (value != null)) { 1051 BaseBean bb = (BaseBean)value; 1052 String [] names = bb.cachedAttributeNames(); 1053 for (int i=0; i<names.length; i++) { 1054 this.setAttributeValue(index, names[i], 1055 bb.cachedAttributeValue(names[i])); 1056 } 1057 bb.cachedAttributeClear(); 1058 } 1059 } 1060 else 1061 this.removeElement(index, false); 1062 1063 this.eventMgr.fireEvents(); 1065 1066 return index; 1067 } 1068 1069 1070 1073 private void removeElement(int index, boolean remove) { 1074 DOMBinding b; 1075 1076 if (index >= this.bindingsSize()) { 1077 return; 1079 } 1080 1081 b = (DOMBinding)this.bindings.get(index); 1082 if (b != null) { 1083 Object oldValue = b.getValue(this); 1084 b.setLastKnownIndex(this, index); 1085 1086 PropertyChangeEvent e = this.createEvent(b, oldValue, null, null); 1087 1088 if (DDLogFlags.debug) { 1089 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1090 DDLogFlags.DBG_EVT, 1, DDLogFlags.CREATEREM, 1091 (e==null?"no-event":e.getPropertyName()) + 1092 " - source " + this.beanName + 1093 "\n\t\toldValue is " + 1094 (oldValue==null?"<null>":"<"+ 1095 oldValue.toString()+">") + 1096 "\n\t\tnewValue is null"); 1097 } 1098 1099 if (remove) 1100 this.bindings.remove(index); 1101 else 1102 this.bindings.set(index, null); 1103 1104 b.syncNodes(this, new Action(Action.REMOVE, e)); 1106 1107 this.notifyInternal(e, true); 1109 } 1110 } 1111 1112 public Object [] knownValues() { 1114 if (this.knownValues == null) 1115 return null; 1116 1117 int size = this.knownValues.size(); 1118 Object a = Array.newInstance(this.propClass, size); 1119 1120 for (int i=0; i<size; i++) 1121 Array.set(a, i, this.knownValues.get(i)); 1122 1123 return (Object [])a; 1124 } 1125 1126 protected void addKnownValue(Object value) { 1128 if (this.knownValues == null) 1129 this.knownValues = new ArrayList(); 1130 1131 if (this.propClass.isAssignableFrom(value.getClass())) 1132 this.knownValues.add(value); 1133 } 1134 1135 1136 1141 1142 1147 1151 public void createAttribute(String dtdName, String name, int type, 1152 String [] values, String defValue) { 1153 AttrProp ap = new AttrProp(this.dtdName, dtdName, name, type, 1154 values, defValue); 1155 this.attributes.add(ap); 1156 1157 if (DDLogFlags.debug) { 1158 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1159 DDLogFlags.DBG_BLD, 5, DDLogFlags.CREATEATTR, 1160 this.beanName + ": " + ap.toString()); 1161 } 1162 } 1163 1164 1169 public void createTransientAttribute(String dtdName) { 1170 AttrProp ap = this.getAttrProp(dtdName, true); 1172 1173 if (ap != null) 1174 return; 1175 1176 ap = new AttrProp(this.dtdName, dtdName, Common.convertName(dtdName), 1177 AttrProp.CDATA | AttrProp.IMPLIED | 1178 AttrProp.TRANSIENT, null, null); 1179 1180 this.attributes.add(ap); 1181 1182 if (DDLogFlags.debug) { 1183 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1184 DDLogFlags.DBG_BLD, 5, DDLogFlags.CREATEATTR, 1185 this.beanName + ": " + ap.toString()); 1186 } 1187 } 1188 1189 1192 public BaseAttribute[] getAttributes() { 1193 int size = this.attributes.size(); 1194 AttrProp[] ret = new AttrProp[size]; 1195 return (AttrProp[])this.attributes.toArray(ret); 1196 } 1197 1198 1201 public String [] getAttributeNames() { 1202 int size = this.attributes.size(); 1203 String [] ret = new String [size]; 1204 1205 for (int i=0; i<size; i++) { 1206 AttrProp ap = (AttrProp)this.attributes.get(i); 1207 ret[i] = ap.getName(); 1208 } 1209 return ret; 1210 } 1211 1212 1215 public AttrProp getAttrProp(String name, boolean quiet) { 1216 int size = this.attributes.size(); 1217 1218 for (int i=0; i<size; i++) { 1219 AttrProp ap = (AttrProp)this.attributes.get(i); 1220 if (ap.hasName(name)) 1221 return ap; 1222 } 1223 1224 if (!quiet) 1225 throw new IllegalArgumentException (Common. 1226 getMessage("UnknownAttributeForProperty_msg", name, 1227 this.beanName)); 1228 else 1229 return null; 1230 } 1231 1232 1235 public AttrProp getAttrProp(String name) { 1236 return this.getAttrProp(name, false); 1237 } 1238 1239 1242 public void setAttributeValue(int index, String name, String value) { 1243 AttrProp ap = this.getAttrProp(name); 1244 1245 this.checkParams(index, null, false); 1246 1247 if (ap.isFixed() && (ap.defaultValue == null || !ap.defaultValue.equals(value))) 1252 throw new IllegalStateException (Common. 1253 getMessage("CannotChangeFIXEDAttribute_msg")); 1254 1255 if (ap.isEnum() && (value != null)) { 1256 String [] values = ap.getValues(); 1257 boolean found = false; 1258 for (int i=0; i<values.length; i++) { 1259 if (values[i].equals(value)) { 1260 found = true; 1261 break; 1262 } 1263 } 1264 if (!found) { 1265 throw new IllegalArgumentException (Common. 1266 getMessage("ValueDoesNotMatchEnumValues_msg", 1267 value, ap.enumsToString())); 1268 } 1269 } 1270 1271 DOMBinding b = null; 1272 1273 if (index != 0 || this.bindingsSize() != 0) { 1275 b = (DOMBinding)this.bindings.get(index); 1276 } else if (DDLogFlags.debug) { 1277 System.err.println("What DOMBinding should I use for BeanProp.setAttributeValue?!?"); 1278 } 1279 1280 if (b != null) { 1281 Object oldValue = b.getAttributeValue(this, ap.getDtdName()); 1282 b.setAttributeValue(this, ap.getDtdName(), normalizedAttrValue(value)); 1283 1284 b.notifyBeansForChange(oldValue, value, name); 1286 } 1287 } 1288 1290 private String normalizedAttrValue(String value) { 1291 if (value==null) return null; 1292 StringBuffer sb = new StringBuffer (); 1293 for (int i=0;i<value.length();i++) { 1294 char ch = value.charAt(i); 1295 if (XMLUtil.isAttrContent((int)ch)) { 1296 sb.append(ch); 1297 } else { 1298 sb.append('?'); } 1300 } 1301 return sb.toString(); 1302 } 1303 1304 1307 public String getAttributeValue(int index, String name) { 1308 String ret = null; 1309 AttrProp ap = this.getAttrProp(name); 1310 1311 if (!Common.isArray(this.type)) { 1312 if ((index > 0) || (this.bindingsSize() == 0)) 1314 return null; 1315 } 1316 1317 DOMBinding b = (DOMBinding)this.bindings.get(index); 1318 1319 if (b != null) 1320 ret = b.getAttributeValue(this, ap.getDtdName()); 1321 1322 if (DDLogFlags.debug) { 1323 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1324 DDLogFlags.DBG_BLD, 10, DDLogFlags.GETATTR, 1325 this.beanName + "[" + index + "]." + 1326 ap.getDtdName() + ": " + ret + " " + 1327 ((b==null)?"<no binding>":("B("+b.hashCode()+")"))+ 1328 " BP(" + this.hashCode() + ")"); 1329 } 1330 1331 return ret; 1332 } 1333 1334 1339 1340 1341 1346 void removeBinding(DOMBinding binding) { 1347 throw new UnsupportedOperationException (Common. 1348 getMessage("NotImplementedYet_msg")); 1349 } 1350 1351 1352 1358 void syncNodes(Action a) { 1359 int size = this.bindingsSize(); 1360 1361 for (int i=0; i<size; i++) { 1362 DOMBinding b = (DOMBinding)this.bindings.get(i); 1363 if (b != null) 1364 b.syncNodes(this, a); 1365 } 1366 } 1367 1368 1385 void buildPathName(DOMBinding binding, StringBuffer str) { 1386 if (binding == null) 1387 return; 1388 1389 if (Common.isArray(this.type)) { 1390 DOMBinding b = null; 1391 int size = this.bindingsSize(); 1392 int index = binding.getLastKnownIndex(this); 1393 1394 for (int i=0; i<size; i++) { 1395 b = (DOMBinding)this.bindings.get(i); 1396 if (b == binding) 1397 break; 1398 else 1399 b = null; 1400 } 1401 1402 if (index != -1) { 1408 str.insert(0, "i" + index); } 1412 1413 if (b != null) 1421 str.insert(0, b.idToString()); 1422 else 1423 str.insert(0, "-1"); 1425 str.insert(0, "."); } 1428 str.insert(0, this.beanName); 1429 str.insert(0, "/"); 1431 if (!this.isRoot && (this.bean != null)) 1432 this.bean.buildPathName(str); 1433 } 1434 1435 1438 PropertyChangeEvent createEvent(DOMBinding b, Object oldValue, 1439 Object newValue, String attrName) { 1440 if (!useEvents() && !useVetoEvents()) 1441 return null; 1442 1443 StringBuffer name = new StringBuffer (); 1444 1445 if (attrName != null) { 1446 name.append(":"); name.append(attrName); 1448 } 1449 1450 this.buildPathName(b, name); 1451 1452 return new PropertyChangeEvent(this.bean, name.toString(), 1453 oldValue, newValue); 1454 } 1455 1456 1465 PropertyChangeEvent prepareForChangeEvent(DOMBinding b, Object oldValue, 1466 Object newValue, String attrName) { 1467 if (!useEvents()) 1468 return null; 1469 1470 PropertyChangeEvent e = 1471 this.createEvent(b, oldValue, newValue, attrName); 1472 1473 if (DDLogFlags.debug) { 1474 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1475 DDLogFlags.DBG_EVT, 1, DDLogFlags.CREATECHG, 1476 (e==null?"no-event":e.getPropertyName()) + 1477 " - source " + this.beanName + 1478 "\n\t\toldValue is " + 1479 (oldValue==null?"<null>":"<"+ 1480 oldValue.toString()+">") + 1481 "\n\t\tnewValue is " + 1482 (newValue==null?"<null>":"<"+ 1483 newValue.toString()+">")); 1484 } 1485 return e; 1486 } 1487 1488 void notifyInternal(PropertyChangeEvent e, boolean propagate) { 1490 this.notifyInternal(new InternalEvent(InternalEvent.CHANGED, e), 1491 propagate); 1492 } 1493 1494 void notifyInternal(InternalEvent ie, boolean propagate) { 1496 if (ie.type == InternalEvent.CHANGED) { 1497 if (!useEvents()) 1498 return; 1499 1500 if (this.eventMgr.isDelayed()) { 1501 this.eventMgr.addEvent(ie.getPropertyChangeEvent(), propagate); 1502 return; 1503 } 1504 1505 if (DDLogFlags.debug) { 1506 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1507 DDLogFlags.DBG_EVT, 1, DDLogFlags.NOTIFYCHG, 1508 ie.getPropertyChangeEvent().getPropertyName()+ 1509 (propagate?"(P)":"") + 1510 " in " + this.beanName + " - " + 1511 (this.changeListeners==null?"null listener": 1512 (this.changeListeners.hasListeners(null)? 1513 "has listeners":"no listener")) ); 1514 } 1515 1516 if (this.changeListeners != null) 1517 this.changeListeners.firePropertyChange( 1519 ie.getPropertyChangeEvent()); 1520 } 1521 else 1522 if (ie.type == InternalEvent.VETOABLE) { 1523 if( !useVetoEvents()) 1524 return; 1525 1526 if (DDLogFlags.debug) { 1527 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1528 DDLogFlags.DBG_EVT, 1, DDLogFlags.NOTIFYVETO, 1529 ie.getPropertyChangeEvent().getPropertyName()+ 1530 (propagate?"(P)":"") + 1531 " in " + this.beanName + " - " + 1532 (this.vetoableListeners==null?"null listener": 1533 (this.vetoableListeners.hasListeners(null)? 1534 "has listeners":"no listener")) ); 1535 } 1536 1537 try { 1538 if (this.vetoableListeners != null) 1539 this.vetoableListeners.fireVetoableChange( 1541 ie.getPropertyChangeEvent()); 1542 } 1543 catch(PropertyVetoException ve) { 1544 throw new BaseProperty.VetoException(ve, 1548 Common.getMessage("ChangeForPropertyVetoed_msg", 1549 this.beanName)); 1550 } 1551 } 1552 1553 if (!this.isRoot && (this.bean != null) && propagate) 1555 this.bean.notifyInternal(ie); 1556 } 1557 1558 private void raiseVetoableEvent(Object value, int index, int op) { 1559 Object curValue = null; 1560 Object newValue = null; 1561 1562 if (Common.isArray(this.type)) { 1564 Object []arrValue; 1565 1566 curValue = this.getValues(); 1567 switch(op) { 1568 case OP_SETTER_SETARRAY: 1569 newValue = value; 1571 break; 1572 case OP_SETTER_SETELT: 1573 arrValue = this.getObjectArray(0); 1575 arrValue[index] = value; 1576 newValue = arrValue; 1577 break; 1578 case OP_SETTER_ADD: 1579 arrValue = this.getObjectArray(1); 1581 arrValue[this.bindingsSize()] = value; 1582 newValue = arrValue; 1583 break; 1584 case OP_SETTER_REMOVE: 1585 1587 int i, j; 1589 Object [] curValues = (Object [])curValue; 1590 arrValue = this.getObjectArray(-1); 1591 1592 for (i=0; i<curValues.length; i++) { 1593 if (curValues[i].equals(value)) 1594 break; 1595 } 1596 1597 if (i < curValues.length) { 1598 for (i=0, j=0; i<curValues.length; i++) 1600 if (!curValues[i].equals(value)) 1601 arrValue[j++] = curValues[i]; 1602 1603 } 1604 else { 1605 arrValue = curValues; 1606 } 1607 1608 newValue = arrValue; 1609 break; 1610 } 1611 } 1612 else { 1613 curValue = this.getValue(0); 1614 newValue = value; 1615 } 1616 1617 PropertyChangeEvent e = this.createEvent(this.bean.binding, 1619 curValue, newValue, null); 1620 1621 if (DDLogFlags.debug) { 1622 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 1623 DDLogFlags.DBG_EVT, 1, DDLogFlags.VETOABLE, 1624 (e==null?"no-event":e.getPropertyName()) + 1625 " - source " + this.beanName + 1626 "\n\t\toldValue is " + 1627 (curValue==null?"<null>":"<"+ 1628 curValue.toString()+">") + 1629 "\n\t\tnewValue is " + 1630 (newValue==null?"<null>":"<"+ 1631 newValue.toString()+">")); 1632 } 1633 1634 this.notifyInternal(new InternalEvent(InternalEvent.VETOABLE, e), 1636 true); 1637 } 1638 1639 1640 1643 public void addPCListener(PropertyChangeListener l) { 1644 handleEvents = true; 1645 if (this.changeListeners == null) { 1646 Object obj = (this.bean==null)?(Object )this:(Object )this.bean; 1647 this.changeListeners = new PropertyChangeSupport(obj); 1648 } 1649 this.changeListeners.addPropertyChangeListener(l); 1650 } 1651 1652 public void removePCListener(PropertyChangeListener l) { 1653 if (this.changeListeners != null) 1654 this.changeListeners.removePropertyChangeListener(l); 1655 } 1656 1657 public void addVCListener(VetoableChangeListener l) { 1658 if (this.checkVetoable(true)) { 1659 handleVetoEvents = true; 1660 if (this.vetoableListeners == null) { 1661 Object obj = (this.bean==null)?(Object )this:(Object )this.bean; 1662 this.vetoableListeners = new VetoableChangeSupport(obj); 1663 } 1664 this.vetoableListeners.addVetoableChangeListener(l); 1665 } 1666 } 1667 1668 public void removeVCListener(VetoableChangeListener l) { 1669 if (this.checkVetoable(false)) 1670 this.vetoableListeners.removeVetoableChangeListener(l); 1671 } 1672 1673 1674 private boolean checkVetoable(boolean raise) { 1679 if (Common.isVetoable(this.type) || Common.isBean(this.type)) 1680 return true; 1681 1682 if (raise) { 1683 if (!Common.isBean(this.type)) { 1684 throw new Schema2BeansRuntimeException(Common. 1685 getMessage("PropertyDoesntSupportVeto_msg", this.beanName)); 1686 } 1687 } 1688 1689 return false; 1690 } 1691 1692 1695 BaseBean newBeanInstance() { 1696 if (Common.isBean(this.type)) { 1697 try { 1698 Constructor c = null; 1699 1700 try { 1701 Class [] cc = new Class [] {int.class}; 1702 c = this.propClass.getDeclaredConstructor(cc); 1703 } 1704 catch(NoSuchMethodException me) { 1705 return (BaseBean)this.propClass.newInstance(); 1706 } 1707 1708 Object [] p = 1710 new Object [] {new Integer (Common.NO_DEFAULT_VALUES)}; 1711 1712 return (BaseBean)c.newInstance(p); 1713 } 1714 catch(Exception e) { 1715 TraceLogger.error(e); 1716 throw new Schema2BeansRuntimeException(Common. 1717 getMessage("CantInstantiateBean_msg", e.getMessage())); 1718 } 1719 } 1720 return null; 1721 } 1722 1723 1751 public DOMBinding registerDomNode(Node node, DOMBinding binding, 1752 BaseBean bean) throws Schema2BeansException { 1753 int count = 0; 1754 int size = this.bindingsSize(); 1755 1756 for (int i=0; i<size; i++) { 1758 DOMBinding b = (DOMBinding)this.bindings.get(i); 1759 if ((b.getNode() == node) || (binding == b)) 1760 throw new Schema2BeansException(Common. 1761 getMessage("NodeAlreadyReferenced_msg", node)); 1762 1763 if (b.getNode() != null) { 1764 count++; 1765 } 1766 } 1767 1768 1769 if (count==0 || Common.isArray(this.type)) { 1771 if (binding == null) 1779 binding = new DOMBinding(node); 1780 1781 if (bean == null) 1782 bean = this.newBeanInstance(); 1783 1784 binding.register(this, bean); 1785 binding.setValue(this, bean); 1786 1787 this.bindings.add(binding); 1788 } 1789 else { 1790 if (DDLogFlags.debug) { 1791 TraceLogger.put(TraceLogger.DEBUG, 1792 TraceLogger.SVC_DD, 1793 DDLogFlags.DBG_BLD, 1, 1794 DDLogFlags.EXCEEDED, 1795 "exceeding capacity for " + this.dtdName + 1796 "(not an array)"); 1797 } 1798 throw new Schema2BeansException(Common. 1800 getMessage("PropertyAlreadyBoundToDOMNode_msg", this.dtdName)); 1801 } 1802 1803 return binding; 1804 } 1805 1806 public String toString() { 1807 return this.dtdName; 1808 } 1809 1810 1811 public boolean isRoot() { 1812 return this.isRoot; 1813 } 1814 1815 public String getName() { 1817 return this.beanName; 1818 } 1819 1820 public String getDtdName() { 1821 return this.dtdName; 1822 } 1823 1824 public boolean isIndexed() { 1825 return Common.isArray(this.type); 1826 } 1827 1828 public Class getPropertyClass() { 1829 return this.propClass; 1830 } 1831 1832 public boolean isBean() { 1833 return Common.isBean(this.type); 1834 } 1835 1836 public int size() { 1837 return this.bindingsSize(); 1838 } 1839 1840 public String getFullName(int index) { 1841 return this.buildFullName(index, null); 1842 } 1843 1844 public String getFullName() { 1845 return this.buildFullName(0, null); 1846 } 1847 1848 String buildFullName(int index, String attr) { 1849 StringBuffer name = new StringBuffer (); 1850 1851 if (!Common.isArray(this.type)) { 1852 if ((index > 0) || (this.bindingsSize() == 0)) 1854 return null; 1855 } 1856 1857 DOMBinding b = (DOMBinding)this.bindings.get(index); 1858 1859 if (b != null) { 1860 if (attr != null) { 1861 name.append(":"); name.append(attr); 1863 } 1864 this.buildPathName(b, name); 1865 } 1866 else 1867 return null; 1868 1869 return name.toString(); 1870 } 1871 1872 public int getInstanceType() { 1873 return (this.type & Common.MASK_INSTANCE); 1874 } 1875 1876 public boolean isChoiceProperty() { 1877 return (this.group != null); 1878 } 1879 1880 public BaseProperty[] getChoiceProperties() { 1881 if (this.isChoiceProperty()) { 1882 return this.group.list(); 1883 } 1884 return null; 1885 } 1886 1887 public boolean hasName(String name) { 1889 if (name.equals(this.beanName) || name.equals(this.dtdName)) 1890 return true; 1891 else 1892 return false; 1893 } 1894 1895 public boolean isKey() { 1896 return Common.isKey(this.type); 1897 } 1898} 1899 1900 1901 | Popular Tags |