commit | author | age
|
4c13bf
|
1 |
/*
|
JM |
2 |
* Copyright 2012 gitblit.com.
|
|
3 |
*
|
|
4 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5 |
* you may not use this file except in compliance with the License.
|
|
6 |
* You may obtain a copy of the License at
|
|
7 |
*
|
|
8 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9 |
*
|
|
10 |
* Unless required by applicable law or agreed to in writing, software
|
|
11 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13 |
* See the License for the specific language governing permissions and
|
|
14 |
* limitations under the License.
|
|
15 |
*/
|
|
16 |
package com.gitblit.wicket.pages;
|
|
17 |
|
d04009
|
18 |
import java.text.MessageFormat;
|
4c13bf
|
19 |
import java.util.ArrayList;
|
548b29
|
20 |
import java.util.LinkedHashSet;
|
4c13bf
|
21 |
import java.util.List;
|
548b29
|
22 |
import java.util.Set;
|
4c13bf
|
23 |
|
31a897
|
24 |
import org.apache.wicket.Component;
|
4c13bf
|
25 |
import org.apache.wicket.PageParameters;
|
JM |
26 |
import org.apache.wicket.markup.html.basic.Label;
|
548b29
|
27 |
import org.apache.wicket.markup.html.form.CheckBox;
|
3d0494
|
28 |
import org.apache.wicket.markup.html.form.ListMultipleChoice;
|
4c13bf
|
29 |
import org.apache.wicket.markup.html.form.TextField;
|
31a897
|
30 |
import org.apache.wicket.markup.html.panel.Fragment;
|
4c13bf
|
31 |
import org.apache.wicket.markup.repeater.Item;
|
JM |
32 |
import org.apache.wicket.markup.repeater.data.DataView;
|
|
33 |
import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
|
34 |
import org.apache.wicket.model.Model;
|
3f0677
|
35 |
import org.eclipse.jgit.lib.Constants;
|
4c13bf
|
36 |
|
3d0494
|
37 |
import com.gitblit.Constants.SearchType;
|
d04009
|
38 |
import com.gitblit.Keys;
|
672296
|
39 |
import com.gitblit.models.RepositoryModel;
|
4c13bf
|
40 |
import com.gitblit.models.SearchResult;
|
672296
|
41 |
import com.gitblit.models.UserModel;
|
7d97c6
|
42 |
import com.gitblit.utils.ArrayUtils;
|
3f0677
|
43 |
import com.gitblit.utils.StringUtils;
|
672296
|
44 |
import com.gitblit.wicket.GitBlitWebSession;
|
ed295f
|
45 |
import com.gitblit.wicket.SessionlessForm;
|
672296
|
46 |
import com.gitblit.wicket.StringChoiceRenderer;
|
4c13bf
|
47 |
import com.gitblit.wicket.WicketUtils;
|
JM |
48 |
import com.gitblit.wicket.panels.LinkPanel;
|
d04009
|
49 |
import com.gitblit.wicket.panels.PagerPanel;
|
4c13bf
|
50 |
|
4e1930
|
51 |
public class LuceneSearchPage extends RootPage {
|
4c13bf
|
52 |
|
4e1930
|
53 |
public LuceneSearchPage() {
|
4c13bf
|
54 |
super();
|
JM |
55 |
setup(null);
|
|
56 |
}
|
|
57 |
|
4e1930
|
58 |
public LuceneSearchPage(PageParameters params) {
|
4c13bf
|
59 |
super(params);
|
JM |
60 |
setup(params);
|
|
61 |
}
|
|
62 |
|
|
63 |
private void setup(PageParameters params) {
|
|
64 |
setupPage("", "");
|
699e71
|
65 |
|
7d97c6
|
66 |
// default values
|
699e71
|
67 |
ArrayList<String> repositories = new ArrayList<String>();
|
7d97c6
|
68 |
String query = "";
|
d04009
|
69 |
int page = 1;
|
99d0d4
|
70 |
int pageSize = app().settings().getInteger(Keys.web.itemsPerPage, 50);
|
3d0494
|
71 |
|
b4d958
|
72 |
// display user-accessible selections
|
VF |
73 |
UserModel user = GitBlitWebSession.get().getUser();
|
|
74 |
List<String> availableRepositories = new ArrayList<String>();
|
|
75 |
for (RepositoryModel model : app().repositories().getRepositoryModels(user)) {
|
|
76 |
if (model.hasCommits && !ArrayUtils.isEmpty(model.indexedBranches)) {
|
|
77 |
availableRepositories.add(model.name);
|
|
78 |
}
|
|
79 |
}
|
|
80 |
|
3d0494
|
81 |
if (params != null) {
|
7d97c6
|
82 |
String repository = WicketUtils.getRepositoryName(params);
|
JM |
83 |
if (!StringUtils.isEmpty(repository)) {
|
|
84 |
repositories.add(repository);
|
|
85 |
}
|
d04009
|
86 |
|
31a897
|
87 |
page = WicketUtils.getPage(params);
|
699e71
|
88 |
|
7d97c6
|
89 |
if (params.containsKey("repositories")) {
|
JM |
90 |
String value = params.getString("repositories", "");
|
699e71
|
91 |
List<String> list = StringUtils.getStringsFromValue(value);
|
7d97c6
|
92 |
repositories.addAll(list);
|
b4d958
|
93 |
}
|
VF |
94 |
|
|
95 |
if (params.containsKey("allrepos")) {
|
|
96 |
repositories.addAll(availableRepositories);
|
7d97c6
|
97 |
}
|
JM |
98 |
|
|
99 |
if (params.containsKey("query")) {
|
699e71
|
100 |
query = params.getString("query", "");
|
7d97c6
|
101 |
} else {
|
JM |
102 |
String value = WicketUtils.getSearchString(params);
|
|
103 |
String type = WicketUtils.getSearchType(params);
|
|
104 |
com.gitblit.Constants.SearchType searchType = com.gitblit.Constants.SearchType.forName(type);
|
|
105 |
if (!StringUtils.isEmpty(value)) {
|
|
106 |
if (searchType == SearchType.COMMIT) {
|
699e71
|
107 |
query = "type:" + searchType.name().toLowerCase() + " AND \"" + value + "\"";
|
7d97c6
|
108 |
} else {
|
JM |
109 |
query = searchType.name().toLowerCase() + ":\"" + value + "\"";
|
|
110 |
}
|
|
111 |
}
|
|
112 |
}
|
3d0494
|
113 |
}
|
699e71
|
114 |
|
99d0d4
|
115 |
boolean luceneEnabled = app().settings().getBoolean(Keys.web.allowLuceneIndexing, true);
|
7db092
|
116 |
if (luceneEnabled) {
|
JM |
117 |
if (availableRepositories.size() == 0) {
|
|
118 |
info(getString("gb.noIndexedRepositoriesWarning"));
|
|
119 |
}
|
|
120 |
} else {
|
|
121 |
error(getString("gb.luceneDisabled"));
|
40ca5c
|
122 |
}
|
JM |
123 |
|
|
124 |
// enforce user-accessible repository selections
|
548b29
|
125 |
Set<String> uniqueRepositories = new LinkedHashSet<String>();
|
40ca5c
|
126 |
for (String selectedRepository : repositories) {
|
JM |
127 |
if (availableRepositories.contains(selectedRepository)) {
|
548b29
|
128 |
uniqueRepositories.add(selectedRepository);
|
40ca5c
|
129 |
}
|
JM |
130 |
}
|
548b29
|
131 |
ArrayList<String> searchRepositories = new ArrayList<String>(uniqueRepositories);
|
699e71
|
132 |
|
7d97c6
|
133 |
// search form
|
JM |
134 |
final Model<String> queryModel = new Model<String>(query);
|
40ca5c
|
135 |
final Model<ArrayList<String>> repositoriesModel = new Model<ArrayList<String>>(searchRepositories);
|
b4d958
|
136 |
final Model<Boolean> allreposModel = new Model<Boolean>(params != null && params.containsKey("allrepos"));
|
ed295f
|
137 |
SessionlessForm<Void> form = new SessionlessForm<Void>("searchForm", getClass()) {
|
699e71
|
138 |
|
7d97c6
|
139 |
private static final long serialVersionUID = 1L;
|
JM |
140 |
|
|
141 |
@Override
|
|
142 |
public void onSubmit() {
|
|
143 |
String q = queryModel.getObject();
|
|
144 |
if (StringUtils.isEmpty(q)) {
|
40ca5c
|
145 |
error(getString("gb.undefinedQueryWarning"));
|
7d97c6
|
146 |
return;
|
699e71
|
147 |
}
|
b4d958
|
148 |
if (repositoriesModel.getObject().size() == 0 && !allreposModel.getObject()) {
|
40ca5c
|
149 |
error(getString("gb.noSelectedRepositoriesWarning"));
|
7d97c6
|
150 |
return;
|
JM |
151 |
}
|
|
152 |
PageParameters params = new PageParameters();
|
|
153 |
params.put("repositories", StringUtils.flattenStrings(repositoriesModel.getObject()));
|
|
154 |
params.put("query", queryModel.getObject());
|
b4d958
|
155 |
params.put("allrepos", allreposModel.getObject());
|
1b84d3
|
156 |
LuceneSearchPage page = new LuceneSearchPage(params);
|
JM |
157 |
setResponsePage(page);
|
7d97c6
|
158 |
}
|
JM |
159 |
};
|
699e71
|
160 |
|
JM |
161 |
ListMultipleChoice<String> selections = new ListMultipleChoice<String>("repositories",
|
672296
|
162 |
repositoriesModel, availableRepositories, new StringChoiceRenderer());
|
4e1930
|
163 |
selections.setMaxRows(8);
|
7db092
|
164 |
form.add(selections.setEnabled(luceneEnabled));
|
JM |
165 |
form.add(new TextField<String>("query", queryModel).setEnabled(luceneEnabled));
|
b4d958
|
166 |
form.add(new CheckBox("allrepos", allreposModel));
|
7db092
|
167 |
add(form.setEnabled(luceneEnabled));
|
699e71
|
168 |
|
7d97c6
|
169 |
// execute search
|
4c13bf
|
170 |
final List<SearchResult> results = new ArrayList<SearchResult>();
|
40ca5c
|
171 |
if (!ArrayUtils.isEmpty(searchRepositories) && !StringUtils.isEmpty(query)) {
|
99d0d4
|
172 |
results.addAll(app().repositories().search(query, page, pageSize, searchRepositories));
|
d04009
|
173 |
}
|
699e71
|
174 |
|
d04009
|
175 |
// results header
|
JM |
176 |
if (results.size() == 0) {
|
22a8a6
|
177 |
if (!ArrayUtils.isEmpty(searchRepositories) && !StringUtils.isEmpty(query)) {
|
JM |
178 |
add(new Label("resultsHeader", query).setRenderBodyOnly(true));
|
6caa93
|
179 |
add(new Label("resultsCount", getString("gb.noHits")).setRenderBodyOnly(true));
|
22a8a6
|
180 |
} else {
|
JM |
181 |
add(new Label("resultsHeader").setVisible(false));
|
|
182 |
add(new Label("resultsCount").setVisible(false));
|
|
183 |
}
|
d04009
|
184 |
} else {
|
JM |
185 |
add(new Label("resultsHeader", query).setRenderBodyOnly(true));
|
6caa93
|
186 |
add(new Label("resultsCount", MessageFormat.format(getString("gb.queryResults"),
|
d04009
|
187 |
results.get(0).hitId, results.get(results.size() - 1).hitId, results.get(0).totalHits)).
|
JM |
188 |
setRenderBodyOnly(true));
|
d896e6
|
189 |
}
|
699e71
|
190 |
|
7d97c6
|
191 |
// search results view
|
4c13bf
|
192 |
ListDataProvider<SearchResult> resultsDp = new ListDataProvider<SearchResult>(results);
|
JM |
193 |
final DataView<SearchResult> resultsView = new DataView<SearchResult>("searchResults", resultsDp) {
|
|
194 |
private static final long serialVersionUID = 1L;
|
699e71
|
195 |
@Override
|
4c13bf
|
196 |
public void populateItem(final Item<SearchResult> item) {
|
31a897
|
197 |
final SearchResult sr = item.getModelObject();
|
4c13bf
|
198 |
switch(sr.type) {
|
JM |
199 |
case commit: {
|
|
200 |
Label icon = WicketUtils.newIcon("type", "icon-refresh");
|
|
201 |
WicketUtils.setHtmlTooltip(icon, "commit");
|
|
202 |
item.add(icon);
|
98b4ed
|
203 |
item.add(new LinkPanel("summary", null, sr.summary, CommitPage.class, WicketUtils.newObjectParameter(sr.repository, sr.commitId)));
|
31a897
|
204 |
// show tags
|
JM |
205 |
Fragment fragment = new Fragment("tags", "tagsPanel", LuceneSearchPage.this);
|
|
206 |
List<String> tags = sr.tags;
|
|
207 |
if (tags == null) {
|
|
208 |
tags = new ArrayList<String>();
|
|
209 |
}
|
|
210 |
ListDataProvider<String> tagsDp = new ListDataProvider<String>(tags);
|
|
211 |
final DataView<String> tagsView = new DataView<String>("tag", tagsDp) {
|
|
212 |
private static final long serialVersionUID = 1L;
|
699e71
|
213 |
@Override
|
31a897
|
214 |
public void populateItem(final Item<String> item) {
|
JM |
215 |
String tag = item.getModelObject();
|
|
216 |
Component c = new LinkPanel("tagLink", null, tag, TagPage.class,
|
|
217 |
WicketUtils.newObjectParameter(sr.repository, Constants.R_TAGS + tag));
|
699e71
|
218 |
WicketUtils.setCssClass(c, "tagRef");
|
31a897
|
219 |
item.add(c);
|
JM |
220 |
}
|
|
221 |
};
|
|
222 |
fragment.add(tagsView);
|
|
223 |
item.add(fragment);
|
4c13bf
|
224 |
break;
|
JM |
225 |
}
|
|
226 |
case blob: {
|
|
227 |
Label icon = WicketUtils.newIcon("type", "icon-file");
|
|
228 |
WicketUtils.setHtmlTooltip(icon, "blob");
|
|
229 |
item.add(icon);
|
98b4ed
|
230 |
item.add(new LinkPanel("summary", null, sr.path, BlobPage.class, WicketUtils.newPathParameter(sr.repository, sr.branch, sr.path)));
|
31a897
|
231 |
item.add(new Label("tags").setVisible(false));
|
4c13bf
|
232 |
break;
|
JM |
233 |
}
|
|
234 |
}
|
98b4ed
|
235 |
item.add(new Label("fragment", sr.fragment).setEscapeModelStrings(false).setVisible(!StringUtils.isEmpty(sr.fragment)));
|
3f0677
|
236 |
item.add(new LinkPanel("repository", null, sr.repository, SummaryPage.class, WicketUtils.newRepositoryParameter(sr.repository)));
|
d04009
|
237 |
if (StringUtils.isEmpty(sr.branch)) {
|
JM |
238 |
item.add(new Label("branch", "null"));
|
|
239 |
} else {
|
|
240 |
item.add(new LinkPanel("branch", "branch", StringUtils.getRelativePath(Constants.R_HEADS, sr.branch), LogPage.class, WicketUtils.newObjectParameter(sr.repository, sr.branch)));
|
|
241 |
}
|
4c13bf
|
242 |
item.add(new Label("author", sr.author));
|
9adf62
|
243 |
item.add(WicketUtils.createDatestampLabel("date", sr.date, getTimeZone(), getTimeUtils()));
|
4c13bf
|
244 |
}
|
JM |
245 |
};
|
7d97c6
|
246 |
add(resultsView.setVisible(results.size() > 0));
|
699e71
|
247 |
|
d04009
|
248 |
PageParameters pagerParams = new PageParameters();
|
JM |
249 |
pagerParams.put("repositories", StringUtils.flattenStrings(repositoriesModel.getObject()));
|
|
250 |
pagerParams.put("query", queryModel.getObject());
|
699e71
|
251 |
|
697def
|
252 |
boolean showPager = false;
|
d04009
|
253 |
int totalPages = 0;
|
JM |
254 |
if (results.size() > 0) {
|
|
255 |
totalPages = (results.get(0).totalHits / pageSize) + (results.get(0).totalHits % pageSize > 0 ? 1 : 0);
|
697def
|
256 |
showPager = results.get(0).totalHits > pageSize;
|
d04009
|
257 |
}
|
699e71
|
258 |
|
697def
|
259 |
add(new PagerPanel("topPager", page, totalPages, LuceneSearchPage.class, pagerParams).setVisible(showPager));
|
JM |
260 |
add(new PagerPanel("bottomPager", page, totalPages, LuceneSearchPage.class, pagerParams).setVisible(showPager));
|
d04009
|
261 |
}
|
4c13bf
|
262 |
}
|