From b6e9bb9ff439eb0e905d8ccf61e15a5a3b2bf444 Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Thu, 1 Oct 2015 19:23:11 +0200 Subject: [PATCH] Updated SchemaNodeIdentifier namespace handling. Introduced notion of derived namespaces and SchemaNodeIdentifier namespace for lookups of refine / augment and other statements - Fixed AugmentUtils and AugmentStatementImpl, UsesStatementImpl to use declarative way to get needed artefacts instead of manual search in statement context. - Removed utility methods, which are not needed anymore. Change-Id: Ifb9c6dffa948cf265f81f2d8cd8615318b1447d0 Signed-off-by: Tony Tkacik --- .../spi/meta/DerivedNamespaceBehaviour.java | 40 ++++ .../parser/spi/meta/ModelActionBuilder.java | 2 +- .../parser/spi/meta/NamespaceBehaviour.java | 20 +- .../stmt/reactor/BuildGlobalContext.java | 31 ++- .../parser/stmt/reactor/ModifierImpl.java | 49 ++--- .../NamespaceBehaviourWithListeners.java | 74 +++---- .../stmt/reactor/RootStatementContext.java | 5 + .../stmt/reactor/SimpleNamespaceContext.java | 40 ++++ .../stmt/reactor/SourceSpecificContext.java | 8 +- .../stmt/reactor/StatementContextBase.java | 7 +- .../stmt/reactor/SubstatementContext.java | 7 +- .../stmt/reactor/VirtualNamespaceContext.java | 38 ++++ .../stmt/rfc6020/AugmentStatementImpl.java | 30 +-- .../parser/stmt/rfc6020/AugmentUtils.java | 189 +++--------------- .../parser/stmt/rfc6020/ChildSchemaNodes.java | 41 +++- .../SchemaNodeIdentifierBuildNamespace.java | 59 ++++++ .../stmt/rfc6020/UsesStatementImpl.java | 9 +- .../yang/parser/stmt/rfc6020/Utils.java | 9 +- .../stmt/rfc6020/YangInferencePipeline.java | 3 +- .../yang/stmt/test/AugmentProcessTest.java | 39 +--- .../src/test/resources/model-new/foo.yang | 2 +- .../src/test/resources/model-new/subfoo.yang | 2 +- .../augments/multiple-augment-imported.yang | 13 +- .../augments/multiple-augment-root.yang | 6 +- 24 files changed, 395 insertions(+), 328 deletions(-) create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/DerivedNamespaceBehaviour.java create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SimpleNamespaceContext.java create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/VirtualNamespaceContext.java create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/DerivedNamespaceBehaviour.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/DerivedNamespaceBehaviour.java new file mode 100644 index 0000000000..03dbfa8565 --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/DerivedNamespaceBehaviour.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.parser.spi.meta; + +import com.google.common.base.Preconditions; +import java.util.Map; +import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; + +public abstract class DerivedNamespaceBehaviour, T extends IdentifierNamespace> + extends NamespaceBehaviour { + + private Class derivedFrom; + + protected DerivedNamespaceBehaviour(Class identifier, Class derivedFrom) { + super(identifier); + this.derivedFrom = Preconditions.checkNotNull(derivedFrom); + } + + public Class getDerivedFrom() { + return derivedFrom; + } + + @Override + public Map getAllFrom(NamespaceStorageNode storage) { + throw new UnsupportedOperationException("Virtual namespaces does not support provision of all items."); + } + + @Override + public abstract V getFrom(NamespaceBehaviour.NamespaceStorageNode storage, K key); + + @Override + public void addTo(NamespaceStorageNode storage, K key, V value) { + // Intentional noop + } +} diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ModelActionBuilder.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ModelActionBuilder.java index 41d22500e4..54605dbc67 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ModelActionBuilder.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ModelActionBuilder.java @@ -151,7 +151,7 @@ public interface ModelActionBuilder { @Nonnull > Prerequisite mutatesEffectiveCtx(T stmt); - @Nonnull ,N extends StatementNamespace> Prerequisite> mutatesEffectiveCtx(StmtContext context,Class namespace, K key); + @Nonnull , N extends IdentifierNamespace>> Prerequisite> mutatesEffectiveCtx(StmtContext context,Class namespace, K key); void apply(InferenceAction action) throws InferenceException; diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/NamespaceBehaviour.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/NamespaceBehaviour.java index 6d156b1c83..53c12ccd57 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/NamespaceBehaviour.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/NamespaceBehaviour.java @@ -33,7 +33,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; public abstract class NamespaceBehaviour> implements Identifiable> { public enum StorageNodeType { - GLOBAL, SOURCE_LOCAL_SPECIAL, STATEMENT_LOCAL, + GLOBAL, SOURCE_LOCAL_SPECIAL, STATEMENT_LOCAL, ROOT_STATEMENT_LOCAL } public interface Registry { @@ -184,10 +184,7 @@ public abstract class NamespaceBehaviour potentialRaw = supports.get(currentPhase).getNamespaceBehaviour(type); if(potentialRaw != null) { - potential = new NamespaceBehaviourWithListeners<>(potentialRaw); + potential = createNamespaceContext(potentialRaw); supportedNamespaces.put(type, potential); + } else { + throw new NamespaceNotAvailableException( + "Namespace " + type + " is not available in phase " + currentPhase); } } - if (potential != null) { - Preconditions.checkState(type.equals(potential.getIdentifier())); + Verify.verify(type.equals(potential.getIdentifier())); /* - * Safe cast, previous checkState checks equivalence of key from - * which type argument are derived - */ - return (NamespaceBehaviourWithListeners) potential; + * Safe cast, previous checkState checks equivalence of key from which type argument are + * derived + */ + return (NamespaceBehaviourWithListeners) potential; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private > NamespaceBehaviourWithListeners createNamespaceContext( + NamespaceBehaviour potentialRaw) { + if (potentialRaw instanceof DerivedNamespaceBehaviour) { + VirtualNamespaceContext derivedContext = + new VirtualNamespaceContext<>(potentialRaw); + getNamespaceBehaviour(((DerivedNamespaceBehaviour) potentialRaw).getDerivedFrom()) + .addDerivedNamespace(derivedContext); + return derivedContext; } - throw new NamespaceNotAvailableException("Namespace " + type + " is not available in phase " + currentPhase); + return new SimpleNamespaceContext<>(potentialRaw); } public StatementDefinitionContext getStatementDefinition(final QName name) { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ModifierImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ModifierImpl.java index 1c71972237..254b65c76b 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ModifierImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ModifierImpl.java @@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor; import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.EFFECTIVE_MODEL; import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.FULL_DECLARATION; + import com.google.common.base.Function; import com.google.common.base.Preconditions; import java.util.HashSet; @@ -62,16 +63,6 @@ class ModifierImpl implements ModelActionBuilder { return new IllegalStateException("Source exception during registering prerequisite. This is probably bug.",e); } - private void tryToResolve() throws InferenceException { - if(action == null || isApplied()) { - // Action was not yet defined - return; - } - if(removeSatisfied()) { - applyAction(); - } - } - private boolean removeSatisfied() { Iterator> prereq = unsatisfied.iterator(); boolean allSatisfied = true; @@ -102,14 +93,8 @@ class ModifierImpl implements ModelActionBuilder { } private void applyAction() throws InferenceException { - - try { - action.apply(); - } catch (InferenceException e) { - actionApplied = false; - return; - } - //  Mark all mutations as performed, so context node could move to next. + Preconditions.checkState(!actionApplied); + action.apply(); actionApplied = true; } @@ -139,10 +124,11 @@ class ModifierImpl implements ModelActionBuilder { } @SuppressWarnings({ "rawtypes", "unchecked" }) - private , N extends StatementNamespace> AbstractPrerequisite mutatesCtxImpl( + private , N extends IdentifierNamespace>> AbstractPrerequisite mutatesCtxImpl( final StmtContext context, final Class namespace, final K key, final ModelProcessingPhase phase) { try { PhaseModificationInNamespace mod = new PhaseModificationInNamespace(phase); + addReq(mod); addMutation(mod); contextImpl(context).onNamespaceItemAddedAction((Class) namespace,key,mod); return mod; @@ -151,9 +137,19 @@ class ModifierImpl implements ModelActionBuilder { } } - private static StatementContextBase contextImpl(final StmtContext context) { - Preconditions.checkArgument(context instanceof StatementContextBase,"Supplied context was not provided by this reactor."); - return StatementContextBase.class.cast(context); + private static StatementContextBase contextImpl(final Object value) { + Preconditions.checkArgument(value instanceof StatementContextBase,"Supplied context was not provided by this reactor."); + return StatementContextBase.class.cast(value); + } + + boolean tryApply() { + Preconditions.checkState(action != null, "Action was not defined yet."); + + if (removeSatisfied()) { + applyAction(); + return true; + } + return false; } @Override @@ -230,7 +226,7 @@ class ModifierImpl implements ModelActionBuilder { @Override - public , N extends StatementNamespace> AbstractPrerequisite> mutatesEffectiveCtx( + public , N extends IdentifierNamespace>> AbstractPrerequisite> mutatesEffectiveCtx( final StmtContext context, final Class namespace, final K key) { return mutatesCtxImpl(context, namespace, key, EFFECTIVE_MODEL); } @@ -240,7 +236,6 @@ class ModifierImpl implements ModelActionBuilder { @Override public void apply(final InferenceAction action) throws InferenceException { this.action = Preconditions.checkNotNull(action); - tryToResolve(); } private abstract class AbstractPrerequisite implements Prerequisite { @@ -262,7 +257,6 @@ class ModifierImpl implements ModelActionBuilder { protected boolean resolvePrereq(final T value) throws InferenceException { this.value = value; this.done = true; - tryToResolve(); return isApplied(); } @@ -353,8 +347,9 @@ class ModifierImpl implements ModelActionBuilder { @Override public void namespaceItemAdded(final StatementContextBase context, final Class namespace, final Object key, final Object value) throws SourceException { - context.addMutation(modPhase,this); - resolvePrereq((C) context); + StatementContextBase targetCtx = contextImpl(value); + targetCtx.addMutation(modPhase,this); + resolvePrereq((C) targetCtx); } @Override diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/NamespaceBehaviourWithListeners.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/NamespaceBehaviourWithListeners.java index c4bbb76f00..1f10c18a96 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/NamespaceBehaviourWithListeners.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/NamespaceBehaviourWithListeners.java @@ -7,76 +7,78 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.reactor; -import com.google.common.base.Optional; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import java.util.Collection; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Map; -import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; -import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; -import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleIdentifierImpl; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; -final class NamespaceBehaviourWithListeners> extends NamespaceBehaviour { +abstract class NamespaceBehaviourWithListeners> + extends NamespaceBehaviour { - abstract static class ValueAddedListener { + abstract static class ValueAddedListener { private final NamespaceStorageNode ctxNode; + private K key; - public ValueAddedListener(final NamespaceStorageNode contextNode) { + public ValueAddedListener(final NamespaceStorageNode contextNode, K key) { this.ctxNode = contextNode; + this.key = key; + } + + public NamespaceStorageNode getCtxNode() { + return ctxNode; + } + + public K getKey() { + return key; } abstract void onValueAdded(Object key, Object value); } private final NamespaceBehaviour delegate; - private final Multimap listeners = HashMultimap.create(); + private final List> derivedNamespaces = new ArrayList<>(); + protected NamespaceBehaviourWithListeners(final NamespaceBehaviour delegate) { super(delegate.getIdentifier()); this.delegate = delegate; } + protected abstract void addListener(K key, ValueAddedListener listener); + + protected abstract Iterator> getMutableListeners(K key); + + protected abstract boolean isRequestedValue(ValueAddedListener listener, NamespaceStorageNode storage, V value); + @Override public void addTo(final NamespaceStorageNode storage, final K key, final V value) { delegate.addTo(storage, key, value); - Iterator keyListeners = listeners.get(key).iterator(); + Iterator> keyListeners = getMutableListeners(key); + List> toNotify = new ArrayList<>(); while (keyListeners.hasNext()) { - ValueAddedListener listener = keyListeners.next(); - if (listener.ctxNode == storage || hasIdentiticalValue(listener.ctxNode,key,value)) { + ValueAddedListener listener = keyListeners.next(); + if (isRequestedValue(listener, storage, value)) { keyListeners.remove(); - listener.onValueAdded(key, value); + toNotify.add(listener); } } - - if (key instanceof ModuleIdentifier && !listeners.isEmpty()) { - Collection defaultImportListeners = getDefaultImportListeners((ModuleIdentifier) key); - Iterator defaultImportsIterator = defaultImportListeners.iterator(); - while (defaultImportsIterator.hasNext()) { - ValueAddedListener listener = defaultImportsIterator.next(); - if(listener.ctxNode == storage || hasIdentiticalValue(listener.ctxNode,key,value)) { - defaultImportsIterator.remove(); - listener.onValueAdded(key, value); - } - } + for(ValueAddedListener listener : toNotify) { + listener.onValueAdded(key, value); + } + for (VirtualNamespaceContext derived : derivedNamespaces) { + derived.addTo(storage, null, value); } } - private Collection getDefaultImportListeners(final ModuleIdentifier key) { - ModuleIdentifier defaultImportKey = new ModuleIdentifierImpl(key.getName(), - Optional.fromNullable(key.getNamespace()), Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_IMP)); - return listeners.get((K)defaultImportKey); - } - - private boolean hasIdentiticalValue(final NamespaceStorageNode ctxNode, final K key, final V value) { - return getFrom(ctxNode, key) == value; + final void addValueListener(final ValueAddedListener listener) { + addListener(listener.key, listener); } - void addValueListener(final K key, final ValueAddedListener listener) { - listeners.put(key, listener); + final void addDerivedNamespace(VirtualNamespaceContext namespace) { + derivedNamespaces.add(namespace); } @Override diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/RootStatementContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/RootStatementContext.java index 8c883dd265..b1bf364e0c 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/RootStatementContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/RootStatementContext.java @@ -15,6 +15,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry; +import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; @@ -100,6 +101,10 @@ public class RootStatementContext, E extends E return sourceContext; } + @Override + public StorageNodeType getStorageNodeType() { + return StorageNodeType.ROOT_STATEMENT_LOCAL; + } /** * @return this as its own root */ diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SimpleNamespaceContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SimpleNamespaceContext.java new file mode 100644 index 0000000000..01e499f37c --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SimpleNamespaceContext.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.parser.stmt.reactor; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; +import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; + +final class SimpleNamespaceContext> + extends NamespaceBehaviourWithListeners { + + // FIXME: Change this to Multimap, once issue with modules + // is resolved. + private final List> listeners = new ArrayList<>(); + public SimpleNamespaceContext(NamespaceBehaviour delegate) { + super(delegate); + } + + protected boolean isRequestedValue(NamespaceBehaviourWithListeners.ValueAddedListener listener, NamespaceStorageNode storage, V value) { + NamespaceStorageNode listenerCtx = listener.getCtxNode(); + return value == getFrom(listenerCtx, listener.getKey()); + } + + @Override + protected void addListener(K key, NamespaceBehaviourWithListeners.ValueAddedListener listener) { + listeners.add(listener); + } + + @Override + protected Iterator> getMutableListeners(K key) { + return listeners.iterator(); + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java index db760d0792..b11d2a40aa 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java @@ -255,11 +255,11 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh PhaseCompletionProgress tryToCompletePhase(final ModelProcessingPhase phase) throws SourceException { Collection currentPhaseModifiers = modifiers.get(phase); - boolean hasProgressed = hasProgress(currentPhaseModifiers); + boolean hasProgressed = tryToProgress(currentPhaseModifiers); boolean phaseCompleted = root.tryToCompletePhase(phase); - hasProgressed = (hasProgress(currentPhaseModifiers) | hasProgressed); + hasProgressed = (tryToProgress(currentPhaseModifiers) | hasProgressed); if (phaseCompleted && (currentPhaseModifiers.isEmpty())) { finishedPhase = phase; @@ -273,12 +273,12 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh } - private static boolean hasProgress(final Collection currentPhaseModifiers) { + private static boolean tryToProgress(final Collection currentPhaseModifiers) { Iterator modifier = currentPhaseModifiers.iterator(); boolean hasProgressed = false; while (modifier.hasNext()) { - if (modifier.next().isApplied()) { + if (modifier.next().tryApply()) { modifier.remove(); hasProgressed = true; } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java index d28dc9a458..5e05a47580 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java @@ -7,9 +7,6 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.reactor; -import java.util.LinkedList; - -import java.util.List; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; import com.google.common.collect.HashMultimap; @@ -20,6 +17,8 @@ import java.util.Collections; import java.util.EventListener; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import javax.annotation.Nonnull; import org.opendaylight.yangtools.concepts.Identifiable; @@ -486,7 +485,7 @@ public abstract class StatementContextBase, E NamespaceBehaviour behaviour = getBehaviourRegistry().getNamespaceBehaviour(type); if (behaviour instanceof NamespaceBehaviourWithListeners) { NamespaceBehaviourWithListeners casted = (NamespaceBehaviourWithListeners) behaviour; - casted.addValueListener(key, new ValueAddedListener(this) { + casted.addValueListener(new ValueAddedListener(this, key) { @Override void onValueAdded(Object key, Object value) { try { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java index 4c3be3e9a2..04a01d17fc 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java @@ -63,10 +63,6 @@ class SubstatementContext, E extends Effective } else { this.argument = original.argument; } - - copyDeclaredStmts(original, newQNameModule, typeOfCopy); - - copyEffectiveStmts(original, newQNameModule, typeOfCopy); } private void copyDeclaredStmts(SubstatementContext original, @@ -150,6 +146,9 @@ class SubstatementContext, E extends Effective } definition().onStatementAdded(copy); + + copy.copyDeclaredStmts(this, newQNameModule, typeOfCopy); + copy.copyEffectiveStmts(this, newQNameModule, typeOfCopy); return copy; } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/VirtualNamespaceContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/VirtualNamespaceContext.java new file mode 100644 index 0000000000..75c4b5e50f --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/VirtualNamespaceContext.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.parser.stmt.reactor; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; +import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; + +final class VirtualNamespaceContext> + extends NamespaceBehaviourWithListeners { + + private final List> listeners = new ArrayList<>(20); + + public VirtualNamespaceContext(NamespaceBehaviour delegate) { + super(delegate); + } + + protected boolean isRequestedValue(NamespaceBehaviourWithListeners.ValueAddedListener listener, NamespaceStorageNode storage, V value) { + return value == getFrom(listener.getCtxNode(), listener.getKey()); + } + + @Override + protected void addListener(K key, NamespaceBehaviourWithListeners.ValueAddedListener listener) { + listeners.add(listener); + } + + @Override + protected Iterator> getMutableListeners(K key) { + return listeners.iterator(); + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentStatementImpl.java index 9e39f9009f..96e311a357 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentStatementImpl.java @@ -22,8 +22,10 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport; import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder; +import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.AugmentEffectiveStatementImpl; @@ -78,32 +80,21 @@ public class AugmentStatementImpl extends } final ModelActionBuilder augmentAction = augmentNode - .newInferenceAction(ModelProcessingPhase.FULL_DECLARATION); + .newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL); final ModelActionBuilder.Prerequisite>> sourceCtxPrereq = augmentAction - .requiresCtx(augmentNode, - ModelProcessingPhase.FULL_DECLARATION); - + .requiresCtx(augmentNode, ModelProcessingPhase.EFFECTIVE_MODEL); + final Prerequisite>> target = augmentAction.mutatesEffectiveCtx(getSearchRoot(augmentNode), SchemaNodeIdentifierBuildNamespace.class, augmentNode.getStatementArgument()); augmentAction.apply(new ModelActionBuilder.InferenceAction() { @Override public void apply() throws InferenceException { - final StatementContextBase augmentTargetCtx = AugmentUtils - .getAugmentTargetCtx(augmentNode); - - if (augmentTargetCtx == null) { - throw new InferenceException( - "Augment target not found: " - + augmentNode.getStatementArgument(), - augmentNode.getStatementSourceReference()); - } + final StatementContextBase augmentTargetCtx = (StatementContextBase) target.get(); if (!AugmentUtils.isSupportedAugmentTarget(augmentTargetCtx) || StmtContextUtils.isInExtensionBody(augmentTargetCtx)) { augmentNode.setIsSupportedToBuildEffective(false); return; } - final StatementContextBase augmentSourceCtx = (StatementContextBase) augmentNode; - try { AugmentUtils.copyFromSourceToTarget(augmentSourceCtx, augmentTargetCtx); @@ -141,6 +132,15 @@ public class AugmentStatementImpl extends } }); } + + private Mutable getSearchRoot(Mutable augmentContext) { + Mutable parent = augmentContext.getParentContext(); + // Augment is in uses - we need to augment instantiated nodes in parent. + if(Rfc6020Mapping.USES.equals(parent.getPublicDefinition())) { + return parent.getParentContext(); + } + return parent; + } } @Nonnull diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentUtils.java index dd14bf87d9..c71ba67c9a 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentUtils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentUtils.java @@ -10,65 +10,48 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; -import javax.annotation.Nullable; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping; -import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement; import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement; import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement; -import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; -import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.TypeOfCopy; -import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; -import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType; import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +// FIXME: Move this to the AugmentStatementDefinition#ApplyAction public final class AugmentUtils { - private static final Logger LOG = LoggerFactory.getLogger(AugmentUtils.class); private static final Pattern PATH_REL_PATTERN1 = Pattern.compile("\\.\\.?\\s*/(.+)"); private static final Pattern PATH_REL_PATTERN2 = Pattern.compile("//.*"); private AugmentUtils() { - throw new UnsupportedOperationException(); } public static Iterable parseAugmentPath(final StmtContext ctx, final String path) { Preconditions.checkArgument(!PATH_REL_PATTERN1.matcher(path).matches() && !PATH_REL_PATTERN2.matcher(path).matches(), - "An argument for augment can be only absolute path; or descendant if used in uses"); - + "An argument for augment can be only absolute path; or descendant if used in uses"); return Utils.parseXPath(ctx, path); } public static void copyFromSourceToTarget(final StatementContextBase sourceCtx, final StatementContextBase targetCtx) throws SourceException { - copyDeclaredStmts(sourceCtx, targetCtx); copyEffectiveStmts(sourceCtx, targetCtx); } - public static void copyDeclaredStmts(final StatementContextBase sourceCtx, + // FIXME: Declared statements should not be copied. + private static void copyDeclaredStmts(final StatementContextBase sourceCtx, final StatementContextBase targetCtx) throws SourceException { final List> subStatements = new Builder>() @@ -91,7 +74,7 @@ public final class AugmentUtils { } } - public static void copyEffectiveStmts(final StatementContextBase sourceCtx, + private static void copyEffectiveStmts(final StatementContextBase sourceCtx, final StatementContextBase targetCtx) throws SourceException { final List> subStatements = new Builder>() @@ -115,54 +98,41 @@ public final class AugmentUtils { } private static void validateNodeCanBeCopiedByAugment(final StatementContextBase sourceCtx, - final Iterable> targetSubStatements, - final boolean sourceAndTargetInSameModule) { + final List> targetSubStatements, final boolean sourceAndTargetInSameModule) { - if (WhenStatement.class.equals(sourceCtx.getPublicDefinition().getDeclaredRepresentationClass())) { + if (sourceCtx.getPublicDefinition().getDeclaredRepresentationClass().equals(WhenStatement.class)) { return; } if (!sourceAndTargetInSameModule) { - for (final StatementContextBase sourceSubStatement : - Iterables.concat(sourceCtx.declaredSubstatements(), sourceCtx.effectiveSubstatements())) { - Preconditions.checkArgument(!MandatoryStatement.class.equals( - sourceSubStatement.getPublicDefinition().getDeclaredRepresentationClass()), - "An augment cannot add node '%s' because it is mandatory and in module different from target", - sourceCtx.rawStatementArgument()); + final List> sourceSubStatements = new Builder>() + .addAll(sourceCtx.declaredSubstatements()).addAll(sourceCtx.effectiveSubstatements()).build(); + + for (final StatementContextBase sourceSubStatement : sourceSubStatements) { + if (sourceSubStatement.getPublicDefinition().getDeclaredRepresentationClass() + .equals(MandatoryStatement.class)) { + throw new IllegalArgumentException( + String.format( + "An augment cannot add node '%s' because it is mandatory and in module different from target", + sourceCtx.rawStatementArgument())); + } } } for (final StatementContextBase subStatement : targetSubStatements) { - final boolean sourceIsDataNode = DataDefinitionStatement.class.isAssignableFrom( - sourceCtx.getPublicDefinition().getDeclaredRepresentationClass()); - final boolean targetIsDataNode = DataDefinitionStatement.class.isAssignableFrom( - subStatement.getPublicDefinition().getDeclaredRepresentationClass()); - Preconditions.checkState(!sourceIsDataNode || !targetIsDataNode - || !Objects.equals(sourceCtx.getStatementArgument(), subStatement.getStatementArgument()), - "An augment cannot add node named '%s' because this name is already used in target", - sourceCtx.rawStatementArgument()); - } - } - - public static QNameModule getNewQNameModule(final StatementContextBase targetCtx, - final StatementContextBase sourceCtx) { - Object targetStmtArgument = targetCtx.getStatementArgument(); - - final StatementContextBase root = sourceCtx.getRoot(); - final QNameModule sourceQNameModule = root.getFromNamespace(ModuleCtxToModuleQName.class, root); - - if (targetStmtArgument instanceof QName) { - QName targetQName = (QName) targetStmtArgument; - QNameModule targetQNameModule = targetQName.getModule(); - - if (targetQNameModule.equals(sourceQNameModule)) { - return null; - } else { - return targetQNameModule; + final boolean sourceIsDataNode = DataDefinitionStatement.class.isAssignableFrom(sourceCtx + .getPublicDefinition().getDeclaredRepresentationClass()); + final boolean targetIsDataNode = DataDefinitionStatement.class.isAssignableFrom(subStatement + .getPublicDefinition().getDeclaredRepresentationClass()); + boolean qNamesEqual = sourceIsDataNode && targetIsDataNode + && Objects.equals(sourceCtx.getStatementArgument(), subStatement.getStatementArgument()); + + if (qNamesEqual) { + throw new IllegalStateException(String.format( + "An augment cannot add node named '%s' because this name is already used in target", + sourceCtx.rawStatementArgument())); } - } else { - return null; } } @@ -178,100 +148,7 @@ public final class AugmentUtils { return REUSED_DEF_SET.contains(stmtContext.getPublicDefinition()); } - public static StatementContextBase getAugmentTargetCtx( - final Mutable> augmentNode) { - - final SchemaNodeIdentifier augmentTargetNode = augmentNode.getStatementArgument(); - Preconditions.checkArgument(augmentTargetNode != null, - "Augment argument null, something bad happened in some of previous parsing phases"); - - List> rootStatementCtxList = new ArrayList<>(); - if (augmentTargetNode.isAbsolute()) { - - QNameModule module = augmentTargetNode.getPathFromRoot().iterator().next().getModule(); - - StatementContextBase rootStatementCtx = - (StatementContextBase) augmentNode.getFromNamespace(NamespaceToModule.class, module); - rootStatementCtxList.add(rootStatementCtx); - - final Map subModules = rootStatementCtx.getAllFromNamespace(IncludedModuleContext.class); - if (subModules != null) { - rootStatementCtxList.addAll((Collection>) subModules.values()); - } - - } else { - StatementContextBase parent = (StatementContextBase) augmentNode.getParentContext(); - if (StmtContextUtils.producesDeclared(parent, UsesStatement.class)) { - rootStatementCtxList.add(parent.getParentContext()); - } else { - // error - } - } - - StatementContextBase augmentTargetCtx = null; - for (final StatementContextBase rootStatementCtx : rootStatementCtxList) { - augmentTargetCtx = findCtxOfNodeInRoot(rootStatementCtx, augmentTargetNode); - if (augmentTargetCtx != null) { - break; - } - } - - return augmentTargetCtx; - } - - @Nullable - public static StatementContextBase findCtxOfNodeInSubstatements(final StatementContextBase rootStmtCtx, - final Iterable path) { - - StatementContextBase parent = rootStmtCtx; - - Iterator pathIter = path.iterator(); - while (pathIter.hasNext()) { - QName nextPathQName = pathIter.next(); - StatementContextBase foundSubstatement = getSubstatementByQName(parent, nextPathQName); - - if (foundSubstatement == null) { - return null; - } - if (!pathIter.hasNext()) { - return foundSubstatement; - } - - parent = foundSubstatement; - } - - return null; - } - - public static StatementContextBase getSubstatementByQName(final StatementContextBase parent, - final QName nextPathQName) { - - Collection> declaredSubstatement = parent.declaredSubstatements(); - Collection> effectiveSubstatement = parent.effectiveSubstatements(); - - for (StatementContextBase substatement : Iterables.concat(declaredSubstatement, effectiveSubstatement)) { - Object substatementArgument = substatement.getStatementArgument(); - QName substatementQName; - if (substatementArgument instanceof QName) { - substatementQName = (QName) substatementArgument; - - if (nextPathQName.getLocalName().equals( - substatementQName.getLocalName())) { - if (isSupportedAugmentTarget(substatement)) { - return substatement; - } else if (Utils.isUnknownNode(substatement)) { - LOG.warn("Module '{}': augment into unknown node '{}'.", - substatement.getRoot().getStatementArgument(), substatementArgument); - return substatement; - } - } - } - } - - return null; - } - - public static boolean isSupportedAugmentTarget(final StatementContextBase substatementCtx) { + static boolean isSupportedAugmentTarget(final StatementContextBase substatementCtx) { /* * :TODO Substatement must be allowed augment target type e.g. Container, etc... and must be not for example @@ -287,10 +164,4 @@ public final class AugmentUtils { return allowedAugmentTargets == null || allowedAugmentTargets.isEmpty() || allowedAugmentTargets.contains(substatementCtx.getPublicDefinition()); } - - @Nullable - public static StatementContextBase findCtxOfNodeInRoot(final StatementContextBase rootStmtCtx, - final SchemaNodeIdentifier node) { - return findCtxOfNodeInSubstatements(rootStmtCtx, node.getPathFromRoot()); - } } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChildSchemaNodes.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChildSchemaNodes.java index b9761b1a91..6482c99f51 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChildSchemaNodes.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChildSchemaNodes.java @@ -7,10 +7,13 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; +import java.util.Map; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; +import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; /** * Statement local namespace, which holds direct schema node descendants. @@ -18,6 +21,42 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace; * @param * @param */ -public interface ChildSchemaNodes,E extends EffectiveStatement> extends StatementNamespace{ +public class ChildSchemaNodes,E extends EffectiveStatement> + extends NamespaceBehaviour, ChildSchemaNodes> + implements StatementNamespace{ + protected ChildSchemaNodes() { + super((Class>) (Class) ChildSchemaNodes.class); + } + + @Override + public StmtContext get(QName key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public StmtContext getFrom(NamespaceStorageNode storage, QName key) { + return globalOrStatementSpecific(storage).getFromLocalStorage(getIdentifier(), key); + } + + @Override + public Map> getAllFrom(NamespaceStorageNode storage) { + // TODO Auto-generated method stub + return null; + } + + @SuppressWarnings("unchecked") + @Override + public void addTo(NamespaceBehaviour.NamespaceStorageNode storage, QName key, StmtContext value) { + globalOrStatementSpecific(storage).addToLocalStorage(ChildSchemaNodes.class, key, value); + } + + private NamespaceStorageNode globalOrStatementSpecific(NamespaceBehaviour.NamespaceStorageNode storage) { + NamespaceStorageNode current = storage; + while(current.getStorageNodeType() != StorageNodeType.STATEMENT_LOCAL && current.getStorageNodeType() != StorageNodeType.GLOBAL) { + current = current.getParentNamespaceStorage(); + } + return current; + } } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java new file mode 100644 index 0000000000..bee80c9ba0 --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; + +import java.util.Iterator; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; +import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedNamespaceBehaviour; +import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; + +class SchemaNodeIdentifierBuildNamespace extends + DerivedNamespaceBehaviour>, SchemaNodeIdentifierBuildNamespace, ChildSchemaNodes> + implements IdentifierNamespace>> { + + @SuppressWarnings({"unchecked", "rawtypes"}) + protected SchemaNodeIdentifierBuildNamespace() { + super(SchemaNodeIdentifierBuildNamespace.class, (Class) ChildSchemaNodes.class); + } + + @Override + public StmtContext.Mutable> get( + SchemaNodeIdentifier key) { + throw new UnsupportedOperationException("Direct access to namespace is not supported"); + } + + @Override + public StmtContext.Mutable> getFrom(NamespaceStorageNode storage, SchemaNodeIdentifier key) { + + final NamespaceStorageNode lookupStartStorage; + if(key.isAbsolute() || storage.getStorageNodeType() == StorageNodeType.ROOT_STATEMENT_LOCAL) { + lookupStartStorage = NamespaceBehaviour.findClosestTowardsRoot(storage, StorageNodeType.GLOBAL); + } else { + lookupStartStorage = storage; + } + Iterator iterator = key.getPathFromRoot().iterator(); + if(!iterator.hasNext()) { + if(lookupStartStorage instanceof StmtContext) { + return (StmtContext.Mutable>) lookupStartStorage; + } else { + return null; + } + } + StmtContext.Mutable> current = (StmtContext.Mutable>) lookupStartStorage.getFromLocalStorage(ChildSchemaNodes.class, iterator.next()); + while(current != null && iterator.hasNext()) { + current = (StmtContext.Mutable>) current.getFromNamespace(ChildSchemaNodes.class, iterator.next()); + } + return current; + } + +} diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java index 514b9f0408..57e5bb0368 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java @@ -30,6 +30,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite; +import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; @@ -67,13 +68,13 @@ public class UsesStatementImpl extends AbstractDeclaredStatement implemen return; } - ModelActionBuilder usesAction = usesNode.newInferenceAction(FULL_DECLARATION); + ModelActionBuilder usesAction = usesNode.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL); final QName groupingName = usesNode.getStatementArgument(); final Prerequisite> sourceGroupingPre = usesAction.requiresCtx(usesNode, - GroupingNamespace.class, groupingName, FULL_DECLARATION); - final Prerequisite> targetNodePre = usesAction.mutatesCtx( - usesNode.getParentContext(), FULL_DECLARATION); + GroupingNamespace.class, groupingName, ModelProcessingPhase.EFFECTIVE_MODEL); + final Prerequisite> targetNodePre = usesAction.mutatesEffectiveCtx( + usesNode.getParentContext()); usesAction.apply(new InferenceAction() { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java index 389456e361..e491c5975d 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java @@ -297,14 +297,9 @@ public final class Utils { } @Nullable - public static StatementContextBase findNode(final StatementContextBase rootStmtCtx, + public static StatementContextBase findNode(final StmtContext rootStmtCtx, final SchemaNodeIdentifier node) { - StatementContextBase current = rootStmtCtx; - Iterator arguments = node.getPathFromRoot().iterator(); - while(current != null && arguments.hasNext()) { - current = (StatementContextBase) current.getFromNamespace(ChildSchemaNodes.class, arguments.next()); - } - return current; + return (StatementContextBase) rootStmtCtx.getFromNamespace(SchemaNodeIdentifierBuildNamespace.class, node); } public static SchemaPath getSchemaPath(final StmtContext ctx) { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java index 9f316ec949..6dd2595d3e 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java @@ -83,7 +83,8 @@ public final class YangInferencePipeline { .addSupport(new YinElementStatementImpl.Definition()) .addSupport(new ArgumentStatementImpl.Definition()) .addSupport(new ExtensionStatementImpl.Definition()) - .addSupport(global(ChildSchemaNodes.class)) + .addSupport(new ChildSchemaNodes()) + .addSupport(new SchemaNodeIdentifierBuildNamespace()) .addSupport(global(ExtensionNamespace.class)) .addSupport(new TypedefStatementImpl.Definition()) .addSupport(treeScoped(TypeNamespace.class)) diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/AugmentProcessTest.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/AugmentProcessTest.java index fdc1802e68..890c47b0fc 100644 --- a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/AugmentProcessTest.java +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/AugmentProcessTest.java @@ -33,6 +33,7 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.meta.ModelStatement; import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource; import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor; @@ -108,11 +109,7 @@ public class AugmentProcessTest { MULTIPLE_AUGMENT_SUBMODULE); EffectiveSchemaContext result = null; - try { - result = reactor.buildEffective(); - } catch (Exception e) { - log(e, ""); - } + result = reactor.buildEffective(); assertNotNull(result); } @@ -123,15 +120,11 @@ public class AugmentProcessTest { addSources(reactor, MULTIPLE_AUGMENT); EffectiveSchemaContext result = null; - try { - result = reactor.buildEffective(); - } catch (Exception e) { - log(e, ""); - } + result = reactor.buildEffective(); assertNotNull(result); } - @Test + @Test(expected=SomeModifiersUnresolvedException.class) public void multipleAugmentIncorrectPathTest() throws SourceException, ReactorException { CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR @@ -139,40 +132,22 @@ public class AugmentProcessTest { addSources(reactor, MULTIPLE_AUGMENT_INCORRECT); EffectiveSchemaContext result = null; - try { - result = reactor.buildEffective(); - } catch (Exception e) { - log(e, ""); - } - + result = reactor.buildEffective(); assertNull(result); } - @Test + @Test(expected=SomeModifiersUnresolvedException.class) public void multipleAugmentIncorrectPathAndGrpTest() throws SourceException, ReactorException { CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR .newBuild(); addSources(reactor, MULTIPLE_AUGMENT_INCORRECT2); - EffectiveSchemaContext result = null; - try { - result = reactor.buildEffective(); - } catch (Exception e) { - log(e, ""); - } - + result = reactor.buildEffective(); assertNull(result); } - private void log(final Throwable e, final String indent) { - System.out.println(indent + e.getMessage()); - Throwable[] suppressed = e.getSuppressed(); - for (Throwable throwable : suppressed) { - log(throwable, indent + " "); - } - } @Test public void readAndParseYangFileTest() throws SourceException, diff --git a/yang/yang-parser-impl/src/test/resources/model-new/foo.yang b/yang/yang-parser-impl/src/test/resources/model-new/foo.yang index ba12bd6ee7..1c361e4b5c 100644 --- a/yang/yang-parser-impl/src/test/resources/model-new/foo.yang +++ b/yang/yang-parser-impl/src/test/resources/model-new/foo.yang @@ -130,7 +130,7 @@ module foo { status obsolete; } - augment "/br:interfaces/br:ifEntry/br:augment-holder" { + augment "/br:interfaces/br:ifEntry/bz:augment-holder" { when "if:ifType='ds0'"; leaf ds0ChannelNumber { type string; diff --git a/yang/yang-parser-impl/src/test/resources/model-new/subfoo.yang b/yang/yang-parser-impl/src/test/resources/model-new/subfoo.yang index 190053010c..412f9c15a9 100644 --- a/yang/yang-parser-impl/src/test/resources/model-new/subfoo.yang +++ b/yang/yang-parser-impl/src/test/resources/model-new/subfoo.yang @@ -54,7 +54,7 @@ submodule subfoo { status obsolete; } - augment "/br:interfaces/br:ifEntry/br:augment-holder" { + augment "/br:interfaces/br:ifEntry/bz:augment-holder" { when "if:ifType='ds0'"; leaf subleaf { type string; diff --git a/yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-imported.yang b/yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-imported.yang index 0d030b23fa..26ec3c8978 100644 --- a/yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-imported.yang +++ b/yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-imported.yang @@ -3,10 +3,6 @@ module multiple-augment-imported { namespace "multiple-augment-imported"; prefix imp; - augment /root-container/container-from-grp1/sub-container-from-grp1/container-in-uses-augment/sub-container-from-augment2/sub-container-from-augment3 { - container sub-container-from-augment4 { - } - } container root-container { uses grp1 { @@ -29,11 +25,6 @@ module multiple-augment-imported { } } - augment /root-container/added-container-1 { - container added-container-2 { - } - } - grouping grp2 { container container-from-grp2 { container sub-container-from-grp2 { @@ -51,10 +42,10 @@ module multiple-augment-imported { container sub-container-from-augment2 { } } - + grouping grp-from-import { container container-from-grp-from-import { - + } } } diff --git a/yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-root.yang b/yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-root.yang index 88123f7736..5ec75d342b 100644 --- a/yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-root.yang +++ b/yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-root.yang @@ -4,7 +4,7 @@ module multiple-augment-root { prefix root; import multiple-augment-imported { prefix imp; revision-date 1970-01-01; } - + include multiple-augment-submodule { revision-date 1970-01-01; } augment /imp:root-container/imp:container-from-grp1/imp:sub-container-from-grp1/imp:container-in-uses-augment/imp:sub-container-from-augment2 { @@ -22,7 +22,7 @@ module multiple-augment-root { } } - augment /imp:root-container/imp:container-from-grp1/imp:sub-container-from-grp1/imp:container-from-grp2/imp:sub-container-from-grp2/imp:sub-container-from-augment5 { + augment /imp:root-container/imp:container-from-grp1/imp:sub-container-from-grp1/imp:container-from-grp2/imp:sub-container-from-grp2/sub-container-from-augment5 { container sub-container-from-augment7 { } } @@ -36,7 +36,7 @@ module multiple-augment-root { container added-container-1 { } } - + container container-with-multiple-uses { uses imp:grp-from-import{ augment container-from-grp-from-import { -- 2.36.6