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
8 package org.opendaylight.yangtools.yang.test.util;
10 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 import java.io.FileFilter;
13 import java.io.IOException;
15 import java.net.URISyntaxException;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collection;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Locale;
22 import java.util.ServiceLoader;
24 import org.eclipse.jdt.annotation.NonNull;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.common.YangConstants;
27 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
28 import org.opendaylight.yangtools.yang.model.api.source.SourceRepresentation;
29 import org.opendaylight.yangtools.yang.model.api.stmt.FeatureSet;
30 import org.opendaylight.yangtools.yang.model.spi.source.FileYangTextSource;
31 import org.opendaylight.yangtools.yang.model.spi.source.URLYangTextSource;
32 import org.opendaylight.yangtools.yang.model.spi.source.YangTextSource;
33 import org.opendaylight.yangtools.yang.parser.api.YangParser;
34 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
35 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
36 import org.opendaylight.yangtools.yang.parser.api.YangParserFactory;
37 import org.opendaylight.yangtools.yang.parser.api.YangSyntaxErrorException;
40 * Utility class which provides convenience methods for producing effective schema context based on the supplied
41 * YANG/YIN sources or paths to these sources.
43 public final class YangParserTestUtils {
44 private static final FileFilter YANG_FILE_FILTER = file -> {
45 // Locale keeps SpotBugs happy. It should not matter that much anyway.
46 final String name = file.getName().toLowerCase(Locale.ENGLISH);
47 return name.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION) && file.isFile();
50 private static final @NonNull YangParserFactory PARSER_FACTORY;
53 final Iterator<@NonNull YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
55 throw new IllegalStateException("No YangParserFactory found");
57 PARSER_FACTORY = it.next();
60 private YangParserTestUtils() {
65 * Creates a new effective schema context containing the specified YANG source. Statement parser mode is set to
66 * default mode and all YANG features are supported.
68 * @param resource relative path to the YANG file to be parsed
70 * @return effective schema context
72 public static EffectiveModelContext parseYangResource(final String resource) {
73 return parseYangResource(resource, YangParserConfiguration.DEFAULT);
77 * Creates a new effective schema context containing the specified YANG source. All YANG features are supported.
79 * @param resource relative path to the YANG file to be parsed
80 * @param config parser configuration
81 * @return effective schema context
83 public static EffectiveModelContext parseYangResource(final String resource, final YangParserConfiguration config) {
84 return parseYangResource(resource, config, null);
88 * Creates a new effective schema context containing the specified YANG source. Statement parser mode is set to
91 * @param resource relative path to the YANG file to be parsed
92 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
94 * @return effective schema context
96 public static EffectiveModelContext parseYangResource(final String resource, final Set<QName> supportedFeatures) {
97 return parseYangResource(resource, YangParserConfiguration.DEFAULT, supportedFeatures);
101 * Creates a new effective schema context containing the specified YANG source.
103 * @param resource relative path to the YANG file to be parsed
104 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
106 * @param config parser configuration
107 * @return effective schema context
109 public static EffectiveModelContext parseYangResource(final String resource, final YangParserConfiguration config,
110 final Set<QName> supportedFeatures) {
111 return parseYangSources(config, supportedFeatures,
112 new URLYangTextSource(YangParserTestUtils.class.getResource(resource)));
116 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
117 * default mode and all YANG features are supported.
119 * @param files YANG files to be parsed
120 * @return effective schema context
122 public static EffectiveModelContext parseYangFiles(final File... files) {
123 return parseYangFiles(Arrays.asList(files));
127 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
128 * default mode and all YANG features are supported.
130 * @param files collection of YANG files to be parsed
131 * @return effective schema context
133 public static EffectiveModelContext parseYangFiles(final Collection<File> files) {
134 return parseYangFiles(YangParserConfiguration.DEFAULT, files);
138 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
141 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
142 * models are resolved
143 * @param files YANG files to be parsed
144 * @return effective schema context
146 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures, final File... files) {
147 return parseYangFiles(supportedFeatures, Arrays.asList(files));
150 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
151 final Collection<File> files) {
152 return parseYangFiles(supportedFeatures, YangParserConfiguration.DEFAULT, files);
156 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
158 * @param config parser configuration
159 * @param files YANG files to be parsed
160 * @return effective schema context
162 public static EffectiveModelContext parseYangFiles(final YangParserConfiguration config, final File... files) {
163 return parseYangFiles(config, Arrays.asList(files));
167 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
169 * @param config parser configuration
170 * @param files collection of YANG files to be parsed
171 * @return effective schema context
173 public static EffectiveModelContext parseYangFiles(final YangParserConfiguration config,
174 final Collection<File> files) {
175 return parseYangFiles(null, config, files);
179 * Creates a new effective schema context containing the specified YANG sources.
181 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
182 * models are resolved
183 * @param config parser configuration
184 * @param files YANG files to be parsed
185 * @return effective schema context
187 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
188 final YangParserConfiguration config, final File... files) {
189 return parseYangFiles(supportedFeatures, config, Arrays.asList(files));
193 * Creates a new effective schema context containing the specified YANG sources.
195 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
196 * models are resolved
197 * @param config parser configuration
198 * @param files YANG files to be parsed
199 * @return effective schema context
201 // FIXME: use Java.nio.file.Path
202 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
203 final YangParserConfiguration config, final Collection<File> files) {
204 return parseSources(config, supportedFeatures,
205 files.stream().map(file -> new FileYangTextSource(file.toPath())).toList());
209 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
210 * default mode and all YANG features are supported.
212 * @param resourcePath relative path to the directory with YANG files to be parsed
213 * @return effective schema context
215 public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath) {
216 return parseYangResourceDirectory(resourcePath, YangParserConfiguration.DEFAULT);
220 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
222 * @param resourcePath relative path to the directory with YANG files to be parsed
223 * @param config parser configuration
224 * @return effective schema context
226 public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
227 final YangParserConfiguration config) {
228 return parseYangResourceDirectory(resourcePath, null, config);
232 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
235 * @param resourcePath relative path to the directory with YANG files to be parsed
236 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
237 * models are resolved
238 * @return effective schema context
240 public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
241 final Set<QName> supportedFeatures) {
242 return parseYangResourceDirectory(resourcePath, supportedFeatures, YangParserConfiguration.DEFAULT);
246 * Creates a new effective schema context containing the specified YANG sources.
248 * @param resourcePath relative path to the directory with YANG files to be parsed
249 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
250 * models are resolved
251 * @param config parser configuration
252 * @return effective schema context
254 @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Wrong inferent on listFiles")
255 public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
256 final Set<QName> supportedFeatures, final YangParserConfiguration config) {
257 final URI directoryPath;
259 directoryPath = YangParserTestUtils.class.getResource(resourcePath).toURI();
260 } catch (URISyntaxException e) {
261 throw new IllegalArgumentException("Failed to open resource " + resourcePath, e);
263 return parseYangFiles(supportedFeatures, config, new File(directoryPath).listFiles(YANG_FILE_FILTER));
267 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
268 * default mode and all YANG features are supported.
270 * @param clazz Resource lookup base
271 * @param resources Resource names to be looked up
272 * @return effective schema context
274 public static EffectiveModelContext parseYangResources(final Class<?> clazz, final String... resources) {
275 return parseYangResources(clazz, Arrays.asList(resources));
278 public static EffectiveModelContext parseYangResources(final Class<?> clazz, final Collection<String> resources) {
279 return parseSources(YangParserConfiguration.DEFAULT, null, resources.stream()
280 .map(resource -> new URLYangTextSource(clazz.getResource(resource)))
285 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
288 * @param yangDirs relative paths to the directories containing YANG files to be parsed
289 * @param yangFiles relative paths to the YANG files to be parsed
290 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
291 * models are resolved
292 * @return effective schema context
294 public static EffectiveModelContext parseYangResources(final List<String> yangDirs, final List<String> yangFiles,
295 final Set<QName> supportedFeatures) {
296 return parseYangResources(yangDirs, yangFiles, supportedFeatures, YangParserConfiguration.DEFAULT);
300 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
302 * @param yangResourceDirs relative paths to the directories containing YANG files to be parsed
303 * @param yangResources relative paths to the YANG files to be parsed
304 * @param config parser configuration
305 * @return effective schema context
307 public static EffectiveModelContext parseYangResources(final List<String> yangResourceDirs,
308 final List<String> yangResources, final YangParserConfiguration config) {
309 return parseYangResources(yangResourceDirs, yangResources, null, config);
313 * Creates a new effective schema context containing the specified YANG sources.
315 * @param yangResourceDirs relative paths to the directories containing YANG files to be parsed
316 * @param yangResources relative paths to the YANG files to be parsed
317 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
318 * models are resolved
319 * @param config parser configuration
320 * @return effective schema context
322 public static EffectiveModelContext parseYangResources(final List<String> yangResourceDirs,
323 final List<String> yangResources, final Set<QName> supportedFeatures,
324 final YangParserConfiguration config) {
325 final List<File> allYangFiles = new ArrayList<>();
326 for (final String yangDir : yangResourceDirs) {
327 allYangFiles.addAll(getYangFiles(yangDir));
330 for (final String yangFile : yangResources) {
332 allYangFiles.add(new File(YangParserTestUtils.class.getResource(yangFile).toURI()));
333 } catch (URISyntaxException e) {
334 throw new IllegalArgumentException("Invalid resource " + yangFile, e);
338 return parseYangFiles(supportedFeatures, config, allYangFiles);
341 public static EffectiveModelContext parseYangSources(final YangParserConfiguration config,
342 final Set<QName> supportedFeatures, final YangTextSource... sources) {
343 return parseSources(config, supportedFeatures, Arrays.asList(sources));
346 public static EffectiveModelContext parseSources(final YangParserConfiguration config,
347 final Set<QName> supportedFeatures, final Collection<? extends SourceRepresentation> sources) {
348 final YangParser parser = PARSER_FACTORY.createParser(config);
349 if (supportedFeatures != null) {
350 parser.setSupportedFeatures(FeatureSet.of(supportedFeatures));
354 parser.addSources(sources);
355 } catch (YangSyntaxErrorException e) {
356 throw new IllegalArgumentException("Malformed source", e);
357 } catch (IOException e) {
358 throw new IllegalArgumentException("Failed to read a source", e);
362 return parser.buildEffectiveModel();
363 } catch (YangParserException e) {
364 throw new IllegalStateException("Failed to assemble SchemaContext", e);
369 * Creates a new effective schema context containing the specified YANG sources.
371 * @param sources list of yang sources in plain string
372 * @return effective schema context
374 public static EffectiveModelContext parseYang(final String... sources) {
375 return parseSources(YangParserConfiguration.DEFAULT, null,
376 Arrays.stream(sources).map(LiteralYangTextSource::ofLiteral).toList());
379 @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Wrong inferent on listFiles")
380 private static Collection<File> getYangFiles(final String resourcePath) {
381 final URI directoryPath;
383 directoryPath = YangParserTestUtils.class.getResource(resourcePath).toURI();
384 } catch (URISyntaxException e) {
385 throw new IllegalArgumentException("Failed to open resource directory " + resourcePath, e);
387 return Arrays.asList(new File(directoryPath).listFiles(YANG_FILE_FILTER));