blob: 2c2482ed19bf9b1f660c281003bf79fc62d9cb63 [file] [log] [blame]
Pierre De Ropfaca2892016-01-31 23:27:05 +00001package org.apache.felix.dm.lambda;
2
3import java.util.concurrent.CompletableFuture;
4import java.util.function.Consumer;
5
6import org.apache.felix.dm.Component;
7import org.apache.felix.dm.DependencyManager;
8import org.apache.felix.dm.lambda.impl.BundleAdapterBuilderImpl;
9import org.apache.felix.dm.lambda.impl.BundleDependencyBuilderImpl;
10import org.apache.felix.dm.lambda.impl.CompletableFutureDependencyImpl;
11import org.apache.felix.dm.lambda.impl.ComponentBuilderImpl;
12import org.apache.felix.dm.lambda.impl.ConfigurationDependencyBuilderImpl;
13import org.apache.felix.dm.lambda.impl.FactoryPidAdapterBuilderImpl;
14import org.apache.felix.dm.lambda.impl.ServiceAdapterBuilderImpl;
15import org.apache.felix.dm.lambda.impl.ServiceAspectBuilderImpl;
16import org.apache.felix.dm.lambda.impl.ServiceDependencyBuilderImpl;
17import org.osgi.framework.BundleActivator;
18import org.osgi.framework.BundleContext;
19
20/**
21 * Defines a base for Activators in order to build DependencyManager Components using a java8 style.<p>
22 *
23 * Code example using auto configured fields:
24 *
25 * <pre> {@code
26 *
Pierre De Rop501d61b2016-02-04 07:53:14 +000027 * import org.apache.felix.dm.lambda.DependencyManagerActivator;
Pierre De Ropfaca2892016-01-31 23:27:05 +000028 *
29 * public class Activator extends DependencyManagerActivator {
Pierre De Rop11527502016-02-18 21:07:16 +000030 * public void init(BundleContext ctx, DependencyManager dm) throws Exception {
Pierre De Ropfaca2892016-01-31 23:27:05 +000031 * component(comp -> comp
32 * .provides(Service.class, property -> "value")
33 * .impl(ServiceImpl.class)
Pierre De Rop11527502016-02-18 21:07:16 +000034 * .withSvc(LogService.class, ConfigurationAdmni.class) // both services are required and injected in class fields with compatible types.
Pierre De Ropfaca2892016-01-31 23:27:05 +000035 * }
36 * }
37 * }</pre>
38 *
39 * Code example using reflection callbacks:
40 *
41 * <pre> {@code
Pierre De Rop501d61b2016-02-04 07:53:14 +000042 * import org.apache.felix.dm.lambda.DependencyManagerActivator;
Pierre De Ropfaca2892016-01-31 23:27:05 +000043 *
44 * public class Activator extends DependencyManagerActivator {
Pierre De Rop11527502016-02-18 21:07:16 +000045 * public void init(BundleContext ctx, DependencyManager dm) throws Exception {
Pierre De Ropfaca2892016-01-31 23:27:05 +000046 * component(comp -> comp
47 * .provides(Service.class, property -> "value")
48 * .impl(ServiceImpl.class)
Pierre De Rop11527502016-02-18 21:07:16 +000049 * .withSvc(LogService.class, svc -> svc.add("setLog"))
50 * .withSvc(ConfigurationAdmni.class, svc -> svc.add("setConfigAdmin")))
Pierre De Ropfaca2892016-01-31 23:27:05 +000051 * }
52 * }
53 * }</pre>
54 *
55 * Code example using method references:
56 *
57 * <pre> {@code
Pierre De Rop501d61b2016-02-04 07:53:14 +000058 * import org.apache.felix.dm.lambda.DependencyManagerActivator;
Pierre De Ropfaca2892016-01-31 23:27:05 +000059 *
60 * public class Activator extends DependencyManagerActivator {
Pierre De Rop11527502016-02-18 21:07:16 +000061 * public void init(BundleContext ctx, DependencyManager dm) throws Exception {
Pierre De Ropfaca2892016-01-31 23:27:05 +000062 * component(comp -> comp
63 * .provides(Service.class, property -> "value")
64 * .impl(ServiceImpl.class)
Pierre De Rop11527502016-02-18 21:07:16 +000065 * .withSvc(LogService.class, svc -> svc.add(ServiceImpl::setLog))
66 * .withSvc(ConfigurationAdmni.class, svc -> svc.add(ServiceImpl::setConfigAdmin)))
Pierre De Ropfaca2892016-01-31 23:27:05 +000067 * }
68 * }
69 * }</pre>
70 */
71public abstract class DependencyManagerActivator implements BundleActivator {
72 /**
73 * DependencyManager object used to create/register real DM Components that are built by this activator.
74 */
Pierre De Rop0aac1362016-02-02 19:46:08 +000075 private DependencyManager m_manager;
Pierre De Ropfaca2892016-01-31 23:27:05 +000076
77 /**
Pierre De Ropfaca2892016-01-31 23:27:05 +000078 * Our Activator is starting.
79 */
80 @Override
81 public void start(BundleContext context) throws Exception {
82 m_manager = new DependencyManager(context);
Pierre De Rop11527502016-02-18 21:07:16 +000083 init(context, m_manager);
Pierre De Ropfaca2892016-01-31 23:27:05 +000084 }
85
86 /**
87 * Our Activator is stopped.
88 */
89 @Override
90 public void stop(BundleContext context) throws Exception {
Pierre De Rop11527502016-02-18 21:07:16 +000091 destroy();
Pierre De Ropfaca2892016-01-31 23:27:05 +000092 }
93
94 /**
95 * Sub classes must override this method in order to build some DM components.
Pierre De Rop11527502016-02-18 21:07:16 +000096 * @param ctx the context associated to the bundle
97 * @param dm the DependencyManager assocaited to this activator
Pierre De Ropfaca2892016-01-31 23:27:05 +000098 * @throws Exception if the activation fails
99 */
Pierre De Rop11527502016-02-18 21:07:16 +0000100 protected abstract void init(BundleContext ctx, DependencyManager dm) throws Exception;
Pierre De Ropfaca2892016-01-31 23:27:05 +0000101
102 /**
103 * Sub classes may override this method that is called when the Activator is stopped.
104 * @throws Exception if the deactivation fails
105 */
Pierre De Rop11527502016-02-18 21:07:16 +0000106 protected void destroy() throws Exception {
Pierre De Ropfaca2892016-01-31 23:27:05 +0000107 }
108
109 /**
110 * Returns the DependencyManager used to create/managed DM Components.
111 *
112 * @return the DependencyManager associated to this Activator
113 */
Pierre De Rop0fdefef2016-02-03 13:43:15 +0000114 public DependencyManager getDM() {
Pierre De Ropfaca2892016-01-31 23:27:05 +0000115 return m_manager;
116 }
117
118 /**
119 * Returns the bundle context that is associated with this bundle.
120 *
121 * @return the bundle context
122 */
Pierre De Rop0fdefef2016-02-03 13:43:15 +0000123 public BundleContext getBC() {
Pierre De Rop0aac1362016-02-02 19:46:08 +0000124 return m_manager.getBundleContext();
Pierre De Ropfaca2892016-01-31 23:27:05 +0000125 }
126
127 /**
128 * Creates a Component builder that can be used to create a DM Component.
129 * @return a Component builder that can be used to create a DM Component.
130 */
131 protected ComponentBuilder<?> component() {
132 return new ComponentBuilderImpl(m_manager);
133 }
134
135 /**
136 * Creates a service Aspect builder that can be used to create a DM Aspect Component.
137 *
138 * @param <T> the aspect service type
139 * @param aspectType the aspect service
140 * @return a service Aspect builder.
141 */
142 protected <T> ServiceAspectBuilder<T> aspect(Class<T> aspectType) {
143 ServiceAspectBuilderImpl<T> aspectBuilder = new ServiceAspectBuilderImpl<>(m_manager, aspectType);
144 return aspectBuilder;
145 }
146
147 /**
148 * Creates a service Adapter builder that can be used to create a DM Adapter Component.
149 *
150 * @param <T> the adapted service type.
151 * @param adaptee the adapted service
152 * @return a service Adapter builder.
153 */
154 protected <T> ServiceAdapterBuilder<T> adapter(Class<T> adaptee) {
155 ServiceAdapterBuilderImpl<T> adapterBuilder = new ServiceAdapterBuilderImpl<>(m_manager, adaptee);
156 return adapterBuilder;
157 }
158
159 /**
160 * Builds a DM Component using a Java8 style ComponentBuilder.
161 * @param consumer the lambda that will use the ComponentBuilder for building the DM component.
162 * The component is auto-added to the DependencyManager, unless the lambda calls the ComponentBuilder.autoAdd(false) method.
163 * @return a newly built DM component.
164 */
165 protected Component component(Consumer<ComponentBuilder<?>> consumer) {
166 return component(m_manager, consumer);
167 }
168
169 /**
170 * Builds a DM Aspect Component using a Java8 style AspectBuilder.
171 * The component is auto-added to the DependencyManager, unless the lambda calls the AspectBuilder.autoAdd(false) method.
172 *
173 * @param <T> the aspect service type
174 * @param aspect the aspect service
175 * @param consumer the lambda that will use the AspectBuilder for building the DM aspect component.
176 * @return the DM component build by the consumer of the aspect builder
177 */
178 protected <T> Component aspect(Class<T> aspect, Consumer<ServiceAspectBuilder<T>> consumer) {
179 return aspect(m_manager, aspect, consumer);
180 }
181
182 /**
183 * Builds a DM Adapter Component using a Java8 style AdapterBuilder.
184 * The component is auto-added to the DependencyManager, unless the lambda calls the AdapterBuilder.autoAdd(false) method.
185 *
186 * @param <T> the adapted service type
187 * @param adaptee the adapted service
188 * @param consumer the lambda that will use the AdapterBuilder for building the DM adapter component.
189 * @return a newly built DM component.
190 */
191 protected <T> Component adapter(Class<T> adaptee, Consumer<ServiceAdapterBuilder<T>> consumer) {
192 return adapter(m_manager, adaptee, consumer);
193 }
194
195 /**
196 * Builds a DM Factory Configuration Adapter Component using a Java8 style FactoryPidAdapterBuilder.
197 * The component is auto-added to the DependencyManager, unless the lambda calls the FactoryPidAdapterBuilder.autoAdd(false) method.
198 *
199 * @param consumer the lambda that will use the FactoryPidAdapterBuilder for building the DM factory configuration adapter component.
200 * @return a newly built DM component.
201 */
202 protected Component factoryPidAdapter(Consumer<FactoryPidAdapterBuilder> consumer) {
203 return factoryPidAdapter(m_manager, consumer);
204 }
205
206 /**
207 * Builds a DM Bundle Adapter Component.
208 * @param consumer the lambda used to build the actual bundle adapter.
209 * The component is auto-added to the DependencyManager, unless the lambda calls the BundleAdapter.autoAdd(false) method.
210 * @return a newly built DM component.
211 */
212 protected Component bundleAdapter(Consumer<BundleAdapterBuilder> consumer) {
213 return bundleAdapter(m_manager, consumer);
214 }
215
216 // These static methods can be used when building DM components outside of an activator.
217
218 /**
219 * Creates a Component builder that can be used to create a Component.
220 *
221 * @param dm the DependencyManager object used to create the component builder
222 * @return a Component builder that can be used to create a Component.
223 */
224 public static ComponentBuilder<?> component(DependencyManager dm) {
225 return new ComponentBuilderImpl(dm);
226 }
227
228 /**
229 * Creates a service Aspect builder that can be used to create an Aspect Component.
230 *
231 * @param <T> the aspect service type
232 * @param dm the DependencyManager object used to register the built component
233 * @param aspect the type of the aspect service
234 * @return a service Aspect builder that can be used to create an Aspect Component.
235 */
236 public static <T> ServiceAspectBuilder<T> aspect(DependencyManager dm, Class<T> aspect) {
237 ServiceAspectBuilderImpl<T> aspectBuilder = new ServiceAspectBuilderImpl<>(dm, aspect);
238 return aspectBuilder;
239 }
240
241 /**
242 * Creates a service Adapter builder that can be used to create an Adapter Component.
243 *
244 * @param <T> the adapted service type
245 * @param dm the DependencyManager object used to register the built component
246 * @param adaptee the type of the adaptee service
247 * @return a service Adapter builder that can be used to create an Adapter Component.
248 */
249 public static <T> ServiceAdapterBuilder<T> adapter(DependencyManager dm, Class<T> adaptee) {
250 ServiceAdapterBuilderImpl<T> adapterBuilder = new ServiceAdapterBuilderImpl<>(dm, adaptee);
251 return adapterBuilder;
252 }
253
254 /**
255 * Creates a factory pid adapter that can be used to create a factory adapter Component.
256 * @param dm the DependencyManager object used to register the built component
257 * @return a factory pid adapter that can be used to create a factory adapter Component.
258 */
259 public static FactoryPidAdapterBuilder factoryPidAdapter(DependencyManager dm) {
260 return new FactoryPidAdapterBuilderImpl(dm);
261 }
262
263 /**
264 * Creates a bundle adapter builder that can be used to create a DM bundle adapter Component.
265 *
266 * @param dm the DependencyManager object used to create the bundle adapter builder.
267 * @return a bundle adapter builder that can be used to create a DM bundle adapter Component.
268 */
269 public static BundleAdapterBuilder bundleAdapter(DependencyManager dm) {
270 return new BundleAdapterBuilderImpl(dm);
271 }
272
273 /**
274 * Creates a DM ServiceDependency builder.
275 *
276 * @param <T> the service dependency type
277 * @param component the component on which you want to build a new service dependency using the returned builder
278 * @param service the service dependency type.
279 * @return a DM ServiceDependency builder.
280 */
281 public static <T> ServiceDependencyBuilder<T> serviceDependency(Component component, Class<T> service) {
282 return new ServiceDependencyBuilderImpl<>(component, service);
283 }
284
285 /**
286 * Creates a DM Configuration Dependency builder.
287 *
288 * @param component the component on which you want to build a new configuration dependency using the returned builder
289 * @return a DM Configuration Dependency builder.
290 */
291 public static ConfigurationDependencyBuilder confDependency(Component component) {
292 return new ConfigurationDependencyBuilderImpl(component);
293 }
294
295 /**
296 * Creates a DM Bundle Dependency builder.
297 *
298 * @param component the component on which you want to build a new bundle dependency using the returned builder
299 * @return a DM Configuration Dependency builder.
300 */
301 public static BundleDependencyBuilder bundleDependency(Component component) {
302 return new BundleDependencyBuilderImpl(component);
303 }
304
305 /**
306 * Creates a DM CompletableFuture Dependency builder.
307 *
308 * @param <F> the type of the CompletableFuture result.
309 * @param component the component on which you want to build a new completable future dependency using the returned builder.
310 * @param future the future the dependency built using the returned builder will depend on.
311 * @return a CompletableFuture dependency builder.
312 */
313 public static <F> FutureDependencyBuilder<F> futureDependency(Component component, CompletableFuture<F> future) {
314 return new CompletableFutureDependencyImpl<>(component, future);
315 }
316
317 /**
318 * Builds a component using a lambda and a component builder
319 * @param dm the DependencyManager where the component is auto-added (unless the component.autoAdd(false) is called)
320 * @param consumer a lambda that is called to build the component. When the lambda is called, it will be provided with a
321 * ComponentBuilder object that is used to build the actual DM component.
322 *
323 * @return the built DM component.
324 */
325 public static Component component(DependencyManager dm, Consumer<ComponentBuilder<?>> consumer) {
326 ComponentBuilder<?> componentBuilder = new ComponentBuilderImpl(dm);
327 consumer.accept(componentBuilder);
328 Component comp = componentBuilder.build();
329 if (((ComponentBuilderImpl) componentBuilder).isAutoAdd()) {
330 dm.add(comp);
331 }
332 return comp;
333 }
334
335 /**
336 * Update an existing component. Typically, this method can be used from a Component.init method, where more dependencies has to be added.
337 * @param comp an existing DM component
338 * @param consumer the lambda that will be used to update the component
339 */
340 public static void component(Component comp, Consumer<ComponentBuilder<?>> consumer) {
341 ComponentBuilder<?> componentBuilder = new ComponentBuilderImpl(comp, true /* update component */);
342 consumer.accept(componentBuilder);
343 componentBuilder.build();
344 }
345
346 /**
347 * Builds an aspect DM Component.
348 *
349 * @param <T> the aspect service type
350 * @param dm the DependencyManager object used to register the built component
351 * @param aspect the type of the aspect service
352 * @param consumer a lambda used to build the DM aspect component
353 * @return a new DM aspect component. The aspect component is auto-added into the dm object, unless the lambda calls
354 * the AspectBuilder.autoAdd(false) method.
355 */
356 public static <T> Component aspect(DependencyManager dm, Class<T> aspect, Consumer<ServiceAspectBuilder<T>> consumer) {
357 ServiceAspectBuilderImpl<T> aspectBuilder = new ServiceAspectBuilderImpl<>(dm, aspect);
358 consumer.accept(aspectBuilder);
359 Component comp = aspectBuilder.build();
360 if (aspectBuilder.isAutoAdd()) {
361 dm.add(comp);
362 }
363 return comp;
364 }
365
366 /**
367 * Builds an adapter DM Component.
368 *
369 * @param <T> the adapted service type
370 * @param dm the DependencyManager object used to register the built component
371 * @param adaptee the type of the adapted service
372 * @param consumer a lambda used to build the DM adapter component
373 * @return a new DM adapter component. The adapter component is auto-added into the dm object, unless the lambda calls
374 * the AspectBuilder.autoAdd(false) method is called.
375 */
376 public static <T> Component adapter(DependencyManager dm, Class<T> adaptee, Consumer<ServiceAdapterBuilder<T>> consumer) {
377 ServiceAdapterBuilderImpl<T> adapterBuilder = new ServiceAdapterBuilderImpl<>(dm, adaptee);
378 consumer.accept(adapterBuilder);
379 Component comp = adapterBuilder.build();
380 if (adapterBuilder.isAutoAdd()) {
381 dm.add(comp);
382 }
383 return comp;
384 }
385
386 /**
387 * Builds a bundle adapter DM Component.
388 *
389 * @param dm the DependencyManager object used to register the built component
390 * @param consumer a lambda used to build the bundle adapter component
391 * @return a new bundle adapter component. The adapter component is auto-added into the dm object, unless the lambda calls
392 * the AspectBuilder.autoAdd(false) method is called.
393 */
394 public static Component bundleAdapter(DependencyManager dm, Consumer<BundleAdapterBuilder> consumer) {
395 BundleAdapterBuilderImpl adapterBuilder = new BundleAdapterBuilderImpl(dm);
396 consumer.accept(adapterBuilder);
397 Component comp = adapterBuilder.build();
398 if (adapterBuilder.isAutoAdd()) {
399 dm.add(comp);
400 }
401 return comp;
402 }
403
404 /**
405 * Builds a DM factory configuration adapter.
406 * @param dm the DependencyManager object used to create DM components.
407 * @param consumer a lambda used to build the DM factory configuration adapter component
408 * @return a new DM factory configuration adapter component. The adapter component is auto-added into the dm object, unless the lambda calls
409 * the FactoryPidAdapterBuilder.autoAdd(false) method is called
410 */
411 public static Component factoryPidAdapter(DependencyManager dm, Consumer<FactoryPidAdapterBuilder> consumer) {
412 FactoryPidAdapterBuilderImpl factoryPidAdapter = new FactoryPidAdapterBuilderImpl(dm);
413 consumer.accept(factoryPidAdapter);
414 Component comp = factoryPidAdapter.build();
415 if (factoryPidAdapter.isAutoAdd()) {
416 dm.add(comp);
417 }
418 return comp;
419 }
420}