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.builder.impl;
10 import java.util.Comparator;
11 import java.util.Date;
14 import java.util.TreeMap;
16 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
17 import org.opendaylight.yangtools.yang.model.api.Module;
18 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
19 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
20 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
21 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
22 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
23 import org.opendaylight.yangtools.yang.parser.builder.api.RefineBuilder;
24 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
25 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
27 public final class GroupingUtils {
29 private GroupingUtils() {
33 * Search given modules for grouping by name defined in uses node.
36 * builder of uses statement
41 * @return grouping with given name if found, null otherwise
43 public static GroupingBuilder getTargetGroupingFromModules(final UsesNodeBuilder usesBuilder,
44 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
45 final int line = usesBuilder.getLine();
47 final String groupingString = usesBuilder.getGroupingPathAsString();
48 String groupingPrefix;
51 if (groupingString.contains(":")) {
52 String[] splitted = groupingString.split(":");
53 if (splitted.length != 2 || groupingString.contains("/")) {
54 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
56 groupingPrefix = splitted[0];
57 groupingName = splitted[1];
59 groupingPrefix = module.getPrefix();
60 groupingName = groupingString;
63 ModuleBuilder dependentModule;
64 if(groupingPrefix == null) {
65 dependentModule = module;
67 if (groupingPrefix.equals(module.getPrefix())) {
68 dependentModule = module;
70 dependentModule = BuilderUtils.findModuleFromBuilders(modules, module, groupingPrefix, line);
73 if (dependentModule == null) {
77 GroupingBuilder result;
78 Set<GroupingBuilder> groupings = dependentModule.getGroupingBuilders();
79 result = findGroupingBuilder(groupings, groupingName);
84 Builder parent = usesBuilder.getParent();
86 while (parent != null) {
87 if (parent instanceof DataNodeContainerBuilder) {
88 groupings = ((DataNodeContainerBuilder) parent).getGroupingBuilders();
89 } else if (parent instanceof RpcDefinitionBuilder) {
90 groupings = ((RpcDefinitionBuilder) parent).getGroupings();
92 result = findGroupingBuilder(groupings, groupingName);
94 parent = parent.getParent();
100 if (result == null) {
101 throw new YangParseException(module.getName(), line, "Referenced grouping '" + groupingName
108 * Search context for grouping by name defined in uses node.
111 * builder of uses statement
115 * SchemaContext containing already resolved modules
116 * @return grouping with given name if found, null otherwise
118 public static GroupingDefinition getTargetGroupingFromContext(final UsesNodeBuilder usesBuilder,
119 final ModuleBuilder module, final SchemaContext context) {
120 final int line = usesBuilder.getLine();
121 String groupingString = usesBuilder.getGroupingPathAsString();
122 String groupingPrefix;
125 if (groupingString.contains(":")) {
126 String[] splitted = groupingString.split(":");
127 if (splitted.length != 2 || groupingString.contains("/")) {
128 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
130 groupingPrefix = splitted[0];
131 groupingName = splitted[1];
133 groupingPrefix = module.getPrefix();
134 groupingName = groupingString;
137 Module dependentModule = BuilderUtils.findModuleFromContext(context, module, groupingPrefix, line);
138 return findGroupingDefinition(dependentModule.getGroupings(), groupingName);
142 * Find grouping by name.
145 * collection of grouping builders to search
148 * @return grouping with given name if present in collection, null otherwise
150 public static GroupingBuilder findGroupingBuilder(final Set<GroupingBuilder> groupings, final String name) {
151 for (GroupingBuilder grouping : groupings) {
152 if (grouping.getQName().getLocalName().equals(name)) {
160 * Find grouping by name.
163 * collection of grouping definitions to search
166 * @return grouping with given name if present in collection, null otherwise
168 public static GroupingDefinition findGroupingDefinition(final Set<GroupingDefinition> groupings, final String name) {
169 for (GroupingDefinition grouping : groupings) {
170 if (grouping.getQName().getLocalName().equals(name)) {
178 * Perform refinement of uses target grouping nodes. Uses process has to be
182 * uses node containing refine statements
184 public static void performRefine(final UsesNodeBuilder usesNode) {
185 for (RefineBuilder refine : usesNode.getRefines()) {
186 String refineTargetPath = refine.getTargetPathString();
188 String[] splitted = refineTargetPath.split("/");
189 Builder currentNode = usesNode.getParent();
190 for (String pathElement : splitted) {
191 if (currentNode instanceof DataNodeContainerBuilder) {
192 currentNode = ((DataNodeContainerBuilder) currentNode).getDataChildByName(pathElement);
193 } else if (currentNode instanceof ChoiceBuilder) {
194 currentNode = ((ChoiceBuilder) currentNode).getCaseNodeByName(pathElement);
198 DataSchemaNodeBuilder nodeToRefine = (DataSchemaNodeBuilder) currentNode;
199 if (nodeToRefine == null) {
200 throw new YangParseException(refine.getModuleName(), refine.getLine(), "Refine target node '"
201 + refine.getTargetPathString() + "' not found");
203 RefineUtils.performRefine(nodeToRefine, refine);
204 usesNode.addRefineNode(nodeToRefine);
208 public static class UsesComparator implements Comparator<UsesNodeBuilder> {
210 public int compare(final UsesNodeBuilder o1, final UsesNodeBuilder o2) {
211 return getElementPosition(o2) - getElementPosition(o1);
215 private static int getElementPosition(final UsesNodeBuilder usesNode) {
217 Builder parent = usesNode.getParent();
218 while (!(parent instanceof ModuleBuilder)) {
219 parent = parent.getParent();