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