Removed sonar warnings from binding-dom-adapter.
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / FutureSchema.java
1 /*
2  * Copyright (c) 2015 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
9 package org.opendaylight.mdsal.binding.dom.adapter;
10
11 import com.google.common.base.Predicate;
12 import com.google.common.base.Throwables;
13 import com.google.common.util.concurrent.SettableFuture;
14 import java.net.URI;
15 import java.util.Collection;
16 import java.util.Date;
17 import java.util.List;
18 import java.util.concurrent.CopyOnWriteArrayList;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.TimeoutException;
22 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
23 import org.opendaylight.yangtools.yang.binding.Augmentation;
24
25 class FutureSchema implements AutoCloseable {
26
27     private final List<FutureSchemaPredicate> postponedOperations = new CopyOnWriteArrayList<>();
28     private final SettableFuture<?> schemaPromise = SettableFuture.create();
29     private final long duration;
30     private final TimeUnit unit;
31
32     protected FutureSchema(final long time, final TimeUnit unit) {
33         this.duration = time;
34         this.unit = unit;
35     }
36
37     void onRuntimeContextUpdated(final BindingRuntimeContext context) {
38         for (final FutureSchemaPredicate op : postponedOperations) {
39             op.unlockIfPossible(context);
40         }
41     }
42
43     long getDuration() {
44         return duration;
45     }
46
47     TimeUnit getUnit() {
48         return unit;
49     }
50
51     @Override
52     public void close() {
53         for (final FutureSchemaPredicate op : postponedOperations) {
54             op.cancel();
55         }
56     }
57
58     private static boolean isSchemaAvailable(final Class<?> clz, final BindingRuntimeContext context) {
59         final Object schema;
60         if (Augmentation.class.isAssignableFrom(clz)) {
61             schema = context.getAugmentationDefinition(clz);
62         } else {
63             schema = context.getSchemaDefinition(clz);
64         }
65         return schema != null;
66     }
67
68     boolean waitForSchema(final URI namespace, final Date revision) {
69         final FutureSchemaPredicate postponedOp = new FutureSchemaPredicate() {
70
71             @Override
72             public boolean apply(final BindingRuntimeContext input) {
73                 return input.getSchemaContext().findModuleByNamespaceAndRevision(namespace, revision) != null;
74             }
75         };
76         return postponedOp.waitForSchema();
77     }
78
79     boolean waitForSchema(final Collection<Class<?>> bindingClasses) {
80         final FutureSchemaPredicate postponedOp = new FutureSchemaPredicate() {
81
82             @Override
83             public boolean apply(final BindingRuntimeContext context) {
84                 for (final Class<?> clz : bindingClasses) {
85                     if (!isSchemaAvailable(clz, context)) {
86                         return false;
87                     }
88                 }
89                 return true;
90             }
91         };
92         return postponedOp.waitForSchema();
93     }
94
95     private abstract class FutureSchemaPredicate implements Predicate<BindingRuntimeContext> {
96
97         final boolean waitForSchema() {
98             try {
99                 schemaPromise.get(duration, unit);
100                 return true;
101             } catch (final InterruptedException | ExecutionException e) {
102                 throw Throwables.propagate(e);
103             } catch (final TimeoutException e) {
104                 return false;
105             } finally {
106                 postponedOperations.remove(this);
107             }
108         }
109
110         final void unlockIfPossible(final BindingRuntimeContext context) {
111             if (!schemaPromise.isDone() && apply(context)) {
112                 schemaPromise.set(null);
113             }
114         }
115
116         final void cancel() {
117             schemaPromise.cancel(true);
118         }
119     }
120
121 }