2 * Copyright (c) 2016 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
9 package org.opendaylight.yangtools.yang.validator;
11 import com.google.common.base.Preconditions;
12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import java.io.FileFilter;
15 import java.io.FileNotFoundException;
16 import java.io.IOException;
17 import java.nio.charset.StandardCharsets;
18 import java.nio.file.Files;
19 import java.nio.file.Paths;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Locale;
26 import java.util.ServiceLoader;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30 import org.eclipse.jdt.annotation.NonNull;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.common.YangConstants;
33 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
34 import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
35 import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
36 import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
37 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
39 final class SystemTestUtils {
41 private static final Pattern MODULE_PATTERN = Pattern.compile("module(.*?)\\{");
42 private static final Pattern WHITESPACES = Pattern.compile("\\s+");
43 private static final @NonNull YangParserFactory PARSER_FACTORY;
46 final Iterator<@NonNull YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
48 throw new IllegalStateException("No YangParserFactory found");
50 PARSER_FACTORY = it.next();
53 private SystemTestUtils() {
54 throw new UnsupportedOperationException();
57 static final FileFilter YANG_FILE_FILTER = file -> {
58 final String name = file.getName().toLowerCase(Locale.ENGLISH);
59 return name.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION) && file.isFile();
62 static SchemaContext parseYangSources(final List<String> yangLibDirs, final List<String> yangTestFiles,
63 final Set<QName> supportedFeatures, final boolean recursiveSearch) throws IOException, YangParserException {
65 * Current dir "." should be always present implicitly in the list of
66 * directories where dependencies are searched for
68 if (!yangLibDirs.contains(".")) {
72 final List<File> libFiles = new ArrayList<>();
73 for (final String yangLibDir : yangLibDirs) {
74 libFiles.addAll(getYangFiles(yangLibDir, recursiveSearch));
77 final List<File> testFiles = new ArrayList<>();
78 for (final String yangTestFile : yangTestFiles) {
79 if (!yangTestFile.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION)) {
80 testFiles.add(findInFiles(libFiles, yangTestFile));
82 testFiles.add(new File(yangTestFile));
86 return parseYangSources(supportedFeatures, testFiles, libFiles);
89 static SchemaContext parseYangSources(final Set<QName> supportedFeatures, final List<File> testFiles,
90 final List<File> libFiles) throws IOException, YangParserException {
91 Preconditions.checkArgument(!testFiles.isEmpty(), "No yang sources");
93 final YangParser parser = PARSER_FACTORY.createParser();
94 if (supportedFeatures != null) {
95 parser.setSupportedFeatures(supportedFeatures);
98 for (File file : testFiles) {
99 parser.addSource(YangTextSchemaSource.forFile(file));
101 for (File file : libFiles) {
102 parser.addLibSource(YangTextSchemaSource.forFile(file));
105 return parser.buildSchemaContext();
108 private static File findInFiles(final List<File> libFiles, final String yangTestFile) throws IOException {
109 for (final File file : libFiles) {
110 if (WHITESPACES.matcher(getModelNameFromFile(file)).replaceAll("").equals(yangTestFile)) {
114 throw new FileNotFoundException("Model with specific module-name does not exist : " + yangTestFile);
117 private static String getModelNameFromFile(final File file) throws IOException {
118 final String fileAsString = readFile(file.getAbsolutePath());
119 final Matcher matcher = MODULE_PATTERN.matcher(fileAsString);
120 return matcher.find() ? matcher.group(1) : "";
123 private static String readFile(final String path) throws IOException {
124 return new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
127 @SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE")
128 private static Collection<File> getYangFiles(final String yangSourcesDirectoryPath, final boolean recursiveSearch)
129 throws FileNotFoundException {
130 final File testSourcesDir = new File(yangSourcesDirectoryPath);
131 if (!testSourcesDir.isDirectory()) {
132 throw new FileNotFoundException(String.format("%s no such directory", yangSourcesDirectoryPath));
135 return recursiveSearch ? searchYangFiles(testSourcesDir)
136 : Arrays.asList(testSourcesDir.listFiles(YANG_FILE_FILTER));
139 @SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE")
140 private static List<File> searchYangFiles(final File dir) {
141 Preconditions.checkNotNull(dir);
142 Preconditions.checkArgument(dir.isDirectory(), "File %s is not a directory", dir.getPath());
144 final List<File> yangFiles = new ArrayList<>();
145 for (final File file : dir.listFiles()) {
146 if (file.isDirectory()) {
147 yangFiles.addAll(searchYangFiles(file));
148 } else if (file.isFile()
149 && file.getName().toLowerCase(Locale.ENGLISH).endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION)) {