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 com.google.common.annotations.Beta;
11 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
13 import java.io.FileFilter;
14 import java.io.IOException;
16 import java.net.URISyntaxException;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Locale;
23 import java.util.ServiceLoader;
25 import java.util.stream.Collectors;
26 import org.eclipse.jdt.annotation.NonNull;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.common.YangConstants;
29 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
30 import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
31 import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
32 import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
33 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
34 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
35 import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
36 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
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.
43 public final class YangParserTestUtils {
45 private static final FileFilter YANG_FILE_FILTER = file -> {
46 // Locale keeps SpotBugs happy. It should not matter that much anyway.
47 final String name = file.getName().toLowerCase(Locale.ENGLISH);
48 return name.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION) && file.isFile();
51 private static final @NonNull YangParserFactory PARSER_FACTORY;
54 final Iterator<@NonNull YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
56 throw new IllegalStateException("No YangParserFactory found");
58 PARSER_FACTORY = it.next();
61 private YangParserTestUtils() {
66 * Creates a new effective schema context containing the specified YANG source. Statement parser mode is set to
67 * default mode and all YANG features are supported.
69 * @param resource relative path to the YANG file to be parsed
71 * @return effective schema context
73 public static EffectiveModelContext parseYangResource(final String resource) {
74 return parseYangResource(resource, StatementParserMode.DEFAULT_MODE);
78 * Creates a new effective schema context containing the specified YANG source. All YANG features are supported.
80 * @param resource relative path to the YANG file to be parsed
81 * @param parserMode mode of statement parser
82 * @return effective schema context
84 public static EffectiveModelContext parseYangResource(final String resource, final StatementParserMode parserMode) {
85 return parseYangResource(resource, parserMode, null);
89 * Creates a new effective schema context containing the specified YANG source. Statement parser mode is set to
92 * @param resource relative path to the YANG file to be parsed
93 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
95 * @return effective schema context
97 public static EffectiveModelContext parseYangResource(final String resource, final Set<QName> supportedFeatures) {
98 return parseYangResource(resource, StatementParserMode.DEFAULT_MODE, supportedFeatures);
102 * Creates a new effective schema context containing the specified YANG source.
104 * @param resource relative path to the YANG file to be parsed
105 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
107 * @param parserMode mode of statement parser
108 * @return effective schema context
110 public static EffectiveModelContext parseYangResource(final String resource, final StatementParserMode parserMode,
111 final Set<QName> supportedFeatures) {
112 final YangTextSchemaSource source = YangTextSchemaSource.forResource(YangParserTestUtils.class, resource);
113 return parseYangSources(parserMode, supportedFeatures, source);
117 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
118 * default mode and all YANG features are supported.
120 * @param files YANG files to be parsed
121 * @return effective schema context
123 public static EffectiveModelContext parseYangFiles(final File... files) {
124 return parseYangFiles(Arrays.asList(files));
128 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
129 * default mode and all YANG features are supported.
131 * @param files collection of YANG files to be parsed
132 * @return effective schema context
134 public static EffectiveModelContext parseYangFiles(final Collection<File> files) {
135 return parseYangFiles(StatementParserMode.DEFAULT_MODE, files);
139 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
142 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
143 * models are resolved
144 * @param files YANG files to be parsed
145 * @return effective schema context
147 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures, final File... files) {
148 return parseYangFiles(supportedFeatures, Arrays.asList(files));
151 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
152 final Collection<File> files) {
153 return parseYangFiles(supportedFeatures, StatementParserMode.DEFAULT_MODE, files);
157 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
159 * @param parserMode mode of statement parser
160 * @param files YANG files to be parsed
161 * @return effective schema context
163 public static EffectiveModelContext parseYangFiles(final StatementParserMode parserMode, final File... files) {
164 return parseYangFiles(parserMode, Arrays.asList(files));
168 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
170 * @param parserMode mode of statement parser
171 * @param files collection of YANG files to be parsed
172 * @return effective schema context
174 public static EffectiveModelContext parseYangFiles(final StatementParserMode parserMode,
175 final Collection<File> files) {
176 return parseYangFiles(null, parserMode, files);
180 * Creates a new effective schema context containing the specified YANG sources.
182 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
183 * models are resolved
184 * @param parserMode mode of statement parser
185 * @param files YANG files to be parsed
186 * @return effective schema context
188 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
189 final StatementParserMode parserMode, final File... files) {
190 return parseYangFiles(supportedFeatures, parserMode, Arrays.asList(files));
194 * Creates a new effective schema context containing the specified YANG sources.
196 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
197 * models are resolved
198 * @param parserMode mode of statement parser
199 * @param files YANG files to be parsed
200 * @return effective schema context
202 public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
203 final StatementParserMode parserMode, final Collection<File> files) {
204 return parseSources(parserMode, supportedFeatures,
205 files.stream().map(YangTextSchemaSource::forFile).collect(Collectors.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, StatementParserMode.DEFAULT_MODE);
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 parserMode mode of statement parser
224 * @return effective schema context
226 public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
227 final StatementParserMode parserMode) {
228 return parseYangResourceDirectory(resourcePath, null, parserMode);
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, StatementParserMode.DEFAULT_MODE);
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 parserMode mode of statement parser
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 StatementParserMode parserMode) {
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, parserMode, 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 final List<YangTextSchemaSource> sources = new ArrayList<>(resources.size());
280 for (final String r : resources) {
281 sources.add(YangTextSchemaSource.forResource(clazz, r));
283 return parseSources(StatementParserMode.DEFAULT_MODE, null, sources);
287 * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
290 * @param yangDirs relative paths to the directories containing YANG files to be parsed
291 * @param yangFiles relative paths to the YANG files to be parsed
292 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
293 * models are resolved
294 * @return effective schema context
296 public static EffectiveModelContext parseYangResources(final List<String> yangDirs, final List<String> yangFiles,
297 final Set<QName> supportedFeatures) {
298 return parseYangResources(yangDirs, yangFiles, supportedFeatures, StatementParserMode.DEFAULT_MODE);
302 * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
304 * @param yangResourceDirs relative paths to the directories containing YANG files to be parsed
305 * @param yangResources relative paths to the YANG files to be parsed
306 * @param statementParserMode mode of statement parser
307 * @return effective schema context
309 public static EffectiveModelContext parseYangResources(final List<String> yangResourceDirs,
310 final List<String> yangResources, final StatementParserMode statementParserMode) {
311 return parseYangResources(yangResourceDirs, yangResources, null, statementParserMode);
315 * Creates a new effective schema context containing the specified YANG sources.
317 * @param yangResourceDirs relative paths to the directories containing YANG files to be parsed
318 * @param yangResources relative paths to the YANG files to be parsed
319 * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
320 * models are resolved
321 * @param statementParserMode mode of statement parser
322 * @return effective schema context
324 public static EffectiveModelContext parseYangResources(final List<String> yangResourceDirs,
325 final List<String> yangResources, final Set<QName> supportedFeatures,
326 final StatementParserMode statementParserMode) {
327 final List<File> allYangFiles = new ArrayList<>();
328 for (final String yangDir : yangResourceDirs) {
329 allYangFiles.addAll(getYangFiles(yangDir));
332 for (final String yangFile : yangResources) {
334 allYangFiles.add(new File(YangParserTestUtils.class.getResource(yangFile).toURI()));
335 } catch (URISyntaxException e) {
336 throw new IllegalArgumentException("Invalid resource " + yangFile, e);
340 return parseYangFiles(supportedFeatures, statementParserMode, allYangFiles);
343 public static EffectiveModelContext parseYangSources(final StatementParserMode parserMode,
344 final Set<QName> supportedFeatures, final YangTextSchemaSource... sources) {
345 return parseSources(parserMode, supportedFeatures, Arrays.asList(sources));
348 public static EffectiveModelContext parseSources(final StatementParserMode parserMode,
349 final Set<QName> supportedFeatures, final Collection<? extends SchemaSourceRepresentation> sources) {
350 final YangParser parser = PARSER_FACTORY.createParser(parserMode);
351 if (supportedFeatures != null) {
352 parser.setSupportedFeatures(supportedFeatures);
356 parser.addSources(sources);
357 } catch (YangSyntaxErrorException e) {
358 throw new IllegalArgumentException("Malformed source", e);
359 } catch (IOException e) {
360 throw new IllegalArgumentException("Failed to read a source", e);
364 return parser.buildEffectiveModel();
365 } catch (YangParserException e) {
366 throw new IllegalStateException("Failed to assemble SchemaContext", e);
370 @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Wrong inferent on listFiles")
371 private static Collection<File> getYangFiles(final String resourcePath) {
372 final URI directoryPath;
374 directoryPath = YangParserTestUtils.class.getResource(resourcePath).toURI();
375 } catch (URISyntaxException e) {
376 throw new IllegalArgumentException("Failed to open resource directory " + resourcePath, e);
378 return Arrays.asList(new File(directoryPath).listFiles(YANG_FILE_FILTER));