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.Collection;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 import java.util.List;
21 import java.util.Map.Entry;
22 import java.util.Objects;
24 import javax.annotation.Nonnull;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
27 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
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.spi.validation.ValidationBundlesNamespace;
41 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
42 import org.opendaylight.yangtools.yang.parser.stmt.reactor.SourceSpecificContext.PhaseCompletionProgress;
43 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext;
45 class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBehaviour.Registry {
47 private static final List<ModelProcessingPhase> PHASE_EXECUTION_ORDER = ImmutableList.<ModelProcessingPhase>builder()
48 .add(ModelProcessingPhase.SOURCE_LINKAGE)
49 .add(ModelProcessingPhase.STATEMENT_DEFINITION)
50 .add(ModelProcessingPhase.FULL_DECLARATION)
51 .add(ModelProcessingPhase.EFFECTIVE_MODEL)
54 private final Map<QName,StatementDefinitionContext<?,?,?>> definitions = new HashMap<>();
55 private final Map<Class<?>,NamespaceBehaviourWithListeners<?, ?, ?>> supportedNamespaces = new HashMap<>();
58 private final Map<ModelProcessingPhase,StatementSupportBundle> supports;
59 private final Set<SourceSpecificContext> sources = new HashSet<>();
61 private ModelProcessingPhase currentPhase = ModelProcessingPhase.INIT;
62 private ModelProcessingPhase finishedPhase = ModelProcessingPhase.INIT;
64 public BuildGlobalContext(final Map<ModelProcessingPhase, StatementSupportBundle> supports) {
66 this.supports = Preconditions.checkNotNull(supports, "BuildGlobalContext#supports cannot be null");
69 public BuildGlobalContext(final Map<ModelProcessingPhase, StatementSupportBundle> supports, final Map<ValidationBundleType,Collection<?>> supportedValidation) {
71 this.supports = Preconditions.checkNotNull(supports, "BuildGlobalContext#supports cannot be null");
73 Set<Entry<ValidationBundleType, Collection<?>>> validationBundles = supportedValidation.entrySet();
74 for (Entry<ValidationBundleType, Collection<?>> validationBundle : validationBundles) {
75 addToNs(ValidationBundlesNamespace.class, validationBundle.getKey(), validationBundle.getValue());
79 public StatementSupportBundle getSupportsForPhase(final ModelProcessingPhase currentPhase) {
80 return supports.get(currentPhase);
83 public void addSource(@Nonnull final StatementStreamSource source) {
84 sources.add(new SourceSpecificContext(this,source));
88 public StorageNodeType getStorageNodeType() {
89 return StorageNodeType.GLOBAL;
93 public NamespaceStorageNode getParentNamespaceStorage() {
98 public NamespaceBehaviour.Registry getBehaviourRegistry() {
103 public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> getNamespaceBehaviour(final Class<N> type) {
104 NamespaceBehaviourWithListeners<?, ?, ?> potential = supportedNamespaces.get(type);
105 if (potential == null) {
106 NamespaceBehaviour<K, V, N> potentialRaw = supports.get(currentPhase).getNamespaceBehaviour(type);
107 if(potentialRaw != null) {
108 potential = new NamespaceBehaviourWithListeners<>(potentialRaw);
109 supportedNamespaces.put(type, potential);
112 if (potential != null) {
113 Preconditions.checkState(type.equals(potential.getIdentifier()));
116 * Safe cast, previous checkState checks equivalence of key from
117 * which type argument are derived
119 return (NamespaceBehaviourWithListeners<K, V, N>) potential;
121 throw new NamespaceNotAvailableException("Namespace " + type + " is not available in phase " + currentPhase);
124 public StatementDefinitionContext<?, ?, ?> getStatementDefinition(final QName name) {
125 StatementDefinitionContext<?, ?, ?> potential = definitions.get(name);
126 if(potential == null) {
127 StatementSupport<?, ?, ?> potentialRaw = supports.get(currentPhase).getStatementDefinition(name);
128 if(potentialRaw != null) {
129 potential = new StatementDefinitionContext<>(potentialRaw);
130 definitions.put(name, potential);
136 public EffectiveModelContext build() throws SourceException, ReactorException {
137 for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) {
139 loadPhaseStatements();
140 completePhaseActions();
146 private EffectiveModelContext transform() {
147 Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
148 List<DeclaredStatement<?>> rootStatements = new ArrayList<>();
149 for(SourceSpecificContext source : sources) {
150 DeclaredStatement<?> root = source.getRoot().buildDeclared();
151 rootStatements.add(root);
153 return new EffectiveModelContext(rootStatements);
156 public EffectiveSchemaContext buildEffective() throws SourceException, ReactorException {
157 for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) {
159 loadPhaseStatements();
160 completePhaseActions();
163 return transformEffective();
166 private EffectiveSchemaContext transformEffective() {
167 Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
168 List<DeclaredStatement<?>> rootStatements = new ArrayList<>();
169 List<EffectiveStatement<?,?>> rootEffectiveStatements = new ArrayList<>();
171 for(SourceSpecificContext source : sources) {
172 DeclaredStatement<?> root = source.getRoot().buildDeclared();
173 rootStatements.add(root);
175 EffectiveStatement<?,?> rootEffective = source.getRoot().buildEffective();
176 rootEffectiveStatements.add(rootEffective);
179 return new EffectiveSchemaContext(rootStatements,rootEffectiveStatements);
182 private void startPhase(final ModelProcessingPhase phase) {
183 Preconditions.checkState(Objects.equals(finishedPhase, phase.getPreviousPhase()));
184 for(SourceSpecificContext source : sources) {
185 source.startPhase(phase);
187 currentPhase = phase;
190 private void loadPhaseStatements() throws SourceException {
191 Preconditions.checkState(currentPhase != null);
192 for(SourceSpecificContext source : sources) {
193 source.loadStatements();
197 private SomeModifiersUnresolvedException addSourceExceptions(final SomeModifiersUnresolvedException buildFailure,
198 final List<SourceSpecificContext> sourcesToProgress) {
199 for(SourceSpecificContext failedSource : sourcesToProgress) {
200 SourceException sourceEx = failedSource.failModifiers(currentPhase);
201 buildFailure.addSuppressed(sourceEx);
206 private void completePhaseActions() throws ReactorException {
207 Preconditions.checkState(currentPhase != null);
208 List<SourceSpecificContext> sourcesToProgress = Lists.newArrayList(sources);
210 boolean progressing = true;
212 // We reset progressing to false.
214 Iterator<SourceSpecificContext> currentSource = sourcesToProgress.iterator();
215 while(currentSource.hasNext()) {
216 SourceSpecificContext nextSourceCtx = currentSource.next();
217 PhaseCompletionProgress sourceProgress = nextSourceCtx.tryToCompletePhase(currentPhase);
218 switch (sourceProgress) {
220 currentSource.remove();
221 // Fallback to progress, since we were able to make progress in computation
229 throw new IllegalStateException("Unsupported phase progress " + sourceProgress);
233 } catch (SourceException e) {
234 throw Throwables.propagate(e);
236 if(!sourcesToProgress.isEmpty()) {
237 SomeModifiersUnresolvedException buildFailure = new SomeModifiersUnresolvedException(currentPhase);
238 buildFailure = addSourceExceptions(buildFailure, sourcesToProgress);
243 private void endPhase(final ModelProcessingPhase phase) {
244 Preconditions.checkState(currentPhase == phase);
245 finishedPhase = currentPhase;
248 public Set<SourceSpecificContext> getSources() {