2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.md.sal.binding.impl;
11 import com.google.common.base.Predicate;
12 import com.google.common.base.Throwables;
13 import com.google.common.util.concurrent.SettableFuture;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.Date;
18 import java.util.LinkedHashSet;
20 import java.util.concurrent.ExecutionException;
21 import java.util.concurrent.TimeUnit;
22 import java.util.concurrent.TimeoutException;
23 import javax.annotation.concurrent.GuardedBy;
24 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
25 import org.opendaylight.yangtools.yang.binding.Augmentation;
27 class FutureSchema implements AutoCloseable {
29 @GuardedBy(value="postponedOperations")
30 private final Set<FutureSchemaPredicate> postponedOperations = new LinkedHashSet<>();
31 private final long duration;
32 private final TimeUnit unit;
33 private final boolean waitEnabled;
34 private volatile BindingRuntimeContext runtimeContext;
36 protected FutureSchema(final long time, final TimeUnit unit, final boolean waitEnabled) {
39 this.waitEnabled = waitEnabled;
42 BindingRuntimeContext runtimeContext() {
43 BindingRuntimeContext localRuntimeContext = runtimeContext;
44 if(localRuntimeContext != null) {
45 return localRuntimeContext;
48 if(waitForSchema(Collections.emptyList())) {
49 return runtimeContext;
52 throw new IllegalStateException("No SchemaContext is available");
55 void onRuntimeContextUpdated(final BindingRuntimeContext context) {
56 synchronized(postponedOperations) {
57 runtimeContext = context;
58 for (final FutureSchemaPredicate op : postponedOperations) {
59 op.unlockIfPossible(context);
74 synchronized(postponedOperations) {
75 for (final FutureSchemaPredicate op : postponedOperations) {
81 private static boolean isSchemaAvailable(final Class<?> clz, final BindingRuntimeContext context) {
83 if (Augmentation.class.isAssignableFrom(clz)) {
84 schema = context.getAugmentationDefinition(clz);
86 schema = context.getSchemaDefinition(clz);
88 return schema != null;
91 boolean waitForSchema(final URI namespace, final Date revision) {
92 return addPostponedOpAndWait(new FutureSchemaPredicate() {
94 public boolean apply(final BindingRuntimeContext input) {
95 return input.getSchemaContext().findModuleByNamespaceAndRevision(namespace, revision) != null;
100 boolean waitForSchema(final Collection<Class<?>> bindingClasses) {
101 return addPostponedOpAndWait(new FutureSchemaPredicate() {
103 public boolean apply(final BindingRuntimeContext context) {
104 for (final Class<?> clz : bindingClasses) {
105 if (!isSchemaAvailable(clz, context)) {
114 private boolean addPostponedOpAndWait(FutureSchemaPredicate postponedOp) {
119 BindingRuntimeContext localRuntimeContext = runtimeContext;
120 synchronized(postponedOperations) {
121 postponedOperations.add(postponedOp);
123 // If the runtimeContext changed, this op may now be satisfied so check it.
124 if(localRuntimeContext != runtimeContext) {
125 postponedOp.unlockIfPossible(runtimeContext);
129 return postponedOp.waitForSchema();
132 private abstract class FutureSchemaPredicate implements Predicate<BindingRuntimeContext> {
134 final boolean waitForSchema() {
136 schemaPromise.get(duration, unit);
138 } catch (final InterruptedException | ExecutionException e) {
139 throw Throwables.propagate(e);
140 } catch (final TimeoutException e) {
143 synchronized(postponedOperations) {
144 postponedOperations.remove(this);
149 final void unlockIfPossible(final BindingRuntimeContext context) {
150 if (!schemaPromise.isDone() && apply(context)) {
151 schemaPromise.set(null);
155 final void cancel() {
156 schemaPromise.cancel(true);
159 private final SettableFuture<?> schemaPromise = SettableFuture.create();