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