Skip to content

Commit

Permalink
Feat/external api (#2)
Browse files Browse the repository at this point in the history
* sonar updates

* update menu controller

* add external api with tests

---------

Co-authored-by: milan.horvath <[email protected]>
  • Loading branch information
milanhorvath and milan.horvath authored Dec 5, 2023
1 parent c281e96 commit db40032
Show file tree
Hide file tree
Showing 29 changed files with 296 additions and 222 deletions.
22 changes: 5 additions & 17 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>io.github.onecx</groupId>
<artifactId>onecx-quarkus3-parent</artifactId>
<version>0.23.0</version>
<version>0.22.0</version>
</parent>

<artifactId>onecx-workspace-svc</artifactId>
Expand Down Expand Up @@ -183,31 +183,19 @@
<modelNameSuffix>DTO</modelNameSuffix>
</configuration>
</execution>
<!-- <execution>
<execution>
<id>v1</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>src/main/openapi/onecx-portal-v1-openapi.yaml</inputSpec>
<apiPackage>gen.io.github.onecx.portal.rs.external.v1</apiPackage>
<modelPackage>gen.io.github.onecx.portal.rs.external.v1.model</modelPackage>
<inputSpec>src/main/openapi/onecx-workspace-v1-openapi.yaml</inputSpec>
<apiPackage>gen.io.github.onecx.workspace.rs.external.v1</apiPackage>
<modelPackage>gen.io.github.onecx.workspace.rs.external.v1.model</modelPackage>
<modelNameSuffix>DTOV1</modelNameSuffix>
<apiNameSuffix>V1Api</apiNameSuffix>
</configuration>
</execution>
<execution>
<id>operator</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>src/main/openapi/onecx-portal-operator-v1-openapi.yaml</inputSpec>
<apiPackage>gen.io.github.onecx.portal.rs.operator.v1</apiPackage>
<modelPackage>gen.io.github.onecx.portal.rs.operator.v1.model</modelPackage>
<modelNameSuffix>DTOV1</modelNameSuffix>
</configuration>
</execution> -->
<execution>
<id>di-workspace-v1</id>
<goals>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package io.github.onecx.workspace.domain.criteria;

import java.io.Serializable;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class WorkspaceSearchCriteria {
public class WorkspaceSearchCriteria implements Serializable {

private String workspaceName;

Expand All @@ -14,4 +16,4 @@ public class WorkspaceSearchCriteria {
private Integer pageNumber;

private Integer pageSize;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

import org.tkit.quarkus.jpa.daos.AbstractDAO;
import org.tkit.quarkus.jpa.exceptions.DAOException;
import org.tkit.quarkus.jpa.models.TraceableEntity_;

import io.github.onecx.workspace.domain.models.Product;
import io.github.onecx.workspace.domain.models.Product_;
import io.github.onecx.workspace.domain.models.Workspace_;

@ApplicationScoped
public class ProductDAO extends AbstractDAO<Product> {
Expand All @@ -21,7 +21,7 @@ public List<Product> getProductsForWorkspaceId(String id) {
var cq = cb.createQuery(Product.class);
var root = cq.from(Product.class);

cq.where(cb.equal(root.get(Product_.WORKSPACE).get(Workspace_.ID), id));
cq.where(cb.equal(root.get(Product_.WORKSPACE).get(TraceableEntity_.ID), id));
return this.getEntityManager().createQuery(cq).getResultList();
} catch (Exception ex) {
throw new DAOException(ProductDAO.ErrorKeys.ERROR_FIND_PRODUCTS_BY_WORKSPACE_ID, ex);
Expand All @@ -34,7 +34,7 @@ public void deleteProduct(String id) {
var cq = cb.createQuery(Product.class);
var root = cq.from(Product.class);

cq.where(cb.equal(root.get(Product_.ID), id));
cq.where(cb.equal(root.get(TraceableEntity_.ID), id));
var product = this.getEntityManager().createQuery(cq).getSingleResult();
this.getEntityManager().remove(product);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.NoResultException;
Expand All @@ -18,6 +19,8 @@

import io.github.onecx.workspace.domain.criteria.WorkspaceSearchCriteria;
import io.github.onecx.workspace.domain.models.Workspace;
import io.github.onecx.workspace.domain.models.WorkspaceInfo;
import io.github.onecx.workspace.domain.models.Workspace_;

@ApplicationScoped
public class WorkspaceDAO extends AbstractDAO<Workspace> {
Expand Down Expand Up @@ -102,12 +105,37 @@ public PageResult<Workspace> findBySearchCriteria(WorkspaceSearchCriteria criter
}
}

/**
* This method fetches a workspace info with
* themeName provided as a param and
* tenantId provided as a param
*
* @return WorkspaceInfo entity if exists otherwise null
*/
public Stream<WorkspaceInfo> findByThemeName(String themeName) {

try {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(WorkspaceInfo.class);
var root = cq.from(Workspace.class);

cq.select(cb.construct(WorkspaceInfo.class, root.get(WORKSPACE_NAME), root.get(Workspace_.DESCRIPTION)));
cq.where(cb.equal(root.get(THEME), themeName));

return this.getEntityManager().createQuery(cq).getResultStream();
} catch (Exception ex) {
throw new DAOException(ErrorKeys.ERROR_FIND_BY_THEME_NAME, ex);
}
}

public enum ErrorKeys {

ERROR_FIND_BY_BASE_URL,

ERROR_FIND_BY_CRITERIA,
ERROR_FIND_WORKSPACE_NAME,

ERROR_FIND_BY_THEME_NAME,
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,7 @@ public void importRequests(WorkspaceDataImportDTOV1 data) {
try {
importRequest(request);
} catch (Exception ex) {
if (request.getWorkspace() != null && request.getWorkspace().getWorkspaceName() != null) {
throw new ImportException("Error import portal " + request.getWorkspace().getWorkspaceName(), ex);
} else {
throw new ImportException("Error import portal", ex);
}
throw new ImportException("Error import portal " + request.getWorkspace().getWorkspaceName(), ex);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.github.onecx.workspace.domain.models;

import java.io.Serializable;

import jakarta.persistence.Embeddable;

import lombok.Getter;
Expand All @@ -8,7 +10,7 @@
@Getter
@Setter
@Embeddable
public class SubjectLink {
public class SubjectLink implements Serializable {

private String label;
private String url;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.github.onecx.workspace.domain.models;

import java.io.Serializable;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;

Expand All @@ -9,7 +11,7 @@
@Getter
@Setter
@Embeddable
public class WorkspaceAddress {
public class WorkspaceAddress implements Serializable {

@Column(name = "street")
private String street;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package io.github.onecx.workspace.domain.models;

public record WorkspaceInfo(String workspaceName, String description) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.github.onecx.workspace.rs.external.v1.controllers;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;

import org.tkit.quarkus.log.cdi.LogService;

import gen.io.github.onecx.workspace.rs.external.v1.WorkspaceExternalV1Api;
import io.github.onecx.workspace.domain.daos.WorkspaceDAO;
import io.github.onecx.workspace.rs.external.v1.mappers.WorkspaceMapper;

@LogService
@ApplicationScoped
@Path("/v1/workspaces/theme/{themeName}")
@Transactional(Transactional.TxType.NOT_SUPPORTED)
public class WorkspaceExternalV1RestController implements WorkspaceExternalV1Api {

@Inject
WorkspaceDAO workspaceDAO;

@Inject
WorkspaceMapper mapper;

@Override
public Response getWorkspaceInfos(String themeName) {
var workspaceInfos = workspaceDAO.findByThemeName(themeName);
return Response.ok(mapper.mapInfoList(workspaceInfos)).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.github.onecx.workspace.rs.external.v1.mappers;

import java.util.List;
import java.util.stream.Stream;

import org.mapstruct.Mapper;
import org.tkit.quarkus.rs.mappers.OffsetDateTimeMapper;

import gen.io.github.onecx.workspace.rs.external.v1.model.WorkspaceInfoDTOV1;
import gen.io.github.onecx.workspace.rs.external.v1.model.WorkspaceInfoListDTOV1;
import io.github.onecx.workspace.domain.models.WorkspaceInfo;

@Mapper(uses = { OffsetDateTimeMapper.class })
public abstract class WorkspaceMapper {

public WorkspaceInfoListDTOV1 mapInfoList(Stream<WorkspaceInfo> data) {
var result = new WorkspaceInfoListDTOV1();
result.setWorkspaces(mapInfo(data));
return result;
}

public abstract List<WorkspaceInfoDTOV1> mapInfo(Stream<WorkspaceInfo> page);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.github.onecx.workspace.rs.internal.controllers;

import static org.jboss.resteasy.reactive.RestResponse.StatusCode.BAD_REQUEST;
import static org.jboss.resteasy.reactive.RestResponse.StatusCode.NOT_FOUND;

import java.util.*;
Expand All @@ -10,6 +9,7 @@
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.validation.ConstraintViolationException;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriInfo;
Expand All @@ -29,6 +29,7 @@

@LogService
@ApplicationScoped
@Path("/internal/workspaces/{id}/menuItems")
@Transactional(Transactional.TxType.NOT_SUPPORTED)
public class MenuInternalRestController implements MenuInternalApi {

Expand Down Expand Up @@ -138,10 +139,7 @@ public Response patchMenuItems(String id, List<MenuItemDTO> menuItemDTO) {
MenuItemDTO dto = tmp.get(item.getId());

// update parent
var response = updateParent(item, dto);
if (response != null) {
return response;
}
updateParent(item, dto);

mapper.update(dto, item);
}
Expand All @@ -158,10 +156,7 @@ public Response updateMenuItem(String id, String menuItemId, MenuItemDTO menuIte
}

// update parent
var response = updateParent(menuItem, menuItemDTO);
if (response != null) {
return response;
}
updateParent(menuItem, menuItemDTO);

mapper.update(menuItemDTO, menuItem);

Expand Down Expand Up @@ -189,54 +184,48 @@ public Response uploadMenuStructureForWorkspaceId(String id, WorkspaceMenuItemSt

}

private Response updateParent(MenuItem menuItem, MenuItemDTO dto) {
private void updateParent(MenuItem menuItem, MenuItemDTO dto) {

if (dto.getParentItemId() == null) {
menuItem.setParent(null);
return null;
return;
}

// check parent change
if (menuItem.getParent() != null && dto.getParentItemId().equals(menuItem.getParent().getId())) {
return null;
return;
}

// checking if request parent id is the same as current id
if (dto.getParentItemId().equals(menuItem.getId())) {
// TODO: make a failed contraint error
return Response.status(BAD_REQUEST).entity("Menu Item " + menuItem.getId() + " id and parentItem id are the same")
.build();
throw new ConstraintException("Menu Item " + menuItem.getId() + " id and parentItem id are the same",
MenuItemErrorKeys.PARENT_MENU_SAME_AS_MENU_ITEM, null);
}

// checking if parent exists
var parent = dao.findById(dto.getParentItemId());
if (parent == null) {
// TODO: make a failed contraint error
return Response.status(BAD_REQUEST)
.entity("Parent menu item " + dto.getParentItemId() + " does not exists").build();
throw new ConstraintException("Parent menu item " + dto.getParentItemId() + " does not exists",
MenuItemErrorKeys.PARENT_MENU_DOES_NOT_EXIST, null);
} else {

// checking if parent exists in the same portal
if (!parent.getWorkspace().getId().equals(menuItem.getWorkspace().getId())) {
// TODO: make a failed contraint error
return Response.status(BAD_REQUEST).entity("Parent menu item is assigned to different portal").build();
throw new ConstraintException("Parent menu item is assigned to different portal",
MenuItemErrorKeys.PARENT_ASSIGNED_TO_DIFFERENT_PORTAL, null);
}

// check for cycle
Set<String> children = new HashSet<>();
children(menuItem, children);
if (children.contains(parent.getId())) {
// TODO: make a failed contraint error
return Response.status(BAD_REQUEST).entity(
"One of the items try to set one of its children to the new parent. Cycle dependency can not be created in tree structure")
.build();
throw new ConstraintException(
"One of the items try to set one of its children to the new parent. Cycle dependency can not be created in tree structure",
MenuItemErrorKeys.CYCLE_DEPENDENCY, null);
}
}

// set new parent
menuItem.setParent(parent);

return null;
}

private void children(MenuItem menuItem, Set<String> result) {
Expand All @@ -259,9 +248,15 @@ public RestResponse<ProblemDetailResponseDTO> constraint(ConstraintViolationExce
enum MenuItemErrorKeys {
WORKSPACE_DOES_NOT_EXIST,
PARENT_MENU_DOES_NOT_EXIST,

PARENT_MENU_SAME_AS_MENU_ITEM,
WORKSPACE_DIFFERENT,

MENU_ITEMS_NULL,

PARENT_ASSIGNED_TO_DIFFERENT_PORTAL,

CYCLE_DEPENDENCY

}
}
Loading

0 comments on commit db40032

Please sign in to comment.