2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.HashMultimap;
12 import com.google.common.collect.Multimap;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.Iterator;
16 import java.util.Objects;
17 import javax.annotation.Nullable;
18 import org.opendaylight.yangtools.concepts.Mutable;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
21 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
22 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.ImportedNamespaceContext;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
27 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
30 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
31 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
32 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
33 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
34 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
35 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.ContextBuilder;
37 public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable {
39 public enum PhaseCompletionProgress {
45 private final StatementStreamSource source;
46 private final BuildGlobalContext currentContext;
47 private final Collection<NamespaceStorageNode> importedNamespaces = new ArrayList<>();
48 private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
50 private RootStatementContext<?,?, ?> root;
52 private ModelProcessingPhase inProgressPhase;
53 private ModelProcessingPhase finishedPhase;
56 SourceSpecificContext(BuildGlobalContext currentContext,StatementStreamSource source) {
58 this.currentContext = currentContext;
61 StatementDefinitionContext<?,?,?> getDefinition(QName name) {
62 return currentContext.getStatementDefinition(name);
65 ContextBuilder<?, ?, ?> createDeclaredChild(StatementContextBase<?, ?, ?> current, QName name, StatementSourceReference ref) {
66 StatementDefinitionContext<?,?,?> def = getDefinition(name);
67 Preconditions.checkArgument(def != null, "Statement %s does not have type mapping defined.",name);
69 return createDeclaredRoot(def,ref);
71 return current.substatementBuilder(def,ref);
74 @SuppressWarnings({ "rawtypes", "unchecked" })
75 private ContextBuilder<?,?, ?> createDeclaredRoot(StatementDefinitionContext<?,?,?> def, StatementSourceReference ref) {
76 return new ContextBuilder(def,ref) {
79 public StatementContextBase build() throws SourceException {
81 root = new RootStatementContext(this, SourceSpecificContext.this);
83 Preconditions.checkState(root.getIdentifier().equals(getIdentifier()), "Root statement was already defined.");
92 RootStatementContext<?,?,?> getRoot() {
96 DeclaredStatement<?> buildDeclared() {
97 return root.buildDeclared();
100 EffectiveStatement<?,?> build() {
101 return root.buildEffective();
104 void startPhase(ModelProcessingPhase phase) {
105 @Nullable ModelProcessingPhase previousPhase = phase.getPreviousPhase();
106 Preconditions.checkState(Objects.equals(previousPhase, finishedPhase));
107 Preconditions.checkState(modifiers.get(previousPhase).isEmpty());
108 inProgressPhase = phase;
112 public <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(Class<N> type, K key, V value) {
113 if(ImportedNamespaceContext.class.isAssignableFrom(type)) {
114 importedNamespaces.add((NamespaceStorageNode) value);
116 getRoot().addToLocalStorage(type, key, value);
120 public StorageNodeType getStorageNodeType() {
121 return StorageNodeType.SourceLocalSpecial;
125 public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key) {
126 final V potentialLocal = getRoot().getFromLocalStorage(type, key);
127 if(potentialLocal != null) {
128 return potentialLocal;
130 for(NamespaceStorageNode importedSource : importedNamespaces) {
131 V potential = importedSource.getFromLocalStorage(type, key);
132 if(potential != null) {
140 public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> type) {
141 return currentContext.getNamespaceBehaviour(type);
145 public NamespaceStorageNode getParentNamespaceStorage() {
146 return currentContext;
149 PhaseCompletionProgress tryToCompletePhase(ModelProcessingPhase phase) throws SourceException {
150 Collection<ModifierImpl> currentPhaseModifiers = modifiers.get(phase);
151 Iterator<ModifierImpl> modifier = currentPhaseModifiers.iterator();
152 boolean hasProgressed = false;
153 while(modifier.hasNext()) {
154 if(modifier.next().isApplied()) {
156 hasProgressed = true;
159 if(root.tryToCompletePhase(phase) && currentPhaseModifiers.isEmpty()) {
160 finishedPhase = phase;
161 return PhaseCompletionProgress.FINISHED;
165 return PhaseCompletionProgress.PROGRESS;
167 return PhaseCompletionProgress.NO_PROGRESS;
170 ModelActionBuilder newInferenceAction(ModelProcessingPhase phase) {
171 ModifierImpl action = new ModifierImpl(phase);
172 modifiers.put(phase, action);
177 public String toString() {
178 return "SourceSpecificContext [source=" + source + ", current=" + inProgressPhase + ", finished="
179 + finishedPhase + "]";
182 SourceException failModifiers(ModelProcessingPhase identifier) {
183 InferenceException sourceEx = new InferenceException("Fail to infer source relationships", root.getStatementSourceReference());
186 for(ModifierImpl mod : modifiers.get(identifier)) {
189 } catch (SourceException e) {
190 sourceEx.addSuppressed(e);
196 void loadStatements() throws SourceException {
197 switch (inProgressPhase) {
199 source.writeLinkage(new StatementContextWriter(this, inProgressPhase),stmtDef());
201 case StatementDefinition:
202 source.writeLinkageAndStatementDefinitions(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes());
203 case FullDeclaration:
204 source.writeFull(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes());
211 private PrefixToModule prefixes() {
212 // TODO Auto-generated method stub
216 private QNameToStatementDefinition stmtDef() {
217 // TODO Auto-generated method stub