2 * Copyright (c) 2015 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.data.impl.leafref;
10 import java.io.ByteArrayInputStream;
11 import java.io.IOException;
12 import java.nio.charset.Charset;
13 import java.util.Collection;
14 import java.util.LinkedList;
15 import java.util.List;
17 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
18 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
20 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.Module;
24 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
25 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
28 class LeafRefContextTreeBuilder {
29 private final SchemaContext schemaContext;
30 private final List<LeafRefContext> leafRefs;
32 public LeafRefContextTreeBuilder(final SchemaContext schemaContext) {
33 this.schemaContext = schemaContext;
34 this.leafRefs = new LinkedList<LeafRefContext>();
37 public LeafRefContext buildLeafRefContextTree() throws IOException,
38 LeafRefYangSyntaxErrorException {
39 final LeafRefContextBuilder rootBuilder = new LeafRefContextBuilder(
40 schemaContext.getQName(), schemaContext.getPath(),
43 final Set<Module> modules = schemaContext.getModules();
44 for (final Module module : modules) {
45 final Collection<DataSchemaNode> childNodes = module.getChildNodes();
46 for (final DataSchemaNode childNode : childNodes) {
47 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencingTree(
50 if (childLeafRefContext.hasReferencingChild()
51 || childLeafRefContext.isReferencing()) {
52 rootBuilder.addReferencingChild(childLeafRefContext,
53 childLeafRefContext.getNodeName());
58 for (final Module module : modules) {
59 final Collection<DataSchemaNode> childNodes = module.getChildNodes();
60 for (final DataSchemaNode childNode : childNodes) {
61 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencedByTree(
64 if (childLeafRefContext.hasReferencedChild()
65 || childLeafRefContext.isReferenced()) {
66 rootBuilder.addReferencedByChild(childLeafRefContext,
67 childLeafRefContext.getNodeName());
72 // FIXME: it might be useful to merge these subtrees (i.e. referencing
73 // and referencedBy subtree)
75 return rootBuilder.build();
78 private LeafRefContext buildLeafRefContextReferencingTree(
79 final DataSchemaNode node, final Module currentModule) throws IOException,
80 LeafRefYangSyntaxErrorException {
82 final LeafRefContextBuilder currentLeafRefContextBuilder = new LeafRefContextBuilder(
83 node.getQName(), node.getPath(), schemaContext);
85 if (node instanceof DataNodeContainer) {
86 final DataNodeContainer dataNodeContainer = (DataNodeContainer) node;
87 final Collection<DataSchemaNode> childNodes = dataNodeContainer
90 for (final DataSchemaNode childNode : childNodes) {
91 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencingTree(
92 childNode, currentModule);
94 if (childLeafRefContext.hasReferencingChild()
95 || childLeafRefContext.isReferencing()) {
96 currentLeafRefContextBuilder.addReferencingChild(
98 childLeafRefContext.getNodeName());
101 } else if (node instanceof ChoiceSchemaNode) {
103 final ChoiceSchemaNode choice = (ChoiceSchemaNode) node;
104 final Set<ChoiceCaseNode> cases = choice.getCases();
105 // :FIXME choice without case
107 for (final ChoiceCaseNode caseNode : cases) {
108 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencingTree(
109 caseNode, currentModule);
111 if (childLeafRefContext.hasReferencingChild()
112 || childLeafRefContext.isReferencing()) {
113 currentLeafRefContextBuilder.addReferencingChild(
115 childLeafRefContext.getNodeName());
119 } else if (node instanceof LeafSchemaNode
120 || node instanceof LeafListSchemaNode) {
122 TypeDefinition<?> type = null;
124 if (node instanceof LeafSchemaNode) {
125 type = ((LeafSchemaNode) node).getType();
127 type = ((LeafListSchemaNode) node).getType();
130 // FIXME: fix case when type is e.g. typdef -> typedef -> leafref
131 if (type instanceof LeafrefTypeDefinition) {
132 final LeafrefTypeDefinition leafrefType = (LeafrefTypeDefinition) type;
133 final String leafRefPathString = leafrefType.getPathStatement()
136 currentLeafRefContextBuilder
137 .setLeafRefTargetPathString(leafRefPathString);
138 currentLeafRefContextBuilder.setReferencing(true);
140 final LeafRefPathParserImpl leafRefPathParser = new LeafRefPathParserImpl(
141 schemaContext, currentModule, node);
143 final ByteArrayInputStream leafRefPathInputStream = new ByteArrayInputStream(
144 leafRefPathString.getBytes(Charset.forName("UTF-8")));
145 final LeafRefPath leafRefPath = leafRefPathParser
146 .parseLeafRefPathSourceToSchemaPath(leafRefPathInputStream);
148 currentLeafRefContextBuilder.setLeafRefTargetPath(leafRefPath);
150 final LeafRefContext currentLeafRefContext = currentLeafRefContextBuilder
152 leafRefs.add(currentLeafRefContext);
153 return currentLeafRefContext;
157 return currentLeafRefContextBuilder.build();
160 private LeafRefContext buildLeafRefContextReferencedByTree(
161 final DataSchemaNode node, final Module currentModule) throws IOException,
162 LeafRefYangSyntaxErrorException {
164 final LeafRefContextBuilder currentLeafRefContextBuilder = new LeafRefContextBuilder(
165 node.getQName(), node.getPath(), schemaContext);
167 if (node instanceof DataNodeContainer) {
168 final DataNodeContainer dataNodeContainer = (DataNodeContainer) node;
169 final Collection<DataSchemaNode> childNodes = dataNodeContainer
172 for (final DataSchemaNode childNode : childNodes) {
173 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencedByTree(
174 childNode, currentModule);
176 if (childLeafRefContext.hasReferencedChild()
177 || childLeafRefContext.isReferenced()) {
178 currentLeafRefContextBuilder.addReferencedByChild(
180 childLeafRefContext.getNodeName());
183 } else if (node instanceof ChoiceSchemaNode) {
185 final ChoiceSchemaNode choice = (ChoiceSchemaNode) node;
186 final Set<ChoiceCaseNode> cases = choice.getCases();
188 for (final ChoiceCaseNode caseNode : cases) {
189 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencedByTree(
190 caseNode, currentModule);
192 if (childLeafRefContext.hasReferencedChild()
193 || childLeafRefContext.isReferenced()) {
194 currentLeafRefContextBuilder.addReferencedByChild(
196 childLeafRefContext.getNodeName());
200 } else if (node instanceof LeafSchemaNode
201 || node instanceof LeafListSchemaNode) {
203 final List<LeafRefContext> foundLeafRefs = getLeafRefsFor(node,
205 if (!foundLeafRefs.isEmpty()) {
206 currentLeafRefContextBuilder.setReferencedBy(true);
207 for (final LeafRefContext leafRef : foundLeafRefs) {
208 currentLeafRefContextBuilder.addReferencedByLeafRefCtx(
209 leafRef.getNodeName(), leafRef);
214 return currentLeafRefContextBuilder.build();
217 private List<LeafRefContext> getLeafRefsFor(final DataSchemaNode node,
218 final Module module) {
219 final LeafRefPath nodeXPath = LeafRefUtils.schemaPathToLeafRefPath(
220 node.getPath(), module);
222 final List<LeafRefContext> foundLeafRefs = new LinkedList<LeafRefContext>();
224 for (final LeafRefContext leafref : leafRefs) {
225 final LeafRefPath leafRefTargetPath = leafref
226 .getAbsoluteLeafRefTargetPath();
227 if (leafRefTargetPath.equals(nodeXPath)) {
228 foundLeafRefs.add(leafref);
232 return foundLeafRefs;