Fix odlparent-3-detected checkstyle issues
[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.List;
23 import java.util.Set;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.common.YangConstants;
28 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
29 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
30 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
31 import org.opendaylight.yangtools.yang.parser.rfc6020.repo.YangStatementStreamSource;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
33 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
34 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
35 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
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
42     private SystemTestUtils() {
43         throw new UnsupportedOperationException();
44     }
45
46     static final FileFilter YANG_FILE_FILTER = file -> {
47         final String name = file.getName().toLowerCase();
48         return name.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION) && file.isFile();
49     };
50
51     static SchemaContext parseYangSources(final List<String> yangLibDirs, final List<String> yangTestFiles,
52             final Set<QName> supportedFeatures, final boolean recursiveSearch)
53             throws ReactorException, IOException, YangSyntaxErrorException {
54         /*
55          * Current dir "." should be always present implicitly in the list of
56          * directories where dependencies are searched for
57          */
58         if (!yangLibDirs.contains(".")) {
59             yangLibDirs.add(".");
60         }
61
62         final List<File> libFiles = new ArrayList<>();
63         for (final String yangLibDir : yangLibDirs) {
64             libFiles.addAll(getYangFiles(yangLibDir, recursiveSearch));
65         }
66
67         final List<File> testFiles = new ArrayList<>();
68         for (final String yangTestFile : yangTestFiles) {
69             if (!yangTestFile.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION)) {
70                 testFiles.add(findInFiles(libFiles, yangTestFile));
71             } else {
72                 testFiles.add(new File(yangTestFile));
73             }
74         }
75
76         return parseYangSources(supportedFeatures, testFiles, libFiles);
77     }
78
79     static SchemaContext parseYangSources(final Set<QName> supportedFeatures, final List<File> testFiles,
80             final List<File> libFiles) throws ReactorException, IOException, YangSyntaxErrorException {
81         final List<StatementStreamSource> testSources = getYangStatementSources(testFiles);
82         final List<StatementStreamSource> libSources = getYangStatementSources(libFiles);
83         return parseYangSources(testSources, libSources, supportedFeatures);
84     }
85
86     static SchemaContext parseYangSources(final List<StatementStreamSource> testSources,
87             final List<StatementStreamSource> libSources, final Set<QName> supportedFeatures) throws ReactorException {
88         Preconditions.checkArgument(testSources != null && !testSources.isEmpty(), "No yang sources");
89
90         final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
91         reactor.addLibSources(libSources);
92         reactor.addSources(testSources);
93
94         if (supportedFeatures != null) {
95             reactor.setSupportedFeatures(supportedFeatures);
96         }
97
98         return reactor.buildEffective();
99     }
100
101     private static File findInFiles(final List<File> libFiles, final String yangTestFile) throws IOException {
102         for (final File file : libFiles) {
103             if (WHITESPACES.matcher(getModelNameFromFile(file)).replaceAll("").equals(yangTestFile)) {
104                 return file;
105             }
106         }
107         throw new FileNotFoundException("Model with specific module-name does not exist : " + yangTestFile);
108     }
109
110     private static String getModelNameFromFile(final File file) throws IOException {
111         final String fileAsString = readFile(file.getAbsolutePath());
112         final Matcher matcher = MODULE_PATTERN.matcher(fileAsString);
113         if (matcher.find()) {
114             return matcher.group(1);
115         } else {
116             return "";
117         }
118     }
119
120     private static String readFile(final String path) throws IOException {
121         return new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
122     }
123
124     private static List<StatementStreamSource> getYangStatementSources(final List<File> yangFiles)
125             throws IOException, YangSyntaxErrorException {
126         final List<StatementStreamSource> yangSources = new ArrayList<>(yangFiles.size());
127         for (final File file : yangFiles) {
128             yangSources.add(YangStatementStreamSource.create(YangTextSchemaSource.forFile(file)));
129         }
130         return yangSources;
131     }
132
133     private static Collection<File> getYangFiles(final String yangSourcesDirectoryPath, final boolean recursiveSearch)
134             throws FileNotFoundException {
135         final File testSourcesDir = new File(yangSourcesDirectoryPath);
136         if (!testSourcesDir.isDirectory()) {
137             throw new FileNotFoundException(String.format("%s no such directory", yangSourcesDirectoryPath));
138         }
139
140         return recursiveSearch ? searchYangFiles(testSourcesDir)
141             : Arrays.asList(testSourcesDir.listFiles(YANG_FILE_FILTER));
142     }
143
144     private static List<File> searchYangFiles(final File dir) {
145         Preconditions.checkNotNull(dir);
146         Preconditions.checkArgument(dir.isDirectory(), "File %s is not a directory", dir.getPath());
147
148         final List<File> yangFiles = new ArrayList<>();
149         for (final File file : dir.listFiles()) {
150             if (file.isDirectory()) {
151                 yangFiles.addAll(searchYangFiles(file));
152             } else if (file.isFile()
153                     && file.getName().toLowerCase().endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION)) {
154                 yangFiles.add(file);
155             }
156         }
157
158         return yangFiles;
159     }
160 }