3e830d80c71c2f409bfa19ef090becef6211ee95
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / spi / meta / StmtContextUtils.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.spi.meta;
9
10 import com.google.common.base.Function;
11 import com.google.common.base.Splitter;
12 import com.google.common.collect.ImmutableSet;
13 import com.google.common.collect.ImmutableSet.Builder;
14 import java.util.Collection;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.common.QNameModule;
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.model.api.stmt.KeyStatement;
20 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
21 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.UnknownStatementImpl;
22
23 public final class StmtContextUtils {
24     public static final Splitter LIST_KEY_SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
25
26     private static final Function<StmtContext<?, ?,?>, DeclaredStatement<?>> BUILD_DECLARED =
27             new Function<StmtContext<?,?,?>, DeclaredStatement<?>>() {
28         @Override
29         public DeclaredStatement<?> apply(final StmtContext<?, ?, ?> input) {
30             return input.buildDeclared();
31         }
32     };
33
34     private static final Function<StmtContext<?, ?,?>, EffectiveStatement<?,?>> BUILD_EFFECTIVE =
35             new Function<StmtContext<?,?,?>, EffectiveStatement<?,?>>() {
36         @Override
37         public EffectiveStatement<?, ?> apply(final StmtContext<?, ?, ?> input) {
38             return input.buildEffective();
39         }
40     };
41
42     private StmtContextUtils() {
43         throw new UnsupportedOperationException("Utility class");
44     }
45
46     @SuppressWarnings("unchecked")
47     public static <D extends DeclaredStatement<?>> Function<StmtContext<?, ? extends D, ?>, D> buildDeclared() {
48         return Function.class.cast(BUILD_DECLARED);
49     }
50
51     @SuppressWarnings("unchecked")
52     public static <E extends EffectiveStatement<?, ?>> Function<StmtContext<?, ?, ? extends E>, E> buildEffective() {
53         return Function.class.cast(BUILD_EFFECTIVE);
54     }
55
56     @SuppressWarnings("unchecked")
57     public static <AT, DT extends DeclaredStatement<AT>> AT firstAttributeOf(
58             final Iterable<? extends StmtContext<?, ?, ?>> contexts, final Class<DT> declaredType) {
59         for (StmtContext<?, ?, ?> ctx : contexts) {
60             if (producesDeclared(ctx, declaredType)) {
61                 return (AT) ctx.getStatementArgument();
62             }
63         }
64         return null;
65     }
66
67     @SuppressWarnings("unchecked")
68     public static <AT, DT extends DeclaredStatement<AT>> AT firstAttributeOf(final StmtContext<?, ?, ?> ctx,
69             final Class<DT> declaredType) {
70         return producesDeclared(ctx, declaredType) ? (AT) ctx.getStatementArgument() : null;
71     }
72
73     @SuppressWarnings("unchecked")
74     public static <AT,DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstDeclaredSubstatement(
75             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
76         for (StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
77             if (producesDeclared(subStmtContext,declaredType)) {
78                 return (StmtContext<AT, ?, ?>) subStmtContext;
79             }
80         }
81         return null;
82     }
83
84     @SuppressWarnings("unchecked")
85     public static <AT,DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstEffectiveSubstatement(
86             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
87         for (StmtContext<?, ?, ?> subStmtContext : stmtContext.effectiveSubstatements()) {
88             if (producesDeclared(subStmtContext,declaredType)) {
89                 return (StmtContext<AT, ?, ?>) subStmtContext;
90             }
91         }
92         return null;
93     }
94
95     public static <AT,DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstSubstatement(
96             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
97         StmtContext<AT, ?, ?> declaredSubstatement = findFirstDeclaredSubstatement(stmtContext, declaredType);
98         return declaredSubstatement != null ? declaredSubstatement : findFirstEffectiveSubstatement(stmtContext, declaredType);
99     }
100
101     @SafeVarargs
102     public static StmtContext<?, ?, ?> findFirstDeclaredSubstatement(final StmtContext<?, ?, ?> stmtContext,
103             int startIndex, final Class<? extends DeclaredStatement<?>>... types) {
104         if (startIndex >= types.length) {
105             return null;
106         }
107
108         for (StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
109             if (producesDeclared(subStmtContext,types[startIndex])) {
110                 return startIndex + 1 == types.length ? subStmtContext
111                         : findFirstDeclaredSubstatement(subStmtContext, ++startIndex, types);
112             }
113         }
114         return null;
115     }
116
117     public static <DT extends DeclaredStatement<?>> StmtContext<?, ?, ?> findFirstDeclaredSubstatementOnSublevel(
118             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType, int sublevel) {
119         for (StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
120             if (sublevel == 1 && producesDeclared(subStmtContext, declaredType)) {
121                 return subStmtContext;
122             }
123             if (sublevel > 1) {
124                 final StmtContext<?, ?, ?> result = findFirstDeclaredSubstatementOnSublevel(
125                     subStmtContext, declaredType, --sublevel);
126                 if (result != null) {
127                     return result;
128                 }
129             }
130         }
131
132         return null;
133     }
134
135     public static <DT extends DeclaredStatement<?>> StmtContext<?, ?, ?> findDeepFirstDeclaredSubstatement(
136             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
137         for (StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
138             if (producesDeclared(subStmtContext, declaredType)) {
139                 return subStmtContext;
140             }
141
142             final StmtContext<?, ?, ?> result = findDeepFirstDeclaredSubstatement(subStmtContext, declaredType);
143             if (result != null) {
144                 return result;
145             }
146         }
147
148         return null;
149     }
150
151     public static boolean producesDeclared(final StmtContext<?, ?, ?> ctx,
152             final Class<? extends DeclaredStatement<?>> type) {
153         return type.isAssignableFrom(ctx.getPublicDefinition().getDeclaredRepresentationClass());
154     }
155
156     public static boolean isInExtensionBody(final StmtContext<?,?,?> stmtCtx) {
157         StmtContext<?,?,?> current = stmtCtx;
158         while (!current.getParentContext().isRootContext()) {
159             current = current.getParentContext();
160             if (producesDeclared(current, UnknownStatementImpl.class)) {
161                 return true;
162             }
163         }
164
165         return false;
166     }
167
168     public static boolean isUnknownStatement(final StmtContext<?, ?, ?> stmtCtx) {
169         return producesDeclared(stmtCtx, UnknownStatementImpl.class);
170     }
171
172     public static Collection<SchemaNodeIdentifier> replaceModuleQNameForKey(
173             final StmtContext<Collection<SchemaNodeIdentifier>, KeyStatement, ?> keyStmtCtx,
174             final QNameModule newQNameModule) {
175
176         final Builder<SchemaNodeIdentifier> builder = ImmutableSet.builder();
177         boolean replaced = false;
178         for (SchemaNodeIdentifier arg : keyStmtCtx.getStatementArgument()) {
179             final QName qname = arg.getLastComponent();
180             if (!newQNameModule.equals(qname)) {
181                 final QName newQname = keyStmtCtx.getFromNamespace(QNameCacheNamespace.class,
182                     QName.create(newQNameModule, qname.getLocalName()));
183                 builder.add(SchemaNodeIdentifier.create(false, newQname));
184                 replaced = true;
185             } else {
186                 builder.add(arg);
187             }
188         }
189
190         // This makes sure we reuse the collection when a grouping is instantiated in the same module
191         return replaced ? builder.build() : keyStmtCtx.getStatementArgument();
192     }
193 }