Add AbstractNormalizedNodeBodyWriter
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / jersey / providers / patch / XmlPatchStatusBodyWriter.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.restconf.nb.rfc8040.jersey.providers.patch;
9
10 import java.io.IOException;
11 import java.io.OutputStream;
12 import java.lang.annotation.Annotation;
13 import java.lang.reflect.Type;
14 import java.nio.charset.StandardCharsets;
15 import java.util.List;
16 import javax.ws.rs.Produces;
17 import javax.ws.rs.core.MediaType;
18 import javax.ws.rs.core.MultivaluedMap;
19 import javax.ws.rs.ext.Provider;
20 import javax.xml.stream.XMLOutputFactory;
21 import javax.xml.stream.XMLStreamException;
22 import javax.xml.stream.XMLStreamWriter;
23 import org.opendaylight.restconf.common.errors.RestconfError;
24 import org.opendaylight.restconf.common.patch.PatchStatusContext;
25 import org.opendaylight.restconf.common.patch.PatchStatusEntity;
26 import org.opendaylight.restconf.nb.rfc8040.MediaTypes;
27
28 @Provider
29 @Produces(MediaTypes.APPLICATION_YANG_DATA_XML)
30 public class XmlPatchStatusBodyWriter extends AbstractPatchStatusBodyWriter {
31     private static final XMLOutputFactory XML_FACTORY;
32
33     static {
34         XML_FACTORY = XMLOutputFactory.newFactory();
35         XML_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
36     }
37
38     @Override
39     public void writeTo(final PatchStatusContext patchStatusContext, final Class<?> type, final Type genericType,
40                         final Annotation[] annotations, final MediaType mediaType,
41                         final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
42             throws IOException {
43         try {
44             final XMLStreamWriter xmlWriter =
45                     XML_FACTORY.createXMLStreamWriter(entityStream, StandardCharsets.UTF_8.name());
46             writeDocument(xmlWriter, patchStatusContext);
47         } catch (final XMLStreamException e) {
48             throw new IOException("Failed to write body", e);
49         }
50     }
51
52     private static void writeDocument(final XMLStreamWriter writer, final PatchStatusContext context)
53             throws XMLStreamException {
54         writer.writeStartElement("", "yang-patch-status", "urn:ietf:params:xml:ns:yang:ietf-yang-patch");
55         writer.writeStartElement("patch-id");
56         writer.writeCharacters(context.getPatchId());
57         writer.writeEndElement();
58
59         if (context.isOk()) {
60             writer.writeEmptyElement("ok");
61         } else {
62             if (context.getGlobalErrors() != null) {
63                 reportErrors(context.getGlobalErrors(), writer);
64             }
65             writer.writeStartElement("edit-status");
66             for (final PatchStatusEntity patchStatusEntity : context.getEditCollection()) {
67                 writer.writeStartElement("edit");
68                 writer.writeStartElement("edit-id");
69                 writer.writeCharacters(patchStatusEntity.getEditId());
70                 writer.writeEndElement();
71                 if (patchStatusEntity.getEditErrors() != null) {
72                     reportErrors(patchStatusEntity.getEditErrors(), writer);
73                 } else {
74                     if (patchStatusEntity.isOk()) {
75                         writer.writeEmptyElement("ok");
76                     }
77                 }
78                 writer.writeEndElement();
79             }
80             writer.writeEndElement();
81
82         }
83         writer.writeEndElement();
84
85         writer.flush();
86     }
87
88     private static void reportErrors(final List<RestconfError> errors, final XMLStreamWriter writer)
89             throws XMLStreamException {
90         writer.writeStartElement("errors");
91
92         for (final RestconfError restconfError : errors) {
93             writer.writeStartElement("error-type");
94             writer.writeCharacters(restconfError.getErrorType().getErrorTypeTag());
95             writer.writeEndElement();
96
97             writer.writeStartElement("error-tag");
98             writer.writeCharacters(restconfError.getErrorTag().getTagValue());
99             writer.writeEndElement();
100
101             // optional node
102             if (restconfError.getErrorPath() != null) {
103                 writer.writeStartElement("error-path");
104                 writer.writeCharacters(restconfError.getErrorPath().toString());
105                 writer.writeEndElement();
106             }
107
108             // optional node
109             if (restconfError.getErrorMessage() != null) {
110                 writer.writeStartElement("error-message");
111                 writer.writeCharacters(restconfError.getErrorMessage());
112                 writer.writeEndElement();
113             }
114
115             // optional node
116             if (restconfError.getErrorInfo() != null) {
117                 writer.writeStartElement("error-info");
118                 writer.writeCharacters(restconfError.getErrorInfo());
119                 writer.writeEndElement();
120             }
121         }
122
123         writer.writeEndElement();
124     }
125 }