1 19 20 package org.netbeans.modules.schema2beans; 21 22 import java.util.*; 23 import java.beans.*; 24 import org.w3c.dom.*; 25 import java.text.MessageFormat ; 26 27 import java.lang.reflect.*; 29 30 31 49 public class DOMBinding { 50 51 int id; 53 54 Node node; 55 56 int pos; 58 int posDOM; 60 61 private static final Class charArrayClass = 62 java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, 0).getClass(); 63 64 class BeanProperty { 65 BeanProp beanProp; 68 69 Object value; 71 72 int lastIndex; 74 75 ArrayList attributes; 76 77 BeanProperty(BeanProp b) { 78 this.beanProp = b; 79 this.value = null; 80 this.lastIndex = -1; 82 this.attributes = null; 83 } 84 } 85 86 class CacheAttr { 87 String name; 88 String value; 89 90 CacheAttr(String name, String value) { 91 this.name = name; 92 this.value = value; 93 } 94 } 95 96 private BeanProperty prop; 97 98 public DOMBinding() { 99 this.id = DDFactory.getUniqueId(); 100 } 101 102 public DOMBinding(Node node) { 103 this(); 104 this.node = node; 106 } 107 108 void setNode(Node node) { 109 this.node = node; 110 } 111 112 void moveBefore(BeanProp prop, Node node) { 113 Node parent = prop.getParentNode(); 114 115 parent.removeChild(this.node); 116 parent.insertBefore(this.node, node); 117 } 118 119 public int getId() { 120 return this.id; 121 } 122 123 String idToString() { 124 return Integer.toHexString(this.id); 125 } 126 127 Node getNode() { 128 return this.node; 129 } 130 131 133 void register(BeanProp prop, Object value) { 134 BeanProperty bp = new BeanProperty(prop); 135 136 if (Common.isBean(prop.type)) 137 ((BaseBean)value).setDomBinding(this); 138 139 this.prop = bp; 140 141 if (DDLogFlags.debug) { 142 TraceLogger.put(TraceLogger.DEBUG, 143 TraceLogger.SVC_DD, 144 DDLogFlags.DBG_BLD, 1, 145 DDLogFlags.BINDPROP, 146 "property " + prop.getDtdName() + 147 " bound to B(" + this.hashCode() + ")"); 148 } 149 150 if (this.node != null) { 157 NamedNodeMap l = this.node.getAttributes(); 158 for (int i=0; i<l.getLength(); i++) { 159 Node n = l.item(i); 160 prop.createTransientAttribute(n.getNodeName()); 161 } 162 } 163 } 164 165 169 private BeanProperty getBeanProperty(BeanProp prop) { 170 if (this.prop != null && this.prop.beanProp == prop) 171 return this.prop; 172 else 173 return null; 174 } 175 176 177 181 BeanProp getBeanProp(BaseBean bean) { 182 if (this.prop != null && this.prop.value == bean) 183 return this.prop.beanProp; 184 else 185 return null; 186 } 187 188 194 void setLastKnownIndex(BeanProp prop, int index) { 195 BeanProperty bp = this.getBeanProperty(prop); 196 if (bp != null) 197 bp.lastIndex = index; 198 } 199 200 203 int getLastKnownIndex(BeanProp prop) { 204 BeanProperty bp = this.getBeanProperty(prop); 205 206 if (bp != null) 207 return bp.lastIndex; 208 else 209 return -1; 210 } 211 212 220 Object getBean(BeanProp prop) { 221 BeanProperty bp = this.getBeanProperty(prop); 222 223 if (bp != null) 224 return bp.value; 225 else 226 return null; 227 } 228 229 233 String getAttributeValue(BeanProp prop, String name) { 234 if (this.node != null) { 235 Attr a = ((Element)this.node).getAttributeNode(name); 237 if (a != null) 238 return a.getValue(); 239 else 240 return null; 241 } else { 242 BeanProperty bp = this.getBeanProperty(prop); 244 if (bp != null && bp.attributes != null) { 245 CacheAttr ca = findCacheAttr(bp, name); 246 if (ca != null) 247 return ca.value; 248 } 249 } 250 return null; 251 } 252 253 private CacheAttr findCacheAttr(BeanProperty bp, String name) { 254 for (int i = 0; i < bp.attributes.size(); i++) { 255 CacheAttr ca = (CacheAttr)bp.attributes.get(i); 256 if (ca.name.equals(name)) 257 return ca; 258 } 259 return null; 260 } 261 262 266 void setAttributeValue(BeanProp prop, String name, String value) { 267 if (this.node != null) { 268 if (value != null) 269 ((Element)this.node).setAttribute(name, value); 270 else { 271 String v = ((Element)this.node).getAttribute(name); 272 if (v != null) { 273 try { 281 ((Element)this.node).removeAttribute(name); 282 } catch(DOMException e) { 283 } 285 } 286 } 287 } else { 288 BeanProperty bp = this.getBeanProperty(prop); 290 if (bp.attributes == null) 291 bp.attributes = new ArrayList(); 292 CacheAttr ca = findCacheAttr(bp, name); 293 if (ca == null) { 294 ca = new CacheAttr(name, value); 295 bp.attributes.add(ca); 296 } else { 297 ca.value = value; 298 } 299 } 300 } 301 302 308 void setDefaultAttributeValues(BeanProp prop) { 309 BeanProperty bp = this.getBeanProperty(prop); 310 if (bp != null) { 311 BaseAttribute[] ap = prop.getAttributes(); 313 for (int i=0; i<ap.length; i++) { 314 String value = ap[i].getDefaultValue(); 315 if (value != null) 316 this.setAttributeValue(prop, ap[i].getDtdName(), value); 317 } 318 } 319 } 320 321 324 public String getDomValue(Node n) { 325 StringBuffer str = new StringBuffer (); 326 this.nodeToString(str, n, true); 327 return str.toString(); 328 } 329 330 private void nodeToString(StringBuffer str, Node n, boolean root) { 332 if (root) 333 nodeChildrenToString(str, n); 335 else { 336 for (;n != null; n = n.getNextSibling()) 337 nodeChildrenToString(str, n); 338 } 339 } 340 341 342 private void nodeChildrenToString(StringBuffer str, Node n) { 344 String value = n.getNodeValue(); 345 short type = n.getNodeType(); 346 347 if ((type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) && (value != null)) 348 str.append(value); 349 350 if (n.getFirstChild() != null) 351 nodeToString(str, n.getFirstChild(), false); 352 } 353 354 355 361 Object getValue(BeanProp prop) { 362 String ret = null; 363 switch(prop.getType() & Common.MASK_TYPE) { 364 case Common.TYPE_STRING: 365 Class cls = prop.getPropClass(); 370 371 if (this.node != null) 372 ret = this.getDomValue(this.node); 373 else 374 ret = (String )this.getBean(prop); 375 376 if (!(java.lang.String .class).isAssignableFrom(cls) 378 && (ret != null)) { 379 String clsName = cls.getName().intern(); 380 386 try { 387 if ((Wrapper.class).isAssignableFrom(cls)) { 389 Wrapper w = (Wrapper)cls.newInstance(); 390 w.setWrapperValue(ret); 391 return w; 392 } 393 if ((java.lang.Character .class).isAssignableFrom(cls)) { 399 String s = ret.trim(); 400 char c = '\0'; 401 if (s.length() == 0) { 402 if (ret.length() != 0) 403 c = ret.charAt(0); 404 } 405 else 406 c = s.charAt(0); 407 408 return new Character (c); 409 } 410 if (charArrayClass.isAssignableFrom(cls)) 411 return ret.toCharArray(); 412 if (clsName == "org.netbeans.modules.schema2beans.QName" 413 || clsName == "javax.xml.namespace.QName") { 414 String ns = ""; 415 String localPart = null; 416 String prefix = ""; 417 int colonPos = ret.indexOf(':'); 418 if (colonPos < 0) { 419 localPart = ret; 420 } else { 421 prefix = ret.substring(0, colonPos); 422 localPart = ret.substring(colonPos+1, ret.length()); 423 ns = findNamespace(prefix); 424 } 425 if (clsName == "org.netbeans.modules.schema2beans.QName") { 427 return new 428 org.netbeans.modules.schema2beans.QName(ns, 429 localPart, 430 prefix); 431 } 432 Constructor c = 433 cls.getDeclaredConstructor(new Class [] {String .class, 434 String .class, 435 String .class}); 436 return c.newInstance(new Object [] {ns, localPart, prefix}); 437 } 438 return JavaBeansUtil.convertValue(cls, ret.trim()); 439 } catch(Exception e) { 440 throw new Schema2BeansRuntimeException( 442 MessageFormat.format(Common.getMessage( 443 "CantInstantiatePropertyClass_msg"), 444 new Object [] {cls.getName(), prop.getName(), 445 ret, e.getLocalizedMessage()}), e); 446 } 447 } 448 return ret; 449 450 case Common.TYPE_BEAN: 451 return this.getBean(prop); 452 case Common.TYPE_BOOLEAN: 454 return nodeToBoolean(prop); 455 default: 456 throw new Schema2BeansRuntimeException(Common.getMessage( 457 "TypeNotSupported_msg", 458 prop.getPropClass(), new Integer (prop.getType()))); 459 } 460 } 461 462 protected Boolean nodeToBoolean(BeanProp prop) { 463 if (node == null) { 468 Object result = getBean(prop); 469 if (result == null) 470 return Boolean.FALSE; 471 return (Boolean ) result; 473 } else { 474 String ret = getDomValue(node); 475 if (ret == null) 477 return Boolean.TRUE; 478 ret = ret.toLowerCase().intern(); 479 if (ret == "false" || ret == "0") 480 return Boolean.FALSE; 481 return Boolean.TRUE; 484 } 485 } 486 487 protected String findNamespace(String prefix) { 488 String targetName = "xmlns:"+prefix; 489 for (Node n = node; n != null; n = n.getParentNode()) { 490 NamedNodeMap nodeMap = n.getAttributes(); 491 if (nodeMap == null) 492 continue; 493 Attr a = (Attr) nodeMap.getNamedItem(targetName); 494 if (a != null) { 495 return a.getValue(); 496 } 497 } 498 return ""; 499 } 500 501 504 private String getWrapperValue(Object value) { 505 if (value.getClass().isInstance(Wrapper.class)) 506 return ((Wrapper)value).getWrapperValue(); 507 else if (value.getClass().isAssignableFrom(charArrayClass)) { 508 return new String ((char[])value); 510 } else if (value instanceof java.util.Calendar ) { 511 return calendarToString((java.util.Calendar ) value); 512 } else if (value instanceof org.netbeans.modules.schema2beans.QName) { 513 org.netbeans.modules.schema2beans.QName q = 514 (org.netbeans.modules.schema2beans.QName) value; 515 if ("".equals(q.getPrefix())) 516 return q.getLocalPart(); 517 else 518 return q.getPrefix() + ":" + q.getLocalPart(); 519 } else { 520 Class cls = value.getClass(); 521 String clsName = cls.getName(); 522 if (clsName.equals("javax.xml.namespace.QName")) { 523 try { 524 Method prefixMethod = cls.getDeclaredMethod("getPrefix", 525 new Class [0]); 526 String prefix = (String ) prefixMethod.invoke(value, 527 new Object [0]); 528 Method localPartMethod = cls.getDeclaredMethod("getLocalPart", 529 new Class [0]); 530 String localPart = (String ) localPartMethod.invoke(value, 531 new Object [0]); 532 if ("".equals(prefix)) 533 return localPart; 534 else 535 return prefix + ":" + localPart; 536 } catch (java.lang.NoSuchMethodException e) { 537 throw new RuntimeException (e); 538 } catch (java.lang.IllegalAccessException e) { 539 throw new RuntimeException (e); 540 } catch (java.lang.reflect.InvocationTargetException e) { 541 throw new RuntimeException (e); 542 } 543 } 544 return value.toString(); 545 } 546 } 547 548 public static String calendarToString(java.util.Calendar cal) { 549 java.util.Date date = cal.getTime(); 550 java.text.SimpleDateFormat formatter; 551 if (cal.get(java.util.Calendar.HOUR) == 0 && cal.get(java.util.Calendar.MINUTE) == 0 && cal.get(java.util.Calendar.SECOND) == 0) { 552 formatter = new java.text.SimpleDateFormat ("yyyy-MM-dd"); } else if (cal.get(java.util.Calendar.MILLISECOND) == 0) { 554 formatter = new java.text.SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss"); } else { 556 formatter = new java.text.SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss.S"); } 558 String result = formatter.format(date); 559 if (java.util.TimeZone.getDefault().hasSameRules(cal.getTimeZone())) { 560 return result; 561 } 562 java.util.TimeZone tz = cal.getTimeZone(); 563 int offset = timeZoneOffset(tz, 0); 564 if (offset == 0) 565 return result+"Z"; 566 int seconds = offset / 1000; 567 if (seconds > 0) { 568 result += "+"; 569 } else { 570 seconds = -1 * seconds; 571 result += "-"; 572 } 573 int hours = seconds / 3600; 574 if (hours < 10) 575 result += "0"; 576 result += hours + ":"; 577 int minutes = (seconds / 60) % 60; 578 if (minutes < 10) 579 result += "0"; 580 result += minutes; 581 return result; 582 } 583 584 588 Object setValue(BeanProp prop, Object value) { 589 Object oldValue = null; 590 BeanProperty bp = this.getBeanProperty(prop); 591 592 if (bp != null) { 593 oldValue = bp.value; 594 595 if ((oldValue == null) && (this.node != null)) 597 oldValue = this.getValue(prop); 598 599 if (Common.isBean(prop.type)) 600 bp.value = value; 601 else 602 if (Common.isString(prop.type) && (value != null)) { 603 if (value instanceof org.netbeans.modules.schema2beans.QName) { 604 org.netbeans.modules.schema2beans.QName q = 605 (org.netbeans.modules.schema2beans.QName) value; 606 String prefix = q.getPrefix(); 607 String declaredNS = ""; 608 if ("".equals(prefix)) { 609 prefix = prop.getDtdName()+"_ns__"; 610 q = new org.netbeans.modules.schema2beans.QName(q.getNamespaceURI(), 611 q.getLocalPart(), 612 prefix); 613 } else { 614 declaredNS = findNamespace(prefix); 615 } 616 if ("".equals(declaredNS)) { 617 ((Element)node).setAttribute("xmlns:"+prefix, 619 q.getNamespaceURI()); 620 prop.createTransientAttribute("xmlns:"+prefix); 621 } 622 } else { 623 Class cls = value.getClass(); 624 String clsName = cls.getName(); 625 if (clsName.equals("javax.xml.namespace.QName")) { 626 try { 627 Method prefixMethod = cls.getDeclaredMethod("getPrefix", 628 new Class [0]); 629 String prefix = (String ) prefixMethod.invoke(value, 630 new Object [0]); 631 Method nsMethod = cls.getDeclaredMethod("getNamespaceURI", 632 new Class [0]); 633 String ns = (String ) nsMethod.invoke(value, 634 new Object [0]); 635 String declaredNS = ""; 636 if ("".equals(prefix)) { 637 Method localPartMethod = cls.getDeclaredMethod("getLocalPart", 638 new Class [0]); 639 String localPart = (String ) localPartMethod.invoke(value, 640 new Object [0]); 641 Constructor c = cls.getDeclaredConstructor(new Class [] {String .class, String .class, String .class}); 642 prefix = prop.getDtdName()+"_ns__"; 643 value = c.newInstance(new Object [] {ns, localPart, 644 prefix}); 645 } else { 646 declaredNS = findNamespace(prefix); 647 } 648 if ("".equals(declaredNS)) { 649 ((Element)node).setAttribute("xmlns:"+prefix, 651 ns); 652 prop.createTransientAttribute("xmlns:"+prefix); 653 } 654 } catch (java.lang.NoSuchMethodException e) { 655 throw new RuntimeException (e); 656 } catch (java.lang.IllegalAccessException e) { 657 throw new RuntimeException (e); 658 } catch (java.lang.InstantiationException e) { 659 throw new RuntimeException (e); 660 } catch (java.lang.reflect.InvocationTargetException e) { 661 throw new RuntimeException (e); 662 } 663 } 664 } 665 bp.value = this.getWrapperValue(value); 666 } else 667 bp.value = value; 668 } 669 670 return oldValue; 671 } 672 673 674 private static int timeZoneOffset (java.util.TimeZone tz, long date) { 675 if (tz.inDaylightTime(new Date(date))) { 676 return tz.getRawOffset() + (tz.useDaylightTime()? 3600000: 0); 677 } 678 return tz.getRawOffset(); 679 } 680 681 682 686 void remove(BeanProp prop) { 687 } 688 689 690 void removeProp(BeanProp prop) { 691 if (this.prop != null && this.prop.beanProp == prop) 692 this.prop = null; 693 } 694 695 void removeNode(BeanProp prop) { 697 if (this.node != null) { 698 Node parent = prop.getParentNode(); 699 700 if (DDLogFlags.debug) { 701 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 702 DDLogFlags.DBG_BLD, 1, 703 DDLogFlags.DELETENODE, 704 this.node.getNodeName() + " from " + 705 parent.getNodeName()); 706 } 707 removeSurroundingSpace(parent, node); 708 parent.removeChild(this.node); 709 this.node = null; 710 } 711 } 712 713 718 private static void removeSurroundingSpace(Node parent, Node node) { 719 Node nextNode = node.getNextSibling(); 720 if (nextNode != null && nextNode.getNodeType() == Node.TEXT_NODE) { 721 String s = nextNode.getNodeValue(); 722 if (s.trim().length() == 0) { 723 int i = s.indexOf('\n'); 724 if (i == -1) { 725 parent.removeChild(nextNode); 726 } else { 727 s = s.substring(i); 728 Node previousNode = node.getPreviousSibling(); 729 if (previousNode != null && previousNode.getNodeType() == Node.TEXT_NODE) { 730 String s1 = previousNode.getNodeValue(); 731 if (previousNode.getPreviousSibling() != null) { 732 if (s1.trim().length() == 0) { 733 i = s1.lastIndexOf('\n'); 734 if (i > 0) { 735 s = s1.substring(0, i) + s; 736 } else { 737 parent.removeChild(previousNode); 738 } 739 } 740 } else { 741 parent.removeChild((previousNode)); 742 } 743 } 744 nextNode.setNodeValue(s); 745 } 746 } 747 } 748 } 749 750 755 void notifyBeansForChange(Object oldValue, Object newValue, 756 String attrName) { 757 758 if (this.prop != null) { 759 PropertyChangeEvent e = this.prop.beanProp. 760 prepareForChangeEvent(this, oldValue, newValue, attrName); 761 762 this.prop.beanProp.notifyInternal(e, true); 763 } 764 } 765 766 777 void syncNodes(BeanProp prop, BeanProp.Action a) { 778 BeanProperty bp = this.getBeanProperty(prop); 779 780 if (DDLogFlags.debug) { 781 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 782 DDLogFlags.DBG_BLD, 1, 783 DDLogFlags.SYNCNODES, 784 a.toString() + " " + prop.getDtdName() + 785 (bp==null?" - unknown prop!":"")); 786 } 787 788 if (bp == null) 789 return; 790 791 if(a.action == a.REMOVE) { 792 int i = prop.idToIndex(this.id); 793 if (i != -1) 794 bp.lastIndex = i; 795 796 PropertyChangeEvent e = 797 prop.prepareForChangeEvent(this, bp.value, null, null); 798 799 if (Common.isBean(prop.type)) { 800 BaseBean bean = ((BaseBean)bp.value); 802 bean.syncNodes(a); 803 } 804 if (this.prop != null && this.prop.beanProp==prop) { 806 if (node != null && 808 (prop.getType() & Common.MASK_TYPE) == Common.TYPE_STRING) { 809 bp.value = getDomValue(node); 814 } 815 } 817 this.removeNode(prop); 818 prop.notifyInternal(e, false); 819 } 820 else 821 if(a.action == a.ADD) { 822 if (Common.isBean(prop.type)) { 823 NodeFactory f = prop.getNodeFactory(); 824 825 if (this.node != null) { 826 System.out.println("Removing from old graph."); 827 BeanProp.Action a2; 828 a2 = new BeanProp.Action(a.REMOVE); 829 syncNodes(this.prop.beanProp, a2); 830 835 } 836 837 Node parent = prop.getParentNode(); 838 this.node = f.createElement(prop); 839 840 if (DDLogFlags.debug) { 841 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 842 DDLogFlags.DBG_BLD, 1, 843 DDLogFlags.SYNCING, 844 "adding new child " + 845 this.node.getNodeName() + 846 " to node " + parent.getNodeName()); 847 } 848 849 Node sibling = prop.getFollowingSibling(this); 850 parent.insertBefore(this.node, sibling); 851 852 BaseBean bean = ((BaseBean)bp.value); 854 bean.setGraphManager(prop.bean.graphManager()); 855 bean.syncNodes(a); 856 } else if (Common.isBoolean(prop.type)) { 857 boolean v = false; 858 859 if (bp.value != null) 860 v = ((Boolean )bp.value).booleanValue(); 861 862 if (Common.shouldNotBeEmpty(prop.type) || node == null || 863 (nodeToBoolean(prop)).booleanValue() != v) { 864 if (DDLogFlags.debug) { 866 TraceLogger.put(TraceLogger.DEBUG, 867 TraceLogger.SVC_DD, 868 DDLogFlags.DBG_BLD, 1, 869 DDLogFlags.SYNCING, 870 (v?"adding new":"removing") + 871 " tag " + 872 prop.getDtdName()); 873 } 874 875 Node parent = prop.getParentNode(); 876 if (v || Common.shouldNotBeEmpty(prop.type)) { 877 NodeFactory f = prop.getNodeFactory(); 878 if (node == null) { 879 node = f.createElement(prop); 880 Node sibling = prop.getFollowingSibling(this); 881 parent.insertBefore(this.node, sibling); 882 } 883 if (Common.shouldNotBeEmpty(prop.type)) { 884 CharacterData text = 885 (CharacterData) node.getFirstChild(); 886 if (text == null) { 887 text = (CharacterData)f.createText(); 888 node.appendChild(text); 889 if (DDLogFlags.debug) { 890 TraceLogger.put(TraceLogger.DEBUG, 891 TraceLogger.SVC_DD, 892 DDLogFlags.DBG_BLD, 1, 893 DDLogFlags.SYNCING, 894 "adding new text node " + 895 text.getNodeName() + 896 " to node " + 897 this.node.getNodeName()); 898 } 899 } 900 text.setData(""+v); 901 } 902 } else if (node != null) { 903 parent.removeChild(this.node); 904 this.node = null; 905 } 906 } 907 else { 908 if (DDLogFlags.debug) { 909 TraceLogger.put(TraceLogger.DEBUG, 910 TraceLogger.SVC_DD, 911 DDLogFlags.DBG_BLD, 1, 912 DDLogFlags.SYNCING, 913 "keeping same boolean value"); 914 } 915 } 916 } else { 917 NodeFactory f = prop.getNodeFactory(); 918 if (this.node == null) { 919 Node parent = prop.getParentNode(); 920 this.node = f.createElement(prop); 921 922 if (DDLogFlags.debug) { 923 TraceLogger.put(TraceLogger.DEBUG, 924 TraceLogger.SVC_DD, 925 DDLogFlags.DBG_BLD, 1, 926 DDLogFlags.SYNCING, 927 "adding new child " + 928 this.node.getNodeName() + 929 " to node " + 930 parent.getNodeName()); 931 } 932 933 Node sibling = prop.getFollowingSibling(this); 934 parent.insertBefore(this.node, sibling); 935 } 936 937 CharacterData text = 938 (CharacterData)this.node.getFirstChild(); 939 940 if (text == null) { 941 text = (CharacterData)f.createText(); 942 this.node.appendChild(text); 943 if (DDLogFlags.debug) { 944 TraceLogger.put(TraceLogger.DEBUG, 945 TraceLogger.SVC_DD, 946 DDLogFlags.DBG_BLD, 1, 947 DDLogFlags.SYNCING, 948 "adding new text node " + 949 text.getNodeName() + 950 " to node " + 951 this.node.getNodeName()); 952 } 953 } 954 955 text.setData(bp.value.toString()); 956 } 957 958 if (this.node != null) { 960 if (bp.attributes != null) { 961 for (int i=0; i<bp.attributes.size(); i++) { 962 CacheAttr ca = (CacheAttr)bp.attributes.get(i); 963 if (ca.value != null) 966 ((Element)this.node).setAttribute(ca.name, ca.value); 967 } 968 bp.attributes = null; 969 } 970 } 971 } 972 else 973 throw new IllegalArgumentException (Common.getMessage( 974 "UnknownAction_msg", new Integer (a.action))); 975 } 976 977 boolean hasDomNode() { 978 return (this.node != null); 979 } 980 } 981 982 983 | Popular Tags |