com.smartitengineering.cms.ws.resources.content.searcher.ContentSearcherResource.java Source code

Java tutorial

Introduction

Here is the source code for com.smartitengineering.cms.ws.resources.content.searcher.ContentSearcherResource.java

Source

/*
 *
 * This is a simple Content Management System (CMS)
 * Copyright (C) 2010  Imran M Yousuf (imyousuf@smartitengineering.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.smartitengineering.cms.ws.resources.content.searcher;

import com.smartitengineering.cms.api.content.Content;
import com.smartitengineering.cms.api.content.Filter;
import com.smartitengineering.cms.api.factory.SmartContentAPI;
import com.smartitengineering.cms.api.type.ContentStatus;
import com.smartitengineering.cms.api.type.ContentTypeId;
import com.smartitengineering.cms.api.type.MutableContentStatus;
import com.smartitengineering.cms.api.workspace.WorkspaceId;
import com.smartitengineering.cms.ws.common.domains.SearchResult;
import com.smartitengineering.cms.ws.resources.content.ContentResource;
import com.smartitengineering.cms.ws.resources.content.ContentResource.ContentAdapterHelper;
import com.smartitengineering.dao.common.queryparam.QueryParameter;
import com.smartitengineering.dao.common.queryparam.QueryParameterFactory;
import com.smartitengineering.util.bean.adapter.GenericAdapter;
import com.smartitengineering.util.bean.adapter.GenericAdapterImpl;
import com.smartitengineering.util.opensearch.api.Url.RelEnum;
import com.smartitengineering.util.opensearch.impl.OpenSearchDescriptorBuilder;
import com.smartitengineering.util.opensearch.impl.UrlBuilder;
import com.smartitengineering.util.rest.atom.server.AbstractResource;
import com.smartitengineering.util.rest.server.ServerResourceInjectables;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriBuilder;
import org.apache.abdera.ext.opensearch.OpenSearchConstants;
import org.apache.abdera.ext.opensearch.model.IntegerElement;
import org.apache.abdera.ext.opensearch.model.Query;
import org.apache.abdera.model.Entry;
import org.apache.abdera.model.Feed;
import org.apache.abdera.model.Link;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author kaisar
 */
public class ContentSearcherResource extends AbstractResource {

    private final transient Logger logger = LoggerFactory.getLogger(getClass());
    private List<String> contentTypeId;
    private List<String> statuses;
    private String workspaceId;
    private String searchTerms;
    private List<String> fieldQuery;
    private String creationDate;
    private String lastModifiedDate;
    private int start;
    private int count;
    private boolean disjunction;
    private Boolean includeFriendlies = null;
    protected final GenericAdapter<Content, com.smartitengineering.cms.ws.common.domains.Content> adapter;
    private final static String WORKSPACE_ID = "workspaceId", STATUS = "status", TYPE_ID = "typeId",
            FIELD = "field", CREATION_DATE = "creationDate", LAST_MODIFIED_DATE = "lastModifiedDate",
            START = "start", COUNT = "count", DISJUNCTION = "disjunction", SEARCH_TERMS = "q",
            INCLUDE_FRIENDLIES = "includeFriendlies";

    public ContentSearcherResource(ServerResourceInjectables injectables) {
        super(injectables);
        GenericAdapterImpl adapterImpl = new GenericAdapterImpl<Content, com.smartitengineering.cms.ws.common.domains.Content>();
        adapterImpl.setHelper(new ContentAdapterHelper(injectables, false));
        adapter = adapterImpl;
    }

