--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.collect.ImmutableList;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractQNameStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+
+/**
+ * Specialization of {@link BaseStatementSupport} for QName statement arguments.
+ *
+ * @param <D> Declared Statement representation
+ * @param <E> Effective Statement representation
+ */
+@Beta
+public abstract class BaseQNameStatementSupport<D extends DeclaredStatement<QName>,
+ E extends EffectiveStatement<QName, D>> extends AbstractQNameStatementSupport<D, E> {
+ protected BaseQNameStatementSupport(final StatementDefinition publicDefinition) {
+ super(publicDefinition);
+ }
+
+ @Override
+ public final E createEffective(final StmtContext<QName, D, E> ctx) {
+ final D declared = BaseStatementSupport.buildDeclared(ctx);
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements =
+ BaseStatementSupport.buildEffectiveSubstatements(ctx);
+ return substatements.isEmpty() ? createEmptyEffective(ctx, declared)
+ : createEffective(ctx, declared, substatements);
+ }
+
+ protected abstract @NonNull E createEffective(@NonNull StmtContext<QName, D, E> ctx, @NonNull D declared,
+ @NonNull ImmutableList<? extends EffectiveStatement<?, ?>> substatements);
+
+ protected abstract @NonNull E createEmptyEffective(@NonNull StmtContext<QName, D, E> ctx, @NonNull D declared);
+
+ protected static final <E extends EffectiveStatement<?, ?>> @Nullable E findFirstStatement(
+ final ImmutableList<? extends EffectiveStatement<?, ?>> statements, final Class<E> type) {
+ return BaseStatementSupport.findFirstStatement(statements, type);
+ }
+
+ protected static final <A, E extends EffectiveStatement<A, ?>> A findFirstArgument(
+ final ImmutableList<? extends EffectiveStatement<?, ?>> statements, final Class<E> type, final A defValue) {
+ return BaseStatementSupport.findFirstArgument(statements, type, defValue);
+ }
+}
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
protected abstract @NonNull E createEmptyEffective(@NonNull StmtContext<A, D, E> ctx, @NonNull D declared);
+ protected static final <E extends EffectiveStatement<?, ?>> @Nullable E findFirstStatement(
+ final ImmutableList<? extends EffectiveStatement<?, ?>> statements, final Class<E> type) {
+ for (EffectiveStatement<?, ?> stmt : statements) {
+ if (type.isInstance(stmt)) {
+ return type.cast(stmt);
+ }
+ }
+ return null;
+ }
+
+ protected static final <A, E extends EffectiveStatement<A, ?>> A findFirstArgument(
+ final ImmutableList<? extends EffectiveStatement<?, ?>> statements, final Class<E> type, final A defValue) {
+ final @Nullable E stmt = findFirstStatement(statements, type);
+ return stmt != null ? stmt.argument() : defValue;
+ }
+
static final <A, D extends DeclaredStatement<A>> @NonNull D buildDeclared(final StmtContext<A, D, ?> ctx) {
/*
* Share original instance of declared statement between all effective
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.concepts.Mutable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware;
+import org.opendaylight.yangtools.yang.model.api.CopyableNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
+import org.opendaylight.yangtools.yang.model.api.MandatoryAware;
+import org.opendaylight.yangtools.yang.model.api.MustConstraintAware;
+import org.opendaylight.yangtools.yang.model.api.MustDefinition;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.WhenConditionAware;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.WhenEffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
+
+/**
+ * Mix-in interfaces providing services required by SchemaNode et al. These interfaces provide implementations, or
+ * implementation helpers based on default methods, so the correct behavior can be logically centralized.
+ */
+@Beta
+public final class EffectiveStatementMixins {
+ // Marker interface requiring all mixins to be derived from EffectiveStatement.
+ private interface Mixin<A, D extends DeclaredStatement<A>> extends EffectiveStatement<A, D> {
+ @SuppressWarnings("unchecked")
+ default <T> Collection<T> filterEffectiveStatements(final Class<T> type) {
+ // Yeah, this is not nice, but saves one transformation
+ return (Collection<T>) Collections2.filter(effectiveSubstatements(), type::isInstance);
+ }
+
+ default <T> List<T> filterEffectiveStatementsList(final Class<T> type) {
+ return effectiveSubstatements().stream().filter(type::isInstance).map(type::cast)
+ .collect(ImmutableList.toImmutableList());
+ }
+ }
+
+ /**
+ * Bridge between {@link EffectiveStatementWithFlags} and {@link AddedByUsesAware}.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface AddedByUsesMixin<A, D extends DeclaredStatement<A>>
+ extends EffectiveStatementWithFlags<A, D>, AddedByUsesAware {
+ @Override
+ default boolean isAddedByUses() {
+ return (flags() & FlagsBuilder.ADDED_BY_USES) != 0;
+ }
+ }
+
+ /**
+ * Bridge between {@link EffectiveStatementWithFlags} and {@link MustConstraintAware}.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface MustConstraintMixin<A, D extends DeclaredStatement<A>> extends Mixin<A, D>, MustConstraintAware {
+ @Override
+ default Collection<MustDefinition> getMustConstraints() {
+ return filterEffectiveStatements(MustDefinition.class);
+ }
+ }
+
+ /**
+ * Bridge between {@link EffectiveStatementWithFlags} and {@link CopyableNode}.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface CopyableMixin<A, D extends DeclaredStatement<A>> extends AddedByUsesMixin<A, D>, CopyableNode {
+ @Override
+ default boolean isAugmenting() {
+ return (flags() & FlagsBuilder.AUGMENTING) != 0;
+ }
+ }
+
+ /**
+ * Bridge between {@link EffectiveStatementWithFlags} and {@link DataSchemaNode}.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface DataSchemaNodeMixin<A, D extends DeclaredStatement<A>>
+ extends DataSchemaNode, CopyableMixin<A, D>, SchemaNodeMixin<A, D>, WhenConditionMixin<A, D> {
+ @Override
+ default boolean isConfiguration() {
+ return (flags() & FlagsBuilder.CONFIGURATION) != 0;
+ }
+ }
+
+ /**
+ * Bridge between {@link EffectiveStatementWithFlags} and {@link DocumentedNode}.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface DocumentedNodeMixin<A, D extends DeclaredStatement<A>> extends Mixin<A, D>, DocumentedNode {
+ /**
+ * Bridge between {@link EffectiveStatementWithFlags} and
+ * {@link org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus}.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ interface WithStatus<A, D extends DeclaredStatement<A>>
+ extends EffectiveStatementWithFlags<A, D>, DocumentedNodeMixin<A, D>, DocumentedNode.WithStatus {
+ @Override
+ default Status getStatus() {
+ final int status = flags() & FlagsBuilder.MASK_STATUS;
+ switch (status) {
+ case FlagsBuilder.STATUS_CURRENT:
+ return Status.CURRENT;
+ case FlagsBuilder.STATUS_DEPRECATED:
+ return Status.DEPRECATED;
+ case FlagsBuilder.STATUS_OBSOLETE:
+ return Status.OBSOLETE;
+ default:
+ throw new IllegalStateException("Illegal status " + status);
+ }
+ }
+ }
+
+ @Override
+ default Optional<String> getDescription() {
+ return findFirstEffectiveSubstatementArgument(DescriptionEffectiveStatement.class);
+ }
+
+ @Override
+ default Optional<String> getReference() {
+ return findFirstEffectiveSubstatementArgument(ReferenceEffectiveStatement.class);
+ }
+
+ @Override
+ default List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return filterEffectiveStatementsList(UnknownSchemaNode.class);
+ }
+ }
+
+ /**
+ * Bridge between {@link EffectiveStatementWithFlags} and {@link MandatoryAware}.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface MandatoryMixin<A, D extends DeclaredStatement<A>>
+ extends EffectiveStatementWithFlags<A, D>, MandatoryAware {
+ @Override
+ default boolean isMandatory() {
+ return (flags() & FlagsBuilder.MANDATORY) != 0;
+ }
+ }
+
+ /**
+ * Bridge between {@link EffectiveStatementWithFlags} and {@link SchemaNode}.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface SchemaNodeMixin<A, D extends DeclaredStatement<A>>
+ extends DocumentedNodeMixin.WithStatus<A, D>, SchemaNode {
+ @Override
+ default QName getQName() {
+ return getPath().getLastComponent();
+ }
+ }
+
+ /**
+ * Bridge between {@link EffectiveStatementWithFlags} and {@code ordered-by} statement.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface UserOrderedMixin<A, D extends DeclaredStatement<A>> extends EffectiveStatementWithFlags<A, D> {
+ default boolean userOrdered() {
+ return (flags() & FlagsBuilder.USER_ORDERED) != 0;
+ }
+ }
+
+ /**
+ * Helper used to locate the effective {@code when} statement and exposing its argument as per
+ * {@link WhenConditionAware}.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface WhenConditionMixin<A, D extends DeclaredStatement<A>> extends Mixin<A, D>, WhenConditionAware {
+ @Override
+ default Optional<RevisionAwareXPath> getWhenCondition() {
+ return findFirstEffectiveSubstatementArgument(WhenEffectiveStatement.class);
+ }
+ }
+
+ /**
+ * Support interface for various mixins. Implementations are required to store 32bits worth of flags, which are
+ * globally assigned to sub-interfaces -- thus providing storage for many low-cardinality properties.
+ *
+ * @param <A> Argument type ({@link Void} if statement does not have argument.)
+ * @param <D> Class representing declared version of this statement.
+ */
+ public interface EffectiveStatementWithFlags<A, D extends DeclaredStatement<A>> extends Mixin<A, D> {
+ /**
+ * Return flags assicated with this statements. Flags can be built using {@link FlagsBuilder}.
+ *
+ * @return Flag field value (32 bits).
+ */
+ int flags();
+
+ @NonNullByDefault
+ final class FlagsBuilder implements Mutable {
+ // We still have 25 flags remaining
+ static final int STATUS_CURRENT = 0x0001;
+ static final int STATUS_DEPRECATED = 0x0002;
+ static final int STATUS_OBSOLETE = 0x0003;
+ static final int MASK_STATUS = 0x0003;
+
+ static final int CONFIGURATION = 0x0004;
+ static final int MANDATORY = 0x0008;
+
+ static final int AUGMENTING = 0x0010;
+ static final int ADDED_BY_USES = 0x0020;
+ private static final int MASK_HISTORY = 0x0030;
+
+ static final int USER_ORDERED = 0x0040;
+
+ private int flags;
+
+ public FlagsBuilder setConfiguration(final boolean config) {
+ if (config) {
+ flags |= CONFIGURATION;
+ } else {
+ flags &= ~CONFIGURATION;
+ }
+ return this;
+ }
+
+ public FlagsBuilder setHistory(final CopyHistory history) {
+ int bits;
+ if (history.contains(CopyType.ADDED_BY_USES_AUGMENTATION)) {
+ bits = AUGMENTING | ADDED_BY_USES;
+ } else {
+ bits = 0;
+ if (history.contains(CopyType.ADDED_BY_AUGMENTATION)) {
+ bits |= AUGMENTING;
+ }
+ if (history.contains(CopyType.ADDED_BY_USES)) {
+ bits |= ADDED_BY_USES;
+ }
+ }
+
+ flags = flags & ~MASK_HISTORY | bits;
+ return this;
+ }
+
+ public FlagsBuilder setMandatory(final boolean mandatory) {
+ if (mandatory) {
+ flags |= MANDATORY;
+ } else {
+ flags &= ~MANDATORY;
+ }
+ return this;
+ }
+
+ public FlagsBuilder setStatus(final Status status) {
+ final int bits;
+ switch (status) {
+ case CURRENT:
+ bits = STATUS_CURRENT;
+ break;
+ case DEPRECATED:
+ bits = STATUS_DEPRECATED;
+ break;
+ case OBSOLETE:
+ bits = STATUS_DEPRECATED;
+ break;
+ default:
+ throw new IllegalStateException("Unhandled status " + status);
+ }
+
+ flags = flags & ~MASK_STATUS | bits;
+ return this;
+ }
+
+ public FlagsBuilder setUserOrdered(final boolean userOrdered) {
+ if (userOrdered) {
+ flags |= USER_ORDERED;
+ } else {
+ flags &= ~USER_ORDERED;
+ }
+ return this;
+ }
+
+ public int toFlags() {
+ return flags;
+ }
+ }
+ }
+}
import com.google.common.annotations.Beta;
import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
}
public static Optional<ElementCountConstraint> createElementCountConstraint(final EffectiveStatement<?, ?> stmt) {
+ return createElementCountConstraint(
+ stmt.findFirstEffectiveSubstatementArgument(MinElementsEffectiveStatement.class).orElse(null),
+ stmt.findFirstEffectiveSubstatementArgument(MaxElementsEffectiveStatement.class).orElse(null));
+ }
+
+ public static Optional<ElementCountConstraint> createElementCountConstraint(
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ return createElementCountConstraint(
+ BaseQNameStatementSupport.findFirstArgument(substatements, MinElementsEffectiveStatement.class, null),
+ BaseQNameStatementSupport.findFirstArgument(substatements, MaxElementsEffectiveStatement.class, null));
+ }
+
+ private static Optional<ElementCountConstraint> createElementCountConstraint(
+ final @Nullable Integer min, final @Nullable String max) {
final Integer minElements;
- final Optional<Integer> min = stmt.findFirstEffectiveSubstatementArgument(MinElementsEffectiveStatement.class);
- if (min.isPresent()) {
- final Integer m = min.get();
- minElements = m > 0 ? m : null;
+ if (min != null) {
+ minElements = min > 0 ? min : null;
} else {
minElements = null;
}
final Integer maxElements;
- final String max = stmt.findFirstEffectiveSubstatementArgument(MaxElementsEffectiveStatement.class)
- .orElse(UNBOUNDED_STR);
- if (!UNBOUNDED_STR.equals(max)) {
+ if (max != null && !UNBOUNDED_STR.equals(max)) {
final Integer m = Integer.valueOf(max);
maxElements = m < Integer.MAX_VALUE ? m : null;
} else {
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
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.leaf;
+
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnitsEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypeBuilder;
+import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypes;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredEffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.DataSchemaNodeMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.MandatoryMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.MustConstraintMixin;
+
+abstract class AbstractLeafEffectiveStatement extends AbstractDeclaredEffectiveStatement.Default<QName, LeafStatement>
+ implements LeafEffectiveStatement, LeafSchemaNode, DerivableSchemaNode,
+ DataSchemaNodeMixin<QName, LeafStatement>, MandatoryMixin<QName, LeafStatement>,
+ MustConstraintMixin<QName, LeafStatement> {
+ // Variable: either a single substatement or an ImmutableList
+ private final @NonNull Object substatements;
+ private final @NonNull SchemaPath path;
+ private final @NonNull TypeDefinition<?> type;
+ private final int flags;
+
+ AbstractLeafEffectiveStatement(final LeafStatement declared, final SchemaPath path, final int flags,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ super(declared);
+ this.substatements = substatements.size() == 1 ? substatements.get(0) : substatements;
+ this.path = requireNonNull(path);
+ this.flags = flags;
+ // TODO: lazy instantiation?
+ this.type = buildType();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final ImmutableList<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+ if (substatements instanceof ImmutableList) {
+ return (ImmutableList<? extends EffectiveStatement<?, ?>>) substatements;
+ }
+ verify(substatements instanceof EffectiveStatement, "Unexpected substatement %s", substatements);
+ return ImmutableList.of((EffectiveStatement<?, ?>) substatements);
+ }
+
+ @Override
+ public final int flags() {
+ return flags;
+ }
+
+ @Override
+ public final @NonNull QName argument() {
+ return getQName();
+ }
+
+ @Override
+ public final @NonNull SchemaPath getPath() {
+ return path;
+ }
+
+ @Override
+ public final TypeDefinition<?> getType() {
+ return type;
+ }
+
+ private TypeDefinition<?> buildType() {
+ final TypeEffectiveStatement<?> typeStmt = findFirstEffectiveSubstatement(TypeEffectiveStatement.class).get();
+ final ConcreteTypeBuilder<?> builder = ConcreteTypes.concreteTypeBuilder(typeStmt.getTypeDefinition(),
+ getPath());
+ for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
+ if (stmt instanceof DefaultEffectiveStatement) {
+ builder.setDefaultValue(((DefaultEffectiveStatement)stmt).argument());
+ } else if (stmt instanceof DescriptionEffectiveStatement) {
+ builder.setDescription(((DescriptionEffectiveStatement)stmt).argument());
+ } else if (stmt instanceof ReferenceEffectiveStatement) {
+ builder.setReference(((ReferenceEffectiveStatement)stmt).argument());
+ } else if (stmt instanceof StatusEffectiveStatement) {
+ builder.setStatus(((StatusEffectiveStatement)stmt).argument());
+ } else if (stmt instanceof UnitsEffectiveStatement) {
+ builder.setUnits(((UnitsEffectiveStatement)stmt).argument());
+ }
+ }
+ return builder.build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.leaf;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Optional;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
+
+final class EmptyLeafEffectiveStatement extends AbstractLeafEffectiveStatement {
+ EmptyLeafEffectiveStatement(final LeafStatement declared, final SchemaPath path, final int flags,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ super(declared, path, flags, substatements);
+ }
+
+ @Override
+ public Optional<LeafSchemaNode> getOriginal() {
+ return Optional.empty();
+ }
+}
+++ /dev/null
-/*
- * 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.leaf;
-
-import java.util.Objects;
-import java.util.Optional;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.UnitsEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypeBuilder;
-import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypes;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractEffectiveMustConstraintAwareDataSchemaNode;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStmtUtils;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-
-final class LeafEffectiveStatementImpl extends AbstractEffectiveMustConstraintAwareDataSchemaNode<LeafStatement>
- implements LeafEffectiveStatement, LeafSchemaNode, DerivableSchemaNode {
- private final LeafSchemaNode original;
- private final TypeDefinition<?> type;
- private final String defaultStr;
- private final String unitsStr;
- private final boolean mandatory;
-
- LeafEffectiveStatementImpl(final StmtContext<QName, LeafStatement, EffectiveStatement<QName, LeafStatement>> ctx) {
- super(ctx);
- this.original = (LeafSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective).orElse(null);
-
- final TypeEffectiveStatement<?> typeStmt = SourceException.throwIfNull(
- firstSubstatementOfType(TypeEffectiveStatement.class), ctx.getStatementSourceReference(),
- "Leaf is missing a 'type' statement");
-
- String dflt = null;
- String units = null;
- final ConcreteTypeBuilder<?> builder = ConcreteTypes.concreteTypeBuilder(typeStmt.getTypeDefinition(),
- ctx.getSchemaPath().get());
- for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
- if (stmt instanceof DefaultEffectiveStatement) {
- dflt = ((DefaultEffectiveStatement)stmt).argument();
- builder.setDefaultValue(stmt.argument());
- } else if (stmt instanceof DescriptionEffectiveStatement) {
- builder.setDescription(((DescriptionEffectiveStatement)stmt).argument());
- } else if (stmt instanceof ReferenceEffectiveStatement) {
- builder.setReference(((ReferenceEffectiveStatement)stmt).argument());
- } else if (stmt instanceof StatusEffectiveStatement) {
- builder.setStatus(((StatusEffectiveStatement)stmt).argument());
- } else if (stmt instanceof UnitsEffectiveStatement) {
- units = ((UnitsEffectiveStatement)stmt).argument();
- builder.setUnits(units);
- }
- }
-
- SourceException.throwIf(
- EffectiveStmtUtils.hasDefaultValueMarkedWithIfFeature(ctx.getRootVersion(), typeStmt, dflt),
- ctx.getStatementSourceReference(),
- "Leaf '%s' has default value '%s' marked with an if-feature statement.", ctx.getStatementArgument(), dflt);
-
- defaultStr = dflt;
- unitsStr = units;
- type = builder.build();
- mandatory = findFirstEffectiveSubstatementArgument(MandatoryEffectiveStatement.class).orElse(Boolean.FALSE)
- .booleanValue();
- }
-
- @Override
- public boolean isMandatory() {
- return mandatory;
- }
-
- @Override
- public Optional<LeafSchemaNode> getOriginal() {
- return Optional.ofNullable(original);
- }
-
- @Override
- public TypeDefinition<?> getType() {
- return type;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + Objects.hashCode(getQName());
- result = prime * result + Objects.hashCode(getPath());
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof LeafEffectiveStatementImpl)) {
- return false;
- }
- final LeafEffectiveStatementImpl other = (LeafEffectiveStatementImpl) obj;
- return Objects.equals(getQName(), other.getQName()) && Objects.equals(getPath(), other.getPath());
- }
-
- @Override
- public String toString() {
- return LeafEffectiveStatementImpl.class.getSimpleName() + "["
- + "qname=" + getQName()
- + ", path=" + getPath()
- + "]";
- }
-}
*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.leaf;
+import com.google.common.collect.ImmutableList;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
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.DefaultEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
-import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractQNameStatementSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseQNameStatementSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.EffectiveStatementWithFlags.FlagsBuilder;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStmtUtils;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-public final class LeafStatementSupport
- extends AbstractQNameStatementSupport<LeafStatement, EffectiveStatement<QName, LeafStatement>> {
+public final class LeafStatementSupport extends BaseQNameStatementSupport<LeafStatement, LeafEffectiveStatement> {
private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping
.LEAF)
.addOptional(YangStmtMapping.CONFIG)
}
@Override
- public void onStatementAdded(final Mutable<QName, LeafStatement, EffectiveStatement<QName, LeafStatement>> stmt) {
+ public void onStatementAdded(final Mutable<QName, LeafStatement, LeafEffectiveStatement> stmt) {
stmt.coerceParentContext().addToNs(ChildSchemaNodeNamespace.class, stmt.coerceStatementArgument(), stmt);
}
@Override
- public void onFullDefinitionDeclared(
- final Mutable<QName, LeafStatement, EffectiveStatement<QName, LeafStatement>> ctx) {
+ public void onFullDefinitionDeclared(final Mutable<QName, LeafStatement, LeafEffectiveStatement> ctx) {
super.onFullDefinitionDeclared(ctx);
StmtContextUtils.validateIfFeatureAndWhenOnListKeys(ctx);
}
}
@Override
- public EffectiveStatement<QName, LeafStatement> createEffective(
- final StmtContext<QName, LeafStatement, EffectiveStatement<QName, LeafStatement>> ctx) {
- return new LeafEffectiveStatementImpl(ctx);
+ protected SubstatementValidator getSubstatementValidator() {
+ return SUBSTATEMENT_VALIDATOR;
}
@Override
- protected SubstatementValidator getSubstatementValidator() {
- return SUBSTATEMENT_VALIDATOR;
+ protected LeafEffectiveStatement createEffective(
+ final StmtContext<QName, LeafStatement, LeafEffectiveStatement> ctx, final LeafStatement declared,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ final TypeEffectiveStatement<?> typeStmt = SourceException.throwIfNull(
+ findFirstStatement(substatements, TypeEffectiveStatement.class), ctx.getStatementSourceReference(),
+ "Leaf is missing a 'type' statement");
+ final String dflt = findFirstArgument(substatements, DefaultEffectiveStatement.class, null);
+ SourceException.throwIf(
+ EffectiveStmtUtils.hasDefaultValueMarkedWithIfFeature(ctx.getRootVersion(), typeStmt, dflt),
+ ctx.getStatementSourceReference(),
+ "Leaf '%s' has default value '%s' marked with an if-feature statement.", ctx.getStatementArgument(), dflt);
+
+ final SchemaPath path = ctx.getSchemaPath().get();
+ final LeafSchemaNode original = (LeafSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective)
+ .orElse(null);
+ final int flags = new FlagsBuilder()
+ .setHistory(ctx.getCopyHistory())
+ .setStatus(findFirstArgument(substatements, StatusEffectiveStatement.class, Status.CURRENT))
+ .setConfiguration(ctx.isConfiguration())
+ .setMandatory(findFirstArgument(substatements, MandatoryEffectiveStatement.class, Boolean.FALSE))
+ .toFlags();
+
+ return original == null ? new EmptyLeafEffectiveStatement(declared, path, flags, substatements)
+ : new RegularLeafEffectiveStatement(declared, path, flags, substatements, original);
+ }
+
+ @Override
+ protected LeafEffectiveStatement createEmptyEffective(
+ final StmtContext<QName, LeafStatement, LeafEffectiveStatement> ctx, final LeafStatement declared) {
+ throw new UnsupportedOperationException("Leaf statements must have at least one substatement");
}
-}
\ No newline at end of file
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.leaf;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
+
+final class RegularLeafEffectiveStatement extends AbstractLeafEffectiveStatement {
+ private final @Nullable LeafSchemaNode original;
+
+ RegularLeafEffectiveStatement(final LeafStatement declared, final SchemaPath path, final int flags,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements, final LeafSchemaNode original) {
+ super(declared, path, flags, substatements);
+ this.original = original;
+ }
+
+ @Override
+ public Optional<LeafSchemaNode> getOriginal() {
+ return Optional.ofNullable(original);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.leaf_list;
+
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Objects;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnitsEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypeBuilder;
+import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypes;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredEffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.DataSchemaNodeMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.MustConstraintMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.UserOrderedMixin;
+
+abstract class AbstractLeafListEffectiveStatement
+ extends AbstractDeclaredEffectiveStatement.Default<QName, LeafListStatement>
+ implements LeafListEffectiveStatement, LeafListSchemaNode, DerivableSchemaNode,
+ UserOrderedMixin<QName, LeafListStatement>, DataSchemaNodeMixin<QName, LeafListStatement>,
+ MustConstraintMixin<QName, LeafListStatement> {
+ // Variable: either a single substatement or an ImmutableList
+ private final @NonNull Object substatements;
+ private final @NonNull SchemaPath path;
+ private final @NonNull TypeDefinition<?> type;
+ private final int flags;
+
+ AbstractLeafListEffectiveStatement(final LeafListStatement declared, final SchemaPath path, final int flags,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ super(declared);
+ this.substatements = substatements.size() == 1 ? substatements.get(0) : substatements;
+ this.path = requireNonNull(path);
+ this.flags = flags;
+ // TODO: lazy instantiation?
+ this.type = buildType();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final ImmutableList<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+ if (substatements instanceof ImmutableList) {
+ return (ImmutableList<? extends EffectiveStatement<?, ?>>) substatements;
+ }
+ verify(substatements instanceof EffectiveStatement, "Unexpected substatement %s", substatements);
+ return ImmutableList.of((EffectiveStatement<?, ?>) substatements);
+ }
+
+ @Override
+ public final int flags() {
+ return flags;
+ }
+
+ @Override
+ public final @NonNull QName argument() {
+ return getQName();
+ }
+
+ @Override
+ public final @NonNull SchemaPath getPath() {
+ return path;
+ }
+
+ @Override
+ public final TypeDefinition<?> getType() {
+ return type;
+ }
+
+ @Override
+ public final boolean isUserOrdered() {
+ return userOrdered();
+ }
+
+ @Override
+ public final int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Objects.hashCode(getQName());
+ result = prime * result + Objects.hashCode(getPath());
+ return result;
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof AbstractLeafListEffectiveStatement)) {
+ return false;
+ }
+ final AbstractLeafListEffectiveStatement other = (AbstractLeafListEffectiveStatement) obj;
+ return Objects.equals(getQName(), other.getQName()) && Objects.equals(getPath(), other.getPath());
+ }
+
+ @Override
+ public final String toString() {
+ return getClass().getSimpleName() + "[" + getQName() + "]";
+ }
+
+ private TypeDefinition<?> buildType() {
+ final TypeEffectiveStatement<?> typeStmt = findFirstEffectiveSubstatement(TypeEffectiveStatement.class).get();
+ final ConcreteTypeBuilder<?> builder = ConcreteTypes.concreteTypeBuilder(typeStmt.getTypeDefinition(),
+ getPath());
+ for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
+ // NOTE: 'default' is ommitted here on purpose
+ if (stmt instanceof DescriptionEffectiveStatement) {
+ builder.setDescription(((DescriptionEffectiveStatement)stmt).argument());
+ } else if (stmt instanceof ReferenceEffectiveStatement) {
+ builder.setReference(((ReferenceEffectiveStatement)stmt).argument());
+ } else if (stmt instanceof StatusEffectiveStatement) {
+ builder.setStatus(((StatusEffectiveStatement)stmt).argument());
+ } else if (stmt instanceof UnitsEffectiveStatement) {
+ builder.setUnits(((UnitsEffectiveStatement)stmt).argument());
+ }
+ }
+ return builder.build();
+ }
+}
*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.leaf_list;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import java.util.Optional;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
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.DefaultEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.LeafListStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OrderedByEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
-import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractQNameStatementSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseQNameStatementSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.EffectiveStatementWithFlags.FlagsBuilder;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStmtUtils;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
abstract class AbstractLeafListStatementSupport
- extends AbstractQNameStatementSupport<LeafListStatement, EffectiveStatement<QName, LeafListStatement>> {
-
+ extends BaseQNameStatementSupport<LeafListStatement, LeafListEffectiveStatement> {
AbstractLeafListStatementSupport() {
super(YangStmtMapping.LEAF_LIST);
}
@Override
- public final void onStatementAdded(
- final Mutable<QName, LeafListStatement, EffectiveStatement<QName, LeafListStatement>> stmt) {
+ public final void onStatementAdded(final Mutable<QName, LeafListStatement, LeafListEffectiveStatement> stmt) {
stmt.coerceParentContext().addToNs(ChildSchemaNodeNamespace.class, stmt.coerceStatementArgument(), stmt);
}
}
@Override
- public final EffectiveStatement<QName, LeafListStatement> createEffective(
- final StmtContext<QName, LeafListStatement, EffectiveStatement<QName, LeafListStatement>> ctx) {
- return new LeafListEffectiveStatementImpl(ctx);
+ protected final LeafListEffectiveStatement createEffective(
+ final StmtContext<QName, LeafListStatement, LeafListEffectiveStatement> ctx,
+ final LeafListStatement declared,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ final TypeEffectiveStatement<?> typeStmt = SourceException.throwIfNull(
+ findFirstStatement(substatements, TypeEffectiveStatement.class), ctx.getStatementSourceReference(),
+ "Leaf-list is missing a 'type' statement");
+
+ final SchemaPath path = ctx.getSchemaPath().get();
+ final LeafListSchemaNode original = (LeafListSchemaNode) ctx.getOriginalCtx()
+ .map(StmtContext::buildEffective).orElse(null);
+
+ final int flags = new FlagsBuilder()
+ .setHistory(ctx.getCopyHistory())
+ .setStatus(findFirstArgument(substatements, StatusEffectiveStatement.class, Status.CURRENT))
+ .setConfiguration(ctx.isConfiguration())
+ .setUserOrdered(findFirstArgument(substatements, OrderedByEffectiveStatement.class, "system")
+ .equals("user"))
+ .toFlags();
+ final ImmutableSet<String> defaultValues = substatements.stream()
+ .filter(DefaultEffectiveStatement.class::isInstance)
+ .map(DefaultEffectiveStatement.class::cast)
+ .map(DefaultEffectiveStatement::argument)
+ .collect(ImmutableSet.toImmutableSet());
+
+ // FIXME: We need to interpret the default value in terms of supplied element type
+ SourceException.throwIf(
+ EffectiveStmtUtils.hasDefaultValueMarkedWithIfFeature(ctx.getRootVersion(), typeStmt, defaultValues),
+ ctx.getStatementSourceReference(),
+ "Leaf-list '%s' has one of its default values '%s' marked with an if-feature statement.",
+ ctx.getStatementArgument(), defaultValues);
+
+ // FIXME: RFC7950 section 7.7.4: we need to check for min-elements and defaultValues conflict
+
+ final Optional<ElementCountConstraint> elementCountConstraint =
+ EffectiveStmtUtils.createElementCountConstraint(substatements);
+
+ if (defaultValues.isEmpty()) {
+ return original == null && !elementCountConstraint.isPresent()
+ ? new EmptyLeafListEffectiveStatement(declared, path, flags, substatements)
+ : new SlimLeafListEffectiveStatement(declared, path, flags, substatements, original,
+ elementCountConstraint.orElse(null));
+ }
+
+ return new RegularLeafListEffectiveStatement(declared, path, flags, substatements, original, defaultValues,
+ elementCountConstraint.orElse(null));
+ }
+
+ @Override
+ protected final LeafListEffectiveStatement createEmptyEffective(
+ final StmtContext<QName, LeafListStatement, LeafListEffectiveStatement> ctx,
+ final LeafListStatement declared) {
+ throw new UnsupportedOperationException("Leaf statements must have at least one substatement");
}
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.leaf_list;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListStatement;
+
+abstract class AbstractNonEmptyLeafListEffectiveStatement extends AbstractLeafListEffectiveStatement {
+ private final @Nullable LeafListSchemaNode original;
+ private final @Nullable ElementCountConstraint elementCountConstraint;
+
+ AbstractNonEmptyLeafListEffectiveStatement(final LeafListStatement declared, final SchemaPath path, final int flags,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements,
+ final LeafListSchemaNode original, final ElementCountConstraint elementCountConstraint) {
+ super(declared, path, flags, substatements);
+ this.original = original;
+ this.elementCountConstraint = elementCountConstraint;
+ }
+
+ @Override
+ public final Optional<LeafListSchemaNode> getOriginal() {
+ return Optional.ofNullable(original);
+ }
+
+ @Override
+ public final Optional<ElementCountConstraint> getElementCountConstraint() {
+ return Optional.ofNullable(elementCountConstraint);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.leaf_list;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import java.util.Collection;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListStatement;
+
+final class EmptyLeafListEffectiveStatement extends AbstractLeafListEffectiveStatement {
+ EmptyLeafListEffectiveStatement(final LeafListStatement declared, final SchemaPath path, final int flags,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ super(declared, path, flags, substatements);
+ }
+
+ @Override
+ public Optional<LeafSchemaNode> getOriginal() {
+ return Optional.empty();
+ }
+
+ @Override
+ public @NonNull Collection<? extends Object> getDefaults() {
+ return ImmutableSet.of();
+ }
+
+ @Override
+ public Optional<ElementCountConstraint> getElementCountConstraint() {
+ return Optional.empty();
+ }
+}
+++ /dev/null
-/*
- * 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.leaf_list;
-
-import com.google.common.collect.ImmutableSet;
-import java.util.Collection;
-import java.util.Objects;
-import java.util.Optional;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.LeafListStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.OrderedByEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.UnitsEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypeBuilder;
-import org.opendaylight.yangtools.yang.model.util.type.ConcreteTypes;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractEffectiveMustConstraintAwareDataSchemaNode;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStmtUtils;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-
-final class LeafListEffectiveStatementImpl extends AbstractEffectiveMustConstraintAwareDataSchemaNode<LeafListStatement>
- implements LeafListEffectiveStatement, LeafListSchemaNode, DerivableSchemaNode {
-
- private static final String ORDER_BY_USER_KEYWORD = "user";
-
- private final TypeDefinition<?> type;
- private final LeafListSchemaNode original;
- private final boolean userOrdered;
- private final @NonNull ImmutableSet<String> defaultValues;
- private final ElementCountConstraint elementCountConstraint;
-
- LeafListEffectiveStatementImpl(
- final StmtContext<QName, LeafListStatement, EffectiveStatement<QName, LeafListStatement>> ctx) {
- super(ctx);
- this.original = (LeafListSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective).orElse(null);
-
- final TypeEffectiveStatement<?> typeStmt = SourceException.throwIfNull(
- firstSubstatementOfType(TypeEffectiveStatement.class), ctx.getStatementSourceReference(),
- "Leaf-list is missing a 'type' statement");
-
- final ConcreteTypeBuilder<?> builder = ConcreteTypes.concreteTypeBuilder(typeStmt.getTypeDefinition(),
- ctx.getSchemaPath().get());
- final ImmutableSet.Builder<String> defaultValuesBuilder = ImmutableSet.builder();
- boolean isUserOrdered = false;
- for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
- if (stmt instanceof OrderedByEffectiveStatement) {
- isUserOrdered = ORDER_BY_USER_KEYWORD.equals(stmt.argument());
- }
-
- if (stmt instanceof DefaultEffectiveStatement) {
- defaultValuesBuilder.add(((DefaultEffectiveStatement) stmt).argument());
- } else if (stmt instanceof DescriptionEffectiveStatement) {
- builder.setDescription(((DescriptionEffectiveStatement)stmt).argument());
- } else if (stmt instanceof ReferenceEffectiveStatement) {
- builder.setReference(((ReferenceEffectiveStatement)stmt).argument());
- } else if (stmt instanceof StatusEffectiveStatement) {
- builder.setStatus(((StatusEffectiveStatement)stmt).argument());
- } else if (stmt instanceof UnitsEffectiveStatement) {
- builder.setUnits(((UnitsEffectiveStatement)stmt).argument());
- }
- }
-
- // FIXME: We need to interpret the default value in terms of supplied element type
- defaultValues = defaultValuesBuilder.build();
- SourceException.throwIf(
- EffectiveStmtUtils.hasDefaultValueMarkedWithIfFeature(ctx.getRootVersion(), typeStmt, defaultValues),
- ctx.getStatementSourceReference(),
- "Leaf-list '%s' has one of its default values '%s' marked with an if-feature statement.",
- ctx.getStatementArgument(), defaultValues);
-
- // FIXME: RFC7950 section 7.7.4: we need to check for min-elements and defaultValues conflict
-
- type = builder.build();
- userOrdered = isUserOrdered;
- elementCountConstraint = EffectiveStmtUtils.createElementCountConstraint(this).orElse(null);
- }
-
- @Override
- public Collection<String> getDefaults() {
- return defaultValues;
- }
-
- @Override
- public Optional<LeafListSchemaNode> getOriginal() {
- return Optional.ofNullable(original);
- }
-
- @Override
- public TypeDefinition<?> getType() {
- return type;
- }
-
- @Override
- public boolean isUserOrdered() {
- return userOrdered;
- }
-
- @Override
- public Optional<ElementCountConstraint> getElementCountConstraint() {
- return Optional.ofNullable(elementCountConstraint);
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + Objects.hashCode(getQName());
- result = prime * result + Objects.hashCode(getPath());
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final LeafListEffectiveStatementImpl other = (LeafListEffectiveStatementImpl) obj;
- return Objects.equals(getQName(), other.getQName()) && Objects.equals(getPath(), other.getPath());
- }
-
- @Override
- public String toString() {
- return LeafListEffectiveStatementImpl.class.getSimpleName() + "[" + getQName() + "]";
- }
-}
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.leaf_list;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListStatement;
+
+final class RegularLeafListEffectiveStatement extends AbstractNonEmptyLeafListEffectiveStatement {
+ private final @NonNull ImmutableSet<String> defaults;
+
+ RegularLeafListEffectiveStatement(final LeafListStatement declared, final SchemaPath path, final int flags,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements, final LeafListSchemaNode original,
+ final ImmutableSet<String> defaults, final ElementCountConstraint elementCountConstraint) {
+ super(declared, path, flags, substatements, original, elementCountConstraint);
+ this.defaults = requireNonNull(defaults);
+ }
+
+ @Override
+ public ImmutableSet<String> getDefaults() {
+ return defaults;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.leaf_list;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListStatement;
+
+final class SlimLeafListEffectiveStatement extends AbstractNonEmptyLeafListEffectiveStatement {
+ SlimLeafListEffectiveStatement(final LeafListStatement declared, final SchemaPath path, final int flags,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements,
+ final LeafListSchemaNode original, final ElementCountConstraint elementCountConstraint) {
+ super(declared, path, flags, substatements, original, elementCountConstraint);
+ }
+
+ @Override
+ public ImmutableSet<String> getDefaults() {
+ return ImmutableSet.of();
+ }
+}