/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.yang.parser.rfc7950.stmt; import com.google.common.annotations.Beta; import com.google.common.base.Strings; import java.util.HashSet; import java.util.Iterator; import java.util.Optional; import java.util.Set; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.YangVersion; import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.MaxElementsEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.MinElementsEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; @Beta public final class EffectiveStmtUtils { // FIXME: this should reside somewhere in max_elements private static final String UNBOUNDED_STR = "unbounded"; private EffectiveStmtUtils() { throw new UnsupportedOperationException("Utility class"); } public static SourceException createNameCollisionSourceException(final StmtContext ctx, final EffectiveStatement effectiveStatement) { return new SourceException(ctx.getStatementSourceReference(), "Error in module '%s': cannot add '%s'. Node name collision: '%s' already declared.", ctx.getRoot().getStatementArgument(), effectiveStatement.argument(), effectiveStatement.argument()); } public static Optional createElementCountConstraint(final EffectiveStatement stmt) { final Integer minElements; final Optional min = stmt.findFirstEffectiveSubstatementArgument(MinElementsEffectiveStatement.class); if (min.isPresent()) { final Integer m = min.get(); minElements = m > 0 ? m : null; } else { minElements = null; } final Integer maxElements; final String max = stmt.findFirstEffectiveSubstatementArgument(MaxElementsEffectiveStatement.class) .orElse(UNBOUNDED_STR); if (!UNBOUNDED_STR.equals(max)) { final Integer m = Integer.valueOf(max); maxElements = m < Integer.MAX_VALUE ? m : null; } else { maxElements = null; } return ElementCountConstraint.forNullable(minElements, maxElements); } /** * Checks whether supplied type has any of specified default values marked * with an if-feature. This method creates mutable copy of supplied set of * default values. * * @param yangVersion * yang version * @param typeStmt * type statement which should be checked * @param defaultValues * set of default values which should be checked. The method * creates mutable copy of this set * * @return true if any of specified default values is marked with an * if-feature, otherwise false */ public static boolean hasDefaultValueMarkedWithIfFeature(final YangVersion yangVersion, final TypeEffectiveStatement typeStmt, final Set defaultValues) { return !defaultValues.isEmpty() && yangVersion == YangVersion.VERSION_1_1 && isRelevantForIfFeatureCheck(typeStmt) && isAnyDefaultValueMarkedWithIfFeature(typeStmt, new HashSet<>(defaultValues)); } /** * Checks whether supplied type has specified default value marked with an * if-feature. This method creates mutable set of supplied default value. * * @param yangVersion * yang version * @param typeStmt * type statement which should be checked * @param defaultValue * default value to be checked * * @return true if specified default value is marked with an if-feature, * otherwise false */ public static boolean hasDefaultValueMarkedWithIfFeature(final YangVersion yangVersion, final TypeEffectiveStatement typeStmt, final String defaultValue) { final HashSet defaultValues = new HashSet<>(); defaultValues.add(defaultValue); return !Strings.isNullOrEmpty(defaultValue) && yangVersion == YangVersion.VERSION_1_1 && isRelevantForIfFeatureCheck(typeStmt) && isAnyDefaultValueMarkedWithIfFeature(typeStmt, defaultValues); } private static boolean isRelevantForIfFeatureCheck(final TypeEffectiveStatement typeStmt) { final TypeDefinition typeDefinition = typeStmt.getTypeDefinition(); return typeDefinition instanceof EnumTypeDefinition || typeDefinition instanceof BitsTypeDefinition || typeDefinition instanceof UnionTypeDefinition; } private static boolean isAnyDefaultValueMarkedWithIfFeature(final TypeEffectiveStatement typeStmt, final Set defaultValues) { final Iterator> iter = typeStmt.effectiveSubstatements().iterator(); while (iter.hasNext() && !defaultValues.isEmpty()) { final EffectiveStatement effectiveSubstatement = iter.next(); if (YangStmtMapping.BIT.equals(effectiveSubstatement.statementDefinition())) { final QName bitQName = (QName) effectiveSubstatement.argument(); if (defaultValues.remove(bitQName.getLocalName()) && containsIfFeature(effectiveSubstatement)) { return true; } } else if (YangStmtMapping.ENUM.equals(effectiveSubstatement.statementDefinition()) && defaultValues.remove(effectiveSubstatement.argument()) && containsIfFeature(effectiveSubstatement)) { return true; } else if (effectiveSubstatement instanceof TypeEffectiveStatement && isAnyDefaultValueMarkedWithIfFeature( (TypeEffectiveStatement) effectiveSubstatement, defaultValues)) { return true; } } return false; } private static boolean containsIfFeature(final EffectiveStatement effectiveStatement) { for (final EffectiveStatement effectiveSubstatement : effectiveStatement.effectiveSubstatements()) { if (YangStmtMapping.IF_FEATURE.equals(effectiveSubstatement.statementDefinition())) { return true; } } return false; } }