Introduce HttpStatusCode
[netconf.git] / restconf / restconf-nb / src / main / java / org / opendaylight / restconf / nb / rfc8040 / ErrorTagMapping.java
1 /*
2  * Copyright (c) 2024 PANTHEON.tech, s.r.o. 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;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.collect.ImmutableMap;
13 import org.eclipse.jdt.annotation.NonNullByDefault;
14 import org.opendaylight.restconf.api.HttpStatusCode;
15 import org.opendaylight.restconf.nb.rfc8040.legacy.ErrorTags;
16 import org.opendaylight.yangtools.yang.common.ErrorTag;
17
18 /**
19  * Mapping of {@link ErrorTag}s to {@link HttpStatusCode}s.
20  */
21 @NonNullByDefault
22 public enum ErrorTagMapping {
23     /**
24      * Mapping specified by <a href="https://www.rfc-editor.org/rfc/rfc8040#page-74">RFC8040</a>:
25      * {@link ErrorTag#DATA_MISSING} is reported as {@code 409 Conflict}. This may be confusing to users, as {@code GET}
26      * requests to non-existent datastore resources do not report {@code 404 Not Found} as would be expected from any
27      * other HTTP server.
28      */
29     RFC8040(HttpStatusCode.CONFLICT),
30     /**
31      * Mapping proposed by <a href="https://www.rfc-editor.org/errata/eid5565">Errata 5565</a>:
32      * {@link ErrorTag#DATA_MISSING} is reported as {@code 404 Not Found}. This is more in-line with expectations rooted
33      * in <a href="https://www.rfc-editor.org/rfc/rfc7231#section-6.5.4">HTTP/1.1 specification</a>.
34      */
35     ERRATA_5565(HttpStatusCode.NOT_FOUND);
36
37     private ImmutableMap<ErrorTag, HttpStatusCode> tagToStatus;
38
39     ErrorTagMapping(final HttpStatusCode dataMissing) {
40         tagToStatus = ImmutableMap.<ErrorTag, HttpStatusCode>builder()
41             .put(ErrorTag.IN_USE,                     HttpStatusCode.CONFLICT)
42             .put(ErrorTag.INVALID_VALUE,              HttpStatusCode.BAD_REQUEST)
43             .put(ErrorTag.TOO_BIG,                    HttpStatusCode.CONTENT_TOO_LARGE)
44             .put(ErrorTag.MISSING_ATTRIBUTE,          HttpStatusCode.BAD_REQUEST)
45             .put(ErrorTag.BAD_ATTRIBUTE,              HttpStatusCode.BAD_REQUEST)
46             .put(ErrorTag.UNKNOWN_ATTRIBUTE,          HttpStatusCode.BAD_REQUEST)
47             .put(ErrorTag.MISSING_ELEMENT,            HttpStatusCode.BAD_REQUEST)
48             .put(ErrorTag.BAD_ELEMENT,                HttpStatusCode.BAD_REQUEST)
49             .put(ErrorTag.UNKNOWN_ELEMENT,            HttpStatusCode.BAD_REQUEST)
50             .put(ErrorTag.UNKNOWN_NAMESPACE,          HttpStatusCode.BAD_REQUEST)
51
52             .put(ErrorTag.ACCESS_DENIED,              HttpStatusCode.FORBIDDEN)
53             .put(ErrorTag.LOCK_DENIED,                HttpStatusCode.CONFLICT)
54             .put(ErrorTag.RESOURCE_DENIED,            HttpStatusCode.CONFLICT)
55             .put(ErrorTag.ROLLBACK_FAILED,            HttpStatusCode.INTERNAL_SERVER_ERROR)
56             .put(ErrorTag.DATA_EXISTS,                HttpStatusCode.CONFLICT)
57             .put(ErrorTag.DATA_MISSING,               dataMissing)
58
59             .put(ErrorTag.OPERATION_NOT_SUPPORTED,    HttpStatusCode.NOT_IMPLEMENTED)
60             .put(ErrorTag.OPERATION_FAILED,           HttpStatusCode.INTERNAL_SERVER_ERROR)
61             .put(ErrorTag.PARTIAL_OPERATION,          HttpStatusCode.INTERNAL_SERVER_ERROR)
62             .put(ErrorTag.MALFORMED_MESSAGE,          HttpStatusCode.BAD_REQUEST)
63             .put(ErrorTags.RESOURCE_DENIED_TRANSPORT, HttpStatusCode.SERVICE_UNAVAILABLE)
64             .build();
65     }
66
67     /**
68      * Return the HTTP {@link HttpStatusCode} corresponding to specified {@link ErrorTag}.
69      *
70      * @param tag Error tag to map
71      * @return A {@link HttpStatusCode}
72      * @throws NullPointerException if {@code tag} is null
73      */
74     public HttpStatusCode statusOf(final ErrorTag tag) {
75         final var known = tagToStatus.get(requireNonNull(tag));
76         return known != null ? known : HttpStatusCode.INTERNAL_SERVER_ERROR;
77     }
78 }