/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.component.xml.impl; import java.io.File; import java.util.Map; import java.util.Map.Entry; import org.w3c.dom.Document; import de.rcenvironment.core.component.api.ComponentException; import de.rcenvironment.core.component.execution.api.ComponentContext; import de.rcenvironment.core.component.xml.XMLComponentConstants; import de.rcenvironment.core.component.xml.api.EndpointXMLService; import de.rcenvironment.core.datamodel.api.DataTypeException; import de.rcenvironment.core.datamodel.api.TypedDatum; import de.rcenvironment.core.datamodel.api.TypedDatumFactory; import de.rcenvironment.core.datamodel.api.TypedDatumService; import de.rcenvironment.core.datamodel.types.api.BooleanTD; import de.rcenvironment.core.datamodel.types.api.FloatTD; import de.rcenvironment.core.datamodel.types.api.IntegerTD; import de.rcenvironment.core.datamodel.types.api.ShortTextTD; import de.rcenvironment.core.utils.common.StringUtils; import de.rcenvironment.core.utils.common.xml.XMLException; import de.rcenvironment.core.utils.common.xml.XMLMapperConstants; import de.rcenvironment.core.utils.common.xml.api.XMLSupportService; /** * Default implementation of the EndpointXMLService. * * @author Brigitte Boden */ public class EndpointXMLServiceImpl implements EndpointXMLService { private XMLSupportService xmlSupport; /** * OSGI bind method. * * @param service the service. */ public void bindXMLSupportService(XMLSupportService service) { xmlSupport = service; } @Override public void updateXMLWithInputs(File xmlFile, Map<String, TypedDatum> dynamicInputs, ComponentContext componentContext) throws DataTypeException, ComponentException { if (dynamicInputs.isEmpty()) { // Nothing to do here return; } if (!xmlFile.exists()) { throw new ComponentException(xmlFile.getAbsolutePath() + " does not exist"); } synchronized (XMLMapperConstants.GLOBAL_MAPPING_LOCK) { Document doc; try { doc = xmlSupport.readXMLFromFile(xmlFile); } catch (XMLException e) { throw new ComponentException("Failed to read " + xmlFile.getAbsolutePath(), e); } for (final Entry<String, TypedDatum> entry : dynamicInputs.entrySet()) { final String xpath = componentContext.getInputMetaDataValue(entry.getKey(), XMLComponentConstants.CONFIG_KEY_XPATH); final TypedDatum value = entry.getValue(); String valueAsString = getValueAsString(value); try { xmlSupport.replaceNodeText(doc, xpath, valueAsString); componentContext.getLog().componentInfo(StringUtils.format("Replaced value for '%s' with input value of '%s': %s", xpath, entry.getKey(), value.toString())); } catch (XMLException e) { throw new ComponentException(StringUtils.format("Failed to replace value for '%s' with value of input '%s': %s", xpath, entry.getKey(), value.toString()), e); } } try { xmlSupport.writeXMLtoFile(doc, xmlFile); } catch (XMLException e) { throw new ComponentException("Failed to write XML content to file: " + xmlFile.getAbsolutePath(), e); } } } private String getValueAsString(final TypedDatum value) throws DataTypeException { switch (value.getDataType()) { case ShortText: return String.valueOf(((ShortTextTD) value).getShortTextValue()); case Boolean: return String.valueOf(((BooleanTD) value).getBooleanValue()); case Float: return String.valueOf(((FloatTD) value).getFloatValue()); case Integer: return String.valueOf(((IntegerTD) value).getIntValue()); default: throw new DataTypeException("Can not convert value of type '" + value.getDataType().getDisplayName() + "' to textual representation for insertion into XML"); } } @Override public void updateOutputsFromXML(File xmlFile, ComponentContext componentContext) throws DataTypeException, ComponentException { if (!xmlFile.exists()) { throw new ComponentException(xmlFile.getAbsolutePath() + " does not exist"); } synchronized (XMLMapperConstants.GLOBAL_MAPPING_LOCK) { Document doc = null; for (String outputName : componentContext.getOutputs()) { if (componentContext.isDynamicOutput(outputName)) { //If the XML file has not been read, read it now. if (doc == null) { try { doc = xmlSupport.readXMLFromFile(xmlFile); } catch (XMLException e) { throw new ComponentException("Failed to read " + xmlFile.getAbsolutePath(), e); } } final String xpath = componentContext.getOutputMetaDataValue(outputName, XMLComponentConstants.CONFIG_KEY_XPATH); String valueAsString; final String message = StringUtils.format("Failed to extract value for output '%s' that points to '%s'", outputName, xpath); try { valueAsString = xmlSupport.getElementText(doc, xpath); } catch (XMLException e) { throw new ComponentException(message, e); } componentContext.getLog().componentInfo( StringUtils.format("Extracted '%s' for XPath '%s' that will be sent to output '%s'", valueAsString, xpath, outputName)); TypedDatum value = getValueAsTypedValue(outputName, valueAsString, componentContext); componentContext.writeOutput(outputName, value); } } } } private TypedDatum getValueAsTypedValue(String outputName, String rawValue, ComponentContext componentContext) throws DataTypeException { String errorMessage = "Can not convert value '%s' to '%s' that is the required data type of output" + " '%s' this value should be sent to"; TypedDatumFactory typedDatumFactory = componentContext.getService(TypedDatumService.class).getFactory(); TypedDatum value; try { switch (componentContext.getOutputDataType(outputName)) { case ShortText: value = typedDatumFactory.createShortText(rawValue); break; case Boolean: value = typedDatumFactory.createBoolean(Boolean.valueOf(rawValue)); break; case Float: value = typedDatumFactory.createFloat(Double.valueOf(rawValue)); break; case Integer: value = typedDatumFactory.createInteger(Long.valueOf(rawValue)); break; default: throw new DataTypeException(StringUtils.format(errorMessage, rawValue, componentContext.getOutputDataType(outputName).getDisplayName(), outputName)); } } catch (NumberFormatException e) { throw new DataTypeException(StringUtils.format(errorMessage, rawValue, componentContext.getOutputDataType(outputName).getDisplayName(), outputName)); } return value; } }