2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Preconditions.checkState;
12 import static com.google.common.base.Verify.verify;
13 import static com.google.common.base.Verify.verifyNotNull;
14 import static java.util.Objects.requireNonNull;
16 import java.util.Optional;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
21 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
22 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
24 final class StatementContextWriter implements StatementWriter {
25 private final ModelProcessingPhase phase;
26 private final SourceSpecificContext ctx;
28 private AbstractResumedStatement<?, ?, ?> current;
30 StatementContextWriter(final SourceSpecificContext ctx, final ModelProcessingPhase phase) {
31 this.ctx = requireNonNull(ctx);
32 this.phase = requireNonNull(phase);
36 public Optional<? extends ResumedStatement> resumeStatement(final int childId) {
37 final AbstractResumedStatement<?, ?, ?> existing = lookupDeclaredChild(current, childId);
38 if (existing != null) {
39 resumeStatement(existing);
40 return Optional.of(existing);
42 return Optional.empty();
45 private void resumeStatement(final AbstractResumedStatement<?, ?, ?> child) {
46 if (child.isFullyDefined()) {
47 child.walkChildren(phase);
48 child.endDeclared(phase);
55 public void storeStatement(final int expectedChildren, final boolean fullyDefined) {
56 checkState(current != null);
57 checkArgument(expectedChildren >= 0);
58 current.resizeSubstatements(expectedChildren);
61 current.setFullyDefined();
66 public void startStatement(final int childId, final QName name, final String argument,
67 final StatementSourceReference ref) {
68 final AbstractResumedStatement<?, ?, ?> existing = lookupDeclaredChild(current, childId);
69 current = existing != null ? existing
70 : verifyNotNull(ctx.createDeclaredChild(current, childId, name, argument, ref));
74 public void endStatement(final StatementSourceReference ref) {
75 checkState(current != null);
76 current.endDeclared(phase);
81 public ModelProcessingPhase getPhase() {
85 private void exitStatement() {
86 // TODO: AbstractResumedStatement should only ever have AbstractResumedStatement parents, which would:
87 // - remove the StatementSource check
88 // - allow endDeclared() to be moved to AbstractResumedStatement
89 // - remove the need for verify()
90 StatementContextBase<?, ?, ?> parentContext = current.getParentContext();
91 while (parentContext != null && StatementSource.CONTEXT == parentContext.getStatementSource()) {
92 parentContext.endDeclared(phase);
93 parentContext = parentContext.getParentContext();
95 if (parentContext != null) {
96 verify(parentContext instanceof AbstractResumedStatement, "Unexpected parent context %s", parentContext);
97 current = (AbstractResumedStatement<?, ?, ?>) parentContext;
103 private static @Nullable AbstractResumedStatement<?, ?, ?> lookupDeclaredChild(
104 final AbstractResumedStatement<?, ?, ?> current, final int childId) {
105 if (current == null) {
109 // Fast path: we are entering a statement which was emitted in previous phase
110 AbstractResumedStatement<?, ?, ?> existing = current.lookupSubstatement(childId);
111 while (existing != null && StatementSource.CONTEXT == existing.getStatementSource()) {
112 existing = existing.lookupSubstatement(childId);