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.model.export;
10 import com.google.common.annotations.Beta;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.base.Strings;
14 import com.google.common.primitives.UnsignedInteger;
16 import java.util.Date;
17 import java.util.Iterator;
18 import java.util.List;
20 import java.util.Map.Entry;
21 import java.util.Objects;
23 import javax.annotation.Nullable;
24 import javax.annotation.concurrent.NotThreadSafe;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
28 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
29 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
31 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
33 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.Deviation;
35 import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
36 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
37 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
38 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
39 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
42 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
43 import org.opendaylight.yangtools.yang.model.api.Module;
44 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
45 import org.opendaylight.yangtools.yang.model.api.MustDefinition;
46 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
47 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
48 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
49 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
50 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
51 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
52 import org.opendaylight.yangtools.yang.model.api.Status;
53 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
54 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
55 import org.opendaylight.yangtools.yang.model.api.UsesNode;
56 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
57 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
58 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
59 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
60 import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
61 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
62 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
63 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
64 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
65 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
66 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
67 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
68 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
69 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
70 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
71 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
72 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
73 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
74 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
75 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
79 class SchemaContextEmitter {
81 private final Rfc6020ModuleWriter writer;
82 private final boolean emitInstantiated;
83 private final boolean emitUses;
84 private final Map<QName, StatementDefinition> extensions;
86 SchemaContextEmitter(final Rfc6020ModuleWriter writer, final Map<QName, StatementDefinition> extensions) {
87 this(writer, extensions,false, true);
90 SchemaContextEmitter(final Rfc6020ModuleWriter writer, final Map<QName, StatementDefinition> extensions, final boolean emitInstantiated, final boolean emitUses) {
91 this.writer = Preconditions.checkNotNull(writer);
92 this.emitInstantiated = emitInstantiated;
93 this.emitUses = emitUses;
94 this.extensions = Preconditions.checkNotNull(extensions);
97 static void writeToStatementWriter(final Module module, final SchemaContext ctx, final StatementTextWriter statementWriter) {
98 final Rfc6020ModuleWriter yangSchemaWriter = SchemaToStatementWriterAdaptor.from(statementWriter);
99 final Map<QName, StatementDefinition> extensions = ExtensionStatement.mapFrom(ctx.getExtensions());
100 new SchemaContextEmitter(yangSchemaWriter,extensions).emitModule(module);
103 void emitModule(final Module input) {
104 writer.startModuleNode(input.getName());
105 emitModuleHeader(input);
106 emitLinkageNodes(input);
107 emitMetaNodes(input);
108 emitRevisionNodes(input);
109 emitBodyNodes(input);
113 private void emitModuleHeader(final Module input) {
114 emitYangVersionNode(input.getYangVersion());
115 emitNamespace(input.getNamespace());
116 emitPrefixNode(input.getPrefix());
119 @SuppressWarnings("unused")
120 private void emitSubmodule(final String input) {
122 * FIXME: BUG-2444: Implement submodule export
124 * submoduleHeaderNodes linkageNodes metaNodes revisionNodes bodyNodes
129 @SuppressWarnings("unused")
130 private void emitSubmoduleHeaderNodes(final Module input) {
132 * FIXME: BUG-2444: Implement submodule headers properly
134 * :yangVersionNode //Optional
140 private void emitMetaNodes(final Module input) {
142 emitOrganizationNode(input.getOrganization()); // FIXME: BUG-2444: Optional
143 emitContact(input.getContact()); // FIXME: BUG-2444: Optional
144 emitDescriptionNode(input.getDescription());
145 emitReferenceNode(input.getReference());
148 private void emitLinkageNodes(final Module input) {
149 for (final ModuleImport importNode : input.getImports()) {
150 emitImport(importNode);
153 * FIXME: BUG-2444: Emit include statements
157 private void emitRevisionNodes(final Module input) {
159 * FIXME: BUG-2444: emit revisions properly, when parsed model will provide enough
162 emitRevision(input.getRevision());
166 private void emitBodyNodes(final Module input) {
168 for (final ExtensionDefinition extension : input.getExtensionSchemaNodes()) {
169 emitExtension(extension);
171 for (final FeatureDefinition definition : input.getFeatures()) {
172 emitFeature(definition);
174 for (final IdentitySchemaNode identity : input.getIdentities()) {
175 emitIdentity(identity);
178 emitDataNodeContainer(input);
180 for (final AugmentationSchema augmentation : input.getAugmentations()) {
181 emitAugment(augmentation);
183 for (final RpcDefinition rpc : input.getRpcs()) {
186 for (final NotificationDefinition notification : input.getNotifications()) {
187 emitNotificationNode(notification);
189 for (final Deviation deviation : input.getDeviations()) {
190 emitDeviation(deviation);
195 private void emitDataNodeContainer(final DataNodeContainer input) {
196 for (final TypeDefinition<?> typedef : input.getTypeDefinitions()) {
197 emitTypedefNode(typedef);
199 for (final GroupingDefinition grouping : input.getGroupings()) {
200 emitGrouping(grouping);
202 for (final DataSchemaNode child : input.getChildNodes()) {
203 emitDataSchemaNode(child);
205 for (final UsesNode usesNode : input.getUses()) {
206 emitUsesNode(usesNode);
210 private void emitDataSchemaNode(final DataSchemaNode child) {
211 if (!emitInstantiated && (child.isAddedByUses() || child.isAugmenting())) {
212 // We skip instantiated nodes.
216 if (child instanceof ContainerSchemaNode) {
217 emitContainer((ContainerSchemaNode) child);
218 } else if (child instanceof LeafSchemaNode) {
219 emitLeaf((LeafSchemaNode) child);
220 } else if (child instanceof LeafListSchemaNode) {
221 emitLeafList((LeafListSchemaNode) child);
222 } else if (child instanceof ListSchemaNode) {
223 emitList((ListSchemaNode) child);
224 } else if (child instanceof ChoiceSchemaNode) {
225 emitChoice((ChoiceSchemaNode) child);
226 } else if (child instanceof AnyXmlSchemaNode) {
227 emitAnyxml((AnyXmlSchemaNode) child);
229 throw new UnsupportedOperationException("Not supported DataSchemaNode type " + child.getClass());
233 private void emitYangVersionNode(final String input) {
234 writer.startYangVersionNode(input);
238 private void emitImport(final ModuleImport importNode) {
239 writer.startImportNode(importNode.getModuleName());
240 emitPrefixNode(importNode.getPrefix());
241 emitRevisionDateNode(importNode.getRevision());
245 @SuppressWarnings("unused")
246 private void emitInclude(final String input) {
248 * FIXME: BUG-2444: Implement proper export of include statements
249 * startIncludeNode(IdentifierHelper.getIdentifier(String :input));
252 * :revisionDateNode :writer.endNode();)
256 private void emitNamespace(final URI uri) {
257 writer.startNamespaceNode(uri);
262 private void emitPrefixNode(final String input) {
263 writer.startPrefixNode(input);
268 @SuppressWarnings("unused")
269 private void emitBelongsTo(final String input) {
271 * FIXME: BUG-2444: Implement proper export of belongs-to statements
272 * startIncludeNode(IdentifierHelper.getIdentifier(String :input));
275 * :writer.startBelongsToNode(IdentifierHelper.getIdentifier(String
286 private void emitOrganizationNode(final String input) {
287 writer.startOrganizationNode(input);
292 private void emitContact(final String input) {
293 writer.startContactNode(input);
298 private void emitDescriptionNode(@Nullable final String input) {
299 if (!Strings.isNullOrEmpty(input)) {
300 writer.startDescriptionNode(input);
305 private void emitReferenceNode(@Nullable final String input) {
306 if (!Strings.isNullOrEmpty(input)) {
307 writer.startReferenceNode(input);
312 private void emitUnitsNode(@Nullable final String input) {
313 if (!Strings.isNullOrEmpty(input)) {
314 writer.startUnitsNode(input);
319 private void emitRevision(final Date date) {
320 writer.startRevisionNode(date);
323 // FIXME: BUG-2444: FIXME: BUG-2444: BUG-2417: descriptionNode //FIXME: BUG-2444: Optional
324 // FIXME: BUG-2444: FIXME: BUG-2444: BUG-2417: referenceNode //FIXME: BUG-2444: Optional
329 private void emitRevisionDateNode(@Nullable final Date date) {
331 writer.startRevisionDateNode(date);
336 private void emitExtension(final ExtensionDefinition extension) {
337 writer.startExtensionNode(extension.getQName());
338 emitArgument(extension.getArgument(),extension.isYinElement());
339 emitStatusNode(extension.getStatus());
340 emitDescriptionNode(extension.getDescription());
341 emitReferenceNode(extension.getReference());
342 emitUnknownStatementNodes(extension.getUnknownSchemaNodes());
347 private void emitArgument(final @Nullable String input, final boolean yinElement) {
349 writer.startArgumentNode(input);
350 emitYinElement(yinElement);
356 private void emitYinElement(final boolean yinElement) {
357 writer.startYinElementNode(yinElement);
362 private void emitIdentity(final IdentitySchemaNode identity) {
363 writer.startIdentityNode(identity.getQName());
364 if (identity.getBaseIdentity() != null) {
365 emitBase(identity.getBaseIdentity().getQName());
367 emitStatusNode(identity.getStatus());
368 emitDescriptionNode(identity.getDescription());
369 emitReferenceNode(identity.getReference());
374 private void emitBase(final QName qName) {
375 writer.startBaseNode(qName);
380 private void emitFeature(final FeatureDefinition definition) {
381 writer.startFeatureNode(definition.getQName());
383 // FIXME: BUG-2444: FIXME: BUG-2444: Expose ifFeature *(ifFeatureNode )
384 emitStatusNode(definition.getStatus());
385 emitDescriptionNode(definition.getDescription());
386 emitReferenceNode(definition.getReference());
391 @SuppressWarnings("unused")
392 private void emitIfFeature(final String input) {
394 * FIXME: BUG-2444: Implement proper export of include statements
395 * startIncludeNode(IdentifierHelper.getIdentifier(String :input));
400 private void emitTypedefNode(final TypeDefinition<?> typedef) {
401 writer.startTypedefNode(typedef.getQName());
402 // Differentiate between derived type and existing type
404 emitTypeNodeDerived(typedef);
405 emitUnitsNode(typedef.getUnits());
406 emitDefaultNode(typedef.getDefaultValue());
407 emitStatusNode(typedef.getStatus());
408 emitDescriptionNode(typedef.getDescription());
409 emitReferenceNode(typedef.getReference());
410 emitUnknownStatementNodes(typedef.getUnknownSchemaNodes());
415 private void emitTypeNode(final SchemaPath parentPath, final TypeDefinition<?> subtype) {
416 final SchemaPath path = subtype.getPath();
417 if (isPrefix(parentPath.getPathFromRoot(), path.getPathFromRoot())) {
418 emitTypeNodeDerived(subtype);
420 emitTypeNodeReferenced(subtype);
424 private void emitTypeNodeReferenced(final TypeDefinition<?> typeDefinition) {
425 writer.startTypeNode(typeDefinition.getQName());
430 private void emitTypeNodeDerived(final TypeDefinition<?> typeDefinition) {
431 final TypeDefinition<?> baseType;
432 if (typeDefinition.getBaseType() != null) {
433 baseType = typeDefinition.getBaseType();
435 baseType = typeDefinition;
437 writer.startTypeNode(baseType.getQName());
438 emitTypeBodyNodes(typeDefinition);
443 private void emitTypeBodyNodes(final TypeDefinition<?> typeDef) {
444 if (typeDef instanceof UnsignedIntegerTypeDefinition) {
445 emitUnsignedIntegerSpecification((UnsignedIntegerTypeDefinition) typeDef);
446 } else if (typeDef instanceof IntegerTypeDefinition) {
447 emitIntegerSpefication((IntegerTypeDefinition) typeDef);
448 } else if (typeDef instanceof DecimalTypeDefinition) {
449 emitDecimal64Specification((DecimalTypeDefinition) typeDef);
450 } else if (typeDef instanceof StringTypeDefinition) {
451 emitStringRestrictions((StringTypeDefinition) typeDef);
452 } else if (typeDef instanceof EnumTypeDefinition) {
453 emitEnumSpecification((EnumTypeDefinition) typeDef);
454 } else if (typeDef instanceof LeafrefTypeDefinition) {
455 emitLeafrefSpecification((LeafrefTypeDefinition) typeDef);
456 } else if (typeDef instanceof IdentityrefTypeDefinition) {
457 emitIdentityrefSpecification((IdentityrefTypeDefinition) typeDef);
458 } else if (typeDef instanceof InstanceIdentifierTypeDefinition) {
459 emitInstanceIdentifierSpecification((InstanceIdentifierTypeDefinition) typeDef);
460 } else if (typeDef instanceof BitsTypeDefinition) {
461 emitBitsSpecification((BitsTypeDefinition) typeDef);
462 } else if (typeDef instanceof UnionTypeDefinition) {
463 emitUnionSpecification((UnionTypeDefinition) typeDef);
464 } else if (typeDef instanceof BinaryTypeDefinition) {
465 // FIXME: BUG-2444: Is this realy NOOP?
466 // should at least support length statement
467 } else if (typeDef instanceof BooleanTypeDefinition || typeDef instanceof EmptyTypeDefinition) {
470 throw new IllegalArgumentException("Not supported type " + typeDef.getClass());
474 private void emitIntegerSpefication(final IntegerTypeDefinition typeDef) {
475 emitRangeNodeOptional(typeDef.getRangeConstraints());
478 private void emitUnsignedIntegerSpecification(final UnsignedIntegerTypeDefinition typeDef) {
479 emitRangeNodeOptional(typeDef.getRangeConstraints());
483 private void emitRangeNodeOptional(final List<RangeConstraint> list) {
484 // FIXME: BUG-2444: Wrong decomposition in API, should be LenghtConstraint
485 // which contains ranges.
486 if (!list.isEmpty()) {
487 writer.startRangeNode(toRangeString(list));
488 final RangeConstraint first = list.iterator().next();
489 emitErrorMessageNode(first.getErrorMessage());
490 emitErrorAppTagNode(first.getErrorAppTag());
491 emitDescriptionNode(first.getDescription());
492 emitReferenceNode(first.getReference());
498 private void emitDecimal64Specification(final DecimalTypeDefinition typeDefinition) {
499 emitFranctionDigitsNode(typeDefinition.getFractionDigits());
500 emitRangeNodeOptional(typeDefinition.getRangeConstraints());
504 private void emitFranctionDigitsNode(final Integer fractionDigits) {
505 writer.startFractionDigitsNode(fractionDigits);
509 private void emitStringRestrictions(final StringTypeDefinition typeDef) {
511 // FIXME: BUG-2444: Wrong decomposition in API, should be LenghtConstraint
512 // which contains ranges.
513 emitLength(typeDef.getLengthConstraints());
515 for (final PatternConstraint pattern : typeDef.getPatternConstraints()) {
516 emitPatternNode(pattern);
521 private void emitLength(final List<LengthConstraint> list) {
522 if (!list.isEmpty()) {
523 writer.startLengthNode(toLengthString(list));
524 // FIXME: BUG-2444: Workaround for incorrect decomposition in API
525 final LengthConstraint first = list.iterator().next();
526 emitErrorMessageNode(first.getErrorMessage());
527 emitErrorAppTagNode(first.getErrorAppTag());
528 emitDescriptionNode(first.getDescription());
529 emitReferenceNode(first.getReference());
534 private static String toLengthString(final List<LengthConstraint> list) {
535 final StringBuilder lengthStr = new StringBuilder();
536 final Iterator<LengthConstraint> constIt = list.iterator();
537 while (constIt.hasNext()) {
538 final LengthConstraint current = constIt.next();
539 if (current.getMin() == current.getMax()) {
540 lengthStr.append(current.getMin());
542 lengthStr.append(current.getMin());
543 lengthStr.append("..");
544 lengthStr.append(current.getMax());
546 if (constIt.hasNext()) {
547 lengthStr.append("|");
550 return lengthStr.toString();
553 private static String toRangeString(final List<RangeConstraint> list) {
554 final StringBuilder lengthStr = new StringBuilder();
555 final Iterator<RangeConstraint> constIt = list.iterator();
556 while (constIt.hasNext()) {
557 final RangeConstraint current = constIt.next();
558 if (current.getMin() == current.getMax()) {
559 lengthStr.append(current.getMin());
561 lengthStr.append(current.getMin());
562 lengthStr.append("..");
563 lengthStr.append(current.getMax());
565 if (constIt.hasNext()) {
566 lengthStr.append("|");
569 return lengthStr.toString();
572 private void emitPatternNode(final PatternConstraint pattern) {
573 writer.startPatternNode(pattern.getRegularExpression());
574 emitErrorMessageNode(pattern.getErrorMessage()); // FIXME: BUG-2444: Optional
575 emitErrorAppTagNode(pattern.getErrorAppTag()); // FIXME: BUG-2444: Optional
576 emitDescriptionNode(pattern.getDescription());
577 emitReferenceNode(pattern.getReference()); // FIXME: BUG-2444: Optional
581 private void emitDefaultNode(@Nullable final Object object) {
582 if (object != null) {
583 writer.startDefaultNode(object.toString());
589 private void emitEnumSpecification(final EnumTypeDefinition typeDefinition) {
590 for (final EnumPair enumValue : typeDefinition.getValues()) {
591 emitEnumNode(enumValue);
595 private void emitEnumNode(final EnumPair enumValue) {
596 writer.startEnumNode(enumValue.getName());
597 emitValueNode(enumValue.getValue());
598 emitStatusNode(enumValue.getStatus());
599 emitDescriptionNode(enumValue.getDescription());
600 emitReferenceNode(enumValue.getReference());
604 private void emitLeafrefSpecification(final LeafrefTypeDefinition typeDefinition) {
605 emitPathNode(typeDefinition.getPathStatement());
606 // FIXME: BUG-2444: requireInstanceNode /Optional removed with (RFC6020 - Errata ID
611 private void emitPathNode(final RevisionAwareXPath revisionAwareXPath) {
612 writer.startPathNode(revisionAwareXPath);
616 private void emitRequireInstanceNode(final boolean require) {
617 writer.startRequireInstanceNode(require);
621 private void emitInstanceIdentifierSpecification(final InstanceIdentifierTypeDefinition typeDefinition) {
622 emitRequireInstanceNode(typeDefinition.requireInstance());
625 private void emitIdentityrefSpecification(final IdentityrefTypeDefinition typeDefinition) {
626 emitBase(typeDefinition.getIdentity().getQName());
629 private void emitUnionSpecification(final UnionTypeDefinition typeDefinition) {
630 for (final TypeDefinition<?> subtype : typeDefinition.getTypes()) {
631 // FIXME: BUG-2444: What if we have locally modified types here?
632 // is solution to look-up in schema path?
633 emitTypeNode(typeDefinition.getPath(), subtype);
637 private void emitBitsSpecification(final BitsTypeDefinition typeDefinition) {
638 for (final Bit bit : typeDefinition.getBits()) {
643 private void emitBit(final Bit bit) {
644 writer.startBitNode(bit.getName());
645 emitPositionNode(bit.getPosition());
646 emitStatusNode(bit.getStatus());
647 emitDescriptionNode(bit.getDescription());
648 emitReferenceNode(bit.getReference());
652 private void emitPositionNode(@Nullable final Long position) {
653 if (position != null) {
654 writer.startPositionNode(UnsignedInteger.valueOf(position));
659 private void emitStatusNode(@Nullable final Status status) {
660 if (status != null) {
661 writer.startStatusNode(status);
666 private void emitConfigNode(final boolean config) {
667 writer.startConfigNode(config);
671 private void emitMandatoryNode(final boolean mandatory) {
672 writer.startMandatoryNode(mandatory);
676 private void emitPresenceNode(final boolean presence) {
677 writer.startPresenceNode(presence);
681 private void emitOrderedBy(final boolean userOrdered) {
683 writer.startOrderedByNode("user");
685 writer.startOrderedByNode("system");
690 private void emitMust(@Nullable final MustDefinition mustCondition) {
691 if (mustCondition != null && mustCondition.getXpath() != null) {
692 writer.startMustNode(mustCondition.getXpath());
693 emitErrorMessageNode(mustCondition.getErrorMessage());
694 emitErrorAppTagNode(mustCondition.getErrorAppTag());
695 emitDescriptionNode(mustCondition.getDescription());
696 emitReferenceNode(mustCondition.getReference());
702 private void emitErrorMessageNode(@Nullable final String input) {
703 if (input != null && !input.isEmpty()) {
704 writer.startErrorMessageNode(input);
709 private void emitErrorAppTagNode(final String input) {
710 if (input != null && !input.isEmpty()) {
711 writer.startErrorAppTagNode(input);
716 private void emitMinElementsNode(final Integer min) {
718 writer.startMinElementsNode(min);
723 private void emitMaxElementsNode(final Integer max) {
725 writer.startMaxElementsNode(max);
730 private void emitValueNode(@Nullable final Integer value) {
732 writer.startValueNode(value);
737 private void emitDocumentedNode(final DocumentedNode input) {
738 emitStatusNode(input.getStatus());
739 emitDescriptionNode(input.getDescription());
740 emitReferenceNode(input.getReference());
743 private void emitGrouping(final GroupingDefinition grouping) {
744 writer.startGroupingNode(grouping.getQName());
745 emitDocumentedNode(grouping);
746 emitDataNodeContainer(grouping);
747 emitUnknownStatementNodes(grouping.getUnknownSchemaNodes());
752 private void emitContainer(final ContainerSchemaNode child) {
753 writer.startContainerNode(child.getQName());
757 emitConstraints(child.getConstraints());
758 // FIXME: BUG-2444: whenNode //:Optional
759 // FIXME: BUG-2444: *(ifFeatureNode )
760 emitMustNodes(child.getConstraints().getMustConstraints());
761 emitPresenceNode(child.isPresenceContainer());
762 emitConfigNode(child.isConfiguration());
763 emitDocumentedNode(child);
764 emitDataNodeContainer(child);
765 emitUnknownStatementNodes(child.getUnknownSchemaNodes());
770 private void emitConstraints(final ConstraintDefinition constraints) {
771 emitWhen(constraints.getWhenCondition());
772 for (final MustDefinition mustCondition : constraints.getMustConstraints()) {
773 emitMust(mustCondition);
778 private void emitLeaf(final LeafSchemaNode child) {
779 writer.startLeafNode(child.getQName());
780 emitWhen(child.getConstraints().getWhenCondition());
781 // FIXME: BUG-2444: *(ifFeatureNode )
782 emitTypeNode(child.getPath(), child.getType());
783 emitUnitsNode(child.getUnits());
784 emitMustNodes(child.getConstraints().getMustConstraints());
785 emitDefaultNode(child.getDefault());
786 emitConfigNode(child.isConfiguration());
787 emitMandatoryNode(child.getConstraints().isMandatory());
788 emitDocumentedNode(child);
789 emitUnknownStatementNodes(child.getUnknownSchemaNodes());
794 private void emitLeafList(final LeafListSchemaNode child) {
795 writer.startLeafListNode(child.getQName());
797 emitWhen(child.getConstraints().getWhenCondition());
798 // FIXME: BUG-2444: *(ifFeatureNode )
799 emitTypeNode(child.getPath(), child.getType());
800 // FIXME: BUG-2444: unitsNode /Optional
801 emitMustNodes(child.getConstraints().getMustConstraints());
802 emitConfigNode(child.isConfiguration());
804 emitMinElementsNode(child.getConstraints().getMinElements());
805 emitMaxElementsNode(child.getConstraints().getMaxElements());
806 emitOrderedBy(child.isUserOrdered());
807 emitDocumentedNode(child);
808 emitUnknownStatementNodes(child.getUnknownSchemaNodes());
813 private void emitList(final ListSchemaNode child) {
814 writer.startListNode(child.getQName());
815 emitWhen(child.getConstraints().getWhenCondition());
817 // FIXME: BUG-2444: *(ifFeatureNode )
818 emitMustNodes(child.getConstraints().getMustConstraints());
819 emitKey(child.getKeyDefinition());
820 // FIXME: BUG-2444: *(uniqueNode )
821 emitConfigNode(child.isConfiguration());
822 emitMinElementsNode(child.getConstraints().getMinElements());
823 emitMaxElementsNode(child.getConstraints().getMaxElements());
824 emitOrderedBy(child.isUserOrdered());
825 emitDocumentedNode(child);
826 emitDataNodeContainer(child);
827 emitUnknownStatementNodes(child.getUnknownSchemaNodes());
832 private void emitMustNodes(final Set<MustDefinition> mustConstraints) {
833 for (final MustDefinition must : mustConstraints) {
838 private void emitKey(final List<QName> keyList) {
839 if (keyList != null && !keyList.isEmpty()) {
840 writer.startKeyNode(keyList);
845 @SuppressWarnings("unused")
846 private void emitUnique(final String input) {
847 // FIXME: BUG-2444: writer.startUniqueNode(uniqueArgStr)); Nodeend
851 private void emitChoice(final ChoiceSchemaNode choice) {
852 writer.startChoiceNode(choice.getQName());
853 emitWhen(choice.getConstraints().getWhenCondition());
854 // FIXME: BUG-2444: *(ifFeatureNode )
855 // FIXME: BUG-2444: defaultNode //Optional
856 emitConfigNode(choice.isConfiguration());
857 emitMandatoryNode(choice.getConstraints().isMandatory());
858 emitDocumentedNode(choice);
859 for (final ChoiceCaseNode caze : choice.getCases()) {
860 // TODO: emit short case?
863 emitUnknownStatementNodes(choice.getUnknownSchemaNodes());
867 private void emitCaseNode(final ChoiceCaseNode caze) {
868 if (!emitInstantiated && caze.isAugmenting()) {
871 writer.startCaseNode(caze.getQName());
872 emitWhen(caze.getConstraints().getWhenCondition());
873 // FIXME: BUG-2444: *(ifFeatureNode )
874 emitDocumentedNode(caze);
875 emitDataNodeContainer(caze);
876 emitUnknownStatementNodes(caze.getUnknownSchemaNodes());
881 private void emitAnyxml(final AnyXmlSchemaNode child) {
882 writer.startAnyxmlNode(child.getQName());
884 emitWhen(child.getConstraints().getWhenCondition());
885 // FIXME: BUG-2444: *(ifFeatureNode )
886 emitMustNodes(child.getConstraints().getMustConstraints());
887 emitConfigNode(child.isConfiguration());
888 emitMandatoryNode(child.getConstraints().isMandatory());
889 emitDocumentedNode(child);
890 emitUnknownStatementNodes(child.getUnknownSchemaNodes());
895 private void emitUsesNode(final UsesNode usesNode) {
896 if (emitUses && !usesNode.isAddedByUses() && !usesNode.isAugmenting()) {
897 writer.startUsesNode(usesNode.getGroupingPath().getLastComponent());
902 * statusNode // Optional F
903 * : descriptionNode // Optional
904 * referenceNode // Optional
906 for (final Entry<SchemaPath, SchemaNode> refine : usesNode.getRefines().entrySet()) {
909 for (final AugmentationSchema aug : usesNode.getAugmentations()) {
910 emitUsesAugmentNode(aug);
916 private void emitRefine(final Entry<SchemaPath, SchemaNode> refine) {
917 final SchemaPath path = refine.getKey();
918 final SchemaNode value = refine.getValue();
919 writer.startRefineNode(path);
921 if (value instanceof LeafSchemaNode) {
922 emitRefineLeafNodes((LeafSchemaNode) value);
923 } else if (value instanceof LeafListSchemaNode) {
924 emitRefineLeafListNodes((LeafListSchemaNode) value);
925 } else if (value instanceof ListSchemaNode) {
926 emitRefineListNodes((ListSchemaNode) value);
927 } else if (value instanceof ChoiceSchemaNode) {
928 emitRefineChoiceNodes((ChoiceSchemaNode) value);
929 } else if (value instanceof ChoiceCaseNode) {
930 emitRefineCaseNodes((ChoiceCaseNode) value);
931 } else if (value instanceof ContainerSchemaNode) {
932 emitRefineContainerNodes((ContainerSchemaNode) value);
933 } else if (value instanceof AnyXmlSchemaNode) {
934 emitRefineAnyxmlNodes((AnyXmlSchemaNode) value);
940 private static <T extends SchemaNode> T getOriginalChecked(final T value) {
941 final Optional<SchemaNode> original = SchemaNodeUtils.getOriginalIfPossible(value);
942 Preconditions.checkArgument(original.isPresent(), "Original unmodified version of node is not present.");
943 @SuppressWarnings("unchecked")
944 final T ret = (T) original.get();
948 private void emitDocumentedNodeRefine(final DocumentedNode original, final DocumentedNode value) {
949 if (Objects.deepEquals(original.getDescription(), value.getDescription())) {
950 emitDescriptionNode(value.getDescription());
952 if (Objects.deepEquals(original.getReference(), value.getReference())) {
953 emitReferenceNode(value.getReference());
957 private void emitRefineContainerNodes(final ContainerSchemaNode value) {
958 final ContainerSchemaNode original = getOriginalChecked(value);
960 // emitMustNodes(child.getConstraints().getMustConstraints());
961 if (Objects.deepEquals(original.isPresenceContainer(), value.isPresenceContainer())) {
962 emitPresenceNode(value.isPresenceContainer());
964 if (Objects.deepEquals(original.isConfiguration(), value.isConfiguration())) {
965 emitConfigNode(value.isConfiguration());
967 emitDocumentedNodeRefine(original, value);
971 private void emitRefineLeafNodes(final LeafSchemaNode value) {
972 final LeafSchemaNode original = getOriginalChecked(value);
974 // emitMustNodes(child.getConstraints().getMustConstraints());
975 if (Objects.deepEquals(original.getDefault(), value.getDefault())) {
976 emitDefaultNode(value.getDefault());
978 if (Objects.deepEquals(original.isConfiguration(), value.isConfiguration())) {
979 emitConfigNode(value.isConfiguration());
981 emitDocumentedNodeRefine(original, value);
982 if (Objects.deepEquals(original.getConstraints().isMandatory(), value.getConstraints().isMandatory())) {
983 emitMandatoryNode(value.getConstraints().isMandatory());
988 private void emitRefineLeafListNodes(final LeafListSchemaNode value) {
989 final LeafListSchemaNode original = getOriginalChecked(value);
991 // emitMustNodes(child.getConstraints().getMustConstraints());
992 if (Objects.deepEquals(original.isConfiguration(), value.isConfiguration())) {
993 emitConfigNode(value.isConfiguration());
995 if (Objects.deepEquals(original.getConstraints().getMinElements(), value.getConstraints().getMinElements())) {
996 emitMinElementsNode(value.getConstraints().getMinElements());
998 if (Objects.deepEquals(original.getConstraints().getMaxElements(), value.getConstraints().getMaxElements())) {
999 emitMaxElementsNode(value.getConstraints().getMaxElements());
1001 emitDocumentedNodeRefine(original, value);
1005 private void emitRefineListNodes(final ListSchemaNode value) {
1006 final ListSchemaNode original = getOriginalChecked(value);
1008 // emitMustNodes(child.getConstraints().getMustConstraints());
1009 if (Objects.deepEquals(original.isConfiguration(), value.isConfiguration())) {
1010 emitConfigNode(value.isConfiguration());
1012 if (Objects.deepEquals(original.getConstraints().getMinElements(), value.getConstraints().getMinElements())) {
1013 emitMinElementsNode(value.getConstraints().getMinElements());
1015 if (Objects.deepEquals(original.getConstraints().getMaxElements(), value.getConstraints().getMaxElements())) {
1016 emitMaxElementsNode(value.getConstraints().getMaxElements());
1018 emitDocumentedNodeRefine(original, value);
1022 private void emitRefineChoiceNodes(final ChoiceSchemaNode value) {
1023 final ChoiceSchemaNode original = getOriginalChecked(value);
1025 // FIXME: BUG-2444: defaultNode //FIXME: BUG-2444: Optional
1026 if (Objects.deepEquals(original.isConfiguration(), value.isConfiguration())) {
1027 emitConfigNode(value.isConfiguration());
1029 if (Objects.deepEquals(original.getConstraints().isMandatory(), value.getConstraints().isMandatory())) {
1030 emitMandatoryNode(value.getConstraints().isMandatory());
1032 emitDocumentedNodeRefine(original, value);
1036 private void emitRefineCaseNodes(final ChoiceCaseNode value) {
1037 final ChoiceCaseNode original = getOriginalChecked(value);
1038 emitDocumentedNodeRefine(original, value);
1042 private void emitRefineAnyxmlNodes(final AnyXmlSchemaNode value) {
1043 final AnyXmlSchemaNode original = getOriginalChecked(value);
1045 // FIXME: BUG-2444: emitMustNodes(child.getConstraints().getMustConstraints());
1046 if (Objects.deepEquals(original.isConfiguration(), value.isConfiguration())) {
1047 emitConfigNode(value.isConfiguration());
1049 if (Objects.deepEquals(original.getConstraints().isMandatory(), value.getConstraints().isMandatory())) {
1050 emitMandatoryNode(value.getConstraints().isMandatory());
1052 emitDocumentedNodeRefine(original, value);
1056 private void emitUsesAugmentNode(final AugmentationSchema aug) {
1058 * differs only in location in schema, otherwise currently (as of
1059 * RFC6020) it is same, so we could freely reuse path.
1064 private void emitAugment(final AugmentationSchema augmentation) {
1065 writer.startAugmentNode(augmentation.getTargetPath());
1066 // FIXME: BUG-2444: whenNode //Optional
1067 // FIXME: BUG-2444: *(ifFeatureNode )
1069 emitStatusNode(augmentation.getStatus());
1070 emitDescriptionNode(augmentation.getDescription());
1071 emitReferenceNode(augmentation.getReference());
1072 for (final UsesNode uses: augmentation.getUses()) {
1076 for (final DataSchemaNode childNode : augmentation.getChildNodes()) {
1077 if (childNode instanceof ChoiceCaseNode) {
1078 emitCaseNode((ChoiceCaseNode) childNode);
1080 emitDataSchemaNode(childNode);
1083 emitUnknownStatementNodes(augmentation.getUnknownSchemaNodes());
1087 private void emitUnknownStatementNodes(final List<UnknownSchemaNode> unknownNodes) {
1088 for (final UnknownSchemaNode unknonwnNode : unknownNodes) {
1089 if (!unknonwnNode.isAddedByAugmentation() && !unknonwnNode.isAddedByUses()) {
1090 emitUnknownStatementNode(unknonwnNode);
1095 private void emitUnknownStatementNode(final UnknownSchemaNode node) {
1096 final StatementDefinition def = getStatementChecked(node.getNodeType());
1097 if (def.getArgumentName() == null) {
1098 writer.startUnknownNode(def);
1100 writer.startUnknownNode(def, node.getNodeParameter());
1102 emitUnknownStatementNodes(node.getUnknownSchemaNodes());
1106 private StatementDefinition getStatementChecked(final QName nodeType) {
1107 final StatementDefinition ret = extensions.get(nodeType);
1108 Preconditions.checkArgument(ret != null, "Unknown extension %s used during export.",nodeType);
1112 private void emitWhen(final RevisionAwareXPath revisionAwareXPath) {
1113 if (revisionAwareXPath != null) {
1114 writer.startWhenNode(revisionAwareXPath);
1117 // FIXME: BUG-2444: descriptionNode //FIXME: BUG-2444: Optional
1118 // FIXME: BUG-2444: referenceNode //FIXME: BUG-2444: Optional
1119 // FIXME: BUG-2444: writer.endNode();)
1123 private void emitRpc(final RpcDefinition rpc) {
1124 writer.startRpcNode(rpc.getQName());
1125 // FIXME: BUG-2444: *(ifFeatureNode )
1126 emitStatusNode(rpc.getStatus());
1127 emitDescriptionNode(rpc.getDescription());
1128 emitReferenceNode(rpc.getReference());
1130 for (final TypeDefinition<?> typedef : rpc.getTypeDefinitions()) {
1131 emitTypedefNode(typedef);
1133 for (final GroupingDefinition grouping : rpc.getGroupings()) {
1134 emitGrouping(grouping);
1136 emitInput(rpc.getInput());
1137 emitOutput(rpc.getOutput());
1138 emitUnknownStatementNodes(rpc.getUnknownSchemaNodes());
1143 private void emitInput(@Nullable final ContainerSchemaNode input) {
1144 if (input != null) {
1145 writer.startInputNode();
1146 emitDataNodeContainer(input);
1147 emitUnknownStatementNodes(input.getUnknownSchemaNodes());
1153 private void emitOutput(@Nullable final ContainerSchemaNode input) {
1154 if (input != null) {
1155 writer.startOutputNode();
1156 emitDataNodeContainer(input);
1157 emitUnknownStatementNodes(input.getUnknownSchemaNodes());
1163 private void emitNotificationNode(final NotificationDefinition notification) {
1164 writer.startNotificationNode(notification.getQName());
1165 // FIXME: BUG-2444: *(ifFeatureNode )
1166 emitDocumentedNode(notification);
1167 emitDataNodeContainer(notification);
1168 emitUnknownStatementNodes(notification.getUnknownSchemaNodes());
1174 //FIXME: Probably should be moved to utils bundle.
1175 private static <T> boolean isPrefix(final Iterable<T> prefix, final Iterable<T> other) {
1176 final Iterator<T> prefixIt = prefix.iterator();
1177 final Iterator<T> otherIt = other.iterator();
1178 while (prefixIt.hasNext()) {
1179 if (!otherIt.hasNext()) {
1182 if (!Objects.deepEquals(prefixIt.next(), otherIt.next())) {
1189 private void emitDeviation(final Deviation deviation) {
1191 * FIXME: BUG-2444: Deviation is not modeled properly and we are loosing lot of
1192 * information in order to export it properly
1194 * writer.startDeviationNode(deviation.getTargetPath());
1196 * :descriptionNode //:Optional
1199 * emitReferenceNode(deviation.getReference());
1200 * :(deviateNotSupportedNode :1*(deviateAddNode :deviateReplaceNode
1201 * :deviateDeleteNode)) :writer.endNode();