X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fconfig-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fconfignetconfconnector%2Fmapping%2Fconfig%2FInstanceConfig.java;fp=opendaylight%2Fnetconf%2Fconfig-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fconfignetconfconnector%2Fmapping%2Fconfig%2FInstanceConfig.java;h=d1ba0b0206b0c44b743302bcba2e3f33fd784947;hb=a92d9d6a21a0f6ca8d2153795721f500eaf29ee9;hp=0000000000000000000000000000000000000000;hpb=fbc3092ca33990f0fc4a47f008786a416c484488;p=controller.git diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java new file mode 100644 index 0000000000..d1ba0b0206 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. 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.opendaylight.controller.netconf.confignetconfconnector.mapping.config; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.opendaylight.controller.config.util.ConfigRegistryClient; +import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeReadingStrategy; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.AttributeMappingStrategy; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectMapper; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.ObjectResolver; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml.AttributeWritingStrategy; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml.ObjectXmlWriter; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.management.ObjectName; +import javax.management.openmbean.OpenType; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public final class InstanceConfig { + private static final Logger logger = LoggerFactory.getLogger(InstanceConfig.class); + + private final Map yangToAttrConfig; + private final Map jmxToAttrConfig; + private final ConfigRegistryClient configRegistryClient; + + public InstanceConfig(ConfigRegistryClient configRegistryClient, Map yangNamesToAttributes) { + this.yangToAttrConfig = yangNamesToAttributes; + this.jmxToAttrConfig = reverseMap(yangNamesToAttributes); + this.configRegistryClient = configRegistryClient; + } + + private Map getMappedConfiguration(ObjectName on, Services depTracker) { + + // TODO make field, mappingStrategies can be instantiated only once + Map>> mappingStrategies = new ObjectMapper(depTracker) + .prepareMapping(jmxToAttrConfig); + + Map toXml = Maps.newHashMap(); + + for (Entry configDefEntry : jmxToAttrConfig.entrySet()) { + + // Skip children runtime beans as they are mapped by InstanceRuntime + if (configDefEntry.getValue() instanceof RuntimeBeanEntry) + continue; + + Object value = configRegistryClient.getAttributeCurrentValue(on, configDefEntry.getKey()); + try { + AttributeMappingStrategy> attributeMappingStrategy = mappingStrategies + .get(configDefEntry.getKey()); + Optional a = attributeMappingStrategy.mapAttribute(value); + if (a.isPresent() == false) + continue; + + toXml.put(configDefEntry.getValue().getAttributeYangName(), a.get()); + } catch (Exception e) { + throw new IllegalStateException("Unable to map value " + value + " to attribute " + + configDefEntry.getKey(), e); + } + } + + return toXml; + } + + public Element toXml(ObjectName on, Services depTracker, String namespace, Document document, Element rootElement) { + + Element cfgElement = rootElement; + + Map strats = new ObjectXmlWriter().prepareWriting(yangToAttrConfig, document); + + Map mappedConfig = getMappedConfiguration(on, depTracker); + + for (Entry mappingEntry : mappedConfig.entrySet()) { + try { + strats.get(mappingEntry.getKey()).writeElement(cfgElement, namespace, mappingEntry.getValue()); + } catch (Exception e) { + throw new IllegalStateException("Unable to write value " + mappingEntry.getValue() + " for attribute " + + mappingEntry.getValue(), e); + } + } + + return cfgElement; + } + + private void resolveConfiguration(InstanceConfigElementResolved mappedConfig, Services depTracker) { + + // TODO make field, resolvingStrategies can be instantiated only once + Map>> resolvingStrategies = new ObjectResolver( + depTracker).prepareResolving(yangToAttrConfig); + + for (Entry configDefEntry : mappedConfig.getConfiguration().entrySet()) { + try { + + AttributeResolvingStrategy> attributeResolvingStrategy = resolvingStrategies + .get(configDefEntry.getKey()); + + configDefEntry.getValue().resolveValue(attributeResolvingStrategy, configDefEntry.getKey()); + configDefEntry.getValue().setJmxName( + yangToAttrConfig.get(configDefEntry.getKey()).getUpperCaseCammelCase()); + } catch (Exception e) { + throw new IllegalStateException("Unable to resolve value " + configDefEntry.getValue() + + " to attribute " + configDefEntry.getKey(), e); + } + } + } + + public InstanceConfigElementResolved fromXml(XmlElement moduleElement, Services services, String moduleNamespace) { + Map retVal = Maps.newHashMap(); + + Map strats = new ObjectXmlReader().prepareReading(yangToAttrConfig); + List recognisedChildren = Lists.newArrayList(); + + XmlElement type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY); + XmlElement name = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY); + List typeAndName = Lists.newArrayList(type, name); + + for (Entry readStratEntry : strats.entrySet()) { + List configNodes = getConfigNodes(moduleElement, moduleNamespace, readStratEntry.getKey(), + recognisedChildren, typeAndName); + AttributeConfigElement readElement = readStratEntry.getValue().readElement(configNodes); + retVal.put(readStratEntry.getKey(), readElement); + } + + recognisedChildren.addAll(typeAndName); + moduleElement.checkUnrecognisedElements(recognisedChildren); + + // TODO: add check for conflicts between global and local edit strategy + String perInstanceEditStrategy = moduleElement.getAttribute(XmlNetconfConstants.OPERATION_ATTR_KEY, + XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + + InstanceConfigElementResolved instanceConfigElementResolved = perInstanceEditStrategy.equals("") ? new InstanceConfigElementResolved( + retVal) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal); + + resolveConfiguration(instanceConfigElementResolved, services); + return instanceConfigElementResolved; + } + + private List getConfigNodes(XmlElement moduleElement, String moduleNamespace, String name, + List recognisedChildren, List typeAndName) { + List foundConfigNodes = moduleElement.getChildElementsWithinNamespace(name, moduleNamespace); + if (foundConfigNodes.isEmpty()) { + logger.debug("No config nodes {}:{} found in {}", moduleNamespace, name, moduleElement); + logger.debug("Trying lookup of config nodes without specified namespace"); + foundConfigNodes = moduleElement.getChildElementsWithinNamespace(name, + XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); + // In case module type or name element is not present in config it + // would be matched with config type or name + // We need to remove config type and name from available module + // config elements + foundConfigNodes.removeAll(typeAndName); + logger.debug("Found {} config nodes {} without specified namespace in {}", foundConfigNodes.size(), name, + moduleElement); + } else { + List foundWithoutNamespaceNodes = moduleElement.getChildElementsWithinNamespace(name, + XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); + foundWithoutNamespaceNodes.removeAll(typeAndName); + Preconditions.checkState(foundWithoutNamespaceNodes.isEmpty(), + "Element %s present multiple times with different namespaces: %s, %s", name, foundConfigNodes, + foundWithoutNamespaceNodes); + } + + recognisedChildren.addAll(foundConfigNodes); + return foundConfigNodes; + } + + private static Map reverseMap(Map yangNameToAttr) { + Map reversednameToAtr = Maps.newHashMap(); + + for (Entry entry : yangNameToAttr.entrySet()) { + reversednameToAtr.put(entry.getValue().getUpperCaseCammelCase(), entry.getValue()); + } + + return reversednameToAtr; + } + +}