Revert "Revert "Updated SchemaNodeIdentifier namespace handling."" 71/27871/2
authorTony Tkacik <ttkacik@cisco.com>
Sat, 3 Oct 2015 12:22:49 +0000 (12:22 +0000)
committerRobert Varga <rovarga@cisco.com>
Sat, 3 Oct 2015 15:34:25 +0000 (17:34 +0200)
Bringing back updated augment lookup and validation code
which turned out to be correct, but unfortunatelly original
implementation of parser (from Hydrogen) accepted incorrect
values and "normalized" them to probably what user really intented.

New code is stricter and did not accept that input, since
it really was unclear what user intented.

Change-Id: I187c3479fd7bbb986f414805401e8b54f6b49ee0
Release-Note: Incompatible-Behaviour
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
24 files changed:
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/DerivedNamespaceBehaviour.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ModelActionBuilder.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/NamespaceBehaviour.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ModifierImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/NamespaceBehaviourWithListeners.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/RootStatementContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SimpleNamespaceContext.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/VirtualNamespaceContext.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentUtils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChildSchemaNodes.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/AugmentProcessTest.java
yang/yang-parser-impl/src/test/resources/model-new/foo.yang
yang/yang-parser-impl/src/test/resources/model-new/subfoo.yang
yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-imported.yang
yang/yang-parser-impl/src/test/resources/stmt-test/augments/multiple-augment-root.yang

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 (file)
index 0000000..03dbfa8
--- /dev/null
@@ -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<K, V, N extends IdentifierNamespace<K, V>, T extends IdentifierNamespace<?, ?>>
+        extends NamespaceBehaviour<K, V, N> {
+
+    private Class<T> derivedFrom;
+
+    protected DerivedNamespaceBehaviour(Class<N> identifier, Class<T> derivedFrom) {
+        super(identifier);
+        this.derivedFrom = Preconditions.checkNotNull(derivedFrom);
+    }
+
+    public Class<T> getDerivedFrom() {
+        return derivedFrom;
+    }
+
+    @Override
+    public Map<K, V> 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
+    }
+}
index 41d22500e432eb3acb41ae7f7f58d1c05c92d39f..54605dbc67961e55fc9d78b7f38adf8d1a32571e 100644 (file)
@@ -151,7 +151,7 @@ public interface ModelActionBuilder {
 
     @Nonnull <T extends Mutable<?,?,?>> Prerequisite<T> mutatesEffectiveCtx(T stmt);
 
-    @Nonnull  <K,E extends EffectiveStatement<?,?>,N extends StatementNamespace<K, ?, ? extends E>> Prerequisite<Mutable<?,?,E>> mutatesEffectiveCtx(StmtContext<?,?,?> context,Class<N> namespace, K key);
+    @Nonnull  <K,E extends EffectiveStatement<?,?>, N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>> Prerequisite<Mutable<?,?,E>> mutatesEffectiveCtx(StmtContext<?,?,?> context,Class<N> namespace, K key);
 
     void apply(InferenceAction action) throws InferenceException;
 
index 6d156b1c837f2eb75f1001bf1439848309030b59..53c12ccd5712e14940d51c60c8f87e34e29625c7 100644 (file)
@@ -33,7 +33,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
 public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K, V>> implements Identifiable<Class<N>> {
 
     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<K, V, N extends IdentifierNamespace<K,
 
         @Override
         public V getFrom(final NamespaceStorageNode storage, final K key) {
-            NamespaceStorageNode current = storage;
-            while (current.getStorageNodeType() != storageType) {
-                current = current.getParentNamespaceStorage();
-            }
+            NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
             return getFromLocalStorage(current, key);
         }
 
@@ -203,10 +200,7 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
 
         @Override
         public void addTo(NamespaceBehaviour.NamespaceStorageNode storage, K key, V value) {
-            NamespaceStorageNode current = storage;
-            while (current.getStorageNodeType() != storageType) {
-                current = current.getParentNamespaceStorage();
-            }
+            NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
             addToStorage(current, key, value);
         }
 
@@ -250,4 +244,12 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
         }
 
     }
+
+    protected static NamespaceStorageNode findClosestTowardsRoot(NamespaceStorageNode storage, StorageNodeType type) {
+        NamespaceStorageNode current = storage;
+        while(current != null && current.getStorageNodeType() != type) {
+            current = current.getParentNamespaceStorage();
+        }
+        return current;
+    }
 }
