Add InferredStatementContext
[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 java.util.Collection;
14 import java.util.Optional;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
17 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
18 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
19 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
24 import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement;
25 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
26 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.ResumedStatement;
27
28 /**
29  * Intermediate subclass of StatementContextBase facing the parser stream via implementation of ResumedStatement. This
30  * shields inference-type substatements from these details.
31  *
32  * @param <A> Argument type
33  * @param <D> Declared Statement representation
34  * @param <E> Effective Statement representation
35  */
36 abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
37         extends StatementContextBase<A, D, E> implements ResumedStatement {
38     private final @NonNull StatementSourceReference statementDeclSource;
39     private final StmtContext<?, ?, ?> originalCtx;
40     private final StmtContext<?, ?, ?> prevCopyCtx;
41     private final String rawArgument;
42
43     private StatementMap substatements = StatementMap.empty();
44
45     AbstractResumedStatement(final AbstractResumedStatement<A, D, E> original) {
46         super(original);
47         this.statementDeclSource = original.statementDeclSource;
48         this.rawArgument = original.rawArgument;
49         this.originalCtx = original.getOriginalCtx().orElse(original);
50         this.prevCopyCtx = original;
51         this.substatements = original.substatements;
52     }
53
54     AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
55             final String rawArgument) {
56         super(def);
57         this.statementDeclSource = requireNonNull(ref);
58         this.rawArgument = def.internArgument(rawArgument);
59         this.originalCtx = null;
60         this.prevCopyCtx = null;
61     }
62
63     AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
64             final String rawArgument, final CopyType copyType) {
65         super(def, CopyHistory.of(copyType, CopyHistory.original()));
66         this.statementDeclSource = requireNonNull(ref);
67         this.rawArgument = rawArgument;
68         this.originalCtx = null;
69         this.prevCopyCtx = null;
70     }
71
72     @Override
73     public final Optional<StmtContext<?, ?, ?>> getOriginalCtx() {
74         return Optional.ofNullable(originalCtx);
75     }
76
77     @Override
78     public final Optional<? extends StmtContext<?, ?, ?>> getPreviousCopyCtx() {
79         return Optional.ofNullable(prevCopyCtx);
80     }
81
82     @Override
83     public final StatementSourceReference getStatementSourceReference() {
84         return statementDeclSource;
85     }
86
87     @Override
88     public final String rawStatementArgument() {
89         return rawArgument;
90     }
91
92     @Override
93     public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
94         return substatements.values();
95     }
96
97     @Override
98     public @NonNull StatementDefinition getDefinition() {
99         return getPublicDefinition();
100     }
101
102     @Override
103     public @NonNull StatementSourceReference getSourceReference() {
104         return getStatementSourceReference();
105     }
106
107     @Override
108     public boolean isFullyDefined() {
109         return fullyDefined();
110     }
111
112     /**
113      * Create a new substatement at the specified offset.
114      *
115      * @param offset Substatement offset
116      * @param def definition context
117      * @param ref source reference
118      * @param argument statement argument
119      * @param <X> new substatement argument type
120      * @param <Y> new substatement declared type
121      * @param <Z> new substatement effective type
122      * @return A new substatement
123      */
124     @SuppressWarnings("checkstyle:methodTypeParameterName")
125     final <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
126             AbstractResumedStatement<X, Y, Z> createSubstatement(final int offset,
127                     final StatementDefinitionContext<X, Y, Z> def, final StatementSourceReference ref,
128                     final String argument) {
129         final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase();
130         checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
131                 "Declared statement cannot be added in effective phase at: %s", getStatementSourceReference());
132
133         final Optional<StatementSupport<?, ?, ?>> implicitParent =
134                 definition().getImplicitParentFor(def.getPublicView());
135         if (implicitParent.isPresent()) {
136             return createImplicitParent(offset, implicitParent.get(), ref, argument).createSubstatement(offset, def,
137                     ref, argument);
138         }
139
140         final AbstractResumedStatement<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
141         substatements = substatements.put(offset, ret);
142         def.onStatementAdded(ret);
143         return ret;
144     }
145
146     /**
147      * Lookup substatement by its offset in this statement.
148      *
149      * @param offset Substatement offset
150      * @return Substatement, or null if substatement does not exist.
151      */
152     final AbstractResumedStatement<?, ?, ?> lookupSubstatement(final int offset) {
153         return substatements.get(offset);
154     }
155
156     final void resizeSubstatements(final int expectedSize) {
157         substatements = substatements.ensureCapacity(expectedSize);
158     }
159
160     final void walkChildren(final ModelProcessingPhase phase) {
161         checkState(isFullyDefined());
162         substatements.values().forEach(stmt -> {
163             stmt.walkChildren(phase);
164             stmt.endDeclared(phase);
165         });
166     }
167
168     private AbstractResumedStatement<?, ?, ?> createImplicitParent(final int offset,
169             final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
170         final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent);
171         return createSubstatement(offset, def, ImplicitSubstatement.of(ref), argument);
172     }
173 }