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

org.opendaylight.jsonrpc.provider.common.Util Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2017 Brocade Communications Systems, Inc. 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.jsonrpc.provider.common;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.jsonrpc.hmap.DataType;
import org.opendaylight.jsonrpc.hmap.HierarchicalEnumMap;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.jsonrpc.rev161201.Config;
import org.opendaylight.yang.gen.v1.urn.opendaylight.jsonrpc.rev161201.Endpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.jsonrpc.rev161201.Peer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.jsonrpc.rev161201.config.ConfiguredEndpoints;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Utility class.
 *
 * @author Richard Kosegi
 */
public final class Util {
    private static final Logger LOG = LoggerFactory.getLogger(Util.class);
    private static final String ERR_UNRECOGNIZED_STORE = "Unrecognized store value %s";
    private static final Gson GSON = new Gson();
    private static final BiMap STORE_MAP = ImmutableBiMap
            .builder()
            .put(0, LogicalDatastoreType.CONFIGURATION)
            .put(1, LogicalDatastoreType.OPERATIONAL)
            .build();

    private static final BiMap STORE_STR_MAP = ImmutableBiMap.builder()
            .put("config", 0)
            .put("operational", 1)
            .build();

    private Util() {
        // utility-class constructor
    }

    /**
     * Transform JSON RPC 2.0 representation of a data store into {@link LogicalDatastoreType}.
     *
     * @param store data store in form of number
     * @return {@link LogicalDatastoreType}.
     */
    public static LogicalDatastoreType int2store(final int store) {
        final LogicalDatastoreType ldt = STORE_MAP.get(store);
        Preconditions.checkNotNull(ldt, ERR_UNRECOGNIZED_STORE, store);
        return ldt;
    }

    /**
     * Transform string representation of a data store into {@link LogicalDatastoreType}.
     *
     * @param store Logical Data Store
     * @return 0 for "config", 1 for "operational"
     */
    public static int store2int(final String store) {
        try {
            /* Integer quoted as string - common JSON bugbear */
            return Integer.parseInt(store);
        } catch (NumberFormatException e) {
            /* String representation of the datastore */
            final Integer s = STORE_STR_MAP.get(store);
            Objects.requireNonNull(s, () -> String.format(ERR_UNRECOGNIZED_STORE, store));
            return s;
        }
    }

    /**
     * Transform instance of {@link LogicalDatastoreType} to JSON RPC 2.0 representation of a data store.
     *
     * @param store Logical Data Store
     * @return 0 for config, 1 for operational
     */
    public static int store2int(@NonNull final LogicalDatastoreType store) {
        Objects.requireNonNull(store);
        final Integer ldt = STORE_MAP.inverse().get(store);
        Objects.requireNonNull(ldt, () -> String.format(ERR_UNRECOGNIZED_STORE, store));
        return ldt;
    }

    /**
     * Transform {@link LogicalDatastoreType} into string representation.
     *
     * @param store Logical Data Store
     * @return "config" for 0, "operational" for 1
     */
    public static String store2str(final int store) {
        final String s = STORE_STR_MAP.inverse().get(store);
        Preconditions.checkNotNull(s, ERR_UNRECOGNIZED_STORE, store);
        return s;
    }

    /**
     * Utility method to reduce repeated null checks.
     *
     * @param closeable an {@link AutoCloseable} to close
     * @throws Exception if invocation of {@link AutoCloseable#close()} throws exception
     */
    public static void closeNullable(@Nullable AutoCloseable closeable) throws Exception {
        if (closeable != null) {
            closeable.close();
        }
    }

    /**
     * Populates {@link HierarchicalEnumMap} entries from list of endpoints.
     *
     * @param pathMap {@link HierarchicalEnumMap} to populate
     * @param endpoints list of endpoints
     * @param key {@link DataType} of entries to populate
     */
    public static void populateFromEndpointList(HierarchicalEnumMap pathMap,
            @Nullable Collection endpoints, DataType key) {
        Optional.ofNullable(endpoints)
                .orElse(Collections.emptyList())
                .stream()
                .filter(p -> p != null && p.getEndpointUri() != null)
                .forEach(ep -> pathMap.put(GSON.fromJson(ep.getPath(), JsonObject.class), key,
                        ep.getEndpointUri().getValue()));
    }

