| 1 19 20 package org.objectweb.jac.aspects.gui; 21 22 import java.lang.reflect.Array; 23 import java.lang.reflect.Modifier; 24 import java.util.Arrays; 25 import java.util.Collection; 26 import java.util.Hashtable; 27 import java.util.Iterator; 28 import java.util.Map; 29 import java.util.Vector; 30 import org.apache.log4j.Logger; 31 import org.objectweb.jac.core.Collaboration; 32 import org.objectweb.jac.core.Naming; 33 import org.objectweb.jac.core.ObjectRepository; 34 import org.objectweb.jac.core.Wrappee; 35 import org.objectweb.jac.core.rtti.AbstractMethodItem; 36 import org.objectweb.jac.core.rtti.ClassItem; 37 import org.objectweb.jac.core.rtti.ClassRepository; 38 import org.objectweb.jac.core.rtti.CollectionItem; 39 import org.objectweb.jac.core.rtti.FieldItem; 40 import org.objectweb.jac.core.rtti.MetaItem; 41 import org.objectweb.jac.core.rtti.MethodItem; 42 import org.objectweb.jac.core.rtti.MixinMethodItem; 43 import org.objectweb.jac.core.rtti.RttiAC; 44 import org.objectweb.jac.core.rtti.VirtualClassItem; 45 import org.objectweb.jac.util.Classes; 46 import org.objectweb.jac.util.Enum; 47 import org.objectweb.jac.util.ExtArrays; 48 import org.objectweb.jac.util.ExtBoolean; 49 import org.objectweb.jac.util.NotInCollectionPredicate; 50 import org.objectweb.jac.util.Predicate; 51 import org.objectweb.jac.util.Stack; 52 import org.objectweb.jac.util.Strings; 53 54 58 59 public class GenericFactory { 60 static Logger logger = Logger.getLogger("gui.generic"); 61 static Logger loggerAssoc = Logger.getLogger("associations"); 62 63 71 72 public static View createObjectView( 73 ViewFactory factory, 74 DisplayContext context, 75 String viewName, 76 Object substance) 77 { 78 logger.debug("createObjectView(" 79 + factory + "," + Strings.hex(substance) + "," + viewName + ")"); 80 81 if (substance == null) { 82 return factory.createView("null", "Empty", context); 83 } 84 85 if (substance instanceof Number 86 || substance instanceof Boolean 87 || substance instanceof Character 88 || substance instanceof String) { 89 return factory.createView( 90 substance.getClass().getName(), 91 "Field", 92 new Object[] { substance, null, null }, 93 context); 94 } 95 96 Class substance_type = substance.getClass(); 97 ClassItem cli = ClassRepository.get().getClass(substance_type); 98 99 CompositeView view = 100 (CompositeView) factory.createCompositeView( 101 cli.getName(), 102 "ObjectView", 103 context); 104 105 fillObjectView(view, cli, viewName, substance); 106 Collection dependencies = GuiAC.getDependentFields(cli); 107 if (dependencies != null) { 108 Iterator it = dependencies.iterator(); 109 while (it.hasNext()) { 110 FieldItem field = (FieldItem) it.next(); 111 Utils.registerField(substance, field, EventHandler.get(), view); 112 } 113 } 114 return view; 115 } 116 117 public static void fillObjectView( 118 CompositeView view, 119 ClassItem cli, 120 String viewName, 121 Object substance) 122 { 123 ObjectView objectView = GuiAC.getView(cli, viewName); 124 ViewFactory factory = view.getFactory(); 125 DisplayContext context = view.getContext(); 126 String[] categories = (String[]) cli.getAttribute(GuiAC.CATEGORIES); 127 String[] icons = GuiAC.getCategoriesIcons(cli); 128 String[] labels = GuiAC.getCategoriesLabels(cli); 129 if (labels == null) 130 labels = categories; 131 132 view.setStyle((String) cli.getAttribute(GuiAC.STYLE)); 133 view.setDescription(GuiAC.getDescription(substance, "<b>", "</b>")); 134 135 logger.debug("categories = " 136 + (categories != null 137 ? Arrays.asList(categories).toString() 138 : "null")); 139 140 if (categories == null) { 141 view.addView( 142 createObjectView( 143 factory, 144 context, 145 objectView, 146 substance, 147 null)); 148 } else { 149 TabsView tabbedPane = 150 (TabsView) factory.createCompositeView( 151 cli.getName(), 152 "Tabbed", 153 context); 154 for (int i = 0; i < categories.length; i++) { 155 logger.debug("add tab for category " + categories[i]); 156 157 String icon; 158 if ((icons != null) && (Array.getLength(icons) > i)) 159 icon = icons[i]; 160 else 161 icon = null; 162 163 CompositeView tab = 164 createObjectView( 165 factory, 166 context, 167 objectView, 168 substance, 169 categories[i]); 170 if (!compositeViewIsEmpty(tab)) 171 tabbedPane.addTab(tab, labels[i], icon); 172 else 173 logger.debug("tab[" + categories[i] + "] is empty"); 174 } 175 view.addView((CompositeView) tabbedPane); 176 } 177 } 178 179 186 187 public static View createObjectViewNoTab( 188 ViewFactory factory, 189 DisplayContext context, 190 Object substance) 191 { 192 logger.debug("createObjectViewNoTab(" 193 + factory 194 + "," 195 + Strings.hex(substance) 196 + ")"); 197 198 if (substance == null) { 199 return factory.createView( 200 substance.getClass().getName(), 201 "Empty", 202 context); 203 } else { 204 return createObjectView( 205 factory, 206 context, 207 GuiAC.getView( 208 ClassRepository.get().getClass(substance), 209 "default"), 210 substance, 211 null); 212 } 213 } 214 215 219 public static boolean compositeViewIsEmpty(CompositeView view) { 220 Iterator it = view.getViews().iterator(); 221 while (it.hasNext()) { 222 View subView = (View) it.next(); 223 if (!(subView instanceof CompositeView)) 224 return false; 225 else if (!compositeViewIsEmpty((CompositeView) subView)) 226 return false; 227 } 228 return true; 229 } 230 231 241 protected static CompositeView createObjectView( 242 ViewFactory factory, 243 DisplayContext context, 244 ObjectView view, 245 Object substance, 246 String category) 247 { 248 logger.debug("createObjectView(" 249 + factory + "," + Strings.hex(substance) + "," 250 + category+ "," + view.getName() + ")"); 251 CompositeView resultPane = 252 factory.createCompositeView( 253 substance.getClass().getName() + "[" + category + "]", 254 "Container", 255 new Object[] { new Integer(Constants.VERTICAL)}, 256 context); 257 258 Class substance_type = substance.getClass(); 259 ClassItem cli = ClassRepository.get().getClass(substance_type); 260 261 CompositeView fieldpane = 262 factory.createCompositeView( 263 "fields", 264 "ParameterContainer", 265 new Object[] { Boolean.TRUE }, 266 context); 267 269 271 FieldItem[] fields = null; 272 fields = view.getAttributesOrder(); 273 if (fields == null) 274 fields = cli.getFields(); 275 276 boolean embedded = view.getName().equals(GuiAC.AUTOCREATE_VIEW); 277 logger.debug("attributes_order = " + Arrays.asList(fields)); 278 FieldItem[] groups = (FieldItem[]) cli.getAttribute(GuiAC.LINE_BREAKS); 279 int curgroup = 0; 280 281 CompositeView subFieldPane = null; 282 FieldItem oppositeRole = 283 (FieldItem) Collaboration.get().getAttribute(GuiAC.OPPOSITE_ROLE); 284 loggerAssoc.debug("opposite role = " + oppositeRole); 285 boolean first = true; 286 for (int i = 0; i < fields.length; i++) { 287 if (groups != null 288 && curgroup < groups.length 289 && groups[curgroup] == fields[i]) { 290 if (subFieldPane != null) { 291 fieldpane.addView(subFieldPane); 292 } 293 subFieldPane = 294 factory.createCompositeView( 295 "subField[" + i + "]", 296 "Container", 297 new Object[] { new Integer(Constants.HORIZONTAL)}, 298 context); 299 first = true; 300 curgroup++; 301 } 302 FieldItem field = fields[i]; 303 if (GuiAC.isMemberInCategory(field, category) 305 && GuiAC.isVisible(substance, field) 306 && !field.isStatic() 307 && !field.equals(oppositeRole)) { 308 CompositeView pane = 309 subFieldPane != null ? subFieldPane : fieldpane; 310 try { 311 if (!first && subFieldPane != null) 312 subFieldPane.addHorizontalStrut(10); 313 pane.addView( 314 getFieldPane( 315 factory, 316 context, 317 substance, 318 view, 319 field, 320 embedded)); 321 first = false; 322 } catch (Exception e) { 323 logger.error( 324 "Failed to build view for field \""+field+"\"", e); 325 } 326 } 327 } 328 if (subFieldPane != null) { 329 fieldpane.addView(subFieldPane); 330 } 331 332 resultPane.addView(fieldpane); 333 334 logger.debug("getMethodsPane for " + cli); 335 336 Collection meths = new Vector(); 337 MethodItem[] ms = view.getMethodsOrder(); 339 if (ms != null) { 340 meths = Arrays.asList(ms); 341 } 342 344 logger.debug("methods = " + meths); 345 346 CompositeView methodsPane = 347 getMethodsPane(factory, context, substance, meths, category, view); 348 if (methodsPane != null) { 349 logger.debug("adding methodPane"); 350 resultPane.addView(methodsPane); 351 } 352 353 return resultPane; 354 355 } 356 357 public static View getFieldPane( 358 ViewFactory factory, 359 DisplayContext context, 360 Object substance, 361 ObjectView objectView, 362 FieldItem field, 363 boolean embedded) 364 { 365 GuiAC.pushGraphicContext(field); 366 try { 367 MemberItemView memberView = GuiAC.getView(field, objectView.getName()); 368 if (field.isReference()) { 369 return getReferenceFieldPane( 370 factory, 371 context, 372 substance, 373 field, 374 embedded, 375 objectView,memberView); 376 } else if (field.isPrimitive() 377 || factory.hasViewerFor(field.getTypeItem().getName())) { 378 return getPrimitiveFieldPane( 379 factory, 380 context, 381 substance, 382 field, 383 objectView, 384 memberView, 385 embedded); 386 } else if (field instanceof CollectionItem) { 387 return getCollectionPane( 388 factory, 389 context, 390 substance, 391 objectView, 392 (CollectionItemView) memberView, 393 (CollectionItem) field); 394 } 395 } finally { 396 GuiAC.popGraphicContext(); 397 } 398 return null; 399 } 400 401 405 protected static boolean getViewer( 406 Object substance, 407 FieldItem field, 408 Object value, 409 CompositeView container, 410 ViewFactory factory, 411 DisplayContext context) 412 { 413 Stack types = new Stack(); 414 types.push(ClassRepository.get().getClass(field.getType())); 415 if (value != null) { 416 ClassItem actualClass = ClassRepository.get().getClass(value); 417 if (types.safeTop()!=actualClass) 418 types.push(actualClass); 419 } 420 421 Enum enum = GuiAC.getEnum(field); 422 if (enum!=null) { 423 types.push(ClassRepository.get().getVirtualClass("Enum")); 424 } 425 426 MetaItem type = RttiAC.getFieldType(field,substance); 427 if (type!=null && types.safeTop()!=type) 428 types.push(type); 429 430 logger.debug("types = " + types); 431 boolean foundViewer = false; 432 while (!types.empty()) { 433 type = (MetaItem) types.pop(); 434 if (factory.hasViewerFor(type.getName())) { 435 container.addView( 436 factory.createView( 437 field.getName(), 438 type.getName(), 439 new Object[] { value, substance, field }, 440 context)); 441 foundViewer = true; 442 break; 443 } 444 } 445 return foundViewer; 446 } 447 448 460 protected static View getPrimitiveFieldPane( 461 ViewFactory factory, 462 DisplayContext context, 463 Object substance, 464 FieldItem field, 465 ObjectView objectView, 466 MemberItemView memberView, 467 boolean embedded) 468 { 469 logger.debug("primitive field : " + substance + "," + field.getName()); 470 471 475 476 CompositeView container = 477 factory.createCompositeView( 478 "field[" + field.getName() + "]", 479 "Container", 480 new Object[] { new Integer(Constants.HORIZONTAL)}, 481 context); 482 Border border = GuiAC.getBorder(field); 483 if (border != null) { 484 border.setTitle(GuiAC.getLabel(field)); 485 container.setViewBorder(border); 486 } 487 container.setStyle((String) field.getAttribute(GuiAC.STYLE)); 488 Boolean displayLabel = 489 (Boolean) field.getAttribute(GuiAC.DISPLAY_LABEL); 490 boolean useEditor = 491 GuiAC.isEditable(substance, field) 492 && memberView.isEmbeddedEditor(embedded) 493 && !objectView.isReadOnly(); 494 if ((border == null) 495 && (displayLabel == null 496 || (displayLabel != null && displayLabel.booleanValue()))) { 497 container.addView( 498 factory.createView( 499 GuiAC.getLabel(field) + ": ", 500 "Label", 501 context)); 502 } 503 504 FieldEditor editor = null; 505 if (useEditor) { 506 MethodItem setter = field.getSetter(); 507 if (setter != null) { 508 try { 509 editor = 510 getEditorComponent( 511 factory, 512 context, 513 field.getSubstance(substance), 514 setter, 515 0, 516 true, 517 null); 518 context.addEditor(editor); 519 container.addView(editor); 520 } catch (Exception e) { 521 logger.error("Failed to build editor component for "+ 523 substance+"."+field.getName(),e); 524 } 525 } 526 } 527 if (editor==null) { 528 Object value = field.getThroughAccessor(substance); 529 if (!getViewer(substance, 530 field, 531 value, 532 container, 533 factory, 534 context)) 535 { 536 Enum enum = GuiAC.getEnum(field); 537 if (enum != null) { 538 container.addView( 539 factory.createView( 540 field.getName(), 541 "Enum", 542 new Object[] { value, enum, substance, field }, 543 context)); 544 } else { 545 container.addView( 546 factory.createView( 547 field.getName(), 548 "Field", 549 new Object[] { value, substance, field }, 550 context)); 551 } 552 } 553 554 if (GuiAC.isEditable(substance, field) && !objectView.isReadOnly()) { 555 container.addView( 556 getEditButton(factory, substance, field, context)); 557 } 558 } 559 return container; 560 } 561 562 572 static protected View getReferenceFieldPane( 573 ViewFactory factory, 574 DisplayContext context, 575 Object substance, 576 FieldItem field, 577 boolean embedded, 578 ObjectView objectView, 579 MemberItemView memberView) 580 { 581 logger.debug("reference field : " + field.getName()); 582 586 CompositeView container = 587 factory.createCompositeView( 588 "field[" + field.getName() + "]", 589 "Container", 590 new Object[] { new Integer(Constants.HORIZONTAL)}, 591 context); 592 593 Border border = GuiAC.getBorder(field); 594 if (border != null) { 595 border.setTitle(GuiAC.getLabel(field)); 596 container.setViewBorder(border); 597 } 598 599 container.setStyle((String) field.getAttribute(GuiAC.STYLE)); 600 Boolean displayLabel = 601 (Boolean) field.getAttribute(GuiAC.DISPLAY_LABEL); 602 603 if ((border == null) 604 && (displayLabel == null 605 || (displayLabel != null && displayLabel.booleanValue()))) { 606 607 container.addView( 608 factory.createView( 609 GuiAC.getLabel(field) + ": ", 610 "Label", 611 context)); 612 } 613 614 if ((memberView != null && memberView.isEmbedded()) && !embedded) { 615 FieldItem oppositeRole = 616 (FieldItem) field.getAttribute(RttiAC.OPPOSITE_ROLE); 617 if (oppositeRole instanceof CollectionItem) { 618 loggerAssoc.debug("Ignoring collection oppositeRole " + oppositeRole); 619 oppositeRole = null; 620 } 621 Collaboration.get().addAttribute(GuiAC.OPPOSITE_ROLE, oppositeRole); 622 try { 623 logger.debug("embedded view for " + field); 624 container.addView( 625 factory.createObjectView( 626 "embbeded " + field.getName(), 627 field.getThroughAccessor(substance), 628 substance, 629 field, 630 context)); 631 } finally { 632 Collaboration.get().addAttribute(GuiAC.OPPOSITE_ROLE, null); 633 } 634 } else { 635 if (memberView.isEmbeddedEditor(embedded) 636 && GuiAC.isEditable(substance, field) 637 && !objectView.isReadOnly()) 638 { 639 MethodItem setter = field.getSetter(); 640 FieldEditor editor = 641 getEditorComponent( 642 factory, 643 context, 644 field.getSubstance(substance), 645 setter, 646 0, 647 true, 648 null); 649 container.addView(editor); 650 context.addEditor(editor); 651 } else { 652 View refView = 655 factory.createView( 656 field.getName(), 657 "Reference", 658 new Object[] { 659 field.getThroughAccessor(substance), 660 field.getSubstance(substance), 661 field.getField()}, 662 context); 663 if (refView instanceof LinkGenerator) 664 ((LinkGenerator)refView).setEnableLinks(objectView.areLinksEnabled()); 665 container.addView(refView); 666 667 if (GuiAC.isEditable(field.getSubstance(substance),field.getField()) 668 && !objectView.isReadOnly()) { 669 container.addView( 670 getEditButton( 671 factory, 672 field.getSubstance(substance), 673 field.getField(), 674 context)); 675 } 676 } 678 } 679 return container; 680 } 681 682 694 static protected void addChoices( 695 ComboBoxModel choice, 696 ClassItem type, 697 Enum enum, 698 Object substance, 699 FieldItem field, 700 boolean nullAllowed, 701 String nullLabel, 702 Predicate predicate) 703 { 704 Collection all_objects = null; 706 logger.debug("ObjectChooser.type = " + type 707 + "; predicate=" + predicate 708 + "; field=" + field 709 + "; nullAllowed=" + nullAllowed); 710 if (field != null) { 711 Object fieldChoice = field.getAttribute(GuiAC.FIELD_CHOICE); 712 logger.debug(" fieldChoice = "+fieldChoice); 713 if (fieldChoice instanceof MethodItem) { 714 try { 715 all_objects = 716 (Collection) (((MethodItem) fieldChoice) 717 .invoke(null, ExtArrays.emptyObjectArray)); 718 } catch (Exception e) { 719 e.printStackTrace(); 720 } 721 } else if (fieldChoice instanceof CollectionItem) { 722 all_objects = ((CollectionItem)fieldChoice).getActualCollectionThroughAccessor(substance); 723 } 724 choice.setType(type); 725 } 726 727 if (enum!=null) { 728 Iterator it = enum.getValues().iterator(); 729 while (it.hasNext()) { 730 String str = (String) it.next(); 731 choice.addObject(new Integer(enum.string2int(str)), str); 732 } 733 choice.setType(type); 734 if (nullAllowed) { 735 choice.setNullLabel(nullLabel); 736 choice.addObject(null); 737 } 738 } else { 739 740 if (all_objects == null) { 741 all_objects = ObjectRepository.getObjects(type); 742 choice.setType(type); 743 } 744 if (nullAllowed) { 745 choice.setNullLabel(nullLabel); 746 choice.addObject(null); 747 } 748 749 Iterator i = all_objects.iterator(); 750 while (i.hasNext()) { 751 Object object = i.next(); 752 if (predicate == null || predicate.apply(object)) { 753 choice.addObject(object); 754 } 755 } 756 choice.sort(); 757 } 758 } 759 760 763 static protected View getEditButton( 764 ViewFactory factory, 765 Object substance, 766 &
|