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;
16 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
17 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
18 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
19 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.Module;
23 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
24 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
25 import org.opendaylight.yangtools.yang.model.util.Leafref;
27 class LeafRefContextTreeBuilder {
28 private final SchemaContext schemaContext;
29 private final LinkedList<LeafRefContext> leafRefs;
31 public LeafRefContextTreeBuilder(final SchemaContext schemaContext) {
32 this.schemaContext = schemaContext;
33 this.leafRefs = new LinkedList<LeafRefContext>();
36 public LeafRefContext buildLeafRefContextTree() throws IOException,
37 LeafRefYangSyntaxErrorException {
38 final LeafRefContextBuilder rootBuilder = new LeafRefContextBuilder(
39 schemaContext.getQName(), schemaContext.getPath(),
42 final Set<Module> modules = schemaContext.getModules();
43 for (final Module module : modules) {
44 final Collection<DataSchemaNode> childNodes = module.getChildNodes();
45 for (final DataSchemaNode childNode : childNodes) {
46 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencingTree(
49 if (childLeafRefContext.hasReferencingChild()
50 || childLeafRefContext.isReferencing()) {
51 rootBuilder.addReferencingChild(childLeafRefContext,
52 childLeafRefContext.getNodeName());
57 for (final Module module : modules) {
58 final Collection<DataSchemaNode> childNodes = module.getChildNodes();
59 for (final DataSchemaNode childNode : childNodes) {
60 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencedByTree(
63 if (childLeafRefContext.hasReferencedChild()
64 || childLeafRefContext.isReferenced()) {
65 rootBuilder.addReferencedByChild(childLeafRefContext,
66 childLeafRefContext.getNodeName());
71 // FIXME: it might be useful to merge these subtrees (i.e. referencing
72 // and referencedBy subtree)
74 return rootBuilder.build();
77 private LeafRefContext buildLeafRefContextReferencingTree(
78 final DataSchemaNode node, final Module currentModule) throws IOException,
79 LeafRefYangSyntaxErrorException {
81 final LeafRefContextBuilder currentLeafRefContextBuilder = new LeafRefContextBuilder(
82 node.getQName(), node.getPath(), schemaContext);
84 if (node instanceof DataNodeContainer) {
85 final DataNodeContainer dataNodeContainer = (DataNodeContainer) node;
86 final Collection<DataSchemaNode> childNodes = dataNodeContainer
89 for (final DataSchemaNode childNode : childNodes) {
90 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencingTree(
91 childNode, currentModule);
93 if (childLeafRefContext.hasReferencingChild()
94 || childLeafRefContext.isReferencing()) {
95 currentLeafRefContextBuilder.addReferencingChild(
97 childLeafRefContext.getNodeName());
100 } else if (node instanceof ChoiceSchemaNode) {
102 final ChoiceSchemaNode choice = (ChoiceSchemaNode) node;
103 final Set<ChoiceCaseNode> cases = choice.getCases();
104 // :FIXME choice without case
106 for (final ChoiceCaseNode caseNode : cases) {
107 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencingTree(
108 caseNode, currentModule);
110 if (childLeafRefContext.hasReferencingChild()
111 || childLeafRefContext.isReferencing()) {
112 currentLeafRefContextBuilder.addReferencingChild(
114 childLeafRefContext.getNodeName());
118 } else if (node instanceof LeafSchemaNode
119 || node instanceof LeafListSchemaNode) {
121 TypeDefinition<?> type = null;
123 if (node instanceof LeafSchemaNode) {
124 type = ((LeafSchemaNode) node).getType();
126 type = ((LeafListSchemaNode) node).getType();
129 // FIXME: fix case when type is e.g. typdef -> typedef -> leafref
130 if (type instanceof Leafref) {
131 final Leafref leafrefType = (Leafref) type;
132 final String leafRefPathString = leafrefType.getPathStatement()
135 currentLeafRefContextBuilder
136 .setLeafRefTargetPathString(leafRefPathString);
137 currentLeafRefContextBuilder.setReferencing(true);
139 final LeafRefPathParserImpl leafRefPathParser = new LeafRefPathParserImpl(
140 schemaContext, currentModule, node);
142 final ByteArrayInputStream leafRefPathInputStream = new ByteArrayInputStream(
143 leafRefPathString.getBytes(Charset.forName("UTF-8")));
144 final LeafRefPath leafRefPath = leafRefPathParser
145 .parseLeafRefPathSourceToSchemaPath(leafRefPathInputStream);
147 currentLeafRefContextBuilder.setLeafRefTargetPath(leafRefPath);
149 final LeafRefContext currentLeafRefContext = currentLeafRefContextBuilder
151 leafRefs.add(currentLeafRefContext);
152 return currentLeafRefContext;
156 return currentLeafRefContextBuilder.build();
159 private LeafRefContext buildLeafRefContextReferencedByTree(
160 final DataSchemaNode node, final Module currentModule) throws IOException,
161 LeafRefYangSyntaxErrorException {
163 final LeafRefContextBuilder currentLeafRefContextBuilder = new LeafRefContextBuilder(
164 node.getQName(), node.getPath(), schemaContext);
166 if (node instanceof DataNodeContainer) {
167 final DataNodeContainer dataNodeContainer = (DataNodeContainer) node;
168 final Collection<DataSchemaNode> childNodes = dataNodeContainer
171 for (final DataSchemaNode childNode : childNodes) {
172 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencedByTree(
173 childNode, currentModule);
175 if (childLeafRefContext.hasReferencedChild()
176 || childLeafRefContext.isReferenced()) {
177 currentLeafRefContextBuilder.addReferencedByChild(
179 childLeafRefContext.getNodeName());
182 } else if (node instanceof ChoiceSchemaNode) {
184 final ChoiceSchemaNode choice = (ChoiceSchemaNode) node;
185 final Set<ChoiceCaseNode> cases = choice.getCases();
187 for (final ChoiceCaseNode caseNode : cases) {
188 final LeafRefContext childLeafRefContext = buildLeafRefContextReferencedByTree(
189 caseNode, currentModule);
191 if (childLeafRefContext.hasReferencedChild()
192 || childLeafRefContext.isReferenced()) {
193 currentLeafRefContextBuilder.addReferencedByChild(
195 childLeafRefContext.getNodeName());
199 } else if (node instanceof LeafSchemaNode
200 || node instanceof LeafListSchemaNode) {
202 final LinkedList<LeafRefContext> foundLeafRefs = getLeafRefsFor(node,
204 if (!foundLeafRefs.isEmpty()) {
205 currentLeafRefContextBuilder.setReferencedBy(true);
206 for (final LeafRefContext leafRef : foundLeafRefs) {
207 currentLeafRefContextBuilder.addReferencedByLeafRefCtx(
208 leafRef.getNodeName(), leafRef);
213 return currentLeafRefContextBuilder.build();
216 private LinkedList<LeafRefContext> getLeafRefsFor(final DataSchemaNode node,
217 final Module module) {
218 final LeafRefPath nodeXPath = LeafRefUtils.schemaPathToLeafRefPath(
219 node.getPath(), module);
221 final LinkedList<LeafRefContext> foundLeafRefs = new LinkedList<LeafRefContext>();
223 for (final LeafRefContext leafref : leafRefs) {
224 final LeafRefPath leafRefTargetPath = leafref
225 .getAbsoluteLeafRefTargetPath();
226 if (leafRefTargetPath.equals(nodeXPath)) {
227 foundLeafRefs.add(leafref);
231 return foundLeafRefs;
234 // private LeafRefContext buildLeafRefContextTreeFor(LeafRefContext parent,
237 // Collection<DataSchemaNode> childNodes = module.getChildNodes();
238 // for (DataSchemaNode childNode : childNodes) {
239 // LeafRefContext childLeafRefContext = buildLeafRefContextTreeFor(parent,
242 // if(childLeafRefContext.hasReferencedByChild() ||
243 // childLeafRefContext.isReferencedBy()) {
244 // parent.addReferencedByChild(childLeafRefContext,
245 // childLeafRefContext.getCurrentNodeQName());
247 // if(childLeafRefContext.hasReferencingChild() ||
248 // childLeafRefContext.isReferencing()) {
249 // parent.addReferencingChild(childLeafRefContext,
250 // childLeafRefContext.getCurrentNodeQName());