
de.tsl2.nano.h5.ARestUI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tsl2.nano.h5 Show documentation
Show all versions of tsl2.nano.h5 Show documentation
TSL2 Framework Html5 Extensions (WebServer, Html5Presentation, RuleCover, BeanConfigurator, LogicTable-Sheet, Expression-Descriptors for Actions, Rules, URLs, Queries)
The newest version!
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("