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 java.util.stream.Collectors;
25 import org.eclipse.jdt.annotation.NonNull;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.common.YangConstants;
28 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
29 import org.opendaylight.yangtools.yang.model.api.source.SourceRepresentation;
30 import org.opendaylight.yangtools.yang.model.api.stmt.FeatureSet;
31 import org.opendaylight.yangtools.yang.model.spi.source.YangTextSource;
32 import org.opendaylight.yangtools.yang.parser.api.YangParser;
33 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
34 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
35 import org.opendaylight.yangtools.yang.parser.api.YangParserFactory;
36 import org.opendaylight.yangtools.yang.parser.api.YangSyntaxErrorException;
39 * Utility class which provides convenience methods for producing effective schema context based on the supplied
40 * YANG/YIN sources or paths to these sources.
42 public final class YangParserTestUtils {
43 private static final FileFilter YANG_FILE_FILTER = file -> {
44 // Locale keeps SpotBugs happy. It should not matter that much anyway.
45 final String name = file.getName().toLowerCase(Locale.ENGLISH);
46 return name.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION) && file.isFile();
49 private static final @NonNull YangParserFactory PARSER_FACTORY;
52 final Iterator<@NonNull YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
54 throw new IllegalStateException("No YangParserFactory found");
56 PARSER_FACTORY = it.next();
59 private YangParserTestUtils() {
64 * Creates a new effective schema context containing the specified YANG source. Statement parser mode is set to
65 * default mode and all YANG features are supported.
67 * @param resource relative path to the YANG file to be parsed
69 * @return effective schema context
71 public static EffectiveModelContext parseYangResource(final String resource) {
72 return parseYangResource(resource, YangParserConfiguration.DEFAULT);
76 * Creates a new effective schema context containing the specified YANG source. All YANG features are supported.
78 * @param resource relative path to the YANG file to be parsed
79 * @param config parser configuration
80 * @return effective schema context
82 public static EffectiveModelContext parseYangResource(final String resource, final YangParserConfiguration config) {
83 return parseYangResource(resource, config, null);
87 * Creates a new effective schema context containing the specified YANG source. Statement parser mode is set to
90 * @param resource relative path to the YANG file to be parsed
91 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
93 * @return effective schema context
95 public static EffectiveModelContext parseYangResource(final String resource, final Set<QName> supportedFeatures) {
96 return parseYangResource(resource, YangParserConfiguration.DEFAULT, supportedFeatures);
100 * Creates a new effective schema context containing the specified YANG source.
102 * @param resource relative path to the YANG file to be parsed
103 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
105 * @param config parser configuration
106 * @return effective schema context
108 public static EffectiveModelContext parseYangResource(final String resource, final YangParserConfiguration config,
109 final Set<QName> supportedFeatures) {
110 return parseYangSources(config, supportedFeatures,
111 YangTextSource.forResource(YangParserTestUtils.class, resource));
115 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
116 * default mode and all YANG features are supported.
118 * @param files YANG files to be parsed
119 * @return effective schema context
121 public static EffectiveModelContext parseYangFiles(final File... files) {
122 return parseYangFiles(Arrays.asList(files));
126 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
127 * default mode and all YANG features are supported.
129 * @param files collection of YANG files to be parsed
130 * @return effective schema context
132 public static EffectiveModelContext parseYangFiles(final Collection<File> files) {
133 return parseYangFiles(YangParserConfiguration.DEFAULT, files);
137 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
140 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
141 * models are resolved
142 * @param files YANG files to be parsed
143 * @return effective schema context
145 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures, final File... files) {
146 return parseYangFiles(supportedFeatures, Arrays.asList(files));
149 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
150 final Collection<File> files) {
151 return parseYangFiles(supportedFeatures, YangParserConfiguration.DEFAULT, files);
155 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
157 * @param config parser configuration
158 * @param files YANG files to be parsed
159 * @return effective schema context
161 public static EffectiveModelContext parseYangFiles(final YangParserConfiguration config, final File... files) {
162 return parseYangFiles(config, Arrays.asList(files));
166 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
168 * @param config parser configuration
169 * @param files collection of YANG files to be parsed
170 * @return effective schema context
172 public static EffectiveModelContext parseYangFiles(final YangParserConfiguration config,
173 final Collection<File> files) {
174 return parseYangFiles(null, config, files);
178 * Creates a new effective schema context containing the specified YANG sources.
180 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
181 * models are resolved
182 * @param config parser configuration
183 * @param files YANG files to be parsed
184 * @return effective schema context
186 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
187 final YangParserConfiguration config, final File... files) {
188 return parseYangFiles(supportedFeatures, config, Arrays.asList(files));
192 * Creates a new effective schema context containing the specified YANG sources.
194 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
195 * models are resolved
196 * @param config parser configuration
197 * @param files YANG files to be parsed
198 * @return effective schema context
200 // FIXME: use Java.nio.file.Path
201 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
202 final YangParserConfiguration config, final Collection<File> files) {
203 return parseSources(config, supportedFeatures,
204 files.stream().map(file -> YangTextSource.forPath(file.toPath())).collect(Collectors.toList()));
208 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
209 * default mode and all YANG features are supported.
211 * @param resourcePath relative path to the directory with YANG files to be parsed
212 * @return effective schema context
214 public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath) {
215 return parseYangResourceDirectory(resourcePath, YangParserConfiguration.DEFAULT);
219 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
221 * @param resourcePath relative path to the directory with YANG files to be parsed
222 * @param config parser configuration
223 * @return effective schema context
225 public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
226 final YangParserConfiguration config) {
227 return parseYangResourceDirectory(resourcePath, null, config);
231 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
234 * @param resourcePath relative path to the directory with YANG files to be parsed
235 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
236 * models are resolved
237 * @return effective schema context
239 public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
240 final Set<QName> supportedFeatures) {
241 return parseYangResourceDirectory(resourcePath, supportedFeatures, YangParserConfiguration.DEFAULT);
245 * Creates a new effective schema context containing the specified YANG sources.
247 * @param resourcePath relative path to the directory with YANG files to be parsed
248 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
249 * models are resolved
250 * @param config parser configuration
251 * @return effective schema context
253 @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Wrong inferent on listFiles")
254 public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
255 final Set<QName> supportedFeatures, final YangParserConfiguration config) {
256 final URI directoryPath;
258 directoryPath = YangParserTestUtils.class.getResource(resourcePath).toURI();
259 } catch (URISyntaxException e) {
260 throw new IllegalArgumentException("Failed to open resource " + resourcePath, e);
262 return parseYangFiles(supportedFeatures, config, new File(directoryPath).listFiles(YANG_FILE_FILTER));
266 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
267 * default mode and all YANG features are supported.
269 * @param clazz Resource lookup base
270 * @param resources Resource names to be looked up
271 * @return effective schema context
273 public static EffectiveModelContext parseYangResources(final Class<?> clazz, final String... resources) {
274 return parseYangResources(clazz, Arrays.asList(resources));
277 public static EffectiveModelContext parseYangResources(final Class<?> clazz, final Collection<String> resources) {
278 final var sources = new ArrayList<YangTextSource>(resources.size());
279 for (final String r : resources) {
280 sources.add(YangTextSource.forResource(clazz, r));
282 return parseSources(YangParserConfiguration.DEFAULT, null, sources);
286 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
289 * @param yangDirs relative paths to the directories containing YANG files to be parsed
290 * @param yangFiles relative paths to the YANG files to be parsed
291 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
292 * models are resolved
293 * @return effective schema context
295 public static EffectiveModelContext parseYangResources(final List<String> yangDirs, final List<String> yangFiles,
296 final Set<QName> supportedFeatures) {
297 return parseYangResources(yangDirs, yangFiles, supportedFeatures, YangParserConfiguration.DEFAULT);
301 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
303 * @param yangResourceDirs relative paths to the directories containing YANG files to be parsed
304 * @param yangResources relative paths to the YANG files to be parsed
305 * @param config parser configuration
306 * @return effective schema context
308 public static EffectiveModelContext parseYangResources(final List<String> yangResourceDirs,
309 final List<String> yangResources, final YangParserConfiguration config) {
310 return parseYangResources(yangResourceDirs, yangResources, null, config);
314 * Creates a new effective schema context containing the specified YANG sources.
316 * @param yangResourceDirs relative paths to the directories containing YANG files to be parsed
317 * @param yangResources relative paths to the YANG files to be parsed
318 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
319 * models are resolved
320 * @param config parser configuration
321 * @return effective schema context
323 public static EffectiveModelContext parseYangResources(final List<String> yangResourceDirs,
324 final List<String> yangResources, final Set<QName> supportedFeatures,
325 final YangParserConfiguration config) {
326 final List<File> allYangFiles = new ArrayList<>();
327 for (final String yangDir : yangResourceDirs) {
328 allYangFiles.addAll(getYangFiles(yangDir));
331 for (final String yangFile : yangResources) {
333 allYangFiles.add(new File(YangParserTestUtils.class.getResource(yangFile).toURI()));
334 } catch (URISyntaxException e) {
335 throw new IllegalArgumentException("Invalid resource " + yangFile, e);
339 return parseYangFiles(supportedFeatures, config, allYangFiles);
342 public static EffectiveModelContext parseYangSources(final YangParserConfiguration config,
343 final Set<QName> supportedFeatures, final YangTextSource... sources) {
344 return parseSources(config, supportedFeatures, Arrays.asList(sources));
347 public static EffectiveModelContext parseSources(final YangParserConfiguration config,
348 final Set<QName> supportedFeatures, final Collection<? extends SourceRepresentation> sources) {
349 final YangParser parser = PARSER_FACTORY.createParser(config);
350 if (supportedFeatures != null) {
351 parser.setSupportedFeatures(FeatureSet.of(supportedFeatures));
355 parser.addSources(sources);
356 } catch (YangSyntaxErrorException e) {
357 throw new IllegalArgumentException("Malformed source", e);
358 } catch (IOException e) {
359 throw new IllegalArgumentException("Failed to read a source", e);
363 return parser.buildEffectiveModel();
364 } catch (YangParserException e) {
365 throw new IllegalStateException("Failed to assemble SchemaContext", e);
370 * Creates a new effective schema context containing the specified YANG sources.
372 * @param sources list of yang sources in plain string
373 * @return effective schema context
375 public static EffectiveModelContext parseYang(final String... sources) {
376 return parseSources(YangParserConfiguration.DEFAULT, null,
377 Arrays.stream(sources).map(LiteralYangTextSource::ofLiteral).toList());
380 @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Wrong inferent on listFiles")
381 private static Collection<File> getYangFiles(final String resourcePath) {
382 final URI directoryPath;
384 directoryPath = YangParserTestUtils.class.getResource(resourcePath).toURI();
385 } catch (URISyntaxException e) {
386 throw new IllegalArgumentException("Failed to open resource directory " + resourcePath, e);
388 return Arrays.asList(new File(directoryPath).listFiles(YANG_FILE_FILTER));