JsonError.java
/******************************************************************************
Copyright 2014 Emily Estes
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************/
package net.metanotion.web.concrete;
import java.util.HashMap;
import java.util.Map;
import net.metanotion.json.JsonArray;
import net.metanotion.json.JsonObject;
import net.metanotion.util.Pair;
import net.metanotion.web.HttpValues;
/** This class represents an HTTP "extended error" message response encoded as a JSON object. The format of
an extended error message is JSON object with a single key named "errors" whose value is an array of error
objects. An error object has 2 required keys and one optional key. The first required key is "selector" which can be
used to indicate the "destination" of the error message as a string(the forms.js lib in src/main/js interprets this as
a CSS selector). The second required key is "message", and it's value is also a string. It is intended, but not
required, that this string is a "machine readable" error message intended for the destination code(determined,
presumably, by "selector") to understand(the forms.js library interprets this as a template name, containing a human
readable error message, thus allowing internationalization/localization concerns to be handled by HTTP language accept
headers and the templating system. The third optional key is "data", whose value can be any legal JSON value. It is
passed to the destination code along with the "message" key(again, forms.js uses this as the data parameter for the
template containing the error message. */
public final class JsonError {
private final Map<String,Map.Entry<String,Object>> errors = new HashMap<>();
/** Add an error object to the response without a data parameter.
@param selector The value of the selector for the error.
@param message The value of the message for the error.
@return This JsonError object.
*/
public JsonError add(final String selector, final String message) {
errors.put(selector, new Pair<String,Object>(message, null));
return this;
}
/** Add an error object to the response.
@param selector The value of the selector for the error.
@param message The value of the message for the error.
@param data The value of the extra data for the error.
@return This JsonError object.
*/
public JsonError add(final String selector, final String message, final JsonObject data) {
errors.put(selector, new Pair<String,Object>(message, data));
return this;
}
/** Add an error object to the response.
@param selector The value of the selector for the error.
@param message The value of the message for the error.
@param data The value of the extra data for the error.
@return This JsonError object.
*/
public JsonError add(final String selector, final String message, final JsonArray data) {
errors.put(selector, new Pair<String,Object>(message, data));
return this;
}
/** Add an error object to the response.
@param selector The value of the selector for the error.
@param message The value of the message for the error.
@param data The value of the extra data for the error.
@return This JsonError object.
*/
public JsonError add(final String selector, final String message, final Number data) {
errors.put(selector, new Pair<String,Object>(message, data));
return this;
}
/** Add an error object to the response.
@param selector The value of the selector for the error.
@param message The value of the message for the error.
@param data The value of the extra data for the error.
@return This JsonError object.
*/
public JsonError add(final String selector, final String message, final Boolean data) {
errors.put(selector, new Pair<String,Object>(message, data));
return this;
}
/** Add an error object to the response.
@param selector The value of the selector for the error.
@param message The value of the message for the error.
@param data The value of the extra data for the error.
@return This JsonError object.
*/
public JsonError add(final String selector, final String message, final String data) {
errors.put(selector, new Pair<String,Object>(message, data));
return this;
}
/** Translate this error into an HTTP response with the provided HTTP status code.
@param status The HTTP status code for the response.
@return An HTTP response.
*/
public HttpValues toHttpResponse(final int status) { return HttpUtil.newJsonResponse(this, status); }
/** Serialize this error into a JSON encoded string.
@return A JSON object as a string.
*/
@Override public String toString() {
final JsonArray arr = new JsonArray();
for(final Map.Entry<String,Map.Entry<String,Object>> err: errors.entrySet()) {
final JsonObject val = new JsonObject();
final Map.Entry<String,Object> payload = err.getValue();
val.put("selector", err.getKey());
val.put("message", payload.getKey());
if(err.getValue() != null) {
val.put("data", payload.getValue());
}
arr.add(val);
}
return "{\"errors\":" + arr.toString() + "}";
}
}