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