Remove EffectiveStatementBase
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / AbstractEffectiveDocumentedNode.java
1 /*
2  * Copyright (c) 2019 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.rfc7950.stmt;
9
10 import com.google.common.annotations.Beta;
11 import com.google.common.collect.Collections2;
12 import com.google.common.collect.ImmutableList;
13 import java.util.Collection;
14 import java.util.Optional;
15 import java.util.function.Predicate;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
19 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
21 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
22 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
23 import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
24 import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
27
28 /**
29  * A declared {@link AbstractEffectiveStatement}.
30  *
31  * @deprecated This class has a number of design problems. Use {@link AbstractDeclaredEffectiveStatement} and its
32  *             subclasses instead.
33  */
34 // TODO: This class is problematic in that it interacts with its subclasses via methods which are guaranteed to allows
35 //       atrocities like RecursiveObjectLeaker tricks. That should be avoided and pushed to caller in a way where
36 //       this class is a pure holder taking {@code ImmutableList<? extends EffectiveStatement<?, ?>>} in the
37 //       constructor.
38 //
39 // From memory efficiency perspective, it is very common to have effective statements without any substatements,
40 // in which case 'substatements' field is redundant.
41 @Beta
42 @Deprecated(forRemoval = true)
43 // FIXME: 6.0.0: fold this into AbstractEffectiveDocumentedNodeWithStatus
44 public abstract class AbstractEffectiveDocumentedNode<A, D extends DeclaredStatement<A>>
45         extends AbstractEffectiveStatement<A, D> implements DocumentedNode {
46     private final @NonNull ImmutableList<? extends EffectiveStatement<?, ?>> substatements;
47     private final @NonNull StatementSource statementSource;
48     private final A argument;
49     private final @NonNull D declaredInstance;
50     private final @Nullable String description;
51     private final @Nullable String reference;
52
53     protected AbstractEffectiveDocumentedNode(final StmtContext<A, D, ?> ctx) {
54         argument = ctx.getStatementArgument();
55         statementSource = ctx.getStatementSource();
56         declaredInstance = ctx.buildDeclared();
57         substatements = ImmutableList.copyOf(initSubstatements(BaseStatementSupport.declaredSubstatements(ctx)));
58
59         description = findFirstEffectiveSubstatementArgument(DescriptionEffectiveStatement.class).orElse(null);
60         reference = findFirstEffectiveSubstatementArgument(ReferenceEffectiveStatement.class).orElse(null);
61     }
62
63     @Override
64     public final StatementDefinition statementDefinition() {
65         return declaredInstance.statementDefinition();
66     }
67
68     @Override
69     public A argument() {
70         return argument;
71     }
72
73     @Override
74     public final StatementSource getStatementSource() {
75         return statementSource;
76     }
77
78     @Override
79     public final D getDeclared() {
80         return declaredInstance;
81     }
82
83     @Override
84     public final Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
85         return substatements;
86     }
87
88     @Override
89     public final Optional<String> getDescription() {
90         return Optional.ofNullable(description);
91     }
92
93     @Override
94     public final Optional<String> getReference() {
95         return Optional.ofNullable(reference);
96     }
97
98     @SuppressWarnings("unchecked")
99     public final <T> Collection<T> allSubstatementsOfType(final Class<T> type) {
100         return Collection.class.cast(Collections2.filter(effectiveSubstatements(), type::isInstance));
101     }
102
103
104     protected final @Nullable String nullableDescription() {
105         return description;
106     }
107
108     protected final @Nullable String nullableReference() {
109         return reference;
110     }
111
112     /**
113      * Create a set of substatements. This method is split out so it can be overridden in
114      * ExtensionEffectiveStatementImpl to leak a not-fully-initialized instance.
115      *
116      * @param substatementsInit proposed substatements
117      * @return Filtered substatements
118      */
119     // FIXME: 6.0.0: this facility is only overridden by ExtensionEffectiveStatementImpl
120     protected Collection<? extends EffectiveStatement<?, ?>> initSubstatements(
121             final Collection<? extends StmtContext<?, ?, ?>> substatementsInit) {
122         return Collections2.transform(Collections2.filter(substatementsInit,
123             StmtContext::isSupportedToBuildEffective), StmtContext::buildEffective);
124     }
125
126     protected final <T> @Nullable T firstSubstatementOfType(final Class<T> type) {
127         return effectiveSubstatements().stream().filter(type::isInstance).findFirst().map(type::cast).orElse(null);
128     }
129
130     protected final <R> R firstSubstatementOfType(final Class<?> type, final Class<R> returnType) {
131         return effectiveSubstatements().stream()
132                 .filter(((Predicate<Object>)type::isInstance).and(returnType::isInstance))
133                 .findFirst().map(returnType::cast).orElse(null);
134     }
135
136     protected final EffectiveStatement<?, ?> firstEffectiveSubstatementOfType(final Class<?> type) {
137         return effectiveSubstatements().stream().filter(type::isInstance).findFirst().orElse(null);
138     }
139
140     // FIXME: rename to 'getFirstEffectiveStatement()'
141     protected final <S extends SchemaNode> S firstSchemaNode(final Class<S> type) {
142         return findFirstEffectiveSubstatement(type).orElse(null);
143     }
144
145
146 }