/* * 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 java.util.Collection; import java.util.Objects; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.CopyableNode; 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.model.api.stmt.SchemaTreeEffectiveStatement; import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace; import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractQNameStatementSupport; import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory; import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType; import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current; 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; /** * Specialization of {@link AbstractQNameStatementSupport} for {@link SchemaTreeEffectiveStatement} implementations. * Every statement automatically participates in {@link SchemaTreeNamespace}. * * @param Declared Statement representation * @param Effective Statement representation */ public abstract class BaseSchemaTreeStatementSupport, E extends SchemaTreeEffectiveStatement> extends AbstractQNameStatementSupport { private static class SchemaTreeEquality> implements StatementEquality { private static final class Instantiated> extends SchemaTreeEquality { @Override public boolean canReuseCurrent(final Current copy, final Current current, final Collection> substatements) { return copy.effectiveConfig() == current.effectiveConfig() && super.canReuseCurrent(copy, current, substatements) // This weird quirk is needed for ... something somewhere && Objects.equals(copy.original(), current.original()); } } @Override public boolean canReuseCurrent(final Current copy, final Current current, final Collection> substatements) { return equalHistory(copy, current) // FIXME: this should devolve to getArgument() equality && copy.getSchemaPath().equals(current.getSchemaPath()); } // TODO: can we speed this up? private static boolean equalHistory(final Current copy, final Current current) { return isAugmenting(copy) == isAugmenting(current) && isAddedByUses(copy) == isAddedByUses(current); } private static boolean isAugmenting(final Current stmt) { final CopyHistory history = stmt.history(); return history.contains(CopyType.ADDED_BY_AUGMENTATION) || history.contains(CopyType.ADDED_BY_USES_AUGMENTATION); } private static boolean isAddedByUses(final Current stmt) { final CopyHistory history = stmt.history(); return history.contains(CopyType.ADDED_BY_USES) || history.contains(CopyType.ADDED_BY_USES_AUGMENTATION); } } private static final StatementPolicy INSTANTIATED_POLICY = StatementPolicy.copyDeclared(new SchemaTreeEquality.Instantiated<>()); private static final StatementPolicy UNINSTANTIATED_POLICY = StatementPolicy.copyDeclared(new SchemaTreeEquality<>()); protected BaseSchemaTreeStatementSupport(final StatementDefinition publicDefinition, final StatementPolicy policy) { super(publicDefinition, policy); } /** * Return the {@link StatementPolicy} corresponding to a potentially-instantiated YANG statement. Statements are * reused as long as: *
    *
  • {@link Current#schemaPath()} does not change
  • *
  • {@link Current#argument()} does not change
  • *
  • {@link Current#history()} does not change as far as {@link CopyableNode} is concerned
  • *
  • {@link Current#effectiveConfig()} does not change
  • *
  • {@link Current#original()} does not change
  • *
* *

* Typical users include {@code container} and {@code leaf}. * * @param Declared Statement representation * @return A StatementPolicy */ @SuppressWarnings("unchecked") public static final > StatementPolicy instantiatedPolicy() { return (StatementPolicy) INSTANTIATED_POLICY; } /** * Return the {@link StatementPolicy} corresponding to an uninstantiated YANG statement. Statements are * reused as long as: *

    *
  • {@link Current#schemaPath()} does not change
  • *
  • {@link Current#argument()} does not change
  • *
  • {@link Current#history()} does not change as far as {@link CopyableNode} is concerned
  • *
* *

* Typical users include {@code action} and {@code notification} (in its YANG 1.1 form). * * @param Declared Statement representation * @return A StatementPolicy */ @SuppressWarnings("unchecked") public static final > StatementPolicy uninstantiatedPolicy() { return (StatementPolicy) UNINSTANTIATED_POLICY; } /** * {@inheritDoc} * *

* This method ensures the statement is added to its parent {@link SchemaTreeNamespace}. */ @Override public void onStatementAdded(final Mutable stmt) { stmt.coerceParentContext().addToNs(SchemaTreeNamespace.class, stmt.getArgument(), stmt); } // Non-final because {@code input} and {@code output} are doing their own thing. @Override public QName parseArgumentValue(final StmtContext ctx, final String value) { return StmtContextUtils.parseIdentifier(ctx, value); } }