/* * * This is a simple Content Management System (CMS) * Copyright (C) 2011 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.type; import com.smartitengineering.cms.api.factory.SmartContentAPI; import com.smartitengineering.cms.api.type.ContentType; import com.smartitengineering.cms.api.type.Filter; import com.smartitengineering.cms.ws.resources.content.searcher.ContentSearcherResource; 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 java.net.URI; 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 imyousuf */ public class ContentTypeSearcherResource extends AbstractResource { private final transient Logger logger = LoggerFactory.getLogger(getClass()); private List<String> contentTypeId; private String parentId; private String workspaceId; private String searchTerms; private String creationDate; private String lastModifiedDate; private int start; private int count; private boolean disjunction; private Boolean includeFriendlies = null; private final static String WORKSPACE_ID = "workspaceId", TYPE_ID = "instanceOf", CREATION_DATE = "creationDate", LAST_MODIFIED_DATE = "lastModifiedDate", START = "start", COUNT = "count", DISJUNCTION = "disjunction", SEARCH_TERMS = "q", INCLUDE_FRIENDLIES = "includeFriendlies", CHILD_OF = "parentId"; 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 String getLastModifiedDate() { return lastModifiedDate; } public void setLastModifiedDate(String lastModifiedDate) { this.lastModifiedDate = lastModifiedDate; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } public String getSearchTerms() { return searchTerms; } public void setSearchTerms(String searchTerms) { this.searchTerms = searchTerms; } public int getStart() { return start; } public void setStart(int start) { this.start = start; } public String getWorkspaceId() { return workspaceId; } public void setWorkspaceId(String workspaceId) { this.workspaceId = workspaceId; } public Boolean getIncludeFriendlies() { return includeFriendlies; } public void setIncludeFriendlies(Boolean includeFriendlies) { this.includeFriendlies = includeFriendlies; } protected void initParams(List<String> contentTypeId, String searchTerms, String workspaceId, String creationDate, String lastModifiedDate, int start, int count, boolean disJunction, boolean includeFriendlies, String parentId) { if (contentTypeId != null && !contentTypeId.isEmpty()) { this.contentTypeId = contentTypeId; } else if (this.contentTypeId == null) { this.contentTypeId = Collections.emptyList(); } if (StringUtils.isNotBlank(parentId)) { this.parentId = parentId; } if (StringUtils.isNotBlank(workspaceId)) { this.workspaceId = workspaceId; } this.creationDate = creationDate; this.lastModifiedDate = lastModifiedDate; this.start = start; this.count = count; this.disjunction = disJunction; this.searchTerms = searchTerms; if (this.includeFriendlies == null) { 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().getContentTypeLoader().createFilter(); if (StringUtils.isNotBlank(searchTerms)) { filter.setSearchTerms(searchTerms); } if (contentTypeId != null && !contentTypeId.isEmpty()) { filter.addInstanceOfContentTypeToFilter(ContentSearcherResource.parseCollectionContentTypeId(contentTypeId)); } if (StringUtils.isNotBlank(parentId)) { filter.setChildOf(ContentSearcherResource.parseContentTypeId(parentId)); } if (StringUtils.isNotBlank(workspaceId)) { filter.setWorkspaceId(ContentSearcherResource.parseWorkspaceId(workspaceId)); } filter.setStartFrom(start); filter.setMaxContents(count); filter.setDisjunction(disjunction); if (includeFriendlies != null) { filter.setFriendliesIncluded(includeFriendlies); } else { logger.debug(String.valueOf(":::VAULE OF Inclue Friendlies is true")); filter.setFriendliesIncluded(true); } if (creationDate != null) { filter.setCreationDateFilter(ContentSearcherResource.formatDate(creationDate)); } if (lastModifiedDate != null) { filter.setLastModifiedDateFilter(ContentSearcherResource.formatDate(lastModifiedDate)); } if (logger.isDebugEnabled()) { logger.debug(":::Workspace ID : " + workspaceId + " " + filter.getWorkspaceId()); logger.debug(":::Parent ID : " + parentId + " " + filter.getChildOf()); logger.debug(":::START FROM : " + String.valueOf(start)); logger.debug(":::NUMBER OF ITEM : " + String.valueOf(count)); logger.debug(":::VAULE OF DISJUNCTION : " + disjunction); logger.debug(":::CREATION DATE : " + creationDate + " " + filter.getCreationDateFilter()); logger.debug(":::LAST MODIFIED DATE : " + lastModifiedDate + " " + filter.getLastModifiedDateFilter()); logger.debug(":::VAULE OF Inclue Friendlies : " + includeFriendlies); logger.debug("Instance of " + contentTypeId + " " + filter.getInstanceOfContentTypeFilters()); } return filter; } 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(CHILD_OF).append("="). append(StringUtils.isBlank(parentId) ? "{parentId?}" : parentId); 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?}"); } 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(parentId)) { templateBuilder.append(CHILD_OF).append("=").append(parentId).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('&'); } } } return templateBuilder; } @Override protected String getAuthor() { return "Smart CMS"; } @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); descBuilder.urls(xmlBuilder.build()); ResponseBuilder builder = Response.ok(descBuilder.build()); return builder.build(); } @GET @Produces(MediaType.APPLICATION_ATOM_XML) public Response getResultFeed(@QueryParam(TYPE_ID) List<String> contentTypeId, @QueryParam(SEARCH_TERMS) String searchTerms, @QueryParam(WORKSPACE_ID) String workspaceId, @QueryParam(CHILD_OF) String parentId, @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, workspaceId, creationDate, lastModifiedDate, start, count, disJunction, includeFriendlies, parentId); ResponseBuilder responseBuilder; Filter filter = getFilter(); final com.smartitengineering.cms.api.common.SearchResult result = SmartContentAPI.getInstance().getContentTypeLoader(). search(filter); final Collection<ContentType> 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 (ContentType type : searchContent) { final URI contentUri = ContentTypeResource.getContentTypeRelativeURI(getUriInfo(), type.getContentTypeID()); Entry entry = getEntry(type.getContentTypeID().toString(), new StringBuilder("ContentType ").append(type. getContentTypeID().toString()).toString(), type.getLastModifiedDate(), getLink(contentUri, Link.REL_ALTERNATE, MediaType.APPLICATION_ATOM_XML), getLink( contentUri, Link.REL_ALTERNATE, MediaType.APPLICATION_XML)); feed.addEntry(entry); } } responseBuilder = Response.ok(feed); return responseBuilder.build(); } }