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.onap.ccsdk.features.sdnr.wt.devicemanager.onf14.util;
 
  10 import com.google.common.annotations.Beta;
 
  12 import java.io.FileFilter;
 
  13 import java.io.IOException;
 
  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;
 
  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;
 
  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.
 
  44 public final class YangParserTestUtils {
 
  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();
 
  52     private static final @NonNull YangParserFactory PARSER_FACTORY;
 
  55         final Iterator<@NonNull YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
 
  57             throw new IllegalStateException("No YangParserFactory found");
 
  59         PARSER_FACTORY = it.next();
 
  62     private YangParserTestUtils() {
 
  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.
 
  70      * @param resource relative path to the YANG file to be parsed
 
  72      * @return effective schema context
 
  74     public static EffectiveModelContext parseYangResource(final String resource) {
 
  75         return parseYangResource(resource, YangParserConfiguration.DEFAULT);
 
  79      * Creates a new effective schema context containing the specified YANG source. All YANG features are supported.
 
  81      * @param resource relative path to the YANG file to be parsed
 
  82      * @param parserMode mode of statement parser
 
  83      * @return effective schema context
 
  85     public static EffectiveModelContext parseYangResource(final String resource, final YangParserConfiguration config) {
 
  86         return parseYangResource(resource, config, null);
 
  90      * Creates a new effective schema context containing the specified YANG source. Statement parser mode is set to
 
  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
 
  96      * @return effective schema context
 
  98     public static EffectiveModelContext parseYangResource(final String resource, final Set<QName> supportedFeatures) {
 
  99         return parseYangResource(resource, YangParserConfiguration.DEFAULT, supportedFeatures);
 
 103      * Creates a new effective schema context containing the specified YANG source.
 
 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
 
 108      * @param parserMode mode of statement parser
 
 109      * @return effective schema context
 
 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);
 
 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.
 
 121      * @param files YANG files to be parsed
 
 122      * @return effective schema context
 
 124     public static EffectiveModelContext parseYangFiles(final File... files) {
 
 125         return parseYangFiles(Arrays.asList(files));
 
 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.
 
 132      * @param files collection of YANG files to be parsed
 
 133      * @return effective schema context
 
 135     public static EffectiveModelContext parseYangFiles(final Collection<File> files) {
 
 136         return parseYangFiles(YangParserConfiguration.DEFAULT, files);
 
 140      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
 
 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
 
 148     public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures, final File... files) {
 
 149         return parseYangFiles(supportedFeatures, Arrays.asList(files));
 
 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()));
 
 158      * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
 
 160      * @param parserMode mode of statement parser
 
 161      * @param files YANG files to be parsed
 
 162      * @return effective schema context
 
 164     public static EffectiveModelContext parseYangFiles(final YangParserConfiguration config, final File... files) {
 
 165         return parseYangFiles(config, Arrays.asList(files));
 
 169      * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
 
 171      * @param parserMode mode of statement parser
 
 172      * @param files collection of YANG files to be parsed
 
 173      * @return effective schema context
 
 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()));
 
 181      * Creates a new effective schema context containing the specified YANG sources.
 
 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
 
 189     public static EffectiveModelContext parseYangFiles(final Set<QName> supportedFeatures,
 
 190                 final YangParserConfiguration config, final Path... files) {
 
 191         return parseYangFiles(supportedFeatures, config, Arrays.asList(files));
 
 195      * Creates a new effective schema context containing the specified YANG sources.
 
 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
 
 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()));
 
 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.
 
 213      * @param resourcePath relative path to the directory with YANG files to be parsed
 
 214      * @return effective schema context
 
 216     public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath) {
 
 217         return parseYangResourceDirectory(resourcePath, YangParserConfiguration.DEFAULT);
 
 221      * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
 
 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
 
 227     public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
 
 228                 final YangParserConfiguration config) {
 
 229         return parseYangResourceDirectory(resourcePath, null, config);
 
 233      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
 
 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
 
 241     public static EffectiveModelContext parseYangResourceDirectory(final String resourcePath,
 
 242             final Set<QName> supportedFeatures) {
 
 243         return parseYangResourceDirectory(resourcePath, supportedFeatures, YangParserConfiguration.DEFAULT);
 
 247      * Creates a new effective schema context containing the specified YANG sources.
 
 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
 
 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;
 
 260             directoryPath = YangParserTestUtils.class.getResource(resourcePath).toURI();
 
 261         } catch (URISyntaxException e) {
 
 262             throw new IllegalArgumentException("Failed to open resource " + resourcePath, e);
 
 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()));
 
 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.
 
 272      * @param clazz Resource lookup base
 
 273      * @param resources Resource names to be looked up
 
 274      * @return effective schema context
 
 276     public static EffectiveModelContext parseYangResources(final Class<?> clazz, final String... resources) {
 
 277         return parseYangResources(clazz, Arrays.asList(resources));
 
 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));
 
 285         return parseSources(YangParserConfiguration.DEFAULT, null, sources);
 
 289      * Creates a new effective schema context containing the specified YANG sources. Statement parser mode is set to
 
 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
 
 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);
 
 304      * Creates a new effective schema context containing the specified YANG sources. All YANG features are supported.
 
 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
 
 311     public static EffectiveModelContext parseYangResources(final List<String> yangResourceDirs,
 
 312             final List<String> yangResources, final YangParserConfiguration config) {
 
 313         return parseYangResources(yangResourceDirs, yangResources, null, config);
 
 317      * Creates a new effective schema context containing the specified YANG sources.
 
 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
 
 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));
 
 334         for (final String yangFile : yangResources) {
 
 336                 allYangFiles.add(new File(YangParserTestUtils.class.getResource(yangFile).toURI()));
 
 337             } catch (URISyntaxException e) {
 
 338                 throw new IllegalArgumentException("Invalid resource " + yangFile, e);
 
 342         return parseYangFiles(supportedFeatures, config, allYangFiles.stream().map(e->e.toPath()).collect(Collectors.toList()));
 
 345     public static EffectiveModelContext parseYangSources(final YangParserConfiguration config,
 
 346             final Set<QName> supportedFeatures, final YangTextSchemaSource... sources) {
 
 347         return parseSources(config, supportedFeatures, Arrays.asList(sources));
 
 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);
 
 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);
 
 366             return parser.buildEffectiveModel();
 
 367         } catch (YangParserException e) {
 
 368             throw new IllegalStateException("Failed to assemble SchemaContext", e);
 
 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;
 
 376             directoryPath = YangParserTestUtils.class.getResource(resourcePath).toURI();
 
 377         } catch (URISyntaxException e) {
 
 378             throw new IllegalArgumentException("Failed to open resource directory " + resourcePath, e);
 
 380         return Arrays.asList(new File(directoryPath).listFiles(YANG_FILE_FILTER));