import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
-import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.restconf.api.ApiPath;
-import org.opendaylight.restconf.api.FormatParameters;
+import org.opendaylight.restconf.api.FormattableBody;
+import org.opendaylight.restconf.api.HttpStatusCode;
import org.opendaylight.restconf.api.MediaTypes;
import org.opendaylight.restconf.api.QueryParameters;
import org.opendaylight.restconf.api.query.PrettyPrintParam;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.errors.RestconfError;
import org.opendaylight.restconf.common.errors.RestconfFuture;
+import org.opendaylight.restconf.nb.rfc8040.ErrorTagMapping;
import org.opendaylight.restconf.nb.rfc8040.URLConstants;
-import org.opendaylight.restconf.nb.rfc8040.legacy.ErrorTags;
-import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.restconf.server.api.ConfigurationMetadata;
import org.opendaylight.restconf.server.api.CreateResourceResult;
import org.opendaylight.restconf.server.api.DataGetResult;
private final @NonNull RestconfServer server;
private final @NonNull ServerRequest emptyRequest;
private final @NonNull PrettyPrintParam prettyPrint;
+ private final @NonNull ErrorTagMapping errorTagMapping;
- public JaxRsRestconf(final RestconfServer server, final PrettyPrintParam prettyPrint) {
+ public JaxRsRestconf(final RestconfServer server, final ErrorTagMapping errorTagMapping,
+ final PrettyPrintParam prettyPrint) {
this.server = requireNonNull(server);
+ this.errorTagMapping = requireNonNull(errorTagMapping);
this.prettyPrint = requireNonNull(prettyPrint);
emptyRequest = ServerRequest.of(QueryParameters.of(), prettyPrint);
+
+ LOG.info("RESTCONF data-missing condition is reported as HTTP status {}", switch (errorTagMapping) {
+ case ERRATA_5565 -> "404 (Errata 5565)";
+ case RFC8040 -> "409 (RFC8040)";
+ });
}
private @NonNull ServerRequest requestOf(final UriInfo uriInfo) {
MediaType.TEXT_XML
})
public void dataGET(@Context final UriInfo uriInfo, @Suspended final AsyncResponse ar) {
- completeDataGET(server.dataGET(requestOf(uriInfo)), ar);
+ final var request = requestOf(uriInfo);
+ completeDataGET(server.dataGET(request), request.prettyPrint(), ar);
}
/**
})
public void dataGET(@Encoded @PathParam("identifier") final ApiPath identifier, @Context final UriInfo uriInfo,
@Suspended final AsyncResponse ar) {
- completeDataGET(server.dataGET(requestOf(uriInfo), identifier), ar);
+ final var request = requestOf(uriInfo);
+ completeDataGET(server.dataGET(request, identifier), request.prettyPrint(), ar);
}
- private static void completeDataGET(final RestconfFuture<DataGetResult> future, final AsyncResponse ar) {
+ @NonNullByDefault
+ private static void completeDataGET(final RestconfFuture<DataGetResult> future, final PrettyPrintParam prettyPrint,
+ final AsyncResponse ar) {
future.addCallback(new JaxRsRestconfCallback<>(ar) {
@Override
Response transform(final DataGetResult result) {
- final var builder = Response.ok().entity(result.payload()).cacheControl(NO_CACHE);
+ final var builder = Response.ok()
+ .entity(new JaxRsFormattableBody(result.body(), prettyPrint))
+ .cacheControl(NO_CACHE);
fillConfigurationMetadata(builder, result);
return builder.build();
}
}
}
- private static void completeDataYangPATCH(final RestconfFuture<DataYangPatchResult> future,
+ private void completeDataYangPATCH(final RestconfFuture<DataYangPatchResult> future,
final AsyncResponse ar) {
future.addCallback(new JaxRsRestconfCallback<>(ar) {
@Override
Response transform(final DataYangPatchResult result) {
- final var status = result.status();
- final var builder = Response.status(statusOf(status))
- .entity(new YangPatchStatusBody(status));
+ final var patchStatus = result.status();
+ final var statusCode = statusOf(patchStatus);
+ final var builder = Response.status(statusCode.code(), statusCode.phrase())
+ .entity(new YangPatchStatusBody(patchStatus));
fillConfigurationMetadata(builder, result);
return builder.build();
}
- private static Status statusOf(final PatchStatusContext result) {
+ private HttpStatusCode statusOf(final PatchStatusContext result) {
if (result.ok()) {
- return Status.OK;
+ return HttpStatusCode.OK;
}
final var globalErrors = result.globalErrors();
if (globalErrors != null && !globalErrors.isEmpty()) {
}
}
}
- return Status.INTERNAL_SERVER_ERROR;
+ return HttpStatusCode.INTERNAL_SERVER_ERROR;
}
- private static Status statusOfFirst(final List<RestconfError> error) {
- return ErrorTags.statusOf(error.get(0).getErrorTag());
+ private @NonNull HttpStatusCode statusOfFirst(final List<RestconfError> error) {
+ return errorTagMapping.statusOf(error.get(0).getErrorTag());
}
});
}
@Suspended final AsyncResponse ar) {
try (var jsonBody = new JsonChildBody(body)) {
final var request = requestOf(uriInfo);
- completeDataPOST(server.dataPOST(request, jsonBody), request.format(), uriInfo, ar);
+ completeDataPOST(server.dataPOST(request, jsonBody), request.prettyPrint(), uriInfo, ar);
}
}
public void postDataJSON(@Encoded @PathParam("identifier") final ApiPath identifier, final InputStream body,
@Context final UriInfo uriInfo, @Suspended final AsyncResponse ar) {
final var request = requestOf(uriInfo);
- completeDataPOST(server.dataPOST(request, identifier, new JsonDataPostBody(body)), request.format(), uriInfo,
- ar);
+ completeDataPOST(server.dataPOST(request, identifier, new JsonDataPostBody(body)), request.prettyPrint(),
+ uriInfo, ar);
}
/**
public void postDataXML(final InputStream body, @Context final UriInfo uriInfo, @Suspended final AsyncResponse ar) {
try (var xmlBody = new XmlChildBody(body)) {
final var request = requestOf(uriInfo);
- completeDataPOST(server.dataPOST(request, xmlBody), request.format(), uriInfo, ar);
+ completeDataPOST(server.dataPOST(request, xmlBody), request.prettyPrint(), uriInfo, ar);
}
}
public void postDataXML(@Encoded @PathParam("identifier") final ApiPath identifier, final InputStream body,
@Context final UriInfo uriInfo, @Suspended final AsyncResponse ar) {
final var request = requestOf(uriInfo);
- completeDataPOST(server.dataPOST(request, identifier, new XmlDataPostBody(body)), request.format(), uriInfo,
- ar);
+ completeDataPOST(server.dataPOST(request, identifier, new XmlDataPostBody(body)), request.prettyPrint(),
+ uriInfo, ar);
}
private static void completeDataPOST(final RestconfFuture<? extends DataPostResult> future,
- final FormatParameters format, final UriInfo uriInfo, final AsyncResponse ar) {
+ final PrettyPrintParam prettyPrint, final UriInfo uriInfo, final AsyncResponse ar) {
future.addCallback(new JaxRsRestconfCallback<DataPostResult>(ar) {
@Override
Response transform(final DataPostResult result) {
if (result instanceof InvokeResult invokeOperation) {
final var output = invokeOperation.output();
return output == null ? Response.noContent().build()
- : Response.ok().entity(new JaxRsFormattableBody(output, format)).build();
+ : Response.ok().entity(new JaxRsFormattableBody(output, prettyPrint)).build();
}
LOG.error("Unhandled result {}", result);
return Response.serverError().build();
MediaTypes.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON
})
public void operationsGET(@Suspended final AsyncResponse ar) {
- server.operationsGET(emptyRequest).addCallback(new FormattableBodyCallback(ar, emptyRequest.format()));
+ server.operationsGET(emptyRequest).addCallback(new FormattableBodyCallback(ar, prettyPrint));
}
/**
})
public void operationsGET(@PathParam("operation") final ApiPath operation, @Suspended final AsyncResponse ar) {
server.operationsGET(emptyRequest, operation)
- .addCallback(new FormattableBodyCallback(ar, emptyRequest.format()));
+ .addCallback(new FormattableBodyCallback(ar, prettyPrint));
}
/**
* @param identifier module name and rpc identifier string for the desired operation
* @param body the body of the operation
* @param uriInfo URI info
- * @param ar {@link AsyncResponse} which needs to be completed with a {@link NormalizedNodePayload} output
+ * @param ar {@link AsyncResponse} which needs to be completed with a {@link FormattableBody} output
*/
@POST
// FIXME: identifier is just a *single* QName
* @param identifier module name and rpc identifier string for the desired operation
* @param body the body of the operation
* @param uriInfo URI info
- * @param ar {@link AsyncResponse} which needs to be completed with a {@link NormalizedNodePayload} output
+ * @param ar {@link AsyncResponse} which needs to be completed with a {@link FormattableBody} output
*/
@POST
// FIXME: identifier is just a *single* QName
MediaType.TEXT_XML
})
public void yangLibraryVersionGET(@Suspended final AsyncResponse ar) {
- server.yangLibraryVersionGET(emptyRequest).addCallback(new FormattableBodyCallback(ar, emptyRequest.format()));
+ server.yangLibraryVersionGET(emptyRequest).addCallback(new FormattableBodyCallback(ar, prettyPrint));
}
// FIXME: References to these resources are generated by our yang-library implementation. That means: