Removed contact application support prints
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / WorkbenchWindowSessionContextProviderSource.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.ui;
13
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.concurrent.atomic.AtomicBoolean;
19
20 import org.eclipse.ui.IWindowListener;
21 import org.eclipse.ui.IWorkbench;
22 import org.eclipse.ui.IWorkbenchWindow;
23 import org.simantics.db.management.ISessionContext;
24 import org.simantics.db.management.ISessionContextProvider;
25 import org.simantics.db.management.ISessionContextProviderSource;
26 import org.simantics.db.management.SessionContextProvider;
27 import org.simantics.ui.internal.SessionUtils;
28
29 /**
30  *
31  */
32 public class WorkbenchWindowSessionContextProviderSource implements ISessionContextProviderSource, IWindowListener {
33
34     private static final boolean         DEBUG            = false;
35
36     ISessionContextProvider[]            ZERO             = new ISessionContextProvider[0];
37
38     Object                               temporaryContext = new Object() {
39         @Override
40         public String toString() {
41             return "Temporary Context Object";
42         }
43     };
44
45     /**
46      * The set of providers associated through
47      * {@link #put(Object, ISessionContextProvider)} for knowing which
48      * associations can be removed with {@link #remove(Object)}.
49      */
50     Set<Object>                          manualProviders  = new HashSet<Object>();
51
52     Map<Object, ISessionContextProvider> providers        = new HashMap<Object, ISessionContextProvider>();
53
54     ISessionContextProvider[]            allProviders     = ZERO;
55
56     IWorkbenchWindow                     activeWindow     = null;
57
58     ISessionContextProvider              activeProvider   = null;
59
60     AtomicBoolean                        isFirstWindow    = new AtomicBoolean(true);
61
62     public WorkbenchWindowSessionContextProviderSource(IWorkbench workbench) {
63         workbench.addWindowListener(this);
64
65         // Bind the initial context provider to a temporary object.
66         // This binding will be replaced later on when a workbench
67         // window is opened.
68         activeProvider = new SessionContextProvider(temporaryContext);
69         if (DEBUG)
70             System.out.println("Initial active session context provider: " + activeProvider);
71         addProvider(temporaryContext, activeProvider);
72     }
73
74     @Override
75     public ISessionContextProvider get(Object context) {
76         synchronized (providers) {
77             return providers.get(context);
78         }
79     }
80
81     @Override
82     public ISessionContextProvider getActive() {
83         // activeWindow may be null at this time.
84         return activeProvider;
85     }
86
87     @Override
88     public ISessionContextProvider[] getAll() {
89         return allProviders;
90     }
91
92     @Override
93     public void put(Object context, ISessionContextProvider provider) {
94         synchronized (providers) {
95             ISessionContextProvider prev = providers.get(context);
96             if (prev != null)
97                 throw new IllegalArgumentException("invalid context (" + context
98                         + "), a session context provider is already associated with this context: " + prev
99                         + ". Attempted to associate the context with this provider: " + provider);
100             providers.put(context, provider);
101             manualProviders.add(context);
102         }
103     }
104
105     @Override
106     public ISessionContextProvider remove(Object context) {
107         synchronized (providers) {
108             if (!manualProviders.remove(context)) {
109                 throw new IllegalArgumentException("specified context not found: " + context);
110             }
111             return providers.remove(context);
112         }
113     }
114
115     @Override
116     public void windowActivated(IWorkbenchWindow window) {
117         if (DEBUG)
118             System.out.println("window activated: " + window);
119
120         boolean firstActiveWindow = (activeWindow == null);
121         activeWindow = window;
122         if (firstActiveWindow) {
123             // activeProvider should already be set.
124             assert activeProvider != null;
125             if (DEBUG)
126                 System.out.println("  first window activation!");
127         } else {
128             synchronized (providers) {
129                 activeProvider = providers.get(window);
130                 if (activeProvider == null) {
131                     // This may be an issue, the context provider
132                     // should already have been created through
133                     // createContextForWindow(IWorkbenchWindow).
134                     activeProvider = new SessionContextProvider(window);
135                     addProvider(window, activeProvider);
136                 }
137             }
138         }
139     }
140
141     @Override
142     public void windowClosed(IWorkbenchWindow window) {
143         if (DEBUG)
144             System.out.println("window closed: " + window);
145         removeProvider(window);
146     }
147
148     @Override
149     public void windowDeactivated(IWorkbenchWindow window) {
150         if (DEBUG)
151             System.out.println("window deactivated: " + window);
152     }
153
154     @Override
155     public void windowOpened(IWorkbenchWindow window) {
156         if (DEBUG)
157             System.out.println("window opened: " + window + ", active window = " + activeWindow);
158     }
159
160     private void addProvider(Object context, ISessionContextProvider p) {
161         synchronized (providers) {
162             if (providers.put(context, p) != null) {
163                 // This is a bug, should never happen.
164                 throw new Error("Unexpected bug, this should never happen!");
165             }
166             allProviders = providers.values().toArray(ZERO);
167         }
168     }
169
170     private void removeProvider(Object context) {
171         synchronized (providers) {
172             ISessionContextProvider provider = providers.remove(context);
173             if (provider == null) {
174                 // This is a bug, should never happen.
175                 throw new Error("Unexpected bug, this should never happen!");
176             }
177             allProviders = providers.values().toArray(ZERO);
178
179             // Make sure that any session remaining in the removed context will
180             // be disposed of eventually.
181             ISessionContext ctx = provider.getSessionContext();
182             if (ctx != null) {
183                 if (!SimanticsUI.isInUse(ctx)) {
184                     SessionUtils.releaseUnusedSessionAfterHoldTime(ctx);
185                 }
186             }
187         }
188     }
189
190     /**
191      * This is a purely internal mechanism to allow proper creation of context
192      * providers for workbench windows as early as possible during the workbench
193      * window construction process, i.e. in the
194      * <code>WorkbenchWindowAdvisor.preWindowOpen()</code> instantiated
195      * by <code>WorkbenchAdvisor</code>.
196      * 
197      * @param context
198      */
199     public void createProviderForWindow(IWorkbenchWindow context) {
200         synchronized (providers) {
201             if (isFirstWindow.compareAndSet(true, false)) {
202                 assert activeProvider != null;
203                 if (DEBUG)
204                     System.out.println("[Create Context] first window: " + context);
205
206                 SessionContextProvider v = (SessionContextProvider) providers.remove(temporaryContext);
207                 if (v != null) {
208                     v.setHandle(context);
209                     providers.put(context, v);
210                     if (DEBUG)
211                         System.out.println("  rebound: '" + v + "' to '" + context + "'");
212                 }
213             } else {
214                 if (DEBUG)
215                     System.out.println("[Create Context] new window: " + context);
216                 // Create new session context provider
217                 SessionContextProvider v = new SessionContextProvider(context);
218                 ISessionContextProvider active = getActive();
219                 if (active != null)
220                     v.setSessionContext(active.getSessionContext());
221                 addProvider(context, v);
222             }
223         }
224     }
225
226 }