import com.google.common.collect.ImmutableMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
* This model of metadata <em>does not</em> have the RFC7952 restriction on metadata attachment to {@code list}s and
* {@code leaf-list}s because NormalizedNode data model has {@link LeafSetNode}, {@link MapNode} and
* {@link UnkeyedListNode} to which metadata can be attached.
- *
- * @author Robert Varga
*/
@Beta
-public interface NormalizedMetadata extends Identifiable<PathArgument>, Immutable {
+public interface NormalizedMetadata extends Immutable {
/**
* Return the set of annotations defined in this metadata node. Values are expected to be effectively-immutable
* scalar types, like {@link String}s, {@link Number}s and similar. The map must also be effectively-immutable.
import java.util.Deque;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedMetadata;
* Snapshot of currently-open data- and metadatastate.
*/
public static final class State {
- final Builder metaBuilder;
+ final BuilderEntry metaBuilder;
final NormalizedNodeBuilder dataBuilder;
- State(final NormalizedNodeBuilder dataBuilder, final Builder metadataBuilder) {
+ State(final NormalizedNodeBuilder dataBuilder, final BuilderEntry metadataBuilder) {
this.dataBuilder = requireNonNull(dataBuilder);
metaBuilder = requireNonNull(metadataBuilder);
}
}
public Builder getMetaBuilder() {
- return metaBuilder;
+ return metaBuilder.builder;
}
}
- private final Deque<Builder> builders = new ArrayDeque<>();
+ @NonNullByDefault
+ private record BuilderEntry(PathArgument identifier, Builder builder) {
+ BuilderEntry {
+ requireNonNull(identifier);
+ requireNonNull(builder);
+ }
+ }
+
+ private final Deque<BuilderEntry> builders = new ArrayDeque<>();
private final NormalizationResultHolder holder;
protected ImmutableMetadataNormalizedNodeStreamWriter(final State state) {
- super(state.getDataBuilder());
- builders.push(state.getMetaBuilder());
+ super(state.dataBuilder);
+ builders.push(state.metaBuilder);
holder = null;
}
@Override
public final void metadata(final ImmutableMap<QName, Object> metadata) throws IOException {
- final Builder current = builders.peek();
+ final var current = builders.peek();
checkState(current != null, "Attempted to emit metadata when no metadata is open");
- current.withAnnotations(metadata);
+ current.builder.withAnnotations(metadata);
}
/**
@SuppressWarnings("rawtypes")
final void enter(final PathArgument identifier, final NormalizedNodeBuilder next) {
super.enter(identifier, next);
- builders.push(ImmutableNormalizedMetadata.builder().withIdentifier(identifier));
+ builders.push(new BuilderEntry(identifier, ImmutableNormalizedMetadata.builder()));
}
@Override
public final void endNode() {
super.endNode();
- final ImmutableNormalizedMetadata metadata = builders.pop().build();
- final Builder current = builders.peek();
+
+ final var last = builders.pop();
+ final var metadata = last.builder.build();
+ final var current = builders.peek();
if (current != null) {
if (!metadata.getAnnotations().isEmpty() || !metadata.getChildren().isEmpty()) {
- current.withChild(metadata);
+ current.builder.withChild(last.identifier, metadata);
}
} else {
// All done
*/
package org.opendaylight.yangtools.yang.data.util;
-import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableMap;
-import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.concepts.AbstractSimpleIdentifiable;
import org.opendaylight.yangtools.concepts.Mutable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
/**
* Immutable implementation of {@link NormalizedMetadata}.
*/
-public sealed class ImmutableNormalizedMetadata extends AbstractSimpleIdentifiable<PathArgument>
- implements NormalizedMetadata {
+public sealed class ImmutableNormalizedMetadata implements NormalizedMetadata {
private static final class Container extends ImmutableNormalizedMetadata {
private final @NonNull ImmutableMap<PathArgument, NormalizedMetadata> children;
- Container(final PathArgument identifier, final Map<QName, Object> annotations,
+ Container(final Map<QName, Object> annotations,
final Map<PathArgument, ImmutableNormalizedMetadata> children) {
- super(identifier, annotations);
+ super(annotations);
this.children = ImmutableMap.copyOf(children);
}
private final @NonNull ImmutableMap<QName, Object> annotations;
- ImmutableNormalizedMetadata(final @NonNull PathArgument identifier, final Map<QName, Object> annotations) {
- super(identifier);
+ ImmutableNormalizedMetadata(final Map<QName, Object> annotations) {
this.annotations = ImmutableMap.copyOf(annotations);
}
public static final class Builder implements Mutable {
private final Map<PathArgument, ImmutableNormalizedMetadata> children = new HashMap<>();
private final Map<QName, Object> annotations = new HashMap<>();
- private PathArgument identifier;
Builder() {
// Hidden to prevent instantiation
}
- @SuppressWarnings("checkstyle:hiddenField")
- public @NonNull Builder withIdentifier(final PathArgument identifier) {
- this.identifier = requireNonNull(identifier);
- return this;
- }
-
public @NonNull Builder withAnnotation(final QName type, final Object value) {
annotations.put(requireNonNull(type, "type"), requireNonNull(value, "value"));
return this;
return this;
}
- public @NonNull Builder withChild(final ImmutableNormalizedMetadata child) {
- children.put(child.getIdentifier(), child);
+ public @NonNull Builder withChild(final PathArgument pathArgument, final ImmutableNormalizedMetadata child) {
+ children.put(requireNonNull(pathArgument, "pathArgument"), requireNonNull(child, "child"));
return this;
}
@SuppressWarnings("checkstyle:hiddenField")
- public @NonNull Builder withChildren(final Collection<ImmutableNormalizedMetadata> children) {
+ public @NonNull Builder withChildren(final Map<PathArgument, ImmutableNormalizedMetadata> children) {
children.forEach(this::withChild);
return this;
}
* @throws IllegalStateException if this builder does not have enough state
*/
public @NonNull ImmutableNormalizedMetadata build() {
- final PathArgument id = identifier;
- checkState(id != null, "Identifier has not been set");
- return children.isEmpty() ? new ImmutableNormalizedMetadata(id, annotations)
- : new Container(id, annotations, children);
+ return children.isEmpty() ? new ImmutableNormalizedMetadata(annotations)
+ : new Container(annotations, children);
}
}
}
package org.opendaylight.yangtools.yang.data.util;
import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedMetadata;
*/
@Beta
public final class ImmutableNormalizedMetadataStreamWriter implements MetadataExtension {
- private final Deque<Builder> builders = new ArrayDeque<>();
+ @NonNullByDefault
+ private record BuilderEntry(PathArgument identifier, Builder builder) {
+ BuilderEntry {
+ requireNonNull(identifier);
+ requireNonNull(builder);
+ }
+ }
+
+ private final Deque<BuilderEntry> builders = new ArrayDeque<>();
private ImmutableNormalizedMetadata result;
public void enter(final PathArgument identifier) {
checkNotDone();
- builders.push(ImmutableNormalizedMetadata.builder().withIdentifier(identifier));
+ builders.push(new BuilderEntry(identifier, ImmutableNormalizedMetadata.builder()));
}
public void exit() {
checkNotDone();
- final ImmutableNormalizedMetadata metadata = builders.pop().build();
- final Builder parent = builders.peek();
- if (parent != null) {
- if (!metadata.getAnnotations().isEmpty()) {
- parent.withChild(metadata);
+
+ final var last = builders.pop();
+ final var metadata = last.builder.build();
+ final var current = builders.peek();
+ if (current != null) {
+ if (!metadata.getAnnotations().isEmpty() || !metadata.getChildren().isEmpty()) {
+ current.builder().withChild(last.identifier, metadata);
}
} else {
result = metadata;
@Override
public void metadata(final ImmutableMap<QName, Object> metadata) throws IOException {
- builders.peek().withAnnotations(metadata);
+ builders.peek().builder.withAnnotations(metadata);
}
private void checkNotDone() {
*/
package org.opendaylight.yangtools.yang.data.util;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
import java.io.Flushable;
import java.io.IOException;
import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedMetadata;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
* @param metadata {@link NormalizedMetadata} metadata
* @return NormalizedNodeWriter this
* @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if metadata does not match data
* @throws IOException when thrown from the backing writer.
*/
public @NonNull NormalizedMetadataWriter write(final NormalizedNode data, final NormalizedMetadata metadata)
throws IOException {
- final PathArgument dataId = data.name();
- final PathArgument metaId = metadata.getIdentifier();
- checkArgument(dataId.equals(metaId), "Mismatched data %s and metadata %s", dataId, metaId);
-
final var metaWriter = writer.extension(MetadataExtension.class);
- final NormalizedNodeStreamWriter delegate = metaWriter == null ? writer
+ final var delegate = metaWriter == null ? writer
: new NormalizedNodeStreamWriterMetadataDecorator(writer, metaWriter, metadata);
- final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(delegate, orderKeyLeaves);
+ final var nnWriter = NormalizedNodeWriter.forStreamWriter(delegate, orderKeyLeaves);
nnWriter.write(data);
nnWriter.flush();
return this;