Adjust test suite parser update to conform with API changes
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / EffectiveStmtUtils.java
1 /*
2  * Copyright (c) 2015 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
9 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt;
10
11 import com.google.common.annotations.Beta;
12 import com.google.common.base.Strings;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.Optional;
16 import java.util.Set;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.common.YangVersion;
19 import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
20 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
21 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
22 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
23 import org.opendaylight.yangtools.yang.model.api.stmt.MaxElementsEffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.MinElementsEffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
26 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
27 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
28 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
30 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
31
32 @Beta
33 public final class EffectiveStmtUtils {
34     // FIXME: this should reside somewhere in max_elements
35     private static final String UNBOUNDED_STR = "unbounded";
36
37     private EffectiveStmtUtils() {
38         throw new UnsupportedOperationException("Utility class");
39     }
40
41     public static SourceException createNameCollisionSourceException(final StmtContext<?, ?, ?> ctx,
42             final EffectiveStatement<?, ?> effectiveStatement) {
43         return new SourceException(ctx.getStatementSourceReference(),
44             "Error in module '%s': cannot add '%s'. Node name collision: '%s' already declared.",
45             ctx.getRoot().getStatementArgument(),
46             effectiveStatement.argument(),
47             effectiveStatement.argument());
48     }
49
50     public static Optional<ElementCountConstraint> createElementCountConstraint(final EffectiveStatement<?, ?> stmt) {
51         final Integer minElements;
52         final Optional<Integer> min = stmt.findFirstEffectiveSubstatementArgument(MinElementsEffectiveStatement.class);
53         if (min.isPresent()) {
54             final Integer m = min.get();
55             minElements = m > 0 ? m : null;
56         } else {
57             minElements = null;
58         }
59
60         final Integer maxElements;
61         final String max = stmt.findFirstEffectiveSubstatementArgument(MaxElementsEffectiveStatement.class)
62                 .orElse(UNBOUNDED_STR);
63         if (!UNBOUNDED_STR.equals(max)) {
64             final Integer m = Integer.valueOf(max);
65             maxElements = m < Integer.MAX_VALUE ? m : null;
66         } else {
67             maxElements = null;
68         }
69
70         return ElementCountConstraint.forNullable(minElements, maxElements);
71     }
72
73
74     /**
75      * Checks whether supplied type has any of specified default values marked
76      * with an if-feature. This method creates mutable copy of supplied set of
77      * default values.
78      *
79      * @param yangVersion
80      *            yang version
81      * @param typeStmt
82      *            type statement which should be checked
83      * @param defaultValues
84      *            set of default values which should be checked. The method
85      *            creates mutable copy of this set
86      *
87      * @return true if any of specified default values is marked with an
88      *         if-feature, otherwise false
89      */
90     public static boolean hasDefaultValueMarkedWithIfFeature(final YangVersion yangVersion,
91             final TypeEffectiveStatement<?> typeStmt, final Set<String> defaultValues) {
92         return !defaultValues.isEmpty() && yangVersion == YangVersion.VERSION_1_1
93                 && isRelevantForIfFeatureCheck(typeStmt)
94                 && isAnyDefaultValueMarkedWithIfFeature(typeStmt, new HashSet<>(defaultValues));
95     }
96
97     /**
98      * Checks whether supplied type has specified default value marked with an
99      * if-feature. This method creates mutable set of supplied default value.
100      *
101      * @param yangVersion
102      *            yang version
103      * @param typeStmt
104      *            type statement which should be checked
105      * @param defaultValue
106      *            default value to be checked
107      *
108      * @return true if specified default value is marked with an if-feature,
109      *         otherwise false
110      */
111     public static boolean hasDefaultValueMarkedWithIfFeature(final YangVersion yangVersion,
112             final TypeEffectiveStatement<?> typeStmt, final String defaultValue) {
113         final HashSet<String> defaultValues = new HashSet<>();
114         defaultValues.add(defaultValue);
115         return !Strings.isNullOrEmpty(defaultValue) && yangVersion == YangVersion.VERSION_1_1
116                 && isRelevantForIfFeatureCheck(typeStmt)
117                 && isAnyDefaultValueMarkedWithIfFeature(typeStmt, defaultValues);
118     }
119
120     private static boolean isRelevantForIfFeatureCheck(final TypeEffectiveStatement<?> typeStmt) {
121         final TypeDefinition<?> typeDefinition = typeStmt.getTypeDefinition();
122         return typeDefinition instanceof EnumTypeDefinition || typeDefinition instanceof BitsTypeDefinition
123                 || typeDefinition instanceof UnionTypeDefinition;
124     }
125
126     private static boolean isAnyDefaultValueMarkedWithIfFeature(final TypeEffectiveStatement<?> typeStmt,
127             final Set<String> defaultValues) {
128         final Iterator<? extends EffectiveStatement<?, ?>> iter = typeStmt.effectiveSubstatements().iterator();
129         while (iter.hasNext() && !defaultValues.isEmpty()) {
130             final EffectiveStatement<?, ?> effectiveSubstatement = iter.next();
131             if (YangStmtMapping.BIT.equals(effectiveSubstatement.statementDefinition())) {
132                 final QName bitQName = (QName) effectiveSubstatement.argument();
133                 if (defaultValues.remove(bitQName.getLocalName()) && containsIfFeature(effectiveSubstatement)) {
134                     return true;
135                 }
136             } else if (YangStmtMapping.ENUM.equals(effectiveSubstatement.statementDefinition())
137                     && defaultValues.remove(effectiveSubstatement.argument())
138                     && containsIfFeature(effectiveSubstatement)) {
139                 return true;
140             } else if (effectiveSubstatement instanceof TypeEffectiveStatement && isAnyDefaultValueMarkedWithIfFeature(
141                     (TypeEffectiveStatement<?>) effectiveSubstatement, defaultValues)) {
142                 return true;
143             }
144         }
145
146         return false;
147     }
148
149     private static boolean containsIfFeature(final EffectiveStatement<?, ?> effectiveStatement) {
150         for (final EffectiveStatement<?, ?> effectiveSubstatement : effectiveStatement.effectiveSubstatements()) {
151             if (YangStmtMapping.IF_FEATURE.equals(effectiveSubstatement.statementDefinition())) {
152                 return true;
153             }
154         }
155         return false;
156     }
157 }