Please wait. This can take some minutes ...
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.
de.tsl2.nano.h5.ARestUI Maven / Gradle / Ivy
package de.tsl2.nano.h5;
import static de.tsl2.nano.h5.ARESTDynamic.Methods.DELETE;
import static de.tsl2.nano.h5.ARESTDynamic.Methods.GET;
import static de.tsl2.nano.h5.ARESTDynamic.Methods.POST;
import static de.tsl2.nano.h5.ARESTDynamic.Methods.PUT;
import static de.tsl2.nano.h5.NanoH5Util.LOG;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.function.Supplier;
import de.tsl2.nano.action.IAction;
import de.tsl2.nano.bean.def.Bean;
import de.tsl2.nano.bean.def.BeanDefinition;
import de.tsl2.nano.bean.def.IPageBuilder;
import de.tsl2.nano.bean.def.IPresentable;
import de.tsl2.nano.core.ENV;
import de.tsl2.nano.core.ISession;
import de.tsl2.nano.core.util.ObjectUtil;
import de.tsl2.nano.core.util.StringUtil;
import de.tsl2.nano.core.util.Util;
import de.tsl2.nano.core.util.parser.JSon;
import de.tsl2.nano.h5.ARESTDynamic.Status;
/**
* Provides a ui service to interact with a static ARESTDynamic restful service.
* enriches responses of that restful service and creates additional dialogs to
* call the restful serivce with methods like PUT, POST and DELETE. Tries to
* implement something like HATEOAS, providing links the possible actions in the
* current context.
* Usage: see initial help text of REST service: '/rest' or go directly to
* the RestUI page: '/restui'. This will you guide further with possible links
* to current context.
*
* Example: http://localhost/8067/restui.
*
* @TYPE RESPONSE response implementation of an HttpServer (e.g.: NanoHTTPD.Response)
*/
public abstract class ARestUI {
private static final String MIME_HTML = "text/html";
public static String BASE_PATH = ENV.get("app.restui.basepath", "/restui");
private static final String URLKEY_ENTITIES = "entities";
private static final String URLKEY_ENTITIESJSON = "entitiesjson";
private static final String FIELD_PATH = "path";
enum CHANGE_ACTIONS {
CREATE, CHANGE, DELETE;
public String value() {
return this.toString().toLowerCase();
}
}
public static boolean canRestUI(String uri) {
return (uri.endsWith(BASE_PATH) || uri.contains(BASE_PATH + "/")) && ENV.get("app.restui.active", true);
}
public static boolean canRest(String uri) {
return ARESTDynamic.canRest(uri) || canRestUI(uri) && !isFileRequest(uri);
}
private static boolean isFileRequest(String uri) {
return uri.matches(".*/icons/.*[.](jpg|png|gif|ico)");
}
RESPONSE serve(ISession session, String url, String method, Map header, Map parms, Map payload) {
if (isChangeAction(url) && method.equals(GET.name()) && !isCanceled(parms)) {
return provideInputDialog(session, url, null);
} else if (method.equals(POST.name())) {
if (isCanceled(parms)) {
url = BASE_PATH + "/" + URLKEY_ENTITIES;
method = GET.name();
//prepare REST request from InputDialog
} else if (is(url, CHANGE_ACTIONS.CREATE)) {
payload.put(ARESTDynamic.BODY, parms.get("payload"));
} else if (is(url, CHANGE_ACTIONS.CHANGE)) {
url = parms.get(FIELD_PATH);
method = PUT.name();
} else if (is(url, CHANGE_ACTIONS.DELETE)) {
url = parms.get(FIELD_PATH);
method = DELETE.name();
}
}
RESPONSE restResponse = callRestService(url, method, header, parms, payload);
if (method.equals(POST.name())) {
return provideInputDialog(session, url, getData(restResponse));
} else if (!getStatus(restResponse).equals(Status.OK)
|| url.equals(BASE_PATH)
|| url.endsWith(URLKEY_ENTITIES)) {
return createResponse(session, url, restResponse, method);
}
return presentDesiredObject(session, url, method, restResponse);
}
private boolean isCanceled(Map parms) {
return parms.containsKey(IAction.CANCELED);
}
private RESPONSE presentDesiredObject(ISession session, String url, String method, RESPONSE restResponse) {
String json = getData(restResponse);
String entity = getEntity(url);
Object instance;
if (entity == null) {
instance = json;
} else if (entity.equals(URLKEY_ENTITIES)) {
instance = json;
} else if (entity.equals(URLKEY_ENTITIESJSON)) {
instance = new JSon().toList(LinkedHashMap.class, json);
} else {
if (JSon.isJSon(json)) {
BeanDefinition> beanDef = BeanDefinition.getBeanDefinition(entity);
instance = new JSon().toObject(beanDef.getClazz(), json);
} else
instance = json;
}
if (instance instanceof String) {
instance = HtmlUtil.createHtmlFromText((String) instance);
}
return createResponse(session, restResponse, entity, instance, method);
}
private RESPONSE provideInputDialog(ISession session, String url, String message) {
String name = StringUtil.substring(url, BASE_PATH + "/", "/");
Map values = Bean.newBean(name).toValueMap(null);
String html = createInputMask(session, url, name, new JSon().serialize(values), message);
return createResponse(Status.OK, MIME_HTML, html);
}
private boolean isChangeAction(String url) {
CHANGE_ACTIONS[] changeActions = CHANGE_ACTIONS.values();
for (int i = 0; i < changeActions.length; i++) {
if (url.endsWith(changeActions[i].value()))
return true;
}
return false;
}
private RESPONSE createResponse(ISession session, String url, RESPONSE restResponse, String method) {
String data = getData(restResponse);
if (!JSon.isJSon(data)) {
data = enrichtTextToHtml(url, data);
}
String entity = getEntity(url);
entity = Util.isEmpty(entity) ? BASE_PATH : entity;
return createResponse(session, restResponse, entity, data, method);
}
RESPONSE createResponse(ISession session, RESPONSE restResponse, String name, Object instance, String method) {
Bean model = instance instanceof String ? null : Bean.getBean(instance);
String msg = instance instanceof String ? instance.toString() : null;
IPageBuilder, String> pageBuilder = ENV.get(IPageBuilder.class); //Bean.getBean(instance).getPresentationHelper();
String html = model == null && msg.contains("