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 return (NamespaceBehaviourWithListeners<K, V, N>) potential;
108 throw new NamespaceNotAvailableException("Namespace " + type + "is not available in phase " + currentPhase);
111 public StatementDefinitionContext<?, ?, ?> getStatementDefinition(QName name) {
112 StatementDefinitionContext<?, ?, ?> potential = definitions.get(name);
113 if(potential == null) {
114 StatementSupport<?, ?, ?> potentialRaw = supports.get(currentPhase).getStatementDefinition(name);
115 if(potentialRaw != null) {
116 potential = new StatementDefinitionContext<>(potentialRaw);
117 definitions.put(name, potential);
123 public EffectiveModelContext build() throws SourceException, ReactorException {
124 for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) {
126 loadPhaseStatements();
127 completePhaseActions();
133 private EffectiveModelContext transform() {
134 Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
135 List<DeclaredStatement<?>> rootStatements = new ArrayList<>();
136 for(SourceSpecificContext source : sources) {
137 DeclaredStatement<?> root = source.getRoot().buildDeclared();
138 rootStatements.add(root);
140 return new EffectiveModelContext(rootStatements);
143 public EffectiveSchemaContext buildEffective() throws SourceException, ReactorException {
144 for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) {
146 loadPhaseStatements();
147 completePhaseActions();
150 return transformEffective();
153 private EffectiveSchemaContext transformEffective() {
154 Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
155 List<DeclaredStatement<?>> rootStatements = new ArrayList<>();
156 List<EffectiveStatement<?,?>> rootEffectiveStatements = new ArrayList<>();
158 for(SourceSpecificContext source : sources) {
159 DeclaredStatement<?> root = source.getRoot().buildDeclared();
160 rootStatements.add(root);
162 EffectiveStatement<?,?> rootEffective = source.getRoot().buildEffective();
163 rootEffectiveStatements.add(rootEffective);
166 return new EffectiveSchemaContext(rootStatements,rootEffectiveStatements);
169 private void startPhase(ModelProcessingPhase phase) {
170 Preconditions.checkState(Objects.equals(finishedPhase, phase.getPreviousPhase()));
171 for(SourceSpecificContext source : sources) {
172 source.startPhase(phase);
174 currentPhase = phase;
177 private void loadPhaseStatements() throws SourceException {
178 Preconditions.checkState(currentPhase != null);
179 for(SourceSpecificContext source : sources) {
180 source.loadStatements();
184 private void completePhaseActions() throws ReactorException {
185 Preconditions.checkState(currentPhase != null);
186 List<SourceSpecificContext> sourcesToProgress = Lists.newArrayList(sources);
188 boolean progressing = true;
190 // We reset progressing to false.
192 Iterator<SourceSpecificContext> currentSource = sourcesToProgress.iterator();
193 while(currentSource.hasNext()) {
194 PhaseCompletionProgress sourceProgress = currentSource.next().tryToCompletePhase(currentPhase);
195 switch (sourceProgress) {
197 currentSource.remove();
205 } catch (SourceException e) {
206 throw Throwables.propagate(e);
208 if(!sourcesToProgress.isEmpty()) {
209 SomeModifiersUnresolvedException buildFailure = new SomeModifiersUnresolvedException(currentPhase);
210 for(SourceSpecificContext failedSource : sourcesToProgress) {
211 SourceException sourceEx = failedSource.failModifiers(currentPhase);
212 buildFailure.addSuppressed(sourceEx);
218 private void endPhase(ModelProcessingPhase phase) {
219 Preconditions.checkState(currentPhase == phase);
220 finishedPhase = currentPhase;
223 public Set<SourceSpecificContext> getSources() {