5f78473409beba91acc998cb7b9343dff70449fb
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / type / TypeStatementRFC7950Support.java
1 /*
2  * Copyright (c) 2017 Cisco Systems, Inc. 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.type;
9
10 import com.google.common.annotations.Beta;
11 import com.google.common.collect.ImmutableMap;
12 import java.util.Optional;
13 import org.opendaylight.yangtools.yang.common.Uint32;
14 import org.opendaylight.yangtools.yang.model.api.stmt.BitEffectiveStatement;
15 import org.opendaylight.yangtools.yang.model.api.stmt.EnumEffectiveStatement;
16 import org.opendaylight.yangtools.yang.model.api.stmt.ValueEffectiveStatement;
17 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
18 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
19 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
20 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
23 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
24
25 /**
26  * Class providing necessary support for processing YANG 1.1 Type statement.
27  */
28 @Beta
29 public final class TypeStatementRFC7950Support extends AbstractTypeStatementSupport {
30     private static final ImmutableMap<String, StatementSupport<?, ?, ?>> ARGUMENT_SPECIFIC_SUPPORTS = ImmutableMap.of(
31         LEAF_REF, new LeafrefSpecificationRFC7950Support(),
32         IDENTITY_REF, new IdentityrefSpecificationRFC7950Support());
33     private static final TypeStatementRFC7950Support INSTANCE = new TypeStatementRFC7950Support();
34
35     private TypeStatementRFC7950Support() {
36         // Hidden
37     }
38
39     public static TypeStatementRFC7950Support getInstance() {
40         return INSTANCE;
41     }
42
43     @Override
44     public boolean hasArgumentSpecificSupports() {
45         return !ARGUMENT_SPECIFIC_SUPPORTS.isEmpty() || super.hasArgumentSpecificSupports();
46     }
47
48     @Override
49     public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
50         final StatementSupport<?, ?, ?> potential = ARGUMENT_SPECIFIC_SUPPORTS.get(argument);
51         return potential != null ? potential : super.getSupportSpecificForArgument(argument);
52     }
53
54     @Override
55     Bit addRestrictedBit(final EffectiveStmtCtx stmt, final BitsTypeDefinition base, final BitEffectiveStatement bit) {
56         // FIXME: this looks like a duplicate of BitsSpecificationEffectiveStatement
57         final Optional<Uint32> declaredPosition = bit.getDeclaredPosition();
58         final Uint32 effectivePos;
59         if (declaredPosition.isEmpty()) {
60             effectivePos = getBaseTypeBitPosition(bit.argument(), base, stmt);
61         } else {
62             effectivePos = declaredPosition.get();
63         }
64
65         return EffectiveTypeUtil.buildBit(bit, effectivePos);
66     }
67
68     @Override
69     EnumPair addRestrictedEnum(final EffectiveStmtCtx stmt, final EnumTypeDefinition base,
70             final EnumEffectiveStatement enumStmt) {
71         final EnumEffectiveStatement enumSubStmt = enumStmt;
72         final Optional<Integer> declaredValue =
73                 enumSubStmt.findFirstEffectiveSubstatementArgument(ValueEffectiveStatement.class);
74         final int effectiveValue;
75         if (declaredValue.isEmpty()) {
76             effectiveValue = getBaseTypeEnumValue(enumSubStmt.getDeclared().rawArgument(), base, stmt);
77         } else {
78             effectiveValue = declaredValue.orElseThrow();
79         }
80
81         return EffectiveTypeUtil.buildEnumPair(enumSubStmt, effectiveValue);
82     }
83
84     private static Uint32 getBaseTypeBitPosition(final String bitName, final BitsTypeDefinition baseType,
85             final EffectiveStmtCtx stmt) {
86         for (Bit baseTypeBit : baseType.getBits()) {
87             if (bitName.equals(baseTypeBit.getName())) {
88                 return baseTypeBit.getPosition();
89             }
90         }
91
92         throw new SourceException(stmt.sourceReference(), "Bit '%s' is not a subset of its base bits type %s.", bitName,
93             baseType.getQName());
94     }
95
96
97     private static int getBaseTypeEnumValue(final String enumName, final EnumTypeDefinition baseType,
98             final EffectiveStmtCtx ctx) {
99         for (EnumPair baseTypeEnumPair : baseType.getValues()) {
100             if (enumName.equals(baseTypeEnumPair.getName())) {
101                 return baseTypeEnumPair.getValue();
102             }
103         }
104
105         throw new SourceException(ctx.sourceReference(), "Enum '%s' is not a subset of its base enumeration type %s.",
106             enumName, baseType.getQName());
107     }
108
109 }