/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* 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.dto;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.eclipse.smarthome.core.items.ActiveItem;
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.library.types.ArithmeticGroupFunction;
import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.TypeParser;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
/**
* The {@link ItemDTOMapper} is an utility class to map items into item data transfer objects (DTOs).
*
* @author Kai Kreuzer - Initial contribution
* @author Stefan Bußweiler - Moved to core and renamed class to DTO mapper
* @author Dennis Nobel - Removed dynamic data
*/
public class ItemDTOMapper {
/**
* Maps item DTO into item object.
*
* @param itemDTO the DTO
* @param itemFactories the item factories in order to create the items
* @return the item object
*/
public static ActiveItem map(ItemDTO itemDTO, Set<ItemFactory> itemFactories) {
Preconditions.checkArgument(itemDTO != null, "The argument 'itemDTO' must no be null.");
Preconditions.checkArgument(itemFactories != null, "The argument 'itemFactories' must no be null.");
GenericItem newItem = null;
if (itemDTO.type != null) {
if (itemDTO instanceof GroupItemDTO && itemDTO.type.equals(GroupItem.TYPE)) {
GroupItemDTO groupItemDTO = (GroupItemDTO) itemDTO;
GenericItem baseItem = null;
if (!Strings.isNullOrEmpty(groupItemDTO.groupType)) {
baseItem = createItem(groupItemDTO.groupType, itemDTO.name, itemFactories);
}
GroupFunction function = new GroupFunction.Equality();
if (groupItemDTO.function != null) {
function = mapFunction(baseItem, groupItemDTO.function);
}
newItem = new GroupItem(itemDTO.name, baseItem, function);
} else {
String itemType = itemDTO.type;
newItem = createItem(itemType, itemDTO.name, itemFactories);
}
if (newItem != null) {
if (itemDTO.label != null) {
newItem.setLabel(itemDTO.label);
}
if (itemDTO.category != null) {
newItem.setCategory(itemDTO.category);
}
if (itemDTO.groupNames != null) {
newItem.addGroupNames(itemDTO.groupNames);
}
if (itemDTO.tags != null) {
newItem.addTags(itemDTO.tags);
}
}
}
return newItem;
}
public static GroupFunction mapFunction(Item baseItem, GroupFunctionDTO function) {
List<State> args = new ArrayList<State>();
if (function.params != null) {
for (String arg : function.params) {
State state = TypeParser.parseState(baseItem.getAcceptedDataTypes(), arg);
if (state == null) {
LoggerFactory.getLogger(ItemDTOMapper.class).warn(
"State '{}' is not valid for a group item with base type '{}'",
new Object[] { arg, baseItem.getType() });
args.clear();
break;
} else {
args.add(state);
}
}
}
GroupFunction groupFunction = null;
switch (function.name.toUpperCase()) {
case "AND":
if (args.size() == 2) {
groupFunction = new ArithmeticGroupFunction.And(args.get(0), args.get(1));
} else {
LoggerFactory.getLogger(ItemDTOMapper.class)
.error("Group function 'AND' requires two arguments. Using Equality instead.");
}
break;
case "OR":
if (args.size() == 2) {
groupFunction = new ArithmeticGroupFunction.Or(args.get(0), args.get(1));
} else {
LoggerFactory.getLogger(ItemDTOMapper.class)
.error("Group function 'OR' requires two arguments. Using Equality instead.");
}
break;
case "NAND":
if (args.size() == 2) {
groupFunction = new ArithmeticGroupFunction.NAnd(args.get(0), args.get(1));
} else {
LoggerFactory.getLogger(ItemDTOMapper.class)
.error("Group function 'NOT AND' requires two arguments. Using Equality instead.");
}
break;
case "NOR":
if (args.size() == 2) {
groupFunction = new ArithmeticGroupFunction.NOr(args.get(0), args.get(1));
} else {
LoggerFactory.getLogger(ItemDTOMapper.class)
.error("Group function 'NOT OR' requires two arguments. Using Equality instead.");
}
break;
case "COUNT":
if (args.size() == 1) {
groupFunction = new ArithmeticGroupFunction.Count(args.get(0));
} else {
LoggerFactory.getLogger(ItemDTOMapper.class)
.error("Group function 'COUNT' requires one argument. Using Equality instead.");
}
break;
case "AVG":
groupFunction = new ArithmeticGroupFunction.Avg();
break;
case "SUM":
groupFunction = new ArithmeticGroupFunction.Sum();
break;
case "MIN":
groupFunction = new ArithmeticGroupFunction.Min();
break;
case "MAX":
groupFunction = new ArithmeticGroupFunction.Max();
break;
case "EQUAL":
groupFunction = new GroupFunction.Equality();
break;
default:
LoggerFactory.getLogger(ItemDTOMapper.class)
.error("Unknown group function '" + function.name + "'. Using Equality instead.");
}
if (groupFunction == null) {
groupFunction = new GroupFunction.Equality();
}
return groupFunction;
}
/**
* Maps item into item DTO object.
*
* @param item the item
* @param drillDown the drill down
* @param uri the uri
* @return item DTO object
*/
public static ItemDTO map(Item item) {
ItemDTO itemDTO = item instanceof GroupItem ? new GroupItemDTO() : new ItemDTO();
fillProperties(itemDTO, item);
return itemDTO;
}
private static void fillProperties(ItemDTO itemDTO, Item item) {
if (item instanceof GroupItem) {
GroupItem groupItem = (GroupItem) item;
GroupItemDTO groupItemDTO = (GroupItemDTO) itemDTO;
if (groupItem.getBaseItem() != null) {
groupItemDTO.groupType = groupItem.getBaseItem().getType();
groupItemDTO.function = mapFunction(groupItem.getFunction());
}
}
itemDTO.name = item.getName();
itemDTO.type = item.getType();
itemDTO.label = item.getLabel();
itemDTO.tags = item.getTags();
itemDTO.category = item.getCategory();
itemDTO.groupNames = item.getGroupNames();
}
public static GroupFunctionDTO mapFunction(GroupFunction function) {
GroupFunctionDTO dto = new GroupFunctionDTO();
dto.name = function.getClass().getSimpleName().toUpperCase();
List<String> params = new ArrayList<>();
for (State param : function.getParameters()) {
params.add(param.toString());
}
if (!params.isEmpty()) {
dto.params = params.toArray(new String[params.size()]);
}
return dto;
}
/**
* helper: Create new item with name and type
*
* @param itemType type of the item
* @param itemname name of the item
* @return the newly created item
*/
private static GenericItem createItem(String itemType, String itemname, Set<ItemFactory> itemFactories) {
GenericItem newItem = null;
for (ItemFactory itemFactory : itemFactories) {
newItem = itemFactory.createItem(itemType, itemname);
if (newItem != null) {
break;
}
}
return newItem;
}
}