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 org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.HashMultimap;
14 import com.google.common.collect.ImmutableMap;
15 import com.google.common.collect.Multimap;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Iterator;
20 import java.util.Objects;
21 import javax.annotation.Nullable;
22 import org.opendaylight.yangtools.concepts.Mutable;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
25 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.ImportedNamespaceContext;
27 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
33 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
34 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
35 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
36 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinitionMap;
37 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
38 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
39 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
40 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.ContextBuilder;
42 public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable {
44 public enum PhaseCompletionProgress {
50 private final StatementStreamSource source;
51 private final BuildGlobalContext currentContext;
52 private final Collection<NamespaceStorageNode> importedNamespaces = new ArrayList<>();
53 private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
55 private RootStatementContext<?,?, ?> root;
57 private ModelProcessingPhase inProgressPhase;
58 private ModelProcessingPhase finishedPhase;
59 private QNameToStatementDefinitionMap qNameToStmtDefMap = new QNameToStatementDefinitionMap();
62 SourceSpecificContext(BuildGlobalContext currentContext,StatementStreamSource source) {
64 this.currentContext = currentContext;
67 StatementDefinitionContext<?,?,?> getDefinition(QName name) {
68 return currentContext.getStatementDefinition(name);
71 ContextBuilder<?, ?, ?> createDeclaredChild(StatementContextBase<?, ?, ?> current, QName name, StatementSourceReference ref) {
72 StatementDefinitionContext<?,?,?> def = getDefinition(name);
73 Preconditions.checkArgument(def != null, "Statement %s does not have type mapping defined.",name);
75 return createDeclaredRoot(def,ref);
77 return current.substatementBuilder(def, ref);
80 @SuppressWarnings({ "rawtypes", "unchecked" })
81 private ContextBuilder<?,?, ?> createDeclaredRoot(StatementDefinitionContext<?,?,?> def, StatementSourceReference ref) {
82 return new ContextBuilder(def,ref) {
85 public StatementContextBase build() throws SourceException {
87 root = new RootStatementContext(this, SourceSpecificContext.this);
89 Preconditions.checkState(root.getIdentifier().equals(getIdentifier()), "Root statement was already defined as %s.", root.getIdentifier());
98 RootStatementContext<?,?,?> getRoot() {
102 DeclaredStatement<?> buildDeclared() {
103 return root.buildDeclared();
106 EffectiveStatement<?,?> buildEffective() {
107 return root.buildEffective();
110 void startPhase(ModelProcessingPhase phase) {
111 @Nullable ModelProcessingPhase previousPhase = phase.getPreviousPhase();
112 Preconditions.checkState(Objects.equals(previousPhase, finishedPhase));
113 Preconditions.checkState(modifiers.get(previousPhase).isEmpty());
114 inProgressPhase = phase;
118 public <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(Class<N> type, K key, V value) {
119 if(ImportedNamespaceContext.class.isAssignableFrom(type)) {
120 importedNamespaces.add((NamespaceStorageNode) value);
122 getRoot().addToLocalStorage(type, key, value);
126 public StorageNodeType getStorageNodeType() {
127 return StorageNodeType.SOURCE_LOCAL_SPECIAL;
131 public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key) {
132 final V potentialLocal = getRoot().getFromLocalStorage(type, key);
133 if(potentialLocal != null) {
134 return potentialLocal;
136 for(NamespaceStorageNode importedSource : importedNamespaces) {
137 V potential = importedSource.getFromLocalStorage(type, key);
138 if(potential != null) {
146 public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> type) {
147 return currentContext.getNamespaceBehaviour(type);
151 public NamespaceStorageNode getParentNamespaceStorage() {
152 return currentContext;
155 PhaseCompletionProgress tryToCompletePhase(ModelProcessingPhase phase) throws SourceException {
156 Collection<ModifierImpl> currentPhaseModifiers = modifiers.get(phase);
158 boolean hasProgressed = hasProgress(currentPhaseModifiers);
160 boolean phaseCompleted = root.tryToCompletePhase(phase);
162 hasProgressed = hasProgress(currentPhaseModifiers);
164 if(phaseCompleted && (currentPhaseModifiers.isEmpty())) {
165 finishedPhase = phase;
166 return PhaseCompletionProgress.FINISHED;
170 return PhaseCompletionProgress.PROGRESS;
172 return PhaseCompletionProgress.NO_PROGRESS;
176 private boolean hasProgress(Collection<ModifierImpl> currentPhaseModifiers) {
178 Iterator<ModifierImpl> modifier = currentPhaseModifiers.iterator();
179 boolean hasProgressed = false;
180 while(modifier.hasNext()) {
181 if(modifier.next().isApplied()) {
183 hasProgressed = true;
187 return hasProgressed;
191 ModelActionBuilder newInferenceAction(ModelProcessingPhase phase) {
192 ModifierImpl action = new ModifierImpl(phase);
193 modifiers.put(phase, action);
198 public String toString() {
199 return "SourceSpecificContext [source=" + source + ", current=" + inProgressPhase + ", finished="
200 + finishedPhase + "]";
203 SourceException failModifiers(ModelProcessingPhase identifier) {
204 InferenceException sourceEx = new InferenceException("Fail to infer source relationships", root.getStatementSourceReference());
207 for(ModifierImpl mod : modifiers.get(identifier)) {
210 } catch (SourceException e) {
211 sourceEx.addSuppressed(e);
217 void loadStatements() throws SourceException {
218 switch (inProgressPhase) {
220 source.writeLinkage(new StatementContextWriter(this, inProgressPhase),stmtDef());
222 case STATEMENT_DEFINITION:
223 source.writeLinkageAndStatementDefinitions(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes());
225 case FULL_DECLARATION:
226 source.writeFull(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes());
233 private PrefixToModule prefixes() {
234 // TODO Auto-generated method stub
238 private QNameToStatementDefinition stmtDef() {
239 ImmutableMap<QName, StatementSupport<?, ?, ?>> definitions = currentContext.getSupportsForPhase(
240 inProgressPhase).getDefinitions();
241 for (Map.Entry<QName, StatementSupport<?,?,?>> entry : definitions.entrySet()) {
242 qNameToStmtDefMap.put(entry.getKey(), entry.getValue());
244 return qNameToStmtDefMap;