All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.netconf.yanglib.writer.YangLibraryContentBuilderUtil Maven / Gradle / Ivy

There is a newer version: 8.0.2
Show newest version
/*
 * Copyright (c) 2023 PANTHEON.tech s.r.o. and others. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.netconf.yanglib.writer;

import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.Module.ConformanceType.Implement;
import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.Module.ConformanceType.Import;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.datastores.rev180214.Operational;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.ModulesState;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.ModulesStateBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.RevisionIdentifier;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.YangLibrary;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.YangLibraryBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.CommonLeafs;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.module.Deviation;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.module.DeviationBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.module.DeviationKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.set.parameters.module.SubmoduleBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.yang.library.parameters.DatastoreBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.yang.library.parameters.ModuleSetBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.yang.library.parameters.SchemaBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.YangIdentifier;
import org.opendaylight.yangtools.binding.util.BindingMap;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.ModuleLike;

/**
 * Utility class responsible for building ietf-yang-library content.
 */
// TODO: current artifact is part of integration with YangLibrarySupport from MDSAL project,
//  it expected to be removed as extra once YangLibrarySupport is fully supporting required functionality.
//  https://jira.opendaylight.org/browse/MDSAL-833
//  https://jira.opendaylight.org/browse/MDSAL-835
final class YangLibraryContentBuilderUtil {
    @Deprecated
    private static final CommonLeafs.Revision EMPTY_REVISION = new CommonLeafs.Revision("");

    static final String DEFAULT_MODULE_SET_NAME = "ODL_modules";
    static final String DEFAULT_SCHEMA_NAME = "ODL_schema";

    private YangLibraryContentBuilderUtil() {
        // utility class
    }

    /**
     * Builds ietf-yang-library content based on model context.
     *
     * @param context effective model context
     * @param contentId YangLibrary content ID
     * @param urlProvider schema source URL provider
     * @return content as an {@link YangLibrary}
     */
    @NonNullByDefault
    static YangLibrary buildYangLibrary(final EffectiveModelContext context, final String contentId,
            final YangLibrarySchemaSourceUrlProvider urlProvider) {
        final var deviationsMap = getDeviationsMap(context);
        return new YangLibraryBuilder()
            .setModuleSet(BindingMap.of(new ModuleSetBuilder()
                .setName(DEFAULT_MODULE_SET_NAME)
                .setModule(context.getModules().stream()
                    .map(module -> buildModule(module, deviationsMap, urlProvider))
                    .collect(BindingMap.toMap())
                )
                .build()))
            .setSchema(BindingMap.of(new SchemaBuilder()
                .setName(DEFAULT_SCHEMA_NAME)
                .setModuleSet(Set.of(DEFAULT_MODULE_SET_NAME))
                .build()))
            .setDatastore(BindingMap.of(new DatastoreBuilder()
                .setName(Operational.VALUE)
                .setSchema(DEFAULT_SCHEMA_NAME)
                .build()))
            .setContentId(contentId)
            .build();
    }

