Remove YangStatementStreamSource.getYangAST()
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / EffectiveStatementBase.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. 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.collect.Collections2;
11 import com.google.common.collect.ImmutableList;
12 import java.util.Collection;
13 import java.util.function.Predicate;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.eclipse.jdt.annotation.Nullable;
16 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
17 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
18 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
19 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
20
21 /**
22  * Stateful version of {@link AbstractEffectiveStatement}, which holds substatements in an {@link ImmutableList}.
23  *
24  * @param <A> Argument type ({@link Void} if statement does not have argument.)
25  * @param <D> Class representing declared version of this statement.
26  *
27  * @deprecated This class has a number of design problems. Please use either {@link AbstractDeclaredEffectiveStatement}
28  *             or {@link AbstractUndeclaredEffectiveStatement} instead.
29  */
30 // TODO: This class is problematic in that it interacts with its subclasses via methods which are guaranteed to allows
31 //       atrocities like RecursiveObjectLeaker tricks. That should be avoided and pushed to caller in a way where
32 //       this class is a pure holder taking {@code ImmutableList<? extends EffectiveStatement<?, ?>>} in the
33 //       constructor.
34 //
35 //       From memory efficiency perspective, it is very common to have effective statements without any substatements,
36 //       in which case 'substatements' field is redundant.
37 @Deprecated(forRemoval = true)
38 // FIXME: 6.0.0: fold this into AbstractEffectiveDocumentedNodeWithStatus
39 public abstract class EffectiveStatementBase<A, D extends DeclaredStatement<A>>
40         extends AbstractEffectiveStatement<A, D> {
41     private final @NonNull ImmutableList<? extends EffectiveStatement<?, ?>> substatements;
42
43     /**
44      * Constructor.
45      *
46      * @param ctx context of statement.
47      */
48     protected EffectiveStatementBase(final StmtContext<A, D, ?> ctx) {
49         this.substatements = ImmutableList.copyOf(initSubstatements(BaseStatementSupport.declaredSubstatements(ctx)));
50     }
51
52     /**
53      * Create a set of substatements. This method is split out so it can be overridden in
54      * ExtensionEffectiveStatementImpl to leak a not-fully-initialized instance.
55      *
56      * @param substatementsInit proposed substatements
57      * @return Filtered substatements
58      */
59     // FIXME: 6.0.0: this facility is only overridden by ExtensionEffectiveStatementImpl
60     protected Collection<? extends EffectiveStatement<?, ?>> initSubstatements(
61             final Collection<? extends StmtContext<?, ?, ?>> substatementsInit) {
62         return Collections2.transform(Collections2.filter(substatementsInit,
63             StmtContext::isSupportedToBuildEffective), StmtContext::buildEffective);
64     }
65
66     @Override
67     public final Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
68         return substatements;
69     }
70
71     @SuppressWarnings("unchecked")
72     public final <T> Collection<T> allSubstatementsOfType(final Class<T> type) {
73         return Collection.class.cast(Collections2.filter(effectiveSubstatements(), type::isInstance));
74     }
75
76     protected final <T> @Nullable T firstSubstatementOfType(final Class<T> type) {
77         return effectiveSubstatements().stream().filter(type::isInstance).findFirst().map(type::cast).orElse(null);
78     }
79
80     protected final <R> R firstSubstatementOfType(final Class<?> type, final Class<R> returnType) {
81         return effectiveSubstatements().stream()
82                 .filter(((Predicate<Object>)type::isInstance).and(returnType::isInstance))
83                 .findFirst().map(returnType::cast).orElse(null);
84     }
85
86     protected final EffectiveStatement<?, ?> firstEffectiveSubstatementOfType(final Class<?> type) {
87         return effectiveSubstatements().stream().filter(type::isInstance).findFirst().orElse(null);
88     }
89
90     // FIXME: rename to 'getFirstEffectiveStatement()'
91     protected final <S extends SchemaNode> S firstSchemaNode(final Class<S> type) {
92         return findFirstEffectiveSubstatement(type).orElse(null);
93     }
94 }