Move MountPointNormalizedNodeWriter
[yangtools.git] / data / yang-data-util / src / main / java / org / opendaylight / yangtools / yang / data / util / AbstractDynamicMountPointContextFactory.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.yangtools.yang.data.util;
9
10 import com.google.common.annotations.Beta;
11 import java.io.IOException;
12 import java.util.Map;
13 import java.util.Map.Entry;
14 import java.util.Optional;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.concepts.AbstractSimpleIdentifiable;
17 import org.opendaylight.yangtools.rfc8528.model.api.MountPointLabel;
18 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
19 import org.opendaylight.yangtools.yang.data.api.schema.MountPointChild;
20 import org.opendaylight.yangtools.yang.data.api.schema.MountPointContext;
21 import org.opendaylight.yangtools.yang.data.api.schema.MountPointContextFactory;
22 import org.opendaylight.yangtools.yang.data.api.schema.MountPointException;
23 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
24 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Abstract base class for dynamic resolvers.
30  */
31 @Beta
32 // FIXME: 7.0.0: consider integrating into AbstractMountPointContextFactory
33 public abstract class AbstractDynamicMountPointContextFactory extends AbstractSimpleIdentifiable<MountPointLabel>
34         implements MountPointContextFactory {
35     private static final Logger LOG = LoggerFactory.getLogger(AbstractDynamicMountPointContextFactory.class);
36
37     protected AbstractDynamicMountPointContextFactory(final @NonNull MountPointLabel label) {
38         super(label);
39     }
40
41     @Override
42     public final MountPointContext createContext(final Map<ContainerName, MountPointChild> libraryContainers,
43             final MountPointChild schemaMounts) throws MountPointException {
44
45         for (Entry<ContainerName, MountPointChild> entry : libraryContainers.entrySet()) {
46             // Context for the specific code word
47             final Optional<EffectiveModelContext> optLibContext = findSchemaForLibrary(entry.getKey());
48             if (optLibContext.isEmpty()) {
49                 LOG.debug("YANG Library context for mount point {} container {} not found", getIdentifier(),
50                     entry.getKey());
51                 continue;
52             }
53
54             final NormalizedNode libData;
55             try {
56                 libData = entry.getValue().normalizeTo(optLibContext.orElseThrow());
57             } catch (IOException e) {
58                 throw new MountPointException("Failed to interpret yang-library data", e);
59             }
60             if (!(libData instanceof ContainerNode libContainer)) {
61                 throw new MountPointException("Invalid yang-library non-container " + libData);
62             }
63
64             final EffectiveModelContext schemaContext = bindLibrary(entry.getKey(), libContainer);
65             if (schemaMounts == null) {
66                 return MountPointContext.of(schemaContext);
67             }
68
69             final NormalizedNode mountData;
70             try {
71                 mountData = schemaMounts.normalizeTo(schemaContext);
72             } catch (IOException e) {
73                 throw new MountPointException("Failed to interpret schema-mount data", e);
74             }
75             if (!(mountData instanceof ContainerNode)) {
76                 throw new MountPointException("Invalid schema-mount non-container " + mountData);
77             }
78
79             return createMountPointContext(schemaContext, (ContainerNode) mountData);
80         }
81
82         throw new MountPointException("Failed to interpret " + libraryContainers);
83     }
84
85     protected abstract @NonNull MountPointContext createMountPointContext(@NonNull EffectiveModelContext schemaContext,
86             @NonNull ContainerNode mountData);
87
88     /**
89      * Assemble the MountPointContext for specified normalized YANG Library top-level container.
90      *
91      * @param containerName Top-level YANG Library container
92      * @param libData Top-level YANG Library container data
93      * @return An assembled MountPointContext
94      * @throws NullPointerException if container is null
95      * @throws MountPointException if the schema context cannot be assembled
96      */
97     protected abstract @NonNull EffectiveModelContext bindLibrary(@NonNull ContainerName containerName,
98             @NonNull ContainerNode libData) throws MountPointException;
99
100     /**
101      * Return the schema in which YANG Library container content should be interpreted.
102      *
103      * <p>
104      * Note this schema is not guaranteed to contain any augmentations, hence parsing could fail.
105      *
106      * @param containerName Top-level YANG Library container name
107      * @return The LibraryContext to use when interpreting the specified YANG Library container, or empty
108      * @throws NullPointerException if container is null
109      */
110     protected abstract Optional<EffectiveModelContext> findSchemaForLibrary(@NonNull ContainerName containerName);
111 }