import java.util.EnumMap;
import java.util.EventListener;
import java.util.Iterator;
+import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceKeyCriterion;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace;
import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures;
-import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.ValueAddedListener;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.KeyedValueAddedListener;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.PredicateValueAddedListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// definition().onNamespaceElementAdded(this, type, key, value);
}
- <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceItemAddedAction(final Class<N> type, final K key,
- final OnNamespaceItemAdded listener) throws SourceException {
+ final <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceItemAddedAction(final Class<N> type, final K key,
+ final OnNamespaceItemAdded listener) {
final Object potential = getFromNamespace(type, key);
if (potential != null) {
LOG.trace("Listener on {} key {} satisfied immediately", type, key);
return;
}
- final NamespaceBehaviour<K, V, N> behaviour = getBehaviourRegistry().getNamespaceBehaviour(type);
- Preconditions.checkArgument(behaviour instanceof NamespaceBehaviourWithListeners,
- "Namespace %s does not support listeners", type);
-
- final NamespaceBehaviourWithListeners<K, V, N> casted = (NamespaceBehaviourWithListeners<K, V, N>) behaviour;
- casted.addListener(key, new ValueAddedListener<K>(this, key) {
+ getBehaviour(type).addListener(new KeyedValueAddedListener<K>(this, key) {
@Override
void onValueAdded(final Object value) {
listener.namespaceItemAdded(StatementContextBase.this, type, key, value);
});
}
+ final <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceItemAddedAction(final Class<N> type,
+ final ModelProcessingPhase phase, final NamespaceKeyCriterion<K> criterion,
+ final OnNamespaceItemAdded listener) {
+ final Optional<Entry<K, V>> existing = getFromNamespace(type, criterion);
+ if (existing.isPresent()) {
+ final Entry<K, V> entry = existing.get();
+ LOG.debug("Listener on {} criterion {} found a pre-existing match: {}", type, criterion, entry);
+ waitForPhase(entry.getValue(), type, phase, criterion, listener);
+ return;
+ }
+
+ final NamespaceBehaviourWithListeners<K, V, N> behaviour = getBehaviour(type);
+ behaviour.addListener(new PredicateValueAddedListener<K, V>(this) {
+ @Override
+ boolean onValueAdded(final K key, final V value) {
+ if (criterion.match(key)) {
+ LOG.debug("Listener on {} criterion {} matched added key {}", type, criterion, key);
+ waitForPhase(value, type, phase, criterion, listener);
+ return true;
+ }
+
+ return false;
+ }
+ });
+ }
+
+ final <K, V, N extends IdentifierNamespace<K, V>> void selectMatch(final Class<N> type,
+ final NamespaceKeyCriterion<K> criterion, final OnNamespaceItemAdded listener) {
+ final Optional<Entry<K, V>> optMatch = getFromNamespace(type, criterion);
+ Preconditions.checkState(optMatch.isPresent(),
+ "Failed to find a match for criterion %s in namespace %s node %s", criterion, type, this);
+ final Entry<K, V> match = optMatch.get();
+ listener.namespaceItemAdded(StatementContextBase.this, type, match.getKey(), match.getValue());
+ }
+
+ final <K, V, N extends IdentifierNamespace<K, V>> void waitForPhase(final Object value, final Class<N> type,
+ final ModelProcessingPhase phase, final NamespaceKeyCriterion<K> criterion,
+ final OnNamespaceItemAdded listener) {
+ ((StatementContextBase<?, ? ,?>) value).addPhaseCompletedListener(phase,
+ (context, completedPhase) -> {
+ selectMatch(type, criterion, listener);
+ return true;
+ });
+ }
+
+ private <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> getBehaviour(
+ final Class<N> type) {
+ final NamespaceBehaviour<K, V, N> behaviour = getBehaviourRegistry().getNamespaceBehaviour(type);
+ Preconditions.checkArgument(behaviour instanceof NamespaceBehaviourWithListeners,
+ "Namespace %s does not support listeners", type);
+
+ return (NamespaceBehaviourWithListeners<K, V, N>) behaviour;
+ }
+
/**
* See {@link StatementSupport#getPublicView()}.
*/