Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2015-2019 the original author or authors.
*
* 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 org.dbflute.remoteapi;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.http.impl.client.CloseableHttpClient;
import org.dbflute.optional.OptionalThing;
import org.dbflute.remoteapi.http.EmptyRequestBody;
import org.dbflute.remoteapi.mock.MockHttpClient;
import org.dbflute.util.DfCollectionUtil;
/**
* The base class of behavior for remote API.
* @author awane
* @author jflute
* @author inoue
*/
public abstract class FlutyRemoteBehavior {
// ===================================================================================
// Definition
// ==========
protected static final Object[] EMPTY_OBJECTS = new Object[] {};
protected static final EmptyRequestBody EMPTY_REQUEST_BODY = new EmptyRequestBody();
// ===================================================================================
// Attribute
// =========
protected final FlutyRemoteApi remoteApi; // not null
// ===================================================================================
// Constructor
// ===========
public FlutyRemoteBehavior() {
this.remoteApi = createRemoteApi();
}
// -----------------------------------------------------
// Create RemoteApi
// ----------------
protected FlutyRemoteApi createRemoteApi() {
return newRemoteApi(createRemoteApiOptionSetupper(), getFacadeExp());
}
// -----------------------------------------------------
// Option Setupper
// ---------------
protected Consumer createRemoteApiOptionSetupper() {
return op -> setupDefaultRemoteApiRule(op);
}
protected void setupDefaultRemoteApiRule(FlutyRemoteApiRule rule) {
reflectMockHttpClientIfNeeds(rule);
if (isUseApplicationalUserAgent()) {
rule.setHeader("User-Agent", buildApplicationalUserAgent());
}
yourDefaultRule(rule); // you can override default rules
}
protected void reflectMockHttpClientIfNeeds(FlutyRemoteApiRule rule) {
if (__xmockHttpClient != null) {
rule.xregisterMockHttpClient(__xmockHttpClient);
}
}
// -----------------------------------------------------
// Applicational UserAgent
// -----------------------
protected boolean isUseApplicationalUserAgent() {
return false; // as default, for security
}
protected String buildApplicationalUserAgent() { // basically for internal remote AIP
final List wordList = DfCollectionUtil.newArrayList();
final String serviceName = getUserAgentServiceName();
if (serviceName != null) {
wordList.add(serviceName);
}
final String appName = getUserAgentAppName();
if (appName != null) {
wordList.add(appName);
}
wordList.add(getClass().getSimpleName());
return wordList.stream().collect(Collectors.joining("-"));
}
/**
* @return The service name for user-agent. (NullAllowed: then no use)
*/
protected String getUserAgentServiceName() {
return null; // as default
}
/**
* @return The application name for user-agent. (NullAllowed: then no use)
*/
protected String getUserAgentAppName() {
return null; // as default
}
// -----------------------------------------------------
// Your Rule
// ---------
/**
* Set up your default rule of remote API.
*
* @param rule The rule of remote API. (NotNull)
*/
protected abstract void yourDefaultRule(FlutyRemoteApiRule rule);
// -----------------------------------------------------
// Facade Expression
// -----------------
protected Object getFacadeExp() { // not null, for various purpose (basically debug)
return getClass(); // as default
}
@Deprecated // use getFacadeExp()
protected Object getCallerExp() { // not null, for various purpose (basically debug)
return getFacadeExp(); // as default
}
// -----------------------------------------------------
// RemoteApi Instance
// ------------------
protected FlutyRemoteApi newRemoteApi(Consumer ruleSetupper, Object facadeExp) {
return new FlutyRemoteApi(ruleSetupper, facadeExp);
}
// ===================================================================================
// Basic Parts
// ===========
/**
* Get the base part of URL for remote API server.
* The string is from first to context path.
* @return The base part of URL. e.g. http://localhost:8090/harbor (NotNull)
*/
protected abstract String getUrlBase();
// ===================================================================================
// Remote Facade
// =============
// -----------------------------------------------------
// GET
// -----
/**
* Request as GET, receiving as simple bean type.
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7?sea=mystic&land=oneman
* return doRequestGet(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), OptionalThing.of(form), rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7?sea=mystic&land=oneman
* return doRequestGet(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), OptionalThing.of(form), rule -> {
* rule.sendQueryBy(new LaQuerySender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The class type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The optional object of query parameter. (NotNull, EmptyAllowed)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestGet(Class extends RETURN> returnType //
, String actionPath, Object[] pathVariables, OptionalThing extends Object> param, Consumer ruleLambda) {
return remoteApi.requestGet(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
/**
* Request as GET, receiving as parameterized type (has nested generics).
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7?sea=mystic&land=oneman
* return doRequestGet(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), OptionalThing.of(form), rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7?sea=mystic&land=oneman
* return doRequestGet(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), OptionalThing.of(form), rule -> {
* rule.sendQueryBy(new LaQuerySender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The parameterized type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The optional object of query parameter. (NotNull, EmptyAllowed)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestGet(ParameterizedType returnType //
, String actionPath, Object[] pathVariables, OptionalThing extends Object> param, Consumer ruleLambda) {
return remoteApi.requestGet(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
// -----------------------------------------------------
// Post
// ------
/**
* Request as POST, receiving as simple bean type.
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestPost(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), body, rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestPost(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), body, rule -> {
* rule.sendBodyBy(new LaJsonSender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The class type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The parameter object of on-body parameters, may be JSON body. (NotNull)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestPost(Class extends RETURN> returnType //
, String actionPath, Object[] pathVariables, Object param, Consumer ruleLambda) {
return remoteApi.requestPost(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
/**
* Request as POST, receiving as parameterized type (has nested generics).
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestPost(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), body, rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestPost(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), body, rule -> {
* rule.sendBodyBy(new LaJsonSender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The parameterized type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The parameter object of on-body parameters, may be JSON body. (NotNull)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestPost(ParameterizedType returnType //
, String actionPath, Object[] pathVariables, Object param, Consumer ruleLambda) {
return remoteApi.requestPost(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
// -----------------------------------------------------
// Put
// -----
/**
* Request as PUT, receiving as simple bean type.
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestPut(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), body, rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestPut(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), body, rule -> {
* rule.sendBodyBy(new LaJsonSender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The class type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The parameter object of on-body parameters, may be JSON body. (NotNull)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestPut(Class extends RETURN> returnType //
, String actionPath, Object[] pathVariables, Object param, Consumer ruleLambda) {
return remoteApi.requestPut(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
/**
* Request as PUT, receiving as parameterized type (has nested generics).
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestPut(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), body, rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestPut(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), body, rule -> {
* rule.sendBodyBy(new LaJsonSender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The parameterized type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The parameter object of on-body parameters, may be JSON body. (NotNull)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestPut(ParameterizedType returnType //
, String actionPath, Object[] pathVariables, Object param, Consumer ruleLambda) {
return remoteApi.requestPut(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
// -----------------------------------------------------
// DELETE
// ------
/**
* Request as DELETE (with query parameter), receiving as simple bean type.
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestDelete(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), OptionalThing.of(form), rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestDelete(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), OptionalThing.of(form), rule -> {
* rule.sendQueryBy(new LaQuerySender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The class type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The optional parameter object of query parameter. (NotNull, EmptyAllowed)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestDelete(Class extends RETURN> returnType //
, String actionPath, Object[] pathVariables, OptionalThing extends Object> param, Consumer ruleLambda) {
return remoteApi.requestDelete(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
/**
* Request as DELETE (with query parameter), receiving as parameterized type (has nested generics).
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestDelete(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), OptionalThing.of(form), rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestDelete(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), OptionalThing.of(form), rule -> {
* rule.sendQueryBy(new LaQuerySender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The parameterized type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The optional parameter object of query parameter. (NotNull, EmptyAllowed)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestDelete(ParameterizedType returnType //
, String actionPath, Object[] pathVariables, OptionalThing extends Object> param, Consumer ruleLambda) {
return remoteApi.requestDelete(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
/**
* Request as DELETE with entity-enclosing, receiving as simple bean type.
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestDeleteEnclosing(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), body, rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestDeleteEnclosing(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), body, rule -> {
* rule.sendBodyBy(new LaJsonSender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The class type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The parameter object of on-body parameters, may be JSON body. (NotNull)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestDeleteEnclosing(Class extends RETURN> returnType //
, String actionPath, Object[] pathVariables, Object param, Consumer ruleLambda) {
return remoteApi.requestDeleteEnclosing(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
/**
* Request as DELETE (with entity-enclosing), receiving as parameterized type (has nested generics).
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestDeleteEnclosing(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), body, rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestDeleteEnclosing(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), body, rule -> {
* rule.sendBodyBy(new LaJsonSender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The parameterized type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The parameter object of on-body parameters, may be JSON body. (NotNull)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestDeleteEnclosing(ParameterizedType returnType //
, String actionPath, Object[] pathVariables, Object param, Consumer ruleLambda) {
return remoteApi.requestDeleteEnclosing(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
// -----------------------------------------------------
// Patch
// -----
/**
* Request as PATCH, receiving as simple bean type.
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestPatch(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), body, rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestPatch(RemoteProductListReturn.class, "/lido/product/list", moreUrl(7), body, rule -> {
* rule.sendBodyBy(new LaJsonSender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The class type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The parameter object of on-body parameters, may be JSON body. (NotNull)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestPatch(Class extends RETURN> returnType //
, String actionPath, Object[] pathVariables, Object param, Consumer ruleLambda) {
return remoteApi.requestPatch(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
/**
* Request as PATCH, receiving as parameterized type (has nested generics).
*
* e.g. if sender, receiver are already set as default: /lido/product/list/7
* return doRequestPatch(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), body, rule -> {});
*
* e.g. if sender, receiver are not set yet, so set them here: /lido/product/list/7
* return doRequestPatch(new ParameterizedRef<RemoteSearchPagingReturn<RemoteProductRowReturn>>() {
* }.getType(), "/lido/product/list", moreUrl(7), body, rule -> {
* rule.sendBodyBy(new LaJsonSender(...));
* rule.receiveBodyBy(new LaJsonReceiver(...));
* });
*
* @param The type of response return.
* @param returnType The parameterized type of bean as return (response body), should have default constructor. (NotNull)
* @param actionPath The path to action without path variables. e.g. /sea/land (NotNull)
* @param pathVariables The array of URL path variables, e.g. ["hangar", 3]. (NotNull, EmptyAllowed)
* @param param The parameter object of on-body parameters, may be JSON body. (NotNull)
* @param ruleLambda The callback for rule of remote API. (NotNull)
* @return The analyzed return of response from the request. (NotNull)
*/
protected RETURN doRequestPatch(ParameterizedType returnType //
, String actionPath, Object[] pathVariables, Object param, Consumer ruleLambda) {
return remoteApi.requestPatch(returnType, getUrlBase(), actionPath, pathVariables, param, ruleLambda);
}
// ===================================================================================
// Assist Logic
// ============
/**
* Make array for path variables. (easy utility)
*
* @param pathVariables The varying arguments for path variables. (NotNull)
* @return The array of object. (NotNull)
*/
protected Object[] moreUrl(Object... pathVariables) {
if (pathVariables == null) {
throw new IllegalArgumentException("The argument 'pathVariables' should not be null.");
}
return pathVariables;
}
/**
* Get empty object array for path variables.
*
* @param The type of query parrameter.
* @param param The parameter object for query parameter. (NotNull)
* @return The optional object as present. (NotNull)
*/
protected OptionalThing query(PARAM param) {
if (param == null) {
throw new IllegalArgumentException("The argument 'param' should not be null.");
}
return OptionalThing.of(param);
}
/**
* Get empty optional for query form.
*