All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.restconf.server.spi.YangPatchStatusBody Maven / Gradle / Ivy

There is a newer version: 8.0.3
Show newest version
/*
 * 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.restconf.server.spi;

import static java.util.Objects.requireNonNull;

import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.opendaylight.restconf.api.FormattableBody;
import org.opendaylight.restconf.api.query.PrettyPrintParam;
import org.opendaylight.restconf.server.api.FormattableBodySupport;
import org.opendaylight.restconf.server.api.PatchStatusContext;
import org.opendaylight.restconf.server.api.ServerError;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.patch.rev170222.yang.patch.status.YangPatchStatus;
import org.opendaylight.yangtools.yang.data.codec.gson.DefaultJSONValueWriter;

/**
 * Result of a {@code PATCH} request as defined in
 * RFC8072, section 2.3.
 */
public final class YangPatchStatusBody extends FormattableBody {
    private static final String IETF_YANG_PATCH_NAMESPACE = YangPatchStatus.QNAME.getNamespace().toString();

    private final PatchStatusContext status;

    public YangPatchStatusBody(final PatchStatusContext status) {
        this.status = requireNonNull(status);
    }

    @Override
    public void formatToJSON(final PrettyPrintParam prettyPrint, final OutputStream out) throws IOException {
        try (var writer = FormattableBodySupport.createJsonWriter(out, prettyPrint)) {
            writer.beginObject().name("ietf-yang-patch:yang-patch-status")
                .beginObject().name("patch-id").value(status.patchId());

            if (status.ok()) {
                writeOk(writer);
            } else {
                final var globalErrors = status.globalErrors();
                if (globalErrors != null) {
                    writeErrors(globalErrors, writer);
                } else {
                    writer.name("edit-status").beginObject()
                        .name("edit").beginArray();
                    for (var editStatus : status.editCollection()) {
                        writer.beginObject().name("edit-id").value(editStatus.getEditId());

                        final var editErrors = editStatus.getEditErrors();
                        if (editErrors != null) {
                            writeErrors(editErrors, writer);
                        } else if (editStatus.isOk()) {
                            writeOk(writer);
                        }
                        writer.endObject();
                    }
                    writer.endArray().endObject();
                }
            }
            writer.endObject().endObject();
        }
    }

    @Override
    public void formatToXML(final PrettyPrintParam prettyPrint, final OutputStream out) throws IOException {
        final var writer = FormattableBodySupport.createXmlWriter(out, prettyPrint);
        try {
            formatToXML(writer);
        } catch (XMLStreamException e) {
            throw new IOException("Failed to write body", e);
        }
    }

    private void formatToXML(final XMLStreamWriter writer) throws XMLStreamException {
        writer.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, "yang-patch-status", IETF_YANG_PATCH_NAMESPACE);
        writer.writeDefaultNamespace(IETF_YANG_PATCH_NAMESPACE);
        writer.writeStartElement("patch-id");
        writer.writeCharacters(status.patchId());
        writer.writeEndElement();

        if (status.ok()) {
            writer.writeEmptyElement("ok");
        } else {
            final var globalErrors = status.globalErrors();
            if (globalErrors != null) {
                reportErrors(globalErrors, writer);
            } else {
                writer.writeStartElement("edit-status");
                for (var patchStatusEntity : status.editCollection()) {
                    writer.writeStartElement("edit");
                    writer.writeStartElement("edit-id");
                    writer.writeCharacters(patchStatusEntity.getEditId());
                    writer.writeEndElement();

                    final var editErrors = patchStatusEntity.getEditErrors();
                    if (editErrors != null) {
                        reportErrors(editErrors, writer);
                    } else if (patchStatusEntity.isOk()) {
                        writer.writeEmptyElement("ok");
                    }
                    writer.writeEndElement();
                }
                writer.writeEndElement();
            }
        }
        writer.writeEndElement();
        writer.close();
    }

    private static void writeOk(final JsonWriter writer) throws IOException {
        writer.name("ok").beginArray().nullValue().endArray();
    }

    private static void writeErrors(final List errors, final JsonWriter writer) throws IOException {
        writer.name("errors").beginObject().name("error").beginArray();

        for (var error : errors) {
            writer.beginObject()
                .name("error-type").value(error.type().elementBody())
                .name("error-tag").value(error.tag().elementBody());

            final var errorPath = error.path();
            if (errorPath != null) {
                writer.name("error-path");
                errorPath.databind().jsonCodecs().instanceIdentifierCodec()
                    .writeValue(new DefaultJSONValueWriter(writer), errorPath.path());
            }
            final var errorMessage = error.message();
            if (errorMessage != null) {
                writer.name("error-message").value(errorMessage.elementBody());
            }
            final var errorInfo = error.info();
            if (errorInfo != null) {
                writer.name("error-info").value(errorInfo.elementBody());
            }

            writer.endObject();
        }

        writer.endArray().endObject();
    }

    private static void reportErrors(final List errors, final XMLStreamWriter writer)
            throws XMLStreamException {
        writer.writeStartElement("errors");

        for (var restconfError : errors) {
            writer.writeStartElement("error-type");
            writer.writeCharacters(restconfError.type().elementBody());
            writer.writeEndElement();

            writer.writeStartElement("error-tag");
            writer.writeCharacters(restconfError.tag().elementBody());
            writer.writeEndElement();

            // optional node
            final var errorPath = restconfError.path();
            if (errorPath != null) {
                writer.writeStartElement("error-path");
                errorPath.databind().xmlCodecs().instanceIdentifierCodec().writeValue(writer, errorPath.path());
                writer.writeEndElement();
            }

            // optional node
            final var errorMessage = restconfError.message();
            if (errorMessage != null) {
                writer.writeStartElement("error-message");
                writer.writeCharacters(errorMessage.elementBody());
                writer.writeEndElement();
            }

            // optional node
            final var errorInfo = restconfError.info();
            if (errorInfo != null) {
                writer.writeStartElement("error-info");
                writer.writeCharacters(errorInfo.elementBody());
                writer.writeEndElement();
            }
        }

        writer.writeEndElement();
    }

    @Override
    protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
        return helper.add("status", status);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy