/* * 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.stmt.rfc6020.effective; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.TypeDefinitionAware; import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement; import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement; import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint; import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint; import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint; import org.opendaylight.yangtools.yang.model.util.ExtendedType; import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder; import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.Decimal64SpecificationEffectiveStatementImpl; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.LengthEffectiveStatementImpl; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.PatternEffectiveStatementImpl; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.RangeEffectiveStatementImpl; public final class TypeDefEffectiveStatementImpl extends AbstractEffectiveSchemaNode implements TypeDefinition>, TypedefEffectiveStatement { private final TypeDefinition baseType; private final String defaultValue; private final String units; private final List ranges; private final List lengths; private final List patterns; private final Integer fractionDigits; private ExtendedType extendedType = null; public TypeDefEffectiveStatementImpl(final StmtContext ctx) { super(ctx); baseType = parseBaseTypeFromCtx(ctx); UnitsEffectiveStatementImpl unitsStmt = firstEffective(UnitsEffectiveStatementImpl.class); this.units = (unitsStmt == null) ? null : unitsStmt.argument(); DefaultEffectiveStatementImpl defaultStmt = firstEffective(DefaultEffectiveStatementImpl.class); this.defaultValue = (defaultStmt == null) ? null : defaultStmt.argument(); EffectiveStatementBase typeEffectiveStmt = firstSubstatementOfType(TypeDefinition.class, EffectiveStatementBase.class); ranges = initRanges(typeEffectiveStmt); lengths = initLengths(typeEffectiveStmt); patterns = initPatterns(typeEffectiveStmt); // due to compatibility problems with original yang parser // :FIXME try to find out better solution if (typeEffectiveStmt.argument().equals(TypeUtils.DECIMAL64) && ranges.isEmpty()) { fractionDigits = null; } else { fractionDigits = initFractionDigits(typeEffectiveStmt); } } private TypeDefinition parseBaseTypeFromCtx(final StmtContext ctx) { TypeDefinition baseTypeInit; QName baseTypeQName = Utils.qNameFromArgument(ctx, StmtContextUtils.firstAttributeOf(ctx.declaredSubstatements(), TypeStatement.class)); if (TypeUtils.isYangBuiltInTypeString(baseTypeQName.getLocalName())) { baseTypeInit = TypeUtils.getYangPrimitiveTypeFromString(baseTypeQName.getLocalName()); if (baseTypeInit == null) { baseTypeInit = firstSubstatementOfType(TypeDefinition.class); // due to compatibility problems with original yang parser // :FIXME try to find out better solution if (baseTypeInit instanceof Decimal64SpecificationEffectiveStatementImpl) { Decimal64SpecificationEffectiveStatementImpl decimal64 = (Decimal64SpecificationEffectiveStatementImpl) baseTypeInit; if (decimal64.isExtended()) { baseTypeInit = decimal64.getBaseType(); } } } } else { StmtContext baseTypeCtx = ctx .getParentContext().getFromNamespace(TypeNamespace.class, baseTypeQName); baseTypeInit = (TypeDefEffectiveStatementImpl) baseTypeCtx.buildEffective(); } return baseTypeInit; } private static Integer initFractionDigits(final EffectiveStatementBase typeEffectiveStmt) { final FractionDigitsEffectiveStatementImpl fractionDigitsEffStmt = typeEffectiveStmt .firstEffective(FractionDigitsEffectiveStatementImpl.class); return fractionDigitsEffStmt != null ? fractionDigitsEffStmt.argument() : null; } private static List initRanges(final EffectiveStatementBase typeEffectiveStmt) { final RangeEffectiveStatementImpl rangeConstraints = typeEffectiveStmt .firstEffective(RangeEffectiveStatementImpl.class); return rangeConstraints != null ? rangeConstraints.argument() : Collections. emptyList(); } private static List initLengths(final EffectiveStatementBase typeEffectiveStmt) { final LengthEffectiveStatementImpl lengthConstraints = typeEffectiveStmt .firstEffective(LengthEffectiveStatementImpl.class); return lengthConstraints != null ? lengthConstraints.argument() : Collections. emptyList(); } private static List initPatterns(final EffectiveStatementBase typeEffectiveStmt) { final List patternConstraints = new ArrayList<>(); for (final EffectiveStatement effectiveStatement : typeEffectiveStmt.effectiveSubstatements()) { if (effectiveStatement instanceof PatternEffectiveStatementImpl) { final PatternConstraint pattern = ((PatternEffectiveStatementImpl) effectiveStatement).argument(); if (pattern != null) { patternConstraints.add(pattern); } } } return ImmutableList.copyOf(patternConstraints); } @Override public TypeDefinition getBaseType() { return baseType; } @Override public String getUnits() { return units; } @Override public Object getDefaultValue() { return defaultValue; } @Override public List getUnknownSchemaNodes() { return Collections.emptyList(); } public List getRangeConstraints() { return ranges; } public List getLengthConstraints() { return lengths; } public List getPatternConstraints() { return patterns; } public Integer getFractionDigits() { return fractionDigits; } @Override public TypeDefinition getTypeDefinition() { if (extendedType != null) { return extendedType; } Builder extendedTypeBuilder; if (baseType instanceof TypeDefinitionAware) { TypeDefinitionAware typeDefBaseType = (TypeDefinitionAware) baseType; extendedTypeBuilder = ExtendedType.builder(getQName(), typeDefBaseType.getTypeDefinition(), Optional.fromNullable(getDescription()), Optional.fromNullable(getReference()), getPath()); } else { extendedTypeBuilder = ExtendedType.builder(getQName(), baseType, Optional.fromNullable(getDescription()), Optional.fromNullable(getReference()), getPath()); } extendedTypeBuilder.defaultValue(defaultValue); extendedTypeBuilder.units(units); extendedTypeBuilder.fractionDigits(fractionDigits); extendedTypeBuilder.ranges(ranges); extendedTypeBuilder.lengths(lengths); extendedTypeBuilder.patterns(patterns); extendedType = extendedTypeBuilder.build(); return extendedType; } }