aba479bba015fbe9a09b31df599f80c553fa30a3
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / repo / ASTSchemaSource.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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.parser.rfc7950.repo;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import java.util.Optional;
14 import javax.annotation.Nonnull;
15 import javax.annotation.Nullable;
16 import org.antlr.v4.runtime.ParserRuleContext;
17 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
18 import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
19 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
20 import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier;
21 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
22
23 /**
24  * Abstract Syntax Tree representation of a schema source. This representation is internal to the YANG parser
25  * implementation, as it relies on ANTLR types.
26  *
27  * <p>
28  * Instances of this representation are used for caching purposes, as they are a natural intermediate step in YANG text
29  * processing pipeline: the text has been successfully parsed, so we know it is syntactically correct. It also passes
30  * basic semantic validation and we were able to extract dependency information.
31  */
32 @Beta
33 public final class ASTSchemaSource implements SchemaSourceRepresentation {
34     private final YangModelDependencyInfo depInfo;
35     private final SemVerSourceIdentifier semVerId;
36     private final ParserRuleContext tree;
37     private final SourceIdentifier id;
38     private final String symbolicName;
39
40     private ASTSchemaSource(@Nonnull final SourceIdentifier id, @Nonnull final SemVerSourceIdentifier semVerId,
41             @Nonnull final ParserRuleContext tree, @Nonnull final YangModelDependencyInfo depInfo,
42             @Nullable final String symbolicName) {
43         this.depInfo = requireNonNull(depInfo);
44         this.tree = requireNonNull(tree);
45         this.id = requireNonNull(id);
46         this.semVerId = requireNonNull(semVerId);
47         this.symbolicName = symbolicName;
48     }
49
50     /**
51      * Create a new instance of AST representation for a abstract syntax tree, performing minimal semantic analysis
52      * to acquire dependency information.
53      *
54      * @param symbolicName
55      *            Symbolic name
56      * @param identifier
57      *            SourceIdentifier of YANG schema source.
58      * @param tree
59      *            ANTLR abstract syntax tree
60      * @return A new representation instance.
61      * @throws YangSyntaxErrorException
62      *             if we fail to extract dependency information.
63      */
64     static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier,
65             @Nullable final String symbolicName, @Nonnull final ParserRuleContext tree)
66                     throws YangSyntaxErrorException {
67         final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(identifier, tree);
68         final SourceIdentifier id = getSourceId(depInfo);
69
70         final SemVerSourceIdentifier semVerId;
71         if (identifier instanceof SemVerSourceIdentifier && !depInfo.getSemanticVersion().isPresent()) {
72             semVerId = (SemVerSourceIdentifier) identifier;
73         } else {
74             semVerId = getSemVerSourceId(depInfo);
75         }
76
77         return new ASTSchemaSource(id, semVerId, tree, depInfo, symbolicName);
78     }
79
80
81     @Override
82     public SourceIdentifier getIdentifier() {
83         return id;
84     }
85
86     @Override
87     public Optional<String> getSymbolicName() {
88         return Optional.ofNullable(symbolicName);
89     }
90
91     public SemVerSourceIdentifier getSemVerIdentifier() {
92         return semVerId;
93     }
94
95     @Nonnull
96     @Override
97     public Class<? extends SchemaSourceRepresentation> getType() {
98         return ASTSchemaSource.class;
99     }
100
101     /**
102      * Return the underlying abstract syntax tree.
103      *
104      * @return Underlying AST.
105      */
106     @Nonnull public ParserRuleContext getAST() {
107         return tree;
108     }
109
110     /**
111      * Return the dependency information as extracted from the AST.
112      *
113      * @return Dependency information.
114      */
115     // FIXME: this method should be extracted into a public interface in the model.api.repo class, relying solely
116     //        on model.api types.
117     @Nonnull public YangModelDependencyInfo getDependencyInformation() {
118         return depInfo;
119     }
120
121     private static SourceIdentifier getSourceId(final YangModelDependencyInfo depInfo) {
122         final String name = depInfo.getName();
123         return depInfo.getFormattedRevision() == null ? RevisionSourceIdentifier.create(name)
124                 : RevisionSourceIdentifier.create(name, depInfo.getRevision());
125     }
126
127     private static SemVerSourceIdentifier getSemVerSourceId(final YangModelDependencyInfo depInfo) {
128         return depInfo.getFormattedRevision() == null
129                 ? SemVerSourceIdentifier.create(depInfo.getName(), depInfo.getSemanticVersion().orElse(null))
130                         : SemVerSourceIdentifier.create(depInfo.getName(), depInfo.getRevision(),
131                             depInfo.getSemanticVersion().orElse(null));
132     }
133 }