comparison src/main/java/edu/harvard/iq/dataverse/SearchIncludeFragment.java @ 10:a50cf11e5178

Rewrite LGDataverse completely upgrading to dataverse4.0
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Tue, 08 Sep 2015 17:00:21 +0200
parents
children
comparison
equal deleted inserted replaced
9:5926d6419569 10:a50cf11e5178
1 package edu.harvard.iq.dataverse;
2
3 import edu.harvard.iq.dataverse.search.SearchFields;
4 import edu.harvard.iq.dataverse.authorization.users.GuestUser;
5 import edu.harvard.iq.dataverse.search.SearchException;
6 import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
7 import edu.harvard.iq.dataverse.util.SystemConfig;
8 import java.util.ArrayList;
9 import java.util.Arrays;
10 import java.util.Date;
11 import java.util.HashMap;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.logging.Logger;
15 import javax.ejb.EJB;
16 import javax.faces.view.ViewScoped;
17 import javax.inject.Inject;
18 import javax.inject.Named;
19 import org.apache.commons.lang.StringUtils;
20
21 @ViewScoped
22 @Named("SearchIncludeFragment")
23 public class SearchIncludeFragment implements java.io.Serializable {
24
25 private static final Logger logger = Logger.getLogger(SearchIncludeFragment.class.getCanonicalName());
26
27 @EJB
28 SearchServiceBean searchService;
29 @EJB
30 DataverseServiceBean dataverseService;
31 @EJB
32 DatasetServiceBean datasetService;
33 @EJB
34 DatasetVersionServiceBean datasetVersionService;
35 @EJB
36 DataFileServiceBean dataFileService;
37 @EJB
38 PermissionServiceBean permissionService;
39 @EJB
40 SettingsServiceBean settingsService;
41 @EJB
42 SystemConfig systemConfig;
43 @Inject
44 DataverseSession session;
45
46 private String browseModeString = "browse";
47 private String searchModeString = "search";
48 private String mode;
49 private String query;
50 private List<String> filterQueries = new ArrayList<>();
51 private List<FacetCategory> facetCategoryList = new ArrayList<>();
52 private List<SolrSearchResult> searchResultsList = new ArrayList<>();
53 private int searchResultsCount;
54 private String fq0;
55 private String fq1;
56 private String fq2;
57 private String fq3;
58 private String fq4;
59 private String fq5;
60 private String fq6;
61 private String fq7;
62 private String fq8;
63 private String fq9;
64 private String dataverseAlias;
65 private Dataverse dataverse;
66 // commenting out dataverseSubtreeContext. it was not well-loved in the GUI
67 // private String dataverseSubtreeContext;
68 private String selectedTypesString;
69 private List<String> selectedTypesList = new ArrayList<String>();
70 private String selectedTypesHumanReadable;
71 private String searchFieldType = SearchFields.TYPE;
72 private String searchFieldSubtree = SearchFields.SUBTREE;
73 // private String searchFieldHostDataverse = SearchFields.HOST_DATAVERSE;
74 private String searchFieldNameSort = SearchFields.NAME_SORT;
75 private String searchFieldRelevance = SearchFields.RELEVANCE;
76 // private String searchFieldReleaseDate = SearchFields.RELEASE_DATE_YYYY;
77 private String searchFieldReleaseOrCreateDate = SearchFields.RELEASE_OR_CREATE_DATE;
78 final private String ASCENDING = "asc";
79 final private String DESCENDING = "desc";
80 private String typeFilterQuery;
81 private Long facetCountDataverses = 0L;
82 private Long facetCountDatasets = 0L;
83 private Long facetCountFiles = 0L;
84 Map<String, Long> previewCountbyType = new HashMap<>();
85 private SolrQueryResponse solrQueryResponseAllTypes;
86 private String sortField;
87 private String sortOrder;
88 private String currentSort;
89 private String currentSortFriendly;
90 private int page = 1;
91 private int paginationGuiStart = 1;
92 private int paginationGuiEnd = 10;
93 private int paginationGuiRows = 10;
94 Map<String, String> datasetfieldFriendlyNamesBySolrField = new HashMap<>();
95 Map<String, String> staticSolrFieldFriendlyNamesBySolrField = new HashMap<>();
96 private boolean solrIsDown = false;
97 private Map<String, Integer> numberOfFacets = new HashMap<>();
98 private boolean debug = false;
99 // private boolean showUnpublished;
100 List<String> filterQueriesDebug = new ArrayList<>();
101 // private Map<String, String> friendlyName = new HashMap<>();
102 private String errorFromSolr;
103 private SearchException searchException;
104
105 /**
106 * @todo:
107 *
108 * better style and icons for facets
109 *
110 * replace * with watermark saying "Search this Dataverse"
111 *
112 * get rid of "_s" et al. (human eyeball friendly)
113 *
114 * pagination (previous/next links)
115 *
116 * test dataset cards
117 *
118 * test files cards
119 *
120 * test dataset cards when Solr is down
121 *
122 * make results sortable: https://redmine.hmdc.harvard.edu/issues/3482
123 *
124 * always show all types, even if zero count:
125 * https://redmine.hmdc.harvard.edu/issues/3488
126 *
127 * make subtree facet look like amazon widget (i.e. a tree)
128 *
129 * see also https://trello.com/c/jmry3BJR/28-browse-dataverses
130 */
131 public String searchRedirect(String dataverseRedirectPage) {
132 /**
133 * These are our decided-upon search/browse rules, the way we expect
134 * users to search/browse and how we want the app behave:
135 *
136 * 1. When a user is browsing (i.e. hasn't entered a search term) we
137 * only show dataverses and datasets. Files are hidden. See
138 * https://redmine.hmdc.harvard.edu/issues/3573
139 *
140 * 2. A search is always brand new. Don't keep around old facets that
141 * were selected. Show page 1 of results. Make the results bookmarkable:
142 * https://redmine.hmdc.harvard.edu/issues/3664
143 *
144 * 3. When you add or remove a facet, you should always go to page 1 of
145 * search results. Search terms should be preserved. Sorting should be
146 * preserved.
147 *
148 * 4. After search terms have been entered and facets have been
149 * selected, we expect users to (optionally) page through search results
150 * and as they do so we will preserve the state of their search terms,
151 * their facet selections, and their sorting.
152 *
153 * 5. Someday the default sort order for browse mode will be by "release
154 * date" (newest first) but that functionality is not yet available in
155 * the system ( see https://redmine.hmdc.harvard.edu/issues/3628 and
156 * https://redmine.hmdc.harvard.edu/issues/3629 ) so for now the default
157 * sort order for browse mode will by alphabetical (sort by name,
158 * ascending). The default sort order for search mode will be by
159 * relevance. (We only offer ascending ordering for relevance since
160 * descending order is unlikely to be useful.) When you sort, facet
161 * selections and what page you are on should be preserved.
162 *
163 */
164
165 dataverseRedirectPage = StringUtils.isBlank(dataverseRedirectPage) ? "dataverse.xhtml" : dataverseRedirectPage;
166 String optionalDataverseScope = "&alias=" + dataverse.getAlias();
167
168 return dataverseRedirectPage + "?faces-redirect=true&q=" + query + optionalDataverseScope;
169
170 }
171
172 public void search() {
173 search(false);
174 }
175
176 public void search(boolean onlyDataRelatedToMe) {
177 logger.fine("search called");
178
179 // wildcard/browse (*) unless user supplies a query
180 String queryToPassToSolr = "*";
181 if (this.query == null) {
182 mode = browseModeString;
183 } else if (this.query.isEmpty()) {
184 mode = browseModeString;
185 } else {
186 mode = searchModeString;
187 }
188
189 if (mode.equals(browseModeString)) {
190 queryToPassToSolr = "*";
191 if (sortField == null) {
192 sortField = searchFieldReleaseOrCreateDate;
193 }
194 if (sortOrder == null) {
195 sortOrder = DESCENDING;
196 }
197 if (selectedTypesString == null || selectedTypesString.isEmpty()) {
198 selectedTypesString = "dataverses:datasets";
199 }
200 } else if (mode.equals(searchModeString)) {
201 queryToPassToSolr = query;
202 if (sortField == null) {
203 sortField = searchFieldRelevance;
204 }
205 if (sortOrder == null) {
206 sortOrder = DESCENDING;
207 }
208 if (selectedTypesString == null || selectedTypesString.isEmpty()) {
209 selectedTypesString = "dataverses:datasets:files";
210 }
211 }
212
213 filterQueries = new ArrayList<>();
214 for (String fq : Arrays.asList(fq0, fq1, fq2, fq3, fq4, fq5, fq6, fq7, fq8, fq9)) {
215 if (fq != null) {
216 filterQueries.add(fq);
217 }
218 }
219
220 SolrQueryResponse solrQueryResponse = null;
221
222 List<String> filterQueriesFinal = new ArrayList<>();
223 if (dataverseAlias != null) {
224 this.dataverse = dataverseService.findByAlias(dataverseAlias);
225 }
226 if (this.dataverse != null) {
227 String dataversePath = dataverseService.determineDataversePath(this.dataverse);
228 String filterDownToSubtree = SearchFields.SUBTREE + ":\"" + dataversePath + "\"";
229 if (!this.dataverse.equals(dataverseService.findRootDataverse())) {
230 /**
231 * @todo centralize this into SearchServiceBean
232 */
233 filterQueriesFinal.add(filterDownToSubtree);
234 // this.dataverseSubtreeContext = dataversePath;
235 } else {
236 // this.dataverseSubtreeContext = "all";
237 }
238 } else {
239 this.dataverse = dataverseService.findRootDataverse();
240 // this.dataverseSubtreeContext = "all";
241 }
242
243 selectedTypesList = new ArrayList<>();
244 String[] parts = selectedTypesString.split(":");
245 // int count = 0;
246 for (String string : parts) {
247 selectedTypesList.add(string);
248 }
249
250 List<String> filterQueriesFinalAllTypes = new ArrayList<>();
251 String[] arr = selectedTypesList.toArray(new String[selectedTypesList.size()]);
252 selectedTypesHumanReadable = combine(arr, " OR ");
253 if (!selectedTypesHumanReadable.isEmpty()) {
254 typeFilterQuery = SearchFields.TYPE + ":(" + selectedTypesHumanReadable + ")";
255 }
256 filterQueriesFinal.addAll(filterQueries);
257 filterQueriesFinalAllTypes.addAll(filterQueriesFinal);
258 filterQueriesFinal.add(typeFilterQuery);
259 String allTypesFilterQuery = SearchFields.TYPE + ":(dataverses OR datasets OR files)";
260 filterQueriesFinalAllTypes.add(allTypesFilterQuery);
261
262 int paginationStart = (page - 1) * paginationGuiRows;
263 /**
264 * @todo
265 *
266 * design/make room for sort widget drop down:
267 * https://redmine.hmdc.harvard.edu/issues/3482
268 *
269 */
270
271 try {
272 logger.fine("query from user: " + query);
273 logger.fine("queryToPassToSolr: " + queryToPassToSolr);
274 logger.fine("sort by: " + sortField);
275
276 /**
277 * @todo Number of search results per page should be configurable -
278 * https://github.com/IQSS/dataverse/issues/84
279 */
280 int numRows = 10;
281 solrQueryResponse = searchService.search(session.getUser(), dataverse, queryToPassToSolr, filterQueriesFinal, sortField, sortOrder, paginationStart, onlyDataRelatedToMe, numRows);
282 solrQueryResponseAllTypes = searchService.search(session.getUser(), dataverse, queryToPassToSolr, filterQueriesFinalAllTypes, sortField, sortOrder, paginationStart, onlyDataRelatedToMe, numRows);
283 } catch (SearchException ex) {
284 Throwable cause = ex;
285 StringBuilder sb = new StringBuilder();
286 sb.append(cause + " ");
287 while (cause.getCause() != null) {
288 cause = cause.getCause();
289 sb.append(cause.getClass().getCanonicalName() + " ");
290 sb.append(cause + " ");
291 }
292 String message = "Exception running search for [" + queryToPassToSolr + "] with filterQueries " + filterQueries + " and paginationStart [" + paginationStart + "]: " + sb.toString();
293 logger.info(message);
294 this.solrIsDown = true;
295 this.searchException = ex;
296 }
297 if (!solrIsDown) {
298 this.facetCategoryList = solrQueryResponse.getFacetCategoryList();
299 this.searchResultsList = solrQueryResponse.getSolrSearchResults();
300 this.searchResultsCount = solrQueryResponse.getNumResultsFound().intValue();
301 this.datasetfieldFriendlyNamesBySolrField = solrQueryResponse.getDatasetfieldFriendlyNamesBySolrField();
302 this.staticSolrFieldFriendlyNamesBySolrField = solrQueryResponse.getStaticSolrFieldFriendlyNamesBySolrField();
303 this.filterQueriesDebug = solrQueryResponse.getFilterQueriesActual();
304 this.errorFromSolr = solrQueryResponse.getError();
305 paginationGuiStart = paginationStart + 1;
306 paginationGuiEnd = Math.min(page * paginationGuiRows, searchResultsCount);
307 List<SolrSearchResult> searchResults = solrQueryResponse.getSolrSearchResults();
308
309 /**
310 * @todo consider creating Java objects called DatasetCard,
311 * DatasetCart, and FileCard since that's what we call them in the
312 * UI. These objects' fields (affiliation, citation, etc.) would be
313 * populated from Solr if possible (for performance, to avoid extra
314 * database calls) or by a database call (if it's tricky or doesn't
315 * make sense to get the data in and out of Solr). We would continue
316 * to iterate through all the SolrSearchResult objects as we build
317 * up the new card objects. Think about how we have a
318 * solrSearchResult.setCitation method but only the dataset card in
319 * the UI (currently) shows this "citation" field.
320 */
321 for (SolrSearchResult solrSearchResult : searchResults) {
322 if (solrSearchResult.getEntityId() == null) {
323 // avoiding EJBException a la https://redmine.hmdc.harvard.edu/issues/3809
324 logger.warning(SearchFields.ENTITY_ID + " was null for Solr document id:" + solrSearchResult.getId() + ", skipping. Bad Solr data?");
325 break;
326 }
327 if (solrSearchResult.getType().equals("dataverses")) {
328 Dataverse dataverseInCard = dataverseService.find(solrSearchResult.getEntityId());
329 String parentId = solrSearchResult.getParent().get("id");
330 solrSearchResult.setIsInTree(false);
331 if (parentId != null) {
332 Dataverse parentDataverseInCard = dataverseService.find(Long.parseLong(parentId));
333 solrSearchResult.setDataverseParentAlias(parentDataverseInCard.getAlias());
334 List<Dataverse> dvTree = new ArrayList();
335 Dataverse testDV = parentDataverseInCard;
336 dvTree.add(testDV);
337 while (testDV.getOwner() != null) {
338 dvTree.add(testDV.getOwner());
339 testDV = testDV.getOwner();
340 }
341 if (dvTree.contains(dataverse)) {
342 solrSearchResult.setIsInTree(true);
343 }
344 }
345
346 if (dataverseInCard != null) {
347 solrSearchResult.setDataverseAffiliation(dataverseInCard.getAffiliation());
348 solrSearchResult.setStatus(getCreatedOrReleasedDate(dataverseInCard, solrSearchResult.getReleaseOrCreateDate()));
349 solrSearchResult.setDataverseAlias(dataverseInCard.getAlias());
350 }
351 } else if (solrSearchResult.getType().equals("datasets")) {
352 Long dataverseId = Long.parseLong(solrSearchResult.getParent().get("id"));
353 Dataverse parentDataverse = dataverseService.find(dataverseId);
354 solrSearchResult.setIsInTree(false);
355 List<Dataverse> dvTree = new ArrayList();
356 Dataverse testDV = parentDataverse;
357 dvTree.add(testDV);
358 /**
359 * @todo Why is a NPE being thrown at this `while
360 * (testDV.getOwner() != null){` line? An NPE was being
361 * thrown while browsing the site *after* issuing the
362 * DestroyDatasetCommand but before a fix was put in to
363 * remove the dataset "card" from Solr. The ticket tracking
364 * this that fix is
365 * https://github.com/IQSS/dataverse/issues/1316 but it's
366 * unclear why the NPE was thrown. The users see a nasty
367 * "Internal Server Error - An unexpected error was
368 * encountered, no more information is available." and
369 * server.log has a stacktrace with the NPE.
370 */
371 while (testDV.getOwner() != null) {
372 dvTree.add(testDV.getOwner());
373 testDV = testDV.getOwner();
374 }
375 if (dvTree.contains(dataverse)) {
376 solrSearchResult.setIsInTree(true);
377 }
378 /**
379 * @todo can a dataverse alias ever be null?
380 */
381 solrSearchResult.setDataverseAlias(parentDataverse.getAlias());
382 Long datasetVersionId = solrSearchResult.getDatasetVersionId();
383 if (datasetVersionId != null) {
384 DatasetVersion datasetVersion = datasetVersionService.find(datasetVersionId);
385 if (datasetVersion != null) {
386 if (datasetVersion.isDeaccessioned()) {
387 solrSearchResult.setDeaccessionedState(true);
388 }
389
390 }
391 }
392 String deaccesssionReason = solrSearchResult.getDeaccessionReason();
393 if (deaccesssionReason != null) {
394 solrSearchResult.setDescriptionNoSnippet(deaccesssionReason);
395 }
396 } else if (solrSearchResult.getType().equals("files")) {
397 DataFile dataFile = dataFileService.find(solrSearchResult.getEntityId());
398 if (dataFile != null) {
399 solrSearchResult.setStatus(getCreatedOrReleasedDate(dataFile, solrSearchResult.getReleaseOrCreateDate()));
400 }
401 Long datasetId = Long.parseLong(solrSearchResult.getParent().get("id"));
402 Dataset parentDS = datasetService.find(datasetId);
403 Dataverse parentDataverse = parentDS.getOwner();
404 solrSearchResult.setIsInTree(false);
405 List<Dataverse> dvTree = new ArrayList();
406 Dataverse testDV = parentDataverse;
407 dvTree.add(testDV);
408 /**
409 * @todo Why is a NPE being thrown at this `while
410 * (testDV.getOwner() != null){` line? An NPE was being
411 * thrown while browsing the site *after* issuing the
412 * DestroyDatasetCommand but before a fix was put in to
413 * remove the dataset "card" from Solr. The ticket tracking
414 * this that fix is
415 * https://github.com/IQSS/dataverse/issues/1316 but it's
416 * unclear why the NPE was thrown. The users see a nasty
417 * "Internal Server Error - An unexpected error was
418 * encountered, no more information is available." and
419 * server.log has a stacktrace with the NPE.
420 */
421 if (testDV != null) {
422 while (testDV.getOwner() != null) {
423 dvTree.add(testDV.getOwner());
424 testDV = testDV.getOwner();
425 }
426 }
427
428 if (dvTree.contains(dataverse)) {
429 solrSearchResult.setIsInTree(true);
430 }
431 /**
432 * @todo: show DataTable variables
433 */
434 }
435 }
436
437 // populate preview counts: https://redmine.hmdc.harvard.edu/issues/3560
438 previewCountbyType.put("dataverses", 0L);
439 previewCountbyType.put("datasets", 0L);
440 previewCountbyType.put("files", 0L);
441 if (solrQueryResponseAllTypes != null) {
442 for (FacetCategory facetCategory : solrQueryResponseAllTypes.getTypeFacetCategories()) {
443 for (FacetLabel facetLabel : facetCategory.getFacetLabel()) {
444 previewCountbyType.put(facetLabel.getName(), facetLabel.getCount());
445 }
446 }
447 }
448
449 } else {
450 List contentsList = dataverseService.findByOwnerId(dataverse.getId());
451 contentsList.addAll(datasetService.findByOwnerId(dataverse.getId()));
452 // directChildDvObjectContainerList.addAll(contentsList);
453 }
454 /**
455 * @todo: pull values from datasetField.getTitle() rather than hard
456 * coding them here
457 */
458 // friendlyName.put(SearchFields.SUBTREE, "Dataverse Subtree");
459 // friendlyName.put(SearchFields.HOST_DATAVERSE, "Original Dataverse");
460 // friendlyName.put(SearchFields.AUTHOR_STRING, "Author");
461 // friendlyName.put(SearchFields.AFFILIATION, "Affiliation");
462 // friendlyName.put(SearchFields.KEYWORD, "Keyword");
463 // friendlyName.put(SearchFields.DISTRIBUTOR, "Distributor");
464 // friendlyName.put(SearchFields.FILE_TYPE, "File Type");
465 // friendlyName.put(SearchFields.PRODUCTION_DATE_YEAR_ONLY, "Production Date");
466 // friendlyName.put(SearchFields.DISTRIBUTION_DATE_YEAR_ONLY, "Distribution Date");
467 }
468
469 // public boolean isShowUnpublished() {
470 // return showUnpublished;
471 // }
472 //
473 // public void setShowUnpublished(boolean showUnpublished) {
474 // this.showUnpublished = showUnpublished;
475 // }
476 public String getBrowseModeString() {
477 return browseModeString;
478 }
479
480 public String getSearchModeString() {
481 return searchModeString;
482 }
483
484 public String getMode() {
485 // enum would be prefered but we can't reference enums from JSF:
486 // http://stackoverflow.com/questions/2524420/how-to-testing-for-enum-equality-in-jsf/2524901#2524901
487 return mode;
488 }
489
490 public int getNumberOfFacets(String name, int defaultValue) {
491 Integer numFacets = numberOfFacets.get(name);
492 if (numFacets == null) {
493 numberOfFacets.put(name, defaultValue);
494 numFacets = defaultValue;
495 }
496 return numFacets;
497 }
498
499 public void incrementFacets(String name, int incrementNum) {
500 Integer numFacets = numberOfFacets.get(name);
501 if (numFacets == null) {
502 numFacets = incrementNum;
503 }
504 numberOfFacets.put(name, numFacets + incrementNum);
505 }
506
507 // http://stackoverflow.com/questions/1515437/java-function-for-arrays-like-phps-join/1515548#1515548
508 String combine(String[] s, String glue) {
509 int k = s.length;
510 if (k == 0) {
511 return null;
512 }
513 StringBuilder out = new StringBuilder();
514 out.append(s[0]);
515 for (int x = 1; x < k; ++x) {
516 out.append(glue).append(s[x]);
517 }
518 return out.toString();
519 }
520
521 private Long findFacetCountByType(String type) {
522 return previewCountbyType.get(type);
523 }
524
525 public boolean isAllowedToClickAddData() {
526 /**
527 * @todo is this the right permission to check?
528 */
529 // being explicit about the user, could just call permissionService.on(dataverse)
530
531 // TODO: decide on rules for this button and check actual permissions
532 return session.getUser() != null && session.getUser().isAuthenticated();
533 //return permissionService.userOn(session.getUser(), dataverse).has(Permission.UndoableEdit);
534 }
535
536 private String getCreatedOrReleasedDate(DvObject dvObject, Date date) {
537 // the hedge is for https://redmine.hmdc.harvard.edu/issues/3806
538 String hedge = "";
539 if (dvObject instanceof Dataverse) {
540 hedge = "";
541 } else if (dvObject instanceof Dataset) {
542 hedge = " maybe";
543 } else if (dvObject instanceof DataFile) {
544 hedge = " maybe";
545 } else {
546 hedge = " what object is this?";
547 }
548 if (dvObject.isReleased()) {
549 return date + " released" + hedge;
550 } else {
551 return date + " created" + hedge;
552 }
553 }
554
555 public String getQuery() {
556 return query;
557 }
558
559 public void setQuery(String query) {
560 this.query = query;
561 }
562
563 public List<String> getFilterQueries() {
564 return filterQueries;
565 }
566
567 public void setFilterQueries(List<String> filterQueries) {
568 this.filterQueries = filterQueries;
569 }
570
571 public List<FacetCategory> getFacetCategoryList() {
572 return facetCategoryList;
573 }
574
575 public void setFacetCategoryList(List<FacetCategory> facetCategoryList) {
576 this.facetCategoryList = facetCategoryList;
577 }
578
579 public List<SolrSearchResult> getSearchResultsList() {
580 return searchResultsList;
581 }
582
583 public void setSearchResultsList(List<SolrSearchResult> searchResultsList) {
584 this.searchResultsList = searchResultsList;
585 }
586
587 public int getSearchResultsCount() {
588 return searchResultsCount;
589 }
590
591 public void setSearchResultsCount(int searchResultsCount) {
592 this.searchResultsCount = searchResultsCount;
593 }
594
595 public String getFq0() {
596 return fq0;
597 }
598
599 public void setFq0(String fq0) {
600 this.fq0 = fq0;
601 }
602
603 public String getFq1() {
604 return fq1;
605 }
606
607 public void setFq1(String fq1) {
608 this.fq1 = fq1;
609 }
610
611 public String getFq2() {
612 return fq2;
613 }
614
615 public void setFq2(String fq2) {
616 this.fq2 = fq2;
617 }
618
619 public String getFq3() {
620 return fq3;
621 }
622
623 public void setFq3(String fq3) {
624 this.fq3 = fq3;
625 }
626
627 public String getFq4() {
628 return fq4;
629 }
630
631 public void setFq4(String fq4) {
632 this.fq4 = fq4;
633 }
634
635 public String getFq5() {
636 return fq5;
637 }
638
639 public void setFq5(String fq5) {
640 this.fq5 = fq5;
641 }
642
643 public String getFq6() {
644 return fq6;
645 }
646
647 public void setFq6(String fq6) {
648 this.fq6 = fq6;
649 }
650
651 public String getFq7() {
652 return fq7;
653 }
654
655 public void setFq7(String fq7) {
656 this.fq7 = fq7;
657 }
658
659 public String getFq8() {
660 return fq8;
661 }
662
663 public void setFq8(String fq8) {
664 this.fq8 = fq8;
665 }
666
667 public String getFq9() {
668 return fq9;
669 }
670
671 public void setFq9(String fq9) {
672 this.fq9 = fq9;
673 }
674
675 public Dataverse getDataverse() {
676 return dataverse;
677 }
678
679 public void setDataverse(Dataverse dataverse) {
680 this.dataverse = dataverse;
681 }
682
683 // public String getDataverseSubtreeContext() {
684 // return dataverseSubtreeContext;
685 // }
686 //
687 // public void setDataverseSubtreeContext(String dataverseSubtreeContext) {
688 // this.dataverseSubtreeContext = dataverseSubtreeContext;
689 // }
690 public String getSelectedTypesString() {
691 return selectedTypesString;
692 }
693
694 public void setSelectedTypesString(String selectedTypesString) {
695 this.selectedTypesString = selectedTypesString;
696 }
697
698 public List<String> getSelectedTypesList() {
699 return selectedTypesList;
700 }
701
702 public void setSelectedTypesList(List<String> selectedTypesList) {
703 this.selectedTypesList = selectedTypesList;
704 }
705
706 public String getSelectedTypesHumanReadable() {
707 return selectedTypesHumanReadable;
708 }
709
710 public void setSelectedTypesHumanReadable(String selectedTypesHumanReadable) {
711 this.selectedTypesHumanReadable = selectedTypesHumanReadable;
712 }
713
714 public String getSearchFieldType() {
715 return searchFieldType;
716 }
717
718 public void setSearchFieldType(String searchFieldType) {
719 this.searchFieldType = searchFieldType;
720 }
721
722 public String getSearchFieldSubtree() {
723 return searchFieldSubtree;
724 }
725
726 public void setSearchFieldSubtree(String searchFieldSubtree) {
727 this.searchFieldSubtree = searchFieldSubtree;
728 }
729
730 // public String getSearchFieldHostDataverse() {
731 // return searchFieldHostDataverse;
732 // }
733 //
734 // public void setSearchFieldHostDataverse(String searchFieldHostDataverse) {
735 // this.searchFieldHostDataverse = searchFieldHostDataverse;
736 // }
737 public String getTypeFilterQuery() {
738 return typeFilterQuery;
739 }
740
741 public void setTypeFilterQuery(String typeFilterQuery) {
742 this.typeFilterQuery = typeFilterQuery;
743 }
744
745 public Long getFacetCountDatasets() {
746 return findFacetCountByType("datasets");
747 }
748
749 public Long getFacetCountDataverses() {
750 return findFacetCountByType("dataverses");
751 }
752
753 public Long getFacetCountFiles() {
754 return findFacetCountByType("files");
755 }
756
757 public String getSearchFieldRelevance() {
758 return searchFieldRelevance;
759 }
760
761 public void setSearchFieldRelevance(String searchFieldRelevance) {
762 this.searchFieldRelevance = searchFieldRelevance;
763 }
764
765 public String getSearchFieldNameSort() {
766 return searchFieldNameSort;
767 }
768
769 public void setSearchFieldNameSort(String searchFieldNameSort) {
770 this.searchFieldNameSort = searchFieldNameSort;
771 }
772
773 public String getSearchFieldReleaseOrCreateDate() {
774 return searchFieldReleaseOrCreateDate;
775 }
776
777 public String getASCENDING() {
778 return ASCENDING;
779 }
780
781 public String getDESCENDING() {
782 return DESCENDING;
783 }
784
785 public String getSortField() {
786 return sortField;
787 }
788
789 public void setSortField(String sortField) {
790 this.sortField = sortField;
791 }
792
793 public String getSortOrder() {
794 return sortOrder;
795 }
796
797 public void setSortOrder(String sortOrder) {
798 this.sortOrder = sortOrder;
799 }
800
801 public String getCurrentSortFriendly() {
802 String friendlySortField = sortField;
803 String friendlySortOrder = sortOrder;
804 if (sortField.equals(SearchFields.NAME_SORT)) {
805 friendlySortField = "Name";
806 if (sortOrder.equals(ASCENDING)) {
807 friendlySortOrder = " (A-Z)";
808 } else if (sortOrder.equals(DESCENDING)) {
809 friendlySortOrder = " (Z-A)";
810 }
811 } else if (sortField.equals(SearchFields.RELEVANCE)) {
812 friendlySortField = "Relevance";
813 friendlySortOrder = "";
814 }
815 return friendlySortField + friendlySortOrder;
816 }
817
818 public String getCurrentSort() {
819 return sortField + ":" + sortOrder;
820 }
821
822 public boolean isSortedByNameAsc() {
823 return getCurrentSort().equals(searchFieldNameSort + ":" + ASCENDING) ? true : false;
824 }
825
826 public boolean isSortedByNameDesc() {
827 return getCurrentSort().equals(searchFieldNameSort + ":" + DESCENDING) ? true : false;
828 }
829
830 public boolean isSortedByReleaseDateAsc() {
831 return getCurrentSort().equals(searchFieldReleaseOrCreateDate + ":" + ASCENDING) ? true : false;
832 }
833
834 public boolean isSortedByReleaseDateDesc() {
835 return getCurrentSort().equals(searchFieldReleaseOrCreateDate + ":" + DESCENDING) ? true : false;
836 }
837
838 public boolean isSortedByRelevance() {
839 return getCurrentSort().equals(searchFieldRelevance + ":" + DESCENDING) ? true : false;
840 }
841
842 public int getPage() {
843 return page;
844 }
845
846 public void setPage(int page) {
847 this.page = page;
848 }
849
850 // helper method
851 public int getTotalPages() {
852 return ((searchResultsCount - 1) / paginationGuiRows) + 1;
853 }
854
855 public int getPaginationGuiStart() {
856 return paginationGuiStart;
857 }
858
859 public void setPaginationGuiStart(int paginationGuiStart) {
860 this.paginationGuiStart = paginationGuiStart;
861 }
862
863 public int getPaginationGuiEnd() {
864 return paginationGuiEnd;
865 }
866
867 public void setPaginationGuiEnd(int paginationGuiEnd) {
868 this.paginationGuiEnd = paginationGuiEnd;
869 }
870
871 public int getPaginationGuiRows() {
872 return paginationGuiRows;
873 }
874
875 public void setPaginationGuiRows(int paginationGuiRows) {
876 this.paginationGuiRows = paginationGuiRows;
877 }
878
879 public boolean isSolrIsDown() {
880 return solrIsDown;
881 }
882
883 public void setSolrIsDown(boolean solrIsDown) {
884 this.solrIsDown = solrIsDown;
885 }
886
887 public boolean isDebug() {
888 return (debug && session.getUser().isSuperuser()) ||
889 systemConfig.isDebugEnabled();
890 }
891
892 public void setDebug(boolean debug) {
893 this.debug = debug;
894 }
895
896 public List<String> getFilterQueriesDebug() {
897 return filterQueriesDebug;
898 }
899
900 public boolean userLoggedIn() {
901 return session.getUser().isAuthenticated();
902 }
903
904 public boolean publishedSelected() {
905 String expected = SearchFields.PUBLICATION_STATUS + ":\"" + getPUBLISHED() + "\"";
906 logger.info("published expected: " + expected + " actual: " + selectedTypesList);
907 return filterQueries.contains(SearchFields.PUBLICATION_STATUS + ":\"" + getPUBLISHED() + "\"");
908 }
909
910 public boolean unpublishedSelected() {
911 String expected = SearchFields.PUBLICATION_STATUS + ":\"" + getUNPUBLISHED() + "\"";
912 logger.info("unpublished expected: " + expected + " actual: " + selectedTypesList);
913 return filterQueries.contains(SearchFields.PUBLICATION_STATUS + ":\"" + getUNPUBLISHED() + "\"");
914 }
915
916 public String getPUBLISHED() {
917 return IndexServiceBean.getPUBLISHED_STRING();
918 }
919
920 public String getUNPUBLISHED() {
921 return IndexServiceBean.getUNPUBLISHED_STRING();
922 }
923
924 public String getDRAFT() {
925 return IndexServiceBean.getDRAFT_STRING();
926 }
927
928 public String getDEACCESSIONED() {
929 return IndexServiceBean.getDEACCESSIONED_STRING();
930 }
931
932 public List<String> getFriendlyNamesFromFilterQuery(String filterQuery) {
933 String[] parts = filterQuery.split(":");
934 String key = parts[0];
935 String value = parts[1];
936 List<String> friendlyNames = new ArrayList<>();
937 String datasetfieldFriendyName = datasetfieldFriendlyNamesBySolrField.get(key);
938 if (datasetfieldFriendyName != null) {
939 friendlyNames.add(datasetfieldFriendyName);
940 } else {
941 String nonDatasetSolrField = staticSolrFieldFriendlyNamesBySolrField.get(key);
942 if (nonDatasetSolrField != null) {
943 friendlyNames.add(nonDatasetSolrField);
944 } else if (key.equals(SearchFields.PUBLICATION_STATUS)) {
945 /**
946 * @todo Refactor this quick fix for
947 * https://github.com/IQSS/dataverse/issues/618 . We really need
948 * to get rid of all the reflection that's happening with
949 * solrQueryResponse.getStaticSolrFieldFriendlyNamesBySolrField()
950 * and
951 */
952 friendlyNames.add("Publication Status");
953 } else {
954 // meh. better than nuthin'
955 friendlyNames.add(key);
956 }
957 }
958 String noLeadingQuote = value.replaceAll("^\"", "");
959 String noTrailingQuote = noLeadingQuote.replaceAll("\"$", "");
960 String valueWithoutQuotes = noTrailingQuote;
961 friendlyNames.add(valueWithoutQuotes);
962 return friendlyNames;
963 }
964
965 public String getNewSelectedTypes(String typeClicked) {
966 List<String> newTypesSelected = new ArrayList<>();
967 for (String selectedType : selectedTypesList) {
968 if (selectedType.equals(typeClicked)) {
969
970 } else {
971 newTypesSelected.add(selectedType);
972 }
973
974 }
975 if (selectedTypesList.contains(typeClicked)) {
976
977 } else {
978 newTypesSelected.add(typeClicked);
979 }
980
981 String[] arr = newTypesSelected.toArray(new String[newTypesSelected.size()]);
982 return combine(arr, ":");
983
984 }
985
986 public String getErrorFromSolr() {
987 return errorFromSolr;
988 }
989
990 /**
991 * @return the dataverseAlias
992 */
993 public String getDataverseAlias() {
994 return dataverseAlias;
995 }
996
997 /**
998 * @param dataverseAlias the dataverseAlias to set
999 */
1000 public void setDataverseAlias(String dataverseAlias) {
1001 this.dataverseAlias = dataverseAlias;
1002 }
1003
1004 public boolean isTabular(Long fileId) {
1005 if (fileId == null) {
1006 return false;
1007 }
1008
1009 DataFile datafile = dataFileService.find(fileId);
1010
1011 if (datafile == null) {
1012 logger.warning("isTabular: datafile service could not locate a DataFile object for id " + fileId + "!");
1013 return false;
1014 }
1015
1016 return datafile.isTabularData();
1017 }
1018
1019 public SearchException getSearchException() {
1020 return searchException;
1021 }
1022
1023 public String tabularDataDisplayInfo(Long fileId) {
1024 String ret = "";
1025
1026 if (fileId == null) {
1027 return "";
1028 }
1029
1030 DataFile datafile = dataFileService.find(fileId);
1031
1032 if (datafile == null) {
1033 logger.warning("isTabular: datafile service could not locate a DataFile object for id " + fileId + "!");
1034 return "";
1035 }
1036
1037 if (datafile.isTabularData() && datafile.getDataTable() != null) {
1038 DataTable datatable = datafile.getDataTable();
1039 String unf = datatable.getUnf();
1040 Long varNumber = datatable.getVarQuantity();
1041 Long obsNumber = datatable.getCaseQuantity();
1042 if (varNumber != null && varNumber.intValue() != 0) {
1043 ret = ret.concat(varNumber + " Variables");
1044 if (obsNumber != null && obsNumber.intValue() != 0) {
1045 ret = ret.concat(", " + obsNumber + " Observations");
1046 }
1047 ret = ret.concat(" - ");
1048 }
1049 if (unf != null && !unf.equals("")) {
1050 ret = ret.concat("UNF: " + unf);
1051 }
1052 }
1053
1054 return ret;
1055 }
1056
1057 public String dataFileSizeDisplay(Long fileId) {
1058 DataFile datafile = dataFileService.find(fileId);
1059 if (datafile == null) {
1060 logger.warning("isTabular: datafile service could not locate a DataFile object for id " + fileId + "!");
1061 return "";
1062 }
1063
1064 return datafile.getFriendlySize();
1065
1066 }
1067
1068 public String dataFileMD5Display(Long fileId) {
1069 DataFile datafile = dataFileService.find(fileId);
1070 if (datafile == null) {
1071 logger.warning("isTabular: datafile service could not locate a DataFile object for id " + fileId + "!");
1072 return "";
1073 }
1074
1075 if (datafile.getmd5() != null && datafile.getmd5() != "") {
1076 return " MD5: " + datafile.getmd5() + " ";
1077 }
1078
1079 return "";
1080 }
1081
1082 public void setDisplayCardValues() {
1083 for (SolrSearchResult result : searchResultsList) {
1084 boolean valueSet = false;
1085 if (result.getType().equals("dataverses") && result.getEntity() instanceof Dataverse){
1086 result.setDisplayImage(dataverseService.isDataverseCardImageAvailable((Dataverse) result.getEntity(), session.getUser()));
1087 valueSet = true;
1088 } else if (result.getType().equals("datasets") && result.getEntity() instanceof Dataset) {
1089 result.setDisplayImage(datasetService.isDatasetCardImageAvailable(datasetVersionService.find(result.getDatasetVersionId()), session.getUser()));
1090 valueSet = true;
1091 } else if (result.getType().equals("files") && result.getEntity() instanceof DataFile) {
1092 result.setDisplayImage(dataFileService.isThumbnailAvailable((DataFile) result.getEntity(), session.getUser()));
1093 valueSet = true;
1094 }
1095
1096 if (!valueSet) {
1097 logger.warning("Index result / entity mismatch (id:resultType) - " + result.getId() + ":" + result.getType());
1098 }
1099 }
1100 }
1101 }