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%2FConfig.java;h=773e4ee933c147d6206394b8da51fd4f8094358f;hb=34bc6ec632529a0dfe419aa7404bb42a456fbc96;hp=f96b3acf20c0f2d518ed042f9191fe33b7de798a;hpb=abf4ba1b0854fdd8b1a15c8c4481cf4b0bc93068;p=controller.git diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java index f96b3acf20..773e4ee933 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java @@ -8,93 +8,83 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config; +import static com.google.common.base.Preconditions.checkState; + import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; -import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; -import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType; -import org.opendaylight.controller.netconf.util.xml.XmlElement; -import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; -import org.opendaylight.controller.netconf.util.xml.XmlUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import javax.management.ObjectName; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import static com.google.common.base.Preconditions.checkState; -import static java.lang.String.format; +import javax.management.ObjectName; + +import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; +import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + public class Config { - private final Logger logger = LoggerFactory.getLogger(Config.class); private final Map> moduleConfigs; - private final Map moduleNamesToConfigs; + + private final Map> identityMap; public Config(Map> moduleConfigs) { + this(moduleConfigs, Collections.>emptyMap()); + } + + public Config(Map> moduleConfigs, Map> identityMap) { this.moduleConfigs = moduleConfigs; - Map moduleNamesToConfigs = new HashMap<>(); - for (Entry> entry : moduleConfigs.entrySet()) { - moduleNamesToConfigs.putAll(entry.getValue()); - } - this.moduleNamesToConfigs = Collections.unmodifiableMap(moduleNamesToConfigs); + this.identityMap = identityMap; } - private Map>> getMappedInstances(Set instancesToMap, - Services serviceTracker) { + public static Map>> getMappedInstances(Set instancesToMap, + Map> configs) { Multimap moduleToInstances = mapInstancesToModules(instancesToMap); Map>> retVal = Maps.newLinkedHashMap(); - for (String namespace : moduleConfigs.keySet()) { + for (Entry> namespaceToModuleToConfigEntry : configs.entrySet()) { Map> innerRetVal = Maps.newHashMap(); - for (Entry mbeEntry : moduleConfigs.get(namespace).entrySet()) { + for (Entry mbeEntry : namespaceToModuleToConfigEntry.getValue().entrySet()) { String moduleName = mbeEntry.getKey(); Collection instances = moduleToInstances.get(moduleName); - if (instances == null) + // TODO, this code does not support same module names from different namespaces + // Namespace should be present in ObjectName + + if (instances == null){ continue; + } innerRetVal.put(moduleName, instances); - // All found instances add to service tracker in advance - // This way all instances will be serialized as all available - // services when get-config is triggered - // (even if they are not used as services by other instances) - // = more user friendly - addServices(serviceTracker, instances, mbeEntry.getValue().getProvidedServices()); - } - retVal.put(namespace, innerRetVal); + retVal.put(namespaceToModuleToConfigEntry.getKey(), innerRetVal); } return retVal; } - private void addServices(Services serviceTracker, Collection instances, - Multimap providedServices) { - for (ObjectName instanceOn : instances) { - for (Entry serviceName : providedServices.entries()) { - serviceTracker.addServiceEntry(serviceName.getKey(), serviceName.getValue(), instanceOn); - } - } - } - private static Multimap mapInstancesToModules(Set instancesToMap) { Multimap retVal = HashMultimap.create(); @@ -105,90 +95,103 @@ public class Config { return retVal; } - // public Element toXml(Set instancesToMap, String namespace, - // Document document) { - // return toXml(instancesToMap, Optional.of(namespace), document); - // } - public Element toXml(Set instancesToMap, Optional maybeNamespace, Document document, - Element dataElement) { - Services serviceTracker = new Services(); + Element dataElement, ServiceRegistryWrapper serviceTracker) { Map>> moduleToInstances = getMappedInstances(instancesToMap, - serviceTracker); + moduleConfigs); - Element root = dataElement; if (maybeNamespace.isPresent()) { - XmlUtil.addNamespaceAttr(root, maybeNamespace.get()); + dataElement.setAttributeNS(maybeNamespace.get(), dataElement.getNodeName(), "xmlns"); } - Element modulesElement = document.createElement(XmlNetconfConstants.MODULES_KEY); - XmlUtil.addNamespaceAttr(modulesElement, - XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); - root.appendChild(modulesElement); - for (String moduleNamespace : moduleToInstances.keySet()) { - for (Entry> moduleMappingEntry : moduleToInstances.get(moduleNamespace) + Element modulesElement = XmlUtil.createElement(document, XmlNetconfConstants.MODULES_KEY, Optional.of(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG)); + dataElement.appendChild(modulesElement); + for (Entry>> moduleToInstanceEntry : moduleToInstances.entrySet()) { + for (Entry> moduleMappingEntry : moduleToInstanceEntry.getValue() .entrySet()) { - ModuleConfig mapping = moduleConfigs.get(moduleNamespace).get(moduleMappingEntry.getKey()); + ModuleConfig mapping = moduleConfigs.get(moduleToInstanceEntry.getKey()).get(moduleMappingEntry.getKey()); if (moduleMappingEntry.getValue().isEmpty()) { - addEmptyModulesCommented(document, modulesElement, moduleNamespace, moduleMappingEntry); - } else { - for (ObjectName objectName : moduleMappingEntry.getValue()) { - modulesElement - .appendChild(mapping.toXml(objectName, serviceTracker, document, moduleNamespace)); - } + continue; + } + + for (ObjectName objectName : moduleMappingEntry.getValue()) { + modulesElement.appendChild(mapping.toXml(objectName, document, moduleToInstanceEntry.getKey())); } } } - root.appendChild(serviceTracker.toXml(serviceTracker.getMappedServices(), document)); - - return root; - } - - // TODO remove commented modules from output - private void addEmptyModulesCommented(Document document, Element root, String moduleNamespace, - Entry> moduleMappingEntry) { - Element emptyModule = document.createElement(XmlNetconfConstants.MODULE_KEY); - - Element typeElement = XmlUtil.createTextElement(document, XmlNetconfConstants.TYPE_KEY, - moduleMappingEntry.getKey()); - emptyModule.appendChild(typeElement); + dataElement.appendChild(Services.toXml(serviceTracker, document)); - root.appendChild(document.createComment(XmlUtil.toString(emptyModule, false))); + return dataElement; } // TODO refactor, replace string representing namespace with namespace class // TODO refactor, replace Map->Multimap with e.g. ConfigElementResolved // class - public Map> fromXml(XmlElement xml, Set instancesForFillingServiceRefMapping, - EditStrategyType defaultEditStrategyType) { + + public Map> fromXmlModulesResolved(XmlElement xml, EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) throws NetconfDocumentedException { + Optional modulesElement = getModulesElement(xml); + List moduleElements = getModulesElementList(modulesElement); + Map> retVal = Maps.newHashMap(); - List recognisedChildren = Lists.newArrayList(); + for (XmlElement moduleElement : moduleElements) { + ResolvingStrategy resolvingStrategy = new ResolvingStrategy() { + @Override + public ModuleElementResolved resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) throws NetconfDocumentedException { + return moduleMapping.fromXml(moduleElement, serviceTracker, + instanceName, moduleNamespace, defaultStrategy, identityMap); + } + }; + + resolveModule(retVal, serviceTracker, moduleElement, defaultEditStrategyType, resolvingStrategy); + } + return retVal; + } - Services serviceTracker = fromXmlServices(xml, recognisedChildren, instancesForFillingServiceRefMapping); - List moduleElements = fromXmlModules(xml, recognisedChildren); + /** + * return a map containing namespace -> moduleName -> instanceName map. Attribute parsing is omitted. + */ + public Map> fromXmlModulesMap(XmlElement xml, + EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) throws NetconfDocumentedException { + Optional modulesElement = getModulesElement(xml); + List moduleElements = getModulesElementList(modulesElement); - xml.checkUnrecognisedElements(recognisedChildren); + Map> retVal = Maps.newHashMap(); for (XmlElement moduleElement : moduleElements) { - resolveModule(retVal, serviceTracker, moduleElement, defaultEditStrategyType); - } + ResolvingStrategy resolvingStrategy = new ResolvingStrategy() { + @Override + public ModuleElementDefinition resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, + ServiceRegistryWrapper serviceTracker, String instanceName, String moduleNamespace, + EditStrategyType defaultStrategy) { + // 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); + return new ModuleElementDefinition(instanceName, perInstanceEditStrategy, defaultStrategy); + } + }; + resolveModule(retVal, serviceTracker, moduleElement, defaultEditStrategyType, resolvingStrategy); + } return retVal; } - private List fromXmlModules(XmlElement xml, List recognisedChildren) { - Optional modulesElement = xml.getOnlyChildElementOptionally(XmlNetconfConstants.MODULES_KEY, - XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); + private static Optional getModulesElement(XmlElement xml) { + return xml.getOnlyChildElementOptionally(XmlNetconfConstants.MODULES_KEY, + XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); + } + + private List getModulesElementList(Optional modulesElement) throws NetconfDocumentedException { List moduleElements; + if (modulesElement.isPresent()) { moduleElements = modulesElement.get().getChildElementsWithSameNamespace(XmlNetconfConstants.MODULE_KEY); - recognisedChildren.add(modulesElement.get()); modulesElement.get().checkUnrecognisedElements(moduleElements); } else { moduleElements = Lists.newArrayList(); @@ -196,12 +199,14 @@ public class Config { return moduleElements; } - private void resolveModule(Map> retVal, Services serviceTracker, - XmlElement moduleElement, EditStrategyType defaultStrategy) { - XmlElement typeElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY); + private void resolveModule(Map> retVal, ServiceRegistryWrapper serviceTracker, + XmlElement moduleElement, EditStrategyType defaultStrategy, ResolvingStrategy resolvingStrategy) throws NetconfDocumentedException { + XmlElement typeElement = null; + typeElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY); Entry prefixToNamespace = typeElement.findNamespaceOfTextContent(); String moduleNamespace = prefixToNamespace.getValue(); - XmlElement nameElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY); + XmlElement nameElement = null; + nameElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY); String instanceName = nameElement.getTextContent(); String factoryNameWithPrefix = typeElement.getTextContent(); String prefixOrEmptyString = prefixToNamespace.getKey(); @@ -209,53 +214,55 @@ public class Config { ModuleConfig moduleMapping = getModuleMapping(moduleNamespace, instanceName, factoryName); - Multimap innerMap = retVal.get(moduleNamespace); + Multimap innerMap = retVal.get(moduleNamespace); if (innerMap == null) { innerMap = HashMultimap.create(); retVal.put(moduleNamespace, innerMap); } - ModuleElementResolved moduleElementResolved = moduleMapping.fromXml(moduleElement, serviceTracker, + T resolvedElement = resolvingStrategy.resolveElement(moduleMapping, moduleElement, serviceTracker, instanceName, moduleNamespace, defaultStrategy); - innerMap.put(factoryName, moduleElementResolved); + innerMap.put(factoryName, resolvedElement); } - private Services fromXmlServices(XmlElement xml, List recognisedChildren, Set instancesForFillingServiceRefMapping) { - Optional servicesElement = xml.getOnlyChildElementOptionally(XmlNetconfConstants.SERVICES_KEY, - XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); + public Services fromXmlServices(XmlElement xml) throws NetconfDocumentedException { + Optional servicesElement = getServicesElement(xml); - Map>> mappedServices; + Services services; if (servicesElement.isPresent()) { - mappedServices = Services.fromXml(servicesElement.get()); - recognisedChildren.add(servicesElement.get()); + services = Services.fromXml(servicesElement.get()); } else { - mappedServices = new HashMap<>(); + services = new Services(); } - Services services = Services.resolveServices(mappedServices); - // merge with what candidate db contains by default - ref_ - for(ObjectName existingON: instancesForFillingServiceRefMapping) { - logger.trace("Filling services from {}", existingON); - // get all its services - String factoryName = ObjectNameUtil.getFactoryName(existingON); - ModuleConfig moduleConfig = moduleNamesToConfigs.get(factoryName); + return services; + } + + private static Optional getServicesElement(XmlElement xml) { + return xml.getOnlyChildElementOptionally(XmlNetconfConstants.SERVICES_KEY, + XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); + } - checkState(moduleConfig != null, "Cannot find ModuleConfig with name " + factoryName + " in " + moduleNamesToConfigs); - // Set services = ; - for (Entry serviceName : moduleConfig.getProvidedServices().entries()) { + public static void checkUnrecognisedChildren(XmlElement parent) throws NetconfDocumentedException { + Optional servicesOpt = getServicesElement(parent); + Optional modulesOpt = getModulesElement(parent); - services.addServiceEntry(serviceName.getKey(), serviceName.getValue(), existingON); - } + List recognised = Lists.newArrayList(); + if(servicesOpt.isPresent()){ + recognised.add(servicesOpt.get()); + } + if(modulesOpt.isPresent()){ + recognised.add(modulesOpt.get()); } - return services; + parent.checkUnrecognisedElements(recognised); } private String getFactoryName(String factoryNameWithPrefix, String prefixOrEmptyString) { checkState( factoryNameWithPrefix.startsWith(prefixOrEmptyString), - format("Internal error: text " + "content '%s' of type node does not start with prefix '%s'", + String.format("Internal error: text " + "content '%s' of type node does not start with prefix '%s'", factoryNameWithPrefix, prefixOrEmptyString)); int factoryNameAfterPrefixIndex; @@ -279,4 +286,8 @@ public class Config { return moduleMapping; } + private interface ResolvingStrategy { + public T resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, + String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) throws NetconfDocumentedException; + } }