1 53 54 package org.swixml; 55 56 import org.jdom.Attribute; 57 import org.jdom.Document; 58 import org.jdom.Element; 59 import org.swixml.converters.ConstraintsConverter; 60 import org.swixml.converters.LocaleConverter; 61 import org.swixml.converters.PrimitiveConverter; 62 63 import javax.swing.*; 64 import java.awt.*; 65 import java.lang.reflect.*; 66 import java.util.*; 67 import java.util.List ; 68 69 81 public class Parser { 82 83 87 90 public static final String ATTR_CONSTRAINTS = "constraints"; 91 92 95 public static final String ATTR_PLAF = "plaf"; 96 97 100 public static final String ATTR_BUNDLE = "bundle"; 101 102 105 public static final String ATTR_LOCALE = "locale"; 106 107 110 public static final String ATTR_ID = "id"; 111 112 115 public static final String ATTR_REFID = "refid"; 116 117 123 public static final String ATTR_USE = "use"; 124 125 128 public static final String ATTR_INCLUDE = "include"; 129 130 133 public static final String ATTR_INITCLASS = "initclass"; 134 135 138 public static final String ATTR_ACTION = "action"; 139 140 143 public static final String ATTR_MACOS_PREFIX = "macos_"; 144 145 148 public static final String ATTR_MACOS_PREF = ATTR_MACOS_PREFIX + "preferences"; 149 150 153 public static final String ATTR_MACOS_ABOUT = ATTR_MACOS_PREFIX + "about"; 154 155 158 public static final String ATTR_MACOS_QUIT = ATTR_MACOS_PREFIX + "quit"; 159 160 163 public static final String ATTR_MACOS_OPENAPP = ATTR_MACOS_PREFIX + "openapp"; 164 165 168 public static final String ATTR_MACOS_OPENFILE = ATTR_MACOS_PREFIX + "openfile"; 169 170 173 public static final String ATTR_MACOS_PRINT = ATTR_MACOS_PREFIX + "print"; 174 175 178 public static final String ATTR_MACOS_REOPEN = ATTR_MACOS_PREFIX + "reopen"; 179 180 181 184 public static final String GETINSTANCE = "getInstance"; 185 186 189 public static final Vector LOCALIZED_ATTRIBUTES = new Vector(); 190 191 195 198 private SwingEngine engine; 199 200 203 private ConverterLibrary cvtlib = ConverterLibrary.getInstance(); 204 205 208 private Map lbl_map = new HashMap(); 209 210 213 private Map mac_map = new HashMap(); 214 215 218 private Document jdoc; 219 220 224 static { 225 LOCALIZED_ATTRIBUTES.add("accelerator"); 226 LOCALIZED_ATTRIBUTES.add("icon"); 227 LOCALIZED_ATTRIBUTES.add("iconimage"); 228 LOCALIZED_ATTRIBUTES.add("label"); 229 LOCALIZED_ATTRIBUTES.add("mnemonic"); 230 LOCALIZED_ATTRIBUTES.add("name"); 231 LOCALIZED_ATTRIBUTES.add("text"); 232 LOCALIZED_ATTRIBUTES.add("title"); 233 LOCALIZED_ATTRIBUTES.add("titleat"); 234 LOCALIZED_ATTRIBUTES.add("titles"); 235 LOCALIZED_ATTRIBUTES.add("tooltiptext"); 236 } 237 238 243 public Parser(SwingEngine engine) { 244 this.engine = engine; 245 } 246 247 259 public void parse(Document jdoc, Container container) throws Exception { 260 this.jdoc = jdoc; 261 this.lbl_map.clear(); 262 this.mac_map.clear(); 263 getSwing(processCustomAttributes(jdoc.getRootElement()), container); 264 265 linkLabels(); 266 supportMacOS(); 267 268 this.lbl_map.clear(); 269 this.mac_map.clear(); 270 } 271 272 283 public Object parse(Document jdoc) throws Exception { 284 this.jdoc = jdoc; 285 this.lbl_map.clear(); 286 Object obj = getSwing(processCustomAttributes(jdoc.getRootElement()), null); 287 288 linkLabels(); 289 supportMacOS(); 290 291 this.lbl_map.clear(); 292 this.mac_map.clear(); 293 return obj; 294 } 295 296 306 private Element processCustomAttributes(Element element) throws Exception { 307 Attribute locale = element.getAttribute(Parser.ATTR_LOCALE); 311 if (locale != null && locale.getValue() != null) { 312 engine.setLocale(LocaleConverter.conv(locale)); 313 element.removeAttribute(Parser.ATTR_LOCALE); 314 } 315 Attribute bundle = element.getAttribute(Parser.ATTR_BUNDLE); 319 if (bundle != null && bundle.getValue() != null) { 320 engine.getLocalizer().setResourceBundle(bundle.getValue()); 321 element.removeAttribute(Parser.ATTR_BUNDLE); 322 } 323 Attribute plaf = element.getAttribute(Parser.ATTR_PLAF); 327 if (plaf != null && plaf.getValue() != null && 0 < plaf.getValue().length()) { 328 try { 329 if (!(SwingEngine.isMacOSXSupported() && SwingEngine.isMacOSX())) { 330 UIManager.setLookAndFeel(plaf.getValue()); 331 } 332 } catch (Exception e) { 333 if (SwingEngine.DEBUG_MODE) { 334 System.err.println(e); 335 } 336 } 337 element.removeAttribute(Parser.ATTR_PLAF); 338 } 339 340 return element; 341 } 342 343 346 private void linkLabels() { 347 Iterator it = lbl_map.keySet().iterator(); 348 while (it != null && it.hasNext()) { 349 JLabel lbl = (JLabel) it.next(); 350 String id = lbl_map.get(lbl).toString(); 351 try { 352 lbl.setLabelFor((Component) engine.getIdMap().get(id)); 353 } catch (ClassCastException e) { 354 } 356 } 357 }; 358 359 362 private void supportMacOS() { 363 if (SwingEngine.isMacOSXSupported() && SwingEngine.isMacOSX()) { 364 try { 365 MacApp.getInstance().update(mac_map); 366 } catch (Throwable t) { 367 } 369 } 370 } 371 372 380 Object getSwing(Element element, Object obj) throws Exception { 381 382 Factory factory = engine.getTaglib().getFactory(element.getName()); 383 String id = element.getAttribute(Parser.ATTR_ID) != null ? element.getAttribute(Parser.ATTR_ID).getValue().trim() : null; 385 boolean unique = !engine.getIdMap().containsKey(id); 387 boolean constructed = false; 388 389 if (!unique) { 390 throw new IllegalStateException ("id already in use: " + id + " : " + engine.getIdMap().get(id).getClass().getName()); 391 } 392 if (factory == null) { 393 throw new Exception ("Unknown TAG, implementation class not defined: " + element.getName()); 394 } 395 396 400 if (element.getAttribute(Parser.ATTR_INCLUDE) != null) { 401 StringTokenizer st = new StringTokenizer(element.getAttribute(Parser.ATTR_INCLUDE).getValue(), "#"); 402 element.removeAttribute(Parser.ATTR_INCLUDE); 403 Document doc = new org.jdom.input.SAXBuilder().build(this.engine.getClassLoader().getResourceAsStream(st.nextToken())); 404 Element xelem = find(doc.getRootElement(), st.nextToken()); 405 if (xelem != null) { 406 moveContent(xelem, element); 407 } 408 } 409 410 414 415 if (element.getAttribute(Parser.ATTR_REFID) != null) { 416 element = (Element) element.clone(); 417 cloneAttributes(element); 418 element.removeAttribute(Parser.ATTR_REFID); 419 } else if (element.getAttribute(Parser.ATTR_USE) != null) { 420 element = (Element) element.clone(); 421 cloneAttributes(element); 422 element.removeAttribute(Parser.ATTR_USE); 423 } 424 428 List attributes = element.getAttributes(); 429 if (obj == null) { 430 Object initParameter = null; 431 432 if (element.getAttribute(Parser.ATTR_INITCLASS) != null) { 433 StringTokenizer st = new StringTokenizer(element.getAttributeValue(Parser.ATTR_INITCLASS), "( )"); 434 element.removeAttribute(Parser.ATTR_INITCLASS); 435 try { 437 if (st.hasMoreTokens()) { 438 Class initClass = Class.forName(st.nextToken()); try { Method factoryMethod = initClass.getMethod(Parser.GETINSTANCE, null); 441 if (Modifier.isStatic(factoryMethod.getModifiers())) { 442 initParameter = factoryMethod.invoke(null, null); 443 } 444 } catch (NoSuchMethodException nsme) { 445 } 447 if (initParameter == null && st.hasMoreTokens()) { try { 449 Constructor ctor = initClass.getConstructor(new Class []{String .class}); 450 String pattern = st.nextToken(); 451 initParameter = ctor.newInstance(new Object []{pattern}); 452 } catch (NoSuchMethodException e) { 453 } catch (SecurityException e) { 454 } catch (InstantiationException e) { 455 } catch (IllegalAccessException e) { 456 } catch (IllegalArgumentException e) { 457 } catch (InvocationTargetException e) { 458 } 459 } 460 if (initParameter == null) { initParameter = initClass.newInstance(); 462 } 463 if (Action.class.isInstance(initParameter)) { 464 for (int i = 0, n = attributes.size(); i < n; i++) { 465 Attribute attrib = (Attribute) attributes.get(i); 466 String attribName = attrib.getName(); 467 if (attribName != null && attribName.startsWith(ATTR_MACOS_PREFIX)) { 468 mac_map.put(attribName, initParameter); 469 } 470 } 471 } 472 } 473 } catch (ClassNotFoundException e) { 474 System.err.println(Parser.ATTR_INITCLASS + " not instantiated : " + e.getLocalizedMessage() + e); 475 } catch (SecurityException e) { 476 System.err.println(Parser.ATTR_INITCLASS + " not instantiated : " + e.getLocalizedMessage() + e); 477 } catch (IllegalAccessException e) { 478 System.err.println(Parser.ATTR_INITCLASS + " not instantiated : " + e.getLocalizedMessage() + e); 479 } catch (IllegalArgumentException e) { 480 System.err.println(Parser.ATTR_INITCLASS + " not instantiated : " + e.getLocalizedMessage() + e); 481 } catch (InvocationTargetException e) { 482 System.err.println(Parser.ATTR_INITCLASS + " not instantiated : " + e.getLocalizedMessage() + e); 483 } catch (InstantiationException e) { 484 System.err.println(Parser.ATTR_INITCLASS + " not instantiated : " + e.getLocalizedMessage() + e); 485 } catch (RuntimeException re) { 486 throw re; 487 } catch (Exception e) { 488 throw new Exception (Parser.ATTR_INITCLASS + " not instantiated : " + e.getLocalizedMessage(), e); 489 } 490 } 491 492 obj = initParameter != null ? factory.newInstance(new Object []{initParameter}) : factory.newInstance(); 493 constructed = true; 494 if (id != null) { 498 engine.getIdMap().put(id, obj); 499 } 500 } 501 Attribute actionAttr = element.getAttribute("Action"); 506 if (actionAttr != null) { 507 element.removeAttribute(actionAttr); 508 attributes.add(0, actionAttr); 509 } 510 if (element.getAttribute("Text") == null && 0 < element.getTextTrim().length()) { 514 attributes.add(new Attribute("Text", element.getTextTrim())); 515 } 516 List remainingAttrs = applyAttributes(obj, factory, attributes); 517 521 LayoutManager layoutMgr = obj instanceof Container ? ((Container) obj).getLayout() : null; 522 523 Iterator it = element.getChildren().iterator(); 524 while (it != null && it.hasNext()) { 525 Element child = (Element) it.next(); 526 if ("buttongroup".equalsIgnoreCase(child.getName())) { 530 531 int k = JMenu.class.isAssignableFrom(obj.getClass()) ? ((JMenu) obj).getItemCount() : ((Container) obj).getComponentCount(); 532 getSwing(child, obj); 533 int n = JMenu.class.isAssignableFrom(obj.getClass()) ? ((JMenu) obj).getItemCount() : ((Container) obj).getComponentCount(); 534 ButtonGroup btnGroup = new ButtonGroup(); 538 if (null != child.getAttribute(Parser.ATTR_ID)) { 540 engine.getIdMap().put(child.getAttribute(Parser.ATTR_ID).getValue(), btnGroup); 541 } 542 while (k < n) { 543 putIntoBtnGrp(JMenu.class.isAssignableFrom(obj.getClass()) ? ((JMenu) obj).getItem(k++) : ((Container) obj).getComponent(k++), btnGroup); 544 } 545 continue; 546 } 547 548 Attribute constrnAttr = child.getAttribute(Parser.ATTR_CONSTRAINTS); 552 Object constrains = null; 553 if (constrnAttr != null && layoutMgr != null) { 554 child.removeAttribute(Parser.ATTR_CONSTRAINTS); constrains = ConstraintsConverter.convert(layoutMgr.getClass(), constrnAttr); 556 } 557 558 Element grandchild = child.getChild("gridbagconstraints"); 563 if (grandchild != null) { 564 addChild((Container) obj, (Component) getSwing(child, null), getSwing(grandchild, null)); 565 } else if (!child.getName().equals("gridbagconstraints")) { 566 addChild((Container) obj, (Component) getSwing(child, null), constrains); 567 } 568 } 569 570 if (remainingAttrs != null && 0 < remainingAttrs.size()) { 574 remainingAttrs = applyAttributes(obj, factory, remainingAttrs); 575 if (remainingAttrs != null) { 576 it = remainingAttrs.iterator(); 577 while (it != null && it.hasNext()) { 578 Attribute attr = (Attribute) it.next(); 579 if (JComponent.class.isAssignableFrom(obj.getClass())) { 580 ((JComponent) obj).putClientProperty(attr.getName(), attr.getValue()); 581 if (SwingEngine.DEBUG_MODE) { 582 System.out.println("ClientProperty put: " + obj.getClass().getName() + "(" + id + "): " + attr.getName() + "=" + attr.getValue()); 583 } 584 } else { 585 if (SwingEngine.DEBUG_MODE) { 586 System.err.println(attr.getName() + " not applied for tag: <" + element.getName() + ">"); 587 } 588 } 589 } 590 } 591 } 592 593 return (constructed ? obj : null); 594 } 595 596 620 private List applyAttributes(Object obj, Factory factory, List attributes) throws Exception { 621 626 for (int i = 0; i < attributes.size(); i++) { 627 Attribute attr = (Attribute) attributes.get(i); 628 if (Parser.ATTR_ACTION.equalsIgnoreCase(attr.getName())) { 629 attributes.remove(i); 630 attributes.add(0, attr); 631 break; 632 } 633 } 634 635 639 Iterator it = attributes.iterator(); 640 List list = new ArrayList(); Action action = null; 643 while (it != null && it.hasNext()) { Attribute attr = (Attribute) it.next(); 645 646 if (Parser.ATTR_ID.equals(attr.getName())) 647 continue; 648 if (Parser.ATTR_REFID.equals(attr.getName())) 649 continue; 650 if (Parser.ATTR_USE.equals(attr.getName())) 651 continue; 652 653 if (action != null && attr.getName().startsWith(Parser.ATTR_MACOS_PREFIX)) { 654 mac_map.put(attr.getName(), action); 655 continue; 656 } 657 658 if (JLabel.class.isAssignableFrom(obj.getClass()) && attr.getName().equalsIgnoreCase("LabelFor")) { 659 lbl_map.put(obj, attr.getValue()); 660 continue; 661 } 662 663 Method method = factory.guessSetter(attr.getName()); 665 if (method != null) { 666 Class paraType = method.getParameterTypes()[0]; 670 Converter converter = cvtlib.getConverter(paraType); 671 672 if (converter != null) { Object para = null; 674 try { 675 if (Action.class.equals(paraType)) { 680 para = engine.getClient().getClass().getField(attr.getValue()).get(engine.getClient()); 681 action = (Action) para; 682 } else { 683 para = converter.convert(paraType, attr, engine.getLocalizer()); 684 } 685 686 method.invoke(obj, new Object []{para}); 688 } catch (NoSuchFieldException e) { 689 if (SwingEngine.DEBUG_MODE) { 690 System.err.println("Action '" + attr.getValue() + "' not set. Public Action '" + attr.getValue() + "' not found in " + engine.getClient().getClass().getName()); 691 } 692 } catch (InvocationTargetException e) { 693 if (obj instanceof RootPaneContainer) { 700 Container rootpane = ((RootPaneContainer) obj).getContentPane(); 701 Factory f = engine.getTaglib().getFactory(rootpane.getClass()); 702 Method m = f.guessSetter(attr.getName()); 703 try { 704 m.invoke(rootpane, new Object []{para}); } catch (Exception ex) { 706 list.add(attr); 707 } 708 } else { 709 list.add(attr); 710 } 711 } catch (Exception e) { 712 throw new Exception (e + ":" + method.getName() + ":" + para, e); 713 } 714 continue; 715 } 716 717 if (paraType.equals(Object .class)) { 721 try { 722 String s = attr.getValue(); 723 if (Parser.LOCALIZED_ATTRIBUTES.contains(attr.getName().toLowerCase()) && attr.getAttributeType() == Attribute.CDATA_TYPE) { 724 s = engine.getLocalizer().getString(s); 725 } 726 method.invoke(obj, new Object []{s}); } catch (Exception e) { 728 list.add(attr); 729 } 730 continue; 731 } 732 733 if (paraType.isPrimitive()) { 737 try { 738 method.invoke(obj, new Object []{PrimitiveConverter.conv(paraType, attr, engine.getLocalizer())}); } catch (Exception e) { 740 list.add(attr); 741 } 742 continue; 743 } 744 list.add(attr); 748 continue; 749 } else { 750 try { 754 Field field = obj.getClass().getField(attr.getName()); 755 if (field != null) { 756 Converter converter = cvtlib.getConverter(field.getType()); 757 if (converter != null) { 758 Object fieldValue = converter.convert(field.getType(), attr, null); 762 if (String .class.equals(converter.convertsTo())) { 763 fieldValue = engine.getLocalizer().getString((String ) fieldValue); 764 } 765 field.set(obj, fieldValue); } else { 767 list.add(attr); 768 } 769 } else { 770 list.add(attr); 771 } 772 } catch (Exception e) { 773 list.add(attr); 774 } 775 } 776 } return list; 778 } 779 780 781 786 private void cloneAttributes(Element target) { 787 Element source = null; 788 if (target.getAttribute(Parser.ATTR_REFID) != null) { 789 source = find(jdoc.getRootElement(), target.getAttribute(Parser.ATTR_REFID).getValue().trim()); 790 } else if (target.getAttribute(Parser.ATTR_USE) != null) { 791 source = find(jdoc.getRootElement(), target.getAttribute(Parser.ATTR_USE).getValue().trim()); 792 } 793 if (source != null) { 794 Iterator it = source.getAttributes().iterator(); 795 while (it != null && it.hasNext()) { 796 Attribute attr = (Attribute) it.next(); 797 String name = attr.getName().trim(); 798 if (!Parser.ATTR_ID.equals(name) && target.getAttribute(name) == null) { 803 Attribute attrcln = (Attribute) attr.clone(); 804 attrcln.detach(); 805 target.setAttribute(attrcln); 806 } 807 } } 809 } 810 811 812 821 private static Component addChild(Container parent, Component component, Object constrains) { 822 if (component == null) 823 return null; 824 if (component instanceof JMenuBar) { 828 829 try { 830 Method m = parent.getClass().getMethod("setJMenuBar", new Class []{JMenuBar.class}); 831 m.invoke(parent, new Object []{component}); 832 } catch (NoSuchMethodException e) { 833 parent.add(component); 834 } catch (Exception e) { 835 } 837 838 } else if (parent instanceof RootPaneContainer) { 839 RootPaneContainer rpc = (RootPaneContainer) parent; 845 if (component instanceof LayoutManager) { 846 rpc.getContentPane().setLayout((LayoutManager) component); 847 } else { 848 rpc.getContentPane().add(component, constrains); 849 } 850 } else if (parent instanceof JScrollPane) { 851 JScrollPane scrollPane = (JScrollPane) parent; 855 scrollPane.setViewportView(component); 856 } else if (parent instanceof JSplitPane) { 857 JSplitPane splitPane = (JSplitPane) parent; 861 if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { 862 if (splitPane.getTopComponent() == null) { 866 splitPane.setTopComponent(component); 867 } else { 868 splitPane.setBottomComponent(component); 869 } 870 } else { 871 if (splitPane.getLeftComponent() == null) { 875 splitPane.setLeftComponent(component); 876 } else { 877 splitPane.setRightComponent(component); 878 } 879 } 880 } else if (parent instanceof JMenuBar && component instanceof JMenu) { 881 JMenuBar menuBar = (JMenuBar) parent; 885 menuBar.add(component, constrains); 886 } else if (JSeparator.class.isAssignableFrom(component.getClass())) { 887 if (JToolBar.class.isAssignableFrom(parent.getClass())) 891 ((JToolBar) parent).addSeparator(); 892 else if (JPopupMenu.class.isAssignableFrom(parent.getClass())) 893 ((JPopupMenu) parent).addSeparator(); 894 else if (JMenu.class.isAssignableFrom(parent.getClass())) 895 ((JMenu) parent).addSeparator(); 896 else if (constrains != null) 897 parent.add(component, constrains); 898 else 899 parent.add(component); 900 901 } else if (parent instanceof Container) { 902 if (constrains == null) { 906 parent.add(component); 907 } else { 908 parent.add(component, constrains); 909 } 910 } 911 return component; 912 } 913 914 915 921 private static void moveContent(Element source, Element target) { 922 List list = source.getContent(); 923 while (!list.isEmpty()) { 924 Object obj = list.remove(0); 925 target.getContent().add(obj); 926 } 927 } 928 929 936 private static Element find(Element element, String id) { 937 Element elem = null; 938 Attribute attr = element.getAttribute(Parser.ATTR_ID); 939 if (attr != null && id.equals(attr.getValue().trim())) { 940 elem = element; 941 } else { 942 Iterator it = element.getChildren().iterator(); 943 while (it != null && it.hasNext() && elem == null) { 944 elem = find((Element) it.next(), id.trim()); 945 } 946 } 947 return elem; 948 } 949 950 956 private static void putIntoBtnGrp(Object obj, ButtonGroup grp) throws Exception { 957 if (AbstractButton.class.isAssignableFrom(obj.getClass())) { 958 grp.add((AbstractButton) obj); 959 } else if (JComponent.class.isAssignableFrom(obj.getClass())) { 960 JComponent jp = (JComponent) obj; 961 for (int i = 0; i < jp.getComponentCount(); i++) { 962 putIntoBtnGrp(jp.getComponent(i), grp); 963 } 964 } } 966 } 967 | Popular Tags |