001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.visualweb.insync.live;
042:
043: import java.beans.BeanInfo;
044: import java.beans.EventSetDescriptor;
045: import java.beans.MethodDescriptor;
046: import java.beans.PropertyChangeEvent;
047: import java.beans.PropertyChangeListener;
048: import java.beans.PropertyDescriptor;
049: import java.util.ArrayList;
050: import java.util.Collections;
051: import java.util.Enumeration;
052: import java.util.HashMap;
053: import java.util.Iterator;
054:
055: import javax.swing.tree.TreeNode;
056:
057: import com.sun.rave.designtime.DisplayAction;
058: import com.sun.rave.designtime.EventDescriptor;
059: import com.sun.rave.designtime.DesignBean;
060: import com.sun.rave.designtime.DesignInfo;
061: import com.sun.rave.designtime.DesignContext;
062: import com.sun.rave.designtime.DesignEvent;
063: import com.sun.rave.designtime.DesignProperty;
064: import com.sun.rave.designtime.Position;
065: import com.sun.rave.designtime.event.DesignBeanListener;
066:
067: /**
068: * Abstract base partial implementation of a DesignBean. Handles management of the BeanInfo and
069: * DesignInfo, as well as the live instance.
070: *
071: * @author Joe Nuxoll
072: * @author Carl Quinn
073: */
074: public abstract class SourceDesignBean implements DesignBean, TreeNode,
075: PropertyChangeListener {
076:
077: public static final SourceDesignBean[] EMPTY_ARRAY = {};
078:
079: protected final LiveUnit unit;
080: protected final BeanInfo beanInfo;
081: protected final DesignInfo liveBeanInfo;
082:
083: protected SourceDesignBean parent;
084: protected ArrayList children; // null when not a container
085: protected Object instance;
086: protected boolean ready; // true when created and ready to expose to clients
087:
088: /**
089: * @param unit
090: * @param beanInfo
091: * @param liveBeanInfo
092: * @param parent
093: * @param instance
094: */
095: protected SourceDesignBean(LiveUnit unit, BeanInfo beanInfo,
096: DesignInfo liveBeanInfo, SourceDesignBean parent,
097: Object instance) {
098: this .unit = unit;
099: this .parent = parent;
100: this .beanInfo = beanInfo;
101: this .liveBeanInfo = liveBeanInfo;
102: this .instance = instance;
103: }
104:
105: /**
106: * Internal mutator for synthetic liveBean updates
107: * @param instance
108: */
109: public void setInstance(Object instance) {
110: this .instance = instance;
111: }
112:
113: /**
114: * Invoke the registered cleanup method for the bean's instance
115: */
116: public void invokeCleanupMethod() {
117: }
118:
119: public static class ClipImage {
120: Class type;
121: String facetName;
122: String instanceName;
123: SourceDesignBean bean; // for cross-reference fixup
124: SourceDesignProperty.ClipImage[] props;
125: SourceDesignEvent.ClipImage[] events;
126: ClipImage[] children;
127:
128: public String toString() {
129: StringBuffer sb = new StringBuffer();
130: toString(sb);
131: return sb.toString();
132: }
133:
134: public void toString(StringBuffer sb) {
135: sb.append("[DesignBean.ClipImage");
136: sb.append(" type=" + type.getName());
137: sb.append(" facetName=" + facetName);
138: sb.append(" instanceName=" + instanceName);
139: if (props != null) {
140: sb.append(" props=");
141: for (int i = 0; i < props.length; i++)
142: props[i].toString(sb);
143: }
144: if (events != null) {
145: sb.append(" events=");
146: for (int i = 0; i < events.length; i++)
147: events[i].toString(sb);
148: }
149: if (children != null) {
150: sb.append(" children=");
151: for (int i = 0; i < children.length; i++)
152: children[i].toString(sb);
153: }
154: sb.append("]");
155: }
156: }
157:
158: public ClipImage getClipImage() {
159: ClipImage ci = new ClipImage();
160: ci.type = beanInfo.getBeanDescriptor().getBeanClass();
161: ci.instanceName = getInstanceName();
162: ci.bean = this ;
163:
164: if (properties == null)
165: loadProperties();
166:
167: if (properties != null) {
168: ArrayList pcis = new ArrayList(properties.size());
169: for (int i = 0; i < properties.size(); i++) {
170: SourceDesignProperty slp = (SourceDesignProperty) properties
171: .get(i);
172: SourceDesignProperty.ClipImage pci = slp.getClipImage();
173: if (pci != null)
174: pcis.add(pci);
175: }
176: ci.props = new SourceDesignProperty.ClipImage[pcis.size()];
177: pcis.toArray(ci.props);
178: }
179:
180: if (events == null) {
181: loadEvents();
182: }
183:
184: if (events != null) {
185: ArrayList ecis = new ArrayList(events.size());
186: for (int i = 0; i < events.size(); i++) {
187: SourceDesignEvent sle = (SourceDesignEvent) events
188: .get(i);
189: SourceDesignEvent.ClipImage eci = sle.getClipImage();
190: if (eci != null)
191: ecis.add(eci);
192: }
193: ci.events = new SourceDesignEvent.ClipImage[ecis.size()];
194: ecis.toArray(ci.events);
195: }
196:
197: if (children != null) {
198: ci.children = new ClipImage[children.size()];
199: for (int i = 0; i < children.size(); i++)
200: ci.children[i] = ((SourceDesignBean) children.get(i))
201: .getClipImage();
202: }
203: return ci;
204: }
205:
206: //------------------------------------------------------------------------------- PropertyChange
207:
208: /*
209: protected void hookPropertyChangeListener() {
210: try {
211: Method apcl = instance.getClass().getMethod("addPropertyChangeListener",
212: new Class[] {PropertyChangeListener.class});
213: if (apcl != null)
214: apcl.invoke(instance, new Object[] {this});
215: }
216: catch (Throwable t) {
217: }
218: }
219:
220: protected void unhookPropertyChangeListener() {
221: try {
222: Method rpcl = instance.getClass().getMethod("removePropertyChangeListener",
223: new Class[] {PropertyChangeListener.class});
224: if (rpcl != null)
225: rpcl.invoke(instance, new Object[] {this});
226: }
227: catch (Throwable t) {
228: }
229: }*/
230:
231: //------------------------------------------------------------------------------------- DesignBean
232: public BeanInfo getBeanInfo() {
233: return beanInfo;
234: }
235:
236: public DesignInfo getDesignInfo() {
237: return liveBeanInfo;
238: }
239:
240: public Object getInstance() {
241: return instance;
242: }
243:
244: public String getInstanceName() {
245: return null;
246: }
247:
248: public boolean canSetInstanceName() {
249: return false;
250: }
251:
252: public boolean setInstanceName(String name) {
253: return setInstanceName(name, false);
254: }
255:
256: public boolean setInstanceName(String name, boolean autoNumber) {
257: return false;
258: }
259:
260: public DesignContext getDesignContext() {
261: return unit;
262: }
263:
264: public DesignBean getBeanParent() {
265: return parent;
266: }
267:
268: public boolean isContainer() {
269: return children != null;
270: }
271:
272: public int getChildBeanCount() {
273: return children != null ? children.size() : -1;
274: }
275:
276: public DesignBean getChildBean(int index) {
277: return children != null ? (DesignBean) children.get(index)
278: : null;
279: }
280:
281: public DesignBean[] getChildBeans() {
282: return children != null ? (DesignBean[]) children
283: .toArray(SourceDesignBean.EMPTY_ARRAY) : null;
284: }
285:
286: //----------------------------------------------------------------------------------- Properties
287:
288: protected ArrayList properties;
289: protected HashMap propertyHash;
290:
291: protected abstract SourceDesignProperty newDesignProperty(
292: PropertyDescriptor descriptor);
293:
294: public final void loadProperties() {
295: properties = new ArrayList();
296: propertyHash = new HashMap();
297: PropertyDescriptor[] propDescrs = beanInfo
298: .getPropertyDescriptors();
299: for (int i = 0; i < propDescrs.length; i++) {
300: SourceDesignProperty prop = newDesignProperty(propDescrs[i]);
301: if (prop != null) {
302: prop.initLive();
303: properties.add(prop);
304: propertyHash.put(propDescrs[i], prop);
305: }
306: }
307: // EAT: Unfortunately there are some side effects on loadEvents that affect properties
308: if (events == null)
309: loadEvents();
310: }
311:
312: public DesignProperty[] getProperties() {
313: if (properties == null)
314: loadProperties();
315: return (DesignProperty[]) properties
316: .toArray(new DesignProperty[properties.size()]);
317: }
318:
319: public DesignProperty getProperty(PropertyDescriptor property) {
320: if (properties == null)
321: loadProperties();
322: return (DesignProperty) propertyHash.get(property);
323: }
324:
325: public DesignProperty getProperty(String propertyName) {
326: if (properties == null)
327: loadProperties();
328: for (int i = 0; i < properties.size(); i++) {
329: DesignProperty p = (DesignProperty) properties.get(i);
330: if (p.getPropertyDescriptor().getName()
331: .equals(propertyName))
332: return p;
333: }
334: return null;
335: }
336:
337: public DesignEvent getEvent(String eventName) {
338: if (events == null)
339: loadEvents();
340: for (int i = 0; i < events.size(); i++) {
341: DesignEvent e = (DesignEvent) events.get(i);
342: if (e.getEventDescriptor().getName().equals(eventName))
343: return e;
344: }
345: return null;
346: }
347:
348: //--------------------------------------------------------------------------------------- Events
349:
350: protected ArrayList events;
351:
352: protected abstract SourceDesignEvent newDesignEvent(
353: EventDescriptor descriptor);
354:
355: protected void loadEvents() {
356: events = new ArrayList();
357: EventSetDescriptor[] esds = beanInfo.getEventSetDescriptors();
358: for (int i = 0; i < esds.length; i++) {
359: MethodDescriptor[] mds = esds[i]
360: .getListenerMethodDescriptors();
361: for (int j = 0; j < mds.length; j++) {
362: EventDescriptor ed = new EventDescriptor(esds[i],
363: mds[j]);
364: SourceDesignEvent e = newDesignEvent(ed);
365: if (e != null)
366: events.add(e);
367: }
368: }
369: }
370:
371: public DesignEvent[] getEvents() {
372: if (events == null)
373: loadEvents();
374: return (DesignEvent[]) events
375: .toArray(SourceDesignEvent.EMPTY_ARRAY);
376: }
377:
378: public DesignEvent[] getEvents(EventSetDescriptor eventSet) {
379: if (events == null)
380: loadEvents();
381:
382: int lec = 0;
383: for (int i = 0; i < events.size(); i++) {
384: DesignEvent e = (DesignEvent) events.get(i);
385: if (e.getEventDescriptor().getEventSetDescriptor() == eventSet)
386: lec++;
387: }
388:
389: DesignEvent[] les = new DesignEvent[lec];
390: lec = 0;
391: for (int i = 0; i < events.size(); i++) {
392: DesignEvent e = (DesignEvent) events.get(i);
393: if (e.getEventDescriptor().getEventSetDescriptor() == eventSet)
394: les[lec++] = e;
395: }
396:
397: return les;
398: }
399:
400: public DesignEvent getEvent(EventSetDescriptor eventSet,
401: MethodDescriptor event) {
402: if (events == null)
403: loadEvents();
404:
405: for (int i = 0; i < events.size(); i++) {
406: DesignEvent e = (DesignEvent) events.get(i);
407: EventDescriptor ed = e.getEventDescriptor();
408: if (ed.getEventSetDescriptor() == eventSet
409: && ed.getListenerMethodDescriptor() == event)
410: return e;
411: }
412: return null;
413: }
414:
415: public DesignEvent getEvent(EventDescriptor event) {
416: return getEvent(event.getEventSetDescriptor(), event
417: .getListenerMethodDescriptor());
418: }
419:
420: //-------------------------------------------------------------------------------- Context Items
421:
422: protected ArrayList contextItems;
423:
424: public void addContextItem(DisplayAction item) {
425: if (contextItems == null)
426: contextItems = new ArrayList();
427: contextItems.add(item);
428: }
429:
430: public void removeContextItem(DisplayAction item) {
431: if (contextItems == null)
432: return;
433: contextItems.remove(item);
434: if (contextItems.size() == 0)
435: contextItems = null;
436: }
437:
438: public DisplayAction[] getContextItems() {
439: if (contextItems != null)
440: return (DisplayAction[]) contextItems
441: .toArray(new DisplayAction[contextItems.size()]);
442: return DisplayAction.EMPTY_ARRAY;
443: }
444:
445: //------------------------------------------------------------------------------------ Listeners
446:
447: protected ArrayList lblList = new ArrayList();
448:
449: public void addDesignBeanListener(DesignBeanListener beanListener) {
450: if (beanListener != null) {
451: //System.err.println("SLB.addDesignBeanListener l:" + beanListener);
452: lblList.add(beanListener);
453: }
454: }
455:
456: public void removeDesignBeanListener(DesignBeanListener beanListener) {
457: lblList.remove(beanListener);
458: }
459:
460: public DesignBeanListener[] getDesignBeanListeners() {
461: return (DesignBeanListener[]) lblList
462: .toArray(new DesignBeanListener[lblList.size()]);
463: }
464:
465: protected void fireDesignBeanInstanceNameChanged(
466: String oldInstanceName) {
467: for (Iterator li = lblList.iterator(); li.hasNext();) {
468: try {
469: ((DesignBeanListener) li.next()).instanceNameChanged(
470: this , oldInstanceName);
471: } catch (Exception e) {
472: e.printStackTrace();
473: }
474: }
475: unit.fireBeanInstanceNameChanged(this , oldInstanceName);
476: }
477:
478: protected void fireDesignBeanChanged() {
479: for (Iterator li = lblList.iterator(); li.hasNext();) {
480: try {
481: ((DesignBeanListener) li.next()).beanChanged(this );
482: } catch (Exception e) {
483: e.printStackTrace();
484: }
485: }
486: unit.fireBeanChanged(this );
487: }
488:
489: protected void fireDesignPropertyChanged(DesignProperty prop,
490: Object oldValue) {
491: for (Iterator li = lblList.iterator(); li.hasNext();) {
492: DesignBeanListener l = (DesignBeanListener) li.next();
493: //System.err.println("SLB.fireDesignPropertyChanged prop:" + prop + " l:" + l);
494: try {
495: l.propertyChanged(prop, oldValue);
496: } catch (Exception e) {
497: e.printStackTrace();
498: }
499: }
500: unit.firePropertyChanged(prop, oldValue);
501: }
502:
503: protected void fireDesignEventChanged(DesignEvent event) {
504: for (Iterator li = lblList.iterator(); li.hasNext();) {
505: try {
506: ((DesignBeanListener) li.next()).eventChanged(event);
507: } catch (Exception e) {
508: e.printStackTrace();
509: }
510: }
511: unit.fireEventChanged(event);
512: }
513:
514: /**
515: * Propagate a regular JavaBean propertyChange out to our listeners by firing a live
516: * propertyChanged event
517: */
518: public void propertyChange(PropertyChangeEvent e) {
519: if (properties == null)
520: loadProperties();
521: DesignProperty prop = (DesignProperty) propertyHash.get(e
522: .getPropertyName());
523: if (prop != null)
524: fireDesignPropertyChanged(prop, e.getOldValue());
525: }
526:
527: //----------------------------------------------------------------------- Internal Containership
528:
529: /*
530: public boolean addLiveChildExtended(SourceDesignBean parent, DesignBean lbean, Position pos) {
531: int index = pos != null ? pos.getIndex() : -1;
532: if (index >= 0 && index < children.size()) {
533: if (children.get(index) == lbean)
534: return true;
535: }
536: else {
537: index = children.size();
538: }
539:
540: SourceDesignBean oldparent = (SourceDesignBean)lbean.getBeanParent();
541: if (oldparent != null)
542: oldparent.removeLiveChild(lbean);
543:
544: children.add(index, lbean);
545: ((SourceDesignBean)lbean).parent = parent;
546:
547: return true;
548: }*/
549:
550: /**
551: * For use by LiveUnit during normal creation
552: * @param lbean
553: */
554: public void addLiveChild(SourceDesignBean lbean, Position pos) {
555: int index = pos != null ? pos.getIndex() : -1;
556: if (index >= 0 && index < children.size())
557: children.add(index, lbean);
558: else
559: children.add(lbean);
560: lbean.parent = this ;
561: }
562:
563: public void removeLiveChild(SourceDesignBean lbean) {
564: children.remove(lbean);
565: }
566:
567: public void clearLiveChildren() {
568: children.clear();
569: }
570:
571: public SourceDesignBean findLiveChild(String name) {
572: for (Iterator i = children.iterator(); i.hasNext();) {
573: SourceDesignBean slb = (SourceDesignBean) i.next();
574: if (slb.getInstanceName().equals(name))
575: return slb;
576: }
577: return null;
578: }
579:
580: //------------------------------------------------------------------------------------- TreeNode
581:
582: private DesignBeanNode node;
583:
584: DesignBeanNode getNode() {
585: if (node == null) {
586: // XXX TODO Ugly implementation, clean it (look at DataObject.getNodeRepresentation).
587: node = DesignBeanNode.getInstance(this );
588: }
589: return node;
590: }
591:
592: public TreeNode getChildAt(int childIndex) {
593: if (children != null) {
594: // TODO EAT: This is a hack, but returning null causes other problems,
595: // and there seems to be a bug copying lots of components from one page to another, see bug #6347643
596: if (childIndex >= children.size()) {
597: childIndex = children.size() - 1;
598: }
599: Object childO = children.get(childIndex);
600: if (childO instanceof TreeNode)
601: return (TreeNode) childO;
602: System.err.println("SLBA.getChildAt: Not a TreeNode: "
603: + childO + " class:" + childO.getClass());
604: }
605: return null;
606: }
607:
608: public int getChildCount() {
609: return children != null ? children.size() : -1;
610: }
611:
612: public TreeNode getParent() {
613: return parent;
614: }
615:
616: public int getIndex(TreeNode node) {
617: if (children != null) {
618: int n = children.size();
619: for (int i = 0; i < n; i++) {
620: if (children.get(i) == node)
621: return i;
622: }
623: }
624: return -1;
625: }
626:
627: public boolean getAllowsChildren() {
628: return children != null;
629: }
630:
631: public boolean isLeaf() {
632: return children == null;
633: }
634:
635: // Note: using old Enumeration only for old NetBeans code
636: public Enumeration children() {
637: return children != null ? Collections.enumeration(children)
638: : null;
639: }
640:
641: protected void setChildCapable() {
642:
643: children = new ArrayList();
644: }
645:
646: //--------------------------------------------------------------------------------------- Object
647:
648: /**
649: * Utility function for debugging--return the name part of this object's class name
650: */
651: protected String clzName() {
652: String cls = getClass().getName();
653: int dot = cls.lastIndexOf('.');
654: return cls.substring(dot + 1);
655: }
656:
657: /**
658: *
659: */
660: public String toString() {
661: // StringBuffer sb = new StringBuffer(30);
662: // sb.append("[");
663: // sb.append(clzName());
664: // toString(sb);
665: // sb.append("]");
666: // return sb.toString();
667: return super .toString() + "[instanceName=" + getInstanceName()
668: + ", instance=" + getInstance() + "]"; // NOI18N
669: }
670:
671: public void toString(StringBuffer sb) {
672: Object instance = getInstance();
673: sb.append(" instance:");
674: if (instance == null) {
675: sb.append("null");
676: } else {
677: sb.append(instance);
678: }
679: /*sb.append(" ");
680: DesignBean[] kids = getChildBeans();
681: if (kids != null)
682: for (int i = 0; i < kids.length; i++)
683: sb.append(kids[i].toString());*/
684: }
685: }
|