/*
* Copyright (C) 2015 SoftIndex LLC.
*
* 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 io.datakernel.uikernel;
import com.google.gson.Gson;
import io.datakernel.async.ForwardingResultCallback;
import io.datakernel.async.ResultCallback;
import io.datakernel.bytebuf.ByteBufStrings;
import io.datakernel.exception.ParseException;
import io.datakernel.http.*;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import static io.datakernel.http.HttpMethod.*;
import static io.datakernel.uikernel.Utils.deserializeUpdateRequest;
import static io.datakernel.uikernel.Utils.fromJson;
/**
* Rest API for UiKernel Tables
*/
public class UiKernelServlets {
private static final ContentType JSON_UTF8 = ContentType.of(MediaTypes.JSON, Charset.forName("UTF-8"));
private static final String ID_PARAMETER_NAME = "id";
public static <K, R extends AbstractRecord<K>> MiddlewareServlet apiServlet(GridModel<K, R> model, Gson gson) {
return MiddlewareServlet.create()
.with(POST, "/", create(model, gson))
.with(GET, "/", read(model, gson))
.with(PUT, "/", update(model, gson))
.with(DELETE, "/:" + ID_PARAMETER_NAME, delete(model, gson))
.with(GET, "/:" + ID_PARAMETER_NAME, get(model, gson));
}
public static <K, R extends AbstractRecord<K>> AsyncServlet read(final GridModel<K, R> model, final Gson gson) {
return new AsyncServlet() {
@Override
public void serve(HttpRequest request, final ResultCallback<HttpResponse> callback) {
try {
Map<String, String> parameters = request.getParameters();
ReadSettings<K> settings = ReadSettings.from(gson, parameters);
model.read(settings, new ForwardingResultCallback<ReadResponse<K,R>>(callback) {
@Override
protected void onResult(ReadResponse<K, R> response) {
String json = response.toJson(gson, model.getRecordType(), model.getIdType());
callback.setResult(createResponse(json));
}
});
} catch (ParseException e) {
callback.setException(e);
}
}
};
}
public static <K, R extends AbstractRecord<K>> AsyncServlet get(final GridModel<K, R> model, final Gson gson) {
return new AsyncServlet() {
@Override
public void serve(HttpRequest request, final ResultCallback<HttpResponse> callback) {
try {
Map<String, String> parameters = request.getParameters();
ReadSettings<K> settings = ReadSettings.from(gson, parameters);
K id = fromJson(gson, request.getUrlParameter(ID_PARAMETER_NAME), model.getIdType());
model.read(id, settings, new ForwardingResultCallback<R>(callback) {
@Override
protected void onResult(R obj) {
String json = gson.toJson(obj, model.getRecordType());
callback.setResult(createResponse(json));
}
});
} catch (ParseException e) {
callback.setException(e);
}
}
};
}
public static <K, R extends AbstractRecord<K>> AsyncServlet create(final GridModel<K, R> model, final Gson gson) {
return new AsyncServlet() {
@Override
public void serve(HttpRequest request, final ResultCallback<HttpResponse> callback) {
try {
String json = ByteBufStrings.decodeUtf8(request.getBody());
R obj = fromJson(gson, json, model.getRecordType());
model.create(obj, new ForwardingResultCallback<CreateResponse<K>>(callback) {
@Override
protected void onResult(CreateResponse<K> response) {
String json = response.toJson(gson, model.getIdType());
callback.setResult(createResponse(json));
}
});
} catch (ParseException e) {
callback.setException(e);
}
}
};
}
public static <K, R extends AbstractRecord<K>> AsyncServlet update(final GridModel<K, R> model, final Gson gson) {
return new AsyncServlet() {
@Override
public void serve(HttpRequest request, final ResultCallback<HttpResponse> callback) {
try {
String json = ByteBufStrings.decodeUtf8(request.getBody());
List<R> list = deserializeUpdateRequest(gson, json, model.getRecordType(), model.getIdType());
model.update(list, new ForwardingResultCallback<UpdateResponse<K,R>>(callback) {
@Override
protected void onResult(UpdateResponse<K, R> result) {
String json = result.toJson(gson, model.getRecordType(), model.getIdType());
callback.setResult(createResponse(json));
}
});
} catch (ParseException e) {
callback.setException(e);
}
}
};
}
public static <K, R extends AbstractRecord<K>> AsyncServlet delete(final GridModel<K, R> model, final Gson gson) {
return new AsyncServlet() {
@Override
public void serve(HttpRequest request, final ResultCallback<HttpResponse> callback) {
try {
K id = fromJson(gson, request.getUrlParameter("id"), model.getIdType());
model.delete(id, new ForwardingResultCallback<DeleteResponse>(callback) {
@Override
protected void onResult(DeleteResponse response) {
HttpResponse res = HttpResponse.ok200();
if (response.hasErrors()) {
String json = gson.toJson(response.getErrors());
res.setContentType(JSON_UTF8);
res.setBody(ByteBufStrings.wrapUtf8(json));
}
callback.setResult(res);
}
});
} catch (ParseException e) {
callback.setException(e);
}
}
};
}
private static HttpResponse createResponse(String body) {
return HttpResponse.ok200()
.withContentType(JSON_UTF8)
.withBody(ByteBufStrings.wrapUtf8(body));
}
}