| package org.apache.felix.dm.lambda; |
| |
| import java.util.concurrent.CompletableFuture; |
| import java.util.function.Consumer; |
| |
| import org.apache.felix.dm.Component; |
| import org.apache.felix.dm.DependencyManager; |
| import org.apache.felix.dm.lambda.impl.BundleAdapterBuilderImpl; |
| import org.apache.felix.dm.lambda.impl.BundleDependencyBuilderImpl; |
| import org.apache.felix.dm.lambda.impl.CompletableFutureDependencyImpl; |
| import org.apache.felix.dm.lambda.impl.ComponentBuilderImpl; |
| import org.apache.felix.dm.lambda.impl.ConfigurationDependencyBuilderImpl; |
| import org.apache.felix.dm.lambda.impl.FactoryPidAdapterBuilderImpl; |
| import org.apache.felix.dm.lambda.impl.ServiceAdapterBuilderImpl; |
| import org.apache.felix.dm.lambda.impl.ServiceAspectBuilderImpl; |
| import org.apache.felix.dm.lambda.impl.ServiceDependencyBuilderImpl; |
| import org.osgi.framework.BundleActivator; |
| import org.osgi.framework.BundleContext; |
| |
| /** |
| * Defines a base for Activators in order to build DependencyManager Components using a java8 style.<p> |
| * |
| * Code example using auto configured fields: |
| * |
| * <pre> {@code |
| * |
| * import org.apache.felix.dm.lambda.DependencyManagerActivator; |
| * |
| * public class Activator extends DependencyManagerActivator { |
| * public void init(BundleContext ctx, DependencyManager dm) throws Exception { |
| * component(comp -> comp |
| * .provides(Service.class, property -> "value") |
| * .impl(ServiceImpl.class) |
| * .withSvc(LogService.class, ConfigurationAdmni.class) // both services are required and injected in class fields with compatible types. |
| * } |
| * } |
| * }</pre> |
| * |
| * Code example using reflection callbacks: |
| * |
| * <pre> {@code |
| * import org.apache.felix.dm.lambda.DependencyManagerActivator; |
| * |
| * public class Activator extends DependencyManagerActivator { |
| * public void init(BundleContext ctx, DependencyManager dm) throws Exception { |
| * component(comp -> comp |
| * .provides(Service.class, property -> "value") |
| * .impl(ServiceImpl.class) |
| * .withSvc(LogService.class, svc -> svc.add("setLog")) |
| * .withSvc(ConfigurationAdmni.class, svc -> svc.add("setConfigAdmin"))) |
| * } |
| * } |
| * }</pre> |
| * |
| * Code example using method references: |
| * |
| * <pre> {@code |
| * import org.apache.felix.dm.lambda.DependencyManagerActivator; |
| * |
| * public class Activator extends DependencyManagerActivator { |
| * public void init(BundleContext ctx, DependencyManager dm) throws Exception { |
| * component(comp -> comp |
| * .provides(Service.class, property -> "value") |
| * .impl(ServiceImpl.class) |
| * .withSvc(LogService.class, svc -> svc.add(ServiceImpl::setLog)) |
| * .withSvc(ConfigurationAdmni.class, svc -> svc.add(ServiceImpl::setConfigAdmin))) |
| * } |
| * } |
| * }</pre> |
| */ |
| public abstract class DependencyManagerActivator implements BundleActivator { |
| /** |
| * DependencyManager object used to create/register real DM Components that are built by this activator. |
| */ |
| private DependencyManager m_manager; |
| |
| /** |
| * Our Activator is starting. |
| */ |
| @Override |
| public void start(BundleContext context) throws Exception { |
| m_manager = new DependencyManager(context); |
| init(context, m_manager); |
| } |
| |
| /** |
| * Our Activator is stopped. |
| */ |
| @Override |
| public void stop(BundleContext context) throws Exception { |
| destroy(); |
| } |
| |
| /** |
| * Sub classes must override this method in order to build some DM components. |
| * @param ctx the context associated to the bundle |
| * @param dm the DependencyManager assocaited to this activator |
| * @throws Exception if the activation fails |
| */ |
| protected abstract void init(BundleContext ctx, DependencyManager dm) throws Exception; |
| |
| /** |
| * Sub classes may override this method that is called when the Activator is stopped. |
| * @throws Exception if the deactivation fails |
| */ |
| protected void destroy() throws Exception { |
| } |
| |
| /** |
| * Returns the DependencyManager used to create/managed DM Components. |
| * |
| * @return the DependencyManager associated to this Activator |
| */ |
| public DependencyManager getDM() { |
| return m_manager; |
| } |
| |
| /** |
| * Returns the bundle context that is associated with this bundle. |
| * |
| * @return the bundle context |
| */ |
| public BundleContext getBC() { |
| return m_manager.getBundleContext(); |
| } |
| |
| /** |
| * Creates a Component builder that can be used to create a DM Component. |
| * @return a Component builder that can be used to create a DM Component. |
| */ |
| protected ComponentBuilder<?> component() { |
| return new ComponentBuilderImpl(m_manager); |
| } |
| |
| /** |
| * Creates a service Aspect builder that can be used to create a DM Aspect Component. |
| * |
| * @param <T> the aspect service type |
| * @param aspectType the aspect service |
| * @return a service Aspect builder. |
| */ |
| protected <T> ServiceAspectBuilder<T> aspect(Class<T> aspectType) { |
| ServiceAspectBuilderImpl<T> aspectBuilder = new ServiceAspectBuilderImpl<>(m_manager, aspectType); |
| return aspectBuilder; |
| } |
| |
| /** |
| * Creates a service Adapter builder that can be used to create a DM Adapter Component. |
| * |
| * @param <T> the adapted service type. |
| * @param adaptee the adapted service |
| * @return a service Adapter builder. |
| */ |
| protected <T> ServiceAdapterBuilder<T> adapter(Class<T> adaptee) { |
| ServiceAdapterBuilderImpl<T> adapterBuilder = new ServiceAdapterBuilderImpl<>(m_manager, adaptee); |
| return adapterBuilder; |
| } |
| |
| /** |
| * Builds a DM Component using a Java8 style ComponentBuilder. |
| * @param consumer the lambda that will use the ComponentBuilder for building the DM component. |
| * The component is auto-added to the DependencyManager, unless the lambda calls the ComponentBuilder.autoAdd(false) method. |
| * @return a newly built DM component. |
| */ |
| protected Component component(Consumer<ComponentBuilder<?>> consumer) { |
| return component(m_manager, consumer); |
| } |
| |
| /** |
| * Builds a DM Aspect Component using a Java8 style AspectBuilder. |
| * The component is auto-added to the DependencyManager, unless the lambda calls the AspectBuilder.autoAdd(false) method. |
| * |
| * @param <T> the aspect service type |
| * @param aspect the aspect service |
| * @param consumer the lambda that will use the AspectBuilder for building the DM aspect component. |
| * @return the DM component build by the consumer of the aspect builder |
| */ |
| protected <T> Component aspect(Class<T> aspect, Consumer<ServiceAspectBuilder<T>> consumer) { |
| return aspect(m_manager, aspect, consumer); |
| } |
| |
| /** |
| * Builds a DM Adapter Component using a Java8 style AdapterBuilder. |
| * The component is auto-added to the DependencyManager, unless the lambda calls the AdapterBuilder.autoAdd(false) method. |
| * |
| * @param <T> the adapted service type |
| * @param adaptee the adapted service |
| * @param consumer the lambda that will use the AdapterBuilder for building the DM adapter component. |
| * @return a newly built DM component. |
| */ |
| protected <T> Component adapter(Class<T> adaptee, Consumer<ServiceAdapterBuilder<T>> consumer) { |
| return adapter(m_manager, adaptee, consumer); |
| } |
| |
| /** |
| * Builds a DM Factory Configuration Adapter Component using a Java8 style FactoryPidAdapterBuilder. |
| * The component is auto-added to the DependencyManager, unless the lambda calls the FactoryPidAdapterBuilder.autoAdd(false) method. |
| * |
| * @param consumer the lambda that will use the FactoryPidAdapterBuilder for building the DM factory configuration adapter component. |
| * @return a newly built DM component. |
| */ |
| protected Component factoryPidAdapter(Consumer<FactoryPidAdapterBuilder> consumer) { |
| return factoryPidAdapter(m_manager, consumer); |
| } |
| |
| /** |
| * Builds a DM Bundle Adapter Component. |
| * @param consumer the lambda used to build the actual bundle adapter. |
| * The component is auto-added to the DependencyManager, unless the lambda calls the BundleAdapter.autoAdd(false) method. |
| * @return a newly built DM component. |
| */ |
| protected Component bundleAdapter(Consumer<BundleAdapterBuilder> consumer) { |
| return bundleAdapter(m_manager, consumer); |
| } |
| |
| // These static methods can be used when building DM components outside of an activator. |
| |
| /** |
| * Creates a Component builder that can be used to create a Component. |
| * |
| * @param dm the DependencyManager object used to create the component builder |
| * @return a Component builder that can be used to create a Component. |
| */ |
| public static ComponentBuilder<?> component(DependencyManager dm) { |
| return new ComponentBuilderImpl(dm); |
| } |
| |
| /** |
| * Creates a service Aspect builder that can be used to create an Aspect Component. |
| * |
| * @param <T> the aspect service type |
| * @param dm the DependencyManager object used to register the built component |
| * @param aspect the type of the aspect service |
| * @return a service Aspect builder that can be used to create an Aspect Component. |
| */ |
| public static <T> ServiceAspectBuilder<T> aspect(DependencyManager dm, Class<T> aspect) { |
| ServiceAspectBuilderImpl<T> aspectBuilder = new ServiceAspectBuilderImpl<>(dm, aspect); |
| return aspectBuilder; |
| } |
| |
| /** |
| * Creates a service Adapter builder that can be used to create an Adapter Component. |
| * |
| * @param <T> the adapted service type |
| * @param dm the DependencyManager object used to register the built component |
| * @param adaptee the type of the adaptee service |
| * @return a service Adapter builder that can be used to create an Adapter Component. |
| */ |
| public static <T> ServiceAdapterBuilder<T> adapter(DependencyManager dm, Class<T> adaptee) { |
| ServiceAdapterBuilderImpl<T> adapterBuilder = new ServiceAdapterBuilderImpl<>(dm, adaptee); |
| return adapterBuilder; |
| } |
| |
| /** |
| * Creates a factory pid adapter that can be used to create a factory adapter Component. |
| * @param dm the DependencyManager object used to register the built component |
| * @return a factory pid adapter that can be used to create a factory adapter Component. |
| */ |
| public static FactoryPidAdapterBuilder factoryPidAdapter(DependencyManager dm) { |
| return new FactoryPidAdapterBuilderImpl(dm); |
| } |
| |
| /** |
| * Creates a bundle adapter builder that can be used to create a DM bundle adapter Component. |
| * |
| * @param dm the DependencyManager object used to create the bundle adapter builder. |
| * @return a bundle adapter builder that can be used to create a DM bundle adapter Component. |
| */ |
| public static BundleAdapterBuilder bundleAdapter(DependencyManager dm) { |
| return new BundleAdapterBuilderImpl(dm); |
| } |
| |
| /** |
| * Creates a DM ServiceDependency builder. |
| * |
| * @param <T> the service dependency type |
| * @param component the component on which you want to build a new service dependency using the returned builder |
| * @param service the service dependency type. |
| * @return a DM ServiceDependency builder. |
| */ |
| public static <T> ServiceDependencyBuilder<T> serviceDependency(Component component, Class<T> service) { |
| return new ServiceDependencyBuilderImpl<>(component, service); |
| } |
| |
| /** |
| * Creates a DM Configuration Dependency builder. |
| * |
| * @param component the component on which you want to build a new configuration dependency using the returned builder |
| * @return a DM Configuration Dependency builder. |
| */ |
| public static ConfigurationDependencyBuilder confDependency(Component component) { |
| return new ConfigurationDependencyBuilderImpl(component); |
| } |
| |
| /** |
| * Creates a DM Bundle Dependency builder. |
| * |
| * @param component the component on which you want to build a new bundle dependency using the returned builder |
| * @return a DM Configuration Dependency builder. |
| */ |
| public static BundleDependencyBuilder bundleDependency(Component component) { |
| return new BundleDependencyBuilderImpl(component); |
| } |
| |
| /** |
| * Creates a DM CompletableFuture Dependency builder. |
| * |
| * @param <F> the type of the CompletableFuture result. |
| * @param component the component on which you want to build a new completable future dependency using the returned builder. |
| * @param future the future the dependency built using the returned builder will depend on. |
| * @return a CompletableFuture dependency builder. |
| */ |
| public static <F> FutureDependencyBuilder<F> futureDependency(Component component, CompletableFuture<F> future) { |
| return new CompletableFutureDependencyImpl<>(component, future); |
| } |
| |
| /** |
| * Builds a component using a lambda and a component builder |
| * @param dm the DependencyManager where the component is auto-added (unless the component.autoAdd(false) is called) |
| * @param consumer a lambda that is called to build the component. When the lambda is called, it will be provided with a |
| * ComponentBuilder object that is used to build the actual DM component. |
| * |
| * @return the built DM component. |
| */ |
| public static Component component(DependencyManager dm, Consumer<ComponentBuilder<?>> consumer) { |
| ComponentBuilder<?> componentBuilder = new ComponentBuilderImpl(dm); |
| consumer.accept(componentBuilder); |
| Component comp = componentBuilder.build(); |
| if (((ComponentBuilderImpl) componentBuilder).isAutoAdd()) { |
| dm.add(comp); |
| } |
| return comp; |
| } |
| |
| /** |
| * Update an existing component. Typically, this method can be used from a Component.init method, where more dependencies has to be added. |
| * @param comp an existing DM component |
| * @param consumer the lambda that will be used to update the component |
| */ |
| public static void component(Component comp, Consumer<ComponentBuilder<?>> consumer) { |
| ComponentBuilder<?> componentBuilder = new ComponentBuilderImpl(comp, true /* update component */); |
| consumer.accept(componentBuilder); |
| componentBuilder.build(); |
| } |
| |
| /** |
| * Builds an aspect DM Component. |
| * |
| * @param <T> the aspect service type |
| * @param dm the DependencyManager object used to register the built component |
| * @param aspect the type of the aspect service |
| * @param consumer a lambda used to build the DM aspect component |
| * @return a new DM aspect component. The aspect component is auto-added into the dm object, unless the lambda calls |
| * the AspectBuilder.autoAdd(false) method. |
| */ |
| public static <T> Component aspect(DependencyManager dm, Class<T> aspect, Consumer<ServiceAspectBuilder<T>> consumer) { |
| ServiceAspectBuilderImpl<T> aspectBuilder = new ServiceAspectBuilderImpl<>(dm, aspect); |
| consumer.accept(aspectBuilder); |
| Component comp = aspectBuilder.build(); |
| if (aspectBuilder.isAutoAdd()) { |
| dm.add(comp); |
| } |
| return comp; |
| } |
| |
| /** |
| * Builds an adapter DM Component. |
| * |
| * @param <T> the adapted service type |
| * @param dm the DependencyManager object used to register the built component |
| * @param adaptee the type of the adapted service |
| * @param consumer a lambda used to build the DM adapter component |
| * @return a new DM adapter component. The adapter component is auto-added into the dm object, unless the lambda calls |
| * the AspectBuilder.autoAdd(false) method is called. |
| */ |
| public static <T> Component adapter(DependencyManager dm, Class<T> adaptee, Consumer<ServiceAdapterBuilder<T>> consumer) { |
| ServiceAdapterBuilderImpl<T> adapterBuilder = new ServiceAdapterBuilderImpl<>(dm, adaptee); |
| consumer.accept(adapterBuilder); |
| Component comp = adapterBuilder.build(); |
| if (adapterBuilder.isAutoAdd()) { |
| dm.add(comp); |
| } |
| return comp; |
| } |
| |
| /** |
| * Builds a bundle adapter DM Component. |
| * |
| * @param dm the DependencyManager object used to register the built component |
| * @param consumer a lambda used to build the bundle adapter component |
| * @return a new bundle adapter component. The adapter component is auto-added into the dm object, unless the lambda calls |
| * the AspectBuilder.autoAdd(false) method is called. |
| */ |
| public static Component bundleAdapter(DependencyManager dm, Consumer<BundleAdapterBuilder> consumer) { |
| BundleAdapterBuilderImpl adapterBuilder = new BundleAdapterBuilderImpl(dm); |
| consumer.accept(adapterBuilder); |
| Component comp = adapterBuilder.build(); |
| if (adapterBuilder.isAutoAdd()) { |
| dm.add(comp); |
| } |
| return comp; |
| } |
| |
| /** |
| * Builds a DM factory configuration adapter. |
| * @param dm the DependencyManager object used to create DM components. |
| * @param consumer a lambda used to build the DM factory configuration adapter component |
| * @return a new DM factory configuration adapter component. The adapter component is auto-added into the dm object, unless the lambda calls |
| * the FactoryPidAdapterBuilder.autoAdd(false) method is called |
| */ |
| public static Component factoryPidAdapter(DependencyManager dm, Consumer<FactoryPidAdapterBuilder> consumer) { |
| FactoryPidAdapterBuilderImpl factoryPidAdapter = new FactoryPidAdapterBuilderImpl(dm); |
| consumer.accept(factoryPidAdapter); |
| Component comp = factoryPidAdapter.build(); |
| if (factoryPidAdapter.isAutoAdd()) { |
| dm.add(comp); |
| } |
| return comp; |
| } |
| } |