Defer copy decisions to StatementSupport
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / status / StatusStatementSupport.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.status;
9
10 import com.google.common.collect.ImmutableList;
11 import java.util.Optional;
12 import org.eclipse.jdt.annotation.NonNull;
13 import org.opendaylight.yangtools.yang.common.QNameModule;
14 import org.opendaylight.yangtools.yang.model.api.Status;
15 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
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.stmt.StatusEffectiveStatement;
19 import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
20 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStatementSupport;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
26 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
27
28 public final class StatusStatementSupport
29         extends BaseStatementSupport<Status, StatusStatement, StatusEffectiveStatement> {
30     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping
31         .STATUS)
32         .build();
33     private static final StatusStatementSupport INSTANCE = new StatusStatementSupport();
34
35     /*
36      * status has low argument cardinality, hence we can reuse them in case declaration does not have any
37      * substatements (which is the usual case). Yeah, we could consider an EnumMap, but this is not too bad, either.
38      */
39     private static final @NonNull EmptyStatusStatement EMPTY_CURRENT_DECL =
40             new EmptyStatusStatement(Status.CURRENT);
41     private static final @NonNull EmptyStatusStatement EMPTY_DEPRECATED_DECL =
42             new EmptyStatusStatement(Status.DEPRECATED);
43     private static final @NonNull EmptyStatusStatement EMPTY_OBSOLETE_DECL =
44             new EmptyStatusStatement(Status.OBSOLETE);
45     private static final @NonNull EmptyStatusEffectiveStatement EMPTY_CURRENT_EFF =
46             new EmptyStatusEffectiveStatement(EMPTY_CURRENT_DECL);
47     private static final @NonNull EmptyStatusEffectiveStatement EMPTY_DEPRECATED_EFF =
48             new EmptyStatusEffectiveStatement(EMPTY_DEPRECATED_DECL);
49     private static final @NonNull EmptyStatusEffectiveStatement EMPTY_OBSOLETE_EFF =
50             new EmptyStatusEffectiveStatement(EMPTY_OBSOLETE_DECL);
51
52     private StatusStatementSupport() {
53         super(YangStmtMapping.STATUS);
54     }
55
56     public static StatusStatementSupport getInstance() {
57         return INSTANCE;
58     }
59
60     @Override
61     public Status parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
62         switch (value) {
63             case "current":
64                 return Status.CURRENT;
65             case "deprecated":
66                 return Status.DEPRECATED;
67             case "obsolete":
68                 return Status.OBSOLETE;
69             default:
70                 throw new SourceException(ctx.getStatementSourceReference(),
71                     "Invalid status '%s', must be one of 'current', 'deprecated' or 'obsolete'", value);
72         }
73     }
74
75     @Override
76     public String internArgument(final String rawArgument) {
77         if ("current".equals(rawArgument)) {
78             return "current";
79         } else if ("deprecated".equals(rawArgument)) {
80             return "deprecated";
81         } else if ("obsolete".equals(rawArgument)) {
82             return "obsolete";
83         } else {
84             return rawArgument;
85         }
86     }
87
88     @Override
89     public Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(final Mutable<?, ?, ?> stmt,
90             final Mutable<?, ?, ?> parent, final CopyType type, final QNameModule targetModule) {
91         return StmtContextUtils.isChildOfGrouping(stmt) ? Optional.empty()
92                 : super.copyAsChildOf(stmt, parent, type, targetModule);
93     }
94
95     @Override
96     protected SubstatementValidator getSubstatementValidator() {
97         return SUBSTATEMENT_VALIDATOR;
98     }
99
100     @Override
101     protected StatusStatement createDeclared(final StmtContext<Status, StatusStatement, ?> ctx,
102             final ImmutableList<? extends DeclaredStatement<?>> substatements) {
103         return new RegularStatusStatement(ctx.coerceStatementArgument(), substatements);
104     }
105
106     @Override
107     protected StatusStatement createEmptyDeclared(final StmtContext<Status, StatusStatement, ?> ctx) {
108         final Status argument = ctx.coerceStatementArgument();
109         switch (argument) {
110             case CURRENT:
111                 return EMPTY_CURRENT_DECL;
112             case DEPRECATED:
113                 return EMPTY_DEPRECATED_DECL;
114             case OBSOLETE:
115                 return EMPTY_OBSOLETE_DECL;
116             default:
117                 throw new IllegalStateException("Unhandled argument " + argument);
118         }
119     }
120
121     @Override
122     protected StatusEffectiveStatement createEffective(
123             final StmtContext<Status, StatusStatement, StatusEffectiveStatement> ctx, final StatusStatement declared,
124             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
125         return new RegularStatusEffectiveStatement(declared, substatements);
126     }
127
128     @Override
129     protected StatusEffectiveStatement createEmptyEffective(
130             final StmtContext<Status, StatusStatement, StatusEffectiveStatement> ctx, final StatusStatement declared) {
131         // Aggressively reuse effective instances which are backed by the corresponding empty declared instance, as this
132         // is the case unless there is a weird extension in use.
133         if (EMPTY_DEPRECATED_DECL.equals(declared)) {
134             // Most likely to be seen (as current is the default)
135             return EMPTY_DEPRECATED_EFF;
136         } else if (EMPTY_OBSOLETE_DECL.equals(declared)) {
137             // less likely
138             return EMPTY_OBSOLETE_EFF;
139         } else if (EMPTY_CURRENT_DECL.equals(declared)) {
140             // ... okay, why is this there? :)
141             return EMPTY_CURRENT_EFF;
142         } else {
143             return new EmptyStatusEffectiveStatement(declared);
144         }
145     }
146 }