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.HashMultimap;
13 import com.google.common.collect.Multimap;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.EventListener;
18 import java.util.Iterator;
19 import java.util.LinkedHashMap;
21 import javax.annotation.Nonnull;
22 import org.opendaylight.yangtools.concepts.Identifiable;
23 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
24 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
26 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
27 import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
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.StorageNodeType;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
33 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
34 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
35 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
36 import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.ValueAddedListener;
38 public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
39 extends NamespaceStorageSupport implements
40 StmtContext.Mutable<A, D, E>, Identifiable<StatementIdentifier> {
42 interface OnNamespaceItemAdded extends EventListener {
44 void namespaceItemAdded(StatementContextBase<?, ?, ?> context,
45 Class<?> namespace, Object key, Object value)
46 throws SourceException;
50 interface OnPhaseFinished extends EventListener {
52 boolean phaseFinished(StatementContextBase<?, ?, ?> context,
53 ModelProcessingPhase phase) throws SourceException;
57 interface ContextMutation {
63 abstract static class ContextBuilder<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> {
65 private final StatementDefinitionContext<A, D, E> definition;
66 private final StatementSourceReference stmtRef;
67 private String rawArg;
68 private StatementSourceReference argRef;
70 public ContextBuilder(StatementDefinitionContext<A, D, E> def,
71 StatementSourceReference sourceRef) {
72 this.definition = def;
73 this.stmtRef = sourceRef;
76 public void setArgument(@Nonnull String argument,
77 @Nonnull StatementSourceReference argumentSource) {
78 Preconditions.checkArgument(definition.hasArgument(),
79 "Statement does not take argument.");
80 this.rawArg = Preconditions.checkNotNull(argument);
81 this.argRef = Preconditions.checkNotNull(argumentSource);
84 public String getRawArgument() {
88 public StatementSourceReference getStamementSource() {
92 public StatementSourceReference getArgumentSource() {
96 public StatementDefinitionContext<A, D, E> getDefinition() {
100 public StatementIdentifier getIdentifier() {
101 return new StatementIdentifier(definition.getStatementName(),
105 public abstract StatementContextBase<A, D, E> build()
106 throws SourceException;
110 private final StatementDefinitionContext<A, D, E> definition;
111 private final StatementIdentifier identifier;
112 private final StatementSourceReference statementDeclSource;
114 private Map<StatementIdentifier, StatementContextBase<?, ?, ?>> substatements = new LinkedHashMap<>();
116 private Collection<StatementContextBase<?, ?, ?>> declared = new ArrayList<>();
117 private Collection<StatementContextBase<?, ?, ?>> effective = new ArrayList<>();
119 private ModelProcessingPhase completedPhase;
121 private Multimap<ModelProcessingPhase, OnPhaseFinished> phaseListeners = HashMultimap
123 private Multimap<ModelProcessingPhase, ContextMutation> phaseMutation = HashMultimap
126 private D declaredInstance;
127 private E effectiveInstance;
129 private StatementContextBase<?, ?, ?> originalCtx;
130 private TypeOfCopy typeOfCopy = TypeOfCopy.ORIGINAL;
133 public TypeOfCopy getTypeOfCopy() {
138 public void setTypeOfCopy(TypeOfCopy typeOfCopy) {
139 this.typeOfCopy = typeOfCopy;
143 public StatementContextBase<?, ?, ?> getOriginalCtx() {
148 public void setOriginalCtx(StatementContextBase<?, ?, ?> originalCtx) {
149 this.originalCtx = originalCtx;
153 public ModelProcessingPhase getCompletedPhase() {
154 return completedPhase;
158 public void setCompletedPhase(ModelProcessingPhase completedPhase) {
159 this.completedPhase = completedPhase;
162 StatementContextBase(@Nonnull ContextBuilder<A, D, E> builder)
163 throws SourceException {
164 this.definition = builder.getDefinition();
165 this.identifier = builder.getIdentifier();
166 this.statementDeclSource = builder.getStamementSource();
167 this.completedPhase = null;
170 StatementContextBase(StatementContextBase<A, D, E> original) {
171 this.definition = original.definition;
172 this.identifier = original.identifier;
173 this.statementDeclSource = original.statementDeclSource;
174 this.completedPhase = null;
178 public abstract StatementContextBase<?, ?, ?> getParentContext();
181 public abstract RootStatementContext<?, ?, ?> getRoot();
184 public StatementIdentifier getIdentifier() {
189 public StatementSource getStatementSource() {
190 return statementDeclSource.getStatementSource();
194 public StatementSourceReference getStatementSourceReference() {
195 return statementDeclSource;
199 public String rawStatementArgument() {
200 return identifier.getArgument();
204 public Collection<StatementContextBase<?, ?, ?>> declaredSubstatements() {
205 return Collections.unmodifiableCollection(declared);
209 public Collection<StatementContextBase<?, ?, ?>> effectiveSubstatements() {
210 return Collections.unmodifiableCollection(effective);
213 public void addEffectiveSubstatement(
214 StatementContextBase<?, ?, ?> substatement) {
215 effective.add(substatement);
218 public void addDeclaredSubstatement(
219 StatementContextBase<?, ?, ?> substatement) {
220 declared.add(substatement);
223 @SuppressWarnings({ "rawtypes", "unchecked" })
224 public ContextBuilder<?, ?, ?> substatementBuilder(
225 StatementDefinitionContext<?, ?, ?> def,
226 StatementSourceReference ref) {
227 return new ContextBuilder(def, ref) {
230 public StatementContextBase build() throws SourceException {
231 StatementContextBase<?, ?, ?> potential = substatements
232 .get(getIdentifier());
233 if (potential == null) {
234 potential = new SubstatementContext(
235 StatementContextBase.this, this);
236 substatements.put(getIdentifier(), potential);
238 potential.resetLists();
239 switch (this.getStamementSource().getStatementSource()) {
241 declared.add(potential);
244 effective.add(potential);
253 public StorageNodeType getStorageNodeType() {
254 return StorageNodeType.STATEMENT_LOCAL;
258 public D buildDeclared() {
260 .checkArgument(completedPhase == ModelProcessingPhase.FULL_DECLARATION
261 || completedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
262 if (declaredInstance == null) {
263 declaredInstance = definition().getFactory().createDeclared(this);
265 return declaredInstance;
269 public E buildEffective() {
270 if (effectiveInstance == null) {
271 effectiveInstance = definition().getFactory().createEffective(this);
273 return effectiveInstance;
280 boolean tryToCompletePhase(ModelProcessingPhase phase)
281 throws SourceException {
282 Iterator<ContextMutation> openMutations = phaseMutation.get(phase)
284 boolean finished = true;
285 while (openMutations.hasNext()) {
286 ContextMutation current = openMutations.next();
287 if (current.isFinished()) {
288 openMutations.remove();
293 for (StatementContextBase<?, ?, ?> child : declared) {
294 finished &= child.tryToCompletePhase(phase);
296 for (StatementContextBase<?, ?, ?> child : effective) {
297 finished &= child.tryToCompletePhase(phase);
301 onPhaseCompleted(phase);
307 private void onPhaseCompleted(ModelProcessingPhase phase)
308 throws SourceException {
309 completedPhase = phase;
310 Iterator<OnPhaseFinished> listener = phaseListeners.get(completedPhase)
312 while (listener.hasNext()) {
313 OnPhaseFinished next = listener.next();
314 if(next.phaseFinished(this, phase)) {
322 * Ends declared section of current node.
325 * @throws SourceException
328 void endDeclared(StatementSourceReference ref, ModelProcessingPhase phase)
329 throws SourceException {
330 definition().onDeclarationFinished(this, phase);
333 protected final StatementDefinitionContext<A, D, E> definition() {
338 protected void checkLocalNamespaceAllowed(
339 Class<? extends IdentifierNamespace<?, ?>> type) {
340 definition().checkNamespaceAllowed(type);
344 protected <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceElementAdded(
345 Class<N> type, K key, V value) {
346 // definition().onNamespaceElementAdded(this, type, key, value);
349 <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceItemAddedAction(
350 final Class<N> type, K key, final OnNamespaceItemAdded listener)
351 throws SourceException {
352 Object potential = getFromNamespace(type, key);
353 if (potential != null) {
354 listener.namespaceItemAdded(this, type, key, potential);
357 NamespaceBehaviour<K, V, N> behaviour = getBehaviourRegistry()
358 .getNamespaceBehaviour(type);
359 if (behaviour instanceof NamespaceBehaviourWithListeners) {
360 NamespaceBehaviourWithListeners<K, V, N> casted = (NamespaceBehaviourWithListeners<K, V, N>) behaviour;
361 casted.addValueListener(key, new ValueAddedListener(this) {
363 void onValueAdded(Object key, Object value) {
365 listener.namespaceItemAdded(StatementContextBase.this,
367 } catch (SourceException e) {
368 throw Throwables.propagate(e);
376 public StatementDefinition getPublicDefinition() {
377 return definition().getPublicView();
381 public ModelActionBuilder newInferenceAction(ModelProcessingPhase phase) {
382 return getRoot().getSourceContext().newInferenceAction(phase);
385 void addPhaseCompletedListener(ModelProcessingPhase phase,
386 OnPhaseFinished listener) throws SourceException {
387 ModelProcessingPhase finishedPhase = completedPhase;
388 while (finishedPhase != null) {
389 if (phase.equals(finishedPhase)) {
390 listener.phaseFinished(this, finishedPhase);
393 finishedPhase = finishedPhase.getPreviousPhase();
395 phaseListeners.put(phase, listener);
398 void addMutation(ModelProcessingPhase phase, ContextMutation mutation) {
399 ModelProcessingPhase finishedPhase = completedPhase;
400 while (finishedPhase != null) {
401 if (phase.equals(finishedPhase)) {
402 throw new IllegalStateException(
403 "Mutation registered after phase was completed.");
405 finishedPhase = finishedPhase.getPreviousPhase();
407 phaseMutation.put(phase, mutation);
411 public <K, KT extends K, N extends StatementNamespace<K, ?, ?>> void addContext(
412 Class<N> namespace, KT key, StmtContext<?, ?, ?> stmt) {
413 addContextToNamespace(namespace, (K) key, stmt);