1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #include "precompiled_framework.hxx"
23 
24 #include "services/ContextChangeEventMultiplexer.hxx"
25 #include "services.h"
26 
27 using ::rtl::OUString;
28 
29 #define A2S(s) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
30 
31 namespace framework {
32 
33 #define IMPLEMENTATION_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexer"
34 #define SERVICE_NAME "com.sun.star.ui.ContextChangeEventMultiplexer"
35 #define SINGLETON_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexerSigleton"
36 
37 
38 ContextChangeEventMultiplexer::ContextChangeEventMultiplexer (
39     const cssu::Reference<css::uno::XComponentContext>& rxContext)
40     : ContextChangeEventMultiplexerInterfaceBase(m_aMutex),
41       maListeners()
42 {
43     (void)rxContext;
44 }
45 
46 
47 
48 
49 ContextChangeEventMultiplexer::~ContextChangeEventMultiplexer (void)
50 {
51     maListeners.clear();
52 }
53 
54 
55 
56 
57 // XContextChangeEventMultiplexer
58 
59 void SAL_CALL ContextChangeEventMultiplexer::addContextChangeEventListener (
60     const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
61     const cssu::Reference<cssu::XInterface>& rxEventFocus)
62     throw(cssu::RuntimeException,cssl::IllegalArgumentException)
63 {
64     if ( ! rxListener.is())
65         throw css::lang::IllegalArgumentException(
66             A2S("can not add an empty reference"),
67             static_cast<XWeak*>(this),
68             0);
69 
70     ListenerMap::iterator iListenerContainer (maListeners.find(rxEventFocus));
71     if (iListenerContainer == maListeners.end())
72     {
73         // Create a new listener container for the event focus.
74         iListenerContainer = maListeners.insert(
75             ListenerMap::value_type(
76                 rxEventFocus,
77                 ListenerContainer())).first;
78     }
79     if (iListenerContainer != maListeners.end())
80     {
81         ListenerContainer& rContainer (iListenerContainer->second);
82         if (::std::find(rContainer.begin(), rContainer.end(), rxListener) == rContainer.end())
83             rContainer.push_back(rxListener);
84         else
85         {
86             // The listener was added for the same event focus
87             // previously.  That is an error.
88             throw cssl::IllegalArgumentException(A2S("listener added twice"), static_cast<XWeak*>(this), 0);
89         }
90     }
91 }
92 
93 
94 
95 
96 void SAL_CALL ContextChangeEventMultiplexer::removeContextChangeEventListener (
97     const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
98     const cssu::Reference<cssu::XInterface>& rxEventFocus)
99     throw(cssu::RuntimeException,cssl::IllegalArgumentException)
100 {
101     if ( ! rxListener.is())
102         throw cssl::IllegalArgumentException(A2S("can not remove an empty reference"), static_cast<XWeak*>(this), 0);
103 
104     ListenerMap::iterator iListenerContainer (maListeners.find(rxEventFocus));
105     if (iListenerContainer != maListeners.end())
106     {
107         ListenerContainer& rContainer (iListenerContainer->second);
108         const ListenerContainer::iterator iListener (::std::find(rContainer.begin(), rContainer.end(), rxListener));
109         if (iListener != rContainer.end())
110             rContainer.erase(iListener);
111     }
112 
113 }
114 
115 
116 
117 
118 void SAL_CALL ContextChangeEventMultiplexer::removeAllContextChangeEventListeners (
119     const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener)
120     throw(cssu::RuntimeException,cssl::IllegalArgumentException)
121 {
122     if ( ! rxListener.is())
123         throw cssl::IllegalArgumentException(A2S("can not remove an empty reference"), static_cast<XWeak*>(this), 0);
124 
125     for (ListenerMap::iterator
126              iContainer(maListeners.begin()),
127              iEnd(maListeners.end());
128          iContainer!=iEnd;
129          ++iContainer)
130     {
131         const ListenerContainer::iterator iListener (::std::find(iContainer->second.begin(), iContainer->second.end(), rxListener));
132         if (iListener != iContainer->second.end())
133             iContainer->second.erase(iListener);
134     }
135 }
136 
137 
138 
139 
140 
141 void SAL_CALL ContextChangeEventMultiplexer::broadcastContextChangeEvent (
142     const css::ui::ContextChangeEventObject& rEventObject,
143     const cssu::Reference<cssu::XInterface>& rxEventFocus)
144     throw(cssu::RuntimeException)
145 {
146     BroadcastEventToSingleContainer(rEventObject, rxEventFocus);
147     if (rxEventFocus.is())
148         BroadcastEventToSingleContainer(rEventObject, NULL);
149 }
150 
151 
152 
153 
154 void ContextChangeEventMultiplexer::BroadcastEventToSingleContainer (
155     const css::ui::ContextChangeEventObject& rEventObject,
156     const cssu::Reference<cssu::XInterface>& rxEventFocus)
157 {
158     ListenerMap::iterator iListenerContainer (maListeners.find(rxEventFocus));
159     if (iListenerContainer != maListeners.end())
160     {
161         // Create a copy of the listener container to avoid problems
162         // when one of the called listeners calls add... or remove...
163         ListenerContainer aContainer (iListenerContainer->second);
164         for (ListenerContainer::const_iterator
165                  iListener(aContainer.begin()),
166                  iEnd(aContainer.end());
167              iListener!=iEnd;
168              ++iListener)
169         {
170             (*iListener)->notifyContextChangeEvent(rEventObject);
171         }
172     }
173 }
174 
175 
176 
177 
178 // XSingleComponentFactory
179 
180 cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::createInstanceWithContext (
181     const cssu::Reference<cssu::XComponentContext>& rxContext)
182     throw (cssu::Exception, cssu::RuntimeException)
183 {
184     (void)rxContext;
185     return cssu::Reference<cssu::XInterface>();
186 }
187 
188 
189 
190 
191 cssu::Reference<cssu::XInterface > SAL_CALL ContextChangeEventMultiplexer::createInstanceWithArgumentsAndContext (
192     const cssu::Sequence<cssu::Any>& rArguments,
193     const cssu::Reference<cssu::XComponentContext>& rxContext)
194     throw (cssu::Exception, cssu::RuntimeException)
195 {
196     (void)rArguments;
197     (void)rxContext;
198     return cssu::Reference<cssu::XInterface>();
199 }
200 
201 
202 
203 
204 // XServiceInfo
205 
206 ::rtl::OUString SAL_CALL ContextChangeEventMultiplexer::getImplementationName (void)
207     throw(cssu::RuntimeException)
208 {
209     return impl_getStaticImplementationName();
210 }
211 
212 
213 
214 
215 
216 sal_Bool SAL_CALL ContextChangeEventMultiplexer::supportsService (
217     const ::rtl::OUString& rsServiceName)
218     throw (cssu::RuntimeException)
219 {
220     return ::comphelper::findValue(static_GetSupportedServiceNames(), rsServiceName, sal_True).getLength() != 0;
221 }
222 
223 
224 
225 
226 cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::getSupportedServiceNames (void)
227     throw (cssu::RuntimeException)
228 {
229     return static_GetSupportedServiceNames();
230 }
231 
232 
233 
234 
235 // Local and static methods.
236 
237 OUString SAL_CALL ContextChangeEventMultiplexer::impl_getStaticImplementationName (void)
238 {
239     return A2S(IMPLEMENTATION_NAME);
240 }
241 
242 
243 
244 
245 cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::static_GetSupportedServiceNames (void)
246 {
247     cssu::Sequence<OUString> aServiceNames (2);
248     aServiceNames[0] = A2S(SERVICE_NAME);
249     aServiceNames[1] = A2S(SINGLETON_NAME);
250     return aServiceNames;
251 }
252 
253 
254 
255 
256 cssu::Reference<cssu::XInterface> ContextChangeEventMultiplexer::impl_createFactory (
257     const cssu::Reference<cssl::XMultiServiceFactory>& rxServiceManager)
258 {
259     (void)rxServiceManager;
260     return cppu::createSingleComponentFactory(
261         ContextChangeEventMultiplexer::static_CreateInstance,
262         ContextChangeEventMultiplexer::impl_getStaticImplementationName(),
263         ContextChangeEventMultiplexer::static_GetSupportedServiceNames()
264         );
265 }
266 
267 
268 
269 
270 cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::static_CreateInstance (
271     const cssu::Reference<cssu::XComponentContext>& rxComponentContext)
272     throw (cssu::Exception)
273 {
274     ContextChangeEventMultiplexer* pObject = new ContextChangeEventMultiplexer(rxComponentContext);
275     cssu::Reference<cssu::XInterface> xService (static_cast<XWeak*>(pObject), cssu::UNO_QUERY);
276     return xService;
277 }
278 
279 }  // end of namespace framework
280