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.bpel.design.model.patterns;
021:
022: import java.awt.event.ActionEvent;
023: import java.awt.geom.Area;
024: import java.beans.PropertyChangeListener;
025: import java.util.ArrayList;
026: import java.util.Collection;
027: import java.util.HashSet;
028: import java.util.List;
029: import java.util.Set;
030: import javax.swing.AbstractAction;
031: import javax.swing.Action;
032: import javax.swing.JMenu;
033: import javax.swing.JMenuItem;
034: import javax.swing.JPopupMenu;
035: import javax.swing.event.ChangeListener;
036: import org.netbeans.modules.bpel.design.DiagramView;
037: import org.netbeans.modules.bpel.design.geometry.FBounds;
038: import org.netbeans.modules.bpel.design.geometry.FPoint;
039: import org.netbeans.modules.bpel.design.model.DiagramModel;
040: import org.netbeans.modules.bpel.design.model.connections.MessageConnection;
041:
042: import org.netbeans.modules.bpel.model.api.BpelEntity;
043: import org.netbeans.modules.bpel.model.api.BpelModel;
044: import org.netbeans.modules.bpel.model.api.NamedElement;
045: import org.netbeans.modules.bpel.model.api.PartnerLink;
046: import org.netbeans.modules.bpel.model.api.support.UniqueId;
047: import org.netbeans.modules.bpel.design.layout.LayoutManager;
048: import org.netbeans.modules.bpel.design.model.connections.Connection;
049:
050: import org.netbeans.modules.bpel.design.model.elements.VisualElement;
051: import org.netbeans.modules.bpel.editors.api.nodes.NodeType;
052: import org.netbeans.modules.bpel.design.selection.PlaceHolder;
053: import org.netbeans.modules.bpel.nodes.BpelNode;
054: import org.netbeans.modules.bpel.nodes.actions.AbstractWrapWithAction;
055: import org.netbeans.modules.bpel.nodes.actions.AddBasicActivitiesAction;
056: import org.netbeans.modules.bpel.nodes.actions.AddFromPaletteAction;
057: import org.netbeans.modules.bpel.nodes.actions.AddPaletteActivityAction;
058: import org.netbeans.modules.bpel.nodes.actions.AddStructuredActivitiesAction;
059: import org.netbeans.modules.bpel.nodes.actions.AddWebServiceActivitiesAction;
060: import org.netbeans.modules.bpel.nodes.actions.BpelNodeAction;
061: import org.netbeans.modules.bpel.nodes.actions.GoToAction;
062: import org.netbeans.modules.bpel.nodes.actions.GoToDiagrammAction;
063: import org.netbeans.modules.bpel.nodes.actions.WrapAction;
064: import org.openide.actions.NewAction;
065: import org.openide.awt.Actions;
066: import org.openide.nodes.Node;
067: import org.openide.util.HelpCtx;
068: import org.openide.util.NbBundle;
069:
070: /**
071: *
072: * @author Alexey Yarmolenko
073: */
074:
075: public abstract class Pattern {
076:
077: private UniqueId omReference;
078:
079: private List<VisualElement> elements = new ArrayList<VisualElement>();
080: private List<Connection> connections = new ArrayList<Connection>();
081:
082: private DiagramModel model;
083: private BpelModel bpelModel;
084:
085: private CompositePattern parent;
086:
087: private VisualElement textElement;
088: private FPoint origin;
089:
090: private FBounds bounds;
091:
092: public FPoint getOrigin() {
093: return origin;
094: }
095:
096: public DiagramView getView() {
097: return model.getView().getProcessView();
098: }
099:
100: public void setOrigin(double x, double y) {
101: origin = new FPoint(x, y);
102: }
103:
104: public Pattern(DiagramModel model) {
105: this .model = model;
106: }
107:
108: public DiagramModel getModel() {
109: return this .model;
110: }
111:
112: public BpelModel getBpelModel() {
113: return this .bpelModel;
114: }
115:
116: public void initPattern(BpelEntity entity) {
117: this .omReference = entity.getUID();
118:
119: this .bpelModel = entity.getBpelModel();
120:
121: createElementsImpl();
122:
123: updateName();
124: }
125:
126: public FBounds getBounds() {
127: assert bounds != null : "Layout manager failed to set bounds for pattern "
128: + this ;
129: return bounds;
130: }
131:
132: public void setBounds(FBounds bounds) {
133: this .bounds = bounds;
134: }
135:
136: public boolean isSelectable() {
137: return true;
138: }
139:
140: public boolean isDraggable() {
141: return true;
142: }
143:
144: public boolean isCollapsable() {
145: return false;
146: }
147:
148: public BpelEntity getOMReference() {
149: // assert bpelModel.getEntity((UniqueId)this.omReference) != null :
150: // "Can not resolve element for pattern: " + this;
151: if (this .omReference != null) {
152: return bpelModel.getEntity((UniqueId) this .omReference);
153:
154: }
155:
156: return null;
157: }
158:
159: public void setParent(CompositePattern newParent) {
160:
161: CompositePattern oldParent = parent;
162:
163: if (oldParent != null) {
164: oldParent.removePattern(this );
165: }
166:
167: if (newParent != null) {
168: newParent.appendPattern(this );
169: }
170:
171: parent = newParent;
172: }
173:
174: public CompositePattern getParent() {
175: return parent;
176: }
177:
178: public Collection<VisualElement> getElements() {
179: return elements;
180:
181: }
182:
183: public void removeAllElements() {
184: elements.clear();
185: }
186:
187: public void appendElement(VisualElement element) {
188: elements.add(element);
189: element.setPattern(this );
190: }
191:
192: public void removeElement(VisualElement element) {
193: elements.remove(element);
194: element.setPattern(null);
195: }
196:
197: public void addConnection(Connection connection) {
198: if (!connections.contains(connection)) {
199: connections.add(connection);
200: }
201: }
202:
203: public void clearConnections() {
204: for (int i = connections.size() - 1; i >= 0; i--) {
205: connections.get(i).remove();
206: }
207: }
208:
209: public void clearConnectionsExcept(Connection connection) {
210: for (int i = connections.size() - 1; i >= 0; i--) {
211: Connection c = connections.get(i);
212: if (c != connection) {
213: c.remove();
214: }
215: }
216: }
217:
218: public void removeConnection(Connection connection) {
219: connections.remove(connection);
220: }
221:
222: public void reconnectElements() {
223: }
224:
225: public abstract VisualElement getFirstElement();
226:
227: public abstract VisualElement getLastElement();
228:
229: public abstract FBounds layoutPattern(LayoutManager manager);
230:
231: protected abstract void createElementsImpl();
232:
233: public void createPlaceholders(Pattern draggedPattern,
234: Collection<PlaceHolder> placeHolders) {
235: }
236:
237: /**
238: * Function builds the popup menu to show on diagram element.
239: * Menu actions are taken from Node wrapping the underlying BpelOM element.
240: * Derived classes should override this method to add extra menu items.
241: * @returns menu to show.
242: **/
243: public JPopupMenu createPopupMenu() {
244: //construct the node for current element
245: Node node = getModel().getView().getNodeForPattern(this );
246:
247: if (node != null) {
248: //set menu label, used by some L&F
249: JPopupMenu menu = new JPopupMenu(node.getDisplayName());
250:
251: Action collapseExpandAction = getModel().getView()
252: .getCollapseExpandDecorationProvider()
253: .createCollapseExpandAction(this );
254: if (collapseExpandAction != null) {
255: JMenuItem item = menu.add(collapseExpandAction);
256: item.setIcon(null);
257: }
258:
259: JMenuItem scrollToPartnerLink = createScrollToPartnerLinkMenuItem();
260: if (scrollToPartnerLink != null) {
261: menu.add(scrollToPartnerLink);
262: }
263:
264: //populate a list of actions
265: Action actions[] = node.getActions(true);
266: if (actions != null) {
267: for (Action a : actions) {
268: if (a instanceof BpelNodeAction) {
269: // inforce action enable status
270: // It's required in case activated node haven't been changed but enable status changes
271: a.setEnabled(((BpelNodeAction) a)
272: .enable(new Node[] { node }));
273: }
274:
275: //null Action indicates a separator
276: if (a instanceof NewAction) {
277: // vb todo add handler for NewAction and sub actions
278: JMenu submenu = new JMenu(NbBundle.getMessage(
279: Pattern.class, "LBL_Add")); // NOI18N
280: List<BpelNodeAction> addActions = ((BpelNode) node)
281: .getAddActions();
282: for (BpelNodeAction elem : addActions) {
283: submenu.add(new Actions.MenuItem(elem,
284: false));
285: }
286: menu.add(submenu);
287: } else if (a instanceof WrapAction) {
288: AbstractWrapWithAction[] wrapActions = ((WrapAction) a)
289: .getWrapActions(new Node[] { node });
290: // todo m
291: if (wrapActions.length == 1) {
292: menu.add(new Actions.MenuItem(a, false));
293: } else {
294: JMenu submenu = new JMenu(((WrapAction) a)
295: .getBundleName());
296: for (AbstractWrapWithAction wrapElem : wrapActions) {
297: submenu.add(new Actions.MenuItem(
298: wrapElem, false));
299: }
300: menu.add(submenu);
301: }
302: } else if (a instanceof GoToAction) {
303: BpelNodeAction[] gotoActions = ((GoToAction) a)
304: .getGoToActions(new Node[] { node });
305: // todo m
306: if (gotoActions.length == 1
307: && !(a instanceof GoToDiagrammAction)) {
308: menu.add(new Actions.MenuItem(a, false));
309: } else {
310: JMenu submenu = new JMenu(((GoToAction) a)
311: .getBundleName());
312: for (BpelNodeAction gotoElem : gotoActions) {
313: if (gotoElem instanceof GoToDiagrammAction) {
314: continue;
315: }
316: submenu.add(new Actions.MenuItem(
317: gotoElem, false));
318: }
319: menu.add(submenu);
320: }
321: } else if (a instanceof AddFromPaletteAction) {
322: BpelNodeAction[] categoriesActions = ((AddFromPaletteAction) a)
323: .getCategoriesAction(new Node[] { node });
324: // todo m
325: if (categoriesActions != null
326: && categoriesActions.length > 0) {
327: JMenu submenu = new JMenu(
328: ((AddFromPaletteAction) a)
329: .getBundleName());
330: for (BpelNodeAction paletteCategory : categoriesActions) {
331:
332: AddPaletteActivityAction[] paletteActions = null;
333: if (paletteCategory instanceof AddBasicActivitiesAction) {
334: paletteActions = ((AddBasicActivitiesAction) paletteCategory)
335: .getPaletteActions(new Node[] { node });
336: } else if (paletteCategory instanceof AddStructuredActivitiesAction) {
337: paletteActions = ((AddStructuredActivitiesAction) paletteCategory)
338: .getPaletteActions(new Node[] { node });
339: } else if (paletteCategory instanceof AddWebServiceActivitiesAction) {
340: paletteActions = ((AddWebServiceActivitiesAction) paletteCategory)
341: .getPaletteActions(new Node[] { node });
342: }
343:
344: if (paletteActions != null
345: && paletteActions.length == 1) {
346: submenu.add(new Actions.MenuItem(
347: paletteCategory, false));
348: } else if (paletteActions != null) {
349: JMenu subsubmenu = new JMenu(
350: ((BpelNodeAction) paletteCategory)
351: .getName());
352: for (AddPaletteActivityAction paletteElem : paletteActions) {
353: subsubmenu
354: .add(new Actions.MenuItem(
355: paletteElem,
356: false));
357: }
358: submenu.add(subsubmenu);
359: }
360: }
361: menu.add(submenu);
362: }
363: } else if (a != null) {
364: // it's diagramm already !
365: if (!(a instanceof GoToDiagrammAction)) {
366: menu.add(new Actions.MenuItem(a, false));
367: }
368: } else {
369: menu.addSeparator();
370: }
371: }
372: }
373: return menu;
374: }
375:
376: return null;
377: }
378:
379: private class AddAction implements Action {
380: private NewAction na;
381:
382: public AddAction(NewAction na) {
383: this .na = na;
384: }
385:
386: public Object getValue(String key) {
387: return na.getValue(key);
388: }
389:
390: public void putValue(String key, Object value) {
391: na.putValue(key, value);
392: }
393:
394: public void setEnabled(boolean b) {
395: }
396:
397: public boolean isEnabled() {
398: return true;
399: }
400:
401: public void addPropertyChangeListener(
402: PropertyChangeListener listener) {
403: }
404:
405: public void removePropertyChangeListener(
406: PropertyChangeListener listener) {
407: }
408:
409: public void actionPerformed(ActionEvent e) {
410: }
411: }
412:
413: private class AddActionSubMenuModel implements Actions.SubMenuModel {
414:
415: private List<BpelNodeAction> addActions;
416: private BpelNode node;
417:
418: public AddActionSubMenuModel(List<BpelNodeAction> addActions,
419: BpelNode node) {
420: this .addActions = addActions;
421: this .node = node;
422: }
423:
424: public int getCount() {
425: return addActions == null ? -1 : addActions.size();
426: }
427:
428: public String getLabel(int index) {
429: if (index < 0 || index > (getCount() - 1)
430: || addActions.get(index) == null) {
431: return null;
432: }
433:
434: return addActions.get(index).getName();
435: }
436:
437: public HelpCtx getHelpCtx(int index) {
438: if (index < 0 || index > (getCount() - 1)
439: || addActions.get(index) == null) {
440: return null;
441: }
442:
443: return addActions.get(index).getHelpCtx();
444: }
445:
446: public void performActionAt(int index) {
447: if (index < 0 || index > (getCount() - 1)
448: || addActions.get(index) == null) {
449: return;
450: }
451:
452: addActions.get(index).performAction(new Node[] { node });
453: }
454:
455: public void addChangeListener(ChangeListener l) {
456: }
457:
458: public void removeChangeListener(ChangeListener l) {
459: }
460:
461: }
462:
463: /*
464: *Checks if p is one of the parents in pattern hierarchy
465: */
466: public boolean isNestedIn(Pattern parent) {
467: Pattern p = getParent();
468: while (p != null) {
469: if (p == parent) {
470: return true;
471: }
472: p = p.getParent();
473: }
474: return false;
475: }
476:
477: public boolean isInModel() {
478: Pattern root = model.getRootPattern();
479: return ((this == root) || isNestedIn(root));
480: }
481:
482: public String getDefaultName() {
483: return ""; // NOI18N
484: }
485:
486: public void registerTextElement(VisualElement newTextElement) {
487: this .textElement = newTextElement;
488: }
489:
490: public VisualElement getTextElement() {
491: return textElement;
492: }
493:
494: public boolean isTextElement(VisualElement element) {
495: return (element != null) ? element == textElement : false;
496: }
497:
498: public void setText(String text) {
499: if (textElement == null)
500: return;
501: textElement.setText(text);
502: }
503:
504: public String getText() {
505: return (textElement != null) ? textElement.getText() : null;
506: }
507:
508: public void updateName() {
509: if (getOMReference() instanceof NamedElement) {
510: String n = ((NamedElement) getOMReference()).getName();
511: setText(n);
512: } else {
513: setText(getDefaultName());
514: }
515: }
516:
517: public String toString() {
518: return getClass().getName() + hashCode();
519: }
520:
521: public NodeType getNodeType() {
522: return NodeType.UNKNOWN_TYPE;
523: }
524:
525: public List<Connection> getConnections() {
526: return connections;
527: }
528:
529: public List<MessageConnection> getMessageConnections() {
530: List<MessageConnection> result = new ArrayList<MessageConnection>();
531:
532: for (Connection connection : getConnections()) {
533: if (connection instanceof MessageConnection) {
534: result.add((MessageConnection) connection);
535: }
536: }
537:
538: return result;
539: }
540:
541: public Set<Pattern> getConnectedParnerLinkPatterns() {
542: Set<Pattern> result = new HashSet<Pattern>();
543:
544: for (Connection connection : getConnections()) {
545: if (!(connection instanceof MessageConnection))
546: continue;
547:
548: Pattern targetPattern = connection.getTarget().getPattern();
549: Pattern sourcePattern = connection.getSource().getPattern();
550:
551: if ((targetPattern.getOMReference() instanceof PartnerLink)
552: && (sourcePattern == this )) {
553: result.add(targetPattern);
554: } else if ((sourcePattern.getOMReference() instanceof PartnerLink)
555: && (targetPattern == this )) {
556: result.add(sourcePattern);
557: }
558: }
559:
560: return result;
561: }
562:
563: public Area createSelection() {
564: return createOutline();
565: }
566:
567: public Area createOutline() {
568: Area result = new Area();
569: for (VisualElement ve : getElements()) {
570: if (ve.getWidth() < 2 && ve.getHeight() < 2)
571: continue;
572: result.add(ve.getShape().createArea());
573: }
574: return result;
575: }
576:
577: public boolean refersTo(UniqueId id) {
578: return omReference.equals(id);
579:
580: }
581:
582: private JMenuItem createScrollToPartnerLinkMenuItem() {
583: Set<Pattern> patterns = getConnectedParnerLinkPatterns();
584:
585: if (patterns.isEmpty())
586: return null;
587:
588: if (patterns.size() == 1) {
589: return new JMenuItem(new ScrollToPattern(patterns
590: .iterator().next(), NbBundle.getMessage(
591: Pattern.class, "LBL_ScrollToPartnerLink"))); // NOI18N
592: }
593:
594: JMenu menu = new JMenu(NbBundle.getMessage(Pattern.class,
595: "LBL_ScrollToPartnerLink")); // NOI18N
596:
597: for (Pattern p : patterns) {
598: menu.add(new ScrollToPattern(p));
599: }
600:
601: return menu;
602: }
603:
604: static class ScrollToPattern extends AbstractAction {
605: private Pattern pattern;
606:
607: public ScrollToPattern(Pattern pattern) {
608: this (pattern, null);
609: }
610:
611: public ScrollToPattern(Pattern pattern, String name) {
612: if (name == null) {
613: name = pattern.getText();
614: if (name == null || name.trim().equals("")) { // NOI18N
615: name = NbBundle.getMessage(Pattern.class,
616: "LBL_Unnamed"); // NOI18N
617: }
618: }
619:
620: this .pattern = pattern;
621:
622: putValue(NAME, name);
623: }
624:
625: public void actionPerformed(ActionEvent e) {
626: pattern.getModel().getView().scrollPatternToView(pattern);
627: }
628: }
629: }
|