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