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.mapper.logging.multiview;
021:
022: import java.awt.EventQueue;
023: import java.beans.PropertyChangeEvent;
024: import java.beans.PropertyChangeListener;
025: import java.lang.ref.WeakReference;
026: import java.util.EventObject;
027: import javax.swing.SwingUtilities;
028: import org.netbeans.modules.bpel.editors.api.utils.Util;
029: import org.netbeans.modules.bpel.mapper.logging.model.LoggingMapperModelFactory;
030: import org.netbeans.modules.bpel.mapper.model.GraphExpandProcessor;
031: import org.netbeans.modules.bpel.mapper.multiview.BpelDesignContext;
032: import org.netbeans.modules.bpel.mapper.multiview.BpelModelSynchListener;
033: import org.netbeans.modules.bpel.mapper.multiview.DesignContextController;
034: import org.netbeans.modules.bpel.mapper.multiview.DesignContextUtil;
035: import org.netbeans.modules.bpel.mapper.multiview.MapperMultiviewElement;
036: import org.netbeans.modules.bpel.mapper.multiview.MapperStateManager;
037: import org.netbeans.modules.bpel.mapper.multiview.ShowMapperCookie;
038: import org.netbeans.modules.bpel.mapper.tree.spi.MapperTcContext;
039: import org.netbeans.modules.bpel.model.api.BpelEntity;
040: import org.netbeans.modules.bpel.model.api.BpelModel;
041: import org.netbeans.modules.bpel.model.api.events.ChangeEvent;
042: import org.netbeans.modules.soa.mappercore.Mapper;
043: import org.netbeans.modules.soa.mappercore.model.MapperModel;
044: import org.netbeans.modules.xml.xam.Model.State;
045: import org.netbeans.modules.xml.xam.Nameable;
046: import org.openide.nodes.Node;
047: import org.openide.util.NbBundle;
048: import org.openide.util.RequestProcessor;
049: import org.openide.windows.TopComponent;
050:
051: /**
052: * Controls the state of the BPEL mapper and manages different events:
053: * - change of activated node (correspondent mapper TC activated nodes)
054: * - change of mapper Tc lifecycle state (intrested in mapperTc showing, hidden, closed )
055: * - change in the related BPEL model
056: * - change the state of BPEL model
057: *
058: * @author nk160297
059: * @author Vitaly Bychkov
060: *
061: */
062: public class DesignContextControllerImpl2 implements
063: DesignContextController, PropertyChangeListener {
064:
065: private BpelDesignContext mContext;
066:
067: private MapperTcContext mMapperTcContext;
068: private BpelModelSynchListener mBpelModelSynchListener;
069:
070: private BpelModel myBpelModel;
071: // flag property for MapperTC showing/hidding states
072: private boolean isMapperShown;
073: private BpelDesignContext mNewContext;
074: private MapperStateManager myMapperStateManager;
075:
076: private static final int ACTION_NODE_CHANGE_TASK_DELAY = 150;
077: private transient RequestProcessor.Task myPreviousTask;
078: private int myDelay = ACTION_NODE_CHANGE_TASK_DELAY;
079:
080: private WeakReference<Object> mBpelModelUpdateSourceRef;
081:
082: /**
083: * The lookup of mapper Tc must contain BPELDataObject, BpelModel and ShowMapperCookie
084: * @param mapperTc
085: */
086: public DesignContextControllerImpl2(TopComponent mapperTc) {
087: assert mapperTc != null;
088: assert mapperTc instanceof MapperTcContext;
089:
090: mMapperTcContext = (MapperTcContext) mapperTc;
091: myBpelModel = mapperTc.getLookup().lookup(BpelModel.class);
092: assert myBpelModel != null;
093: mBpelModelSynchListener = new BpelModelSynchListener(this );
094: mBpelModelSynchListener.register(myBpelModel);
095:
096: TopComponent.getRegistry().addPropertyChangeListener(this );
097:
098: initContext();
099: }
100:
101: public void cleanup() {
102: TopComponent.getRegistry().removePropertyChangeListener(this );
103: mBpelModelSynchListener.unregisterAll();
104: myBpelModel = null;
105: mMapperTcContext = null;
106: }
107:
108: public synchronized void setBpelModelUpdateSource(Object source) {
109: mBpelModelUpdateSourceRef = new WeakReference<Object>(source);
110: }
111:
112: public synchronized BpelDesignContext getContext() {
113: return mContext;
114: }
115:
116: public synchronized void setContext(BpelDesignContext newContext) {
117: assert EventQueue.isDispatchThread();
118: setContext(newContext, false);
119: }
120:
121: // context changes if selectedEntity changes
122: public synchronized void setContext(BpelDesignContext newContext,
123: boolean forceReload) {
124: assert EventQueue.isDispatchThread();
125: //
126:
127: if (mNewContext == null && forceReload) {
128: reloadMapper(new EventObject(new Object()));
129: return;
130: }
131:
132: mNewContext = newContext;
133:
134: boolean isValidContext = DesignContextUtil
135: .isValidContext(mContext);
136: // null means unsupported context - in result the old context must be stored
137: if (newContext == null && isValidContext) {
138: return;
139: }
140:
141: // todo m
142: if (newContext == null && !isValidContext) {
143: if (isMapperShown) {
144: showNotValidContext(mContext);
145: }
146: return;
147: }
148:
149: BpelEntity newEntity = newContext.getSelectedEntity();
150:
151: // avoid entities from another BpelModel
152: if ((newEntity != null && !myBpelModel.equals(newEntity
153: .getBpelModel()))
154: || newEntity == null) {
155: return;
156: }
157:
158: // the context have to be updated just if context changes,
159: // in case the bpel model changes doesn't need to update context
160: if (newContext.equals(mContext) && !forceReload) {
161: return;
162: }
163:
164: setActivatedNodes(newContext == null ? null : newContext
165: .getActivatedNode());
166:
167: if (isMapperShown) {
168: setContextImpl(forceReload);
169: }
170: }
171:
172: // TODO m
173: public void reloadMapper(EventObject event) {
174: //
175: // Ignore reload if it has been initiated by the mapper itself
176: if (event.getSource() == getBpelModelUpdateSource()) {
177: return;
178: }
179:
180: if (myPreviousTask != null) {
181: myPreviousTask.cancel();
182: }
183: if (myPreviousTask != null
184: && !myPreviousTask.isFinished()
185: && RequestProcessor.getDefault()
186: .isRequestProcessorThread()) // issue 125439
187: {
188: myPreviousTask.waitFinished();
189: myPreviousTask = null;
190: }
191:
192: if (!EventQueue.isDispatchThread()) {
193: SwingUtilities.invokeLater(new Runnable() {
194:
195: public void run() {
196: performReloadMapperInAwt();
197: }
198: });
199: } else {
200: performReloadMapperInAwt();
201: }
202: }
203:
204: synchronized void performReloadMapperInAwt() {
205: assert EventQueue.isDispatchThread();
206: if (!DesignContextUtil.isValidContext(mContext)) {
207: setDelay(0);
208: updateContext(-1, false);
209: return;
210: }
211:
212: if (isMapperShown) {
213: reloadMapperImpl();
214: }
215: }
216:
217: private void setDelay(int delay) {
218: myDelay = delay;
219: }
220:
221: private int getDelay() {
222: return myDelay;
223: }
224:
225: // TODO m
226: public void propertyChange(PropertyChangeEvent evt) {
227: String propertyName = evt.getPropertyName();
228:
229: if (propertyName
230: .equals(TopComponent.Registry.PROP_ACTIVATED_NODES)) {
231: updateContext();
232: } else {
233: // Other properties are not supported
234: return;
235: }
236: }
237:
238: public void showMapper() {
239: assert EventQueue.isDispatchThread();
240: // TODO m
241: isMapperShown = true;
242: Mapper mapper = mMapperTcContext != null ? mMapperTcContext
243: .getMapper() : null;
244: if (mapper != null) {
245: mapper.setVisible(true);
246: }
247:
248: updateContext(-1, true);
249: // setContextImpl(true);
250: }
251:
252: public void hideMapper() {
253: assert EventQueue.isDispatchThread();
254: isMapperShown = false;
255: Mapper mapper = mMapperTcContext != null ? mMapperTcContext
256: .getMapper() : null;
257: if (mapper != null) {
258: mapper.setVisible(false);
259: }
260: }
261:
262: public MapperTcContext getMapperTcContext() {
263: return mMapperTcContext;
264: }
265:
266: private synchronized void initContext() {
267: setContext(LoggingDesignContextFactory.getInstance()
268: .getActivatedContext(myBpelModel));
269: myMapperStateManager = new MapperStateManager(mMapperTcContext);
270: }
271:
272: private void updateContext(int delay, boolean forceReload) {
273: assert EventQueue.isDispatchThread();
274: if (delay <= 0) {
275: setDelay(ACTION_NODE_CHANGE_TASK_DELAY);
276: }
277:
278: if (myPreviousTask != null) {
279: myPreviousTask.cancel();
280: }
281: if (myPreviousTask != null
282: && !myPreviousTask.isFinished()
283: && RequestProcessor.getDefault()
284: .isRequestProcessorThread()) // issue 125439
285: {
286: myPreviousTask.waitFinished();
287: myPreviousTask = null;
288: }
289:
290: if (delay <= 0) {
291: setContext(LoggingDesignContextFactory.getInstance()
292: .getActivatedContext(myBpelModel), forceReload);
293: } else {
294: myPreviousTask = RequestProcessor.getDefault().post(
295: new Runnable() {
296: public void run() {
297: // BpelDesignContext newBpelContext = DesignContextChangeListener.getActivatedContext(myBpelModel);
298: SwingUtilities.invokeLater(new Runnable() {
299: public void run() {
300: setContext(LoggingDesignContextFactory
301: .getInstance()
302: .getActivatedContext(
303: myBpelModel));
304: }
305: });
306: }
307: }, delay);
308: }
309: }
310:
311: // todo m
312: private void updateContext() {
313: updateContext(getDelay(), false);
314: }
315:
316: // TODO m correct behaviour if just selectedEntity changes
317: private void setContextImpl() {
318: setContextImpl(false);
319: }
320:
321: private void setContextImpl(boolean forceReload) {
322: // Copy the context to a new local variable at first.
323: BpelDesignContext newContext = mNewContext;
324: //
325: if (newContext == null) {
326: // do nothing - simple continue to show the old context
327: return;
328: }
329:
330: if (isModelInvalid()) {
331: myMapperStateManager.storeOldEntityContext(mContext);
332: // hide mapper if BpelModel is invalid
333: showModelIsInvalid();
334: return;
335: }
336: //
337: BpelEntity oldContextEntity = mContext != null ? mContext
338: .getContextEntity() : null;
339: BpelEntity newContextEntity = newContext.getContextEntity();
340: if (newContextEntity == null) {
341: myMapperStateManager.storeOldEntityContext(mContext);
342: // Hide the mapper if unmappable BPEL entity is selected
343: showUnsupportedEntity(newContext);
344: return;
345: }
346: //
347:
348: if (forceReload || !newContext.equals(mContext)) {
349: if (forceReload
350: || !newContextEntity.equals(oldContextEntity)) {
351: myMapperStateManager.storeOldEntityContext(mContext);
352: //
353: MapperModel newMapperModel = new LoggingMapperModelFactory()
354: .constructModel(mMapperTcContext, newContext);
355: //
356:
357: mContext = newContext;
358: setMapperModel(newMapperModel);
359: myMapperStateManager.restoreOldEntityContext(mContext);
360: //
361: }
362:
363: SwingUtilities.invokeLater(new Runnable() {
364: public void run() {
365: GraphExpandProcessor.expandGraph(mMapperTcContext,
366: mContext);
367: }
368: });
369: //
370: // mMapperTcContext.showMapperTcGroup(true);
371: }
372: /*
373: else {
374: //
375: boolean needReload;
376: synchronized(DesignContextControllerImpl2.this) {
377: needReload = mNeedReload;
378: }
379: if (needReload) {
380: reloadMapperImpl();
381: }
382: }
383: */
384: }
385:
386: private void reloadMapperImpl() {
387: if (mContext == null) {
388: return;
389: }
390: //
391: if (isModelInvalid()) {
392: myMapperStateManager.storeOldEntityContext(mContext);
393: showModelIsInvalid();
394: return;
395: }
396:
397: // if (!isValidContext(mContext)) {
398: // updateContext();
399: // return;
400: // }
401: //
402: //
403: MapperModel newMapperModel = new LoggingMapperModelFactory()
404: .constructModel(mMapperTcContext, mContext);
405:
406: myMapperStateManager.storeOldEntityContext(mContext);
407: setMapperModel(newMapperModel);
408: myMapperStateManager.restoreOldEntityContext(mContext);
409: }
410:
411: private synchronized Object getBpelModelUpdateSource() {
412: if (mBpelModelUpdateSourceRef != null) {
413: return mBpelModelUpdateSourceRef.get();
414: }
415: //
416: return null;
417: }
418:
419: /**
420: * works in swing thread only
421: *
422: */
423: private void setActivatedNodes(final Node aNode) {
424: assert EventQueue.isDispatchThread();
425: if (mMapperTcContext != null) {
426:
427: TopComponent mapperTc = mMapperTcContext.getTopComponent();
428: if (mapperTc != null) {
429: if (aNode != null) {
430: mapperTc.setActivatedNodes(new Node[] { aNode });
431: } else {
432: mapperTc.setActivatedNodes(new Node[0]);
433: }
434: }
435: }
436: }
437:
438: private void setMapperModel(MapperModel newMapperModel) {
439: assert newMapperModel != null;
440: mMapperTcContext.setMapperModel(newMapperModel);
441: }
442:
443: private void showModelIsInvalid() {
444: disableMapper(NbBundle.getMessage(MapperMultiviewElement.class,
445: "LBL_LoggingInvalid_BpelModel")); // NOI18N
446: }
447:
448: private void showUnsupportedEntity(BpelDesignContext context) {
449: assert context != null;
450: String entityName = null;
451: Node node = context.getActivatedNode();
452: entityName = node != null ? node.getDisplayName() : null;
453: if (entityName == null) {
454: BpelEntity entity = context.getSelectedEntity();
455: entityName = entity instanceof Nameable ? ((Nameable) entity)
456: .getName()
457: : Util.getTagName(entity);
458: }
459: entityName = entityName == null ? "" : entityName;
460: disableMapper(NbBundle.getMessage(MapperMultiviewElement.class,
461: "LBL_LoggingEmptyMapper", entityName)); // NOI18N
462: }
463:
464: private void showNotValidContext(BpelDesignContext context) {
465: assert context != null;
466: String entityName = null;
467: Node node = context.getActivatedNode();
468: entityName = node != null ? node.getDisplayName() : null;
469: if (entityName == null) {
470: BpelEntity entity = context.getSelectedEntity();
471: entityName = entity instanceof Nameable ? ((Nameable) entity)
472: .getName()
473: : Util.getTagName(entity);
474: }
475: entityName = entityName == null ? "" : entityName;
476: disableMapper(NbBundle.getMessage(MapperMultiviewElement.class,
477: "LBL_LoggingInValidMapperContext", entityName)); // NOI18N
478: }
479:
480: private void disableMapper(String message) {
481: TopComponent tc = mMapperTcContext.getTopComponent();
482: if (tc == null) {
483: return;
484: }
485:
486: ShowMapperCookie showCookie = tc.getLookup().lookup(
487: ShowMapperCookie.class);
488: if (showCookie != null) {
489: showCookie.show(message);
490: }
491:
492: mContext = null;
493: }
494:
495: private boolean isModelInvalid() {
496: BpelModel bpelModel = myBpelModel;
497: if (bpelModel != null) {
498: return bpelModel.getState().equals(State.NOT_WELL_FORMED);
499: }
500: return false; // Consider the model valid by default
501: }
502:
503: public void processDataObject(Object dataObject) {
504: mBpelModelSynchListener.processDataObject(dataObject);
505: }
506: }
|