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: package org.netbeans.modules.bpel.design.model;
020:
021: import java.util.Iterator;
022: import javax.swing.SwingUtilities;
023: import org.netbeans.modules.bpel.model.api.ActivityHolder;
024: import org.netbeans.modules.bpel.model.api.BpelEntity;
025: import org.netbeans.modules.bpel.model.api.BpelModel;
026: import org.netbeans.modules.bpel.model.api.Correlation;
027: import org.netbeans.modules.bpel.model.api.CorrelationSet;
028: import org.netbeans.modules.bpel.model.api.Import;
029: import org.netbeans.modules.bpel.model.api.NamedElement;
030: import org.netbeans.modules.bpel.model.api.OperationReference;
031: import org.netbeans.modules.bpel.model.api.PartnerLinkReference;
032: import org.netbeans.modules.bpel.model.api.PortTypeReference;
033: import org.netbeans.modules.bpel.model.api.Variable;
034: import org.netbeans.modules.bpel.model.api.Process;
035:
036: import org.netbeans.modules.bpel.model.api.events.ArrayUpdateEvent;
037: import org.netbeans.modules.bpel.model.api.events.ChangeEvent;
038: import org.netbeans.modules.bpel.model.api.events.ChangeEventListener;
039: import org.netbeans.modules.bpel.model.api.events.EntityInsertEvent;
040: import org.netbeans.modules.bpel.model.api.events.EntityRemoveEvent;
041: import org.netbeans.modules.bpel.model.api.events.EntityUpdateEvent;
042: import org.netbeans.modules.bpel.design.DesignView;
043: import org.netbeans.modules.bpel.design.model.patterns.CompositePattern;
044: import org.netbeans.modules.bpel.design.model.patterns.PartnerlinkPattern;
045: import org.netbeans.modules.bpel.design.model.patterns.Pattern;
046: import org.netbeans.modules.bpel.design.model.patterns.ProcessPattern;
047: import org.netbeans.modules.bpel.design.selection.EntitySelectionModel;
048: import org.netbeans.modules.bpel.model.api.events.PropertyRemoveEvent;
049: import org.netbeans.modules.bpel.model.api.events.PropertyUpdateEvent;
050: import org.openide.ErrorManager;
051:
052: /**
053: *
054: * @author Alexey
055: */
056: public class ModelChangeHandler implements ChangeEventListener {
057:
058: private DiagramModel model;
059: private BpelEntity bpelEntityToShow = null;
060:
061: /** Creates a new instance of ModelChangeHandler */
062: public ModelChangeHandler(DiagramModel model) {
063: this .model = model;
064: }
065:
066: public void notifyPropertyUpdated(final PropertyUpdateEvent event) {
067: Runnable r = new Runnable() {
068:
069: public void run() {
070: String name = event.getName();
071:
072: if (name.equals(BpelModel.STATE)) {
073:
074: model.getView().reloadModel();
075: return;
076: }
077:
078: Pattern pattern = getParentPattern(event.getParent());
079:
080: if (pattern == null) {
081: return;
082: }
083:
084: if (name.equals(NamedElement.NAME)) {
085: pattern.updateName();
086: } else if (pattern instanceof PartnerlinkPattern) {
087: reloadPartnerlinks();
088: }
089:
090: }
091:
092: private void reloadPartnerlinks() {
093: Process ps = model.getView().getBPELModel()
094: .getProcess();
095: ProcessPattern psp = (ProcessPattern) model
096: .getPattern(ps);
097: if (psp != null) {
098: psp.reloadPartnerlinks();
099: }
100:
101: }
102: };
103:
104: executeInAWTThread(r, event);
105: }
106:
107: public void notifyEntityRemoved(final EntityRemoveEvent event) {
108: Runnable r = new Runnable() {
109:
110: public void run() {
111: Pattern child = model.getPattern(event.getOldValue());
112: if (child != null) {
113: model.getView().getSelectionModel().fixSelection();
114: child.setParent(null);
115:
116: }
117: }
118: };
119: executeInAWTThread(r, event);
120:
121: }
122:
123: public void notifyEntityInserted(final EntityInsertEvent event) {
124: Runnable r = new Runnable() {
125:
126: public void run() {
127: BpelEntity child = event.getValue();
128:
129: //filter out elements like variabless and correlation sets
130: if (child instanceof Variable
131: || child instanceof CorrelationSet
132: || child instanceof Correlation
133: || child instanceof Import) {
134: return;
135: }
136:
137: updateParent(getParentPattern(event.getParent()),
138: getChildPattern(child));
139: bpelEntityToShow = child;
140: }
141:
142: ;
143:
144: }
145:
146: ;
147: executeInAWTThread(r, event);
148:
149: }
150:
151: public void notifyEntityUpdated(final EntityUpdateEvent event) {
152: Runnable r = new Runnable() {
153:
154: public void run() {
155: /**
156: * Remove old pattern
157: **/
158: BpelEntity oldChild = event.getOldValue();
159: if (oldChild != null) {
160: Pattern toRemove = model.getPattern(oldChild);
161: if (toRemove != null) {
162: toRemove.setParent(null);
163: }
164:
165: }
166:
167: BpelEntity parent = event.getParent();
168: BpelEntity child = event.getNewValue();
169:
170: if (parent == null) {
171: //root pattern was changed
172: if (child == null) {
173: //null child means broken model
174: model.setRootPattern(null);
175: } else if (child instanceof Process) {
176: model.setRootPattern(getChildPattern(child));
177: }
178: } else {
179: updateParent(getParentPattern(parent),
180: getChildPattern(child));
181: bpelEntityToShow = child;
182: }
183: }
184:
185: ;
186:
187: }
188:
189: ;
190: executeInAWTThread(r, event);
191:
192: }
193:
194: /**
195: * This method was supposed to delegate processing of events to AWT thread if necessary,
196: * but..
197: * read comments below
198: **/
199: private void executeInAWTThread(final Runnable inner,
200: final ChangeEvent event) {
201: Runnable outer = new Runnable() {
202:
203: public void run() {
204: try {
205: if (inner != null) {
206: inner.run();
207: }
208:
209: DesignView view = model.getView();
210: if (event.isLastInAtomic()) {
211:
212: //update diagram
213: view.diagramChanged();
214:
215: //notify the decoration model to update
216: view.getDecorationManager().decorationChanged();
217:
218: // if (patternToShow != null){
219: // view.getSelectionModel().setSelectedPattern(patternToShow);
220: // view.scrollSelectedToView();
221: // patternToShow = null;
222: // }
223:
224: if (bpelEntityToShow != null) {
225: view.getModel().expandToBeVisible(
226: bpelEntityToShow);
227: view.getSelectionModel().setSelected(
228: bpelEntityToShow);
229: view.scrollSelectedToView();
230: bpelEntityToShow = null;
231: }
232: }
233: } catch (Exception ex) {
234: ErrorManager.getDefault().notify(
235: ErrorManager.INFORMATIONAL, ex);
236: }
237: }
238: };
239: /**
240: * PROBLEM! Visual OM access is not thread-safe.
241: * We can use it only in AWT thread!
242: *
243: * We can't delegate the event dispatching to AWT.invokeLater,
244: * because we can work with removed elements only before the dispatch loop is over
245: *
246: * We can't delegate the event dispatching to AWT.invokeAndWait,
247: * because it can cause deadlock
248: **/
249:
250: if (SwingUtilities.isEventDispatchThread()) {
251: outer.run();
252: } else {
253: SwingUtilities.invokeLater(outer);
254: }
255:
256: }
257:
258: private void updateParent(Pattern parent, Pattern child) {
259: if (parent != null && child != null
260: && parent instanceof CompositePattern) {
261: child.setParent((CompositePattern) parent);
262: // patternToShow = child;
263: }
264: }
265:
266: /**
267: * Function returns pattern for parent element.
268: * In some cases intermediate BPEL container do not have their own patterns,
269: * so pattern of outer container is used
270: * @returns null if entity is not represented on diagram.
271: */
272:
273: private Pattern getParentPattern(BpelEntity e) {
274:
275: BpelEntity realParent = e;
276: if (e == null) {
277: //special case for brocken BPEL model
278: realParent = null;
279: } else if (e.getElementType() == ActivityHolder.class) {
280: //workaround for problem when Otherwise is not represented as pattern on diagramm
281: realParent = e.getParent();
282: }
283:
284: return (realParent != null) ? model.getPattern(realParent)
285: : null;
286: }
287:
288: private Pattern getChildPattern(BpelEntity e) {
289:
290: if (e == null) {
291: return null;
292: }
293:
294: Pattern result = model.getPattern(e);
295:
296: if (result == null) {
297: result = model.createPattern(e);
298: }
299: return result;
300: }
301:
302: public void notifyPropertyRemoved(PropertyRemoveEvent event) {
303: /**
304: * try to dispatch this event with empty runnable, because it can hold
305: * "lastInAtomic" flag ON, so it should trigger diagram repaint
306: **/
307: executeInAWTThread(null, event);
308: }
309:
310: public void notifyArrayUpdated(ArrayUpdateEvent event) {
311: /**
312: * try to dispatch this event with empty runnable, because it can hold
313: * "lastInAtomic" flag ON, so it should trigger diagram repaint
314: **/
315:
316: executeInAWTThread(null, event);
317: }
318: }
|