7e306dbabca93e871e2f800cf6f4b592811ca76c
[yangtools.git] / yang / rfc7952-parser-support / src / main / java / org / opendaylight / yangtools / rfc7952 / parser / AnnotationStatementSupport.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.rfc7952.parser;
9
10 import com.google.common.collect.ImmutableList;
11 import org.eclipse.jdt.annotation.NonNull;
12 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationEffectiveStatement;
13 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationSchemaNode;
14 import org.opendaylight.yangtools.rfc7952.model.api.AnnotationStatement;
15 import org.opendaylight.yangtools.rfc7952.model.api.MetadataStatements;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
18 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
19 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
20 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
21 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
22 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
23 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.UnitsStatement;
25 import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypeBuilder;
26 import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypes;
27 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredStatement.WithQNameArgument.WithSubstatements;
28 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStatementSupport;
29 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.UnknownEffectiveStatementBase;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
33 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
35 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
36
37 public final class AnnotationStatementSupport
38         extends BaseStatementSupport<QName, AnnotationStatement, AnnotationEffectiveStatement> {
39
40     private static final class Declared extends WithSubstatements implements AnnotationStatement {
41         Declared(final QName argument, final ImmutableList<? extends DeclaredStatement<?>> substatements) {
42             super(argument, substatements);
43         }
44     }
45
46     private static final class Effective extends UnknownEffectiveStatementBase<QName, AnnotationStatement>
47             implements AnnotationEffectiveStatement, AnnotationSchemaNode {
48
49         private final @NonNull TypeDefinition<?> type;
50         private final @NonNull SchemaPath path;
51
52         Effective(final Current<QName, AnnotationStatement> stmt,
53                   final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
54             super(stmt, substatements);
55             path = stmt.getEffectiveParent().getSchemaPath().createChild(argument());
56
57             final TypeEffectiveStatement<?> typeStmt = SourceException.throwIfNull(
58                 firstSubstatementOfType(TypeEffectiveStatement.class), stmt,
59                 "AnnotationStatementSupport %s is missing a 'type' statement", argument());
60
61             final ConcreteTypeBuilder<?> builder = ConcreteTypes.concreteTypeBuilder(typeStmt.getTypeDefinition(),
62                 path);
63             final StmtContext<String, ?, ?> unitsStmt = StmtContextUtils.findFirstEffectiveSubstatement(
64                     stmt.caerbannog(), UnitsStatement.class);
65             if (unitsStmt != null) {
66                 builder.setUnits(unitsStmt.argument());
67             }
68             type = builder.build();
69         }
70
71         @Override
72         public QName getQName() {
73             return path.getLastComponent();
74         }
75
76         @Override
77         @Deprecated
78         public SchemaPath getPath() {
79             return path;
80         }
81
82         @Override
83         public TypeDefinition<?> getType() {
84             return type;
85         }
86
87         @Override
88         public TypeDefinition<?> getTypeDefinition() {
89             return type;
90         }
91
92         @Override
93         public AnnotationEffectiveStatement asEffectiveStatement() {
94             return this;
95         }
96     }
97
98     private static final AnnotationStatementSupport INSTANCE = new AnnotationStatementSupport(
99         MetadataStatements.ANNOTATION);
100
101     private final SubstatementValidator validator;
102
103     AnnotationStatementSupport(final StatementDefinition definition) {
104         super(definition);
105         this.validator = SubstatementValidator.builder(definition)
106                 .addMandatory(YangStmtMapping.TYPE)
107                 .addOptional(YangStmtMapping.DESCRIPTION)
108                 .addAny(YangStmtMapping.IF_FEATURE)
109                 .addOptional(YangStmtMapping.REFERENCE)
110                 .addOptional(YangStmtMapping.STATUS)
111                 .addOptional(YangStmtMapping.UNITS)
112                 .build();
113     }
114
115     public static AnnotationStatementSupport getInstance() {
116         return INSTANCE;
117     }
118
119     @Override
120     public QName parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
121         return StmtContextUtils.parseIdentifier(ctx, value);
122     }
123
124     @Override
125     public void onStatementAdded(final Mutable<QName, AnnotationStatement, AnnotationEffectiveStatement> stmt) {
126         final StatementDefinition parentDef = stmt.coerceParentContext().publicDefinition();
127         SourceException.throwIf(YangStmtMapping.MODULE != parentDef && YangStmtMapping.SUBMODULE != parentDef,
128                 stmt, "Annotations may only be defined at root of either a module or a submodule");
129     }
130
131     @Override
132     protected SubstatementValidator getSubstatementValidator() {
133         return validator;
134     }
135
136     @Override
137     protected AnnotationStatement createDeclared(final StmtContext<QName, AnnotationStatement, ?> ctx,
138             final ImmutableList<? extends DeclaredStatement<?>> substatements) {
139         return new Declared(ctx.getArgument(), substatements);
140     }
141
142     @Override
143     protected AnnotationStatement createEmptyDeclared(final StmtContext<QName, AnnotationStatement, ?> ctx) {
144         return createDeclared(ctx, ImmutableList.of());
145     }
146
147     @Override
148     protected AnnotationEffectiveStatement createEffective(final Current<QName, AnnotationStatement> stmt,
149             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
150         return new Effective(stmt, substatements);
151     }
152 }