CCM NG: RESTful backend for PageModel Editor

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5418 8810af33-2d31-482b-a856-94f89814c4df

Former-commit-id: dfff31bd8a
pull/2/head
jensp 2018-05-07 15:46:01 +00:00
parent 817fd20d30
commit ebe7ec02e8
4 changed files with 266 additions and 2 deletions

View File

@ -20,12 +20,23 @@ package org.libreccm.pagemodel.rs;
import org.libreccm.core.CoreConstants; import org.libreccm.core.CoreConstants;
import org.libreccm.pagemodel.ComponentModel; import org.libreccm.pagemodel.ComponentModel;
import org.libreccm.pagemodel.ComponentModelRepository;
import org.libreccm.pagemodel.ContainerModel; import org.libreccm.pagemodel.ContainerModel;
import org.libreccm.pagemodel.ContainerModelManager;
import org.libreccm.pagemodel.PageModel; import org.libreccm.pagemodel.PageModel;
import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege; import org.libreccm.security.RequiresPrivilege;
import org.libreccm.web.CcmApplication; import org.libreccm.web.CcmApplication;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.json.Json; import javax.json.Json;
@ -34,10 +45,14 @@ import javax.json.JsonArrayBuilder;
import javax.json.JsonObject; import javax.json.JsonObject;
import javax.json.JsonObjectBuilder; import javax.json.JsonObjectBuilder;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
/** /**
* *
@ -47,6 +62,12 @@ import javax.ws.rs.Produces;
@Path("/") @Path("/")
public class Components { public class Components {
@Inject
private ComponentModelRepository componentRepo;
@Inject
private ContainerModelManager containerManager;
@Inject @Inject
private PageModelsController controller; private PageModelsController controller;
@ -104,6 +125,53 @@ public class Components {
return mapComponentModelToJson(component); return mapComponentModelToJson(component);
} }
@PUT
@Path(PageModelsApp.COMPONENT_PATH)
@Consumes("application/json; charset=utf-8")
@Produces("application/json; charset=utf-8")
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public JsonObject putComponent(
@PathParam(PageModelsApp.APP_NAME) final String appPath,
@PathParam(PageModelsApp.PAGE_MODEL_NAME) final String pageModelName,
@PathParam(PageModelsApp.CONTAINER_KEY) final String containerKey,
@PathParam(PageModelsApp.COMPONENT_KEY) final String componentKey,
final JsonObject componentModelJson) {
final CcmApplication app = controller.findCcmApplication(
String.format("/%s/", appPath));
final PageModel pageModel = controller.findPageModel(app,
pageModelName);
final ContainerModel container = controller.findContainer(app,
pageModel,
containerKey);
final Optional<ComponentModel> result = container
.getComponents()
.stream()
.filter(c -> c.getKey().equals(componentKey))
.findAny();
final ComponentModel componentModel;
if (result.isPresent()) {
componentModel = result.get();
} else {
componentModel = createComponentModel(componentModelJson);
componentModel.setKey(componentKey);
containerManager.addComponentModel(container, componentModel);
}
setComponentPropertiesFromJson(componentModelJson, componentModel);
componentRepo.save(componentModel);
return mapComponentModelToJson(componentModel);
}
private JsonObject mapComponentModelToJson( private JsonObject mapComponentModelToJson(
final ComponentModel componentModel) { final ComponentModel componentModel) {
@ -133,4 +201,98 @@ public class Components {
return objectBuilder.build(); return objectBuilder.build();
} }
private ComponentModel createComponentModel(final JsonObject data) {
if (!data.containsKey("type")) {
throw new BadRequestException("The JSON data for creating the "
+ "component has no value for the type of the component to "
+ "create.");
}
final String type = data.getString("type");
final Class<? extends ComponentModel> clazz = findComponentModelClass(
type);
final ComponentModel componentModel;
try {
componentModel = clazz.getConstructor().newInstance();
} catch (IllegalAccessException
| InstantiationException
| InvocationTargetException
| NoSuchMethodException ex) {
throw new WebApplicationException(ex);
}
return componentModel;
}
@SuppressWarnings("unchecked")
private Class<? extends ComponentModel> findComponentModelClass(
final String type) {
try {
final Class<?> clazz = Class.forName(type);
if (clazz.isAssignableFrom(ComponentModel.class)) {
return (Class<? extends ComponentModel>) clazz;
} else {
throw new BadRequestException(String.format(
"The type \"%s\" is not a subclass of \"%s\".",
type,
ComponentModel.class.getName()));
}
} catch (ClassNotFoundException ex) {
throw new BadRequestException(String.format(
"The component model type \"%s\" "
+ "does not exist.",
type));
}
}
private void setComponentPropertiesFromJson(
final JsonObject data,
final ComponentModel componentModel) {
final BeanInfo beanInfo;
try {
beanInfo = Introspector.getBeanInfo(componentModel.getClass());
} catch (IntrospectionException ex) {
throw new WebApplicationException(ex);
}
Arrays
.stream(beanInfo.getPropertyDescriptors())
.forEach(
propertyDesc -> setComponentPropertyFromJson(componentModel,
propertyDesc,
data));
}
private void setComponentPropertyFromJson(
final ComponentModel componentModel,
final PropertyDescriptor propertyDesc,
final JsonObject data) {
// Ignore key and type (handled by other methods).
if ("key".equals(propertyDesc.getName())
|| "type".equals(propertyDesc.getName())) {
return;
}
if (data.containsKey(propertyDesc.getName())) {
final Method writeMethod = propertyDesc.getWriteMethod();
if (writeMethod != null) {
try {
writeMethod.invoke(componentModel,
data.getString(propertyDesc.getName()));
} catch (IllegalAccessException
| InvocationTargetException ex) {
throw new WebApplicationException(ex);
}
}
}
}
} }

View File

@ -20,11 +20,16 @@ package org.libreccm.pagemodel.rs;
import org.libreccm.core.CoreConstants; import org.libreccm.core.CoreConstants;
import org.libreccm.pagemodel.ContainerModel; import org.libreccm.pagemodel.ContainerModel;
import org.libreccm.pagemodel.ContainerModelRepository;
import org.libreccm.pagemodel.PageModel; import org.libreccm.pagemodel.PageModel;
import org.libreccm.pagemodel.PageModelManager;
import org.libreccm.pagemodel.PageModelRepository;
import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege; import org.libreccm.security.RequiresPrivilege;
import org.libreccm.web.CcmApplication; import org.libreccm.web.CcmApplication;
import java.util.Optional;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.json.Json; import javax.json.Json;
@ -32,7 +37,10 @@ import javax.json.JsonArray;
import javax.json.JsonArrayBuilder; import javax.json.JsonArrayBuilder;
import javax.json.JsonObject; import javax.json.JsonObject;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
@ -48,6 +56,15 @@ public class Containers {
@Inject @Inject
private PageModelsController controller; private PageModelsController controller;
@Inject
private ContainerModelRepository containerModelRepo;
@Inject
private PageModelManager pageModelManager;
@Inject
private PageModelRepository pageModelRepo;
@GET @GET
@Path(PageModelsApp.CONTAINERS_PATH) @Path(PageModelsApp.CONTAINERS_PATH)
@Produces("application/json; charset=utf-8") @Produces("application/json; charset=utf-8")
@ -98,6 +115,72 @@ public class Containers {
return mapContainerModelToJson(container); return mapContainerModelToJson(container);
} }
@PUT
@Path(PageModelsApp.CONTAINER_PATH)
@Consumes("application/json; charset=utf-8")
@Produces("application/json; charset=utf-8")
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public JsonObject putContainer(
@PathParam(PageModelsApp.APP_NAME) final String appPath,
@PathParam(PageModelsApp.PAGE_MODEL_NAME) final String pageModelName,
@PathParam(PageModelsApp.CONTAINER_KEY) final String containerKey,
final JsonObject containerModelJson) {
final CcmApplication app = controller.findCcmApplication(
String.format("/%s/", appPath));
final PageModel pageModel = controller.findPageModel(app,
pageModelName);
final Optional<ContainerModel> result = pageModel
.getContainers()
.stream()
.filter(model -> model.getKey().equals(containerKey))
.findAny();
final ContainerModel containerModel;
if (result.isPresent()) {
containerModel = result.get();
result.get().setKey(containerKey);
containerModelRepo.save(result.get());
} else {
containerModel = new ContainerModel();
containerModel.setKey(containerKey);
pageModelManager.addContainerModel(pageModel, containerModel);
}
return mapContainerModelToJson(containerModel);
}
@DELETE
@Path(PageModelsApp.CONTAINER_PATH)
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public void deleteContainer(
@PathParam(PageModelsApp.APP_NAME) final String appPath,
@PathParam(PageModelsApp.PAGE_MODEL_NAME) final String pageModelName,
@PathParam(PageModelsApp.CONTAINER_KEY) final String containerKey) {
final CcmApplication app = controller.findCcmApplication(
String.format("/%s/", appPath));
final PageModel pageModel = controller.findPageModel(app,
pageModelName);
final ContainerModel container = controller.findContainer(app,
pageModel,
containerKey);
pageModelManager.removeContainerModel(pageModel, container);
}
private JsonObject mapContainerModelToJson( private JsonObject mapContainerModelToJson(
final ContainerModel containerModel) { final ContainerModel containerModel) {

View File

@ -36,6 +36,7 @@ import javax.json.JsonArrayBuilder;
import javax.json.JsonObject; import javax.json.JsonObject;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
@ -145,12 +146,28 @@ public class PageModels {
pageModel.setApplication(app); pageModel.setApplication(app);
} }
pageModel.setName(pageModelName); pageModel.setName(pageModelName);
controller.savePageModel(pageModel); controller.savePageModel(pageModel);
return mapPageModelToJson(controller.findPageModel(app, pageModelName)); return mapPageModelToJson(controller.findPageModel(app, pageModelName));
} }
@DELETE
@Path(PageModelsApp.PAGE_MODEL_PATH)
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public void deletePageModel(
@PathParam(PageModelsApp.APP_NAME) final String appPath,
@PathParam(PageModelsApp.PAGE_MODEL_NAME) final String pageModelName) {
final CcmApplication app = controller
.findCcmApplication(String.format("/%s/", appPath));
final PageModel pageModel = controller.findPageModel(app,
pageModelName);
pageModelRepo.delete(pageModel);
}
private JsonObject mapPageModelToJson(final PageModel pageModel) { private JsonObject mapPageModelToJson(final PageModel pageModel) {
return Json return Json

View File

@ -98,6 +98,8 @@ class PageModelsController {
containerKey))); containerKey)));
} }
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
protected boolean existsPageModel(final CcmApplication app, protected boolean existsPageModel(final CcmApplication app,
final String pageModelName) { final String pageModelName) {