/*
* 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.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
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.openmuc.framework.config.RootConfig;
import org.openmuc.framework.datalogger.spi.LogChannel;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public final class RootConfigImpl implements RootConfig {
private String dataLogSource = null;
final HashMap<String, DriverConfigImpl> driverConfigsById = new LinkedHashMap<>();
final HashMap<String, DeviceConfigImpl> deviceConfigsById = new HashMap<>();
final HashMap<String, ChannelConfigImpl> channelConfigsById = new HashMap<>();
// TODO really needed?:
List<LogChannel> logChannels;
@Override
public String getDataLogSource() {
return dataLogSource;
}
@Override
public void setDataLogSource(String source) {
dataLogSource = source;
}
static RootConfigImpl createFromFile(File configFile) throws ParseException, FileNotFoundException {
if (configFile == null) {
throw new NullPointerException("configFileName is null or the empty string.");
}
if (!configFile.exists()) {
throw new FileNotFoundException();
}
DocumentBuilderFactory docBFac = DocumentBuilderFactory.newInstance();
docBFac.setIgnoringComments(true);
Document doc;
try {
doc = docBFac.newDocumentBuilder().parse(configFile);
} catch (Exception e) {
throw new ParseException(e);
}
Node rootNode = doc.getDocumentElement();
if (!rootNode.getNodeName().equals("configuration")) {
throw new ParseException("root node in configuration is not of type \"configuration\"");
}
return getRootConfigFromDomNode(rootNode);
}
static RootConfigImpl getRootConfigFromDomNode(Node rootConfigNode) throws ParseException {
RootConfigImpl rootConfig = new RootConfigImpl();
NodeList rootConfigChildren = rootConfigNode.getChildNodes();
for (int i = 0; i < rootConfigChildren.getLength(); i++) {
Node childNode = rootConfigChildren.item(i);
String childName = childNode.getNodeName();
if (childName.equals("#text")) {
continue;
}
else if (childName.equals("driver")) {
DriverConfigImpl.addDriverFromDomNode(childNode, rootConfig);
}
else if (childName.equals("dataLogSource")) {
rootConfig.dataLogSource = childNode.getTextContent();
}
else {
throw new ParseException("found unknown tag:" + childName);
}
}
return rootConfig;
}
void writeToFile(File configFile) throws TransformerFactoryConfigurationError, IOException,
ParserConfigurationException, TransformerException {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
StreamResult result = new StreamResult(new FileWriter(configFile));
DocumentBuilder docBuild = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = docBuild.newDocument();
doc.appendChild(getDomElement(doc));
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
}
Element getDomElement(Document document) {
Element rootConfigElement = document.createElement("configuration");
if (dataLogSource != null) {
Node loggerChild = document.createElement("dataLogSource");
loggerChild.setTextContent(dataLogSource);
rootConfigElement.appendChild(loggerChild);
}
for (DriverConfig driverConfig : driverConfigsById.values()) {
rootConfigElement.appendChild(((DriverConfigImpl) driverConfig).getDomElement(document));
}
return rootConfigElement;
}
@Override
public DriverConfig getOrAddDriver(String id) {
try {
return addDriver(id);
} catch (IdCollisionException e) {
return driverConfigsById.get(id);
}
}
@Override
public DriverConfig addDriver(String id) throws IdCollisionException {
if (id == null) {
throw new IllegalArgumentException("The driver ID may not be null");
}
ChannelConfigImpl.checkIdSyntax(id);
if (driverConfigsById.containsKey(id)) {
throw new IdCollisionException("Collision with the driver ID:" + id);
}
DriverConfigImpl driverConfig = new DriverConfigImpl(id, this);
driverConfigsById.put(id, driverConfig);
return driverConfig;
}
@Override
public DriverConfig getDriver(String id) {
return driverConfigsById.get(id);
}
@Override
public DeviceConfig getDevice(String id) {
return deviceConfigsById.get(id);
}
@Override
public ChannelConfig getChannel(String id) {
return channelConfigsById.get(id);
}
@SuppressWarnings("unchecked")
@Override
public Collection<DriverConfig> getDrivers() {
return (Collection<DriverConfig>) (Collection<?>) Collections
.unmodifiableCollection(driverConfigsById.values());
}
@Override
protected RootConfigImpl clone() {
RootConfigImpl configClone = new RootConfigImpl();
configClone.dataLogSource = dataLogSource;
for (DriverConfigImpl driverConfig : driverConfigsById.values()) {
configClone.addDriver(driverConfig.clone(configClone));
}
return configClone;
}
RootConfigImpl cloneWithDefaults() {
RootConfigImpl configClone = new RootConfigImpl();
if (dataLogSource != null) {
configClone.dataLogSource = dataLogSource;
}
else {
configClone.dataLogSource = "";
}
for (DriverConfigImpl driverConfig : driverConfigsById.values()) {
configClone.addDriver(driverConfig.cloneWithDefaults(configClone));
}
return configClone;
}
private void addDriver(DriverConfigImpl driverConfig) {
driverConfigsById.put(driverConfig.getId(), driverConfig);
for (DeviceConfigImpl deviceConfig : driverConfig.deviceConfigsById.values()) {
deviceConfigsById.put(deviceConfig.getId(), deviceConfig);
for (ChannelConfigImpl channelConfig : deviceConfig.channelConfigsById.values()) {
channelConfigsById.put(channelConfig.getId(), channelConfig);
}
}
}
}