fix #128, remove mobile jsp and minor fixes.
This commit is contained in:
parent
b93e053482
commit
ef4e3b4fe7
22 changed files with 218 additions and 143 deletions
|
@ -205,6 +205,8 @@ public class IndexAction {
|
|||
|
||||
public String username;
|
||||
|
||||
public String appendHighlightQueries;
|
||||
|
||||
public String getPagingQuery() {
|
||||
if (pagingQuery == null) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
|
@ -317,7 +319,7 @@ public class IndexAction {
|
|||
return "error.jsp";
|
||||
}
|
||||
|
||||
final String content = viewHelper.createCacheContent(doc);
|
||||
final String content = viewHelper.createCacheContent(doc, indexForm.hq);
|
||||
if (content == null) {
|
||||
errorMessage = MessageResourcesUtil.getMessage(RequestUtil
|
||||
.getRequest().getLocale(), "errors.docid_not_found",
|
||||
|
@ -1002,6 +1004,16 @@ public class IndexAction {
|
|||
searchLogHelper.addSearchLog(searchLog);
|
||||
}
|
||||
|
||||
final String[] highlightQueries = (String[]) request
|
||||
.getAttribute(Constants.HIGHLIGHT_QUERIES);
|
||||
if (highlightQueries != null) {
|
||||
final StringBuilder buf = new StringBuilder(100);
|
||||
for (final String q : highlightQueries) {
|
||||
buf.append("&hq=").append(q);
|
||||
}
|
||||
appendHighlightQueries = buf.toString();
|
||||
}
|
||||
|
||||
Beans.copy(documentItems, this)
|
||||
.includes("pageSize", "currentPageNumber", "allRecordCount",
|
||||
"allPageCount", "existNextPage", "existPrevPage",
|
||||
|
@ -1182,6 +1194,7 @@ public class IndexAction {
|
|||
username = loginInfo.getUsername();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void buildInitParams() {
|
||||
|
|
|
@ -65,6 +65,8 @@ public class IndexForm implements Serializable {
|
|||
@Maxbytelength(maxbytelength = 100)
|
||||
public String docId;
|
||||
|
||||
public String[] hq;
|
||||
|
||||
// xml/json
|
||||
|
||||
@Maxbytelength(maxbytelength = 20)
|
||||
|
|
|
@ -30,14 +30,19 @@ import jp.sf.fess.db.exentity.PathMapping;
|
|||
|
||||
import org.seasar.framework.container.SingletonS2Container;
|
||||
import org.seasar.framework.container.annotation.tiger.InitMethod;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PathMappingHelper implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(PathMappingHelper.class);
|
||||
|
||||
private final Map<String, List<PathMapping>> pathMappingMap = new HashMap<String, List<PathMapping>>();
|
||||
|
||||
private List<PathMapping> cachedPathMappingList = null;
|
||||
private volatile List<PathMapping> cachedPathMappingList = null;
|
||||
|
||||
@InitMethod
|
||||
public void init() {
|
||||
|
@ -45,14 +50,19 @@ public class PathMappingHelper implements Serializable {
|
|||
ptList.add(CDef.ProcessType.Displaying);
|
||||
ptList.add(CDef.ProcessType.Both);
|
||||
|
||||
final PathMappingCB cb = new PathMappingCB();
|
||||
try {
|
||||
final PathMappingBhv pathMappingBhv = SingletonS2Container
|
||||
.getComponent(PathMappingBhv.class);
|
||||
final PathMappingCB cb = new PathMappingCB();
|
||||
|
||||
cb.query().setDeletedBy_IsNull();
|
||||
cb.query().addOrderBy_SortOrder_Asc();
|
||||
cb.query().setProcessType_InScope_AsProcessType(ptList);
|
||||
cb.query().setDeletedBy_IsNull();
|
||||
cb.query().addOrderBy_SortOrder_Asc();
|
||||
cb.query().setProcessType_InScope_AsProcessType(ptList);
|
||||
|
||||
cachedPathMappingList = SingletonS2Container.getComponent(
|
||||
PathMappingBhv.class).selectList(cb);
|
||||
cachedPathMappingList = pathMappingBhv.selectList(cb);
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load path mappings.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPathMappingList(final String sessionId,
|
||||
|
@ -86,6 +96,13 @@ public class PathMappingHelper implements Serializable {
|
|||
}
|
||||
|
||||
public String replaceUrl(final String url) {
|
||||
if (cachedPathMappingList == null) {
|
||||
synchronized (this) {
|
||||
if (cachedPathMappingList == null) {
|
||||
init();
|
||||
}
|
||||
}
|
||||
}
|
||||
return replaceUrl(cachedPathMappingList, url);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,8 @@ public class QueryHelper implements Serializable {
|
|||
|
||||
protected Set<String> apiResponseFieldSet;
|
||||
|
||||
protected Set<String> highlightFieldSet = new HashSet<>();
|
||||
|
||||
protected String[] responseFields = new String[] { "id", "docId", "score",
|
||||
"boost", "contentLength", "host", "site", "lastModified",
|
||||
"mimetype", "filetype_s", "created", TITLE_FIELD, "digest", "url",
|
||||
|
@ -376,7 +378,7 @@ public class QueryHelper implements Serializable {
|
|||
}
|
||||
nonPrefix = true;
|
||||
operator = _AND_;
|
||||
if (!LABEL_FIELD.equals(field)) {
|
||||
if (highlightFieldSet.contains(field)) {
|
||||
highLightQueryList.add(targetWord);
|
||||
}
|
||||
if (fieldLogMap != null) {
|
||||
|
@ -1187,6 +1189,10 @@ public class QueryHelper implements Serializable {
|
|||
this.supportedSortFields = supportedSortFields;
|
||||
}
|
||||
|
||||
public void addHighlightField(final String field) {
|
||||
highlightFieldSet.add(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the highlightSnippetSize
|
||||
*/
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -374,7 +375,8 @@ public class ViewHelper implements Serializable {
|
|||
return file.isFile();
|
||||
}
|
||||
|
||||
public String createCacheContent(final Map<String, Object> doc) {
|
||||
public String createCacheContent(final Map<String, Object> doc,
|
||||
final String[] queries) {
|
||||
|
||||
final FileTemplateLoader loader = new FileTemplateLoader(new File(
|
||||
ResourceUtil.getViewTemplatePath(StringUtil.EMPTY)));
|
||||
|
@ -401,6 +403,20 @@ public class ViewHelper implements Serializable {
|
|||
doc.put("cacheMsg", MessageResourcesUtil.getMessage(locale,
|
||||
"labels.search_cache_msg", url, created));
|
||||
|
||||
doc.put("queries", queries);
|
||||
|
||||
final String cache = (String) doc.get("cache");
|
||||
if (cache != null) {
|
||||
if (queries != null && queries.length > 0) {
|
||||
doc.put("hlCache", replaceHighlightQueries(cache, queries));
|
||||
} else {
|
||||
doc.put("hlCache", cache);
|
||||
}
|
||||
} else {
|
||||
doc.put("cache", StringUtil.EMPTY);
|
||||
doc.put("hlCache", StringUtil.EMPTY);
|
||||
}
|
||||
|
||||
try {
|
||||
final Template template = handlebars.compile(cacheTemplateName);
|
||||
final Context hbsContext = Context.newContext(doc);
|
||||
|
@ -412,6 +428,42 @@ public class ViewHelper implements Serializable {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected String replaceHighlightQueries(final String cache,
|
||||
final String[] queries) {
|
||||
final StringBuffer buf = new StringBuffer(cache.length() + 100);
|
||||
final StringBuffer segBuf = new StringBuffer(1000);
|
||||
final Pattern p = Pattern.compile("<[^>]+>");
|
||||
final Matcher m = p.matcher(cache);
|
||||
final String[] regexQueries = new String[queries.length];
|
||||
final String[] hlQueries = new String[queries.length];
|
||||
for (int i = 0; i < queries.length; i++) {
|
||||
regexQueries[i] = Pattern.quote(queries[i]);
|
||||
hlQueries[i] = highlightTagPre + queries[i] + highlightTagPost;
|
||||
}
|
||||
while (m.find()) {
|
||||
segBuf.setLength(0);
|
||||
m.appendReplacement(segBuf, StringUtil.EMPTY);
|
||||
String segment = segBuf.toString();
|
||||
for (int i = 0; i < queries.length; i++) {
|
||||
segment = Pattern
|
||||
.compile(regexQueries[i], Pattern.CASE_INSENSITIVE)
|
||||
.matcher(segment).replaceAll(hlQueries[i]);
|
||||
}
|
||||
buf.append(segment);
|
||||
buf.append(m.group(0));
|
||||
}
|
||||
segBuf.setLength(0);
|
||||
m.appendTail(segBuf);
|
||||
String segment = segBuf.toString();
|
||||
for (int i = 0; i < queries.length; i++) {
|
||||
segment = Pattern
|
||||
.compile(regexQueries[i], Pattern.CASE_INSENSITIVE)
|
||||
.matcher(segment).replaceAll(hlQueries[i]);
|
||||
}
|
||||
buf.append(segment);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public boolean isUseSession() {
|
||||
return useSession;
|
||||
}
|
||||
|
|
|
@ -118,7 +118,9 @@ public abstract class AbstractFessXpathTransformer extends XpathTransformer {
|
|||
|
||||
protected void putResultDataBody(final Map<String, Object> dataMap,
|
||||
final String key, final Object value) {
|
||||
if (dataMap.containsKey(key)) {
|
||||
if ("url".equals(key)) {
|
||||
dataMap.put(key, value);
|
||||
} else if (dataMap.containsKey(key)) {
|
||||
if (appendResultData) {
|
||||
final Object oldValue = dataMap.get(key);
|
||||
if (key.endsWith("_m")) {
|
||||
|
|
|
@ -68,6 +68,12 @@
|
|||
"contentLength", "host", "site", "lastModified", "mimetype", "filetype_s",
|
||||
"created", "title", "digest", "url"}</arg>
|
||||
</initMethod>
|
||||
<initMethod name="addHighlightField">
|
||||
<arg>"title"</arg>
|
||||
</initMethod>
|
||||
<initMethod name="addHighlightField">
|
||||
<arg>"content"</arg>
|
||||
</initMethod>
|
||||
<!--
|
||||
<property name="additionalGeoQuery">"location_i_i:1"</property>
|
||||
<property name="responseFields">new String[]{ "id", "docId", "score",
|
||||
|
|
|
@ -72,10 +72,6 @@ new String[] {
|
|||
"-XX:G1ReservePercent=10",
|
||||
-->
|
||||
</property>
|
||||
<!--
|
||||
"-XX:+OptimizeStringConcat",
|
||||
"-XX:+UseCompressedStrings",
|
||||
-->
|
||||
<!-- remote debug
|
||||
"-Xdebug",
|
||||
"-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=127.0.0.1:8000",
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
<div style="border:1px solid #999;margin:5px -1px;padding:0;">
|
||||
<div style="color:#000;background:#ddd;border:1px solid #666;margin:10px 15px;padding:5px;text-align:left;">{{cacheMsg}}</div>
|
||||
</div>
|
||||
{{{cache}}}
|
||||
{{{hlCache}}}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
<%@page pageEncoding="UTF-8" %>
|
||||
<html>
|
||||
<head>
|
||||
<jsp:include page="indexHtmlHead.jsp"/>
|
||||
</head>
|
||||
<body>
|
||||
<jsp:include page="indexMain.jsp"/>
|
||||
</body>
|
||||
</html>
|
|
@ -1,4 +0,0 @@
|
|||
<%@page pageEncoding="UTF-8" %>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=<m:charset/>" />
|
||||
<meta content="no-cache" http-equiv="Cache-Control"/>
|
||||
<title><bean:message key="labels.mobile_search_title"/></title>
|
|
@ -1,14 +0,0 @@
|
|||
<%@page pageEncoding="UTF-8" %>
|
||||
<div>
|
||||
<div style="text-align: center;">
|
||||
<m:img src="logo-top.gif" magniWidth="0.8" style="vertical-align: middle;" />
|
||||
<br/>
|
||||
<s:form>
|
||||
<div>
|
||||
<html:text property="query" title="Search" size="20" maxlength="1000" />
|
||||
<br/>
|
||||
<input type="submit" value="<bean:message key="labels.top.search"/>" name="search" />
|
||||
</div>
|
||||
</s:form>
|
||||
</div>
|
||||
</div>
|
|
@ -1,18 +0,0 @@
|
|||
<%@page pageEncoding="UTF-8" %>
|
||||
<html>
|
||||
<head>
|
||||
<jsp:include page="searchHtmlHead.jsp"/>
|
||||
</head>
|
||||
<body>
|
||||
<jsp:include page="searchHeader.jsp"/>
|
||||
<c:choose>
|
||||
<c:when test="${f:h(allRecordCount) != 0}">
|
||||
<jsp:include page="searchResults.jsp"/>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<jsp:include page="searchNoResult.jsp"/>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
<jsp:include page="searchFooter.jsp"/>
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +0,0 @@
|
|||
<%@page pageEncoding="UTF-8" %>
|
||||
<hr style="border-style: solid; border-color: #ffffff;"/>
|
||||
<div style="font-size: x-small; text-align: center;">
|
||||
<bean:message key="labels.footer.copyright"/>
|
||||
</div>
|
|
@ -1,13 +0,0 @@
|
|||
<%@page pageEncoding="UTF-8" %>
|
||||
<div id="header">
|
||||
<div>
|
||||
<s:form>
|
||||
<div>
|
||||
<m:img src="logo-top.gif" magniWidth="0.3" />
|
||||
<br/>
|
||||
<html:text property="query" title="Search" size="16" maxlength="1000" />
|
||||
<input type="submit" value="<bean:message key="labels.search"/>" name="search"/>
|
||||
</div>
|
||||
</s:form>
|
||||
</div>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<%@page pageEncoding="UTF-8" %>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=<m:charset/>" />
|
||||
<meta content="no-cache" http-equiv="Cache-Control"/>
|
||||
<title>${f:h(query)} - <bean:message key="labels.search_title"/></title>
|
|
@ -1,4 +0,0 @@
|
|||
<%@page pageEncoding="UTF-8" %>
|
||||
<div id="result">
|
||||
<bean:message key="labels.did_not_match" arg0="${f:h(query)}"/>
|
||||
</div>
|
|
@ -1,55 +0,0 @@
|
|||
<%@page pageEncoding="UTF-8" %>
|
||||
<div id="result">
|
||||
<div>
|
||||
<c:forEach var="doc" varStatus="s" items="${documentItems}">
|
||||
<div>
|
||||
<a href="${doc.urlLink}"><span>${f:h(doc.contentTitle)}</span></a>
|
||||
<span id="snip">
|
||||
<br/>
|
||||
<span style="color: #666666;">
|
||||
${doc.contentDescription}
|
||||
</span>
|
||||
</span>
|
||||
<span style="color: #008000;">
|
||||
<br/>
|
||||
${f:h(doc.site)}
|
||||
</span>
|
||||
<br/>
|
||||
</div>
|
||||
<br/>
|
||||
</c:forEach>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="subfooter" style="text-align: center;">
|
||||
<p>
|
||||
<c:if test="${existPrevPage}">
|
||||
<span>
|
||||
<s:link href="prev?query=${f:u(query)}&pn=${f:u(currentPageNumber)}&num=${f:u(pageSize)}">
|
||||
<bean:message key="labels.prev_page"/>
|
||||
</s:link>
|
||||
</span>
|
||||
</c:if>
|
||||
<c:forEach var="pageNumber" varStatus="s" items="${pageNumberList}">
|
||||
<c:if test="${pageNumber == currentPageNumber}">
|
||||
<span>
|
||||
${pageNumber}
|
||||
</span>
|
||||
</c:if>
|
||||
<c:if test="${pageNumber != currentPageNumber}">
|
||||
<span>
|
||||
<s:link href="move?query=${f:u(query)}&pn=${f:u(pageNumber)}&num=${f:u(pageSize)}">
|
||||
${f:h(pageNumber)}
|
||||
</s:link>
|
||||
</span>
|
||||
</c:if>
|
||||
</c:forEach>
|
||||
<c:if test="${existNextPage}">
|
||||
<span>
|
||||
<s:link href="next?query=${f:u(query)}&pn=${f:u(currentPageNumber)}&num=${f:u(pageSize)}">
|
||||
<bean:message key="labels.next_page"/>
|
||||
</s:link>
|
||||
</span>
|
||||
</c:if>
|
||||
</p>
|
||||
</div>
|
|
@ -36,7 +36,7 @@
|
|||
<div class="site ellipsis">
|
||||
<cite>${f:h(doc.site)}</cite>
|
||||
<c:if test="${doc.hasCache_s_s=='true'}">
|
||||
<a href="cache?docId=${doc.docId}" class="cache"><bean:message
|
||||
<a href="cache?docId=${doc.docId}${appendHighlightQueries}" class="cache"><bean:message
|
||||
key="labels.search_result_cache" /></a>
|
||||
</c:if>
|
||||
</div>
|
||||
|
|
|
@ -57,6 +57,7 @@ h3 {
|
|||
|
||||
#result .body a.cache {
|
||||
color: #093;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#result .favorited {
|
||||
|
|
88
src/test/java/jp/sf/fess/helper/ViewHelperTest.java
Normal file
88
src/test/java/jp/sf/fess/helper/ViewHelperTest.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 2009-2014 the CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 jp.sf.fess.helper;
|
||||
|
||||
import org.seasar.extension.unit.S2TestCase;
|
||||
|
||||
public class ViewHelperTest extends S2TestCase {
|
||||
public ViewHelper viewHelper;
|
||||
|
||||
@Override
|
||||
protected String getRootDicon() throws Throwable {
|
||||
return "jp/sf/fess/helper/view.dicon";
|
||||
}
|
||||
|
||||
public void test_replaceHighlightQueries() {
|
||||
String text;
|
||||
String[] queries;
|
||||
|
||||
text = "<a>123<b>456<c>";
|
||||
queries = new String[] { "123", "456" };
|
||||
assertEquals("<a><em>123</em><b><em>456</em><c>",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "<123><456>";
|
||||
queries = new String[] { "123", "456" };
|
||||
assertEquals("<123><456>",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "123<aaa 123>456<bbb 456>123";
|
||||
queries = new String[] { "123", "456" };
|
||||
assertEquals("<em>123</em><aaa 123><em>456</em><bbb 456><em>123</em>",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "abc";
|
||||
queries = new String[] { "123" };
|
||||
assertEquals("abc", viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "123";
|
||||
queries = new String[] { "123" };
|
||||
assertEquals("<em>123</em>",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "abc123efg";
|
||||
queries = new String[] { "123" };
|
||||
assertEquals("abc<em>123</em>efg",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "123";
|
||||
queries = new String[] { "123", "456" };
|
||||
assertEquals("<em>123</em>",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "123456";
|
||||
queries = new String[] { "123", "456" };
|
||||
assertEquals("<em>123</em><em>456</em>",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "a123b456c";
|
||||
queries = new String[] { "123", "456" };
|
||||
assertEquals("a<em>123</em>b<em>456</em>c",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "abc";
|
||||
queries = new String[] { "abc" };
|
||||
assertEquals("<em>abc</em>",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
|
||||
text = "1ABC2";
|
||||
queries = new String[] { "abc" };
|
||||
assertEquals("1<em>abc</em>2",
|
||||
viewHelper.replaceHighlightQueries(text, queries));
|
||||
}
|
||||
|
||||
}
|
18
src/test/resources/jp/sf/fess/helper/view.dicon
Normal file
18
src/test/resources/jp/sf/fess/helper/view.dicon
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
|
||||
"http://www.seasar.org/dtd/components24.dtd">
|
||||
<components>
|
||||
<component name="viewHelper" class="jp.sf.fess.helper.ViewHelper">
|
||||
</component>
|
||||
<component name="pathMappingHelper" class="jp.sf.fess.helper.PathMappingHelper">
|
||||
</component>
|
||||
<component name="userAgentHelper" class="jp.sf.fess.helper.UserAgentHelper">
|
||||
</component>
|
||||
<component name="crawlerProperties" class="org.codelibs.core.util.DynamicProperties">
|
||||
<arg>
|
||||
@org.seasar.framework.util.ResourceUtil@getBuildDir(@jp.sf.fess.FessClass@class).getCanonicalPath()
|
||||
+ "/conf/crawler.properties"
|
||||
</arg>
|
||||
</component>
|
||||
|
||||
</components>
|
Loading…
Add table
Reference in a new issue