Trim down ReplicaStatementContext
[yangtools.git] / yang / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / AbstractResumedStatement.java
1 /*
2  * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
9
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
12
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;
33
34 /**
35  * Intermediate subclass of StatementContextBase facing the parser stream via implementation of ResumedStatement. This
36  * shields inference-type substatements from these details.
37  *
38  * @param <A> Argument type
39  * @param <D> Declared Statement representation
40  * @param <E> Effective Statement representation
41  */
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);
45
46     private final @NonNull StatementSourceReference statementDeclSource;
47     private final String rawArgument;
48
49     private List<ReactorStmtCtx<?, ?, ?>> effective = ImmutableList.of();
50     private StatementMap substatements = StatementMap.empty();
51     private @Nullable D declaredInstance;
52
53     // Copy constructor
54     AbstractResumedStatement(final AbstractResumedStatement<A, D, E> original) {
55         super(original);
56         this.statementDeclSource = original.statementDeclSource;
57         this.rawArgument = original.rawArgument;
58         this.substatements = original.substatements;
59         this.declaredInstance = original.declaredInstance;
60     }
61
62     AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
63             final String rawArgument) {
64         super(def);
65         this.statementDeclSource = requireNonNull(ref);
66         this.rawArgument = def.support().internArgument(rawArgument);
67     }
68
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;
74     }
75
76     @Override
77     public final Optional<StmtContext<A, D, E>> getOriginalCtx() {
78         return Optional.empty();
79     }
80
81     @Override
82     public final Optional<StmtContext<A, D, E>> getPreviousCopyCtx() {
83         return Optional.empty();
84     }
85
86     @Override
87     public final StatementSourceReference sourceReference() {
88         return statementDeclSource;
89     }
90
91     @Override
92     public final String rawArgument() {
93         return rawArgument;
94     }
95
96     @Override
97     public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
98         return substatements;
99     }
100
101     @Override
102     public final Collection<? extends Mutable<?, ?, ?>> mutableEffectiveSubstatements() {
103         return mutableEffectiveSubstatements(effective);
104     }
105
106     @Override
107     public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef) {
108         effective = removeStatementFromEffectiveSubstatements(effective, statementDef);
109     }
110
111     @Override
112     public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef,
113             final String statementArg) {
114         effective = removeStatementFromEffectiveSubstatements(effective, statementDef, statementArg);
115     }
116
117     @Override
118     public final void addEffectiveSubstatement(final Mutable<?, ?, ?> substatement) {
119         effective = addEffectiveSubstatement(effective, substatement);
120     }
121
122     @Override
123     final void addEffectiveSubstatementsImpl(final Collection<? extends Mutable<?, ?, ?>> statements) {
124         effective = addEffectiveSubstatementsImpl(effective, statements);
125     }
126
127     @Override
128     public final D declared() {
129         final D existing;
130         return (existing = declaredInstance) != null ? existing : loadDeclared();
131     }
132
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);
138     }
139
140     @Override
141     public StatementDefinition getDefinition() {
142         return publicDefinition();
143     }
144
145     @Override
146     public StatementSourceReference getSourceReference() {
147         return sourceReference();
148     }
149
150     @Override
151     public boolean isFullyDefined() {
152         return fullyDefined();
153     }
154
155     /**
156      * Create a new substatement at the specified offset.
157      *
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
166      */
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());
175
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,
180                     ref, argument);
181         }
182
183         final AbstractResumedStatement<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
184         substatements = substatements.put(offset, ret);
185         def.onStatementAdded(ret);
186         return ret;
187     }
188
189     @Override
190     final boolean hasEmptySubstatements() {
191         return substatements.size() == 0 && effective.isEmpty();
192     }
193
194     @Override
195     final Iterable<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
196         return effective;
197     }
198
199     @Override
200     final Stream<? extends StmtContext<?, ?, ?>> streamDeclared() {
201         return declaredSubstatements().stream();
202     }
203
204     @Override
205     final Stream<? extends StmtContext<?, ?, ?>> streamEffective() {
206         return effective.stream();
207     }
208
209     @Override
210     final int sweepSubstatements() {
211         // First we need to sweep all statements, which may trigger sweeps all across the place, for example:
212         // - 'effective' member sweeping a 'substatements' member
213         // - 'substatements' member sweeping a 'substatements' member which came before it during iteration
214         // We then iterate once again, counting what remains unswept
215         sweep(substatements);
216         sweep(effective);
217         final int count = countUnswept(substatements) + countUnswept(effective);
218         if (count != 0) {
219             LOG.debug("{} children left to sweep from {}", count, this);
220         }
221         substatements = null;
222         effective = null;
223         return count;
224     }
225
226     /**
227      * Lookup substatement by its offset in this statement.
228      *
229      * @param offset Substatement offset
230      * @return Substatement, or null if substatement does not exist.
231      */
232     final AbstractResumedStatement<?, ?, ?> lookupSubstatement(final int offset) {
233         return substatements.get(offset);
234     }
235
236     final void resizeSubstatements(final int expectedSize) {
237         substatements = substatements.ensureCapacity(expectedSize);
238     }
239
240     final void walkChildren(final ModelProcessingPhase phase) {
241         checkState(isFullyDefined());
242         substatements.forEach(stmt -> {
243             stmt.walkChildren(phase);
244             stmt.endDeclared(phase);
245         });
246     }
247
248     private AbstractResumedStatement<?, ?, ?> createImplicitParent(final int offset,
249             final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
250         final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent);
251         return createSubstatement(offset, def, ImplicitSubstatement.of(ref), argument);
252     }
253 }