7151db18f4c37124fc925074a37ddb331297b2cd
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / effective / 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.stmt.rfc6020.effective;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Predicate;
12 import com.google.common.base.Predicates;
13 import com.google.common.collect.Collections2;
14 import com.google.common.collect.ImmutableList;
15 import com.google.common.collect.Iterables;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.List;
19 import java.util.Map;
20 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
21 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
23 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
27 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
28
29 public abstract class EffectiveStatementBase<A, D extends DeclaredStatement<A>> implements EffectiveStatement<A, D> {
30
31     private static final Predicate<StmtContext<?, ?,?>> IS_SUPPORTED_TO_BUILD_EFFECTIVE =
32             new Predicate<StmtContext<?,?,?>>() {
33         @Override
34         public boolean apply(final StmtContext<?, ?, ?> input) {
35             return input.isSupportedToBuildEffective();
36         }
37     };
38
39     private static final Predicate<StmtContext<?, ?,?>> IS_UNKNOWN_STATEMENT_CONTEXT =
40             new Predicate<StmtContext<?,?,?>>() {
41         @Override
42         public boolean apply(final StmtContext<?, ?, ?> input) {
43             return StmtContextUtils.isUnknownStatement(input);
44         }
45     };
46
47     private final List<? extends EffectiveStatement<?, ?>> substatements;
48     private final List<StatementContextBase<?, ?, ?>> unknownSubstatementsToBuild;
49
50     protected EffectiveStatementBase(final StmtContext<A, D, ?> ctx) {
51         this(ctx, true);
52     }
53
54     /**
55      * Constructor.
56      *
57      * @param ctx
58      *            context of statement.
59      * @param buildUnknownSubstatements
60      *            if it is false, the unknown substatements are omitted from
61      *            build of effective substatements till the call of either
62      *            effectiveSubstatements or getOmittedUnknownSubstatements
63      *            method. The main purpose of this is to allow the build of
64      *            recursive extension definitions.
65      */
66     protected EffectiveStatementBase(final StmtContext<A, D, ?> ctx, boolean buildUnknownSubstatements) {
67
68         final Collection<StatementContextBase<?, ?, ?>> effectiveSubstatements = ctx.effectiveSubstatements();
69         final Collection<StatementContextBase<?, ?, ?>> substatementsInit = new ArrayList<>();
70
71         for(StatementContextBase<?, ?, ?> declaredSubstatement : ctx.declaredSubstatements()) {
72             if (declaredSubstatement.getPublicDefinition().equals(Rfc6020Mapping.USES)) {
73                 substatementsInit.add(declaredSubstatement);
74                 substatementsInit.addAll(declaredSubstatement.getEffectOfStatement());
75                 ((StatementContextBase<?, ?, ?>) ctx).removeStatementsFromEffectiveSubstatements(declaredSubstatement
76                         .getEffectOfStatement());
77             } else {
78                 substatementsInit.add(declaredSubstatement);
79             }
80         }
81         substatementsInit.addAll(effectiveSubstatements);
82
83         Collection<StatementContextBase<?, ?, ?>> substatementsToBuild = Collections2.filter(substatementsInit,
84                 IS_SUPPORTED_TO_BUILD_EFFECTIVE);
85         if (!buildUnknownSubstatements) {
86             this.unknownSubstatementsToBuild = ImmutableList.copyOf(Collections2.filter(substatementsToBuild,
87                     IS_UNKNOWN_STATEMENT_CONTEXT));
88             substatementsToBuild = Collections2.filter(substatementsToBuild,
89                     Predicates.not(IS_UNKNOWN_STATEMENT_CONTEXT));
90         } else {
91             this.unknownSubstatementsToBuild = ImmutableList.of();
92         }
93
94         this.substatements = ImmutableList.copyOf(Collections2.transform(substatementsToBuild,
95                 StmtContextUtils.buildEffective()));
96     }
97
98     Collection<EffectiveStatement<?, ?>> getOmittedUnknownSubstatements() {
99         return Collections2.transform(unknownSubstatementsToBuild,
100                 StmtContextUtils.buildEffective());
101     }
102
103     @Override
104     public final <K, V, N extends IdentifierNamespace<K, V>> V get(final Class<N> namespace, final K identifier) {
105         throw new UnsupportedOperationException("Not implemented yet.");
106     }
107
108     @Override
109     public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(final Class<N> namespace) {
110         throw new UnsupportedOperationException("Not implemented yet.");
111     }
112
113     @Override
114     public final Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
115         if (unknownSubstatementsToBuild.isEmpty()) {
116             return substatements;
117         } else {
118             return ImmutableList.copyOf(Iterables.concat(substatements, getOmittedUnknownSubstatements()));
119         }
120     }
121
122     protected final <S extends EffectiveStatement<?, ?>> S firstEffective(final Class<S> type) {
123         Optional<? extends EffectiveStatement<?, ?>> possible = Iterables.tryFind(substatements,
124                 Predicates.instanceOf(type));
125         return possible.isPresent() ? type.cast(possible.get()) : null;
126     }
127
128     protected final <S extends SchemaNode> S firstSchemaNode(final Class<S> type) {
129         Optional<? extends EffectiveStatement<?, ?>> possible = Iterables.tryFind(substatements,
130                 Predicates.instanceOf(type));
131         return possible.isPresent() ? type.cast(possible.get()) : null;
132     }
133
134     @SuppressWarnings("unchecked")
135     protected final <T> Collection<T> allSubstatementsOfType(final Class<T> type) {
136         return Collection.class.cast(Collections2.filter(substatements, Predicates.instanceOf(type)));
137     }
138
139     protected final <T> T firstSubstatementOfType(final Class<T> type) {
140         Optional<? extends EffectiveStatement<?, ?>> possible = Iterables.tryFind(substatements,
141                 Predicates.instanceOf(type));
142         return possible.isPresent() ? type.cast(possible.get()) : null;
143     }
144
145     protected final <R> R firstSubstatementOfType(final Class<?> type, final Class<R> returnType) {
146         Optional<? extends EffectiveStatement<?, ?>> possible = Iterables.tryFind(substatements,
147                 Predicates.and(Predicates.instanceOf(type), Predicates.instanceOf(returnType)));
148         return possible.isPresent() ? returnType.cast(possible.get()) : null;
149     }
150
151     protected final EffectiveStatement<?, ?> firstEffectiveSubstatementOfType(final Class<?> type) {
152         return Iterables.tryFind(substatements, Predicates.instanceOf(type)).orNull();
153     }
154 }