Add BaseQNameStatementSupport.historyAndStatusFlags()
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / action / ActionStatementSupport.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies, 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.rfc7950.stmt.action;
9
10 import com.google.common.collect.ImmutableList;
11 import com.google.common.collect.ImmutableSet;
12 import org.opendaylight.yangtools.yang.common.QName;
13 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
14 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
15 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
16 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
17 import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
18 import org.opendaylight.yangtools.yang.model.api.stmt.ActionStatement;
19 import org.opendaylight.yangtools.yang.model.api.stmt.InputStatement;
20 import org.opendaylight.yangtools.yang.model.api.stmt.OutputStatement;
21 import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
22 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseQNameStatementSupport;
23 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.input.InputStatementRFC7950Support;
24 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.output.OutputStatementRFC7950Support;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
27 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
29 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
30 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
31 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
32
33 public final class ActionStatementSupport extends BaseQNameStatementSupport<ActionStatement, ActionEffectiveStatement> {
34     private static final ImmutableSet<StatementDefinition> ILLEGAL_PARENTS = ImmutableSet.of(
35             YangStmtMapping.NOTIFICATION, YangStmtMapping.RPC, YangStmtMapping.ACTION);
36
37     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(
38         YangStmtMapping.ACTION)
39         .addOptional(YangStmtMapping.DESCRIPTION)
40         .addAny(YangStmtMapping.GROUPING)
41         .addAny(YangStmtMapping.IF_FEATURE)
42         .addOptional(YangStmtMapping.INPUT)
43         .addOptional(YangStmtMapping.OUTPUT)
44         .addOptional(YangStmtMapping.REFERENCE)
45         .addOptional(YangStmtMapping.STATUS)
46         .addAny(YangStmtMapping.TYPEDEF)
47         .build();
48     private static final ActionStatementSupport INSTANCE = new ActionStatementSupport();
49
50     private ActionStatementSupport() {
51         super(YangStmtMapping.ACTION);
52     }
53
54     public static ActionStatementSupport getInstance() {
55         return INSTANCE;
56     }
57
58     @Override
59     public QName parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
60         return StmtContextUtils.parseIdentifier(ctx, value);
61     }
62
63     @Override
64     public void onStatementAdded(final Mutable<QName, ActionStatement, ActionEffectiveStatement> stmt) {
65         stmt.coerceParentContext().addToNs(ChildSchemaNodeNamespace.class, stmt.coerceStatementArgument(), stmt);
66     }
67
68     @Override
69     public void onFullDefinitionDeclared(final Mutable<QName, ActionStatement, ActionEffectiveStatement> stmt) {
70         super.onFullDefinitionDeclared(stmt);
71
72         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, InputStatement.class) == null) {
73             ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(
74                 InputStatementRFC7950Support.getInstance(), null);
75         }
76         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, OutputStatement.class) == null) {
77             ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(
78                 OutputStatementRFC7950Support.getInstance(), null);
79         }
80     }
81
82     @Override
83     protected SubstatementValidator getSubstatementValidator() {
84         return SUBSTATEMENT_VALIDATOR;
85     }
86
87     @Override
88     protected ActionStatement createDeclared(final StmtContext<QName, ActionStatement, ?> ctx,
89             final ImmutableList<? extends DeclaredStatement<?>> substatements) {
90         return new RegularActionStatement(ctx.coerceStatementArgument(), substatements);
91     }
92
93     @Override
94     protected ActionStatement createEmptyDeclared(final StmtContext<QName, ActionStatement, ?> ctx) {
95         return new EmptyActionStatement(ctx.coerceStatementArgument());
96     }
97
98     @Override
99     protected ActionEffectiveStatement createEffective(
100             final StmtContext<QName, ActionStatement, ActionEffectiveStatement> ctx, final ActionStatement declared,
101             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
102         final QName argument = ctx.coerceStatementArgument();
103         final StatementSourceReference ref = ctx.getStatementSourceReference();
104         SourceException.throwIf(StmtContextUtils.hasAncestorOfType(ctx, ILLEGAL_PARENTS), ref,
105             "Action %s is defined within a notification, rpc or another action", argument);
106         SourceException.throwIf(
107             !StmtContextUtils.hasAncestorOfTypeWithChildOfType(ctx, YangStmtMapping.LIST, YangStmtMapping.KEY), ref,
108             "Action %s is defined within a list that has no key statement", argument);
109         SourceException.throwIf(StmtContextUtils.hasParentOfType(ctx, YangStmtMapping.CASE), ref,
110             "Action %s is defined within a case statement", argument);
111         SourceException.throwIf(StmtContextUtils.hasParentOfType(ctx, YangStmtMapping.MODULE), ref,
112             "Action %s is defined at the top level of a module", argument);
113
114         return new ActionEffectiveStatementImpl(declared, ctx.getSchemaPath().get(),
115             historyAndStatusFlags(ctx, substatements), ctx, substatements);
116     }
117
118     @Override
119     protected ActionEffectiveStatement createEmptyEffective(
120             final StmtContext<QName, ActionStatement, ActionEffectiveStatement> ctx, final ActionStatement declared) {
121         throw new IllegalStateException("Missing implicit input/output statements at "
122             + ctx.getStatementSourceReference());
123     }
124 }