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.io.ByteArrayOutputStream;
12 import java.io.FileNotFoundException;
13 import java.io.IOException;
14 import java.io.InputStream;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collection;
19 import java.util.Date;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.List;
25 import java.util.TreeMap;
27 import org.apache.commons.io.IOUtils;
28 import org.opendaylight.yangtools.yang.common.QName;
29 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
31 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
32 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
34 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
36 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.Module;
40 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
41 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
42 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
43 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
44 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
45 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
46 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
47 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
48 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
49 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
50 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
51 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
52 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingMember;
53 import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
54 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
55 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
56 import org.opendaylight.yangtools.yang.parser.util.NamedByteArrayInputStream;
57 import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
58 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 import com.google.common.base.Function;
63 import com.google.common.base.Optional;
64 import com.google.common.base.Preconditions;
65 import com.google.common.base.Splitter;
66 import com.google.common.collect.Collections2;
67 import com.google.common.io.ByteSource;
69 public final class BuilderUtils {
71 private static final Logger LOG = LoggerFactory.getLogger(BuilderUtils.class);
72 private static final Splitter SLASH_SPLITTER = Splitter.on('/');
73 private static final Splitter COLON_SPLITTER = Splitter.on(':');
74 private static final String INPUT = "input";
75 private static final String OUTPUT = "output";
77 private BuilderUtils() {
80 public static Collection<ByteSource> streamsToByteSources(final Collection<InputStream> streams) throws IOException {
81 Collection<ByteSource> result = new HashSet<>();
82 for (InputStream stream : streams) {
83 result.add(new ByteSourceImpl(stream));
88 public static ByteSource fileToByteSource(final File file) {
89 return new ByteSource() {
91 public InputStream openStream() throws IOException {
92 return new NamedFileInputStream(file, file.getAbsolutePath());
97 public static Collection<ByteSource> filesToByteSources(final Collection<File> streams)
98 throws FileNotFoundException {
99 return Collections2.transform(streams, new Function<File, ByteSource>() {
101 public ByteSource apply(final File input) {
102 return new ByteSource() {
104 public InputStream openStream() throws IOException {
105 return new NamedFileInputStream(input, input.getAbsolutePath());
113 * Set string representation of source to ModuleBuilder.
115 * @param sourceToBuilder
116 * source to module mapping
118 public static void setSourceToBuilder(final Map<ByteSource, ModuleBuilder> sourceToBuilder) throws IOException {
119 for (Map.Entry<ByteSource, ModuleBuilder> entry : sourceToBuilder.entrySet()) {
120 ModuleBuilder builder = entry.getValue();
121 ByteSource source = entry.getKey();
123 String content = null;
124 InputStream stream = null;
126 stream = source.openStream();
127 content = IOUtils.toString(stream);
129 if (stream != null) {
132 } catch (IOException e) {
134 * Failed stream close does not prevent us from
135 * continuing to work correctly, we just report that and
138 LOG.warn("Failed to close stream {}. Leaving stream unclosed.", stream, e);
142 builder.setSource(content);
147 * Create new SchemaPath from given path and qname.
152 * one or more qnames added to base path
153 * @return new SchemaPath from given path and qname
155 * @deprecated Use {@link SchemaPath#createChild(QName...)} instead.
158 public static SchemaPath createSchemaPath(final SchemaPath schemaPath, final QName... qname) {
159 List<QName> path = new ArrayList<>(schemaPath.getPath());
160 path.addAll(Arrays.asList(qname));
161 return SchemaPath.create(path, schemaPath.isAbsolute());
165 * Get module import referenced by given prefix.
170 * prefix associated with import
171 * @return ModuleImport based on given prefix
173 public static ModuleImport getModuleImport(final ModuleBuilder builder, final String prefix) {
174 for (ModuleImport mi : builder.getModuleImports()) {
175 if (mi.getPrefix().equals(prefix)) {
184 * Find dependent module based on given prefix
187 * all available modules
191 * target module prefix
193 * current line in yang model
194 * @return module builder if found, null otherwise
196 public static ModuleBuilder findModuleFromBuilders(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
197 final ModuleBuilder module, final String prefix, final int line) {
198 ModuleBuilder dependentModule = null;
199 Date dependentModuleRevision = null;
201 if (prefix == null) {
202 dependentModule = module;
203 } else if (prefix.equals(module.getPrefix())) {
204 dependentModule = module;
206 ModuleImport dependentModuleImport = getModuleImport(module, prefix);
207 if (dependentModuleImport == null) {
208 throw new YangParseException(module.getName(), line, "No import found with prefix '" + prefix + "'.");
210 String dependentModuleName = dependentModuleImport.getModuleName();
211 dependentModuleRevision = dependentModuleImport.getRevision();
213 TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
214 if (moduleBuildersByRevision == null) {
217 if (dependentModuleRevision == null) {
218 dependentModule = moduleBuildersByRevision.lastEntry().getValue();
220 dependentModule = moduleBuildersByRevision.get(dependentModuleRevision);
223 return dependentModule;
227 * Find module from context based on prefix.
231 * @param currentModule
234 * current prefix used to reference dependent module
236 * current line in yang model
237 * @return module based on given prefix if found in context, null otherwise
239 public static Module findModuleFromContext(final SchemaContext context, final ModuleBuilder currentModule,
240 final String prefix, final int line) {
241 if (context == null) {
242 throw new YangParseException(currentModule.getName(), line, "Cannot find module with prefix '" + prefix
245 TreeMap<Date, Module> modulesByRevision = new TreeMap<>();
247 ModuleImport dependentModuleImport = BuilderUtils.getModuleImport(currentModule, prefix);
248 if (dependentModuleImport == null) {
249 throw new YangParseException(currentModule.getName(), line, "No import found with prefix '" + prefix + "'.");
251 String dependentModuleName = dependentModuleImport.getModuleName();
252 Date dependentModuleRevision = dependentModuleImport.getRevision();
254 for (Module contextModule : context.getModules()) {
255 if (contextModule.getName().equals(dependentModuleName)) {
256 Date revision = contextModule.getRevision();
257 if (revision == null) {
258 revision = new Date(0L);
260 modulesByRevision.put(revision, contextModule);
264 Module result = null;
265 if (dependentModuleRevision == null) {
266 result = modulesByRevision.get(modulesByRevision.firstKey());
268 result = modulesByRevision.get(dependentModuleRevision);
274 * Parse XPath string.
278 * @return SchemaPath from given String
280 public static SchemaPath parseXPathString(final String xpathString) {
281 final boolean absolute = xpathString.indexOf('/') == 0;
283 final List<QName> path = new ArrayList<QName>();
284 for (String pathElement : SLASH_SPLITTER.split(xpathString)) {
285 if (pathElement.length() > 0) {
286 final Iterator<String> it = COLON_SPLITTER.split(pathElement).iterator();
287 final String s = it.next();
291 name = new QName(null, null, s, it.next());
293 name = new QName(null, null, null, s);
298 return SchemaPath.create(path, absolute);
302 * Add all augment's child nodes to given target.
305 * builder of augment statement
307 * augmentation target node
309 public static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final Builder target) {
310 if (target instanceof DataNodeContainerBuilder) {
311 fillAugmentTarget(augment, (DataNodeContainerBuilder) target);
312 } else if (target instanceof ChoiceBuilder) {
313 fillAugmentTarget(augment, (ChoiceBuilder) target);
315 throw new YangParseException(
316 augment.getModuleName(),
318 "Error in augment parsing: The target node MUST be either a container, list, choice, case, input, output, or notification node.");
323 * Add all augment's child nodes to given target.
326 * builder of augment statement
328 * augmentation target node
330 private static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final DataNodeContainerBuilder target) {
331 for (DataSchemaNodeBuilder child : augment.getChildNodeBuilders()) {
332 DataSchemaNodeBuilder childCopy = CopyUtils.copy(child, target, false);
333 if (augment.getParent() instanceof UsesNodeBuilder) {
334 setNodeAddedByUses(childCopy);
336 setNodeAugmenting(childCopy);
338 target.addChildNode(childCopy);
339 } catch (YangParseException e) {
341 // more descriptive message
342 throw new YangParseException(augment.getModuleName(), augment.getLine(),
343 "Failed to perform augmentation: " + e.getMessage());
349 * Add all augment's child nodes to given target.
352 * builder of augment statement
354 * augmentation target choice node
356 private static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final ChoiceBuilder target) {
357 for (DataSchemaNodeBuilder builder : augment.getChildNodeBuilders()) {
358 DataSchemaNodeBuilder childCopy = CopyUtils.copy(builder, target, false);
359 if (augment.getParent() instanceof UsesNodeBuilder) {
360 setNodeAddedByUses(childCopy);
362 setNodeAugmenting(childCopy);
363 target.addCase(childCopy);
365 for (UsesNodeBuilder usesNode : augment.getUsesNodeBuilders()) {
366 if (usesNode != null) {
367 throw new YangParseException(augment.getModuleName(), augment.getLine(),
368 "Error in augment parsing: cannot augment choice with nodes from grouping");
374 * Set augmenting flag to true for node and all its child nodes.
378 private static void setNodeAugmenting(final DataSchemaNodeBuilder node) {
379 node.setAugmenting(true);
380 if (node instanceof DataNodeContainerBuilder) {
381 DataNodeContainerBuilder dataNodeChild = (DataNodeContainerBuilder) node;
382 for (DataSchemaNodeBuilder inner : dataNodeChild.getChildNodeBuilders()) {
383 setNodeAugmenting(inner);
385 } else if (node instanceof ChoiceBuilder) {
386 ChoiceBuilder choiceChild = (ChoiceBuilder) node;
387 for (ChoiceCaseBuilder inner : choiceChild.getCases()) {
388 setNodeAugmenting(inner);
394 * Set addedByUses flag to true for node and all its child nodes.
398 public static void setNodeAddedByUses(final GroupingMember node) {
399 node.setAddedByUses(true);
400 if (node instanceof DataNodeContainerBuilder) {
401 DataNodeContainerBuilder dataNodeChild = (DataNodeContainerBuilder) node;
402 for (DataSchemaNodeBuilder inner : dataNodeChild.getChildNodeBuilders()) {
403 setNodeAddedByUses(inner);
405 } else if (node instanceof ChoiceBuilder) {
406 ChoiceBuilder choiceChild = (ChoiceBuilder) node;
407 for (ChoiceCaseBuilder inner : choiceChild.getCases()) {
408 setNodeAddedByUses(inner);
414 * Set config flag to new value.
421 public static void setNodeConfig(final DataSchemaNodeBuilder node, final Boolean config) {
422 if (node instanceof ContainerSchemaNodeBuilder || node instanceof LeafSchemaNodeBuilder
423 || node instanceof LeafListSchemaNodeBuilder || node instanceof ListSchemaNodeBuilder
424 || node instanceof ChoiceBuilder || node instanceof AnyXmlBuilder) {
425 node.setConfiguration(config);
427 if (node instanceof DataNodeContainerBuilder) {
428 DataNodeContainerBuilder dataNodeChild = (DataNodeContainerBuilder) node;
429 for (DataSchemaNodeBuilder inner : dataNodeChild.getChildNodeBuilders()) {
430 setNodeConfig(inner, config);
432 } else if (node instanceof ChoiceBuilder) {
433 ChoiceBuilder choiceChild = (ChoiceBuilder) node;
434 for (ChoiceCaseBuilder inner : choiceChild.getCases()) {
435 setNodeConfig(inner, config);
440 public static DataSchemaNodeBuilder findSchemaNode(final List<QName> path, final SchemaNodeBuilder parentNode) {
441 DataSchemaNodeBuilder node = null;
442 SchemaNodeBuilder parent = parentNode;
444 while (i < path.size()) {
445 String name = path.get(i).getLocalName();
446 if (parent instanceof DataNodeContainerBuilder) {
447 node = ((DataNodeContainerBuilder) parent).getDataChildByName(name);
448 } else if (parent instanceof ChoiceBuilder) {
449 node = ((ChoiceBuilder) parent).getCaseNodeByName(name);
450 } else if (parent instanceof RpcDefinitionBuilder) {
451 if ("input".equals(name)) {
452 node = ((RpcDefinitionBuilder) parent).getInput();
453 } else if ("output".equals(name)) {
454 node = ((RpcDefinitionBuilder) parent).getOutput();
462 if (i < path.size() - 1) {
473 * Find a builder for node in data namespace of YANG module.
475 * Search is performed on full QName equals, this means builders and schema
476 * path MUST be resolved against imports and their namespaces.
478 * Search is done in data namespace, this means notification, rpc
479 * definitions and top level data definitions are considered as top-level
480 * items, from which it is possible to traverse.
484 * Schema Path to node
486 * ModuleBuilder to start lookup in
487 * @return Node Builder if found, {@link Optional#absent()} otherwise.
489 public static Optional<SchemaNodeBuilder> findSchemaNodeInModule(final SchemaPath schemaPath,
490 final ModuleBuilder module) {
491 Iterator<QName> path = schemaPath.getPathFromRoot().iterator();
492 Preconditions.checkArgument(path.hasNext(), "Schema Path must contain at least one element.");
493 QName first = path.next();
494 Optional<SchemaNodeBuilder> currentNode = getDataNamespaceChild(module, first);
496 while (currentNode.isPresent() && path.hasNext()) {
497 currentNode = findDataChild(currentNode.get(), path.next());
502 private static Optional<SchemaNodeBuilder> findDataChild(final SchemaNodeBuilder parent, final QName child) {
503 if (parent instanceof DataNodeContainerBuilder) {
504 return castOptional(SchemaNodeBuilder.class,
505 findDataChildInDataNodeContainer((DataNodeContainerBuilder) parent, child));
506 } else if (parent instanceof ChoiceBuilder) {
507 return castOptional(SchemaNodeBuilder.class, findCaseInChoice((ChoiceBuilder) parent, child));
508 } else if (parent instanceof RpcDefinitionBuilder) {
509 return castOptional(SchemaNodeBuilder.class, findContainerInRpc((RpcDefinitionBuilder) parent, child));
512 LOG.trace("Child {} not found in node {}", child, parent);
513 return Optional.absent();
518 * Casts optional from one argument to other.
521 * Class to be checked
526 private static <T> Optional<T> castOptional(final Class<T> cls, final Optional<?> optional) {
527 if (optional.isPresent()) {
528 Object value = optional.get();
529 if (cls.isInstance(value)) {
530 @SuppressWarnings("unchecked")
531 // Actually checked by outer if
532 T casted = (T) value;
533 return Optional.of(casted);
536 return Optional.absent();
541 * Gets input / output container from {@link RpcDefinitionBuilder} if QName
546 * RPC Definition builder
549 * @return Optional of input/output if defined and QName is input/output.
550 * Otherwise {@link Optional#absent()}.
552 private static Optional<ContainerSchemaNodeBuilder> findContainerInRpc(final RpcDefinitionBuilder parent, final QName child) {
553 if (INPUT.equals(child.getLocalName())) {
554 return Optional.of(parent.getInput());
555 } else if (OUTPUT.equals(child.getLocalName())) {
556 return Optional.of(parent.getOutput());
558 LOG.trace("Child {} not found in node {}", child, parent);
559 return Optional.absent();
563 * Finds case by QName in {@link ChoiceBuilder}
567 * DataNodeContainer in which lookup should be performed
570 * @return Optional of child if found.
573 private static Optional<ChoiceCaseBuilder> findCaseInChoice(final ChoiceBuilder parent, final QName child) {
574 for (ChoiceCaseBuilder caze : parent.getCases()) {
575 if (caze.getQName().equals(child)) {
576 return Optional.of(caze);
579 LOG.trace("Child {} not found in node {}", child, parent);
580 return Optional.absent();
584 * Finds direct child by QName in {@link DataNodeContainerBuilder}
588 * DataNodeContainer in which lookup should be performed
591 * @return Optional of child if found.
593 private static Optional<DataSchemaNodeBuilder> findDataChildInDataNodeContainer(final DataNodeContainerBuilder parent,
595 for (DataSchemaNodeBuilder childNode : parent.getChildNodeBuilders()) {
596 if (childNode.getQName().equals(child)) {
597 return Optional.of(childNode);
600 LOG.trace("Child {} not found in node {}", child, parent);
601 return Optional.absent();
606 * Find a child builder for node in data namespace of YANG module.
608 * Search is performed on full QName equals, this means builders and schema
609 * path MUST be resolved against imports and their namespaces.
611 * Search is done in data namespace, this means notification, rpc
612 * definitions and top level data definitions are considered as top-level
613 * items, from which it is possible to traverse.
619 * ModuleBuilder to start lookup in
620 * @return Node Builder if found, {@link Optional#absent()} otherwise.
622 private static Optional<SchemaNodeBuilder> getDataNamespaceChild(final ModuleBuilder module, final QName child) {
624 * First we do lookup in data tree, if node is found we return it.
626 final Optional<SchemaNodeBuilder> dataTreeNode = getDataChildByQName(module, child);
627 if (dataTreeNode.isPresent()) {
632 * We lookup in notifications
634 Set<NotificationBuilder> notifications = module.getAddedNotifications();
635 for (NotificationBuilder notification : notifications) {
636 if (notification.getQName().equals(child)) {
637 return Optional.<SchemaNodeBuilder> of(notification);
644 Set<RpcDefinitionBuilder> rpcs = module.getAddedRpcs();
645 for (RpcDefinitionBuilder rpc : rpcs) {
646 if (rpc.getQName().equals(child)) {
647 return Optional.<SchemaNodeBuilder> of(rpc);
650 LOG.trace("Child {} not found in data namespace of module {}", child, module);
651 return Optional.absent();
654 private static Optional<SchemaNodeBuilder> getDataChildByQName(final DataNodeContainerBuilder builder, final QName child) {
655 for (DataSchemaNodeBuilder childNode : builder.getChildNodeBuilders()) {
656 if (childNode.getQName().equals(child)) {
657 return Optional.<SchemaNodeBuilder> of(childNode);
660 LOG.trace("Child {} not found in node {}", child, builder);
661 return Optional.absent();
665 * Find augment target node and perform augmentation.
668 * @param firstNodeParent
669 * parent of first node in path
671 * path to augment target
672 * @return true if augmentation process succeed, false otherwise
674 public static boolean processAugmentation(final AugmentationSchemaBuilder augment,
675 final ModuleBuilder firstNodeParent) {
676 Optional<SchemaNodeBuilder> potentialTargetNode = findSchemaNodeInModule(augment.getTargetNodeSchemaPath(),
678 if (!potentialTargetNode.isPresent()) {
681 SchemaNodeBuilder targetNode = potentialTargetNode.get();
682 fillAugmentTarget(augment, targetNode);
683 Preconditions.checkState(targetNode instanceof AugmentationTargetBuilder,
684 "Node refered by augmentation must be valid augmentation target");
685 ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
686 augment.setResolved(true);
690 public static IdentitySchemaNodeBuilder findBaseIdentity(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
691 final ModuleBuilder module, final String baseString, final int line) {
693 // FIXME: optimize indexOf() away?
694 if (baseString.indexOf(':') != -1) {
695 final Iterator<String> it = COLON_SPLITTER.split(baseString).iterator();
696 final String prefix = it.next();
697 final String name = it.next();
700 throw new YangParseException(module.getName(), line, "Failed to parse identityref base: " + baseString);
703 ModuleBuilder dependentModule = findModuleFromBuilders(modules, module, prefix, line);
704 if (dependentModule == null) {
708 return findIdentity(dependentModule.getAddedIdentities(), name);
710 return findIdentity(module.getAddedIdentities(), baseString);
714 public static IdentitySchemaNodeBuilder findIdentity(final Set<IdentitySchemaNodeBuilder> identities,
716 for (IdentitySchemaNodeBuilder identity : identities) {
717 if (identity.getQName().getLocalName().equals(name)) {
725 * Get module in which this node is defined.
728 * @return builder of module where this node is defined
730 public static ModuleBuilder getParentModule(final Builder node) {
731 if (node instanceof ModuleBuilder) {
732 return (ModuleBuilder) node;
734 Builder parent = node.getParent();
735 while (!(parent instanceof ModuleBuilder)) {
736 parent = parent.getParent();
738 Preconditions.checkState(parent instanceof ModuleBuilder);
739 ModuleBuilder parentModule = (ModuleBuilder) parent;
740 if (parentModule.isSubmodule()) {
741 parentModule = parentModule.getParent();
746 public static Set<DataSchemaNodeBuilder> wrapChildNodes(final String moduleName, final int line,
747 final Set<DataSchemaNode> nodes, final SchemaPath parentPath, final URI ns, final Date rev,
749 Set<DataSchemaNodeBuilder> result = new HashSet<>();
751 for (DataSchemaNode node : nodes) {
752 QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
753 DataSchemaNodeBuilder wrapped = wrapChildNode(moduleName, line, node, parentPath, qname);
759 public static DataSchemaNodeBuilder wrapChildNode(final String moduleName, final int line,
760 final DataSchemaNode node, final SchemaPath parentPath, final QName qname) {
762 final SchemaPath schemaPath = parentPath.createChild(qname);
764 if (node instanceof AnyXmlSchemaNode) {
765 return new AnyXmlBuilder(moduleName, line, qname, schemaPath, ((AnyXmlSchemaNode) node));
766 } else if (node instanceof ChoiceNode) {
767 return new ChoiceBuilder(moduleName, line, qname, schemaPath, ((ChoiceNode) node));
768 } else if (node instanceof ContainerSchemaNode) {
769 return new ContainerSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((ContainerSchemaNode) node));
770 } else if (node instanceof LeafSchemaNode) {
771 return new LeafSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((LeafSchemaNode) node));
772 } else if (node instanceof LeafListSchemaNode) {
773 return new LeafListSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((LeafListSchemaNode) node));
774 } else if (node instanceof ListSchemaNode) {
775 return new ListSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((ListSchemaNode) node));
776 } else if (node instanceof ChoiceCaseNode) {
777 return new ChoiceCaseBuilder(moduleName, line, qname, schemaPath, ((ChoiceCaseNode) node));
779 throw new YangParseException(moduleName, line, "Failed to copy node: Unknown type of DataSchemaNode: "
784 public static Set<GroupingBuilder> wrapGroupings(final String moduleName, final int line,
785 final Set<GroupingDefinition> nodes, final SchemaPath parentPath, final URI ns, final Date rev,
787 Set<GroupingBuilder> result = new HashSet<>();
788 for (GroupingDefinition node : nodes) {
789 QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
790 SchemaPath schemaPath = parentPath.createChild(qname);
791 result.add(new GroupingBuilderImpl(moduleName, line, qname, schemaPath, node));
796 public static Set<TypeDefinitionBuilder> wrapTypedefs(final String moduleName, final int line,
797 final DataNodeContainer dataNode, final SchemaPath parentPath, final URI ns, final Date rev,
799 Set<TypeDefinition<?>> nodes = dataNode.getTypeDefinitions();
800 Set<TypeDefinitionBuilder> result = new HashSet<>();
801 for (TypeDefinition<?> node : nodes) {
802 QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
803 List<QName> path = new ArrayList<>(parentPath.getPath());
805 SchemaPath schemaPath = SchemaPath.create(path, parentPath.isAbsolute());
806 result.add(new TypeDefinitionBuilderImpl(moduleName, line, qname, schemaPath, ((ExtendedType) node)));
811 public static List<UnknownSchemaNodeBuilderImpl> wrapUnknownNodes(final String moduleName, final int line,
812 final List<UnknownSchemaNode> nodes, final SchemaPath parentPath, final URI ns, final Date rev,
814 List<UnknownSchemaNodeBuilderImpl> result = new ArrayList<>();
815 for (UnknownSchemaNode node : nodes) {
816 QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
817 List<QName> path = new ArrayList<>(parentPath.getPath());
819 SchemaPath schemaPath = SchemaPath.create(path, parentPath.isAbsolute());
820 result.add(new UnknownSchemaNodeBuilderImpl(moduleName, line, qname, schemaPath, node));
825 private static final class ByteSourceImpl extends ByteSource {
826 private final String toString;
827 private final ByteArrayOutputStream output = new ByteArrayOutputStream();
829 private ByteSourceImpl(final InputStream input) throws IOException {
830 toString = input.toString();
831 IOUtils.copy(input, output);
835 public InputStream openStream() throws IOException {
836 return new NamedByteArrayInputStream(output.toByteArray(), toString);