001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.modules.xslt.tmap.nodes;
021:
022: import java.awt.Image;
023: import java.awt.datatransfer.Transferable;
024: import java.io.IOException;
025: import java.util.ArrayList;
026: import java.util.HashMap;
027: import java.util.List;
028: import java.util.Map;
029: import javax.swing.Action;
030: import javax.swing.JTree;
031: import org.openide.actions.CopyAction;
032: import org.openide.actions.CutAction; //import org.openide.actions.DeleteAction;
033: import org.netbeans.modules.soa.ui.nodes.InstanceRef;
034: import org.netbeans.modules.soa.ui.nodes.NodeTypeHolder;
035: import org.netbeans.modules.xml.xam.ComponentEvent;
036: import org.netbeans.modules.xml.xam.ComponentListener;
037: import org.netbeans.modules.xml.xam.Model;
038: import org.netbeans.modules.xml.xam.Model.State;
039: import org.netbeans.modules.xml.xam.ui.XAMUtils;
040: import org.netbeans.modules.xslt.tmap.model.api.TMapComponent;
041: import org.netbeans.modules.xslt.tmap.model.api.TMapModel;
042: import org.netbeans.modules.xslt.tmap.nodes.actions.ActionType;
043: import org.netbeans.modules.xslt.tmap.nodes.actions.DeleteAction;
044: import org.netbeans.modules.xslt.tmap.nodes.actions.TMapAbstractNodeAction;
045: import org.netbeans.modules.xslt.tmap.nodes.actions.TMapNodeNewType;
046: import org.openide.actions.NewAction;
047: import org.openide.actions.PasteAction;
048: import org.openide.actions.PropertiesAction;
049: import org.openide.nodes.AbstractNode;
050: import org.openide.nodes.Children;
051: import org.openide.nodes.Node;
052: import org.openide.nodes.Sheet;
053: import org.openide.util.Lookup;
054: import org.openide.util.actions.SystemAction;
055: import org.openide.util.datatransfer.NewType;
056: import org.openide.util.datatransfer.PasteType;
057:
058: /**
059: *
060: * @author Vitaly Bychkov
061: * @version 1.0
062: */
063: public class TMapComponentNode<T extends DecoratedTMapComponent>
064: extends AbstractNode implements InstanceRef<T>,
065: NodeTypeHolder<NodeType> {
066:
067: public static final String EMPTY_STRING = ""; // NOI18N
068: public static final String WHITE_SPACE = " "; // NOI18N
069:
070: public static final String MAIN_SET = "Main"; // NOI18N
071:
072: private T myDecoratedComponent;
073: private NodeType myNodeType;
074: private Synchronizer synchronizer = new Synchronizer();
075: private Object NAME_LOCK = new Object();
076: private String cachedName;
077: private String cachedShortDescription;
078: private String cachedHtmlDisplayName;
079:
080: private static final Map<ActionType, Action> ACTION_TYPE_MAP = new HashMap<ActionType, Action>();
081:
082: static {
083: ACTION_TYPE_MAP.put(ActionType.REMOVE, SystemAction
084: .get(DeleteAction.class));
085: ACTION_TYPE_MAP.put(ActionType.COPY, SystemAction
086: .get(CopyAction.class));
087: ACTION_TYPE_MAP.put(ActionType.CUT, SystemAction
088: .get(CutAction.class));
089: ACTION_TYPE_MAP.put(ActionType.PASTE, SystemAction
090: .get(PasteAction.class));
091: ACTION_TYPE_MAP.put(ActionType.PROPERTIES, SystemAction
092: .get(PropertiesAction.class));
093: ACTION_TYPE_MAP.put(ActionType.ADD_NEWTYPES, SystemAction
094: .get(NewAction.class));
095:
096: }
097:
098: public TMapComponentNode(T ref, Lookup lookup) {
099: this (ref, Children.LEAF, lookup);
100: }
101:
102: public TMapComponentNode(T ref, Children children, Lookup lookup) {
103: super (children);
104: assert ref != null;
105: setReference(ref);
106: myNodeType = NodeType.getNodeType(ref.getOriginal());
107: assert myNodeType != null;
108:
109: assert ref.getOriginal() != null;
110: TMapModel model = ref.getOriginal().getModel();
111:
112: assert model != null : "Can't create Node for orphaned TMapComponent"; // NOI18N
113: model.addComponentListener(synchronizer);
114:
115: // set nodeDescription property which is shown in property sheet help region
116: setValue("nodeDescription", "");
117: }
118:
119: public Object getAlternativeReference() {
120: return null;
121: }
122:
123: public NodeType getNodeType() {
124: return myNodeType;
125: }
126:
127: private void setReference(T ref) {
128: myDecoratedComponent = ref;
129: }
130:
131: /**
132: * The reference to an object which the node represents.
133: */
134: public T getReference() {
135: return myDecoratedComponent;
136: }
137:
138: @Override
139: public boolean equals(Object obj) {
140: if (super .equals(obj)) {
141: return true;
142: }
143:
144: //
145: if (obj instanceof TMapComponentNode) {
146: Object this Orig = this .getReference().getOriginal();
147: Object objOrig = ((TMapComponentNode) obj).getReference();
148:
149: return this .getNodeType().equals(
150: ((TMapComponentNode) obj).getNodeType())
151: && this Orig != null && this Orig.equals(objOrig);
152: }
153: //
154: return false;
155: }
156:
157: @Override
158: public boolean canCopy() {
159: return true;
160: }
161:
162: @Override
163: public boolean canCut() {
164: return true;
165: }
166:
167: @Override
168: public boolean canDestroy() {
169: return true;
170: }
171:
172: @Override
173: public Image getIcon(int type) {
174: T ref = getReference();
175: return ref == null ? null : ref.getIcon();
176: }
177:
178: @Override
179: public Image getOpenedIcon(int type) {
180: return getIcon(type);
181: }
182:
183: protected String getNameImpl() {
184: T ref = getReference();
185: String name = null;
186: return ref != null ? ref.getName() : "";
187: }
188:
189: @Override
190: public String getName() {
191: synchronized (NAME_LOCK) {
192: if (cachedName == null) {
193: cachedName = getNameImpl();
194: }
195: return cachedName;
196: }
197: }
198:
199: @Override
200: public String getDisplayName() {
201: String instanceName = getName();
202: return ((instanceName == null || instanceName.length() == 0) ? ""
203: : instanceName + " ")
204: + "[" + getNodeType().getDisplayName() + "]"; // NOI18N
205: }
206:
207: @Override
208: public String getHtmlDisplayName() {
209: synchronized (NAME_LOCK) {
210: if (cachedHtmlDisplayName == null) {
211: cachedHtmlDisplayName = getImplHtmlDisplayName();
212: }
213: }
214:
215: return cachedHtmlDisplayName;
216: }
217:
218: protected String getImplHtmlDisplayName() {
219: T ref = getReference();
220: String name = null;
221: return ref != null ? ref.getHtmlDisplayName() : "";
222: }
223:
224: protected String getImplShortDescription() {
225: T ref = getReference();
226: String name = null;
227: return ref != null ? ref.getTooltip() : "";
228: }
229:
230: @Override
231: public String getShortDescription() {
232: synchronized (NAME_LOCK) {
233: if (cachedShortDescription == null) {
234: cachedShortDescription = getImplShortDescription();
235: }
236: }
237: return cachedShortDescription;
238: }
239:
240: public void updateName() {
241:
242: //name will be reloaded from model during next getName call
243: synchronized (NAME_LOCK) {
244: cachedName = null;
245: }
246:
247: fireNameChange(null, getName());
248: synchronized (NAME_LOCK) {
249: cachedShortDescription = null;
250: }
251:
252: synchronized (NAME_LOCK) {
253: cachedHtmlDisplayName = null;
254: }
255: fireShortDescriptionChange(null, getShortDescription());
256: fireDisplayNameChange(null, getDisplayName());
257: }
258:
259: // protected void updateProperty(PropertyType propertyType) {
260: // updateProperty(propertyType.toString());
261: // }
262: //
263: // protected void updateProperty(String propertyName) {
264: // Property prop = PropertyUtils.lookForPropertyByName(this, propertyName);
265: // Object newValue = null;
266: // try {
267: // newValue = prop.getValue();
268: // } catch (Exception ex) {
269: // // do nothing here
270: // }
271: // firePropertyChange(propertyName, UNKNOWN_OLD_VALUE, newValue);
272: // }
273:
274: public void updatePropertyChange(String propertyName,
275: Object oldValue, Object newValue) {
276: firePropertyChange(propertyName, oldValue, newValue);
277: synchronized (NAME_LOCK) {
278: cachedShortDescription = null;
279: }
280:
281: synchronized (NAME_LOCK) {
282: cachedHtmlDisplayName = null;
283: }
284: fireDisplayNameChange(null, getDisplayName());
285: fireShortDescriptionChange(null, getShortDescription());
286: }
287:
288: public void updateShortDescription() {
289: synchronized (NAME_LOCK) {
290: cachedShortDescription = null;
291: }
292:
293: fireShortDescriptionChange(null, getShortDescription());
294: }
295:
296: /**
297: * Looks for the Properties Set by the Group enum.
298: * If the group isn't
299: */
300: protected Sheet.Set getPropertySet(Sheet sheet) {
301: Sheet.Set propSet = sheet.get(TMapComponentNode.MAIN_SET);
302: if (propSet == null) {
303: propSet = new Sheet.Set();
304: propSet.setName(TMapComponentNode.MAIN_SET);
305: sheet.put(propSet);
306: }
307: //
308: return propSet;
309: }
310:
311: @Override
312: public Action[] getActions(boolean context) {
313: TMapComponent ref = getComponentRef();
314: TMapModel model = ref == null ? null : ref.getModel();
315: Action[] actions = null;
316: if (model != null
317: && TMapModel.State.VALID.equals(model.getState())) {
318: actions = createActionsArray(context);
319: }
320: return actions == null ? super .getActions(context) : actions;
321: }
322:
323: protected ActionType[] getActionsArray() {
324: List<ActionType> actionList = new ArrayList<ActionType>();
325: T ref = getReference();
326:
327: // if (ref instanceof Activity) {
328: // actionList.add(ActionType.ADD_FROM_PALETTE);
329: // if (!(ref instanceof Process)) {
330: // actionList.add(ActionType.WRAP);
331: // }
332: // actionList.add(ActionType.SEPARATOR);
333: // }
334: // if (ref instanceof CompositeActivity) {
335: // actionList.add(ActionType.CHANGE_ORDER_ACTION);
336: // actionList.add(ActionType.SEPARATOR);
337: // }
338: //
339: // actionList.add(ActionType.GO_TO_SOURCE);
340: // if (ref instanceof Activity) {
341: // actionList.add(ActionType.GO_TO_DIAGRAMM);
342: // }
343: // if (ref instanceof Activity) {
344: // actionList.add(ActionType.SEPARATOR);
345: // actionList.add(ActionType.MOVE_UP);
346: // actionList.add(ActionType.MOVE_DOWN);
347: // actionList.add(ActionType.SEPARATOR);
348: // actionList.add(ActionType.TOGGLE_BREAKPOINT);
349: // }
350: // actionList.add(ActionType.SEPARATOR);
351: actionList.add(ActionType.REMOVE);
352: // actionList.add(ActionType.SEPARATOR);
353: // actionList.add(ActionType.COPY);
354: // actionList.add(ActionType.CUT);
355: // actionList.add(ActionType.PASTE);
356: // actionList.add(ActionType.SEPARATOR);
357: PropertySet[] propertySets = getPropertySets();
358: if (propertySets != null && propertySets.length > 0) {
359: actionList.add(ActionType.SEPARATOR);
360: actionList.add(ActionType.PROPERTIES);
361: }
362: return actionList.toArray(new ActionType[actionList.size()]);
363: }
364:
365: /**
366: * @return actions type which used to create new elements
367: * used in #getNewTypes
368: */
369: public ActionType[] getAddActionArray() {
370: return new ActionType[0];
371: }
372:
373: /**
374: * @return the new types that can be created in this node
375: */
376: @Override
377: public NewType[] getNewTypes() {
378: List<TMapAbstractNodeAction> actions = getAddActions();
379: if (actions == null || actions.size() < 1) {
380: return super .getNewTypes();
381: }
382: NewType[] newTypes = new NewType[actions.size()];
383: for (int i = 0; i < newTypes.length; i++) {
384: newTypes[i] = new TMapNodeNewType(actions.get(i), this );
385: }
386: return newTypes;
387: }
388:
389: public List<TMapAbstractNodeAction> getAddActions() {
390: ActionType[] actions = getAddActionArray();
391: if (actions == null || actions.length == 0) {
392: return null;
393: }
394: List<TMapAbstractNodeAction> resultAddActions = new ArrayList<TMapAbstractNodeAction>();
395: for (ActionType elem : actions) {
396: if (elem != null) {
397: Action action = createAction(elem);
398: if (action != null
399: && action instanceof TMapAbstractNodeAction
400: && ((TMapAbstractNodeAction) action)
401: .enable(new Node[] { this })) {
402: resultAddActions
403: .add((TMapAbstractNodeAction) action);
404: }
405: }
406: }
407:
408: return resultAddActions;
409: }
410:
411: protected Action[] createActionsArray(boolean context) {
412: ActionType[] actions = getActionsArray();
413: if (actions == null) {
414: return null;
415: }
416:
417: Action[] actionsArray = new Action[actions.length];
418: for (int i = 0; i < actions.length; i++) {
419: actionsArray[i] = createAction(actions[i]);
420: }
421: return actionsArray;
422: }
423:
424: public Action createAction(ActionType actionType) {
425: Action action = null;
426: return ACTION_TYPE_MAP.get(actionType);
427: }
428:
429: protected TMapComponent getComponentRef() {
430: T ref = getReference();
431: return ref.getOriginal();
432: }
433:
434: // @Override
435: // public Transferable clipboardCopy() throws IOException {
436: // return super.clipboardCopy();
437: // }
438: //
439: // @Override
440: // public Transferable clipboardCut() throws IOException {
441: // return super.clipboardCut();
442: // }
443:
444: // /**
445: // * Iterates over all registered properties and update them.
446: // */
447: // public void updateAllProperties() {
448: // PropertySet[] psArr = getSheet().toArray();
449: // for (PropertySet ps : psArr) {
450: // Property[] propArr = ps.getProperties();
451: // for (Property prop : propArr) {
452: // String propName = prop.getName();
453: // try {
454: // Object newPropValue = prop.getValue();
455: // firePropertyChange(propName, UNKNOWN_OLD_VALUE, newPropValue);
456: // } catch (Exception ex) {
457: // ErrorManager.getDefault().notify(ex);
458: // }
459: // }
460: // }
461: // }
462: //
463: // public void updateAttributeProperty(String attributeName) {
464: // Property prop = PropertyUtils.lookForPropertyByBoundedAttribute(
465: // this, attributeName);
466: // if (prop != null) {
467: // String propName = prop.getName();
468: // try {
469: // Object newPropValue = prop.getValue();
470: // firePropertyChange(propName, UNKNOWN_OLD_VALUE, newPropValue);
471: // } catch (Exception ex) {
472: // ErrorManager.getDefault().notify(ex);
473: // }
474: // }
475: //
476: // }
477: //
478: // public void updateElementProperty(Class elementClass) {
479: // Property prop = PropertyUtils.lookForPropertyByBoundedElement(
480: // this, elementClass);
481: // if (prop != null) {
482: // String propName = prop.getName();
483: // try {
484: // Object newPropValue = prop.getValue();
485: // firePropertyChange(propName, UNKNOWN_OLD_VALUE, newPropValue);
486: // } catch (Exception ex) {
487: // ErrorManager.getDefault().notify(ex);
488: // }
489: // }
490: // }
491:
492: private class Synchronizer implements ComponentListener {
493: public Synchronizer() {
494: }
495:
496: public void valueChanged(ComponentEvent evt) {
497: // System.out.println("value changed: "+evt.getSource());
498: }
499:
500: public void childrenAdded(ComponentEvent evt) {
501: // System.out.println("value changed: "+evt.getSource());
502: reloadChildren();
503: }
504:
505: public void childrenDeleted(ComponentEvent evt) {
506: // System.out.println("value changed: "+evt.getSource());
507: reloadChildren();
508: }
509:
510: private void reloadChildren() {
511:
512: Children children = getChildren();
513:
514: if (children instanceof ReloadableChildren) {
515: ((ReloadableChildren) children).reload();
516: } else if (TMapComponentNode.this instanceof ReloadableChildren) {
517: ((ReloadableChildren) TMapComponentNode.this ).reload();
518: }
519: }
520:
521: ////// public void notifyEntityRemoved(EntityRemoveEvent event) {
522: ////// BpelEntity entity = event.getOutOfModelEntity();
523: ////// //
524: ////// T ref = getReference();
525: ////// if (ref == null) {
526: ////// //
527: ////// // the referenced element already removed
528: ////// //
529: ////// BpelModel bpelModel = entity.getBpelModel();
530: ////// unsubscribedFromAndDestroy(bpelModel);
531: ////// } else {
532: ////// if (BpelNode.this.isEventRequreUpdate(event)) {
533: ////// reloadChildren();
534: ////// }
535: //////
536: ////// if (event.getOutOfModelEntity() instanceof Documentation
537: ////// && ref.equals(event.getParent()))
538: ////// {
539: ////// updateShortDescription();
540: ////// }
541: ////// }
542: ////// //
543: ////// // Perform update processing of complex ptoperties
544: ////// updateComplexProperties(event);
545: ////// }
546: //////
547: ////// public void notifyPropertyRemoved(PropertyRemoveEvent event) {
548: ////// BpelEntity entity = event.getParent();
549: //////
550: ////// //
551: //////////// if (BpelNode.this.isEventRequreUpdate(event)) {
552: //////////// String attributeName = event.getName();
553: //////////// updateAttributeProperty(attributeName);
554: //////////// updateName();
555: //////////// //
556: //////////// // Check if the property has the List type
557: //////////// Object value = event.getOldValue();
558: //////////// if (value != null && value instanceof List) {
559: //////////// reloadChildren();
560: //////////// }
561: //////////// }
562: //////////// //
563: //////////// // Check that the property is the content of an entity
564: //////////// // which owned by the node's entity.
565: //////////// if (ContentElement.CONTENT_PROPERTY.equals(event.getName())) {
566: //////////// BpelEntity parentEntity = event.getParent();
567: //////////// //
568: //////////// T curEntity = getReference();
569: //////////// if (curEntity != null && parentEntity != null &&
570: //////////// parentEntity.getParent() == curEntity) {
571: //////////// updateElementProperty(parentEntity.getClass());
572: //////////// }
573: //////////// }
574: ////////////
575: ////// //
576: ////// T ref = getReference();
577: ////// if (ref == null) {
578: ////// //
579: ////// // the referenced element already removed
580: ////// //
581: ////// BpelModel bpelModel = entity.getBpelModel();
582: ////// unsubscribedFromAndDestroy(bpelModel);
583: ////// } else {
584: ////// if (BpelNode.this.isEventRequreUpdate(event)) {
585: ////// reloadChildren();
586: ////// }
587: ////// }
588: ////// //
589: ////// // Perform update processing of complex ptoperties
590: ////// updateComplexProperties(event);
591: ////// }
592: //////
593: ////// public void notifyPropertyUpdated(PropertyUpdateEvent event) {
594: ////// if (BpelNode.this.isEventRequreUpdate(event)) {
595: ////// String attributeName = event.getName();
596: ////// updateAttributeProperty(attributeName);
597: ////// updateName();
598: ////// //
599: ////// // Check if the property has the List type
600: ////// Object value = event.getNewValue();
601: ////// if (value == null) {
602: ////// value = event.getOldValue();
603: ////// }
604: ////// if (value != null && value instanceof List) {
605: ////// reloadChildren();
606: ////// }
607: ////// }
608: ////// //
609: ////// // Check that the property is the content of an entity
610: ////// // which owned by the node's entity.
611: ////// if (ContentElement.CONTENT_PROPERTY.equals(event.getName())) {
612: ////// BpelEntity parentEntity = event.getParent();
613: ////// //
614: ////// T curEntity = getReference();
615: ////// if (curEntity != null && parentEntity != null &&
616: ////// parentEntity.getParent() == curEntity) {
617: ////// updateElementProperty(parentEntity.getClass());
618: ////// if (parentEntity instanceof Documentation) {
619: ////// updateShortDescription();
620: ////// }
621: ////// }
622: ////// }
623: ////// //
624: ////// // Perform update processing of complex ptoperties
625: ////// updateComplexProperties(event);
626: ////// }
627: //////
628: ////// public void notifyArrayUpdated(ArrayUpdateEvent event) {
629: ////// if (BpelNode.this.isEventRequreUpdate(event)) {
630: ////// reloadChildren();
631: ////// }
632: ////// //
633: ////// // Perform update processing of complex ptoperties
634: ////// updateComplexProperties(event);
635: ////// }
636: //////
637: ////// public void notifyEntityUpdated(EntityUpdateEvent event) {
638: ////// if (BpelNode.this.isEventRequreUpdate(event)) {
639: ////// BpelEntity entity = event.getNewValue();
640: ////// if (entity == null) {
641: ////// entity = event.getOldValue();
642: ////// }
643: ////// if (entity != null) {
644: ////// updateElementProperty(entity.getClass());
645: ////// }
646: ////// //
647: ////// reloadChildren();
648: ////// }
649: //////
650: ////// //
651: ////// // Perform update processing of complex ptoperties
652: ////// updateComplexProperties(event);
653: ////// }
654: //////
655: ////// public void notifyEntityInserted(EntityInsertEvent event) {
656: ////// if (BpelNode.this.isEventRequreUpdate(event)) {
657: ////// BpelEntity entity = event.getValue();
658: ////// if (entity != null) {
659: ////// updateElementProperty(entity.getClass());
660: ////// }
661: //////
662: ////// if (entity instanceof Documentation) {
663: ////// updateShortDescription();
664: ////// } else {
665: ////// //
666: ////// reloadChildren();
667: ////// }
668: ////// }
669: ////// //
670: ////// // Perform update processing of complex ptoperties
671: ////// updateComplexProperties(event);
672: ////// }
673:
674: }
675:
676: /**
677: * Determines if this node represents a component that is contained
678: * is editable
679: *
680: * @return true if component is editable, false otherwise.
681: */
682:
683: protected boolean isEditable() {
684: TMapComponent component = getComponentRef();
685: Model model = component == null ? null : component.getModel();
686: return model != null && XAMUtils.isWritable(model);
687: }
688:
689: }
|