    @GET
    @Produces(com.smartitengineering.util.opensearch.jaxrs.MediaType.APPLICATION_OPENSEARCHDESCRIPTION_XML)
    public Response getSpec() {
        OpenSearchDescriptorBuilder descBuilder = OpenSearchDescriptorBuilder.getBuilder();
        descBuilder.shortName("Content Search");
        descBuilder.description("Search the content repository for contents!");
        StringBuilder templateBuilder = getSearchUri(true);
        final String urlTemplate = templateBuilder.toString();
        if (logger.isDebugEnabled()) {
            logger.debug("Template URL: " + urlTemplate);
        }
        UrlBuilder xmlBuilder = UrlBuilder.getBuilder().rel(RelEnum.RESULTS).indexOffset(start)
                .template(urlTemplate).type(MediaType.APPLICATION_ATOM_XML);
        UrlBuilder jsonBulder = UrlBuilder.getBuilder().rel(RelEnum.RESULTS).indexOffset(start)
                .template(urlTemplate).type(MediaType.APPLICATION_JSON);
        descBuilder.urls(xmlBuilder.build(), jsonBulder.build());
        ResponseBuilder builder = Response.ok(descBuilder.build());
        return builder.build();
    }

    protected StringBuilder getSearchUri(boolean withTemplate) {
        StringBuilder templateBuilder = new StringBuilder(getUriInfo().getRequestUri().toASCIIString());
        if (withTemplate) {
            templateBuilder.append('?').append(SEARCH_TERMS).append("=")
                    .append(StringUtils.isBlank(searchTerms) ? "{searchTerms}" : searchTerms);
            templateBuilder.append('&').append(START).append("=").append(start <= 0 ? "{startIndex?}" : start);
            templateBuilder.append('&').append(COUNT).append("=").append(count <= 0 ? "{count?}" : count);
            templateBuilder.append('&').append(WORKSPACE_ID).append("=")
                    .append(StringUtils.isBlank(workspaceId) ? "{workspaceId?}" : workspaceId);
            templateBuilder.append('&').append(CREATION_DATE).append("=")
                    .append(StringUtils.isBlank(creationDate) ? "{creationModifiedDateSpec?}" : creationDate);
            templateBuilder.append('&').append(LAST_MODIFIED_DATE).append("=")
                    .append(StringUtils.isBlank(lastModifiedDate) ? "{lastModifiedDateSpec?}" : lastModifiedDate);
            templateBuilder.append('&').append(INCLUDE_FRIENDLIES).append("=")
                    .append(includeFriendlies == null ? "{includeFriendlies?}" : includeFriendlies.booleanValue());
            if (contentTypeId != null && !contentTypeId.isEmpty()) {
                for (String typeId : contentTypeId) {
                    templateBuilder.append('&').append(TYPE_ID).append("=").append(typeId);
                }
            } else {
                templateBuilder.append('&').append(TYPE_ID).append("=").append("{contentTypeId?}");
            }
            if (statuses != null && !statuses.isEmpty()) {
                for (String status : statuses) {
                    templateBuilder.append('&').append(STATUS).append("=").append(status);
                }
            } else {
                templateBuilder.append('&').append(STATUS).append("=").append("{statuses?}");
            }
            if (fieldQuery != null && !fieldQuery.isEmpty()) {
                for (String query : fieldQuery) {
                    templateBuilder.append('&').append(FIELD).append("=").append(query);
                }
            } else {
                templateBuilder.append('&').append(FIELD).append("=").append("{fieldQuery?}");
            }
            templateBuilder.append('&').append(DISJUNCTION).append("=").append("{disjunction?}");
        } else {
            templateBuilder.append('?');
            if (StringUtils.isNotBlank(searchTerms)) {
                templateBuilder.append(SEARCH_TERMS).append("=").append(searchTerms).append('&');
            }
            if (StringUtils.isNotBlank(workspaceId)) {
                templateBuilder.append(WORKSPACE_ID).append("=").append(workspaceId).append('&');
            }
            if (StringUtils.isNotBlank(creationDate)) {
                templateBuilder.append(CREATION_DATE).append("=").append(creationDate).append('&');
            }
            if (StringUtils.isNotBlank(lastModifiedDate)) {
                templateBuilder.append(LAST_MODIFIED_DATE).append("=").append(lastModifiedDate).append('&');
            }
            if (includeFriendlies != null) {
                templateBuilder.append(INCLUDE_FRIENDLIES).append("=").append(includeFriendlies.booleanValue())
                        .append('&');
            }
            if (start >= 0) {
                templateBuilder.append(START).append("=").append(start).append('&');
            }
            if (count >= 0) {
                templateBuilder.append(COUNT).append("=").append(count).append('&');
            }
            if (disjunction) {
                templateBuilder.append(DISJUNCTION).append("=").append(disjunction).append('&');
            }
            if (contentTypeId != null && !contentTypeId.isEmpty()) {
                for (String typeId : contentTypeId) {
                    templateBuilder.append(TYPE_ID).append("=").append(typeId).append('&');
                }
            }
            if (statuses != null && !statuses.isEmpty()) {
                for (String status : statuses) {
                    templateBuilder.append(STATUS).append("=").append(status).append('&');
                }
            }
            if (fieldQuery != null && !fieldQuery.isEmpty()) {
                for (String query : fieldQuery) {
                    templateBuilder.append(FIELD).append("=").append(query);
                }
            }
        }
        return templateBuilder;
    }

