| /** |
| * Copyright (c) 2012, 2015 - Lunifera GmbH (Austria), Loetz GmbH&Co.KG and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Florian Pirchner - initial API and implementation |
| */ |
| package org.eclipse.osbp.ecview.core.common.context; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.eclipse.osbp.ecview.core.common.beans.IBeanRegistry; |
| import org.eclipse.osbp.ecview.core.common.beans.ISlot; |
| import org.eclipse.osbp.ecview.core.common.beans.ObjectBean; |
| import org.eclipse.osbp.ecview.core.common.services.DelegatingServiceProviderManager; |
| import org.eclipse.osbp.ecview.core.common.services.IServiceRegistry; |
| import org.eclipse.osbp.runtime.common.dispose.AbstractDisposable; |
| import org.eclipse.osbp.runtime.common.event.IEventBroker; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.FrameworkUtil; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.event.Event; |
| import org.osgi.service.event.EventHandler; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| // TODO: Auto-generated Javadoc |
| /** |
| * Base implementation for a disposable context. |
| */ |
| public abstract class DisposableContext extends AbstractDisposable implements |
| IBeanRegistry, IServiceRegistry, IContext { |
| |
| /** The Constant logger. */ |
| private static final Logger logger = LoggerFactory |
| .getLogger(DisposableContext.class); |
| |
| /** The value beans. */ |
| private Map<String, ISlot> valueBeans = Collections |
| .synchronizedMap(new HashMap<String, ISlot>()); |
| |
| /** The services. */ |
| private Map<String, Object> services = Collections |
| .synchronizedMap(new HashMap<String, Object>()); |
| |
| /** The final dispose. */ |
| // preparations for final disposal after view has been disposed |
| private Map<String, Object> finalDispose = new HashMap<String, Object>(); |
| |
| /** The locale. */ |
| private Locale locale = Locale.getDefault(); |
| |
| /** The event handlers. */ |
| private List<EventHandler> eventHandlers = new ArrayList<EventHandler>(); |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.ecview.core.common.context.IContext#setLocale(java.util.Locale) |
| */ |
| @Override |
| public void setLocale(Locale locale) { |
| Locale oldLocale = this.locale; |
| this.locale = locale; |
| |
| if (oldLocale != this.locale) { |
| updateLocale(this.locale); |
| } |
| } |
| |
| /** |
| * The locale changed and needs to become updated. |
| * |
| * @param locale |
| * the locale |
| */ |
| protected abstract void updateLocale(Locale locale); |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.ecview.core.common.context.IContext#getLocale() |
| */ |
| @Override |
| public Locale getLocale() { |
| return locale != null ? locale : Locale.getDefault(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Object getBean(String selector) { |
| checkDisposed(); |
| |
| ISlot slot = getBeanSlot(selector); |
| return slot != null ? slot.getValue() : null; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void setBean(String selector, Object bean) { |
| checkDisposed(); |
| |
| ISlot slot = getBeanSlot(selector); |
| if (slot == null && bean == null) { |
| throw new IllegalArgumentException( |
| "Can not create a slot for bean that is null!"); |
| } |
| |
| if (slot == null) { |
| slot = createBeanSlot(selector, bean.getClass()); |
| } else { |
| if (bean != null |
| && !slot.getValueType().isAssignableFrom(bean.getClass())) { |
| throw new IllegalArgumentException(String.format( |
| "%s is not a valid class for slot with type %s", bean |
| .getClass().getName(), slot.getValueType() |
| .getName())); |
| } |
| } |
| |
| valueBeans.get(selector).setValue(bean); |
| logger.debug("Bean registered: {}", selector); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.ecview.core.common.beans.IBeanRegistry#getBeanSlot(java.lang.String) |
| */ |
| @Override |
| public ISlot getBeanSlot(String selector) { |
| checkDisposed(); |
| ISlot slot = valueBeans.get(selector); |
| return slot; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.ecview.core.common.beans.IBeanRegistry#createBeanSlot(java.lang.String, java.lang.Class) |
| */ |
| @Override |
| public ISlot createBeanSlot(String selector, Class<?> type) { |
| ISlot slot = getBeanSlot(selector); |
| if (slot == null) { |
| slot = new ObjectBean(type); |
| valueBeans.put(selector, slot); |
| } |
| return slot; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.ecview.core.common.beans.IBeanRegistry#createBeanSlot(java.lang.String, java.lang.Class, java.lang.String) |
| */ |
| @Override |
| public ISlot createBeanSlot(String selector, Class<?> type, |
| String eventTopic) { |
| final ISlot slot = createBeanSlot(selector, type); |
| if (eventTopic != null && !eventTopic.equals("")) { |
| IEventBroker eventBroker = getService(IEventBroker.class.getName()); |
| if (eventBroker != null) { |
| EventHandler handler = new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| slot.setValue(event.getProperty(IEventBroker.DATA)); |
| } |
| }; |
| eventHandlers.add(handler); |
| eventBroker.subscribe(eventTopic, handler); |
| } else { |
| logger.error("EventBroker service not available!"); |
| } |
| } |
| return slot; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.ecview.core.common.services.IServiceRegistry#registerService(java.lang.String, java.lang.Object) |
| */ |
| public void registerService(String selector, Object service) { |
| checkDisposed(); |
| synchronized (services) { |
| logger.debug("Service registered: {}", selector); |
| services.put(selector, service); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.ecview.core.common.services.IServiceRegistry#unregisterService(java.lang.String) |
| */ |
| public void unregisterService(String selector) { |
| checkDisposed(); |
| synchronized (services) { |
| logger.debug("Service unregistered: {}", selector); |
| services.remove(selector); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.ecview.core.common.services.IServiceRegistry#getService(java.lang.String) |
| */ |
| @SuppressWarnings("unchecked") |
| @Override |
| public <S> S getService(String selector) { |
| checkDisposed(); |
| |
| synchronized (services) { |
| if (!services.containsKey(selector)) { |
| S service = DelegatingServiceProviderManager.getInstance() |
| .createService(selector, this); |
| if (service != null) { |
| registerService(selector, service); |
| } |
| } |
| } |
| |
| // now try to access the view set |
| S service = (S) services.get(selector); |
| |
| // use the strategy of the subclass to find the service |
| if (service == null) { |
| service = delegateGetService(selector); |
| } |
| |
| // access the OSGi service registry to find the service |
| if (service == null) { |
| BundleContext bundleContext = FrameworkUtil.getBundle(getClass()) |
| .getBundleContext(); |
| ServiceReference<?> serviceRef = bundleContext |
| .getServiceReference(selector); |
| if (serviceRef != null) { |
| service = (S) bundleContext.getService(serviceRef); |
| } |
| } |
| |
| if (service == null) { |
| logger.warn("No proper serviceProvider found for element {}", |
| selector); |
| } |
| |
| return service; |
| } |
| |
| /** |
| * If no service was found in the current context, sub classes may specify a |
| * different strategy to find it. |
| * |
| * @param <S> |
| * the generic type |
| * @param selector |
| * the selector |
| * @return the s |
| */ |
| protected <S> S delegateGetService(String selector) { |
| return null; |
| } |
| |
| /** |
| * Allows the context to prepare its disposal. In a first state, the view |
| * will be disposed and afterwards the context needs to do some clean up. To |
| * avoid disposed exceptions, the context may prepare required services,... |
| */ |
| protected void preDispose() { |
| if (eventHandlers != null) { |
| finalDispose.put(IEventBroker.class.getName(), |
| getService(IEventBroker.class.getName())); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.runtime.common.dispose.AbstractDisposable#internalDispose() |
| */ |
| @Override |
| protected void internalDispose() { |
| // Remove all event handler from the event service |
| IEventBroker eventBroker = (IEventBroker) finalDispose |
| .get(IEventBroker.class.getName()); |
| for (EventHandler eventHandler : eventHandlers) { |
| eventBroker.unsubscribe(eventHandler); |
| } |
| |
| eventHandlers = null; |
| valueBeans = null; |
| services = null; |
| finalDispose = null; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.ecview.core.common.beans.IBeanRegistry#getValueBeans() |
| */ |
| @Override |
| public Map<String, ISlot> getValueBeans() { |
| return valueBeans; |
| } |
| |
| } |