blob: c5d7e4642f4082444367c40c74ba05127d7d6071 [file] [log] [blame]
/**
* 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 && type != 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;
}
}