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.parser.stmt.rfc6020;
10 import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
13 import java.net.URISyntaxException;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.Date;
17 import java.util.Iterator;
18 import java.util.LinkedList;
19 import java.util.List;
20 import javax.annotation.Nullable;
21 import javax.xml.xpath.XPath;
22 import javax.xml.xpath.XPathExpressionException;
23 import javax.xml.xpath.XPathFactory;
24 import com.google.common.base.CharMatcher;
25 import com.google.common.base.Splitter;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import org.antlr.v4.runtime.tree.TerminalNode;
29 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser;
30 import org.opendaylight.yangtools.yang.common.QName;
31 import org.opendaylight.yangtools.yang.common.QNameModule;
32 import org.opendaylight.yangtools.yang.common.YangConstants;
33 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
34 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
35 import org.opendaylight.yangtools.yang.model.api.stmt.BelongsToStatement;
36 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
37 import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
38 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
39 import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement;
40 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
41 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
42 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleName;
43 import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
44 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName;
45 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
46 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
47 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
48 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
50 public final class Utils {
52 private static final Logger LOG = LoggerFactory.getLogger(Utils.class);
53 private static final CharMatcher DOUBLE_QUOTE_MATCHER = CharMatcher.is('"');
54 private static final CharMatcher SINGLE_QUOTE_MATCHER = CharMatcher.is('\'');
56 private static final char SEPARATOR_NODENAME = '/';
58 private static final String REGEX_PATH_ABS = "/[^/].*";
63 public static List<String> splitPathToNodeNames(String path) {
65 Splitter keySplitter = Splitter.on(SEPARATOR_NODENAME).omitEmptyStrings().trimResults();
66 return keySplitter.splitToList(path);
69 public static void validateXPath(String path) {
71 final XPath xPath = XPathFactory.newInstance().newXPath();
75 } catch (XPathExpressionException e) {
76 throw new IllegalArgumentException("Argument is not valid XPath string", e);
80 public static boolean isXPathAbsolute(String path) {
84 return path.matches(REGEX_PATH_ABS);
87 public static QName trimPrefix(QName identifier) {
88 String prefixedLocalName = identifier.getLocalName();
89 String[] namesParts = prefixedLocalName.split(":");
91 if (namesParts.length == 2) {
92 String localName = namesParts[1];
93 return QName.create(identifier.getModule(), localName);
99 public static boolean isValidStatementDefinition(PrefixToModule prefixes, QNameToStatementDefinition stmtDef,
101 if (stmtDef.get(identifier) != null) {
104 String prefixedLocalName = identifier.getLocalName();
105 String[] namesParts = prefixedLocalName.split(":");
107 if (namesParts.length == 2) {
108 String prefix = namesParts[0];
109 String localName = namesParts[1];
110 if (prefixes != null && prefixes.get(prefix) != null
111 && stmtDef.get(new QName(YangConstants.RFC6020_YIN_NAMESPACE, localName)) != null) {
119 public static Iterable<QName> parseXPath(StmtContext<?, ?, ?> ctx, String path) {
123 List<String> nodeNames = splitPathToNodeNames(path);
124 List<QName> qNames = new ArrayList<>();
126 for (String nodeName : nodeNames) {
128 final QName qName = Utils.qNameFromArgument(ctx, nodeName);
130 } catch (Exception e) {
131 throw new IllegalArgumentException(e);
138 public static String stringFromStringContext(final YangStatementParser.ArgumentContext context) {
139 StringBuilder sb = new StringBuilder();
140 List<TerminalNode> strings = context.STRING();
141 if (strings.isEmpty()) {
142 strings = Arrays.asList(context.IDENTIFIER());
144 for (TerminalNode stringNode : strings) {
145 final String str = stringNode.getText();
146 char firstChar = str.charAt(0);
147 final CharMatcher quoteMatcher;
148 if (SINGLE_QUOTE_MATCHER.matches(firstChar)) {
149 quoteMatcher = SINGLE_QUOTE_MATCHER;
150 } else if (DOUBLE_QUOTE_MATCHER.matches(firstChar)) {
151 quoteMatcher = DOUBLE_QUOTE_MATCHER;
156 sb.append(quoteMatcher.removeFrom(str.substring(1, str.length() - 1)));
158 return sb.toString();
161 public static QName qNameFromArgument(StmtContext<?, ?, ?> ctx, String value) {
164 QNameModule qNameModule = null;
166 qNameModule = QNameModule.create(new URI(""), new Date(0));
167 } catch (URISyntaxException e) {
168 LOG.warn(e.getMessage(), e);
170 String localName = null;
172 String[] namesParts = value.split(":");
173 switch (namesParts.length) {
175 localName = namesParts[0];
177 if (StmtContextUtils.producesDeclared(ctx.getRoot(), ModuleStatement.class)) {
178 prefix = firstAttributeOf(ctx.getRoot().declaredSubstatements(), PrefixStatement.class);
179 qNameModule = ctx.getFromNamespace(PrefixToModule.class, prefix);
181 } else if (StmtContextUtils.producesDeclared(ctx.getRoot(), SubmoduleStatement.class)) {
182 String belongsToModuleName = firstAttributeOf(ctx.getRoot().declaredSubstatements(),
183 BelongsToStatement.class);
184 qNameModule = ctx.getFromNamespace(ModuleNameToModuleQName.class, belongsToModuleName);
188 prefix = namesParts[0];
189 localName = namesParts[1];
191 ModuleIdentifier impModIdentifier = ctx.getRoot().getFromNamespace(ImpPrefixToModuleIdentifier.class,
193 qNameModule = ctx.getFromNamespace(ModuleIdentifierToModuleQName.class, impModIdentifier);
195 if (qNameModule == null && StmtContextUtils.producesDeclared(ctx.getRoot(), SubmoduleStatement.class)) {
196 String moduleName = ctx.getRoot().getFromNamespace(BelongsToPrefixToModuleName.class, prefix);
197 qNameModule = ctx.getFromNamespace(ModuleNameToModuleQName.class, moduleName);
205 return QName.create(qNameModule, localName);
209 private static StatementContextBase<?, ?, ?> findCtxOfNodeInSubstatements(
210 StatementContextBase<?, ?, ?> rootStmtCtx, final Iterable<QName> path, boolean searchInEffective) {
212 StatementContextBase<?, ?, ?> parent = rootStmtCtx;
214 Iterator<QName> pathIter = path.iterator();
215 QName targetNode = pathIter.next();
217 while (pathIter.hasNext()) {
219 for (StatementContextBase<?, ?, ?> child : searchInEffective ? parent.effectiveSubstatements() : parent
220 .declaredSubstatements()) {
222 if (targetNode.equals(child.getStatementArgument())) {
224 targetNode = pathIter.next();
228 if (parent.equals(rootStmtCtx)) {
234 StatementContextBase<?, ?, ?> targetCtx = null;
236 for (StatementContextBase<?, ?, ?> child : searchInEffective ? parent.effectiveSubstatements() : parent
237 .declaredSubstatements()) {
239 if (targetNode.equals(child.getStatementArgument())) {
248 public static StatementContextBase<?, ?, ?> findCtxOfNodeInRoot(StatementContextBase<?, ?, ?> rootStmtCtx,
249 final SchemaNodeIdentifier node) {
251 System.out.println(node.getPathFromRoot());
253 StatementContextBase<?, ?, ?> targetCtx = findCtxOfNodeInSubstatements(rootStmtCtx, node.getPathFromRoot(),
256 if (targetCtx == null) {
258 targetCtx = findCtxOfNodeInSubstatements(rootStmtCtx, node.getPathFromRoot(), true);
265 public static StatementContextBase<?, ?, ?> findCtxOfNodeInRoot(StatementContextBase<?, ?, ?> rootStmtCtx,
266 final Iterable<QName> path) {
268 StatementContextBase<?, ?, ?> targetCtx = findCtxOfNodeInSubstatements(rootStmtCtx, path, false);
270 if (targetCtx == null) {
272 targetCtx = findCtxOfNodeInSubstatements(rootStmtCtx, path, true);
278 public static SchemaPath getSchemaPath(StmtContext<?, ?, ?> ctx) {
280 Iterator<Object> argumentsIterator = ctx.getArgumentsFromRoot().iterator();
281 argumentsIterator.next(); // skip root argument
283 List<QName> qNamesFromRoot = new LinkedList<>();
285 while (argumentsIterator.hasNext()) {
286 Object argument = argumentsIterator.next();
287 if (argument instanceof QName) {
288 QName qname = (QName) argument;
289 qNamesFromRoot.add(qname);
291 return SchemaPath.SAME;
295 return SchemaPath.create(qNamesFromRoot, true);