    @GET
    @Produces(MediaType.APPLICATION_ATOM_XML)
    public Response getResultFeed(@QueryParam(TYPE_ID) List<String> contentTypeId,
            @QueryParam(SEARCH_TERMS) String searchTerms, @QueryParam(STATUS) List<String> statuses,
            @QueryParam(WORKSPACE_ID) String workspaceId, @QueryParam(FIELD) List<String> fieldQuery,
            @QueryParam(CREATION_DATE) String creationDate, @QueryParam(LAST_MODIFIED_DATE) String lastModifiedDate,
            @QueryParam(INCLUDE_FRIENDLIES) @DefaultValue("true") boolean includeFriendlies,
            @QueryParam(START) int start, @QueryParam(COUNT) @DefaultValue("5") int count,
            @QueryParam(DISJUNCTION) boolean disJunction) {
        initParams(contentTypeId, searchTerms, statuses, workspaceId, fieldQuery, creationDate, lastModifiedDate,
                start, count, disJunction, includeFriendlies);
        ResponseBuilder responseBuilder;
        Filter filter = getFilter();
        final com.smartitengineering.cms.api.common.SearchResult result = SmartContentAPI.getInstance()
                .getContentLoader().search(filter);
        final Collection<Content> searchContent = result.getResult();
        Feed feed = getFeed("search", "Content Search Result", new Date());
        feed.addLink(getLink(getUriInfo().getRequestUri().toASCIIString(), Link.REL_ALTERNATE,
                MediaType.APPLICATION_JSON));
        feed.addLink(getLink(
                new StringBuilder(getUriInfo().getBaseUri().toASCIIString()).append(getUriInfo().getPath())
                        .toString(),
                "search",
                com.smartitengineering.util.opensearch.jaxrs.MediaType.APPLICATION_OPENSEARCHDESCRIPTION_XML));
        Query query = feed.<Query>addExtension(OpenSearchConstants.QUERY);
        query.setRole(Query.Role.REQUEST);
        query.setCount(count);
        query.setStartIndex(start);
        query.setSearchTerms(searchTerms);
        IntegerElement countElem = feed.<IntegerElement>addExtension(OpenSearchConstants.ITEMS_PER_PAGE);
        countElem.setValue(count);
        IntegerElement startIndexElem = feed.<IntegerElement>addExtension(OpenSearchConstants.START_INDEX);
        startIndexElem.setValue(start);
        IntegerElement totalResultsElem = feed.<IntegerElement>addExtension(OpenSearchConstants.TOTAL_RESULTS);
        totalResultsElem.setValue(Long.valueOf(result.getTotalResultsCount()).intValue());
        if (searchContent != null && !searchContent.isEmpty()) {
            feed.addLink(getLink(getNextPage().toASCIIString(), Link.REL_NEXT, MediaType.APPLICATION_ATOM_XML));
            if (getPreviousPage() != null) {
                feed.addLink(getLink(getPreviousPage().toASCIIString(), Link.REL_PREVIOUS,
                        MediaType.APPLICATION_ATOM_XML));
            }
            for (Content content : searchContent) {
                final URI contentUri = ContentResource.getContentUri(getRelativeURIBuilder(),
                        content.getContentId());
                Entry entry = getEntry(content.getContentId().toString(),
                        new StringBuilder("Content ").append(content.getContentId().toString()).toString(),
                        content.getLastModifiedDate(),
                        getLink(contentUri, Link.REL_ALTERNATE, MediaType.APPLICATION_ATOM_XML),
                        getLink(contentUri, Link.REL_ALTERNATE, MediaType.APPLICATION_JSON));
                feed.addEntry(entry);
            }
        }
        responseBuilder = Response.ok(feed);
        return responseBuilder.build();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response get(@QueryParam(TYPE_ID) List<String> contentTypeId,
            @QueryParam(SEARCH_TERMS) String searchTerms, @QueryParam(STATUS) List<String> statuses,
            @QueryParam(WORKSPACE_ID) String workspaceId, @QueryParam(FIELD) List<String> fieldQuery,
            @QueryParam(CREATION_DATE) String creationDate, @QueryParam(LAST_MODIFIED_DATE) String lastModifiedDate,
            @QueryParam(INCLUDE_FRIENDLIES) @DefaultValue("true") boolean includeFriendlies,
            @QueryParam(START) int start, @QueryParam(COUNT) @DefaultValue("5") int count,
            @QueryParam(DISJUNCTION) boolean disJunction) {
        initParams(contentTypeId, searchTerms, statuses, workspaceId, fieldQuery, creationDate, lastModifiedDate,
                start, count, disJunction, includeFriendlies);
        Collection<Content> searchContent;
        ResponseBuilder responseBuilder;
        Filter filter = getFilter();
        final com.smartitengineering.cms.api.common.SearchResult searchResult = SmartContentAPI.getInstance()
                .getContentLoader().search(filter);
        searchContent = searchResult.getResult();
        if (searchContent.isEmpty() || searchContent == null) {
            responseBuilder = Response.status(Response.Status.NO_CONTENT);
        } else {
            SearchResult result = new SearchResult();
            result.setTotalResults(searchResult.getTotalResultsCount());
            result.setResult(adapter.convert(searchContent.toArray(new Content[searchContent.size()])));
            result.setCount(count);
            result.setStart(start);
            result.setNext(getNextPage());
            result.setPrevious(getPreviousPage());
            responseBuilder = Response.ok(result);
        }
        return responseBuilder.build();
    }

    protected void initParams(List<String> contentTypeId, String searchTerms, List<String> statuses,
            String workspaceId, List<String> fieldQuery, String creationDate, String lastModifiedDate, int start,
            int count, boolean disJunction, boolean includeFriendlies) {
        if (contentTypeId != null && !contentTypeId.isEmpty()) {
            this.contentTypeId = contentTypeId;
        } else if (this.contentTypeId == null) {
            this.contentTypeId = Collections.emptyList();
        }
        this.statuses = statuses;
        if (StringUtils.isNotBlank(workspaceId)) {
            this.workspaceId = workspaceId;
        }
        this.fieldQuery = fieldQuery;
        this.creationDate = creationDate;
        this.lastModifiedDate = lastModifiedDate;
        this.start = start;
        this.count = count;
        this.disjunction = disJunction;
        this.searchTerms = searchTerms;
        this.includeFriendlies = includeFriendlies;
    }

    protected URI getNextPage() {
        return getPage(1);
    }

    protected URI getPreviousPage() {
        if (start - count < 0) {
            return null;
        }
        return getPage(-1);
    }

    protected URI getPage(int offset) {
        return UriBuilder.fromUri(getUriInfo().getRequestUri()).replaceQueryParam(START, start + offset * count)
                .build();
    }

    private Filter getFilter() {
        Filter filter = SmartContentAPI.getInstance().getContentLoader().craeteFilter();
        if (StringUtils.isNotBlank(searchTerms)) {
            filter.setSearchTerms(searchTerms);
        }
        if (contentTypeId != null && !contentTypeId.isEmpty()) {
            filter.addContentTypeToFilter(parseCollectionContentTypeId(contentTypeId));
        }
        if (statuses != null && !statuses.isEmpty()) {
            filter.addStatusFilter(parseContentStatus(statuses));
        }
        if (fieldQuery != null && !fieldQuery.isEmpty()) {
            filter.addFieldFilter(parseFieldQuery(fieldQuery));
        }
        if (logger.isDebugEnabled()) {
            logger.debug(":::WORKSPACE ID : " + workspaceId);
            logger.debug(":::START FROM : " + String.valueOf(start));
            logger.debug(":::NUMBER OF ITEM : " + String.valueOf(count));
            logger.debug(":::VAULE OF DISJUNCTION : " + disjunction);
            logger.debug(":::VAULE OF Inclue Friendlies : " + includeFriendlies);
            logger.debug(":::CREATION DATE : " + creationDate);
            logger.debug(":::LAST MODIFIED DATE : " + lastModifiedDate);
        }
        if (StringUtils.isNotBlank(workspaceId)) {
            filter.setWorkspaceId(parseWorkspaceId(workspaceId));
        }
        filter.setStartFrom(start);
        filter.setMaxContents(count);
        filter.setDisjunction(disjunction);
        if (includeFriendlies != null) {
            filter.setFriendliesIncluded(includeFriendlies);
        } else {
            filter.setFriendliesIncluded(true);
        }
        if (creationDate != null) {
            filter.setCreationDateFilter(formatDate(creationDate));
        }
        if (lastModifiedDate != null) {
            filter.setLastModifiedDateFilter(formatDate(lastModifiedDate));
        }
        return filter;
    }

    public static ContentTypeId[] parseCollectionContentTypeId(List<String> strCollectionContentTypeId) {
        Collection<ContentTypeId> contentTypeIds = new ArrayList<ContentTypeId>();
        for (String strContentTypeId : strCollectionContentTypeId) {
            if (StringUtils.isBlank(strContentTypeId)) {
                continue;
            }
            final ContentTypeId id = parseContentTypeId(strContentTypeId);
            if (id != null) {
                contentTypeIds.add(id);
            }
        }
        ContentTypeId[] retContentTypeIds = contentTypeIds.toArray(new ContentTypeId[contentTypeIds.size()]);
        return retContentTypeIds;
    }

    private ContentStatus[] parseContentStatus(List<String> strCollectionContentStatus) {
        Collection<ContentStatus> contentStatuses = new ArrayList<ContentStatus>();
        for (String strContentStatus : strCollectionContentStatus) {
            if (StringUtils.isBlank(strContentStatus)) {
                continue;
            }
            if (logger.isDebugEnabled()) {
                logger.debug(":::CONTENT STATUS : " + strContentStatus);
            }
            MutableContentStatus contentStatus = SmartContentAPI.getInstance().getContentTypeLoader()
                    .createMutableContentStatus();
            contentStatus.setName(strContentStatus);
            contentStatuses.add(contentStatus);
        }
        ContentStatus[] retContentStatus = contentStatuses.toArray(new ContentStatus[contentStatuses.size()]);
        return retContentStatus;
    }

    public static WorkspaceId parseWorkspaceId(String strWorkspaceId) {
        if (StringUtils.isBlank(strWorkspaceId)) {
            return null;
        }
        String[] workspaceParam = splitStr(strWorkspaceId.replace(':', ','), ",");
        if (workspaceParam.length < 2) {
            return null;
        }
        WorkspaceId parsedWorkspaceId = SmartContentAPI.getInstance().getWorkspaceApi()
                .createWorkspaceId(workspaceParam[0], workspaceParam[1]);
        return parsedWorkspaceId;
    }

    private QueryParameter[] parseFieldQuery(List<String> strFieldQuery) {
        Collection<QueryParameter> parseQuery = new ArrayList<QueryParameter>();
        for (String strSingleFieldQuery : strFieldQuery) {
            if (StringUtils.isBlank(strSingleFieldQuery)) {
                continue;
            }
            if (logger.isDebugEnabled()) {
                logger.debug(":::FIELD QUERY : " + strSingleFieldQuery);
            }
            String[] values = splitStr(strSingleFieldQuery, ",");
            if (values.length < 2) {
                continue;
            }
            parseQuery.add(QueryParameterFactory.getStringLikePropertyParam(values[0], values[1]));
        }
        QueryParameter[] parsedQueryParameter = parseQuery.toArray(new QueryParameter[parseQuery.size()]);
        return parsedQueryParameter;
    }

    public static ContentTypeId parseContentTypeId(String strContentTypeId) {
        if (StringUtils.isBlank(strContentTypeId)) {
            return null;
        }
        String[] contentTypeIdStr = splitStr(strContentTypeId.replace(':', ','), ",");
        if (contentTypeIdStr.length < 4) {
            return null;
        }
        WorkspaceId contentWorkspaceId = SmartContentAPI.getInstance().getWorkspaceApi()
                .createWorkspaceId(contentTypeIdStr[0], contentTypeIdStr[1]);
        ContentTypeId parsedContentTypeId = SmartContentAPI.getInstance().getContentTypeLoader()
                .createContentTypeId(contentWorkspaceId, contentTypeIdStr[2], contentTypeIdStr[3]);
        return parsedContentTypeId;
    }

    private static String[] splitStr(String string, String splitChar) {
        String[] retStr;
        retStr = string.split(splitChar);
        return retStr;
    }

    public static QueryParameter<Date> formatDate(String strDate) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }
        QueryParameter<Date> queryParameter = null;
        if (strDate.startsWith(">=")) {
            String date = strDate.replaceAll(">=", "");
            queryParameter = QueryParameterFactory.getGreaterThanEqualToPropertyParam("greaterOrEqual",
                    new Date(Long.parseLong(date)));
        } else if (strDate.startsWith("<=")) {
            String date = strDate.replaceAll("<=", "");
            queryParameter = QueryParameterFactory.getLesserThanEqualToPropertyParam("lessOrEqual",
                    new Date(Long.parseLong(date)));
        } else if (strDate.startsWith("<")) {
            String date = strDate.replace("<", "");
            queryParameter = QueryParameterFactory.getLesserThanPropertyParam("lessThan",
                    new Date(Long.parseLong(date)));
        } else if (strDate.startsWith(">")) {
            String date = strDate.replace(">", "");
            queryParameter = QueryParameterFactory.getGreaterThanPropertyParam("greaterThan",
                    new Date(Long.parseLong(date)));
        } else if (strDate.contains(",")) {
            String[] date = strDate.split(",");
            queryParameter = QueryParameterFactory.getBetweenPropertyParam("between",
                    new Date(Long.parseLong(date[0])), new Date(Long.parseLong(date[1])));
        } else {
            queryParameter = null;
        }
        return queryParameter;
    }

    @Override
    protected String getAuthor() {
        return "Smart CMS";
    }

    public List<String> getContentTypeId() {
        return contentTypeId;
    }

    public void setContentTypeId(List<String> contentTypeId) {
        this.contentTypeId = contentTypeId;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public String getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(String creationDate) {
        this.creationDate = creationDate;
    }

    public boolean isDisJunction() {
        return disjunction;
    }

    public void setDisJunction(boolean disJunction) {
        this.disjunction = disJunction;
    }

    public List<String> getFieldQuery() {
        return fieldQuery;
    }

    public void setFieldQuery(List<String> fieldQuery) {
        this.fieldQuery = fieldQuery;
    }

    public String getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(String lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }

    public Boolean getIncludeFriendlies() {
        return includeFriendlies;
    }

    public void setIncludeFriendlies(Boolean includeFriendlies) {
        this.includeFriendlies = includeFriendlies;
    }

    public int getStart() {
        return start;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public List<String> getStatuses() {
        return statuses;
    }

    public void setStatuses(List<String> statuses) {
        this.statuses = statuses;
    }

    public String getWorkspaceId() {
        return workspaceId;
    }

    public void setWorkspaceId(String workspaceId) {
        this.workspaceId = workspaceId;
    }
}