ee20dccae947068adcbfa9e575b2a7c9fab8cab8
[ccsdk/features.git] / sdnr / wt / devicemanager-onap / onf14 / provider / src / test / java / org / onap / ccsdk / features / sdnr / wt / devicemanager / onf14 / util / YangParserTestUtils.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 package org.onap.ccsdk.features.sdnr.wt.devicemanager.onf14.util;
9
10 import com.google.common.annotations.Beta;
11 import java.io.File;
12 import java.io.FileFilter;
13 import java.io.IOException;
14 import java.net.URI;
15 import java.net.URISyntaxException;
16 import java.nio.file.Path;
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;
24 import java.util.Set;
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.parser.api.YangParser;
31 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
32 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
33 import org.opendaylight.yangtools.yang.parser.api.YangParserFactory;
34 import org.opendaylight.yangtools.yang.parser.api.YangSyntaxErrorException;
35 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
36 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
37 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
38
39 /**
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.
42  */
43 @Beta
44 public final class YangParserTestUtils {
45
46     private static final FileFilter YANG_FILE_FILTER = file -> {
47         // Locale keeps SpotBugs happy. It should not matter that much anyway.
48         final String name = file.getName().toLowerCase(Locale.ENGLISH);
49         return name.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION) && file.isFile();
50     };
51
52     private static final @NonNull YangParserFactory PARSER_FACTORY;
53
54     static {
55         final Iterator<@NonNull YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
56         if (!it.hasNext()) {
57             throw new IllegalStateException("No YangParserFactory found");
58         }
59         PARSER_FACTORY = it.next();
60     }
61
62     private YangParserTestUtils() {
63         // Hidden on purpose
64     }
65
66     /**
67      * Creates a new effective schema context containing the specified YANG source. Statement parser mode is set to
68      * default mode and all YANG features are supported.
69      *
70      * @param resource relative path to the YANG file to be parsed
71      *
72      * @return effective schema context
73      */
74     public static EffectiveModelContext parseYangResource(final String resource) {
75         return parseYangResource(resource, YangParserConfiguration.DEFAULT);
76     }
77
78     /**
79      * Creates a new effective schema context containing the specified YANG source. All YANG features are supported.
80      *
81      * @param resource relative path to the YANG file to be parsed
82      * @param parserMode mode of statement parser
83      * @return effective schema context
84      */
85     public static EffectiveModelContext parseYangResource(final String resource, final YangParserConfiguration config) {
86         return parseYangResource(resource, config, null);
87     }
88
89     /**
90      * Creates a new effective schema context containing the specified YANG source. Statement parser mode is set to
91      * default mode.
92      *
93      * @param resource relative path to the YANG file to be parsed
94      * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
95      *                          model are resolved
96      * @return effective schema context
97      */
98     public static EffectiveModelContext parseYangResource(final String resource, final Set<QName> supportedFeatures) {
99         return parseYangResource(resource, YangParserConfiguration.DEFAULT, supportedFeatures);
100     }
101
102     /**
103      * Creates a new effective schema context containing the specified YANG source.
104      *
105      * @param resource relative path to the YANG file to be parsed
106      * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
107      *                          model are resolved
108      * @param parserMode mode of statement parser
109      * @return effective schema context
110      */
111     public static EffectiveModelContext parseYangResource(final String resource, final YangParserConfiguration config,
112             final Set<QName> supportedFeatures) {
113         final YangTextSchemaSource source = YangTextSchemaSource.forResource(YangParserTestUtils.class, resource);
114         return parseYangSources(config, supportedFeatures, source);
115     }
116
117     /**
118      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
119      * default mode and all YANG features are supported.
120      *
121      * @param files YANG files to be parsed
122      * @return effective schema context
123      */
124     public static EffectiveModelContext parseYangFiles(final File... files) {
125         return parseYangFiles(Arrays.asList(files));
126     }
127
128     /**
129      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
130      * default mode and all YANG features are supported.
131      *
132      * @param files collection of YANG files to be parsed
133      * @return effective schema context
134      */
135     public static EffectiveModelContext parseYangFiles(final Collection<File> files) {
136         return parseYangFiles(YangParserConfiguration.DEFAULT, files);
137     }
138
139     /**
140      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
141      * default mode.
142      *
143      * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
144      *                          models are resolved
145      * @param files YANG files to be parsed
146      * @return effective schema context
147      */
148     public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures, final File... files) {
149         return parseYangFiles(supportedFeatures, Arrays.asList(files));
150     }
151
152     public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
153             final Collection<File> files) {
154         return parseYangFiles(supportedFeatures, YangParserConfiguration.DEFAULT, files.stream().map(e->e.toPath()).collect(Collectors.toList()));
155     }
156
157     /**
158      * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
159      *
160      * @param parserMode mode of statement parser
161      * @param files YANG files to be parsed
162      * @return effective schema context
163      */
164     public static EffectiveModelContext parseYangFiles(final YangParserConfiguration config, final File... files) {
165         return parseYangFiles(config, Arrays.asList(files));
166     }
167
168     /**
169      * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
170      *
171      * @param parserMode mode of statement parser
172      * @param files collection of YANG files to be parsed
173      * @return effective schema context
174      */
175     public static EffectiveModelContext parseYangFiles(final YangParserConfiguration config,
176             final Collection<File> files) {
177         return parseYangFiles(null, config, files.stream().map(e->e.toPath()).collect(Collectors.toList()));
178     }
179
180     /**
181      * Creates a new effective schema context containing the specified YANG sources.
182      *
183      * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
184      *                          models are resolved
185      * @param parserMode mode of statement parser
186      * @param files YANG files to be parsed
187      * @return effective schema context
188      */
189     public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
190                 final YangParserConfiguration config, final Path... files) {
191         return parseYangFiles(supportedFeatures, config, Arrays.asList(files));
192     }
193
194     /**
195      * Creates a new effective schema context containing the specified YANG sources.
196      *
197      * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
198      *                          models are resolved
199      * @param parserMode mode of statement parser
200      * @param files YANG files to be parsed
201      * @return effective schema context
202      */
203     public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
204                 final YangParserConfiguration config, final Collection<Path> files) {
205         return parseSources(config, supportedFeatures,
206             files.stream().map(YangTextSchemaSource::forPath).collect(Collectors.toList()));
207     }
208
209     /**
210      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
211      * default mode and all YANG features are supported.
212      *
213      * @param resourcePath relative path to the directory with YANG files to be parsed
214      * @return effective schema context
215      */
216     public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath) {
217         return parseYangResourceDirectory(resourcePath, YangParserConfiguration.DEFAULT);
218     }
219
220     /**
221      * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
222      *
223      * @param resourcePath relative path to the directory with YANG files to be parsed
224      * @param parserMode mode of statement parser
225      * @return effective schema context
226      */
227     public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
228                 final YangParserConfiguration config) {
229         return parseYangResourceDirectory(resourcePath, null, config);
230     }
231
232     /**
233      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
234      * default mode.
235      *
236      * @param resourcePath relative path to the directory with YANG files to be parsed
237      * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
238      *                          models are resolved
239      * @return effective schema context
240      */
241     public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
242             final Set<QName> supportedFeatures) {
243         return parseYangResourceDirectory(resourcePath, supportedFeatures, YangParserConfiguration.DEFAULT);
244     }
245
246     /**
247      * Creates a new effective schema context containing the specified YANG sources.
248      *
249      * @param resourcePath relative path to the directory with YANG files to be parsed
250      * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
251      *                          models are resolved
252      * @param parserMode mode of statement parser
253      * @return effective schema context
254      */
255     @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Wrong inferent on listFiles")
256     public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
257             final Set<QName> supportedFeatures, final YangParserConfiguration config) {
258         final URI directoryPath;
259         try {
260             directoryPath = YangParserTestUtils.class.getResource(resourcePath).toURI();
261         } catch (URISyntaxException e) {
262             throw new IllegalArgumentException("Failed to open resource " + resourcePath, e);
263         }
264         File[] files = new File(directoryPath).listFiles(YANG_FILE_FILTER);
265         return parseYangFiles(supportedFeatures, config, Arrays.asList(files).stream().map(e->e.toPath()).collect(Collectors.toList()));
266     }
267
268     /**
269      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
270      * default mode and all YANG features are supported.
271      *
272      * @param clazz Resource lookup base
273      * @param resources Resource names to be looked up
274      * @return effective schema context
275      */
276     public static EffectiveModelContext parseYangResources(final Class<?> clazz, final String... resources) {
277         return parseYangResources(clazz, Arrays.asList(resources));
278     }
279
280     public static EffectiveModelContext parseYangResources(final Class<?> clazz, final Collection<String> resources) {
281         final List<YangTextSchemaSource> sources = new ArrayList<>(resources.size());
282         for (final String r : resources) {
283             sources.add(YangTextSchemaSource.forResource(clazz, r));
284         }
285         return parseSources(YangParserConfiguration.DEFAULT, null, sources);
286     }
287
288     /**
289      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
290      * default mode.
291      *
292      * @param yangDirs relative paths to the directories containing YANG files to be parsed
293      * @param yangFiles relative paths to the YANG files to be parsed
294      * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
295      *                          models are resolved
296      * @return effective schema context
297      */
298     public static EffectiveModelContext parseYangResources(final List<String> yangDirs, final List<String> yangFiles,
299             final Set<QName> supportedFeatures) {
300         return parseYangResources(yangDirs, yangFiles, supportedFeatures, YangParserConfiguration.DEFAULT);
301     }
302
303     /**
304      * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
305      *
306      * @param yangResourceDirs relative paths to the directories containing YANG files to be parsed
307      * @param yangResources relative paths to the YANG files to be parsed
308      * @param statementParserMode mode of statement parser
309      * @return effective schema context
310      */
311     public static EffectiveModelContext parseYangResources(final List<String> yangResourceDirs,
312             final List<String> yangResources, final YangParserConfiguration config) {
313         return parseYangResources(yangResourceDirs, yangResources, null, config);
314     }
315
316     /**
317      * Creates a new effective schema context containing the specified YANG sources.
318      *
319      * @param yangResourceDirs relative paths to the directories containing YANG files to be parsed
320      * @param yangResources relative paths to the YANG files to be parsed
321      * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
322      *                          models are resolved
323      * @param statementParserMode mode of statement parser
324      * @return effective schema context
325      */
326     public static EffectiveModelContext parseYangResources(final List<String> yangResourceDirs,
327             final List<String> yangResources, final Set<QName> supportedFeatures,
328             final YangParserConfiguration config) {
329         final List<File> allYangFiles = new ArrayList<>();
330         for (final String yangDir : yangResourceDirs) {
331             allYangFiles.addAll(getYangFiles(yangDir));
332         }
333
334         for (final String yangFile : yangResources) {
335             try {
336                 allYangFiles.add(new File(YangParserTestUtils.class.getResource(yangFile).toURI()));
337             } catch (URISyntaxException e) {
338                 throw new IllegalArgumentException("Invalid resource " + yangFile, e);
339             }
340         }
341
342         return parseYangFiles(supportedFeatures, config, allYangFiles.stream().map(e->e.toPath()).collect(Collectors.toList()));
343     }
344
345     public static EffectiveModelContext parseYangSources(final YangParserConfiguration config,
346             final Set<QName> supportedFeatures, final YangTextSchemaSource... sources) {
347         return parseSources(config, supportedFeatures, Arrays.asList(sources));
348     }
349
350     public static EffectiveModelContext parseSources(final YangParserConfiguration config,
351             final Set<QName> supportedFeatures, final Collection<? extends SchemaSourceRepresentation> sources) {
352         final YangParser parser = PARSER_FACTORY.createParser(config);
353         if (supportedFeatures != null) {
354             parser.setSupportedFeatures(supportedFeatures);
355         }
356
357         try {
358             parser.addSources(sources);
359         } catch (YangSyntaxErrorException e) {
360             throw new IllegalArgumentException("Malformed source", e);
361         } catch (IOException e) {
362             throw new IllegalArgumentException("Failed to read a source", e);
363         }
364
365         try {
366             return parser.buildEffectiveModel();
367         } catch (YangParserException e) {
368             throw new IllegalStateException("Failed to assemble SchemaContext", e);
369         }
370     }
371
372     @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Wrong inferent on listFiles")
373     private static Collection<File> getYangFiles(final String resourcePath) {
374         final URI directoryPath;
375         try {
376             directoryPath = YangParserTestUtils.class.getResource(resourcePath).toURI();
377         } catch (URISyntaxException e) {
378             throw new IllegalArgumentException("Failed to open resource directory " + resourcePath, e);
379         }
380         return Arrays.asList(new File(directoryPath).listFiles(YANG_FILE_FILTER));
381     }
382 }