Rework undeclared statement definition
[yangtools.git] / parser / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / OriginalStmtCtx.java
1 /*
2  * Copyright (c) 2021 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.Verify.verify;
11 import static com.google.common.base.Verify.verifyNotNull;
12 import static java.util.Objects.requireNonNull;
13
14 import com.google.common.collect.ImmutableList;
15 import java.util.Collection;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Optional;
19 import java.util.stream.Stream;
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
22 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
23 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
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.StmtContext;
27 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 abstract class OriginalStmtCtx<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
32         extends StatementContextBase<A, D, E> {
33     private static final Logger LOG = LoggerFactory.getLogger(OriginalStmtCtx.class);
34
35     private final @NonNull StatementSourceReference ref;
36
37     private List<ReactorStmtCtx<?, ?, ?>> effective = ImmutableList.of();
38
39     OriginalStmtCtx(final OriginalStmtCtx<A, D, E> original) {
40         super(original);
41         this.ref = original.ref;
42     }
43
44     OriginalStmtCtx(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref) {
45         super(def);
46         this.ref = requireNonNull(ref);
47     }
48
49     OriginalStmtCtx(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
50             final CopyType copyType) {
51         super(def, copyType);
52         this.ref = requireNonNull(ref);
53     }
54
55     @Override
56     public final StatementSourceReference sourceReference() {
57         return ref;
58     }
59
60     @Override
61     public final Optional<StmtContext<A, D, E>> getOriginalCtx() {
62         return Optional.empty();
63     }
64
65     @Override
66     public final Optional<StmtContext<A, D, E>> getPreviousCopyCtx() {
67         return Optional.empty();
68     }
69
70     @Override
71     public final Collection<? extends Mutable<?, ?, ?>> mutableEffectiveSubstatements() {
72         return mutableEffectiveSubstatements(effective);
73     }
74
75     @Override
76     public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef) {
77         effective = removeStatementFromEffectiveSubstatements(effective, statementDef);
78     }
79
80     @Override
81     public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef,
82             final String statementArg) {
83         effective = removeStatementFromEffectiveSubstatements(effective, statementDef, statementArg);
84     }
85
86     @Override
87     public final void addEffectiveSubstatement(final Mutable<?, ?, ?> substatement) {
88         effective = addEffectiveSubstatement(effective, substatement);
89     }
90
91     @Override
92     final void addEffectiveSubstatementsImpl(final Collection<? extends Mutable<?, ?, ?>> statements) {
93         effective = addEffectiveSubstatementsImpl(effective, statements);
94     }
95
96     @Override
97     final Iterator<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
98         return effective.iterator();
99     }
100
101     @Override
102     final Stream<? extends @NonNull StmtContext<?, ?, ?>> streamEffective() {
103         return effective.stream().filter(StmtContext::isSupportedToBuildEffective);
104     }
105
106     @Override
107     final OriginalStmtCtx<A, D, E> unmodifiedEffectiveSource() {
108         // This statement is comes from the source
109         return this;
110     }
111
112     @Override
113     final boolean hasEmptySubstatements() {
114         return effective.isEmpty() && mutableDeclaredSubstatements().isEmpty();
115     }
116
117     @Override
118     final boolean noSensitiveSubstatements() {
119         return hasEmptySubstatements()
120             || noSensitiveSubstatements(effective) && noSensitiveSubstatements(mutableDeclaredSubstatements());
121     }
122
123     @Override
124     final void markNoParentRef() {
125         markNoParentRef(mutableDeclaredSubstatements());
126         markNoParentRef(effective);
127     }
128
129     @Override
130     final int sweepSubstatements() {
131         // First we need to sweep all statements, which may trigger sweeps all across the place, for example:
132         // - 'effective' member sweeping a 'substatements' member
133         // - 'substatements' member sweeping a 'substatements' member which came before it during iteration
134         // We then iterate once again, counting what remains unswept
135         final var declared = mutableDeclaredSubstatements();
136
137         sweep(declared);
138         sweep(effective);
139         final int count = countUnswept(declared) + countUnswept(effective);
140         if (count != 0) {
141             LOG.debug("{} children left to sweep from {}", count, this);
142         }
143         effective = null;
144         dropDeclaredSubstatements();
145         return count;
146     }
147
148     abstract void dropDeclaredSubstatements();
149
150     void declarationFinished(final ModelProcessingPhase phase) {
151         finishDeclaration(phase);
152     }
153
154     /**
155      * Ends declared section of current node for the specified phase.
156      *
157      * @param phase processing phase that ended
158      */
159     final void finishDeclaration(final ModelProcessingPhase phase) {
160         definition().onDeclarationFinished(this, phase);
161     }
162
163     final OriginalStmtCtx<?, ?, ?> getResumedSubstatement() {
164         final var local = verifyNotNull(effective);
165         verify(!local.isEmpty(), "Unexpected empty statements");
166         final var ret = local.get(0);
167         verify(ret instanceof OriginalStmtCtx, "Unexpected statement %s", ret);
168         return (OriginalStmtCtx<?, ?, ?>) ret;
169     }
170 }