Skip to content

Commit

Permalink
#28894 Create Endpoint to calculate Hierarchy (#29142)
Browse files Browse the repository at this point in the history
  • Loading branch information
freddyDOTCMS and dsilvam authored Jul 9, 2024
1 parent c98dafc commit 7bbef89
Show file tree
Hide file tree
Showing 11 changed files with 1,292 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.dotmarketing.portlets.categories.business.CategoryAPI;
import com.dotmarketing.portlets.categories.business.PaginatedCategories;
import com.dotmarketing.portlets.categories.model.Category;
import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
import com.dotmarketing.util.ActivityLogger;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.PageMode;
Expand Down Expand Up @@ -138,7 +139,6 @@ public CategoriesResource(final WebResource webresource, final PaginationUtil pa
* <li>per_page: limit of items to return</li>
* <li>ordeby: field to order by</li>
* <li>direction: asc for upward order and desc for downward order</li>
* <li>showChildrenCount: true for including children categories count and false to exclude it</li>
* </ul>
* <p>
* Url example: /api/v1/categories?filter=&page=0&per_page=5&ordeby=category_name&direction=ASC&showChildrenCount=true
Expand Down Expand Up @@ -196,22 +196,30 @@ public final Response getCategories(@Context final HttpServletRequest httpReques

/**
* Return a list of {@link com.dotmarketing.portlets.categories.model.Category}, entity response
* syntax:.
* Syntax:.
*
* <code>
* {
* contentTypes: array of Category,
* total: total number of Categories
* }
* <code/>
*
* <code> { contentTypes: array of Category total: total number of Categories } <code/>
* <p>
* Url syntax:
* api/v1/categories/children?filter=filter-string&page=page-number&per_page=per-page&orderby=order-field-name&direction=order-direction&inode=parentId
* <p>
* where:
*
* <ul>
* <li>filter-string: just return Category whose content this pattern into its name</li>
* <li>page: page to return</li>
* <li>per_page: limit of items to return</li>
* <li>ordeby: field to order by</li>
* <li>direction: asc for upward order and desc for downward order</li>
* </ul>
* Parameeters:
*
* - filter-string: Return categories whose names contain this pattern.
* - page: The page number to return.
* - per_page: The limit of items to return.
* - orderby: The field to order by.
* - direction: Sorting direction, asc for ascending and desc for descending.
* - showChildrenCount: true to include the count of child categories, false to exclude it.
* - allLevels: A Boolean value. If TRUE, the search will include categories at any level, ignoring the childrenCategories parameter. If showChildrenCount is TRUE, this parameter is ignored.
*
* <p>
* Url example: v1/categories/children?filter=test&page=0&per_page=5&orderby=category_name
*
Expand Down Expand Up @@ -276,6 +284,79 @@ public final Response getChildren(@Context final HttpServletRequest httpRequest,
return response;
}

/**
* Response with the list of parents for a specific set of {@link Category}.
*
* This ned point receive a list the {@link Category}'s endpoint as follow:
*
* <code>
* {
* "inodes": ["352ca17e238357ce12e9dff10afc8516", "c0ab974897f8d37c98afa4bba74ef9f1"]
* }
* </code>
*
* The output is going to be something like:
*
* <code>
* {
* entity: [
* {
* "inode": "352ca17e238357ce12e9dff10afc8516",
* "parentList": [
* {
* 'categoryName': 'Grand Parent Name',
* 'key': 'Grand Parent Key',
* 'inode': 'Grand Parent inode'
* },
* {
* 'categoryName': 'Parent Name',
* 'key': 'Parent Key',
* 'inode': 'Parent inode'
* }
* ]
* },
* {
* "inode": "c0ab974897f8d37c98afa4bba74ef9f1",
* "parentList": [
* {
* 'categoryName': 'Category name value',
* 'key': 'Key value',
* 'inode': 'inode value'
* }
* ]
* }
* ]
* }
* </code>
*
* parentList is the list of parents where the 0 is the more top level parent and the last one is the direct
* parent.
*
* @param httpRequest
* @param httpResponse
* @param form
* @return
* @throws DotDataException
* @throws DotSecurityException
*/
@GET
@Path(("/hierarchy"))
@JSONP
@NoCache
@Produces({MediaType.APPLICATION_JSON})
public final Response getHierarchy(@Context final HttpServletRequest httpRequest,
@Context final HttpServletResponse httpResponse,
final CategoryInodesForm form) throws DotDataException, DotSecurityException {

Logger.debug(this, () -> "Getting the List of Parents for the follow categories: " +
form.getInodes().stream().collect(Collectors.joining(",")));

webResource.init(null, httpRequest, httpResponse, true, null);

return Response.ok(
new HierarchyShortCategoriesResponseView(categoryAPI.findHierarchy(form.getInodes()))).build();
}

/**
* Lookup operation. Categories can be retrieved by category id or key
* @param httpRequest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.dotcms.rest.api.v1.categories;

import com.dotcms.repackage.javax.validation.constraints.NotNull;
import com.dotcms.rest.api.Validated;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import java.util.List;

/**
* Category Input Form
*/
@JsonDeserialize(builder = CategoryInodesForm.Builder.class)
public class CategoryInodesForm extends Validated {

private List<String> inodes;

private CategoryInodesForm(final Builder builder) {

this.inodes = builder.inodes;
}

public List<String> getInodes() {
return inodes;
}

public static final class Builder {

@JsonProperty
private List<String> inodes;

public void setInodes(List<String> inodes) {
this.inodes = inodes;
}

public CategoryInodesForm build() {

return new CategoryInodesForm(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.dotcms.rest.api.v1.categories;

import com.dotcms.experiments.model.Experiment;
import com.dotcms.rest.ResponseEntityView;
import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;

import java.util.List;

public class HierarchyShortCategoriesResponseView extends ResponseEntityView<List<HierarchyShortCategory>> {
public HierarchyShortCategoriesResponseView(final List<HierarchyShortCategory> categories) {
super(categories);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.portlets.categories.model.Category;
import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
import com.dotmarketing.portlets.contentlet.model.Contentlet;
import com.liferay.portal.model.User;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
/**
Expand Down Expand Up @@ -496,4 +499,38 @@ Category findByVariable(final String variable, final User user,
*/
PaginatedCategories findAll(final CategorySearchCriteria searchCriteria, final User user, boolean respectFrontendRoles)
throws DotDataException, DotSecurityException;

/**
* Find Categories by inodes and calculate its Hierarchy.
*
* For Example if you have the follows categories:
*
*
* | Inode | Name | key |Parent |
* |--------|-------------|-------------|----------------|
* | 1 | Top Category| top | null |
* | 2 | Child | child | Top Category |
* | 3 | Grand Child | grand_child | Child |
*
* And you search by inode 3 then you got:
*
* Inode: 3
* parentList <code>[
* {
* 'categoryName':'Top Category',
* 'key': 'top',
* 'inode': '1'
* },
* {
* 'categoryName':'Child',
* 'key': 'child',
* 'inode': '2'
* }
* ]</code>
*
* @param inodes List of inodes to search
* @return
* @throws DotDataException
*/
List<HierarchyShortCategory> findHierarchy(final Collection<String> inodes) throws DotDataException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.portlets.categories.model.Category;
import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
import com.dotmarketing.portlets.contentlet.model.Contentlet;
import com.dotmarketing.util.ActivityLogger;
import com.dotmarketing.util.InodeUtils;
Expand All @@ -25,14 +26,8 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.liferay.portal.model.User;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

import java.util.*;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -978,4 +973,18 @@ public PaginatedCategories findAll(final CategorySearchCriteria searchCriteria,
return getCategoriesSubList(searchCriteria.offset, searchCriteria.limit, categories, null);
}

/**
* Default implementation of {@link CategoryAPI}
*
* @param inodes List of inodes to search
* @return
*
* @throws DotDataException
*/
@CloseDBIfOpened
@Override
public List<HierarchyShortCategory> findHierarchy(final Collection<String> inodes) throws DotDataException {
Logger.debug(this, "Getting parentList for the follow Categories: " + inodes);
return categoryFactory.findHierarchy(inodes);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.dotmarketing.portlets.categories.business;


import java.util.Collection;
import java.util.List;

import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.portlets.categories.model.Category;
import com.dotmarketing.portlets.categories.model.HierarchedCategory;
import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;


/**
Expand Down Expand Up @@ -286,4 +288,38 @@ public abstract class CategoryFactory {
* @return List of Category filteredx
*/
public abstract List<HierarchedCategory> findAll(final CategorySearchCriteria searchCriteria) throws DotDataException;

/**
* Find Categories by inodes and calculate its Hierarchy.
*
* For Example if you have the follows categories:
*
*
* | Inode | Name | key |Parent |
* |--------|-------------|-------------|----------------|
* | 1 | Top Category| top | null |
* | 2 | Child | child | Top Category |
* | 3 | Grand Child | grand_child | Child |
*
* And you search by inode 3 then you got:
*
* Inode: 3
* parentList <code>[
* {
* 'categoryName':'Top Category',
* 'key': 'top',
* 'inode': '1'
* },
* {
* 'categoryName':'Child',
* 'key': 'child',
* 'inode': '2'
* }
* ]</code>
*
* @param inodes List of inodes to search
* @return
* @throws DotDataException
*/
public abstract List<HierarchyShortCategory> findHierarchy(final Collection<String> inodes) throws DotDataException;
}
Loading

0 comments on commit 7bbef89

Please sign in to comment.