331ec0d204cc4a555c956680e89c188e07ed9bcf
[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.Predicate;
12 import com.google.common.base.Splitter;
13 import java.util.Collection;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Set;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
20 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
21 import org.opendaylight.yangtools.yang.model.api.stmt.KeyStatement;
22 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
23 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.UnknownStatementImpl;
24
25 public final class StmtContextUtils {
26
27     public static final char LIST_KEY_SEPARATOR = ' ';
28     private static final Splitter KEY_SPLITTER = Splitter.on(LIST_KEY_SEPARATOR).omitEmptyStrings().trimResults();
29
30     private static final Function<StmtContext<?, ?,?>, DeclaredStatement<?>> BUILD_DECLARED =
31             new Function<StmtContext<?,?,?>, DeclaredStatement<?>>() {
32         @Override
33         public DeclaredStatement<?> apply(final StmtContext<?, ?, ?> input) {
34             return input.buildDeclared();
35         }
36     };
37
38     private static final Function<StmtContext<?, ?,?>, EffectiveStatement<?,?>> BUILD_EFFECTIVE =
39             new Function<StmtContext<?,?,?>, EffectiveStatement<?,?>>() {
40         @Override
41         public EffectiveStatement<?, ?> apply(final StmtContext<?, ?, ?> input) {
42             return input.buildEffective();
43         }
44     };
45
46     public static final Predicate<StmtContext<?, ?,?>> IS_SUPPORTED_TO_BUILD_EFFECTIVE =
47             new Predicate<StmtContext<?,?,?>>() {
48         @Override
49         public boolean apply(final StmtContext<?, ?, ?> input) {
50             return input.isSupportedToBuildEffective();
51         }
52     };
53
54     private StmtContextUtils() {
55         throw new UnsupportedOperationException("Utility class");
56     }
57
58     @SuppressWarnings("unchecked")
59     public static <D extends DeclaredStatement<?>> Function<StmtContext<?, ? extends D, ?>, D> buildDeclared() {
60         return Function.class.cast(BUILD_DECLARED);
61     }
62
63     @SuppressWarnings("unchecked")
64     public static final <E extends EffectiveStatement<?, ?>> Function<StmtContext<?, ?, ? extends E>, E> buildEffective() {
65         return Function.class.cast(BUILD_EFFECTIVE);
66     }
67
68     @SuppressWarnings("unchecked")
69     public static final <AT, DT extends DeclaredStatement<AT>> AT firstAttributeOf(
70             final Iterable<? extends StmtContext<?, ?, ?>> contexts, final Class<DT> declaredType) {
71         for (StmtContext<?, ?, ?> ctx : contexts) {
72             if (producesDeclared(ctx, declaredType)) {
73                 return (AT) ctx.getStatementArgument();
74             }
75         }
76         return null;
77     }
78
79     @SuppressWarnings("unchecked")
80     public static final <AT, DT extends DeclaredStatement<AT>> AT firstAttributeOf(final StmtContext<?, ?, ?> ctx,
81             final Class<DT> declaredType) {
82         return producesDeclared(ctx, declaredType) ? (AT) ctx.getStatementArgument() : null;
83     }
84
85     @SuppressWarnings("unchecked")
86     public static final <AT,DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstDeclaredSubstatement(
87             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
88         for (StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
89             if (producesDeclared(subStmtContext,declaredType)) {
90                 return (StmtContext<AT, ?, ?>) subStmtContext;
91             }
92         }
93         return null;
94     }
95
96     public static final StmtContext<?, ?, ?> findFirstDeclaredSubstatement(final StmtContext<?, ?, ?> stmtContext,
97             int startIndex, final Class<? extends DeclaredStatement<?>>... types) {
98         if (startIndex >= types.length) {
99             return null;
100         }
101
102         Collection<? extends StmtContext<?, ?, ?>> declaredSubstatements = stmtContext.declaredSubstatements();
103         for (StmtContext<?, ?, ?> subStmtContext : declaredSubstatements) {
104             if (producesDeclared(subStmtContext,types[startIndex])) {
105                 if (startIndex + 1 == types.length) {
106                     return subStmtContext;
107                 } else {
108                     return findFirstDeclaredSubstatement(subStmtContext, ++startIndex, types);
109                 }
110             }
111         }
112         return null;
113     }
114
115     public static final <DT extends DeclaredStatement<?>> StmtContext<?, ?, ?> findFirstDeclaredSubstatementOnSublevel(
116             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType, int sublevel) {
117         for (StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
118             if (sublevel == 1 && producesDeclared(subStmtContext, declaredType)) {
119                 return subStmtContext;
120             }
121             if (sublevel > 1) {
122                 StmtContext<?, ?, ?> result = findFirstDeclaredSubstatementOnSublevel(
123                     subStmtContext, declaredType, --sublevel);
124                 if (result != null) {
125                     return result;
126                 }
127             }
128         }
129
130         return null;
131     }
132
133     public static final <DT extends DeclaredStatement<?>> StmtContext<?, ?, ?> findDeepFirstDeclaredSubstatement(
134             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
135         for (StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
136             if (producesDeclared(subStmtContext, declaredType)) {
137                 return subStmtContext;
138             }
139
140             StmtContext<?, ?, ?> result = findDeepFirstDeclaredSubstatement(subStmtContext, declaredType);
141             if (result != null) {
142                 return result;
143             }
144         }
145
146         return null;
147     }
148
149     public static final boolean producesDeclared(final StmtContext<?, ?, ?> ctx,
150             final Class<? extends DeclaredStatement<?>> type) {
151         return type.isAssignableFrom(ctx.getPublicDefinition().getDeclaredRepresentationClass());
152     }
153
154     public static boolean isInExtensionBody(final StmtContext<?,?,?> stmtCtx) {
155         StmtContext<?,?,?> current = stmtCtx;
156         while(!current.getParentContext().isRootContext()) {
157             current = current.getParentContext();
158             if (producesDeclared(current, UnknownStatementImpl.class)) {
159                 return true;
160             }
161         }
162
163         return false;
164     }
165
166     public static boolean isUnknownStatement(final StmtContext<?, ?, ?> stmtCtx) {
167         return producesDeclared(stmtCtx, UnknownStatementImpl.class);
168     }
169
170     public static Collection<SchemaNodeIdentifier> replaceModuleQNameForKey(
171             final StmtContext<Collection<SchemaNodeIdentifier>, KeyStatement, ?> keyStmtCtx,
172             final QNameModule newQNameModule) {
173
174         List<String> keyTokens = KEY_SPLITTER.splitToList(keyStmtCtx.rawStatementArgument());
175         Set<SchemaNodeIdentifier> newKeys = new HashSet<>();
176         for (String keyToken : keyTokens) {
177             QName keyQName = QName.create(newQNameModule, keyToken);
178             SchemaNodeIdentifier keyIdentifier = SchemaNodeIdentifier.create(false, keyQName);
179             newKeys.add(keyIdentifier);
180         }
181
182         return newKeys;
183     }
184 }