Fix enum members' name
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / SourceSpecificContext.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
9
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;
36
37 public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable {
38
39     public enum PhaseCompletionProgress {
40         NO_PROGRESS,
41         PROGRESS,
42         FINISHED
43     }
44
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();
49
50     private RootStatementContext<?,?, ?> root;
51
52     private ModelProcessingPhase inProgressPhase;
53     private ModelProcessingPhase finishedPhase;
54
55
56     SourceSpecificContext(BuildGlobalContext currentContext,StatementStreamSource source) {
57         this.source = source;
58         this.currentContext = currentContext;
59     }
60
61     StatementDefinitionContext<?,?,?> getDefinition(QName name) {
62         return currentContext.getStatementDefinition(name);
63     }
64
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);
68         if(current == null) {
69             return createDeclaredRoot(def,ref);
70         }
71         return current.substatementBuilder(def,ref);
72     }
73
74     @SuppressWarnings({ "rawtypes", "unchecked" })
75     private ContextBuilder<?,?, ?> createDeclaredRoot(StatementDefinitionContext<?,?,?> def, StatementSourceReference ref) {
76         return new ContextBuilder(def,ref) {
77
78             @Override
79             public StatementContextBase build() throws SourceException {
80                 if(root == null) {
81                     root = new RootStatementContext(this, SourceSpecificContext.this);
82                 } else {
83                     Preconditions.checkState(root.getIdentifier().equals(getIdentifier()), "Root statement was already defined.");
84                 }
85                 root.resetLists();
86                 return root;
87             }
88
89         };
90     }
91
92     RootStatementContext<?,?,?> getRoot() {
93         return root;
94     }
95
96     DeclaredStatement<?> buildDeclared() {
97         return root.buildDeclared();
98     }
99
100     EffectiveStatement<?,?> build() {
101         return root.buildEffective();
102     }
103
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;
109     }
110
111     @Override
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);
115         }
116         getRoot().addToLocalStorage(type, key, value);
117     }
118
119     @Override
120     public StorageNodeType getStorageNodeType() {
121         return StorageNodeType.SOURCE_LOCAL_SPECIAL;
122     }
123
124     @Override
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;
129         }
130         for(NamespaceStorageNode importedSource : importedNamespaces) {
131             V potential = importedSource.getFromLocalStorage(type, key);
132             if(potential != null) {
133                 return potential;
134             }
135         }
136         return null;
137     }
138
139     @Override
140     public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> type) {
141         return currentContext.getNamespaceBehaviour(type);
142     }
143
144     @Override
145     public NamespaceStorageNode getParentNamespaceStorage() {
146         return currentContext;
147     }
148
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()) {
155                 modifier.remove();
156                 hasProgressed = true;
157             }
158         }
159         if(root.tryToCompletePhase(phase) && currentPhaseModifiers.isEmpty()) {
160             finishedPhase = phase;
161             return PhaseCompletionProgress.FINISHED;
162
163         }
164         if(hasProgressed) {
165             return PhaseCompletionProgress.PROGRESS;
166         }
167         return PhaseCompletionProgress.NO_PROGRESS;
168     }
169
170     ModelActionBuilder newInferenceAction(ModelProcessingPhase phase) {
171         ModifierImpl action = new ModifierImpl(phase);
172         modifiers.put(phase, action);
173         return action;
174     }
175
176     @Override
177     public String toString() {
178         return "SourceSpecificContext [source=" + source + ", current=" + inProgressPhase + ", finished="
179                 + finishedPhase + "]";
180     }
181
182     SourceException failModifiers(ModelProcessingPhase identifier) {
183         InferenceException sourceEx = new InferenceException("Fail to infer source relationships", root.getStatementSourceReference());
184
185
186         for(ModifierImpl mod : modifiers.get(identifier)) {
187             try {
188                 mod.failModifier();
189             } catch (SourceException e) {
190                 sourceEx.addSuppressed(e);
191             }
192         }
193         return sourceEx;
194     }
195
196     void loadStatements() throws SourceException {
197         switch (inProgressPhase) {
198         case SOURCE_LINKAGE:
199             source.writeLinkage(new StatementContextWriter(this, inProgressPhase),stmtDef());
200             break;
201         case STATEMENT_DEFINITION:
202             source.writeLinkageAndStatementDefinitions(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes());
203         case FULL_DECLARATION:
204             source.writeFull(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes());
205
206         default:
207             break;
208         }
209     }
210
211     private PrefixToModule prefixes() {
212         // TODO Auto-generated method stub
213         return null;
214     }
215
216     private QNameToStatementDefinition stmtDef() {
217         // TODO Auto-generated method stub
218         return null;
219     }
220
221 }