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; } }); }
@Override public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> getNamespaceBehaviour( final Class<N> type) { NamespaceBehaviourWithListeners<?, ?, ?> potential = supportedNamespaces.get(type); if (potential == null) { final NamespaceBehaviour<K, V, N> potentialRaw = supports.get(currentPhase).getNamespaceBehaviour(type); if (potentialRaw != null) { potential = createNamespaceContext(potentialRaw); supportedNamespaces.put(type, potential); } else { throw new NamespaceNotAvailableException("Namespace " + type + " is not available in phase " + currentPhase); } } Verify.verify(type.equals(potential.getIdentifier())); /* * Safe cast, previous checkState checks equivalence of key from which * type argument are derived */ return (NamespaceBehaviourWithListeners<K, V, N>) potential; }
@SuppressWarnings({ "unchecked", "rawtypes" }) private <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> createNamespaceContext( final NamespaceBehaviour<K, V, N> potentialRaw) { if (potentialRaw instanceof DerivedNamespaceBehaviour) { final VirtualNamespaceContext derivedContext = new VirtualNamespaceContext( (DerivedNamespaceBehaviour) potentialRaw); getNamespaceBehaviour(((DerivedNamespaceBehaviour) potentialRaw).getDerivedFrom()).addDerivedNamespace( derivedContext); return derivedContext; } return new SimpleNamespaceContext<>(potentialRaw); }
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); listener.namespaceItemAdded(this, type, key, potential); return; } getBehaviour(type).addListener(new KeyedValueAddedListener<K>(this, key) { @Override void onValueAdded(final Object value) { listener.namespaceItemAdded(StatementContextBase.this, type, key, value); } }); }