/** * Copyright 2008 - 2009 Pro-Netics S.P.A. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package it.pronetics.madstore.server.jaxrs.atom.search.impl; import it.pronetics.madstore.common.AtomConstants; import it.pronetics.madstore.repository.util.PagingList; import it.pronetics.madstore.server.HttpConstants; import it.pronetics.madstore.server.jaxrs.atom.impl.AbstractResourceHandler; import it.pronetics.madstore.server.jaxrs.atom.resolver.ResourceName; import it.pronetics.madstore.server.jaxrs.atom.search.CollectionSearchResourceHandler; import it.pronetics.madstore.server.jaxrs.atom.resolver.ResourceUriFor; import java.net.URL; import java.util.Arrays; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import org.apache.abdera.Abdera; import org.apache.abdera.ext.opensearch.OpenSearchConstants; import org.apache.abdera.ext.opensearch.model.IntegerElement; import org.apache.abdera.factory.Factory; import org.apache.abdera.model.Entry; import org.apache.abdera.model.Feed; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * {@link it.pronetics.madstore.server.jaxrs.atom.search.CollectionSearchResourceHandler} implementation based on * JBoss Resteasy and Abdera atom model. * * @author Sergio Bossa */ @Path("/") public class DefaultCollectionSearchResourceHandler extends AbstractResourceHandler implements CollectionSearchResourceHandler<Feed> { private static final Logger LOG = LoggerFactory.getLogger(DefaultCollectionSearchResourceHandler.class); private String collectionKey; private int maxNumberOfEntries; private int pageNumberOfEntries; private String searchTitle; private String searchTerms; @Transactional(propagation = Propagation.REQUIRED, readOnly = true) @ResourceUriFor(resource = ResourceName.COLLECTION_SEARCH) @GET @Path("/search/{collectionKey}") @Produces(AtomConstants.ATOM_MEDIA_TYPE) public Response getCollectionSearchResource() { try { String[] termsArray = searchTerms.split(" "); int max = maxNumberOfEntries; int offset = (pageNumberOfEntries - 1) * max; // Factory abderaFactory = Abdera.getInstance().getFactory(); Feed feed = abderaFactory.newFeed(); PagingList<Entry> entries = findEntriesFromRepository(collectionKey, Arrays.asList(termsArray), offset, max); configureFeed(feed, entries); Response response = buildOkResponse(feed); return response; } catch (Exception ex) { LOG.error(ex.getMessage(), ex); throw new WebApplicationException(Response.serverError().build()); } } @PathParam("collectionKey") public void setCollectionKey(String collectionKey) { this.collectionKey = collectionKey; } @QueryParam(HttpConstants.MAX_PARAMETER) @DefaultValue("10") public void setMaxNumberOfEntries(int maxNumberOfEntries) { this.maxNumberOfEntries = maxNumberOfEntries; } @QueryParam(HttpConstants.PAGE_PARAMETER) @DefaultValue("1") public void setPageNumberOfEntries(int pageNumberOfEntries) { this.pageNumberOfEntries = pageNumberOfEntries; } @QueryParam(HttpConstants.TITLE_PARAMETER) @DefaultValue("") public void setSearchTitle(String searchTitle) { this.searchTitle = searchTitle; } @QueryParam(HttpConstants.TERMS_PARAMETER) @DefaultValue("") public void setSearchTerms(String searchTerms) { this.searchTerms = searchTerms; } private void configureFeed(Feed feed, PagingList<Entry> entries) throws Exception { URL baseUrl = resourceResolver.resolveResourceUriFor( ResourceName.COLLECTION_SEARCH, uriInfo.getBaseUri().toString(), collectionKey); URL nextUrl = UriBuilder.fromUri( baseUrl.toURI()).queryParam(HttpConstants.TITLE_PARAMETER, searchTitle).queryParam(HttpConstants.TERMS_PARAMETER, searchTerms).queryParam(HttpConstants.PAGE_PARAMETER, new Integer(pageNumberOfEntries + 1)).queryParam(HttpConstants.MAX_PARAMETER, maxNumberOfEntries).build().toURL(); URL prevUrl = UriBuilder.fromUri( baseUrl.toURI()).queryParam(HttpConstants.TITLE_PARAMETER, searchTitle).queryParam(HttpConstants.TERMS_PARAMETER, searchTerms).queryParam(HttpConstants.PAGE_PARAMETER, new Integer(pageNumberOfEntries - 1)).queryParam(HttpConstants.MAX_PARAMETER, maxNumberOfEntries).build().toURL(); String id = resourceResolver.resolveResourceIdFor( uriInfo.getBaseUri().toString(), ResourceName.COLLECTION_SEARCH, collectionKey); feed.setId(id); feed.setTitle(searchTitle); feed.addAuthor(Abdera.getInstance().getFactory().newAuthor().getText()); for (Entry entry : entries) { feed.addEntry(entry); } if (entries.size() > 0) { int currentLastResult = ((pageNumberOfEntries - 1) * maxNumberOfEntries) + entries.size(); if (currentLastResult < entries.getTotal()) { feed.addLink(nextUrl.toString(), "next"); } if (pageNumberOfEntries > 1) { feed.addLink(prevUrl.toString(), "previous"); } IntegerElement totalResults = feed.addExtension(OpenSearchConstants.TOTAL_RESULTS); totalResults.setValue(entries.getTotal()); IntegerElement itemsPerPage = feed.addExtension(OpenSearchConstants.ITEMS_PER_PAGE); itemsPerPage.setValue(entries.getMax()); IntegerElement startIndex = feed.addExtension(OpenSearchConstants.START_INDEX); startIndex.setValue(entries.getOffset() + 1); } } }