    private static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104
        .module.set.parameters.@NonNull Module buildModule(final @NonNull Module module,
            final @NonNull  Map> deviationsMap,
            final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {
        return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library
            .rev190104.module.set.parameters.ModuleBuilder()
            .setName(buildModuleKeyName(module))
            .setRevision(buildRevision(module))
            .setNamespace(new Uri(module.getNamespace().toString()))
            .setFeature(buildFeatures(module))
            .setDeviation(buildDeviations(module, deviationsMap))
            .setLocation(buildSchemaSourceUrls(module, urlProvider))
            .setSubmodule(module.getSubmodules().stream()
                .map(subModule -> new SubmoduleBuilder()
                    .setName(buildModuleKeyName(subModule))
                    .setRevision(buildRevision(subModule))
                    .setLocation(buildSchemaSourceUrls(subModule, urlProvider))
                    .build())
                .collect(BindingMap.toMap()))
            .build();
    }

    /**
     * Builds ietf-yang-library legacy content based on model context.
     *
     * @param context effective model context
     * @param moduleSetId the ID of the constructed module set
     * @param urlProvider schema source URL provider
     * @return content as a {@link ModulesState}
     * @deprecated due to model update via RFC 8525, the functionality serves backward compatibility.
     */
    @Deprecated
    static ModulesState buildModuleState(final @NonNull EffectiveModelContext context,
            final @NonNull String moduleSetId, final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {
        final var deviationsMap = getDeviationsMap(context);
        return new ModulesStateBuilder()
            .setModule(context.getModules().stream()
                .map(module -> buildLegacyModule(module, deviationsMap, urlProvider))
                .collect(BindingMap.toMap()))
            .setModuleSetId(moduleSetId)
            .build();
    }

    @Deprecated
    private static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library
        .rev190104.module.list.@NonNull Module buildLegacyModule(final @NonNull Module module,
            final @NonNull  Map> deviationsMap,
            final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {

        return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library
            .rev190104.module.list.ModuleBuilder()
            .setName(buildModuleKeyName(module))
            .setRevision(buildLegacyRevision(module))
            .setNamespace(new Uri(module.getNamespace().toString()))
            .setFeature(buildFeatures(module))
            .setSchema(buildSchemaSourceUrl(module, urlProvider))
            .setConformanceType(hasDeviations(module) ? Implement : Import)
            .setDeviation(buildLegacyDeviations(module, deviationsMap))
            .setSubmodule(module.getSubmodules().stream()
                .map(subModule -> new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library
                    .rev190104.module.list.module.SubmoduleBuilder()
                    .setName(buildModuleKeyName(subModule))
                    .setRevision(buildLegacyRevision(subModule))
                    .setSchema(buildSchemaSourceUrl(subModule, urlProvider))
                    .build())
                .collect(BindingMap.toMap()))
            .build();
    }

    private static RevisionIdentifier buildRevision(final ModuleLike module) {
        final var revision = module.getQNameModule().revision();
        return revision != null ? new RevisionIdentifier(revision.toString()) : null;
    }

    @Deprecated
    private static CommonLeafs.Revision buildLegacyRevision(final ModuleLike module) {
        final var revision = module.getQNameModule().revision();
        return revision != null ? new CommonLeafs.Revision(new RevisionIdentifier(revision.toString()))
            : EMPTY_REVISION;
    }

    private static YangIdentifier buildModuleKeyName(final ModuleLike module) {
        final var revision = module.getQNameModule().revision();
        return revision == null ? new YangIdentifier(module.getName()) :
            new YangIdentifier(module.getName() + "_" + revision);
    }

    @Deprecated
    private static @Nullable Uri buildSchemaSourceUrl(final @NonNull ModuleLike module,
            final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {
        final var uris = buildSchemaSourceUrls(module, urlProvider);
        return uris == null ? null : uris.iterator().next();
    }

    private static @Nullable Set buildSchemaSourceUrls(final @NonNull ModuleLike module,
            final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {
        final var uris = urlProvider.getSchemaSourceUrl(DEFAULT_MODULE_SET_NAME, module.getName(),
            module.getRevision().orElse(null));
        return uris.isEmpty() ? null : uris;
    }

    private static @Nullable Set buildFeatures(final ModuleLike module) {
        final var moduleFeatures = module.getFeatures();
        if (moduleFeatures == null || moduleFeatures.isEmpty()) {
            return null;
        }
        final var namespace = module.getQNameModule();
        final var features = module.getFeatures().stream()
            .map(FeatureDefinition::getQName)
            // ensure the features belong to same module
            .filter(featureName -> namespace.equals(featureName.getModule()))
            .map(featureName -> new YangIdentifier(featureName.getLocalName()))
            .collect(Collectors.toUnmodifiableSet());
        return features.isEmpty() ? null : features;
    }

    private static boolean hasDeviations(final Module module) {
        return module.getDeviations() != null && !module.getDeviations().isEmpty();
    }

    private static @Nullable Set buildDeviations(final Module module,
            final Map> deviationsMap) {
        final var deviationModules = deviationsMap.get(module.getQNameModule());
        return deviationModules == null ? null : deviationModules.stream()
            .map(devModule -> new YangIdentifier(buildModuleKeyName(devModule)))
            .collect(ImmutableSet.toImmutableSet());
    }

    @Deprecated
    private static @Nullable Map buildLegacyDeviations(final Module module,
            final Map> deviationsMap) {
        final var deviationModules = deviationsMap.get(module.getQNameModule());
        return deviationModules == null ? null : deviationModules.stream()
            .map(devModule -> new DeviationBuilder()
                .setName(buildModuleKeyName(devModule))
                .setRevision(buildLegacyRevision(devModule))
                .build())
            .collect(BindingMap.toMap());
    }

    private static @NonNull Map> getDeviationsMap(final EffectiveModelContext context) {
        final var result = new HashMap>();
        for (final var module : context.getModules()) {
            if (module.getDeviations() == null || module.getDeviations().isEmpty()) {
                continue;
            }
            for (final var deviation : module.getDeviations()) {
                final var targetQname = deviation.getTargetPath().lastNodeIdentifier().getModule();
                result.computeIfAbsent(targetQname, key -> new HashSet<>()).add(module);
            }
        }
        return ImmutableMap.copyOf(result);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy