Bug 3866: Support for Restconf HTTP Patch
[netconf.git] / opendaylight / restconf / sal-rest-connector / src / main / java / org / opendaylight / netconf / sal / rest / impl / PATCHJsonBodyWriter.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
9 package org.opendaylight.netconf.sal.rest.impl;
10
11 import com.google.common.base.Charsets;
12 import com.google.gson.stream.JsonWriter;
13 import java.io.IOException;
14 import java.io.OutputStream;
15 import java.io.OutputStreamWriter;
16 import java.lang.annotation.Annotation;
17 import java.lang.reflect.Type;
18 import java.util.List;
19 import javax.ws.rs.Produces;
20 import javax.ws.rs.WebApplicationException;
21 import javax.ws.rs.core.MediaType;
22 import javax.ws.rs.core.MultivaluedMap;
23 import javax.ws.rs.ext.MessageBodyWriter;
24 import javax.ws.rs.ext.Provider;
25 import org.opendaylight.netconf.sal.rest.api.Draft02.MediaTypes;
26 import org.opendaylight.netconf.sal.rest.api.RestconfService;
27 import org.opendaylight.netconf.sal.restconf.impl.PATCHStatusContext;
28 import org.opendaylight.netconf.sal.restconf.impl.PATCHStatusEntity;
29 import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
30 import org.opendaylight.yangtools.yang.data.codec.gson.JsonWriterFactory;
31
32 @Provider
33 @Produces({MediaTypes.PATCH_STATUS + RestconfService.JSON})
34 public class PATCHJsonBodyWriter implements MessageBodyWriter<PATCHStatusContext> {
35
36     @Override
37     public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
38         return type.equals(PATCHStatusContext.class);
39     }
40
41     @Override
42     public long getSize(PATCHStatusContext patchStatusContext, Class<?> type, Type genericType, Annotation[]
43             annotations, MediaType mediaType) {
44         return -1;
45     }
46
47     @Override
48     public void writeTo(PATCHStatusContext patchStatusContext, Class<?> type, Type genericType, Annotation[]
49             annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
50                 throws IOException, WebApplicationException {
51
52         final JsonWriter jsonWriter = createJsonWriter(entityStream);
53         jsonWriter.beginObject().name("ietf-yang-patch:yang-patch-status");
54         jsonWriter.beginObject();
55         jsonWriter.name("patch-id").value(patchStatusContext.getPatchId());
56         if (patchStatusContext.isOk()) {
57             jsonWriter.name("ok").nullValue();
58         } else {
59             if (patchStatusContext.getGlobalErrors() != null) {
60                 reportErrors(patchStatusContext.getGlobalErrors(), jsonWriter);
61             }
62
63             jsonWriter.name("edit-status");
64             jsonWriter.beginObject();
65             jsonWriter.name("edit");
66             jsonWriter.beginArray();
67             for (PATCHStatusEntity patchStatusEntity : patchStatusContext.getEditCollection()) {
68                 jsonWriter.beginObject();
69                 jsonWriter.name("edit-id").value(patchStatusEntity.getEditId());
70                 if (patchStatusEntity.getEditErrors() != null) {
71                     reportErrors(patchStatusEntity.getEditErrors(), jsonWriter);
72                 } else {
73                     if (patchStatusEntity.isOk()) {
74                         jsonWriter.name("ok").nullValue();
75                     }
76                 }
77                 jsonWriter.endObject();
78             }
79             jsonWriter.endArray();
80             jsonWriter.endObject();
81         }
82         jsonWriter.endObject();
83         jsonWriter.endObject();
84         jsonWriter.flush();
85
86     }
87
88     private static void reportErrors(List<RestconfError> errors, JsonWriter jsonWriter) throws IOException {
89         jsonWriter.name("errors");
90         jsonWriter.beginObject();
91         jsonWriter.name("error");
92         jsonWriter.beginArray();
93
94         for (RestconfError restconfError : errors) {
95             jsonWriter.beginObject();
96             jsonWriter.name("error-type").value(restconfError.getErrorType().getErrorTypeTag());
97             jsonWriter.name("error-tag").value(restconfError.getErrorTag().getTagValue());
98             //TODO: fix error-path reporting (separate error-path from error-message)
99             //jsonWriter.name("error-path").value(restconfError.getErrorPath());
100             jsonWriter.name("error-message").value(restconfError.getErrorMessage());
101             jsonWriter.endObject();
102         }
103
104         jsonWriter.endArray();
105         jsonWriter.endObject();
106     }
107
108     private static JsonWriter createJsonWriter(final OutputStream entityStream) {
109         return JsonWriterFactory.createJsonWriter(new OutputStreamWriter(entityStream, Charsets.UTF_8));
110     }
111 }