Un-deprecate CopyableNode, AddedByUsesAware
[yangtools.git] / yang / yang-parser-spi / src / main / java / org / opendaylight / yangtools / yang / parser / spi / meta / AbstractSchemaTreeStatementSupport.java
1 /*
2  * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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 package org.opendaylight.yangtools.yang.parser.spi.meta;
9
10 import com.google.common.annotations.Beta;
11 import java.util.Collection;
12 import java.util.Objects;
13 import org.opendaylight.yangtools.yang.common.QName;
14 import org.opendaylight.yangtools.yang.model.api.CopyableNode;
15 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
16 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
17 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
18 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
19 import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
22
23 /**
24  * Specialization of {@link AbstractQNameStatementSupport} for {@link SchemaTreeEffectiveStatement} implementations.
25  * Every statement automatically participates in {@link SchemaTreeNamespace}.
26  *
27  * @param <D> Declared Statement representation
28  * @param <E> Effective Statement representation
29  */
30 @Beta
31 public abstract class AbstractSchemaTreeStatementSupport<D extends DeclaredStatement<QName>,
32         E extends SchemaTreeEffectiveStatement<D>> extends AbstractQNameStatementSupport<D, E> {
33     private static class SchemaTreeEquality<D extends DeclaredStatement<QName>>
34             implements StatementEquality<QName, D> {
35         private static final class Instantiated<D extends DeclaredStatement<QName>> extends SchemaTreeEquality<D> {
36             @Override
37             public boolean canReuseCurrent(final Current<QName, D> copy, final Current<QName, D> current,
38                     final Collection<? extends EffectiveStatement<?, ?>> substatements) {
39                 return copy.effectiveConfig() == current.effectiveConfig()
40                     && super.canReuseCurrent(copy, current, substatements)
41                     // This weird quirk is needed for ... something somewhere
42                     && Objects.equals(copy.original(), current.original());
43             }
44         }
45
46         @Override
47         public boolean canReuseCurrent(final Current<QName, D> copy, final Current<QName, D> current,
48                 final Collection<? extends EffectiveStatement<?, ?>> substatements) {
49             return equalHistory(copy.history(), current.history())
50                 && copy.getArgument().equals(current.getArgument())
51                 // FIXME: 8.0.0: eliminate this call
52                 && copy.equalParentPath(current);
53         }
54
55         private static boolean equalHistory(final CopyHistory copy, final CopyHistory current) {
56             return copy.isAugmenting() == current.isAugmenting() && copy.isAddedByUses() == current.isAddedByUses();
57         }
58     }
59
60     private static final StatementPolicy<QName, ?> INSTANTIATED_POLICY =
61         StatementPolicy.copyDeclared(new SchemaTreeEquality.Instantiated<>());
62     private static final StatementPolicy<QName, ?> UNINSTANTIATED_POLICY =
63         StatementPolicy.copyDeclared(new SchemaTreeEquality<>());
64
65     protected AbstractSchemaTreeStatementSupport(final StatementDefinition publicDefinition,
66             final StatementPolicy<QName, D> policy) {
67         super(publicDefinition, policy);
68     }
69
70     /**
71      * Return the {@link StatementPolicy} corresponding to a potentially-instantiated YANG statement. Statements are
72      * reused as long as:
73      * <ul>
74      *   <li>{@link Current#schemaPath()} does not change</li>
75      *   <li>{@link Current#argument()} does not change</li>
76      *   <li>{@link Current#history()} does not change as far as {@link CopyableNode} is concerned</li>
77      *   <li>{@link Current#effectiveConfig()} does not change</li>
78      *   <li>{@link Current#original()} does not change</li>
79      * </ul>
80      *
81      * <p>
82      * Typical users include {@code container} and {@code leaf}.
83      *
84      * @param <D> Declared Statement representation
85      * @return A StatementPolicy
86      */
87     @SuppressWarnings("unchecked")
88     public static final <D extends DeclaredStatement<QName>> StatementPolicy<QName, D> instantiatedPolicy() {
89         return (StatementPolicy<QName, D>) INSTANTIATED_POLICY;
90     }
91
92     /**
93      * Return the {@link StatementPolicy} corresponding to an uninstantiated YANG statement. Statements are
94      * reused as long as:
95      * <ul>
96      *   <li>{@link Current#schemaPath()} does not change</li>
97      *   <li>{@link Current#argument()} does not change</li>
98      *   <li>{@link Current#history()} does not change as far as {@link CopyableNode} is concerned</li>
99      * </ul>
100      *
101      * <p>
102      * Typical users include {@code action} and {@code notification} (in its YANG 1.1 form).
103      *
104      * @param <D> Declared Statement representation
105      * @return A StatementPolicy
106      */
107     @SuppressWarnings("unchecked")
108     public static final <D extends DeclaredStatement<QName>> StatementPolicy<QName, D> uninstantiatedPolicy() {
109         return (StatementPolicy<QName, D>) UNINSTANTIATED_POLICY;
110     }
111
112     /**
113      * {@inheritDoc}
114      *
115      * <p>
116      * This method ensures the statement is added to its parent {@link SchemaTreeNamespace}.
117      */
118     @Override
119     public void onStatementAdded(final Mutable<QName, D, E> stmt) {
120         stmt.coerceParentContext().addToNs(SchemaTreeNamespace.class, stmt.getArgument(), stmt);
121     }
122
123     // Non-final because {@code input} and {@code output} are doing their own thing.
124     @Override
125     public QName parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
126         return StmtContextUtils.parseIdentifier(ctx, value);
127     }
128 }