2 * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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 static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.collect.ImmutableList;
14 import java.util.Collection;
15 import java.util.List;
16 import java.util.Optional;
17 import java.util.stream.Stream;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
21 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
22 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
27 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
28 import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement;
29 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
30 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.ResumedStatement;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
35 * Intermediate subclass of StatementContextBase facing the parser stream via implementation of ResumedStatement. This
36 * shields inference-type substatements from these details.
38 * @param <A> Argument type
39 * @param <D> Declared Statement representation
40 * @param <E> Effective Statement representation
42 abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
43 extends StatementContextBase<A, D, E> implements ResumedStatement {
44 private static final Logger LOG = LoggerFactory.getLogger(AbstractResumedStatement.class);
46 private final @NonNull StatementSourceReference statementDeclSource;
47 private final String rawArgument;
49 private List<ReactorStmtCtx<?, ?, ?>> effective = ImmutableList.of();
50 private StatementMap substatements = StatementMap.empty();
51 private @Nullable D declaredInstance;
54 AbstractResumedStatement(final AbstractResumedStatement<A, D, E> original) {
56 this.statementDeclSource = original.statementDeclSource;
57 this.rawArgument = original.rawArgument;
58 this.substatements = original.substatements;
59 this.declaredInstance = original.declaredInstance;
62 AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
63 final String rawArgument) {
65 this.statementDeclSource = requireNonNull(ref);
66 this.rawArgument = def.support().internArgument(rawArgument);
69 AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
70 final String rawArgument, final CopyType copyType) {
71 super(def, CopyHistory.of(copyType, CopyHistory.original()));
72 this.statementDeclSource = requireNonNull(ref);
73 this.rawArgument = rawArgument;
77 public final Optional<StmtContext<A, D, E>> getOriginalCtx() {
78 return Optional.empty();
82 public final Optional<StmtContext<A, D, E>> getPreviousCopyCtx() {
83 return Optional.empty();
87 public final StatementSourceReference sourceReference() {
88 return statementDeclSource;
92 public final String rawArgument() {
97 public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
102 public final Collection<? extends Mutable<?, ?, ?>> mutableEffectiveSubstatements() {
103 return mutableEffectiveSubstatements(effective);
107 public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef) {
108 effective = removeStatementFromEffectiveSubstatements(effective, statementDef);
112 public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef,
113 final String statementArg) {
114 effective = removeStatementFromEffectiveSubstatements(effective, statementDef, statementArg);
118 public final void addEffectiveSubstatement(final Mutable<?, ?, ?> substatement) {
119 effective = addEffectiveSubstatement(effective, substatement);
123 final void addEffectiveSubstatementsImpl(final Collection<? extends Mutable<?, ?, ?>> statements) {
124 effective = addEffectiveSubstatementsImpl(effective, statements);
128 public final D declared() {
130 return (existing = declaredInstance) != null ? existing : loadDeclared();
133 private @NonNull D loadDeclared() {
134 final ModelProcessingPhase phase = getCompletedPhase();
135 checkState(phase == ModelProcessingPhase.FULL_DECLARATION || phase == ModelProcessingPhase.EFFECTIVE_MODEL,
136 "Cannot build declared instance after phase %s", phase);
137 return declaredInstance = definition().getFactory().createDeclared(this);
141 public StatementDefinition getDefinition() {
142 return publicDefinition();
146 public StatementSourceReference getSourceReference() {
147 return sourceReference();
151 public boolean isFullyDefined() {
152 return fullyDefined();
156 * Create a new substatement at the specified offset.
158 * @param offset Substatement offset
159 * @param def definition context
160 * @param ref source reference
161 * @param argument statement argument
162 * @param <X> new substatement argument type
163 * @param <Y> new substatement declared type
164 * @param <Z> new substatement effective type
165 * @return A new substatement
167 @SuppressWarnings("checkstyle:methodTypeParameterName")
168 final <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
169 AbstractResumedStatement<X, Y, Z> createSubstatement(final int offset,
170 final StatementDefinitionContext<X, Y, Z> def, final StatementSourceReference ref,
171 final String argument) {
172 final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase();
173 checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
174 "Declared statement cannot be added in effective phase at: %s", sourceReference());
176 final Optional<StatementSupport<?, ?, ?>> implicitParent =
177 definition().getImplicitParentFor(def.getPublicView());
178 if (implicitParent.isPresent()) {
179 return createImplicitParent(offset, implicitParent.get(), ref, argument).createSubstatement(offset, def,
183 final AbstractResumedStatement<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
184 substatements = substatements.put(offset, ret);
185 def.onStatementAdded(ret);
190 final AbstractResumedStatement<A, D, E> unmodifiedEffectiveSource() {
191 // This statement is comes from the source
196 final boolean hasEmptySubstatements() {
197 return substatements.size() == 0 && effective.isEmpty();
201 final boolean noSensitiveSubstatements() {
202 return hasEmptySubstatements()
203 || noSensitiveSubstatements(substatements) && noSensitiveSubstatements(effective);
207 final Iterable<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
212 final Stream<? extends @NonNull StmtContext<?, ?, ?>> streamDeclared() {
213 return declaredSubstatements().stream().filter(StmtContext::isSupportedToBuildEffective);
217 final Stream<? extends @NonNull StmtContext<?, ?, ?>> streamEffective() {
218 return effective.stream().filter(StmtContext::isSupportedToBuildEffective);
222 final void markNoParentRef() {
223 markNoParentRef(substatements);
224 markNoParentRef(effective);
228 final int sweepSubstatements() {
229 // First we need to sweep all statements, which may trigger sweeps all across the place, for example:
230 // - 'effective' member sweeping a 'substatements' member
231 // - 'substatements' member sweeping a 'substatements' member which came before it during iteration
232 // We then iterate once again, counting what remains unswept
233 sweep(substatements);
235 final int count = countUnswept(substatements) + countUnswept(effective);
237 LOG.debug("{} children left to sweep from {}", count, this);
239 substatements = null;
245 * Lookup substatement by its offset in this statement.
247 * @param offset Substatement offset
248 * @return Substatement, or null if substatement does not exist.
250 final AbstractResumedStatement<?, ?, ?> lookupSubstatement(final int offset) {
251 return substatements.get(offset);
254 final void resizeSubstatements(final int expectedSize) {
255 substatements = substatements.ensureCapacity(expectedSize);
258 final void walkChildren(final ModelProcessingPhase phase) {
259 checkState(isFullyDefined());
260 substatements.forEach(stmt -> {
261 stmt.walkChildren(phase);
262 stmt.endDeclared(phase);
266 private AbstractResumedStatement<?, ?, ?> createImplicitParent(final int offset,
267 final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
268 final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent);
269 return createSubstatement(offset, def, ImplicitSubstatement.of(ref), argument);