Merge branch 'teichsta-storage-service'

This commit is contained in:
Kai Kreuzer 2014-05-20 21:30:25 +02:00
Родитель a0c5c0a832 36b1a77179
Коммит f292faab81
27 изменённых файлов: 693 добавлений и 54 удалений

Просмотреть файл

@ -210,7 +210,7 @@ public class ArithmeticGroupFunctionTest {
class TestItem extends GenericItem {
public TestItem(String name, State state) {
super(name);
super("Test", name);
setState(state);
}

Просмотреть файл

@ -24,24 +24,33 @@ import org.eclipse.smarthome.core.library.items.SwitchItem;
* {@link CoreItemFactory}-Implementation for the core ItemTypes
*
* @author Thomas.Eichstaedt-Engelen
* @author Kai Kreuzer
*/
public class CoreItemFactory implements ItemFactory {
private static String[] ITEM_TYPES = new String[] { "Switch", "Rollershutter", "Contact", "String", "Number", "Dimmer", "DateTime", "Color", "Image" };
public static final String SWITCH = "Switch";
public static final String ROLLERSHUTTER = "Rollershutter";
public static final String CONTACT = "Contact";
public static final String STRING = "String";
public static final String NUMBER = "Number";
public static final String DIMMER = "Dimmer";
public static final String DATETIME = "DateTime";
public static final String COLOR = "Color";
public static final String IMAGE = "Image";
/**
* @{inheritDoc}
*/
public GenericItem createItem(String itemTypeName, String itemName) {
if (itemTypeName.equals(ITEM_TYPES[0])) return new SwitchItem(itemName);
if (itemTypeName.equals(ITEM_TYPES[1])) return new RollershutterItem(itemName);
if (itemTypeName.equals(ITEM_TYPES[2])) return new ContactItem(itemName);
if (itemTypeName.equals(ITEM_TYPES[3])) return new StringItem(itemName);
if (itemTypeName.equals(ITEM_TYPES[4])) return new NumberItem(itemName);
if (itemTypeName.equals(ITEM_TYPES[5])) return new DimmerItem(itemName);
if (itemTypeName.equals(ITEM_TYPES[6])) return new DateTimeItem(itemName);
if (itemTypeName.equals(ITEM_TYPES[7])) return new ColorItem(itemName);
if (itemTypeName.equals(ITEM_TYPES[8])) return new ImageItem(itemName);
if (itemTypeName.equals(SWITCH)) return new SwitchItem(itemName);
if (itemTypeName.equals(ROLLERSHUTTER)) return new RollershutterItem(itemName);
if (itemTypeName.equals(CONTACT)) return new ContactItem(itemName);
if (itemTypeName.equals(STRING)) return new StringItem(itemName);
if (itemTypeName.equals(NUMBER)) return new NumberItem(itemName);
if (itemTypeName.equals(DIMMER)) return new DimmerItem(itemName);
if (itemTypeName.equals(DATETIME)) return new DateTimeItem(itemName);
if (itemTypeName.equals(COLOR)) return new ColorItem(itemName);
if (itemTypeName.equals(IMAGE)) return new ImageItem(itemName);
else return null;
}
@ -49,7 +58,9 @@ public class CoreItemFactory implements ItemFactory {
* @{inheritDoc}
*/
public String[] getSupportedItemTypes() {
return ITEM_TYPES;
return new String[] {
SWITCH, ROLLERSHUTTER, CONTACT, STRING, NUMBER, DIMMER, DATETIME, COLOR, IMAGE
};
}
}

Просмотреть файл

@ -12,6 +12,7 @@ import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.HSBType;
import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType;
@ -44,7 +45,7 @@ import org.eclipse.smarthome.core.types.UnDefType;
}
public ColorItem(String name) {
super(name);
super(CoreItemFactory.COLOR, name);
}
public void send(HSBType command) {

Просмотреть файл

@ -10,6 +10,7 @@ package org.eclipse.smarthome.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.OpenClosedType;
import org.eclipse.smarthome.core.library.types.PercentType;
@ -36,7 +37,7 @@ public class ContactItem extends GenericItem {
}
public ContactItem(String name) {
super(name);
super(CoreItemFactory.CONTACT, name);
}
public void send(OpenClosedType command) {

Просмотреть файл

@ -10,6 +10,7 @@ package org.eclipse.smarthome.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.DateTimeType;
import org.eclipse.smarthome.core.items.GenericItem;
import org.eclipse.smarthome.core.types.Command;
@ -34,7 +35,7 @@ public class DateTimeItem extends GenericItem {
}
public DateTimeItem(String name) {
super(name);
super(CoreItemFactory.DATETIME, name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {

Просмотреть файл

@ -12,6 +12,7 @@ import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType;
import org.eclipse.smarthome.core.library.types.OnOffType;
@ -43,7 +44,11 @@ public class DimmerItem extends SwitchItem {
}
public DimmerItem(String name) {
super(name);
super(CoreItemFactory.DIMMER, name);
}
/* package */ DimmerItem(String type, String name) {
super(CoreItemFactory.DIMMER, name);
}
public void send(PercentType command) {

Просмотреть файл

@ -11,6 +11,7 @@ import java.util.ArrayList;
import java.util.List;
import org.eclipse.smarthome.core.items.GenericItem;
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.RawType;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.State;
@ -33,7 +34,7 @@ public class ImageItem extends GenericItem {
}
public ImageItem(String name) {
super(name);
super(CoreItemFactory.IMAGE, name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {

Просмотреть файл

@ -10,6 +10,7 @@ package org.eclipse.smarthome.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.items.GenericItem;
import org.eclipse.smarthome.core.types.Command;
@ -38,7 +39,7 @@ public class NumberItem extends GenericItem {
}
public NumberItem(String name) {
super(name);
super(CoreItemFactory.NUMBER, name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {

Просмотреть файл

@ -12,6 +12,7 @@ import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.PercentType;
import org.eclipse.smarthome.core.library.types.StopMoveType;
@ -44,7 +45,7 @@ public class RollershutterItem extends GenericItem {
}
public RollershutterItem(String name) {
super(name);
super(CoreItemFactory.ROLLERSHUTTER, name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {

Просмотреть файл

@ -10,6 +10,7 @@ package org.eclipse.smarthome.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.DateTimeType;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.items.GenericItem;
@ -39,7 +40,7 @@ public class StringItem extends GenericItem {
}
public StringItem(String name) {
super(name);
super(CoreItemFactory.STRING, name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {

Просмотреть файл

@ -10,6 +10,7 @@ package org.eclipse.smarthome.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.library.types.PercentType;
@ -38,7 +39,11 @@ public class SwitchItem extends GenericItem {
}
public SwitchItem(String name) {
super(name);
super(CoreItemFactory.SWITCH, name);
}
/* package */ SwitchItem(String type, String name) {
super(CoreItemFactory.SWITCH, name);
}
public void send(OnOffType command) {

Просмотреть файл

@ -0,0 +1,92 @@
/**
* Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.storage
import static org.hamcrest.CoreMatchers.*
import static org.junit.Assert.*
import static org.junit.matchers.JUnitMatchers.*
import org.eclipse.smarthome.core.items.ItemProvider
import org.eclipse.smarthome.core.library.items.StringItem
import org.eclipse.smarthome.core.library.items.SwitchItem
import org.eclipse.smarthome.test.OSGiTest
import org.junit.Before
import org.junit.After
import org.junit.Test
/**
* The {@link ManagedItemProviderOSGiTest} runs inside an
* OSGi container and tests the {@link ManagedItemProvider}.
*
* @author Thomas Eichstaedt-Engelen - Initial contribution
* @author Kai Kreuzer - added tests for repeated addition and removal
*/
class ManagedItemProviderOSGiTest extends OSGiTest {
ItemProvider itemProvider
@Before
void setUp() {
itemProvider = getService(ItemProvider)
}
@After
void tearUp() {
unregisterService(itemProvider)
}
@Test
void 'assert getItems returns item from registered ItemProvider'() {
assertThat itemProvider.getItems().size, is(0)
itemProvider.addItem new SwitchItem('SwitchItem')
itemProvider.addItem new StringItem('StringItem')
def items = itemProvider.getItems()
assertThat items.size, is(2)
itemProvider.removeItem 'StringItem'
itemProvider.removeItem 'SwitchItem'
assertThat itemProvider.getItems().size, is(0)
}
@Test
void 'assert adding twice returns first value'() {
assertThat itemProvider.getItems().size, is(0)
itemProvider.addItem new StringItem('Item')
def result = itemProvider.addItem new SwitchItem('Item')
assertThat result.type, is("String")
itemProvider.removeItem 'Item'
assertThat itemProvider.getItems().size, is(0)
}
@Test
void 'assert removal returns old value'() {
assertThat itemProvider.getItems().size, is(0)
itemProvider.addItem new StringItem('Item')
def result = itemProvider.removeItem 'Unknown'
assertNull result
result = itemProvider.removeItem 'Item'
assertThat result.name, is('Item')
assertThat itemProvider.getItems().size, is(0)
}
}

Просмотреть файл

@ -55,7 +55,7 @@ public class GroupItemTest {
class TestItem extends GenericItem {
public TestItem(String name) {
super(name);
super("Test", name);
}
@Override

Просмотреть файл

@ -4,7 +4,7 @@ Export-Package: org.eclipse.smarthome.core.binding,
org.eclipse.smarthome.core.items;uses:="org.eclipse.smarthome.core.types,org.eclipse.smarthome.core.events",
org.eclipse.smarthome.core.service,
org.eclipse.smarthome.core.types
Service-Component: OSGI-INF/eventpublisher.xml,OSGI-INF/itemregistry.xml,OSGI-INF/itemupdater.xml
Service-Component: OSGI-INF/*
Private-Package: org.eclipse.smarthome.core.internal,org.eclipse.smarthome.core.internal.e
vents,org.eclipse.smarthome.core.internal.items,org.eclipse.smarthome.core.internal.loggi
ng
@ -25,3 +25,4 @@ Import-Package: org.apache.commons.io,
org.osgi.service.log,
org.slf4j
Bundle-SymbolicName: org.eclipse.smarthome.core
Bundle-Activator: org.eclipse.smarthome.core.internal.CoreActivator

Просмотреть файл

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.eclipse.smarthome.core.manageditemprovider">
<implementation class="org.eclipse.smarthome.core.items.ManagedItemProvider"/>
<service>
<provide interface="org.eclipse.smarthome.core.items.ItemProvider"/>
</service>
<reference bind="addStorageService" cardinality="1..n"
interface="org.eclipse.smarthome.core.storage.StorageService" name="StorageService"
policy="dynamic" unbind="removeStorageService"/>
<reference bind="addItemFactory" cardinality="0..n"
interface="org.eclipse.smarthome.core.items.ItemFactory" name="ItemFactory"
policy="dynamic" unbind="removeItemFactory"/>
</scr:component>

Просмотреть файл

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.eclipse.smarthome.core.storage.volatilestorageservice">
<implementation class="org.eclipse.smarthome.core.internal.storage.VolatileStorageService"/>
<service>
<provide interface="org.eclipse.smarthome.core.storage.StorageService"/>
</service>
</scr:component>

Просмотреть файл

@ -0,0 +1,49 @@
/**
* Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.internal;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The activator class controls the plug-in life cycle
*/
public class CoreActivator implements BundleActivator {
private static Logger logger = LoggerFactory.getLogger(CoreActivator.class);
private static BundleContext context;
/**
* Called whenever the OSGi framework starts our bundle
*/
public void start(BundleContext bc) throws Exception {
context = bc;
logger.debug("Core bundle has been started.");
}
/**
* Called whenever the OSGi framework stops our bundle
*/
public void stop(BundleContext bc) throws Exception {
context = null;
logger.debug("Core bundle has been stopped.");
}
/**
* Returns the bundle context of this bundle
* @return the bundle context
*/
public static BundleContext getContext() {
return context;
}
}

Просмотреть файл

@ -0,0 +1,67 @@
/**
* Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.internal.storage;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.smarthome.core.storage.Storage;
/**
* A {@link Storage} implementation which stores it's data in-memory.
*
* @author Thomas.Eichstaedt-Engelen - Initial Contribution and API
* @author Kai Kreuzer - improved return values
*/
public class VolatileStorage<T> implements Storage<T> {
Map<String, T> storage = new ConcurrentHashMap<String, T>();
/**
* {@inheritDoc}
*/
@Override
public T put(String key, T value) {
return storage.put(key, value);
}
/**
* {@inheritDoc}
*/
@Override
public T remove(String key) {
return storage.remove(key);
}
/**
* {@inheritDoc}
*/
@Override
public T get(String key) {
return storage.get(key);
}
/**
* {@inheritDoc}
*/
@Override
public Collection<String> getKeys() {
return storage.keySet();
}
/**
* {@inheritDoc}
*/
@Override
public Collection<T> getValues() {
return storage.values();
}
}

Просмотреть файл

@ -0,0 +1,41 @@
/**
* Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.internal.storage;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.smarthome.core.storage.Storage;
import org.eclipse.smarthome.core.storage.StorageService;
/**
* The {@link VolatileStorageService} returns {@link VolatileStorage}s
* which stores their data in-memory.
*
* @author Thomas.Eichstaedt-Engelen - Initial Contribution and API
*/
public class VolatileStorageService implements StorageService {
@SuppressWarnings("rawtypes")
Map<String, Storage> storages = new ConcurrentHashMap<String, Storage>();
/**
* {@inheritDoc}
* @return
*/
@SuppressWarnings("unchecked")
public synchronized <T> Storage<T> getStorage(String name) {
if (!storages.containsKey(name)) {
storages.put(name, new VolatileStorage<T>());
}
return storages.get(name);
}
}

Просмотреть файл

@ -0,0 +1,61 @@
/**
* Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.items;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Abstract base class for {@link ItemProvider}s. In particular it handles
* the management and notification of {@link ItemsChangeListener}.
*
* @author Thomas.Eichstaedt-Engelen - Initial Contribution
*/
public abstract class AbstractItemProvider implements ItemProvider {
/** keeps track of all item change listeners */
protected Collection<ItemsChangeListener> itemsChangeListeners = new CopyOnWriteArrayList<ItemsChangeListener>();
/**
* {@inheritDoc}
*/
@Override
public void addItemChangeListener(ItemsChangeListener listener) {
itemsChangeListeners.add(listener);
}
/**
* {@inheritDoc}
*/
@Override
public void removeItemChangeListener(ItemsChangeListener listener) {
itemsChangeListeners.remove(listener);
}
protected void notifyItemChangeListenersAboutAddedItem(Item item) {
for (ItemsChangeListener itemsChangeListener : itemsChangeListeners) {
itemsChangeListener.itemAdded(this, item);
}
}
protected void notifyItemChangeListenersAboutRemovedItem(Item item) {
for (ItemsChangeListener itemsChangeListener : itemsChangeListeners) {
itemsChangeListener.itemRemoved(this, item);
}
}
protected void notifyItemChangeListenersAboutAllItemsChanged(Collection<String> oldItemNames) {
for (ItemsChangeListener itemsChangeListener : itemsChangeListeners) {
itemsChangeListener.allItemsChanged(this, oldItemNames);
}
}
}

Просмотреть файл

@ -37,10 +37,13 @@ abstract public class GenericItem implements Item {
final protected String name;
final protected String type;
protected State state = UnDefType.NULL;
public GenericItem(String name) {
public GenericItem(String type, String name) {
this.name = name;
this.type = type;
}
/**
@ -74,6 +77,13 @@ abstract public class GenericItem implements Item {
return name;
}
/**
* {@inheritDoc}
*/
public String getType() {
return type;
}
/**
* {@inheritDoc}
*/

Просмотреть файл

@ -38,7 +38,7 @@ public class GroupItem extends GenericItem implements StateChangeListener {
}
public GroupItem(String name, GenericItem baseItem, GroupFunction function) {
super(name);
super("Group", name);
members = new CopyOnWriteArrayList<Item>();
this.function = function;
this.baseItem = baseItem;

Просмотреть файл

@ -44,6 +44,13 @@ public interface Item {
*/
public String getName();
/**
* returns the item type as defined by {@link ItemFactory}s
*
* @return the item type
*/
public String getType();
/**
* <p>This method provides a list of all data types that can be used to update the item state</p>
* <p>Imagine e.g. a dimmer device: It's status could be 0%, 10%, 50%, 100%, but also OFF or ON and

Просмотреть файл

@ -0,0 +1,168 @@
package org.eclipse.smarthome.core.items;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.smarthome.core.internal.CoreActivator;
import org.eclipse.smarthome.core.storage.Storage;
import org.eclipse.smarthome.core.storage.StorageService;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link ManagedItemProvider} is an OSGi service, that allows to add or remove
* items at runtime by calling {@link ManagedItemProvider#addItem(Item)} or
* {@link ManagedItemProvider#removeItem(Item)}. An added item is automatically
* exposed to the {@link ItemRegistry}. Persistence of added Items is handled by
* a {@link StorageService}. Items are being restored using the given
* {@link ItemFactory}s.
*
* @author Dennis Nobel - Initial contribution
* @author Thomas Eichstaedt-Engelen
* @author Kai Kreuzer - improved return values
*/
public class ManagedItemProvider extends AbstractItemProvider {
private static final Logger logger =
LoggerFactory.getLogger(ManagedItemProvider.class);
private Collection<StorageService> storageServiceCandidates = new CopyOnWriteArrayList<StorageService>();
private Storage<String> itemStorage;
private Collection<ItemFactory> itemFactories = new CopyOnWriteArrayList<ItemFactory>();
public void addStorageService(StorageService storageService) {
storageServiceCandidates.add(storageService);
// small optimization - if there is just one StorageService available
// we don't have to select amongst others.
if (storageServiceCandidates.size() == 1) {
itemStorage = storageService.getStorage(Item.class.getName());
} else {
itemStorage = findStorageServiceByPriority();
}
}
public void removeStorageService(StorageService storageService) {
storageServiceCandidates.remove(storageService);
// if there are still StorageService left, we have to select
// a new one to take over ...
if (storageServiceCandidates.size() > 0) {
itemStorage = findStorageServiceByPriority();
} else {
itemStorage = null;
}
}
/**
* Returns a {@link Storage} returned by a {@link StorageService} with the
* highest priority available in the OSGi container. In theory this should
* not be necessary if DS would have taken the {@code service.ranking} property
* into account properly. Unfortunately it haven't during my tests. So this
* method should be seen as workaround until somebody proofs that DS evaluates
* the property correctly.
*
* @return a {@link Storage} created by the {@link StorageService} with the
* highest priority (according to the OSGi container)
*/
private Storage<String> findStorageServiceByPriority() {
ServiceReference<?> reference =
CoreActivator.getContext().getServiceReference(StorageService.class);
if (reference != null) {
StorageService service =
(StorageService) CoreActivator.getContext().getService(reference);
Storage<String> storage = service.getStorage(Item.class.getName());
return storage;
}
// no service of type StorageService available
throw new IllegalStateException(
"There is no Service of type 'StorageService' available. This should not happen!");
}
public void addItemFactory(ItemFactory itemFactory) {
itemFactories.add(itemFactory);
}
public void removeItemFactory(ItemFactory itemFactory) {
itemFactories.remove(itemFactory);
}
public Item addItem(Item item) {
if (item == null) {
throw new IllegalArgumentException("Cannot add null Item.");
}
String oldItemType = itemStorage.put(item.getName(), toItemFactoryName(item));
Item oldItem = null;
if(oldItemType!=null) {
oldItem = instantiateItem(oldItemType, item.getName());
notifyItemChangeListenersAboutRemovedItem(oldItem);
}
notifyItemChangeListenersAboutAddedItem(item);
return oldItem;
}
/**
* Translates the Items class simple name into a type name understandable by
* the {@link ItemFactory}s.
*
* @param item the Item to translate the name
* @return the translated ItemTypeName understandable by the
* {@link ItemFactory}s
*/
private String toItemFactoryName(Item item) {
return item.getType();
}
public Item removeItem(String itemName) {
if (itemName == null) {
throw new IllegalArgumentException("Cannot remove null Item");
}
String removedItemType = itemStorage.remove(itemName);
if (removedItemType!=null) {
Item removedItem = instantiateItem(removedItemType, itemName);
notifyItemChangeListenersAboutRemovedItem(removedItem);
return removedItem;
}
return null;
}
/**
* Returns all Items of this {@link ItemProvider} being restored from the
* underlying {@link StorageService} and instantiated using the appropriate
* {@link ItemFactory}s.
*
* {@inheritDoc}
*/
@Override
public Collection<Item> getItems() {
Collection<Item> storedItems = new ArrayList<Item>();
for (String itemName : itemStorage.getKeys()) {
String itemTypeName = itemStorage.get(itemName);
storedItems.add(instantiateItem(itemTypeName, itemName));
}
return storedItems;
}
private Item instantiateItem(String itemTypeName, String itemName) {
for (ItemFactory itemFactory : itemFactories) {
GenericItem item = itemFactory.createItem(itemTypeName, itemName);
if (item != null) {
return item;
}
}
logger.debug(
"Couldn't restore item '{}' of type '{}' ~ there is no appropriate ItemFactory available.",
itemName, itemTypeName);
return null;
}
}

Просмотреть файл

@ -0,0 +1,61 @@
/**
* Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.storage;
import java.util.Collection;
/**
* A Storage is the generic way to store key-value pairs in ESH. Each Storage
* implementation can store its data differently, e.g in-memory or in-database.
*
* @author Thomas.Eichstaedt-Engelen - Initial Contribution and API
* @author Kai Kreuzer - improved return values
*/
public interface Storage<T> {
/**
* Puts a key-value mapping into this Storage.
*
* @param key the key to add
* @param value the value to add
* @return previous value for the key or null if no value was replaced
*/
T put(String key, T value);
/**
* Removes the specified mapping from this map.
*
* @param key the mapping to remove
* @return the removed value or null if no entry existed
*/
T remove(String key);
/**
* Gets the value mapped to the key specified.
*
* @param key the key
* @return the mapped value, null if no match
*/
T get(String key);
/**
* Gets all keys of this Storage.
*
* @return the keys of this Storage
*/
Collection<String> getKeys();
/**
* Gets all values of this Storage.
*
* @return the values of this Storage
*/
Collection<T> getValues();
}

Просмотреть файл

@ -0,0 +1,35 @@
/**
* Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.storage;
/**
* The {@link StorageService} provides instances of {@link Storage}s
* which are meant as a means for generic storage of key-value pairs.
* You can think of different {@link StorageService}s that store these
* key-value pairs differently. One can think of e.g in-memory or
* in-database {@link Storage}s and many more. This {@link StorageService}
* decides which kind of {@link Storage} is returned on request. It is
* meant to be injected into service consumers with the need for storing
* generic key-value pairs like the ManagedXXXProviders.
*
* @author Thomas.Eichstaedt-Engelen - Initial Contribution and API
*/
public interface StorageService {
/**
* Returns the {@link Storage} with the given {@code name}. If no
* {@link Storage} with this name exists a new initialized instance
* is returned.
*
* @param name the name of the {@link StorageService} to return
* @return a ready to use {@link Storage}, never {@code null}
*/
<T> Storage<T> getStorage(String name);
}

Просмотреть файл

@ -10,19 +10,18 @@ package org.eclipse.smarthome.model.item.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.EList;
import org.eclipse.smarthome.core.binding.BindingConfigParseException;
import org.eclipse.smarthome.core.binding.BindingConfigReader;
import org.eclipse.smarthome.core.items.AbstractItemProvider;
import org.eclipse.smarthome.core.items.GenericItem;
import org.eclipse.smarthome.core.items.GroupFunction;
import org.eclipse.smarthome.core.items.GroupItem;
import org.eclipse.smarthome.core.items.Item;
import org.eclipse.smarthome.core.items.ItemFactory;
import org.eclipse.smarthome.core.items.ItemProvider;
import org.eclipse.smarthome.core.items.ItemsChangeListener;
import org.eclipse.smarthome.core.library.types.ArithmeticGroupFunction;
import org.eclipse.smarthome.core.types.State;
@ -47,14 +46,11 @@ import org.slf4j.LoggerFactory;
* @author Kai Kreuzer - Initial contribution and API
* @author Thomas.Eichstaedt-Engelen
*/
public class GenericItemProvider implements ItemProvider, ModelRepositoryChangeListener {
public class GenericItemProvider extends AbstractItemProvider implements ModelRepositoryChangeListener {
private static final Logger logger =
LoggerFactory.getLogger(GenericItemProvider.class);
/** to keep track of all item change listeners */
private Collection<ItemsChangeListener> listeners = new HashSet<ItemsChangeListener>();
/** to keep track of all binding config readers */
private Map<String, BindingConfigReader> bindingConfigReaders = new HashMap<String, BindingConfigReader>();
@ -348,22 +344,6 @@ public class GenericItemProvider implements ItemProvider, ModelRepositoryChangeL
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void addItemChangeListener(ItemsChangeListener listener) {
listeners.add(listener);
}
/**
* {@inheritDoc}
*/
@Override
public void removeItemChangeListener(ItemsChangeListener listener) {
listeners.remove(listener);
}
/**
* {@inheritDoc}
@ -374,12 +354,8 @@ public class GenericItemProvider implements ItemProvider, ModelRepositoryChangeL
@Override
public void modelChanged(String modelName, EventType type) {
if (modelName.endsWith("items")) {
processBindingConfigsFromModel(modelName);
for (ItemsChangeListener listener : listeners) {
listener.allItemsChanged(this, null);
}
notifyItemChangeListenersAboutAllItemsChanged(null);
}
}