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.base.Throwables;
12 import com.google.common.collect.ImmutableList;
13 import com.google.common.collect.Lists;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.List;
20 import java.util.Objects;
22 import javax.annotation.Nonnull;
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.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.meta.NamespaceNotAvailableException;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
33 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
35 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
36 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
37 import org.opendaylight.yangtools.yang.parser.stmt.reactor.SourceSpecificContext.PhaseCompletionProgress;
39 class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBehaviour.Registry {
41 private static final List<ModelProcessingPhase> PHASE_EXECUTION_ORDER = ImmutableList.<ModelProcessingPhase>builder()
42 .add(ModelProcessingPhase.SOURCE_LINKAGE)
43 .add(ModelProcessingPhase.STATEMENT_DEFINITION)
44 .add(ModelProcessingPhase.FULL_DECLARATION)
45 .add(ModelProcessingPhase.EFFECTIVE_MODEL)
48 private final Map<QName,StatementDefinitionContext<?,?,?>> definitions = new HashMap<>();
49 private final Map<Class<?>,NamespaceBehaviourWithListeners<?, ?, ?>> namespaces = new HashMap<>();
52 private final Map<ModelProcessingPhase,StatementSupportBundle> supports;
53 private final Set<SourceSpecificContext> sources = new HashSet<>();
55 private ModelProcessingPhase currentPhase;
56 private ModelProcessingPhase finishedPhase;
58 public BuildGlobalContext(Map<ModelProcessingPhase, StatementSupportBundle> supports) {
60 this.supports = supports;
63 public void addSource(@Nonnull StatementStreamSource source) {
64 sources.add(new SourceSpecificContext(this,source));
68 public StorageNodeType getStorageNodeType() {
69 return StorageNodeType.GLOBAL;
73 public NamespaceStorageNode getParentNamespaceStorage() {
78 public NamespaceBehaviour.Registry getBehaviourRegistry() {
83 public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> getNamespaceBehaviour(Class<N> type) {
84 NamespaceBehaviourWithListeners<?, ?, ?> potential = namespaces.get(type);
85 if (potential == null) {
86 NamespaceBehaviour<K, V, N> potentialRaw = supports.get(currentPhase).getNamespaceBehaviour(type);
87 if(potentialRaw != null) {
88 potential = new NamespaceBehaviourWithListeners<>(potentialRaw);
89 namespaces.put(type, potential);
92 if (potential != null) {
93 Preconditions.checkState(type.equals(potential.getIdentifier()));
96 * Safe cast, previous checkState checks equivalence of key from
97 * which type argument are derived
99 @SuppressWarnings("unchecked")
100 NamespaceBehaviourWithListeners<K, V, N> casted = (NamespaceBehaviourWithListeners<K, V, N>) potential;
103 throw new NamespaceNotAvailableException("Namespace " + type + "is not available in phase " + currentPhase);
106 public StatementDefinitionContext<?, ?, ?> getStatementDefinition(QName name) {
107 StatementDefinitionContext<?, ?, ?> potential = definitions.get(name);
108 if(potential == null) {
109 StatementSupport<?, ?, ?> potentialRaw = supports.get(currentPhase).getStatementDefinition(name);
110 if(potentialRaw != null) {
111 potential = new StatementDefinitionContext<>(potentialRaw);
112 definitions.put(name, potential);
118 public EffectiveModelContext build() throws SourceException, ReactorException {
119 for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) {
121 loadPhaseStatements();
122 completePhaseActions();
128 private EffectiveModelContext transform() {
129 Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
130 List<DeclaredStatement<?>> rootStatements = new ArrayList<>();
131 for(SourceSpecificContext source : sources) {
132 DeclaredStatement<?> root = source.getRoot().buildDeclared();
133 rootStatements.add(root);
135 return new EffectiveModelContext(rootStatements);
138 private void startPhase(ModelProcessingPhase phase) {
139 Preconditions.checkState(Objects.equals(finishedPhase, phase.getPreviousPhase()));
140 for(SourceSpecificContext source : sources) {
141 source.startPhase(phase);
143 currentPhase = phase;
146 private void loadPhaseStatements() throws SourceException {
147 Preconditions.checkState(currentPhase != null);
148 for(SourceSpecificContext source : sources) {
149 source.loadStatements();
153 private void completePhaseActions() throws ReactorException {
154 Preconditions.checkState(currentPhase != null);
155 ArrayList<SourceSpecificContext> sourcesToProgress = Lists.newArrayList(sources);
157 boolean progressing = true;
159 // We reset progressing to false.
161 Iterator<SourceSpecificContext> currentSource = sourcesToProgress.iterator();
162 while(currentSource.hasNext()) {
163 PhaseCompletionProgress sourceProgress = currentSource.next().tryToCompletePhase(currentPhase);
164 switch (sourceProgress) {
166 currentSource.remove();
174 } catch (SourceException e) {
175 throw Throwables.propagate(e);
177 if(!sourcesToProgress.isEmpty()) {
178 SomeModifiersUnresolvedException buildFailure = new SomeModifiersUnresolvedException(currentPhase);
179 for(SourceSpecificContext failedSource : sourcesToProgress) {
180 SourceException sourceEx = failedSource.failModifiers(currentPhase);
181 buildFailure.addSuppressed(sourceEx);
187 private void endPhase(ModelProcessingPhase phase) {
188 Preconditions.checkState(currentPhase == phase);
189 finishedPhase = currentPhase;
192 public Set<SourceSpecificContext> getSources() {