Refactor NetconfDeviceSchemas
[netconf.git] / plugins / netconf-client-mdsal / src / main / java / org / opendaylight / netconf / client / mdsal / impl / DefaultDeviceNetconfSchemaProvider.java
1 /*
2  * Copyright (c) 2024 PANTHEON.tech, s.r.o. 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.opendaylight.netconf.client.mdsal.impl;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.VisibleForTesting;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.util.concurrent.Executor;
16 import java.util.stream.Collectors;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchema;
19 import org.opendaylight.netconf.client.mdsal.api.DeviceNetconfSchema;
20 import org.opendaylight.netconf.client.mdsal.api.DeviceNetconfSchemaProvider;
21 import org.opendaylight.netconf.client.mdsal.api.NetconfDeviceSchemasResolver;
22 import org.opendaylight.netconf.client.mdsal.api.NetconfRpcService;
23 import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
24 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
25 import org.opendaylight.yangtools.concepts.Registration;
26 import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
27 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
28 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
29 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource.Costs;
30 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
31 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 @VisibleForTesting
36 public final class DefaultDeviceNetconfSchemaProvider implements DeviceNetconfSchemaProvider {
37     private static final Logger LOG = LoggerFactory.getLogger(DefaultDeviceNetconfSchemaProvider.class);
38
39     // FIXME: resolver seems to be a useless indirection
40     private final NetconfDeviceSchemasResolver resolver = new NetconfStateSchemasResolverImpl();
41     private final @NonNull EffectiveModelContextFactory contextFactory;
42     private final @NonNull SchemaSourceRegistry registry;
43     private final @NonNull SchemaRepository repository;
44     // FIXME: private final Executor processingExecutor;
45
46     DefaultDeviceNetconfSchemaProvider(final SharedSchemaRepository repository) {
47         this(repository, repository,
48             repository.createEffectiveModelContextFactory(SchemaContextFactoryConfiguration.getDefault()));
49     }
50
51     @VisibleForTesting
52     public DefaultDeviceNetconfSchemaProvider(final SchemaSourceRegistry registry, final SchemaRepository repository,
53             final EffectiveModelContextFactory contextFactory) {
54         this.registry = requireNonNull(registry);
55         this.repository = requireNonNull(repository);
56         this.contextFactory = requireNonNull(contextFactory);
57     }
58
59     @Override
60     public ListenableFuture<DeviceNetconfSchema> deviceNetconfSchemaFor(final RemoteDeviceId deviceId,
61             final NetconfSessionPreferences sessionPreferences, final NetconfRpcService deviceRpc,
62             final BaseNetconfSchema baseSchema, final Executor processingExecutor) {
63         // Acquire sources
64         final var sourceResolverFuture = resolver.resolve(deviceId, sessionPreferences, deviceRpc,
65             baseSchema.modelContext());
66
67         // Set up the EffectiveModelContext for the device
68         return Futures.transformAsync(sourceResolverFuture, deviceSources -> {
69             LOG.debug("{}: Resolved device sources to {}", deviceId, deviceSources);
70
71             // Register all sources with repository and start resolution
72             final var registrations = deviceSources.providedSources().stream()
73                 .flatMap(sources -> sources.registerWith(registry, Costs.REMOTE_IO.getValue()))
74                 .collect(Collectors.toUnmodifiableList());
75             final var future = new SchemaSetup(repository, contextFactory, deviceId, deviceSources, sessionPreferences)
76                 .startResolution();
77
78             // Unregister sources once resolution is complete
79             future.addListener(() -> registrations.forEach(Registration::close), processingExecutor);
80
81             return future;
82         }, processingExecutor);
83     }
84
85     @Deprecated
86     @Override
87     public SchemaRepository repository() {
88         return repository;
89     }
90
91     @Deprecated
92     @Override
93     public SchemaSourceRegistry registry() {
94         return registry;
95     }
96
97     @Deprecated
98     @Override
99     public EffectiveModelContextFactory contextFactory() {
100         return contextFactory;
101     }
102 }