Populate xpath/ hierarchy
[yangtools.git] / parser / 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.CopyType;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
27 import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement;
28 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
29 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.ResumedStatement;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Intermediate subclass of StatementContextBase facing the parser stream via implementation of ResumedStatement. This
35  * shields inference-type substatements from these details.
36  *
37  * @param <A> Argument type
38  * @param <D> Declared Statement representation
39  * @param <E> Effective Statement representation
40  */
41 abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
42         extends StatementContextBase<A, D, E> implements ResumedStatement {
43     private static final Logger LOG = LoggerFactory.getLogger(AbstractResumedStatement.class);
44
45     private final @NonNull StatementSourceReference statementDeclSource;
46     private final String rawArgument;
47
48     private List<ReactorStmtCtx<?, ?, ?>> effective = ImmutableList.of();
49     private StatementMap substatements = StatementMap.empty();
50     private @Nullable D declaredInstance;
51
52     // Copy constructor
53     AbstractResumedStatement(final AbstractResumedStatement<A, D, E> original) {
54         super(original);
55         this.statementDeclSource = original.statementDeclSource;
56         this.rawArgument = original.rawArgument;
57         this.substatements = original.substatements;
58         this.declaredInstance = original.declaredInstance;
59     }
60
61     AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
62             final String rawArgument) {
63         super(def);
64         this.statementDeclSource = requireNonNull(ref);
65         this.rawArgument = def.support().internArgument(rawArgument);
66     }
67
68     AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
69             final String rawArgument, final CopyType copyType) {
70         super(def, copyType);
71         this.statementDeclSource = requireNonNull(ref);
72         this.rawArgument = rawArgument;
73     }
74
75     @Override
76     public final Optional<StmtContext<A, D, E>> getOriginalCtx() {
77         return Optional.empty();
78     }
79
80     @Override
81     public final Optional<StmtContext<A, D, E>> getPreviousCopyCtx() {
82         return Optional.empty();
83     }
84
85     @Override
86     public final StatementSourceReference sourceReference() {
87         return statementDeclSource;
88     }
89
90     @Override
91     public final String rawArgument() {
92         return rawArgument;
93     }
94
95     @Override
96     public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
97         return substatements;
98     }
99
100     @Override
101     public final Collection<? extends Mutable<?, ?, ?>> mutableEffectiveSubstatements() {
102         return mutableEffectiveSubstatements(effective);
103     }
104
105     @Override
106     public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef) {
107         effective = removeStatementFromEffectiveSubstatements(effective, statementDef);
108     }
109
110     @Override
111     public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef,
112             final String statementArg) {
113         effective = removeStatementFromEffectiveSubstatements(effective, statementDef, statementArg);
114     }
115
116     @Override
117     public final void addEffectiveSubstatement(final Mutable<?, ?, ?> substatement) {
118         effective = addEffectiveSubstatement(effective, substatement);
119     }
120
121     @Override
122     final void addEffectiveSubstatementsImpl(final Collection<? extends Mutable<?, ?, ?>> statements) {
123         effective = addEffectiveSubstatementsImpl(effective, statements);
124     }
125
126     @Override
127     public final D declared() {
128         final D existing;
129         return (existing = declaredInstance) != null ? existing : loadDeclared();
130     }
131
132     private @NonNull D loadDeclared() {
133         final ModelProcessingPhase phase = getCompletedPhase();
134         checkState(phase == ModelProcessingPhase.FULL_DECLARATION || phase == ModelProcessingPhase.EFFECTIVE_MODEL,
135                 "Cannot build declared instance after phase %s", phase);
136         return declaredInstance = definition().getFactory().createDeclared(this);
137     }
138
139     @Override
140     public final StatementDefinition getDefinition() {
141         return publicDefinition();
142     }
143
144     @Override
145     public final StatementSourceReference getSourceReference() {
146         return statementDeclSource;
147     }
148
149     @Override
150     public final boolean isFullyDefined() {
151         return fullyDefined();
152     }
153
154     /**
155      * Create a new substatement at the specified offset.
156      *
157      * @param offset Substatement offset
158      * @param def definition context
159      * @param ref source reference
160      * @param argument statement argument
161      * @param <X> new substatement argument type
162      * @param <Y> new substatement declared type
163      * @param <Z> new substatement effective type
164      * @return A new substatement
165      */
166     @SuppressWarnings("checkstyle:methodTypeParameterName")
167     final <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
168             AbstractResumedStatement<X, Y, Z> createSubstatement(final int offset,
169                     final StatementDefinitionContext<X, Y, Z> def, final StatementSourceReference ref,
170                     final String argument) {
171         final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase();
172         checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
173                 "Declared statement cannot be added in effective phase at: %s", sourceReference());
174
175         final Optional<StatementSupport<?, ?, ?>> implicitParent =
176                 definition().getImplicitParentFor(def.getPublicView());
177         if (implicitParent.isPresent()) {
178             return createImplicitParent(offset, implicitParent.get(), ref, argument).createSubstatement(offset, def,
179                     ref, argument);
180         }
181
182         final AbstractResumedStatement<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
183         substatements = substatements.put(offset, ret);
184         def.onStatementAdded(ret);
185         return ret;
186     }
187
188     @Override
189     final AbstractResumedStatement<A, D, E> unmodifiedEffectiveSource() {
190         // This statement is comes from the source
191         return this;
192     }
193
194     @Override
195     final boolean hasEmptySubstatements() {
196         return substatements.size() == 0 && effective.isEmpty();
197     }
198
199     @Override
200     final boolean noSensitiveSubstatements() {
201         return hasEmptySubstatements()
202             || noSensitiveSubstatements(substatements) && noSensitiveSubstatements(effective);
203     }
204
205     @Override
206     final Iterable<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
207         return effective;
208     }
209
210     @Override
211     final Stream<? extends @NonNull StmtContext<?, ?, ?>> streamDeclared() {
212         return declaredSubstatements().stream().filter(StmtContext::isSupportedToBuildEffective);
213     }
214
215     @Override
216     final Stream<? extends @NonNull StmtContext<?, ?, ?>> streamEffective() {
217         return effective.stream().filter(StmtContext::isSupportedToBuildEffective);
218     }
219
220     @Override
221     final void markNoParentRef() {
222         markNoParentRef(substatements);
223         markNoParentRef(effective);
224     }
225
226     @Override
227     final int sweepSubstatements() {
228         // First we need to sweep all statements, which may trigger sweeps all across the place, for example:
229         // - 'effective' member sweeping a 'substatements' member
230         // - 'substatements' member sweeping a 'substatements' member which came before it during iteration
231         // We then iterate once again, counting what remains unswept
232         sweep(substatements);
233         sweep(effective);
234         final int count = countUnswept(substatements) + countUnswept(effective);
235         if (count != 0) {
236             LOG.debug("{} children left to sweep from {}", count, this);
237         }
238         substatements = null;
239         effective = null;
240         return count;
241     }
242
243     /**
244      * Lookup substatement by its offset in this statement.
245      *
246      * @param offset Substatement offset
247      * @return Substatement, or null if substatement does not exist.
248      */
249     final AbstractResumedStatement<?, ?, ?> lookupSubstatement(final int offset) {
250         return substatements.get(offset);
251     }
252
253     final void resizeSubstatements(final int expectedSize) {
254         substatements = substatements.ensureCapacity(expectedSize);
255     }
256
257     final void walkChildren(final ModelProcessingPhase phase) {
258         checkState(isFullyDefined());
259         substatements.forEach(stmt -> {
260             stmt.walkChildren(phase);
261             stmt.endDeclared(phase);
262         });
263     }
264
265     private AbstractResumedStatement<?, ?, ?> createImplicitParent(final int offset,
266             final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
267         final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent);
268         return createSubstatement(offset, def, ImplicitSubstatement.of(ref), argument);
269     }
270 }