2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt;
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;
22 * Stateful version of {@link AbstractEffectiveStatement}, which holds substatements in an {@link ImmutableList}.
24 * @param <A> Argument type ({@link Void} if statement does not have argument.)
25 * @param <D> Class representing declared version of this statement.
27 // TODO: This class is problematic in that it interacts with its subclasses via methods which are guaranteed to allows
28 // atrocities like RecursiveObjectLeaker tricks. That should be avoided and pushed to caller in a way where
29 // this class is a pure holder taking {@code ImmutableList<? extends EffectiveStatement<?, ?>>} in the
32 // From memory efficiency perspective, it is very common to have effective statements without any substatements,
33 // in which case 'substatements' field is redundant.
34 public abstract class EffectiveStatementBase<A, D extends DeclaredStatement<A>>
35 extends AbstractEffectiveStatement<A, D> {
36 private final @NonNull ImmutableList<? extends EffectiveStatement<?, ?>> substatements;
41 * @param ctx context of statement.
43 protected EffectiveStatementBase(final StmtContext<A, D, ?> ctx) {
44 this.substatements = ImmutableList.copyOf(initSubstatements(BaseStatementSupport.declaredSubstatements(ctx)));
48 * Create a set of substatements. This method is split out so it can be overridden in
49 * ExtensionEffectiveStatementImpl to leak a not-fully-initialized instance.
51 * @param substatementsInit proposed substatements
52 * @return Filtered substatements
54 protected Collection<? extends EffectiveStatement<?, ?>> initSubstatements(
55 final Collection<? extends StmtContext<?, ?, ?>> substatementsInit) {
56 return Collections2.transform(Collections2.filter(substatementsInit,
57 StmtContext::isSupportedToBuildEffective), StmtContext::buildEffective);
61 public final Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
65 @SuppressWarnings("unchecked")
66 public final <T> Collection<T> allSubstatementsOfType(final Class<T> type) {
67 return Collection.class.cast(Collections2.filter(effectiveSubstatements(), type::isInstance));
70 protected final <T> @Nullable T firstSubstatementOfType(final Class<T> type) {
71 return effectiveSubstatements().stream().filter(type::isInstance).findFirst().map(type::cast).orElse(null);
74 protected final <R> R firstSubstatementOfType(final Class<?> type, final Class<R> returnType) {
75 return effectiveSubstatements().stream()
76 .filter(((Predicate<Object>)type::isInstance).and(returnType::isInstance))
77 .findFirst().map(returnType::cast).orElse(null);
80 protected final EffectiveStatement<?, ?> firstEffectiveSubstatementOfType(final Class<?> type) {
81 return effectiveSubstatements().stream().filter(type::isInstance).findFirst().orElse(null);
84 // FIXME: rename to 'getFirstEffectiveStatement()'
85 protected final <S extends SchemaNode> S firstSchemaNode(final Class<S> type) {
86 return findFirstEffectiveSubstatement(type).orElse(null);