    /**
     * Attempt to close provided {@link AutoCloseable} instance and log error if {@link Exception} is thrown.
     *
     * @param closeable instance of {@link AutoCloseable} to close, can be null.
     */
    @SuppressWarnings("checkstyle:IllegalCatch")
    public static void closeAndLogOnError(@Nullable AutoCloseable closeable) {
        try {
            closeNullable(closeable);
        } catch (Exception e) {
            LOG.error("Fail to close {}", closeable, e);
        }
    }

    /**
     * Remove entry from {@link Map} using provided key and call {@link AutoCloseable#close()} if entry was found (and
     * removed).
     *
     * @param  type key
     * @param  type of value
     * @param map {@link Map} to remove entry from
     * @param key entry key
     */
    public static  void removeFromMapAndClose(Map map, K key) {
        Optional.ofNullable(map.remove(key)).ifPresent(Util::closeAndLogOnError);
    }

    /**
     * Create a Binding Independent path identifier for a name.
     *
     * @param name - name to create the Bi identifier for
     * @return Bi identifier
     */
    public static YangInstanceIdentifier createBiPath(final String name) {
        final YangInstanceIdentifier.InstanceIdentifierBuilder builder = YangInstanceIdentifier.builder();
        builder.node(Config.QNAME)
                .node(ConfiguredEndpoints.QNAME)
                .nodeWithKey(ConfiguredEndpoints.QNAME, QName.create(ConfiguredEndpoints.QNAME.getNamespace(),
                        ConfiguredEndpoints.QNAME.getRevision(), "name"), name);
        return builder.build();
    }

    @VisibleForTesting
    static boolean isNullableTrue(@Nullable Boolean condition) {
        return condition != null && condition;
    }

    /**
     * Strip query parameters off URI.
     *
     * @param baseUri base URI to strip query parameters from
     * @return stripped URI
     */
    @VisibleForTesting
    static String stripUri(String baseUri) {
        try {
            final URI uri = new URI(baseUri);
            final StringBuilder sb = new StringBuilder();
            sb.append(uri.getScheme());
            sb.append("://");
            sb.append(uri.getHost());
            if (uri.getPort() != -1) {
                sb.append(':');
                sb.append(uri.getPort());
            }
            sb.append(uri.getPath());
            return sb.toString();
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Find subtype of {@link SchemaNode} such as {@link NotificationDefinition} or {@link RpcDefinition} in
     * {@link SchemaContext} based on given name and {@link Function}.Name can be prefixed by module name.
     *
     * @param schemaContext {@link SchemaContext}
     * @param name name of RPC method
     * @param mapper {@link Function} that "extracts" {@link SchemaNode} subtype from {@link Module}
     * @return {@link Optional} of {@link NotificationDefinition}.
     */
    public static  Optional findNode(SchemaContext schemaContext, String name,
            Function> mapper) {
        if (name.indexOf(':') != -1) {
            final String[] parts = name.split(":");
            final Optional modOpt = findModule(schemaContext, parts[0]);
            if (modOpt.isEmpty()) {
                return Optional.empty();
            } else {
                return findNode(mapper.apply(modOpt.orElseThrow()).stream(), parts[1]);
            }
        } else {
            return findNode(schemaContext.getModules().stream().flatMap(m -> mapper.apply(m).stream()), name);
        }
    }

    private static  Optional findNode(Stream stream, String name) {
        return stream.filter(r -> r.getQName().getLocalName().equals(name)).findFirst();
    }

    private static Optional findModule(SchemaContext schemaContext, String name) {
        return schemaContext.getModules().stream().filter(m -> m.getName().equals(name)).findFirst();
    }

    public static LogicalDatastoreType storeFromString(String str) {
        try {
            return int2store(Integer.parseInt(str));
        } catch (NumberFormatException e) {
            return int2store(STORE_STR_MAP.get(str));
        }
    }

    public static boolean supportInbandModels(Peer peer) {
        return (peer.getModules() != null && peer.getModules().size() == 1
                && peer.getModules().iterator().next().getValue().startsWith("jsonrpc-inband-models"));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy