import java.lang.reflect.Array;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Arrays;
+import java.util.Base64;
import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
return 0;
}
- if (byte[].class.equals(value.getClass())) {
- return Arrays.hashCode((byte[]) value);
+ if (value instanceof byte[] bytes) {
+ return Arrays.hashCode(bytes);
}
if (value.getClass().isArray()) {
return hash;
}
- return Objects.hashCode(value);
+ return value.hashCode();
}
private int loadHashCode() {
@Override
@SuppressWarnings("checkstyle:equalsHashCode")
public boolean equals(final Object obj) {
- if (!super.equals(obj)) {
- return false;
- }
- final NodeWithValue<?> other = (NodeWithValue<?>) obj;
- return Objects.deepEquals(value, other.value);
+ return super.equals(obj) && Objects.deepEquals(value, ((NodeWithValue<?>) obj).value);
}
@Override
public String toString() {
- return super.toString() + '[' + value + ']';
+ final var str = super.toString();
+ return value instanceof byte[] bytes ? str + "[b64:" + Base64.getEncoder().encodeToString(bytes) + ']'
+ : str + '[' + value + ']';
}
@Override
/**
* Abstract base class for {@link LeafNode} implementations.
*/
-public abstract non-sealed class AbstractLeafNode<T> extends AbstractNormalizedSimpleValueNode<LeafNode<T>, T>
+public abstract non-sealed class AbstractLeafNode<T> extends AbstractValueNode<LeafNode<T>, T>
implements LeafNode<T> {
@Override
@SuppressWarnings("unchecked")
* Abstract base class for {@link LeafSetEntryNode} implementations.
*/
public abstract non-sealed class AbstractLeafSetEntryNode<T>
- extends AbstractNormalizedSimpleValueNode<LeafSetEntryNode<T>, T> implements LeafSetEntryNode<T> {
+ extends AbstractValueNode<LeafSetEntryNode<T>, T> implements LeafSetEntryNode<T> {
@Override
@SuppressWarnings("unchecked")
protected final Class<LeafSetEntryNode<T>> implementedType() {
@Override
public final String toString() {
- return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
+ return addToStringAttributes(MoreObjects.toStringHelper(toStringClass())).toString();
+ }
+
+ /**
+ * Return the {@link #toString()} class identity of this object. Default implementation defers to
+ * {@link #getClass()}. Override may be needed to hide implementation-internal class hierarchy -- for example if
+ * providing different implementations of {@link LeafNode} for {@code String} and {@code byte[]} values.
+ *
+ * @return the {@link #toString()} class identity of this object
+ */
+ protected @NonNull Class<?> toStringClass() {
+ return getClass();
+ }
+
+ @NonNull Object toStringBody() {
+ return body();
}
protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
- return toStringHelper.add("name", name()).add("body", body());
+ return toStringHelper.add("name", name()).add("body", toStringBody());
}
protected abstract @NonNull Class<T> implementedType();
abstract sealed class AbstractNormalizedSimpleValueNode<N extends NormalizedNode, V>
extends AbstractNormalizedValueNode<N, V>
- permits AbstractAnydataNode, AbstractAnyxmlNode, AbstractLeafNode, AbstractLeafSetEntryNode {
+ permits AbstractAnydataNode, AbstractAnyxmlNode, AbstractValueNode {
@Override
protected final int valueHashCode() {
return value().hashCode();
--- /dev/null
+/*
+ * Copyright (c) 2024 PANTHEON.tech, 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.yangtools.yang.data.api.schema;
+
+import java.util.Base64;
+
+abstract sealed class AbstractValueNode<N extends ValueNode<V>, V> extends AbstractNormalizedSimpleValueNode<N, V>
+ implements ValueNode<V> permits AbstractLeafNode, AbstractLeafSetEntryNode {
+ @Override
+ final Object toStringBody() {
+ final var body = body();
+ return body instanceof byte[] bytes ? "b64:" + Base64.getEncoder().encodeToString(bytes) : body;
+ }
+}
*
* @param <V> Value of node, which needs to be a well-published simple value type.
*/
-public sealed interface ValueNode<V> extends NormalizedNode permits LeafNode, LeafSetEntryNode {
+public sealed interface ValueNode<V> extends NormalizedNode permits LeafNode, LeafSetEntryNode, AbstractValueNode {
/**
* {@inheritDoc}
*
protected final T value() {
return value;
}
+
+ @Override
+ protected final Class<?> toStringClass() {
+ return ImmutableLeafNode.class;
+ }
}
protected final T value() {
return name.getValue();
}
+
+ @Override
+ protected final Class<?> toStringClass() {
+ return ImmutableLeafSetEntryNode.class;
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2024 PANTHEON.tech, 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.yangtools.yang.data.spi.node.impl;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+
+class YT1562Test {
+ @Test
+ void regualarLeafToString() {
+ assertEquals("ImmutableLeafNode{name=(test)test, body=42}",
+ ImmutableLeafNode.of(new NodeIdentifier(QName.create("test", "test")), 42).toString());
+ }
+
+ @Test
+ void binaryLeafToString() {
+ assertEquals("ImmutableLeafNode{name=(test)test, body=b64:Kis=}",
+ ImmutableLeafNode.of(new NodeIdentifier(QName.create("test", "test")), new byte[] { 42, 43 }).toString());
+ }
+
+ @Test
+ void regualarLeafSetEntryToString() {
+ assertEquals("ImmutableLeafSetEntryNode{name=(test)test[42], body=42}",
+ ImmutableLeafSetEntryNode.of(new NodeWithValue<>(QName.create("test", "test"), 42)).toString());
+ }
+
+ @Test
+ void binaryLeafSetEntryToString() {
+ assertEquals("ImmutableLeafSetEntryNode{name=(test)test[b64:Kis=], body=b64:Kis=}",
+ ImmutableLeafSetEntryNode.of(new NodeWithValue<>(QName.create("test", "test"), new byte[] { 42, 43 }))
+ .toString());
+ }
+}