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