Eliminate SchemaResourcesDTO
[netconf.git] / plugins / netconf-client-mdsal / src / main / java / org / opendaylight / netconf / client / mdsal / DeviceMountPointContext.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netconf.client.mdsal;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.collect.ImmutableMap;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.Map;
17 import java.util.Optional;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.opendaylight.yangtools.concepts.Immutable;
20 import org.opendaylight.yangtools.rfc8528.model.api.SchemaMountConstants;
21 import org.opendaylight.yangtools.yang.common.MountPointLabel;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.common.QNameModule;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
28 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.MountPointContext;
32 import org.opendaylight.yangtools.yang.data.api.schema.MountPointContextFactory;
33 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
34 import org.opendaylight.yangtools.yang.model.api.Module;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 // TODO: this should really come from rfc8528-data-util
39 final class DeviceMountPointContext implements Immutable, MountPointContext {
40     private static final Logger LOG = LoggerFactory.getLogger(DeviceMountPointContext.class);
41     private static final NodeIdentifier MOUNT_POINT = NodeIdentifier.create(
42         QName.create(SchemaMountConstants.RFC8528_MODULE, "mount-point").intern());
43     private static final NodeIdentifier CONFIG = NodeIdentifier.create(
44         QName.create(SchemaMountConstants.RFC8528_MODULE, "config").intern());
45     private static final NodeIdentifier MODULE = NodeIdentifier.create(
46         QName.create(SchemaMountConstants.RFC8528_MODULE, "module").intern());
47     private static final NodeIdentifier LABEL = NodeIdentifier.create(
48         QName.create(SchemaMountConstants.RFC8528_MODULE, "label").intern());
49     private static final NodeIdentifier SCHEMA_REF = NodeIdentifier.create(
50         QName.create(SchemaMountConstants.RFC8528_MODULE, "schema-ref").intern());
51     private static final NodeIdentifier INLINE = NodeIdentifier.create(
52         QName.create(SchemaMountConstants.RFC8528_MODULE, "inline").intern());
53     private static final NodeIdentifier SHARED_SCHEMA = NodeIdentifier.create(
54         QName.create(SchemaMountConstants.RFC8528_MODULE, "shared-schema").intern());
55     private static final NodeIdentifier PARENT_REFERENCE = NodeIdentifier.create(
56         QName.create(SchemaMountConstants.RFC8528_MODULE, "parent-reference").intern());
57
58     private final ImmutableMap<MountPointLabel, NetconfMountPointContextFactory> mountPoints;
59     private final @NonNull EffectiveModelContext modelContext;
60
61     private DeviceMountPointContext(final EffectiveModelContext modelContext,
62             final Map<MountPointLabel, NetconfMountPointContextFactory> mountPoints) {
63         this.modelContext = requireNonNull(modelContext);
64         this.mountPoints = ImmutableMap.copyOf(mountPoints);
65     }
66
67     static MountPointContext create(final MountPointContext emptyContext, final ContainerNode mountData) {
68         final Optional<DataContainerChild> optMountPoint = mountData.findChildByArg(MOUNT_POINT);
69         if (optMountPoint.isEmpty()) {
70             LOG.debug("mount-point list not present in {}", mountData);
71             return emptyContext;
72         }
73
74         final EffectiveModelContext schemaContext = emptyContext.modelContext();
75         final DataContainerChild mountPoint = optMountPoint.orElseThrow();
76         checkArgument(mountPoint instanceof MapNode, "mount-point list %s is not a MapNode", mountPoint);
77
78         final Map<MountPointLabel, NetconfMountPointContextFactory> mountPoints = new HashMap<>();
79         for (MapEntryNode entry : ((MapNode) mountPoint).body()) {
80             final String moduleName = entry.findChildByArg(MODULE).map(mod -> {
81                 checkArgument(mod instanceof LeafNode, "Unexpected module leaf %s", mod);
82                 final Object value = mod.body();
83                 checkArgument(value instanceof String, "Unexpected module leaf value %s", value);
84                 return (String) value;
85             }).orElseThrow(() -> new IllegalArgumentException("Mount module missing in " + entry));
86             final Iterator<? extends Module> it = schemaContext.findModules(moduleName).iterator();
87             checkArgument(it.hasNext(), "Failed to find a module named %s", moduleName);
88             final QNameModule module = it.next().getQNameModule();
89
90             final MountPointLabel mountId = new MountPointLabel(QName.create(module,
91                 entry.findChildByArg(LABEL).map(lbl -> {
92                     checkArgument(lbl instanceof LeafNode, "Unexpected label leaf %s", lbl);
93                     final Object value = lbl.body();
94                     checkArgument(value instanceof String, "Unexpected label leaf value %s", value);
95                     return (String) value;
96                 }).orElseThrow(() -> new IllegalArgumentException("Mount module missing in " + entry))));
97
98             final DataContainerChild child = entry.findChildByArg(SCHEMA_REF).orElseThrow(
99                 () -> new IllegalArgumentException("Missing schema-ref choice in " + entry));
100             checkArgument(child instanceof ChoiceNode, "Unexpected schema-ref choice %s", child);
101             final ChoiceNode schemaRef = (ChoiceNode) child;
102
103             final Optional<DataContainerChild> maybeShared = schemaRef.findChildByArg(SHARED_SCHEMA);
104             if (maybeShared.isEmpty()) {
105                 LOG.debug("Ignoring non-shared mountpoint entry {}", entry);
106                 continue;
107             }
108
109             mountPoints.put(mountId, new NetconfMountPointContextFactory(schemaContext));
110         }
111
112         return new DeviceMountPointContext(schemaContext, mountPoints);
113     }
114
115     @Override
116     public EffectiveModelContext modelContext() {
117         return modelContext;
118     }
119
120     @Override
121     public Optional<MountPointContextFactory> findMountPoint(@NonNull final MountPointLabel label) {
122         return Optional.ofNullable(mountPoints.get(requireNonNull(label)));
123     }
124 }