From: Jakub Toth Date: Tue, 6 Jun 2017 13:20:02 +0000 (+0200) Subject: Binding v2 DOM Codec - generator - SPI - part 2 X-Git-Tag: release/nitrogen~141 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=6cd0af8477aeb6ae2e3acc602e06b32804db4cdc;p=mdsal.git Binding v2 DOM Codec - generator - SPI - part 2 * prepare base SPI parts of generating serializers for writers * added implementation of StreamWriterGenerator Change-Id: I9445495e5893296e1384b258856eca8236ea6698 Signed-off-by: Jakub Toth --- diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/impl/StreamWriterGenerator.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/impl/StreamWriterGenerator.java new file mode 100644 index 0000000000..78ab7daaf1 --- /dev/null +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/impl/StreamWriterGenerator.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.mdsal.binding.javav2.dom.codec.generator.impl; + +import com.google.common.annotations.Beta; +import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.api.TreeNodeSerializerGenerator; +import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.spi.generator.AbstractStreamWriterGenerator; +import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.spi.source.AbstractAugmentableDataNodeContainerEmitterSource; +import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.spi.source.AbstractDataNodeContainerSerializerSource; +import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.spi.source.AbstractTreeNodeSerializerSource; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.serializer.AugmentableDispatchSerializer; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.serializer.ChoiceDispatchSerializer; +import org.opendaylight.mdsal.binding.javav2.generator.impl.util.javassist.JavassistUtils; +import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingStreamEventWriter; +import org.opendaylight.mdsal.binding.javav2.spec.runtime.TreeNodeSerializerImplementation; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; + +/** + * Concrete implementation of {@link AbstractStreamWriterGenerator} which in + * runtime generates classes implementing + * {@link TreeNodeSerializerImplementation} interface and are used to serialize + * Binding {@link TreeNode}. + * + * Actual implementation of codecs is done via static methods, which allows for + * static wiring of codecs. Choice codec and Augmentable codecs are static + * properties of parent codec and stateless implementations are used ( + * {@link ChoiceDispatchSerializer}, {@link AugmentableDispatchSerializer}, + * which uses registry to dispatch to concrete item codec. + * + */ +@Beta +public class StreamWriterGenerator extends AbstractStreamWriterGenerator { + + private static final String UNKNOWN_SIZE = BindingStreamEventWriter.class.getName() + ".UNKNOWN_SIZE"; + + private StreamWriterGenerator(final JavassistUtils utils, final Void ignore) { + super(utils); + } + + /** + * Create a new instance backed by a specific {@link JavassistUtils} + * instance. + * + * @param utils + * JavassistUtils instance to use + * @return A new generator + */ + public static TreeNodeSerializerGenerator create(final JavassistUtils utils) { + return new StreamWriterGenerator(utils, null); + } + + @Override + protected AbstractTreeNodeSerializerSource generateContainerSerializer(final GeneratedType type, + final ContainerSchemaNode node) { + + return new AbstractAugmentableDataNodeContainerEmitterSource(this, type, node) { + @Override + public CharSequence emitStartEvent() { + return startContainerNode(classReference(type), UNKNOWN_SIZE); + } + }; + } + + @Override + protected AbstractTreeNodeSerializerSource generateNotificationSerializer(final GeneratedType type, + final NotificationDefinition node) { + + return new AbstractAugmentableDataNodeContainerEmitterSource(this, type, node) { + @Override + public CharSequence emitStartEvent() { + return startContainerNode(classReference(type), UNKNOWN_SIZE); + } + }; + } + + @Override + protected AbstractTreeNodeSerializerSource generateCaseSerializer(final GeneratedType type, + final ChoiceCaseNode node) { + return new AbstractAugmentableDataNodeContainerEmitterSource(this, type, node) { + @Override + public CharSequence emitStartEvent() { + return startCaseNode(classReference(type), UNKNOWN_SIZE); + } + }; + } + + @Override + protected AbstractTreeNodeSerializerSource generateUnkeyedListEntrySerializer(final GeneratedType type, + final ListSchemaNode node) { + return new AbstractAugmentableDataNodeContainerEmitterSource(this, type, node) { + + @Override + public CharSequence emitStartEvent() { + return startUnkeyedListItem(UNKNOWN_SIZE); + } + }; + } + + @Override + protected AbstractTreeNodeSerializerSource generateSerializer(final GeneratedType type, + final AugmentationSchema schema) { + return new AbstractDataNodeContainerSerializerSource(this, type, schema) { + + @Override + public CharSequence emitStartEvent() { + return startAugmentationNode(classReference(type)); + } + }; + } + + @Override + protected AbstractTreeNodeSerializerSource generateMapEntrySerializer(final GeneratedType type, + final ListSchemaNode node) { + return new AbstractAugmentableDataNodeContainerEmitterSource(this, type, node) { + @Override + public CharSequence emitStartEvent() { + return startMapEntryNode(invoke(INPUT, "getKey"), UNKNOWN_SIZE); + } + }; + } +} diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/generator/AbstractStreamWriterGenerator.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/generator/AbstractStreamWriterGenerator.java index 4924d3f161..8831609f21 100644 --- a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/generator/AbstractStreamWriterGenerator.java +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/generator/AbstractStreamWriterGenerator.java @@ -53,7 +53,7 @@ public abstract class AbstractStreamWriterGenerator extends AbstractGenerator im private static final Logger LOG = LoggerFactory.getLogger(AbstractStreamWriterGenerator.class); public static final String SERIALIZE_METHOD_NAME = "serialize"; - protected static final AugmentableDispatchSerializer AUGMENTABLE = new AugmentableDispatchSerializer(); + public static final AugmentableDispatchSerializer AUGMENTABLE = new AugmentableDispatchSerializer(); private static final Field FIELD_MODIFIERS; private final LoadingCache, TreeNodeSerializerImplementation> implementations; diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractAugmentableDataNodeContainerEmitterSource.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractAugmentableDataNodeContainerEmitterSource.java new file mode 100644 index 0000000000..5ddd7ee425 --- /dev/null +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractAugmentableDataNodeContainerEmitterSource.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.mdsal.binding.javav2.dom.codec.generator.spi.source; + +import com.google.common.annotations.Beta; +import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.impl.StreamWriterGenerator; +import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.spi.generator.AbstractStreamWriterGenerator; +import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType; +import org.opendaylight.mdsal.binding.javav2.spec.runtime.TreeNodeSerializerImplementation; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; + +@Beta +public abstract class AbstractAugmentableDataNodeContainerEmitterSource + extends AbstractDataNodeContainerSerializerSource { + + private static final String AUGMENTABLE_SERIALIZER = "AUGMENTABLE_SERIALIZER"; + + public AbstractAugmentableDataNodeContainerEmitterSource(final AbstractStreamWriterGenerator generator, + final GeneratedType type, final DataNodeContainer node) { + super(generator, type, node); + /* + * Eventhough intuition says the serializer could reference the + * generator directly, that is not true in OSGi environment -- so we + * need to resolve the reference first and inject it as a static + * constant. + */ + staticConstant(AUGMENTABLE_SERIALIZER, TreeNodeSerializerImplementation.class, + StreamWriterGenerator.AUGMENTABLE); + } + + @Override + protected void emitAfterBody(final StringBuilder b) { + b.append(statement(invoke(AUGMENTABLE_SERIALIZER, "serialize", REGISTRY, INPUT, STREAM))); + } +} diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractDataNodeContainerSerializerSource.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractDataNodeContainerSerializerSource.java new file mode 100644 index 0000000000..a66cfa5acf --- /dev/null +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractDataNodeContainerSerializerSource.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.mdsal.binding.javav2.dom.codec.generator.spi.source; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.util.HashMap; +import java.util.Map; +import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.impl.StreamWriterGenerator; +import org.opendaylight.mdsal.binding.javav2.dom.codec.generator.spi.generator.AbstractGenerator; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.serializer.ChoiceDispatchSerializer; +import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier; +import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer; +import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType; +import org.opendaylight.mdsal.binding.javav2.model.api.MethodSignature; +import org.opendaylight.mdsal.binding.javav2.model.api.ParameterizedType; +import org.opendaylight.mdsal.binding.javav2.model.api.Type; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingSerializer; +import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingStreamEventWriter; +import org.opendaylight.mdsal.binding.javav2.spec.runtime.TreeNodeSerializerImplementation; +import org.opendaylight.mdsal.binding.javav2.spec.runtime.TreeNodeSerializerRegistry; +import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.TypedSchemaNode; +import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Beta +public abstract class AbstractDataNodeContainerSerializerSource extends AbstractTreeNodeSerializerSource { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractDataNodeContainerSerializerSource.class); + + protected static final String INPUT = "_input"; + private static final String CHOICE_PREFIX = "CHOICE_"; + + private final DataNodeContainer schemaNode; + private final GeneratedType dtoType; + + public AbstractDataNodeContainerSerializerSource(final AbstractGenerator generator, final GeneratedType type, + final DataNodeContainer node) { + super(generator); + this.dtoType = Preconditions.checkNotNull(type); + this.schemaNode = Preconditions.checkNotNull(node); + } + + /** + * Return the character sequence which should be used for start event. + * + * @return Start event character sequence + */ + protected abstract CharSequence emitStartEvent(); + + @Override + public CharSequence getSerializerBody() { + final StringBuilder b = new StringBuilder(); + b.append("{\n"); + b.append(statement(assign(TreeNodeSerializerRegistry.class.getName(), REGISTRY, "$1"))); + b.append(statement(assign(dtoType.getFullyQualifiedName(), INPUT, + cast(dtoType.getFullyQualifiedName(), "$2")))); + b.append(statement(assign(BindingStreamEventWriter.class.getName(), STREAM, cast(BindingStreamEventWriter.class.getName(), "$3")))); + b.append(statement(assign(BindingSerializer.class.getName(), SERIALIZER, null))); + b.append("if ("); + b.append(STREAM); + b.append(" instanceof "); + b.append(BindingSerializer.class.getName()); + b.append(") {"); + b.append(statement(assign(SERIALIZER, cast(BindingSerializer.class.getName(), STREAM)))); + b.append('}'); + b.append(statement(emitStartEvent())); + + emitBody(b); + emitAfterBody(b); + b.append(statement(endNode())); + b.append(statement("return null")); + b.append('}'); + return b; + } + + /** + * Allows for customization of emitting code, which is processed after + * normal DataNodeContainer body. Ideal for augmentations or others. + */ + protected void emitAfterBody(final StringBuilder b) { + } + + private static Map collectAllProperties(final GeneratedType type, final Map hashMap) { + for (final MethodSignature definition : type.getMethodDefinitions()) { + hashMap.put(definition.getName(), definition.getReturnType()); + } + for (final Type parent : type.getImplements()) { + if (parent instanceof GeneratedType) { + collectAllProperties((GeneratedType) parent, hashMap); + } + } + return hashMap; + } + + private static String getGetterName(final DataSchemaNode node) { + final TypeDefinition type; + if (node instanceof TypedSchemaNode) { + type = ((TypedSchemaNode) node).getType(); + } else { + type = null; + } + + final String prefix; + if (type instanceof BooleanTypeDefinition || type instanceof EmptyTypeDefinition) { + prefix = "is"; + } else { + prefix = "get"; + } + return prefix + JavaIdentifierNormalizer.normalizeSpecificIdentifier(node.getQName().getLocalName(), JavaIdentifier.CLASS); + } + + private void emitBody(final StringBuilder b) { + final Map getterToType = collectAllProperties(dtoType, new HashMap()); + for (final DataSchemaNode schemaChild : schemaNode.getChildNodes()) { + if (!schemaChild.isAugmenting()) { + final String getter = getGetterName(schemaChild); + final Type childType = getterToType.get(getter); + if (childType == null) { + // FIXME AnyXml nodes are ignored, since their type cannot be found in generated bindnig + // Bug-706 https://bugs.opendaylight.org/show_bug.cgi?id=706 + if (schemaChild instanceof AnyXmlSchemaNode) { + LOG.warn("Node {} will be ignored. AnyXml is not yet supported from binding aware code." + + "Binding Independent code can be used to serialize anyXml nodes.", schemaChild.getPath()); + continue; + } + + throw new IllegalStateException( + String.format("Unable to find type for child node %s. Expected child nodes: %s", + schemaChild.getPath(), getterToType)); + } + emitChild(b, getter, childType, schemaChild); + } + } + } + + private void emitChild(final StringBuilder b, final String getterName, final Type childType, + final DataSchemaNode schemaChild) { + b.append(statement(assign(childType, getterName, cast(childType, invoke(INPUT, getterName))))); + + b.append("if (").append(getterName).append(" != null) {\n"); + emitChildInner(b, getterName, childType, schemaChild); + b.append("}\n"); + } + + private void emitChildInner(final StringBuilder b, final String getterName, final Type childType, + final DataSchemaNode child) { + if (child instanceof LeafSchemaNode) { + b.append(statement(leafNode(child.getQName().getLocalName(), getterName))); + } else if (child instanceof AnyXmlSchemaNode) { + b.append(statement(anyxmlNode(child.getQName().getLocalName(), getterName))); + } else if (child instanceof LeafListSchemaNode) { + final CharSequence startEvent; + if (((LeafListSchemaNode) child).isUserOrdered()) { + startEvent = startOrderedLeafSet(child.getQName().getLocalName(),invoke(getterName, "size")); + } else { + startEvent = startLeafSet(child.getQName().getLocalName(),invoke(getterName, "size")); + } + b.append(statement(startEvent)); + final Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0]; + b.append(forEach(getterName, valueType, statement(leafSetEntryNode(CURRENT)))); + b.append(statement(endNode())); + } else if (child instanceof ListSchemaNode) { + final Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0]; + final ListSchemaNode casted = (ListSchemaNode) child; + emitList(b, getterName, valueType, casted); + } else if (child instanceof ContainerSchemaNode) { + b.append(tryToUseCacheElse(getterName,statement(staticInvokeEmitter(childType, getterName)))); + } else if (child instanceof ChoiceSchemaNode) { + final String propertyName = CHOICE_PREFIX + childType.getName(); + staticConstant(propertyName, TreeNodeSerializerImplementation.class, ChoiceDispatchSerializer.from(loadClass(childType))); + b.append(tryToUseCacheElse(getterName,statement(invoke(propertyName, StreamWriterGenerator.SERIALIZE_METHOD_NAME, REGISTRY, cast(TreeNode.class.getName(),getterName), STREAM)))); + } + } + + private static StringBuilder tryToUseCacheElse(final String getterName, final CharSequence statement) { + final StringBuilder b = new StringBuilder(); + + b.append("if ( "); + b.append(SERIALIZER).append("== null || "); + b.append(invoke(SERIALIZER, "serialize", getterName)).append("== null"); + b.append(") {"); + b.append(statement); + b.append('}'); + return b; + } + + private void emitList(final StringBuilder b, final String getterName, final Type valueType, + final ListSchemaNode child) { + final CharSequence startEvent; + + b.append(statement(assign("int", "_count", invoke(getterName, "size")))); + if (child.getKeyDefinition().isEmpty()) { + startEvent = startUnkeyedList(classReference(valueType), "_count"); + } else if (child.isUserOrdered()) { + startEvent = startOrderedMapNode(classReference(valueType), "_count"); + } else { + startEvent = startMapNode(classReference(valueType), "_count"); + } + b.append(statement(startEvent)); + b.append(forEach(getterName, valueType, tryToUseCacheElse(CURRENT,statement(staticInvokeEmitter(valueType, CURRENT))))); + b.append(statement(endNode())); + } +} diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractSource.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractSource.java index 0d44cc4280..97c6efbff3 100644 --- a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractSource.java +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractSource.java @@ -94,7 +94,7 @@ abstract class AbstractSource { * - arguments of method * @return invoking method on object with more arguments as String */ - static final CharSequence invoke(final CharSequence object, final String methodName, + protected static final CharSequence invoke(final CharSequence object, final String methodName, final Object... args) { final StringBuilder sb = prepareCommonInvokePart(object, methodName); diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractTreeNodeSerializerSource.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractTreeNodeSerializerSource.java index d6307d03b6..16675cf685 100644 --- a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractTreeNodeSerializerSource.java +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/generator/spi/source/AbstractTreeNodeSerializerSource.java @@ -138,7 +138,7 @@ public abstract class AbstractTreeNodeSerializerSource extends AbstractSource { * - argument for invoking startContainerNode * @return invoking startContainerNode method as String */ - static final CharSequence startContainerNode(final CharSequence type, final CharSequence expected) { + public static final CharSequence startContainerNode(final CharSequence type, final CharSequence expected) { return invoke(STREAM, "startContainerNode", type, expected); } @@ -163,7 +163,7 @@ public abstract class AbstractTreeNodeSerializerSource extends AbstractSource { * - argument for invoking startUnkeyedListItem * @return invoking startUnkeyedListItem method as String */ - static final CharSequence startUnkeyedListItem(final CharSequence expected) { + protected static final CharSequence startUnkeyedListItem(final CharSequence expected) { return invoke(STREAM, "startUnkeyedListItem", expected); } @@ -204,7 +204,7 @@ public abstract class AbstractTreeNodeSerializerSource extends AbstractSource { * - argument for invoking startMapEntryNode * @return invoking startMapEntryNode method as String */ - static final CharSequence startMapEntryNode(final CharSequence key, final CharSequence expected) { + protected static final CharSequence startMapEntryNode(final CharSequence key, final CharSequence expected) { return invoke(STREAM, "startMapEntryNode", key, expected); } @@ -215,7 +215,7 @@ public abstract class AbstractTreeNodeSerializerSource extends AbstractSource { * - argument for invoking startAugmentationNode * @return invoking startAugmentationNode method as String */ - static final CharSequence startAugmentationNode(final CharSequence key) { + protected static final CharSequence startAugmentationNode(final CharSequence key) { return invoke(STREAM, "startAugmentationNode", key); } @@ -243,7 +243,7 @@ public abstract class AbstractTreeNodeSerializerSource extends AbstractSource { * - argument for invoking startCaseNode * @return invoking startCaseNode method as String */ - static final CharSequence startCaseNode(final CharSequence localName, final CharSequence expected) { + protected static final CharSequence startCaseNode(final CharSequence localName, final CharSequence expected) { return invoke(STREAM, "startCase", localName, expected); } @@ -308,7 +308,7 @@ public abstract class AbstractTreeNodeSerializerSource extends AbstractSource { * - type for referencing class * @return referenced class of type */ - static final CharSequence classReference(final Type type) { + protected static final CharSequence classReference(final Type type) { return type.getFullyQualifiedName() + ".class"; }