2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.data.impl.leafref;
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.Lists;
13 import java.util.ArrayList;
14 import java.util.Date;
15 import java.util.List;
16 import java.util.Optional;
17 import org.antlr.v4.runtime.tree.TerminalNode;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.common.QNameModule;
20 import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.IdentifierContext;
21 import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Node_identifierContext;
22 import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_argContext;
23 import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_equality_exprContext;
24 import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_predicateContext;
25 import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.PrefixContext;
26 import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Rel_path_keyexprContext;
27 import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Relative_pathContext;
28 import org.opendaylight.yangtools.yang.model.api.Module;
29 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
30 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
31 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
33 final class LeafRefPathParserListenerImpl extends LeafRefPathParserBaseListener {
35 private final List<QNameWithPredicateBuilder> leafRefPathQnameList = new ArrayList<>();
36 private final SchemaContext schemaContext;
37 private final Module module;
38 // FIXME: use for identifier path completion
39 private final SchemaNode node;
41 private ParsingState currentParsingState = ParsingState.LEAF_REF_PATH;
42 private List<QNameWithPredicateBuilder> predicatePathKeyQnameList;
43 private QNameWithPredicateBuilder currentLeafRefPathQName;
44 private QNamePredicateBuilder currentPredicate;
45 private QNameModule currentQnameModule;
46 private String currentQNameLocalName;
47 private LeafRefPath leafRefPath;
48 private boolean relativePath = false;
50 private enum ParsingState {
51 LEAF_REF_PATH, PATH_PREDICATE, PREDICATE_PATH_EQUALITY_EXPR, PATH_KEY_EXPR
54 LeafRefPathParserListenerImpl(final SchemaContext schemaContext, final Module currentModule,
55 final SchemaNode currentNode) {
56 this.schemaContext = schemaContext;
57 this.module = currentModule;
58 this.node = currentNode;
62 public void enterPath_predicate(final Path_predicateContext ctx) {
63 currentParsingState = ParsingState.PATH_PREDICATE;
64 currentPredicate = new QNamePredicateBuilder();
68 public void exitPath_predicate(final Path_predicateContext ctx) {
69 currentLeafRefPathQName.addQNamePredicate(currentPredicate.build());
70 currentPredicate = null;
71 currentParsingState = ParsingState.LEAF_REF_PATH;
76 public void enterRel_path_keyexpr(final Rel_path_keyexprContext ctx) {
77 currentParsingState = ParsingState.PATH_KEY_EXPR;
79 final List<TerminalNode> dots = ctx.DOTS();
80 predicatePathKeyQnameList = new ArrayList<>(dots.size());
81 for (int i = 0; i < dots.size(); ++i) {
82 predicatePathKeyQnameList.add(QNameWithPredicateBuilder.UP_PARENT_BUILDER);
87 public void exitRel_path_keyexpr(final Rel_path_keyexprContext ctx) {
88 final LeafRefPath pathKeyExpression = LeafRefPath.create(Lists.transform(predicatePathKeyQnameList,
89 QNameWithPredicateBuilder::build), false);
90 currentPredicate.setPathKeyExpression(pathKeyExpression);
92 currentParsingState = ParsingState.PREDICATE_PATH_EQUALITY_EXPR;
96 public void enterRelative_path(final Relative_pathContext ctx) {
98 final List<TerminalNode> dots = ctx.DOTS();
99 for (int i = 0; i < dots.size(); ++i) {
100 leafRefPathQnameList.add(QNameWithPredicateBuilder.UP_PARENT_BUILDER);
105 public void enterPath_equality_expr(final Path_equality_exprContext ctx) {
106 currentParsingState = ParsingState.PREDICATE_PATH_EQUALITY_EXPR;
110 public void exitPath_equality_expr(final Path_equality_exprContext ctx) {
111 currentParsingState = ParsingState.PATH_PREDICATE;
115 public void enterPrefix(final PrefixContext ctx) {
116 final String prefix = ctx.getText();
117 if (!module.getPrefix().equals(prefix)) {
118 final Optional<QNameModule> qnameModuleOpt = getQNameModuleForImportPrefix(prefix);
119 Preconditions.checkArgument(qnameModuleOpt.isPresent(), "No module import for prefix: %s in module: %s",
120 prefix, module.getName());
121 currentQnameModule = qnameModuleOpt.get();
123 currentQnameModule = module.getQNameModule();
128 public void exitPath_arg(final Path_argContext ctx) {
129 leafRefPath = LeafRefPath.create(Lists.transform(leafRefPathQnameList, QNameWithPredicateBuilder::build),
134 public void enterIdentifier(final IdentifierContext ctx) {
135 currentQNameLocalName = ctx.getText();
139 public void exitNode_identifier(final Node_identifierContext ctx) {
140 if (currentQnameModule == null) {
141 currentQnameModule = module.getQNameModule();
144 if (currentParsingState == ParsingState.PREDICATE_PATH_EQUALITY_EXPR) {
145 currentPredicate.setIdentifier(QName.create(currentQnameModule, currentQNameLocalName));
147 final QNameWithPredicateBuilder qnameBuilder = new QNameWithPredicateBuilder(currentQnameModule,
148 currentQNameLocalName);
150 if (currentParsingState == ParsingState.PATH_KEY_EXPR) {
151 predicatePathKeyQnameList.add(qnameBuilder);
152 } else if (currentParsingState == ParsingState.LEAF_REF_PATH) {
153 currentLeafRefPathQName = qnameBuilder;
154 leafRefPathQnameList.add(qnameBuilder);
157 currentQnameModule = null;
158 currentQNameLocalName = null;
161 public LeafRefPath getLeafRefPath() {
165 private URI getNamespaceForImportPrefix(final String prefix) {
166 final ModuleImport moduleImport = getModuleImport(prefix);
167 final Module findedModule = schemaContext.findModuleByName(moduleImport.getModuleName(),
168 moduleImport.getRevision());
170 return findedModule.getNamespace();
173 private Optional<QNameModule> getQNameModuleForImportPrefix(final String prefix) {
174 final ModuleImport moduleImport = getModuleImport(prefix);
175 if (moduleImport == null) {
176 return Optional.empty();
179 final String moduleName = moduleImport.getModuleName();
180 final Date revision = moduleImport.getRevision();
181 final Module foundModule = schemaContext.findModuleByName(moduleName, revision);
183 return Optional.of(foundModule.getQNameModule());
186 private ModuleImport getModuleImport(final String prefix) {
187 return module.getImports().stream().filter(imp -> prefix.equals(imp.getPrefix())).findFirst().orElse(null);