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.parser.stmt.rfc6020.effective.EffectiveSchemaContext;
12 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
13 import com.google.common.base.Preconditions;
14 import com.google.common.base.Throwables;
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.collect.Lists;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.Iterator;
21 import java.util.List;
23 import java.util.Objects;
25 import javax.annotation.Nonnull;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
28 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
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.NamespaceNotAvailableException;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
37 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
38 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
39 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
40 import org.opendaylight.yangtools.yang.parser.stmt.reactor.SourceSpecificContext.PhaseCompletionProgress;
42 class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBehaviour.Registry {
44 private static final List<ModelProcessingPhase> PHASE_EXECUTION_ORDER = ImmutableList.<ModelProcessingPhase>builder()
45 .add(ModelProcessingPhase.SOURCE_LINKAGE)
46 .add(ModelProcessingPhase.STATEMENT_DEFINITION)
47 .add(ModelProcessingPhase.FULL_DECLARATION)
48 .add(ModelProcessingPhase.EFFECTIVE_MODEL)
51 private final Map<QName,StatementDefinitionContext<?,?,?>> definitions = new HashMap<>();
52 private final Map<Class<?>,NamespaceBehaviourWithListeners<?, ?, ?>> namespaces = new HashMap<>();
55 private final Map<ModelProcessingPhase,StatementSupportBundle> supports;
56 private final Set<SourceSpecificContext> sources = new HashSet<>();
58 private ModelProcessingPhase currentPhase;
59 private ModelProcessingPhase finishedPhase;
61 public BuildGlobalContext(Map<ModelProcessingPhase, StatementSupportBundle> supports) {
63 this.supports = supports;
66 public StatementSupportBundle getSupportsForPhase(ModelProcessingPhase currentPhase) {
67 return supports.get(currentPhase);
70 public void addSource(@Nonnull StatementStreamSource source) {
71 sources.add(new SourceSpecificContext(this,source));
75 public StorageNodeType getStorageNodeType() {
76 return StorageNodeType.GLOBAL;
80 public NamespaceStorageNode getParentNamespaceStorage() {
85 public NamespaceBehaviour.Registry getBehaviourRegistry() {
90 public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> getNamespaceBehaviour(Class<N> type) {
91 NamespaceBehaviourWithListeners<?, ?, ?> potential = namespaces.get(type);
92 if (potential == null) {
93 NamespaceBehaviour<K, V, N> potentialRaw = supports.get(currentPhase).getNamespaceBehaviour(type);
94 if(potentialRaw != null) {
95 potential = new NamespaceBehaviourWithListeners<>(potentialRaw);
96 namespaces.put(type, potential);
99 if (potential != null) {
100 Preconditions.checkState(type.equals(potential.getIdentifier()));
103 * Safe cast, previous checkState checks equivalence of key from
104 * which type argument are derived
106 @SuppressWarnings("unchecked")
107 NamespaceBehaviourWithListeners<K, V, N> casted = (NamespaceBehaviourWithListeners<K, V, N>) potential;
110 throw new NamespaceNotAvailableException("Namespace " + type + "is not available in phase " + currentPhase);
113 public StatementDefinitionContext<?, ?, ?> getStatementDefinition(QName name) {
114 StatementDefinitionContext<?, ?, ?> potential = definitions.get(name);
115 if(potential == null) {
116 StatementSupport<?, ?, ?> potentialRaw = supports.get(currentPhase).getStatementDefinition(name);
117 if(potentialRaw != null) {
118 potential = new StatementDefinitionContext<>(potentialRaw);
119 definitions.put(name, potential);
125 public EffectiveModelContext build() throws SourceException, ReactorException {
126 for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) {
128 loadPhaseStatements();
129 completePhaseActions();
135 private EffectiveModelContext transform() {
136 Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
137 List<DeclaredStatement<?>> rootStatements = new ArrayList<>();
138 for(SourceSpecificContext source : sources) {
139 DeclaredStatement<?> root = source.getRoot().buildDeclared();
140 rootStatements.add(root);
142 return new EffectiveModelContext(rootStatements);
145 public EffectiveSchemaContext buildEffective() throws SourceException, ReactorException {
146 for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) {
148 loadPhaseStatements();
149 completePhaseActions();
152 return transformEffective();
155 private EffectiveSchemaContext transformEffective() {
156 Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
157 List<DeclaredStatement<?>> rootStatements = new ArrayList<>();
158 List<EffectiveStatement<?,?>> rootEffectiveStatements = new ArrayList<>();
160 for(SourceSpecificContext source : sources) {
161 DeclaredStatement<?> root = source.getRoot().buildDeclared();
162 rootStatements.add(root);
164 EffectiveStatement<?,?> rootEffective = source.getRoot().buildEffective();
165 rootEffectiveStatements.add(rootEffective);
168 return new EffectiveSchemaContext(rootStatements,rootEffectiveStatements);
171 private void startPhase(ModelProcessingPhase phase) {
172 Preconditions.checkState(Objects.equals(finishedPhase, phase.getPreviousPhase()));
173 for(SourceSpecificContext source : sources) {
174 source.startPhase(phase);
176 currentPhase = phase;
179 private void loadPhaseStatements() throws SourceException {
180 Preconditions.checkState(currentPhase != null);
181 for(SourceSpecificContext source : sources) {
182 source.loadStatements();
186 private void completePhaseActions() throws ReactorException {
187 Preconditions.checkState(currentPhase != null);
188 ArrayList<SourceSpecificContext> sourcesToProgress = Lists.newArrayList(sources);
190 boolean progressing = true;
192 // We reset progressing to false.
194 Iterator<SourceSpecificContext> currentSource = sourcesToProgress.iterator();
195 while(currentSource.hasNext()) {
196 PhaseCompletionProgress sourceProgress = currentSource.next().tryToCompletePhase(currentPhase);
197 switch (sourceProgress) {
199 currentSource.remove();
207 } catch (SourceException e) {
208 throw Throwables.propagate(e);
210 if(!sourcesToProgress.isEmpty()) {
211 SomeModifiersUnresolvedException buildFailure = new SomeModifiersUnresolvedException(currentPhase);
212 for(SourceSpecificContext failedSource : sourcesToProgress) {
213 SourceException sourceEx = failedSource.failModifiers(currentPhase);
214 buildFailure.addSuppressed(sourceEx);
220 private void endPhase(ModelProcessingPhase phase) {
221 Preconditions.checkState(currentPhase == phase);
222 finishedPhase = currentPhase;
225 public Set<SourceSpecificContext> getSources() {