Promote SchemaSourceRepresentation
[yangtools.git] / yang / yang-repo-spi / src / main / java / org / opendaylight / yangtools / yang / model / repo / spi / SchemaSourceTransformer.java
1 /*
2  * Copyright (c) 2014 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.opendaylight.yangtools.yang.model.repo.spi;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.util.concurrent.AsyncFunction;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import java.util.HashMap;
17 import java.util.Map;
18 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
19 import org.opendaylight.yangtools.yang.model.api.source.SourceRepresentation;
20 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
21
22 public class SchemaSourceTransformer<S extends SourceRepresentation, D extends SourceRepresentation>
23         implements SchemaSourceListener, SchemaSourceProvider<D> {
24     @FunctionalInterface
25     public interface Transformation<S extends SourceRepresentation, D extends SourceRepresentation>
26             extends AsyncFunction<S, D> {
27         @Override
28         ListenableFuture<D> apply(S input) throws Exception;
29     }
30
31     private final Map<PotentialSchemaSource<?>, RefcountedRegistration> availableSources = new HashMap<>();
32     private final SchemaSourceRegistry consumer;
33     private final SchemaRepository provider;
34     private final AsyncFunction<S, D> function;
35     private final Class<S> srcClass;
36     private final Class<D> dstClass;
37
38     public SchemaSourceTransformer(final SchemaRepository provider, final Class<S> srcClass,
39             final SchemaSourceRegistry consumer, final Class<D> dstClass, final AsyncFunction<S, D> function) {
40         this.provider = requireNonNull(provider);
41         this.consumer = requireNonNull(consumer);
42         this.function = requireNonNull(function);
43         this.srcClass = requireNonNull(srcClass);
44         this.dstClass = requireNonNull(dstClass);
45     }
46
47     @Override
48     public final ListenableFuture<D> getSource(final SourceIdentifier sourceIdentifier) {
49         return Futures.transformAsync(provider.getSchemaSource(sourceIdentifier, srcClass), function,
50             MoreExecutors.directExecutor());
51     }
52
53     @Override
54     public final void schemaSourceEncountered(final SourceRepresentation source) {
55         // Not interesting
56     }
57
58     @Override
59     public final void schemaSourceRegistered(final Iterable<PotentialSchemaSource<?>> sources) {
60         for (var src : sources) {
61             final var rep = src.getRepresentation();
62             if (srcClass.isAssignableFrom(rep) && dstClass != rep) {
63                 registerSource(src);
64             }
65         }
66     }
67
68     @Override
69     public final void schemaSourceUnregistered(final PotentialSchemaSource<?> source) {
70         final var rep = source.getRepresentation();
71         if (srcClass.isAssignableFrom(rep) && dstClass != rep) {
72             unregisterSource(source);
73         }
74     }
75
76     private void registerSource(final PotentialSchemaSource<?> src) {
77         final var reg = availableSources.get(src);
78         if (reg != null) {
79             reg.incRef();
80             return;
81         }
82
83         final var newSrc = PotentialSchemaSource.create(src.getSourceIdentifier(), dstClass,
84             src.getCost() + PotentialSchemaSource.Costs.COMPUTATION.getValue());
85         availableSources.put(src, new RefcountedRegistration(consumer.registerSchemaSource(this, newSrc)));
86     }
87
88     private void unregisterSource(final PotentialSchemaSource<?> src) {
89         final RefcountedRegistration reg = availableSources.get(src);
90         if (reg != null && reg.decRef()) {
91             availableSources.remove(src);
92         }
93     }
94 }