fda0a17581840c7e210ca85ca47a85f6c9b35a74
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / util / 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.util;
9
10 import static org.opendaylight.yangtools.yang.model.api.Module.DEFAULT_SEMANTIC_VERSION;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.Function;
14 import com.google.common.base.Preconditions;
15 import java.util.Optional;
16 import javax.annotation.Nonnull;
17 import javax.annotation.Nullable;
18 import org.antlr.v4.runtime.ParserRuleContext;
19 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
20 import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
21 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
22 import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier;
23 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
24 import org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo;
25
26 /**
27  * Abstract Syntax Tree representation of a schema source. This representation is internal to the YANG parser
28  * implementation, as it relies on ANTLR types.
29  *
30  * <p>
31  * Instances of this representation are used for caching purposes, as they are a natural intermediate step in YANG text
32  * processing pipeline: the text has been successfully parsed, so we know it is syntactically correct. It also passes
33  * basic semantic validation and we were able to extract dependency information.
34  */
35 @Beta
36 public final class ASTSchemaSource implements SchemaSourceRepresentation {
37     @Deprecated
38     public static final Function<ASTSchemaSource, SourceIdentifier> GET_IDENTIFIER =
39         ASTSchemaSource::getIdentifier;
40     @Deprecated
41     public static final Function<ASTSchemaSource, SourceIdentifier> GET_SEMVER_IDENTIFIER =
42         ASTSchemaSource::getSemVerIdentifier;
43     @Deprecated
44     public static final Function<ASTSchemaSource, YangModelDependencyInfo> GET_DEPINFO =
45         ASTSchemaSource::getDependencyInformation;
46     @Deprecated
47     public static final Function<ASTSchemaSource, ParserRuleContext> GET_AST = ASTSchemaSource::getAST;
48
49     private final YangModelDependencyInfo depInfo;
50     private final SemVerSourceIdentifier semVerId;
51     private final ParserRuleContext tree;
52     private final SourceIdentifier id;
53     private final String symbolicName;
54
55     private ASTSchemaSource(@Nonnull final SourceIdentifier id, @Nonnull final SemVerSourceIdentifier semVerId,
56             @Nonnull final ParserRuleContext tree, @Nonnull final YangModelDependencyInfo depInfo,
57             @Nullable final String symbolicName) {
58         this.depInfo = Preconditions.checkNotNull(depInfo);
59         this.tree = Preconditions.checkNotNull(tree);
60         this.id = Preconditions.checkNotNull(id);
61         this.semVerId = Preconditions.checkNotNull(semVerId);
62         this.symbolicName = symbolicName;
63     }
64
65     /**
66      * Create a new instance of AST representation for a abstract syntax tree,
67      * performing minimal semantic analysis to acquire dependency information.
68      *
69      * @param name YANG source name. Used only for error reporting.
70      * @param tree ANTLR abstract syntax tree
71      * @return A new representation instance.
72      * @throws YangSyntaxErrorException if we fail to extract dependency information.
73      */
74     public static ASTSchemaSource create(@Nonnull final String name, @Nonnull final ParserRuleContext tree)
75             throws YangSyntaxErrorException {
76         final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(name, tree);
77         final SourceIdentifier id = getSourceId(depInfo);
78         final SemVerSourceIdentifier semVerId = getSemVerSourceId(depInfo);
79         return new ASTSchemaSource(id, semVerId, tree, depInfo, null);
80     }
81
82     /**
83      * Create a new instance of AST representation for a abstract syntax tree,
84      * performing minimal semantic analysis to acquire dependency information.
85      *
86      * @param identifier
87      *            SourceIdentifier of yang schema source.
88      * @param tree
89      *            ANTLR abstract syntax tree
90      * @param text
91      *            YANG text source
92      * @return A new representation instance.
93      * @throws YangSyntaxErrorException
94      *             if we fail to extract dependency information.
95      *
96      * @deprecated Use {@link #create(SourceIdentifier, ParserRuleContext)} instead.
97      */
98     @Deprecated
99     public static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier,
100             @Nonnull final ParserRuleContext tree, final String text) throws YangSyntaxErrorException {
101         return create(identifier, tree);
102     }
103
104     /**
105      * Create a new instance of AST representation for a abstract syntax tree, performing minimal semantic analysis
106      * to acquire dependency information.
107      *
108      * @param identifier
109      *            SourceIdentifier of yang schema source.
110      * @param tree
111      *            ANTLR abstract syntax tree
112      * @return A new representation instance.
113      * @throws YangSyntaxErrorException
114      *             if we fail to extract dependency information.
115      */
116     public static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier,
117             @Nonnull final ParserRuleContext tree) throws YangSyntaxErrorException {
118         return create(identifier, null, tree);
119     }
120
121     /**
122      * Create a new instance of AST representation for a abstract syntax tree, performing minimal semantic analysis
123      * to acquire dependency information.
124      *
125      * @param symbolicName
126      *            Symbolic name
127      * @param identifier
128      *            SourceIdentifier of yang schema source.
129      * @param tree
130      *            ANTLR abstract syntax tree
131      * @return A new representation instance.
132      * @throws YangSyntaxErrorException
133      *             if we fail to extract dependency information.
134      */
135     public static ASTSchemaSource create(@Nonnull final String symbolicName, @Nonnull final SourceIdentifier identifier,
136             @Nonnull final ParserRuleContext tree) throws YangSyntaxErrorException {
137         return create(identifier, symbolicName, tree);
138     }
139
140     private static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier,
141             @Nullable final String symbolicName, @Nonnull final ParserRuleContext tree)
142                     throws YangSyntaxErrorException {
143         final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(identifier.getName(), tree);
144         final SourceIdentifier id = getSourceId(depInfo);
145
146         final SemVerSourceIdentifier semVerId;
147         if (identifier instanceof SemVerSourceIdentifier && !depInfo.getSemanticVersion().isPresent()) {
148             semVerId = (SemVerSourceIdentifier) identifier;
149         } else {
150             semVerId = getSemVerSourceId(depInfo);
151         }
152
153         return new ASTSchemaSource(id, semVerId, tree, depInfo, symbolicName);
154     }
155
156
157     @Override
158     public SourceIdentifier getIdentifier() {
159         return id;
160     }
161
162     @Override
163     public Optional<String> getSymbolicName() {
164         return Optional.ofNullable(symbolicName);
165     }
166
167     public SemVerSourceIdentifier getSemVerIdentifier() {
168         return semVerId;
169     }
170
171     @Nonnull
172     @Override
173     public Class<? extends SchemaSourceRepresentation> getType() {
174         return ASTSchemaSource.class;
175     }
176
177     /**
178      * Return the underlying abstract syntax tree.
179      *
180      * @return Underlying AST.
181      */
182     @Nonnull public ParserRuleContext getAST() {
183         return tree;
184     }
185
186     /**
187      * Return the dependency information as extracted from the AST.
188      *
189      * @return Dependency information.
190      */
191     // FIXME: this method should be extracted into a public interface in the model.api.repo class, relying solely
192     //        on model.api types.
193     @Nonnull public YangModelDependencyInfo getDependencyInformation() {
194         return depInfo;
195     }
196
197     private static SourceIdentifier getSourceId(final YangModelDependencyInfo depInfo) {
198         final String name = depInfo.getName();
199         return depInfo.getFormattedRevision() == null ? RevisionSourceIdentifier.create(name)
200                 : RevisionSourceIdentifier.create(name, depInfo.getFormattedRevision());
201     }
202
203     private static SemVerSourceIdentifier getSemVerSourceId(final YangModelDependencyInfo depInfo) {
204         return depInfo.getFormattedRevision() == null
205                 ? SemVerSourceIdentifier.create(depInfo.getName(),
206                     depInfo.getSemanticVersion().or(DEFAULT_SEMANTIC_VERSION))
207                         : SemVerSourceIdentifier.create(depInfo.getName(), depInfo.getFormattedRevision(),
208                             depInfo.getSemanticVersion().or(DEFAULT_SEMANTIC_VERSION));
209     }
210 }