blob: 25ad7df5069b9951eefca3a1d67a9e50da319c2b [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
package org.eclipse.mdm.businessobjects.utils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.util.NoSuchElementException;
import io.vavr.API;
import io.vavr.CheckedFunction0;
import io.vavr.Lazy;
import io.vavr.collection.HashMap;
import io.vavr.collection.Map;
import io.vavr.control.Try;
/**
* Class representing the JSON request body as a accessible map of values. The
* parsing occurs lazily on first get() on a value and as the {@link Lazy}
* result is memoized, the body is only parsed once. Any exceptions due to
* parsing or non-existing keys are thrown on get() call.
*
* @author Alexander Nehmer, science+computing AG Tuebingen (Atos SE)
*
*/
public final class RequestBody {
private Lazy<HashMap<String, Object>> requestBodyMap;
private static ObjectMapper mapper;
static {
mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(Object.class, new ISODateDeseralizer());
mapper.registerModule(simpleModule);
}
/**
* Just hide the default constructor
*/
private RequestBody() {
}
/**
* Builds RequestBody by using the given function that returns the request body
* as a parsed {@link Map<String, Object>.
*
* @param requestBodyMapSupplier function that return a {@link Map<String,
* Object> with the parsed JSON body
*/
private RequestBody(CheckedFunction0<HashMap<String, Object>> requestBodyMapSupplier) {
// make the function lazily evaluated, so that any parsing exception occur on
// first get() on a value
// unchecked() makes it possible to trick the compiler to not force us to deal
// with the checked exceptions here
this.requestBodyMap = Lazy.of(API.unchecked(requestBodyMapSupplier));
}
/**
* Creates a RequestBody
*
* @param body JSON request body to create RequestBody
* @return the RequestBody
*/
public static RequestBody create(String requestBodyString) {
// create requestbody with a function that parses the json request and
// transforms it to a {@link Map<String, Object>
return new RequestBody(() -> HashMap
.ofAll(mapper.readValue(requestBodyString, new TypeReference<java.util.Map<String, Object>>() {
})));
}
/**
* Returns a {@link Try> that holds the string value for the given key. If the
* underlying request body map cannot be parsed, the appropriate JSON exceptions
* are thrown if get() is called on the {@link Try>. If the key was not found, a
* {@link NoSuchElementException} is thrown correspondingly.
*
* @param key key to get value for
* @return the string value for the given key
*/
public Try<String> getStringValueSupplier(String key) {
return Try.of(() -> Lazy.of(() -> requestBodyMap.get().get(key).map(Object::toString).onEmpty(() -> {
throw new NoSuchElementException("Key [" + key + "] not found in request body.");
}).get()).get());
}
/**
* Returns a {@link Try<Object>> that holds the value for the given key. If the
* underlying request body map cannot be parsed, the appropriate JSON exceptions
* are thrown if get() is called on the {@link Try>. If the key was not found, a
* {@link NoSuchElementException} is thrown correspondingly.
*
* @param key key to get value for
* @return the value for the given key
*/
public Try<Object> getValueSupplier(String key) {
return Try.of(() -> Lazy.of(() -> requestBodyMap.get().get(key).map(Object::toString).onEmpty(() -> {
throw new NoSuchElementException("Key [" + key + "] not found in request body.");
}).get()).get());
}
/**
* Returns a {@link Try} of the complete {@link Map<String, Object>} of the
* request body
*
* @return a {@link Try} of {@link Map<String, Object>} of the request body
*/
public Try<Map<String, Object>> getValueMapSupplier() {
return Try.of(() -> requestBodyMap.get());
}
}