YANGTOOLS-706: Split out yang-parser-rfc7950
[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.ArrayList;
13 import java.util.Collection;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.function.Predicate;
17 import javax.annotation.Nonnull;
18 import javax.annotation.Nullable;
19 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
21 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
22 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
23 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
25 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
26
27 public abstract class EffectiveStatementBase<A, D extends DeclaredStatement<A>> implements EffectiveStatement<A, D> {
28     private final List<? extends EffectiveStatement<?, ?>> substatements;
29
30     /**
31      * Constructor.
32      *
33      * @param ctx
34      *            context of statement.
35      */
36     protected EffectiveStatementBase(final StmtContext<A, D, ?> ctx) {
37         final Collection<? extends StmtContext<?, ?, ?>> effectiveSubstatements = ctx.effectiveSubstatements();
38         final Collection<StmtContext<?, ?, ?>> substatementsInit = new ArrayList<>();
39
40         final Collection<? extends StmtContext<?, ?, ?>> supportedDeclaredSubStmts = Collections2.filter(
41                 ctx.declaredSubstatements(), StmtContext::isSupportedByFeatures);
42         for (final StmtContext<?, ?, ?> declaredSubstatement : supportedDeclaredSubStmts) {
43             if (YangStmtMapping.USES == declaredSubstatement.getPublicDefinition()) {
44                 substatementsInit.add(declaredSubstatement);
45                 substatementsInit.addAll(declaredSubstatement.getEffectOfStatement());
46                 ((StatementContextBase<?, ?, ?>) ctx).removeStatementsFromEffectiveSubstatements(declaredSubstatement
47                         .getEffectOfStatement());
48             } else {
49                 substatementsInit.add(declaredSubstatement);
50             }
51         }
52         substatementsInit.addAll(effectiveSubstatements);
53
54         this.substatements = ImmutableList.copyOf(initSubstatements(substatementsInit));
55     }
56
57     /**
58      * Create a set of substatements. This method is split out so it can be overridden in
59      * ExtensionEffectiveStatementImpl to leak a not-fully-initialized instance.
60      *
61      * @param substatementsInit proposed substatements
62      * @return Filtered substatements
63      */
64     protected Collection<? extends EffectiveStatement<?, ?>> initSubstatements(
65             final Collection<? extends StmtContext<?, ?, ?>> substatementsInit) {
66         return Collections2.transform(Collections2.filter(substatementsInit,
67             StmtContext::isSupportedToBuildEffective), StmtContext::buildEffective);
68     }
69
70     @Override
71     public final <K, V, N extends IdentifierNamespace<K, V>> V get(@Nonnull final Class<N> namespace,
72             @Nonnull final K identifier) {
73         throw new UnsupportedOperationException("Not implemented yet.");
74     }
75
76     @Override
77     public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(@Nonnull final Class<N> namespace) {
78         throw new UnsupportedOperationException("Not implemented yet.");
79     }
80
81     @Nonnull
82     @Override
83     public final Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
84         return substatements;
85     }
86
87     /**
88      * Find first substatement of specified type.
89      *
90      * @param type Requested type
91      * @return First matching substatement, or null if no match is found.
92      *
93      * @deprecated Use {@link #findFirstEffectiveSubstatement(Class)} instead.
94      */
95     @Deprecated
96     public final <S extends EffectiveStatement<?, ?>> S firstEffective(final Class<S> type) {
97         return findFirstEffectiveSubstatement(type).orElse(null);
98     }
99
100     protected final <S extends SchemaNode> S firstSchemaNode(final Class<S> type) {
101         return substatements.stream().filter(type::isInstance).findFirst().map(type::cast).orElse(null);
102     }
103
104     @SuppressWarnings("unchecked")
105     public final <T> Collection<T> allSubstatementsOfType(final Class<T> type) {
106         return Collection.class.cast(Collections2.filter(substatements, type::isInstance));
107     }
108
109     @Nullable protected final <T> T firstSubstatementOfType(final Class<T> type) {
110         return substatements.stream().filter(type::isInstance).findFirst().map(type::cast).orElse(null);
111     }
112
113     protected final <R> R firstSubstatementOfType(final Class<?> type, final Class<R> returnType) {
114         return substatements.stream()
115                 .filter(((Predicate<Object>)type::isInstance).and(returnType::isInstance))
116                 .findFirst().map(returnType::cast).orElse(null);
117     }
118
119     protected final EffectiveStatement<?, ?> firstEffectiveSubstatementOfType(final Class<?> type) {
120         return substatements.stream().filter(type::isInstance).findFirst().orElse(null);
121     }
122 }