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 com.google.common.base.Function;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.base.Splitter;
14 import com.google.common.collect.Collections2;
15 import com.google.common.io.ByteSource;
17 import java.io.ByteArrayOutputStream;
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Date;
25 import java.util.HashSet;
26 import java.util.Iterator;
27 import java.util.List;
30 import java.util.TreeMap;
32 import org.apache.commons.io.IOUtils;
33 import org.opendaylight.yangtools.yang.common.QName;
34 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
36 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
37 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
39 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
41 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
42 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
43 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.Module;
45 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
46 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
47 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
48 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
49 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
50 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
51 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
52 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
53 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
54 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
55 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
56 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
57 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingMember;
58 import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
59 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
60 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
61 import org.opendaylight.yangtools.yang.parser.util.NamedByteArrayInputStream;
62 import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
63 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
67 public final class BuilderUtils {
69 private static final Logger LOG = LoggerFactory.getLogger(BuilderUtils.class);
70 private static final Splitter SLASH_SPLITTER = Splitter.on('/').omitEmptyStrings();
71 private static final Splitter COLON_SPLITTER = Splitter.on(':');
72 private static final Date NULL_DATE = new Date(0L);
73 private static final String INPUT = "input";
74 private static final String OUTPUT = "output";
76 private BuilderUtils() {
79 public static Collection<ByteSource> streamsToByteSources(final Collection<InputStream> streams) throws IOException {
80 Collection<ByteSource> result = new HashSet<>();
81 for (InputStream stream : streams) {
82 result.add(new ByteSourceImpl(stream));
87 public static ByteSource fileToByteSource(final File file) {
88 return new ByteSource() {
90 public InputStream openStream() throws IOException {
91 return new NamedFileInputStream(file, file.getAbsolutePath());
96 public static Collection<ByteSource> filesToByteSources(final Collection<File> streams)
97 throws FileNotFoundException {
98 return Collections2.transform(streams, new Function<File, ByteSource>() {
100 public ByteSource apply(final File input) {
101 return new ByteSource() {
103 public InputStream openStream() throws IOException {
104 return new NamedFileInputStream(input, input.getAbsolutePath());
112 * Create new SchemaPath from given path and qname.
117 * one or more qnames added to base path
118 * @return new SchemaPath from given path and qname
120 * @deprecated Use {@link SchemaPath#createChild(QName...)} instead.
123 public static SchemaPath createSchemaPath(final SchemaPath schemaPath, final QName... qname) {
124 return schemaPath.createChild(qname);
128 * Get module import referenced by given prefix.
133 * prefix associated with import
134 * @return ModuleImport based on given prefix
136 private static ModuleImport getModuleImport(final ModuleBuilder builder, final String prefix) {
137 for (ModuleImport mi : builder.getModuleImports()) {
138 if (mi.getPrefix().equals(prefix)) {
147 * Find dependent module based on given prefix
150 * all available modules
154 * target module prefix
156 * current line in yang model
157 * @return module builder if found, null otherwise
159 public static ModuleBuilder findModuleFromBuilders(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
160 final ModuleBuilder module, final String prefix, final int line) {
161 ModuleBuilder dependentModule;
162 Date dependentModuleRevision;
164 if (prefix == null) {
165 dependentModule = module;
166 } else if (prefix.equals(module.getPrefix())) {
167 dependentModule = module;
169 ModuleImport dependentModuleImport = getModuleImport(module, prefix);
170 if (dependentModuleImport == null) {
171 throw new YangParseException(module.getName(), line, "No import found with prefix '" + prefix + "'.");
173 String dependentModuleName = dependentModuleImport.getModuleName();
174 dependentModuleRevision = dependentModuleImport.getRevision();
176 TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
177 if (moduleBuildersByRevision == null) {
180 if (dependentModuleRevision == null) {
181 dependentModule = moduleBuildersByRevision.lastEntry().getValue();
183 dependentModule = moduleBuildersByRevision.get(dependentModuleRevision);
186 return dependentModule;
190 * Find module from context based on prefix.
194 * @param currentModule
197 * current prefix used to reference dependent module
199 * current line in yang model
200 * @return module based on given prefix if found in context, null otherwise
202 public static Module findModuleFromContext(final SchemaContext context, final ModuleBuilder currentModule,
203 final String prefix, final int line) {
204 if (context == null) {
205 throw new YangParseException(currentModule.getName(), line, "Cannot find module with prefix '" + prefix
208 TreeMap<Date, Module> modulesByRevision = new TreeMap<>();
210 ModuleImport dependentModuleImport = BuilderUtils.getModuleImport(currentModule, prefix);
211 if (dependentModuleImport == null) {
212 throw new YangParseException(currentModule.getName(), line, "No import found with prefix '" + prefix + "'.");
214 String dependentModuleName = dependentModuleImport.getModuleName();
215 Date dependentModuleRevision = dependentModuleImport.getRevision();
217 for (Module contextModule : context.getModules()) {
218 if (contextModule.getName().equals(dependentModuleName)) {
219 Date revision = contextModule.getRevision();
220 if (revision == null) {
221 revision = NULL_DATE;
223 modulesByRevision.put(revision, contextModule);
228 if (dependentModuleRevision == null) {
229 result = modulesByRevision.get(modulesByRevision.firstKey());
231 result = modulesByRevision.get(dependentModuleRevision);
237 * Parse XPath string.
241 * @return SchemaPath from given String
243 public static SchemaPath parseXPathString(final String xpathString) {
244 final boolean absolute = !xpathString.isEmpty() && xpathString.charAt(0) == '/';
246 final List<QName> path = new ArrayList<>();
247 for (String pathElement : SLASH_SPLITTER.split(xpathString)) {
248 final Iterator<String> it = COLON_SPLITTER.split(pathElement).iterator();
249 final String s = it.next();
253 name = new QName(null, null, s, it.next());
255 name = new QName(null, null, null, s);
259 return SchemaPath.create(path, absolute);
263 * Add all augment's child nodes to given target.
266 * builder of augment statement
268 * augmentation target node
270 public static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final Builder target) {
271 if (target instanceof DataNodeContainerBuilder) {
272 fillAugmentTarget(augment, (DataNodeContainerBuilder) target);
273 } else if (target instanceof ChoiceBuilder) {
274 fillAugmentTarget(augment, (ChoiceBuilder) target);
276 throw new YangParseException(
277 augment.getModuleName(),
279 "Error in augment parsing: The target node MUST be either a container, list, choice, case, input, output, or notification node.");
284 * Add all augment's child nodes to given target.
287 * builder of augment statement
289 * augmentation target node
291 private static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final DataNodeContainerBuilder target) {
292 for (DataSchemaNodeBuilder child : augment.getChildNodeBuilders()) {
293 DataSchemaNodeBuilder childCopy = CopyUtils.copy(child, target, false);
294 if (augment.getParent() instanceof UsesNodeBuilder) {
295 setNodeAddedByUses(childCopy);
297 setNodeAugmenting(childCopy);
299 target.addChildNode(childCopy);
300 } catch (YangParseException e) {
302 // more descriptive message
303 throw new YangParseException(augment.getModuleName(), augment.getLine(),
304 "Failed to perform augmentation: " + e.getMessage());
310 * Add all augment's child nodes to given target.
313 * builder of augment statement
315 * augmentation target choice node
317 private static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final ChoiceBuilder target) {
318 for (DataSchemaNodeBuilder builder : augment.getChildNodeBuilders()) {
319 DataSchemaNodeBuilder childCopy = CopyUtils.copy(builder, target, false);
320 if (augment.getParent() instanceof UsesNodeBuilder) {
321 setNodeAddedByUses(childCopy);
323 setNodeAugmenting(childCopy);
324 target.addCase(childCopy);
326 for (UsesNodeBuilder usesNode : augment.getUsesNodeBuilders()) {
327 if (usesNode != null) {
328 throw new YangParseException(augment.getModuleName(), augment.getLine(),
329 "Error in augment parsing: cannot augment choice with nodes from grouping");
335 * Set augmenting flag to true for node and all its child nodes.
339 private static void setNodeAugmenting(final DataSchemaNodeBuilder node) {
340 node.setAugmenting(true);
341 if (node instanceof DataNodeContainerBuilder) {
342 DataNodeContainerBuilder dataNodeChild = (DataNodeContainerBuilder) node;
343 for (DataSchemaNodeBuilder inner : dataNodeChild.getChildNodeBuilders()) {
344 setNodeAugmenting(inner);
346 } else if (node instanceof ChoiceBuilder) {
347 ChoiceBuilder choiceChild = (ChoiceBuilder) node;
348 for (ChoiceCaseBuilder inner : choiceChild.getCases()) {
349 setNodeAugmenting(inner);
355 * Set addedByUses flag to true for node and all its child nodes.
359 public static void setNodeAddedByUses(final GroupingMember node) {
360 node.setAddedByUses(true);
361 if (node instanceof DataNodeContainerBuilder) {
362 DataNodeContainerBuilder dataNodeChild = (DataNodeContainerBuilder) node;
363 for (DataSchemaNodeBuilder inner : dataNodeChild.getChildNodeBuilders()) {
364 setNodeAddedByUses(inner);
366 } else if (node instanceof ChoiceBuilder) {
367 ChoiceBuilder choiceChild = (ChoiceBuilder) node;
368 for (ChoiceCaseBuilder inner : choiceChild.getCases()) {
369 setNodeAddedByUses(inner);
375 * Set config flag to new value.
382 private static void setNodeConfig(final DataSchemaNodeBuilder node, final Boolean config) {
383 if (node instanceof ContainerSchemaNodeBuilder || node instanceof LeafSchemaNodeBuilder
384 || node instanceof LeafListSchemaNodeBuilder || node instanceof ListSchemaNodeBuilder
385 || node instanceof ChoiceBuilder || node instanceof AnyXmlBuilder) {
386 node.setConfiguration(config);
388 if (node instanceof DataNodeContainerBuilder) {
389 DataNodeContainerBuilder dataNodeChild = (DataNodeContainerBuilder) node;
390 for (DataSchemaNodeBuilder inner : dataNodeChild.getChildNodeBuilders()) {
391 setNodeConfig(inner, config);
393 } else if (node instanceof ChoiceBuilder) {
394 ChoiceBuilder choiceChild = (ChoiceBuilder) node;
395 for (ChoiceCaseBuilder inner : choiceChild.getCases()) {
396 setNodeConfig(inner, config);
401 public static DataSchemaNodeBuilder findSchemaNode(final List<QName> path, final SchemaNodeBuilder parentNode) {
402 DataSchemaNodeBuilder node = null;
403 SchemaNodeBuilder parent = parentNode;
405 while (i < path.size()) {
406 String name = path.get(i).getLocalName();
407 if (parent instanceof DataNodeContainerBuilder) {
408 node = ((DataNodeContainerBuilder) parent).getDataChildByName(name);
409 } else if (parent instanceof ChoiceBuilder) {
410 node = ((ChoiceBuilder) parent).getCaseNodeByName(name);
411 } else if (parent instanceof RpcDefinitionBuilder) {
412 if ("input".equals(name)) {
413 node = ((RpcDefinitionBuilder) parent).getInput();
414 } else if ("output".equals(name)) {
415 node = ((RpcDefinitionBuilder) parent).getOutput();
423 if (i < path.size() - 1) {
434 * Find a builder for node in data namespace of YANG module.
436 * Search is performed on full QName equals, this means builders and schema
437 * path MUST be resolved against imports and their namespaces.
439 * Search is done in data namespace, this means notification, rpc
440 * definitions and top level data definitions are considered as top-level
441 * items, from which it is possible to traverse.
445 * Schema Path to node
447 * ModuleBuilder to start lookup in
448 * @return Node Builder if found, {@link Optional#absent()} otherwise.
450 public static Optional<SchemaNodeBuilder> findSchemaNodeInModule(final SchemaPath schemaPath,
451 final ModuleBuilder module) {
452 Iterator<QName> path = schemaPath.getPathFromRoot().iterator();
453 Preconditions.checkArgument(path.hasNext(), "Schema Path must contain at least one element.");
454 QName first = path.next();
455 Optional<SchemaNodeBuilder> currentNode = getDataNamespaceChild(module, first);
457 while (currentNode.isPresent() && path.hasNext()) {
458 currentNode = findDataChild(currentNode.get(), path.next());
463 private static Optional<SchemaNodeBuilder> findDataChild(final SchemaNodeBuilder parent, final QName child) {
464 if (parent instanceof DataNodeContainerBuilder) {
465 return castOptional(SchemaNodeBuilder.class,
466 findDataChildInDataNodeContainer((DataNodeContainerBuilder) parent, child));
467 } else if (parent instanceof ChoiceBuilder) {
468 return castOptional(SchemaNodeBuilder.class, findCaseInChoice((ChoiceBuilder) parent, child));
469 } else if (parent instanceof RpcDefinitionBuilder) {
470 return castOptional(SchemaNodeBuilder.class, findContainerInRpc((RpcDefinitionBuilder) parent, child));
473 LOG.trace("Child {} not found in node {}", child, parent);
474 return Optional.absent();
479 * Casts optional from one argument to other.
482 * Class to be checked
487 private static <T> Optional<T> castOptional(final Class<T> cls, final Optional<?> optional) {
488 if (optional.isPresent()) {
489 Object value = optional.get();
490 if (cls.isInstance(value)) {
491 @SuppressWarnings("unchecked")
492 // Actually checked by outer if
493 T casted = (T) value;
494 return Optional.of(casted);
497 return Optional.absent();
502 * Gets input / output container from {@link RpcDefinitionBuilder} if QName
507 * RPC Definition builder
510 * @return Optional of input/output if defined and QName is input/output.
511 * Otherwise {@link Optional#absent()}.
513 private static Optional<ContainerSchemaNodeBuilder> findContainerInRpc(final RpcDefinitionBuilder parent, final QName child) {
514 if (INPUT.equals(child.getLocalName())) {
515 return Optional.of(parent.getInput());
516 } else if (OUTPUT.equals(child.getLocalName())) {
517 return Optional.of(parent.getOutput());
519 LOG.trace("Child {} not found in node {}", child, parent);
520 return Optional.absent();
524 * Finds case by QName in {@link ChoiceBuilder}
528 * DataNodeContainer in which lookup should be performed
531 * @return Optional of child if found.
534 private static Optional<ChoiceCaseBuilder> findCaseInChoice(final ChoiceBuilder parent, final QName child) {
535 for (ChoiceCaseBuilder caze : parent.getCases()) {
536 if (caze.getQName().equals(child)) {
537 return Optional.of(caze);
540 LOG.trace("Child {} not found in node {}", child, parent);
541 return Optional.absent();
545 * Finds direct child by QName in {@link DataNodeContainerBuilder}
549 * DataNodeContainer in which lookup should be performed
552 * @return Optional of child if found.
554 private static Optional<DataSchemaNodeBuilder> findDataChildInDataNodeContainer(final DataNodeContainerBuilder parent,
556 for (DataSchemaNodeBuilder childNode : parent.getChildNodeBuilders()) {
557 if (childNode.getQName().equals(child)) {
558 return Optional.of(childNode);
561 LOG.trace("Child {} not found in node {}", child, parent);
562 return Optional.absent();
567 * Find a child builder for node in data namespace of YANG module.
569 * Search is performed on full QName equals, this means builders and schema
570 * path MUST be resolved against imports and their namespaces.
572 * Search is done in data namespace, this means notification, rpc
573 * definitions and top level data definitions are considered as top-level
574 * items, from which it is possible to traverse.
580 * ModuleBuilder to start lookup in
581 * @return Node Builder if found, {@link Optional#absent()} otherwise.
583 private static Optional<SchemaNodeBuilder> getDataNamespaceChild(final ModuleBuilder module, final QName child) {
585 * First we do lookup in data tree, if node is found we return it.
587 final Optional<SchemaNodeBuilder> dataTreeNode = getDataChildByQName(module, child);
588 if (dataTreeNode.isPresent()) {
593 * We lookup in notifications
595 Set<NotificationBuilder> notifications = module.getAddedNotifications();
596 for (NotificationBuilder notification : notifications) {
597 if (notification.getQName().equals(child)) {
598 return Optional.<SchemaNodeBuilder> of(notification);
605 Set<RpcDefinitionBuilder> rpcs = module.getAddedRpcs();
606 for (RpcDefinitionBuilder rpc : rpcs) {
607 if (rpc.getQName().equals(child)) {
608 return Optional.<SchemaNodeBuilder> of(rpc);
611 LOG.trace("Child {} not found in data namespace of module {}", child, module);
612 return Optional.absent();
615 private static Optional<SchemaNodeBuilder> getDataChildByQName(final DataNodeContainerBuilder builder, final QName child) {
616 for (DataSchemaNodeBuilder childNode : builder.getChildNodeBuilders()) {
617 if (childNode.getQName().equals(child)) {
618 return Optional.<SchemaNodeBuilder> of(childNode);
621 LOG.trace("Child {} not found in node {}", child, builder);
622 return Optional.absent();
626 * Find augment target node and perform augmentation.
629 * @param firstNodeParent
630 * parent of first node in path
632 * path to augment target
633 * @return true if augmentation process succeed, false otherwise
635 public static boolean processAugmentation(final AugmentationSchemaBuilder augment,
636 final ModuleBuilder firstNodeParent) {
637 Optional<SchemaNodeBuilder> potentialTargetNode = findSchemaNodeInModule(augment.getTargetNodeSchemaPath(),
639 if (!potentialTargetNode.isPresent()) {
642 SchemaNodeBuilder targetNode = potentialTargetNode.get();
643 fillAugmentTarget(augment, targetNode);
644 Preconditions.checkState(targetNode instanceof AugmentationTargetBuilder,
645 "Node refered by augmentation must be valid augmentation target");
646 ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
647 augment.setResolved(true);
651 public static IdentitySchemaNodeBuilder findBaseIdentity(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
652 final ModuleBuilder module, final String baseString, final int line) {
654 // FIXME: optimize indexOf() away?
655 if (baseString.indexOf(':') != -1) {
656 final Iterator<String> it = COLON_SPLITTER.split(baseString).iterator();
657 final String prefix = it.next();
658 final String name = it.next();
661 throw new YangParseException(module.getName(), line, "Failed to parse identityref base: " + baseString);
664 ModuleBuilder dependentModule = findModuleFromBuilders(modules, module, prefix, line);
665 if (dependentModule == null) {
669 return findIdentity(dependentModule.getAddedIdentities(), name);
671 return findIdentity(module.getAddedIdentities(), baseString);
675 public static IdentitySchemaNodeBuilder findIdentity(final Set<IdentitySchemaNodeBuilder> identities,
677 for (IdentitySchemaNodeBuilder identity : identities) {
678 if (identity.getQName().getLocalName().equals(name)) {
686 * Get module in which this node is defined.
689 * @return builder of module where this node is defined
691 public static ModuleBuilder getParentModule(final Builder node) {
692 if (node instanceof ModuleBuilder) {
693 return (ModuleBuilder) node;
695 Builder parent = node.getParent();
696 while (!(parent instanceof ModuleBuilder)) {
697 parent = parent.getParent();
699 ModuleBuilder parentModule = (ModuleBuilder) parent;
700 if (parentModule.isSubmodule()) {
701 parentModule = parentModule.getParent();
706 public static Set<DataSchemaNodeBuilder> wrapChildNodes(final String moduleName, final int line,
707 final Set<DataSchemaNode> nodes, final SchemaPath parentPath, final QName parentQName) {
708 Set<DataSchemaNodeBuilder> result = new HashSet<>();
710 for (DataSchemaNode node : nodes) {
711 QName qname = QName.create(parentQName, node.getQName().getLocalName());
712 DataSchemaNodeBuilder wrapped = wrapChildNode(moduleName, line, node, parentPath, qname);
718 public static DataSchemaNodeBuilder wrapChildNode(final String moduleName, final int line,
719 final DataSchemaNode node, final SchemaPath parentPath, final QName qname) {
721 final SchemaPath schemaPath = parentPath.createChild(qname);
723 if (node instanceof AnyXmlSchemaNode) {
724 return new AnyXmlBuilder(moduleName, line, qname, schemaPath, ((AnyXmlSchemaNode) node));
725 } else if (node instanceof ChoiceNode) {
726 return new ChoiceBuilder(moduleName, line, qname, schemaPath, ((ChoiceNode) node));
727 } else if (node instanceof ContainerSchemaNode) {
728 return new ContainerSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((ContainerSchemaNode) node));
729 } else if (node instanceof LeafSchemaNode) {
730 return new LeafSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((LeafSchemaNode) node));
731 } else if (node instanceof LeafListSchemaNode) {
732 return new LeafListSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((LeafListSchemaNode) node));
733 } else if (node instanceof ListSchemaNode) {
734 return new ListSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((ListSchemaNode) node));
735 } else if (node instanceof ChoiceCaseNode) {
736 return new ChoiceCaseBuilder(moduleName, line, qname, schemaPath, ((ChoiceCaseNode) node));
738 throw new YangParseException(moduleName, line, "Failed to copy node: Unknown type of DataSchemaNode: "
743 public static Set<GroupingBuilder> wrapGroupings(final String moduleName, final int line,
744 final Set<GroupingDefinition> nodes, final SchemaPath parentPath, final QName parentQName) {
745 Set<GroupingBuilder> result = new HashSet<>();
746 for (GroupingDefinition node : nodes) {
747 QName qname = QName.create(parentQName, node.getQName().getLocalName());
748 SchemaPath schemaPath = parentPath.createChild(qname);
749 result.add(new GroupingBuilderImpl(moduleName, line, qname, schemaPath, node));
754 public static Set<TypeDefinitionBuilder> wrapTypedefs(final String moduleName, final int line,
755 final DataNodeContainer dataNode, final SchemaPath parentPath, final QName parentQName) {
756 Set<TypeDefinition<?>> nodes = dataNode.getTypeDefinitions();
757 Set<TypeDefinitionBuilder> result = new HashSet<>();
758 for (TypeDefinition<?> node : nodes) {
759 QName qname = QName.create(parentQName, node.getQName().getLocalName());
760 SchemaPath schemaPath = parentPath.createChild(qname);
761 result.add(new TypeDefinitionBuilderImpl(moduleName, line, qname, schemaPath, ((ExtendedType) node)));
766 public static List<UnknownSchemaNodeBuilderImpl> wrapUnknownNodes(final String moduleName, final int line,
767 final List<UnknownSchemaNode> nodes, final SchemaPath parentPath, final QName parentQName) {
768 List<UnknownSchemaNodeBuilderImpl> result = new ArrayList<>();
769 for (UnknownSchemaNode node : nodes) {
770 QName qname = QName.create(parentQName, node.getQName().getLocalName());
771 SchemaPath schemaPath = parentPath.createChild(qname);
772 result.add(new UnknownSchemaNodeBuilderImpl(moduleName, line, qname, schemaPath, node));
777 private static final class ByteSourceImpl extends ByteSource {
778 private final String toString;
779 private final ByteArrayOutputStream output = new ByteArrayOutputStream();
781 private ByteSourceImpl(final InputStream input) throws IOException {
782 toString = input.toString();
783 IOUtils.copy(input, output);
787 public InputStream openStream() throws IOException {
788 return new NamedByteArrayInputStream(output.toByteArray(), toString);