/* * Copyright 2011-16 Fraunhofer ISE * * This file is part of OpenMUC. * For more information visit http://www.openmuc.org * * OpenMUC is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenMUC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenMUC. If not, see <http://www.gnu.org/licenses/>. * */ package org.openmuc.framework.core.datamanager; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import org.openmuc.framework.config.ChannelConfig; import org.openmuc.framework.config.DeviceConfig; import org.openmuc.framework.config.DriverConfig; import org.openmuc.framework.config.IdCollisionException; import org.openmuc.framework.config.ParseException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public final class DeviceConfigImpl implements DeviceConfig { String id; String description = null; String deviceAddress = null; String settings = null; Integer samplingTimeout = null; Integer connectRetryInterval = null; Boolean disabled = null; Device device = null; final HashMap<String, ChannelConfigImpl> channelConfigsById = new LinkedHashMap<>(); DriverConfigImpl driverParent; DeviceConfigImpl(String id, DriverConfigImpl driverParent) { this.id = id; this.driverParent = driverParent; } @Override public String getId() { return id; } @Override public void setId(String id) throws IdCollisionException { if (id == null) { throw new IllegalArgumentException("The device ID may not be null"); } ChannelConfigImpl.checkIdSyntax(id); if (driverParent.rootConfigParent.deviceConfigsById.containsKey(id)) { throw new IdCollisionException("Collision with device ID:" + id); } driverParent.deviceConfigsById.put(id, driverParent.deviceConfigsById.remove(this.id)); driverParent.rootConfigParent.deviceConfigsById.put(id, driverParent.rootConfigParent.deviceConfigsById.remove(this.id)); this.id = id; } @Override public String getDescription() { return description; } @Override public void setDescription(String description) { this.description = description; } @Override public String getDeviceAddress() { return deviceAddress; } @Override public void setDeviceAddress(String address) { deviceAddress = address; } @Override public String getSettings() { return settings; } @Override public void setSettings(String settings) { this.settings = settings; } @Override public Integer getSamplingTimeout() { return samplingTimeout; } @Override public void setSamplingTimeout(Integer timeout) { if (timeout != null && timeout < 0) { throw new IllegalArgumentException("A negative sampling timeout is not allowed"); } samplingTimeout = timeout; } @Override public Integer getConnectRetryInterval() { return connectRetryInterval; } @Override public void setConnectRetryInterval(Integer interval) { if (interval != null && interval < 0) { throw new IllegalArgumentException("A negative connect retry interval is not allowed"); } connectRetryInterval = interval; } @Override public Boolean isDisabled() { return disabled; } @Override public void setDisabled(Boolean disabled) { this.disabled = disabled; } @Override public ChannelConfig addChannel(String channelId) throws IdCollisionException { if (channelId == null) { throw new IllegalArgumentException("The channel ID may not be null"); } ChannelConfigImpl.checkIdSyntax(channelId); if (driverParent.rootConfigParent.channelConfigsById.containsKey(channelId)) { throw new IdCollisionException("Collision with channel ID: " + channelId); } ChannelConfigImpl newChannel = new ChannelConfigImpl(channelId, this); driverParent.rootConfigParent.channelConfigsById.put(channelId, newChannel); channelConfigsById.put(channelId, newChannel); return newChannel; } @Override public ChannelConfig getChannel(String channelId) { return channelConfigsById.get(channelId); } @SuppressWarnings("unchecked") @Override public Collection<ChannelConfig> getChannels() { return (Collection<ChannelConfig>) (Collection<?>) Collections .unmodifiableCollection(channelConfigsById.values()); } @Override public void delete() { driverParent.deviceConfigsById.remove(id); clear(); } void clear() { for (ChannelConfigImpl channelConfig : channelConfigsById.values()) { channelConfig.clear(); } channelConfigsById.clear(); driverParent.rootConfigParent.deviceConfigsById.remove(id); driverParent = null; } @Override public DriverConfig getDriver() { return driverParent; } static void addDeviceFromDomNode(Node deviceConfigNode, DriverConfig parentConfig) throws ParseException { String id = ChannelConfigImpl.getAttributeValue(deviceConfigNode, "id"); if (id == null) { throw new ParseException("device has no id attribute"); } DeviceConfigImpl config; try { config = (DeviceConfigImpl) parentConfig.addDevice(id); } catch (Exception e) { throw new ParseException(e); } NodeList deviceChildren = deviceConfigNode.getChildNodes(); try { for (int i = 0; i < deviceChildren.getLength(); i++) { Node childNode = deviceChildren.item(i); String childName = childNode.getNodeName(); if (childName.equals("#text")) { continue; } else if (childName.equals("channel")) { ChannelConfigImpl.addChannelFromDomNode(childNode, config); } else if (childName.equals("description")) { config.setDescription(childNode.getTextContent()); } else if (childName.equals("deviceAddress")) { config.setDeviceAddress(childNode.getTextContent()); } else if (childName.equals("settings")) { config.setSettings(childNode.getTextContent()); } else if (childName.equals("samplingTimeout")) { config.setSamplingTimeout(ChannelConfigImpl.timeStringToMillis(childNode.getTextContent())); } else if (childName.equals("connectRetryInterval")) { config.setConnectRetryInterval(ChannelConfigImpl.timeStringToMillis(childNode.getTextContent())); } else if (childName.equals("disabled")) { String disabledString = childNode.getTextContent().toLowerCase(); if (disabledString.equals("true")) { config.disabled = true; } else if (disabledString.equals("false")) { config.disabled = false; } else { throw new ParseException("\"disabled\" tag contains neither \"true\" nor \"false\""); } } else { throw new ParseException("found unknown tag:" + childName); } } } catch (IllegalArgumentException e) { throw new ParseException(e); } } Element getDomElement(Document document) { Element parentElement = document.createElement("device"); parentElement.setAttribute("id", id); Element childElement; if (description != null) { childElement = document.createElement("description"); childElement.setTextContent(description); parentElement.appendChild(childElement); } if (deviceAddress != null) { childElement = document.createElement("deviceAddress"); childElement.setTextContent(deviceAddress); parentElement.appendChild(childElement); } if (settings != null) { childElement = document.createElement("settings"); childElement.setTextContent(settings); parentElement.appendChild(childElement); } if (samplingTimeout != null) { childElement = document.createElement("samplingTimeout"); childElement.setTextContent(ChannelConfigImpl.millisToTimeString(samplingTimeout)); parentElement.appendChild(childElement); } if (connectRetryInterval != null) { childElement = document.createElement("connectRetryInterval"); childElement.setTextContent(ChannelConfigImpl.millisToTimeString(connectRetryInterval)); parentElement.appendChild(childElement); } if (disabled != null) { childElement = document.createElement("disabled"); if (disabled) { childElement.setTextContent("true"); } else { childElement.setTextContent("false"); } parentElement.appendChild(childElement); } for (ChannelConfigImpl channelConfig : channelConfigsById.values()) { parentElement.appendChild(channelConfig.getDomElement(document)); } return parentElement; } DeviceConfigImpl clone(DriverConfigImpl clonedParentConfig) { DeviceConfigImpl configClone = new DeviceConfigImpl(id, clonedParentConfig); configClone.description = description; configClone.deviceAddress = deviceAddress; configClone.settings = settings; configClone.samplingTimeout = samplingTimeout; configClone.connectRetryInterval = connectRetryInterval; configClone.disabled = disabled; for (ChannelConfigImpl channelConfig : channelConfigsById.values()) { configClone.channelConfigsById.put(channelConfig.id, channelConfig.clone(configClone)); } return configClone; } DeviceConfigImpl cloneWithDefaults(DriverConfigImpl clonedParentConfig) { DeviceConfigImpl configClone = new DeviceConfigImpl(id, clonedParentConfig); if (description == null) { configClone.description = DESCRIPTION_DEFAULT; } else { configClone.description = description; } if (deviceAddress == null) { configClone.deviceAddress = DEVICE_ADDRESS_DEFAULT; } else { configClone.deviceAddress = deviceAddress; } if (settings == null) { configClone.settings = SETTINGS_DEFAULT; } else { configClone.settings = settings; } if (samplingTimeout == null) { configClone.samplingTimeout = clonedParentConfig.samplingTimeout; } else { configClone.samplingTimeout = samplingTimeout; } if (connectRetryInterval == null) { configClone.connectRetryInterval = clonedParentConfig.connectRetryInterval; } else { configClone.connectRetryInterval = connectRetryInterval; } if (disabled == null || clonedParentConfig.disabled) { configClone.disabled = clonedParentConfig.disabled; } else { configClone.disabled = disabled; } for (ChannelConfigImpl channelConfig : channelConfigsById.values()) { configClone.channelConfigsById.put(channelConfig.id, channelConfig.cloneWithDefaults(configClone)); } return configClone; } }