2 * Copyright (c) 2013 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.util;
10 import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.createSchemaPath;
13 import java.util.ArrayList;
14 import java.util.Date;
15 import java.util.HashSet;
16 import java.util.List;
19 import java.util.TreeMap;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
24 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
27 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.Module;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
32 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
33 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
34 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
35 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
36 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
37 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
38 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
39 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingMember;
40 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
41 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
42 import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
43 import org.opendaylight.yangtools.yang.parser.builder.impl.RpcDefinitionBuilder;
44 import org.opendaylight.yangtools.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
46 public class GroupingUtils {
49 * Search given modules for grouping by name defined in uses node.
52 * builder of uses statement
57 * @return grouping with given name if found, null otherwise
59 public static GroupingBuilder getTargetGroupingFromModules(final UsesNodeBuilder usesBuilder,
60 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
61 final int line = usesBuilder.getLine();
62 final String groupingString = usesBuilder.getGroupingName();
63 String groupingPrefix;
66 if (groupingString.contains(":")) {
67 String[] splitted = groupingString.split(":");
68 if (splitted.length != 2 || groupingString.contains("/")) {
69 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
71 groupingPrefix = splitted[0];
72 groupingName = splitted[1];
74 groupingPrefix = module.getPrefix();
75 groupingName = groupingString;
78 ModuleBuilder dependentModule = null;
79 if (groupingPrefix.equals(module.getPrefix())) {
80 dependentModule = module;
82 dependentModule = ParserUtils.findDependentModuleBuilder(modules, module, groupingPrefix, line);
85 if (dependentModule == null) {
89 GroupingBuilder result = null;
90 Set<GroupingBuilder> groupings = dependentModule.getGroupingBuilders();
91 result = findGroupingBuilder(groupings, groupingName);
96 Builder parent = usesBuilder.getParent();
98 while (parent != null) {
99 if (parent instanceof DataNodeContainerBuilder) {
100 groupings = ((DataNodeContainerBuilder) parent).getGroupingBuilders();
101 } else if (parent instanceof RpcDefinitionBuilder) {
102 groupings = ((RpcDefinitionBuilder) parent).getGroupings();
104 result = findGroupingBuilder(groupings, groupingName);
105 if (result == null) {
106 parent = parent.getParent();
112 if (result == null) {
113 throw new YangParseException(module.getName(), line, "Referenced grouping '" + groupingName
120 * Search context for grouping by name defined in uses node.
123 * builder of uses statement
127 * SchemaContext containing already resolved modules
128 * @return grouping with given name if found, null otherwise
130 public static GroupingDefinition getTargetGroupingFromContext(final UsesNodeBuilder usesBuilder,
131 final ModuleBuilder module, final SchemaContext context) {
132 final int line = usesBuilder.getLine();
133 String groupingString = usesBuilder.getGroupingName();
134 String groupingPrefix;
137 if (groupingString.contains(":")) {
138 String[] splitted = groupingString.split(":");
139 if (splitted.length != 2 || groupingString.contains("/")) {
140 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
142 groupingPrefix = splitted[0];
143 groupingName = splitted[1];
145 groupingPrefix = module.getPrefix();
146 groupingName = groupingString;
149 Module dependentModule = ParserUtils.findModuleFromContext(context, module, groupingPrefix, line);
150 return findGroupingDefinition(dependentModule.getGroupings(), groupingName);
154 * Find grouping by name.
157 * collection of grouping builders to search
160 * @return grouping with given name if present in collection, null otherwise
162 public static GroupingBuilder findGroupingBuilder(Set<GroupingBuilder> groupings, String name) {
163 for (GroupingBuilder grouping : groupings) {
164 if (grouping.getQName().getLocalName().equals(name)) {
172 * Find grouping by name.
175 * collection of grouping definitions to search
178 * @return grouping with given name if present in collection, null otherwise
180 public static GroupingDefinition findGroupingDefinition(Set<GroupingDefinition> groupings, String name) {
181 for (GroupingDefinition grouping : groupings) {
182 if (grouping.getQName().getLocalName().equals(name)) {
190 * Add nodes defined in uses target grouping to uses parent.
194 public static void updateUsesParent(UsesNodeBuilder usesNode) {
195 DataNodeContainerBuilder parent = usesNode.getParent();
198 for (DataSchemaNodeBuilder child : usesNode.getTargetChildren()) {
199 if (child instanceof GroupingMember) {
200 ((GroupingMember) child).setAddedByUses(true);
202 parent.addChildNode(child);
206 for (GroupingBuilder gb : usesNode.getTargetGroupings()) {
207 gb.setAddedByUses(true);
208 parent.addGrouping(gb);
212 for (TypeDefinitionBuilder tdb : usesNode.getTargetTypedefs()) {
213 tdb.setAddedByUses(true);
214 parent.addTypedef(tdb);
218 for (UnknownSchemaNodeBuilder un : usesNode.getTargetUnknownNodes()) {
219 un.setAddedByUses(true);
220 parent.addUnknownNodeBuilder(un);
224 public static void collectUsesData(UsesNodeBuilder usesNode) {
225 usesNode.setTargetChildren(collectUsesChildNodes(usesNode));
226 usesNode.setTargetTypedefs(collectUsesTypedefs(usesNode));
227 usesNode.setTargetGroupings(collectUsesGroupings(usesNode));
228 usesNode.setTargetUnknownNodes(collectUsesUnknownNodes(usesNode));
229 usesNode.setDataCollected(true);
232 private static Set<DataSchemaNodeBuilder> collectUsesChildNodes(UsesNodeBuilder usesNode) {
233 final GroupingBuilder target = usesNode.getGroupingBuilder();
234 Set<DataSchemaNodeBuilder> childNodes = target.getChildNodeBuilders();
235 Set<DataSchemaNodeBuilder> copies = new HashSet<>();
236 for (DataSchemaNodeBuilder childNode : childNodes) {
237 copies.add(CopyUtils.copy(childNode, usesNode.getParent(), true));
239 for (UsesNodeBuilder targetUses : target.getUsesNodes()) {
240 copies.addAll(collectUsesChildNodes(targetUses));
245 private static Set<TypeDefinitionBuilder> collectUsesTypedefs(UsesNodeBuilder usesNode) {
246 final GroupingBuilder target = usesNode.getGroupingBuilder();
247 Set<TypeDefinitionBuilder> typedefs = target.getTypeDefinitionBuilders();
248 Set<TypeDefinitionBuilder> copies = new HashSet<>();
249 for (TypeDefinitionBuilder typedef : typedefs) {
250 copies.add(CopyUtils.copy(typedef, usesNode.getParent(), true));
252 for (UsesNodeBuilder targetUses : target.getUsesNodes()) {
253 copies.addAll(collectUsesTypedefs(targetUses));
258 private static Set<GroupingBuilder> collectUsesGroupings(UsesNodeBuilder usesNode) {
259 final GroupingBuilder target = usesNode.getGroupingBuilder();
260 Set<GroupingBuilder> groupings = target.getGroupingBuilders();
261 Set<GroupingBuilder> copies = new HashSet<>();
262 for (GroupingBuilder grouping : groupings) {
263 copies.add(CopyUtils.copy(grouping, usesNode.getParent(), true));
265 for (UsesNodeBuilder targetUses : target.getUsesNodes()) {
266 copies.addAll(collectUsesGroupings(targetUses));
271 private static List<UnknownSchemaNodeBuilder> collectUsesUnknownNodes(UsesNodeBuilder usesNode) {
272 final GroupingBuilder target = usesNode.getGroupingBuilder();
273 List<UnknownSchemaNodeBuilder> unknownNodes = target.getUnknownNodeBuilders();
274 List<UnknownSchemaNodeBuilder> copies = new ArrayList<>();
275 for (UnknownSchemaNodeBuilder unknownNode : unknownNodes) {
276 copies.add(CopyUtils.copy(unknownNode, usesNode.getParent(), true));
278 for (UsesNodeBuilder targetUses : target.getUsesNodes()) {
279 copies.addAll(collectUsesUnknownNodes(targetUses));
284 public static void collectUsesDataFromContext(UsesNodeBuilder usesNode) {
285 DataNodeContainerBuilder parent = usesNode.getParent();
286 URI namespace = parent.getQName().getNamespace();
287 Date revision = parent.getQName().getRevision();
288 String prefix = parent.getQName().getPrefix();
289 String moduleName = parent.getModuleName();
290 int line = parent.getLine();
293 final Set<DataSchemaNodeBuilder> newChildren = new HashSet<>();
294 for (DataSchemaNode child : usesNode.getGroupingDefinition().getChildNodes()) {
296 DataSchemaNodeBuilder newChild = null;
297 QName newQName = new QName(namespace, revision, prefix, child.getQName().getLocalName());
298 if (child instanceof AnyXmlSchemaNode) {
299 newChild = CopyUtils.createAnyXml((AnyXmlSchemaNode) child, newQName, moduleName, line);
300 } else if (child instanceof ChoiceNode) {
301 newChild = CopyUtils.createChoice((ChoiceNode) child, newQName, moduleName, line);
302 } else if (child instanceof ContainerSchemaNode) {
303 newChild = CopyUtils.createContainer((ContainerSchemaNode) child, newQName, moduleName, line);
304 } else if (child instanceof LeafListSchemaNode) {
305 newChild = CopyUtils.createLeafList((LeafListSchemaNode) child, newQName, moduleName, line);
306 } else if (child instanceof LeafSchemaNode) {
307 newChild = CopyUtils.createLeafBuilder((LeafSchemaNode) child, newQName, moduleName, line);
308 } else if (child instanceof ListSchemaNode) {
309 newChild = CopyUtils.createList((ListSchemaNode) child, newQName, moduleName, line);
312 if (newChild == null) {
313 throw new YangParseException(moduleName, line,
314 "Unknown member of target grouping while resolving uses node.");
316 if (newChild instanceof GroupingMember) {
317 ((GroupingMember) newChild).setAddedByUses(true);
320 newChild.setPath(createSchemaPath(parent.getPath(), newQName));
321 newChildren.add(newChild);
324 usesNode.setTargetChildren(newChildren);
327 final Set<GroupingBuilder> newGroupings = new HashSet<>();
328 for (GroupingDefinition g : usesNode.getGroupingDefinition().getGroupings()) {
329 QName newQName = new QName(namespace, revision, prefix, g.getQName().getLocalName());
330 GroupingBuilder newGrouping = CopyUtils.createGrouping(g, newQName, moduleName, line);
331 newGrouping.setAddedByUses(true);
332 newGrouping.setPath(createSchemaPath(parent.getPath(), newQName));
333 newGroupings.add(newGrouping);
335 usesNode.setTargetGroupings(newGroupings);
338 final Set<TypeDefinitionBuilder> newTypedefs = new HashSet<>();
339 for (TypeDefinition<?> td : usesNode.getGroupingDefinition().getTypeDefinitions()) {
340 QName newQName = new QName(namespace, revision, prefix, td.getQName().getLocalName());
341 TypeDefinitionBuilder newType = CopyUtils.createTypedef((ExtendedType) td, newQName, moduleName, line);
342 newType.setAddedByUses(true);
343 newType.setPath(createSchemaPath(parent.getPath(), newQName));
344 newTypedefs.add(newType);
346 usesNode.setTargetTypedefs(newTypedefs);
349 final List<UnknownSchemaNodeBuilder> newUnknownNodes = new ArrayList<>();
350 for (UnknownSchemaNode un : usesNode.getGroupingDefinition().getUnknownSchemaNodes()) {
351 QName newQName = new QName(namespace, revision, prefix, un.getQName().getLocalName());
352 UnknownSchemaNodeBuilder newNode = CopyUtils.createUnknownSchemaNode(un, newQName, moduleName, line);
353 newNode.setAddedByUses(true);
354 newNode.setPath(createSchemaPath(parent.getPath(), newQName));
355 newUnknownNodes.add(newNode);
357 usesNode.setTargetUnknownNodes(newUnknownNodes);
359 usesNode.setDataCollected(true);
362 public static void fixUsesNodesPath(UsesNodeBuilder usesNode) {
363 DataNodeContainerBuilder parent = usesNode.getParent();
366 Set<DataSchemaNodeBuilder> currentChildNodes = parent.getChildNodeBuilders();
367 for (DataSchemaNodeBuilder child : currentChildNodes) {
368 if (child instanceof GroupingMember) {
369 GroupingMember gm = (GroupingMember) child;
370 if (gm.isAddedByUses()) {
371 ParserUtils.correctNodePath(child, parent.getPath());
377 Set<GroupingBuilder> currentGroupings = parent.getGroupingBuilders();
378 for (GroupingBuilder child : currentGroupings) {
379 if (child.isAddedByUses()) {
380 ParserUtils.correctNodePath(child, parent.getPath());
386 Set<TypeDefinitionBuilder> currentTypedefs = parent.getTypeDefinitionBuilders();
387 for (TypeDefinitionBuilder child : currentTypedefs) {
388 if (child.isAddedByUses()) {
389 ParserUtils.correctNodePath(child, parent.getPath());
395 List<UnknownSchemaNodeBuilder> currentUN = parent.getUnknownNodeBuilders();
396 for (UnknownSchemaNodeBuilder un : currentUN) {
397 if (un.isAddedByUses()) {
398 ParserUtils.correctNodePath(un, parent.getPath());
404 * Perform refinement of uses target grouping nodes. Uses process has to be
409 public static void performRefine(UsesNodeBuilder usesNode) {
410 for (RefineHolder refine : usesNode.getRefines()) {
411 DataSchemaNodeBuilder nodeToRefine = null;
412 for (DataSchemaNodeBuilder dataNode : usesNode.getParent().getChildNodeBuilders()) {
413 if (refine.getName().equals(dataNode.getQName().getLocalName())) {
414 nodeToRefine = dataNode;
418 if (nodeToRefine == null) {
419 throw new YangParseException(refine.getModuleName(), refine.getLine(), "Refine target node '"
420 + refine.getName() + "' not found");
422 RefineUtils.performRefine(nodeToRefine, refine);
423 usesNode.addRefineNode(nodeToRefine);