index a7041f2f14040c117557dc1f7bd75c0e7696e564..f6d935e6145ab46b7ceaaf241d874db77ee7e927 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
+import com.google.common.base.Verify;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import java.util.ArrayList;
@@ -26,6 +27,7 @@ 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.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedNamespaceBehaviour;
 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.NamespaceBehaviour.NamespaceStorageNode;
@@ -105,20 +107,33 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh
         if (potential == null) {
             NamespaceBehaviour<K, V, N> 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<K, V, N>) potential;
+         * 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(
+            NamespaceBehaviour<K, V, N> 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) {
index 1c719722373d92a319cfdab345b6161e057176e1..254b65c76b741cc591469ab7614da9ef6402952b 100644 (file)
@@ -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<AbstractPrerequisite<?>> 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 <K, C extends StmtContext.Mutable<?, ?, ?> , N extends StatementNamespace<K, ?, ? >> AbstractPrerequisite<C> mutatesCtxImpl(
+    private <K, C extends StmtContext.Mutable<?, ?, ?> , N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>> AbstractPrerequisite<C> mutatesCtxImpl(
                 final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key, final ModelProcessingPhase phase) {
             try {
                 PhaseModificationInNamespace<C> mod = new PhaseModificationInNamespace<C>(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 <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>> AbstractPrerequisite<Mutable<?, ?, E>> mutatesEffectiveCtx(
+    public <K, E extends EffectiveStatement<?, ?>, N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>> AbstractPrerequisite<Mutable<?, ?, E>> mutatesEffectiveCtx(
             final StmtContext<?, ?, ?> context, final Class<N> 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<T> implements Prerequisite<T> {
@@ -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
index c4bbb76f004a6417f456a791a49001063e14948c..1f10c18a96bcc33a7d1e00d3f5e49836af7b9bb8 100644 (file)
@@ -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<K,V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
+abstract class NamespaceBehaviourWithListeners<K, V, N extends IdentifierNamespace<K, V>>
+        extends NamespaceBehaviour<K, V, N> {
 
-    abstract static class ValueAddedListener {
+    abstract static class ValueAddedListener<K> {
         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<K, V, N> delegate;
-    private final Multimap<K, ValueAddedListener> listeners = HashMultimap.create();
+    private final List<VirtualNamespaceContext<?, V, ?>> derivedNamespaces = new ArrayList<>();
+
 
     protected NamespaceBehaviourWithListeners(final NamespaceBehaviour<K, V, N> delegate) {
         super(delegate.getIdentifier());
         this.delegate = delegate;
     }
 
+    protected abstract void addListener(K key, ValueAddedListener<K> listener);
+
+    protected abstract Iterator<ValueAddedListener<K>> getMutableListeners(K key);
+
+    protected abstract boolean isRequestedValue(ValueAddedListener<K> listener, NamespaceStorageNode storage, V value);
+
     @Override
     public void addTo(final NamespaceStorageNode storage, final K key, final V value) {
         delegate.addTo(storage, key, value);
 
-        Iterator<ValueAddedListener> keyListeners = listeners.get(key).iterator();
+        Iterator<ValueAddedListener<K>> keyListeners = getMutableListeners(key);
+        List<ValueAddedListener<K>> toNotify = new ArrayList<>();
         while (keyListeners.hasNext()) {
-            ValueAddedListener listener = keyListeners.next();
-            if (listener.ctxNode == storage || hasIdentiticalValue(listener.ctxNode,key,value)) {
+            ValueAddedListener<K> listener = keyListeners.next();
+            if (isRequestedValue(listener, storage, value)) {
                 keyListeners.remove();
-                listener.onValueAdded(key, value);
+                toNotify.add(listener);
             }
         }
-
-        if (key instanceof ModuleIdentifier && !listeners.isEmpty()) {
-            Collection<ValueAddedListener> defaultImportListeners = getDefaultImportListeners((ModuleIdentifier) key);
-            Iterator<ValueAddedListener> 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<K> listener : toNotify) {
+            listener.onValueAdded(key, value);
+        }
+        for (VirtualNamespaceContext<?, V, ?> derived : derivedNamespaces) {
+            derived.addTo(storage, null, value);
         }
     }
 
-    private Collection<ValueAddedListener> 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<K> listener) {
+        addListener(listener.key, listener);
     }
 
-    void addValueListener(final K key, final ValueAddedListener listener) {
-        listeners.put(key, listener);
+    final void addDerivedNamespace(VirtualNamespaceContext<?, V, ?> namespace) {
+        derivedNamespaces.add(namespace);
     }
 
     @Override
index 8c883dd26572b680ac0537dc5297d79e1640ffae..b1bf364e0c387792d4b156d333ce25aa1dd387a0 100644 (file)
@@ -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<A, D extends DeclaredStatement<A>, 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 (file)
index 0000000..01e499f
--- /dev/null
@@ -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<K, V, N extends IdentifierNamespace<K, V>>
+        extends NamespaceBehaviourWithListeners<K, V, N> {
+
+    // FIXME: Change this to Multimap, once issue with modules
+    // is resolved.
+    private final List<NamespaceBehaviourWithListeners.ValueAddedListener<K>> listeners = new ArrayList<>();
+    public SimpleNamespaceContext(NamespaceBehaviour<K, V, N> delegate) {
+        super(delegate);
+    }
+
+    protected boolean isRequestedValue(NamespaceBehaviourWithListeners.ValueAddedListener<K> listener, NamespaceStorageNode storage, V value) {
+        NamespaceStorageNode listenerCtx = listener.getCtxNode();
+        return value == getFrom(listenerCtx, listener.getKey());
+    }
+
+    @Override
+    protected void addListener(K key, NamespaceBehaviourWithListeners.ValueAddedListener<K> listener) {
+        listeners.add(listener);
+    }
+
+    @Override
+    protected Iterator<NamespaceBehaviourWithListeners.ValueAddedListener<K>> getMutableListeners(K key) {
+        return listeners.iterator();
+    }
+}
\ No newline at end of file
index db760d0792cfd2be2f7901ca98626656d89b1ab0..b11d2a40aa3d732144a08f114e0c0628010ad04b 100644 (file)
@@ -255,11 +255,11 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
     PhaseCompletionProgress tryToCompletePhase(final ModelProcessingPhase phase) throws SourceException {
         Collection<ModifierImpl> 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<ModifierImpl> currentPhaseModifiers) {
+    private static boolean tryToProgress(final Collection<ModifierImpl> currentPhaseModifiers) {
 
         Iterator<ModifierImpl> modifier = currentPhaseModifiers.iterator();
         boolean hasProgressed = false;
         while (modifier.hasNext()) {
-            if (modifier.next().isApplied()) {
+            if (modifier.next().tryApply()) {
                 modifier.remove();
                 hasProgressed = true;
             }
index d28dc9a458c472d70c13b7645c7e282779168e6d..5e05a47580d57e1091c628c3ddcb26945f824149 100644 (file)
@@ -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<A, D extends DeclaredStatement<A>, E
         NamespaceBehaviour<K, V, N> behaviour = getBehaviourRegistry().getNamespaceBehaviour(type);
         if (behaviour instanceof NamespaceBehaviourWithListeners) {
             NamespaceBehaviourWithListeners<K, V, N> casted = (NamespaceBehaviourWithListeners<K, V, N>) behaviour;
-            casted.addValueListener(key, new ValueAddedListener(this) {
+            casted.addValueListener(new ValueAddedListener<K>(this, key) {
                 @Override
                 void onValueAdded(Object key, Object value) {
                     try {
index 4c3be3e9a2e16ad4fb2696d60a8ba9f67d6af180..04a01d17fceaebb6b1b913c071519724ea8cb489 100644 (file)
@@ -63,10 +63,6 @@ class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Effective
         } else {
             this.argument = original.argument;
         }
-
-        copyDeclaredStmts(original, newQNameModule, typeOfCopy);
-
-        copyEffectiveStmts(original, newQNameModule, typeOfCopy);
     }
 
     private void copyDeclaredStmts(SubstatementContext<A, D, E> original,
@@ -150,6 +146,9 @@ class SubstatementContext<A, D extends DeclaredStatement<A>, 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 (file)
index 0000000..75c4b5e
--- /dev/null
@@ -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<K, V, N extends IdentifierNamespace<K, V>>
+        extends NamespaceBehaviourWithListeners<K, V, N> {
+
+    private final List<NamespaceBehaviourWithListeners.ValueAddedListener<K>> listeners = new ArrayList<>(20);
+
+    public VirtualNamespaceContext(NamespaceBehaviour<K, V, N> delegate) {
+        super(delegate);
+    }
+
+    protected boolean isRequestedValue(NamespaceBehaviourWithListeners.ValueAddedListener<K> listener, NamespaceStorageNode storage, V value) {
+        return value == getFrom(listener.getCtxNode(), listener.getKey());
+    }
+
+    @Override
+    protected void addListener(K key, NamespaceBehaviourWithListeners.ValueAddedListener<K> listener) {
+        listeners.add(listener);
+    }
+
+    @Override
+    protected Iterator<NamespaceBehaviourWithListeners.ValueAddedListener<K>> getMutableListeners(K key) {
+        return listeners.iterator();
+    }
+}
\ No newline at end of file
index 12e1a06bb184d16c9b2d1fb7c984b40ab76142ae..4d660e91b2e02a4a57768bb7b90964e02de5181e 100644 (file)
@@ -20,8 +20,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.meta.StmtContextUtils;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.parser.spi.source.StmtOrderingNamespace;
@@ -77,32 +79,21 @@ public class AugmentStatementImpl extends AbstractDeclaredStatement<SchemaNodeId
             }
 
             final ModelActionBuilder augmentAction = augmentNode
-                    .newInferenceAction(ModelProcessingPhase.FULL_DECLARATION);
+                    .newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
             final ModelActionBuilder.Prerequisite<StmtContext<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>>> sourceCtxPrereq = augmentAction
-                    .requiresCtx(augmentNode,
-                            ModelProcessingPhase.FULL_DECLARATION);
-
+                    .requiresCtx(augmentNode, ModelProcessingPhase.EFFECTIVE_MODEL);
+            final Prerequisite<Mutable<?, ?, EffectiveStatement<?, ?>>> 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);
@@ -140,6 +131,15 @@ public class AugmentStatementImpl extends AbstractDeclaredStatement<SchemaNodeId
                 }
             });
         }
+
+        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
index 3a068971d52c8a2b02a068f922d9a2355fb8a03b..08acdd5a016d5740cf75a2711a8cab8fff4d4500 100644 (file)
@@ -10,54 +10,37 @@ 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 javax.annotation.Nullable;
+import java.util.regex.Pattern;
 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 AugmentUtils() {
-        throw new UnsupportedOperationException();
     }
 
     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<StatementContextBase<?, ?, ?>> subStatements = new Builder<StatementContextBase<?, ?, ?>>()
@@ -80,7 +63,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<StatementContextBase<?, ?, ?>> subStatements = new Builder<StatementContextBase<?, ?, ?>>()
@@ -104,54 +87,41 @@ public final class AugmentUtils {
     }
 
     private static void validateNodeCanBeCopiedByAugment(final StatementContextBase<?, ?, ?> sourceCtx,
-            final Iterable<StatementContextBase<?, ?, ?>> targetSubStatements,
-            final boolean sourceAndTargetInSameModule) {
+            final List<StatementContextBase<?, ?, ?>> 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<StatementContextBase<?, ?, ?>> sourceSubStatements = new Builder<StatementContextBase<?, ?, ?>>()
+                    .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;
         }
     }
 
@@ -167,100 +137,7 @@ public final class AugmentUtils {
         return REUSED_DEF_SET.contains(stmtContext.getPublicDefinition());
     }
 
-    public static StatementContextBase<?, ?, ?> getAugmentTargetCtx(
-            final Mutable<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>> augmentNode) {
-
-        final SchemaNodeIdentifier augmentTargetNode = augmentNode.getStatementArgument();
-        Preconditions.checkArgument(augmentTargetNode != null,
-                "Augment argument null, something bad happened in some of previous parsing phases");
-
-        List<StatementContextBase<?, ?, ?>> 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<? extends StatementContextBase<?, ?, ?>>) 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<QName> path) {
-
-        StatementContextBase<?, ?, ?> parent = rootStmtCtx;
-
-        Iterator<QName> 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<StatementContextBase<?, ?, ?>> declaredSubstatement = parent.declaredSubstatements();
-        Collection<StatementContextBase<?, ?, ?>> 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
@@ -276,10 +153,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());
-    }
 }
index b9761b1a913edcd5d27ec64751a4c399de42e637..6482c99f510c4dc7ccb39c1f4fbfc9fe066bae72 100644 (file)
@@ -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 <D>
  * @param <E>
  */
-public interface ChildSchemaNodes<D extends DeclaredStatement<QName>,E extends EffectiveStatement<QName, D>> extends StatementNamespace<QName, D, E>{
+public class ChildSchemaNodes<D extends DeclaredStatement<QName>,E extends EffectiveStatement<QName, D>>
+    extends NamespaceBehaviour<QName, StmtContext<?, D, E>, ChildSchemaNodes<D, E>>
+    implements StatementNamespace<QName, D, E>{
 
+    protected ChildSchemaNodes() {
+        super((Class<ChildSchemaNodes<D,E>>) (Class) ChildSchemaNodes.class);
+    }
+
+    @Override
+    public StmtContext<?, D, E> get(QName key) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public StmtContext<?, D, E> getFrom(NamespaceStorageNode storage, QName key) {
+        return globalOrStatementSpecific(storage).getFromLocalStorage(getIdentifier(), key);
+    }
+
+    @Override
+    public Map<QName, StmtContext<?, D, E>> getAllFrom(NamespaceStorageNode storage) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void addTo(NamespaceBehaviour.NamespaceStorageNode storage, QName key, StmtContext<?, D, E> 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 (file)
index 0000000..bee80c9
--- /dev/null
@@ -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<SchemaNodeIdentifier, StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>, SchemaNodeIdentifierBuildNamespace, ChildSchemaNodes<?, ?>>
+        implements IdentifierNamespace<SchemaNodeIdentifier, StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>> {
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    protected SchemaNodeIdentifierBuildNamespace() {
+        super(SchemaNodeIdentifierBuildNamespace.class, (Class) ChildSchemaNodes.class);
+    }
+
+    @Override
+    public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> get(
+            SchemaNodeIdentifier key) {
+        throw new UnsupportedOperationException("Direct access to namespace is not supported");
+    }
+
+    @Override
+    public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> 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<QName> iterator = key.getPathFromRoot().iterator();
+        if(!iterator.hasNext()) {
+            if(lookupStartStorage instanceof StmtContext<?, ?, ?>) {
+                return (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage;
+            } else {
+                return null;
+            }
+        }
+        StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> current = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage.getFromLocalStorage(ChildSchemaNodes.class, iterator.next());
+        while(current != null && iterator.hasNext()) {
+            current = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) current.getFromNamespace(ChildSchemaNodes.class, iterator.next());
+        }
+        return current;
+    }
+
+}
index 514b9f04082e2ddd1f0fba75156ff4f1c14b10da..57e5bb0368716d86ac6d8db625691e54c74a6416 100644 (file)
@@ -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<QName> implemen
                 return;
             }
 
-            ModelActionBuilder usesAction = usesNode.newInferenceAction(FULL_DECLARATION);
+            ModelActionBuilder usesAction = usesNode.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
             final QName groupingName = usesNode.getStatementArgument();
 
             final Prerequisite<StmtContext<?, ?, ?>> sourceGroupingPre = usesAction.requiresCtx(usesNode,
-                    GroupingNamespace.class, groupingName, FULL_DECLARATION);
-            final Prerequisite<? extends StmtContext.Mutable<?, ?, ?>> targetNodePre = usesAction.mutatesCtx(
-                    usesNode.getParentContext(), FULL_DECLARATION);
+                    GroupingNamespace.class, groupingName, ModelProcessingPhase.EFFECTIVE_MODEL);
+            final Prerequisite<? extends StmtContext.Mutable<?, ?, ?>> targetNodePre = usesAction.mutatesEffectiveCtx(
+                    usesNode.getParentContext());
 
             usesAction.apply(new InferenceAction() {
 
index e3b9152d2bd0920a2bea47dff8d2cba1b3c492e0..32ab655db707207ccc0a8b47b581168557edb85e 100644 (file)
@@ -294,14 +294,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<QName> 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) {
index 9f316ec9491fd5e9a9071c5944fe4a1bed510eb4..6dd2595d3ed8a70e0df8a41c2b3562eab4c5c9b6 100644 (file)
@@ -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))
index fdc1802e684dad99614b367e5738a15d6bccaecf..890c47b0fc65fa4f49d9d07cc97f84935cf055a5 100644 (file)
@@ -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,
index ba12bd6ee75ccdd9f6ed5e9157ae542fb28b030b..1c361e4b5cd09a672cd327b285dd48529be2fd70 100644 (file)
@@ -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;
index 190053010cc7c4994a7f1496e6fa153b495f0528..412f9c15a94cee69b1eb00034608dba937de79d1 100644 (file)
@@ -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;
index 0d030b23fad18061cd0a621d5163b6c68a367b27..26ec3c8978eb47fea6c0e5d44f5befdb9f2794af 100644 (file)
@@ -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 {
-            
+
         }
     }
 }
index 88123f77367698d74f60ff45b35bb648f9768002..5ec75d342b24b98f1a3f68e5e7f1fbe383b4cb23 100644 (file)
@@ -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 {