blob: 40ba5855be7642ad5a33f25dbd539971d3e54748 [file] [log] [blame]
/*
d * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.sling.cms.reference.models;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.jcr.query.Query;
import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.cms.reference.SearchService;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Model for retrieving search results and pagination based on a search of the
* Sling CMS repository.
*/
@Model(adaptables = SlingHttpServletRequest.class)
public class Search {
private static final Logger log = LoggerFactory.getLogger(Search.class);
public static final String TERM_PARAMETER = "q";
private final int count;
private final int end;
private final int page;
private final Integer[] pages;
private final SlingHttpServletRequest request;
private final List<Resource> results;
private final int start;
private final ResourceResolver resolver;
@Inject
public Search(@Self SlingHttpServletRequest request, @ValueMapValue @Named("limit") int limit,
@OSGiService SearchService searchService, @ValueMapValue @Named("basePath") String basePath) {
this.request = request;
Set<String> distinct = new HashSet<>();
String term = Text.escapeIllegalXpathSearchChars(request.getParameter(TERM_PARAMETER)).replace("'", "''");
List<Resource> queryResults = new ArrayList<>();
resolver = searchService.getResourceResolver(request);
String query = "SELECT * FROM [sling:Page] AS p WHERE [jcr:content/sling:published]=true AND (p.[jcr:content/hideInSitemap] <> true OR [jcr:content/hideInSitemap] IS NULL) AND ISDESCENDANTNODE(p, '"
+ basePath + "') AND CONTAINS(p.*, '" + term + "')";
log.debug("Searching for pages with {} under {} with query: {}", term, basePath, query);
Iterator<Resource> res = resolver.findResources(query, Query.JCR_SQL2);
while (res.hasNext()) {
Resource result = res.next();
if (!distinct.contains(result.getPath())) {
queryResults.add(result);
distinct.add(result.getPath());
}
}
count = queryResults.size();
log.debug("Found {} results", count);
if (StringUtils.isNotBlank(request.getParameter("page")) && request.getParameter("page").matches("\\d+")) {
page = Integer.parseInt(request.getParameter("page"), 10) - 1;
log.debug("Using page {}", page);
} else {
page = 0;
log.debug("Page not specified or not valid");
}
if (page * limit >= count) {
start = count;
} else {
start = page * limit;
}
log.debug("Using start {}", start);
if ((page * limit) + limit >= count) {
end = count;
} else {
end = (page * limit) + limit;
}
log.debug("Using end {}", end);
results = queryResults.subList(start, end);
List<Integer> pgs = new ArrayList<>();
int max = ((int) Math.ceil((double) count / limit)) + 1;
for (int i = 1; i < max; i++) {
pgs.add(i);
}
pages = pgs.toArray(new Integer[pgs.size()]);
if (log.isDebugEnabled()) {
log.debug("Loaded pages {}", Arrays.toString(pages));
}
}
public int getCount() {
return count;
}
public int getCurrentPage() {
return page + 1;
}
public int getEnd() {
return end;
}
public Integer[] getPages() {
return pages;
}
public List<Resource> getResults() {
return results;
}
public int getStart() {
return start;
}
public String getTerm() {
return request.getParameter(TERM_PARAMETER);
}
public boolean isFirst() {
return page == 0;
}
public boolean isLast() {
if (pages.length > 0) {
return page + 1 == pages[pages.length - 1];
}
return true;
}
}