001: /*
002: * WithdrawnItems.java
003: *
004: * Version: $Revision: 1.0 $
005: *
006: * Date: $Date: 2007/08/28 10:00:00 $
007: *
008: * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
009: * Institute of Technology. All rights reserved.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions are
013: * met:
014: *
015: * - Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * - Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in the
020: * documentation and/or other materials provided with the distribution.
021: *
022: * - Neither the name of the Hewlett-Packard Company nor the name of the
023: * Massachusetts Institute of Technology nor the names of their
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
030: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
032: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
033: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
034: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
036: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
037: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
038: * DAMAGE.
039: */
040:
041: package org.dspace.app.xmlui.aspect.administrative;
042:
043: import java.io.IOException;
044: import java.io.Serializable;
045: import java.sql.SQLException;
046: import java.util.HashMap;
047: import java.util.Locale;
048: import java.util.Map;
049: import java.util.Set;
050:
051: import org.apache.cocoon.caching.CacheableProcessingComponent;
052: import org.apache.cocoon.environment.ObjectModelHelper;
053: import org.apache.cocoon.environment.Request;
054: import org.apache.cocoon.util.HashUtil;
055: import org.apache.excalibur.source.SourceValidity;
056: import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
057: import org.dspace.app.xmlui.utils.ContextUtil;
058: import org.dspace.app.xmlui.utils.DSpaceValidity;
059: import org.dspace.app.xmlui.utils.HandleUtil;
060: import org.dspace.app.xmlui.utils.RequestUtils;
061: import org.dspace.app.xmlui.utils.UIException;
062: import org.dspace.app.xmlui.wing.Message;
063: import org.dspace.app.xmlui.wing.WingException;
064: import org.dspace.app.xmlui.wing.element.Body;
065: import org.dspace.app.xmlui.wing.element.Cell;
066: import org.dspace.app.xmlui.wing.element.Division;
067: import org.dspace.app.xmlui.wing.element.List;
068: import org.dspace.app.xmlui.wing.element.PageMeta;
069: import org.dspace.app.xmlui.wing.element.Para;
070: import org.dspace.app.xmlui.wing.element.ReferenceSet;
071: import org.dspace.app.xmlui.wing.element.Row;
072: import org.dspace.app.xmlui.wing.element.Select;
073: import org.dspace.app.xmlui.wing.element.Table;
074: import org.dspace.authorize.AuthorizeException;
075: import org.dspace.browse.BrowseEngine;
076: import org.dspace.browse.BrowseException;
077: import org.dspace.browse.BrowseIndex;
078: import org.dspace.browse.BrowseInfo;
079: import org.dspace.browse.BrowseItem;
080: import org.dspace.browse.BrowserScope;
081: import org.dspace.sort.SortOption;
082: import org.dspace.sort.SortException;
083: import org.dspace.content.Collection;
084: import org.dspace.content.Community;
085: import org.dspace.content.DCDate;
086: import org.dspace.content.DSpaceObject;
087: import org.dspace.core.ConfigurationManager;
088: import org.dspace.core.Context;
089: import org.xml.sax.SAXException;
090:
091: /**
092: * Implements all the browse functionality (browse by title, subject, authors,
093: * etc.) The types of browse available are configurable by the implementor. See
094: * dspace.cfg and documentation for instructions on how to configure.
095: *
096: * @author Graham Triggs
097: */
098: public class WithdrawnItems extends AbstractDSpaceTransformer implements
099: CacheableProcessingComponent {
100: /**
101: * Static Messages for common text
102: */
103: private final static Message T_dspace_home = message("xmlui.general.dspace_home");
104:
105: private final static Message T_go = message("xmlui.general.go");
106:
107: private final static Message T_update = message("xmlui.general.update");
108:
109: private final static Message T_choose_month = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.choose_month");
110:
111: private final static Message T_choose_year = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.choose_year");
112:
113: private final static Message T_jump_year = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_year");
114:
115: private final static Message T_jump_year_help = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_year_help");
116:
117: private final static Message T_jump_select = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_select");
118:
119: private final static Message T_starts_with = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.starts_with");
120:
121: private final static Message T_starts_with_help = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.starts_with_help");
122:
123: private final static Message T_sort_by = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.sort_by");
124:
125: private final static Message T_order = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.order");
126:
127: private final static Message T_rpp = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.rpp");
128:
129: private final static Message T_etal = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.etal");
130:
131: private final static Message T_etal_all = message("xmlui.ArtifactBrowser.ConfigurableBrowse.etal.all");
132:
133: private final static Message T_order_asc = message("xmlui.ArtifactBrowser.ConfigurableBrowse.order.asc");
134:
135: private final static Message T_order_desc = message("xmlui.ArtifactBrowser.ConfigurableBrowse.order.desc");
136:
137: private final static String WITHDRAWN_URL_BASE = "withdrawn";
138:
139: /**
140: * These variables dictate when the drop down list of years is to break from
141: * 1 year increments, to 5 year increments, to 10 year increments, and
142: * finally to stop.
143: */
144: private static final int ONE_YEAR_LIMIT = 10;
145:
146: private static final int FIVE_YEAR_LIMIT = 30;
147:
148: private static final int TEN_YEAR_LIMIT = 100;
149:
150: /** Cached validity object */
151: private SourceValidity validity;
152:
153: /** Cached UI parameters, results and messages */
154: private BrowseParams userParams;
155:
156: private BrowseInfo browseInfo;
157:
158: private Message titleMessage = null;
159: private Message trailMessage = null;
160:
161: public Serializable getKey() {
162: try {
163: BrowseParams params = getUserParams();
164:
165: String key = params.getKey();
166:
167: if (key != null) {
168: DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
169: if (dso != null)
170: key += "-" + dso.getHandle();
171:
172: return HashUtil.hash(key);
173: }
174: } catch (Exception e) {
175: // Ignore all errors and just don't cache.
176: }
177:
178: return "0";
179: }
180:
181: public SourceValidity getValidity() {
182: if (validity == null) {
183: try {
184: DSpaceValidity validity = new DSpaceValidity();
185: DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
186:
187: if (dso != null)
188: validity.add(dso);
189:
190: BrowseInfo info = getBrowseInfo();
191:
192: // Are we browsing items, or unique metadata?
193: if (isItemBrowse(info)) {
194: // Add the browse items to the validity
195: for (BrowseItem item : (java.util.List<BrowseItem>) info
196: .getResults()) {
197: validity.add(item);
198: }
199: } else {
200: // Add the metadata to the validity
201: for (String singleEntry : browseInfo
202: .getStringResults()) {
203: validity.add(singleEntry);
204: }
205: }
206: } catch (Exception e) {
207: // Just ignore all errors and return an invalid cache.
208: }
209:
210: }
211:
212: return this .validity;
213: }
214:
215: /**
216: * Add Page metadata.
217: */
218: public void addPageMeta(PageMeta pageMeta) throws SAXException,
219: WingException, UIException, SQLException, IOException,
220: AuthorizeException {
221: BrowseInfo info = getBrowseInfo();
222:
223: // Get the name of the index
224: String type = info.getBrowseIndex().getName();
225:
226: pageMeta.addMetadata("title").addContent(getTitleMessage(info));
227:
228: DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
229:
230: pageMeta.addTrailLink(contextPath + "/", T_dspace_home);
231: if (dso != null)
232: HandleUtil.buildHandleTrail(dso, pageMeta, contextPath);
233:
234: pageMeta.addTrail().addContent(getTrailMessage(info));
235: }
236:
237: /**
238: * Add the browse-title division.
239: */
240: public void addBody(Body body) throws SAXException, WingException,
241: UIException, SQLException, IOException, AuthorizeException {
242: BrowseParams params = getUserParams();
243: BrowseInfo info = getBrowseInfo();
244:
245: String type = "withdrawn";
246:
247: // Build the DRI Body
248: Division div = body.addDivision("browse-by-" + type, "primary");
249:
250: div.setHead(getTitleMessage(info));
251:
252: // Build the internal navigation (jump lists)
253: addBrowseJumpNavigation(div, info, params);
254:
255: // Build the sort and display controls
256: addBrowseControls(div, info, params);
257:
258: // This div will hold the browsing results
259: Division results = div.addDivision("browse-by-" + type
260: + "-results", "primary");
261:
262: // Add the pagination
263: if (info.getTotal() <= 0) {
264: results.setSimplePagination(0, 0, 0, null, null);
265:
266: } else {
267: results.setSimplePagination(info.getTotal(), browseInfo
268: .getOverallPosition() + 1, browseInfo
269: .getOverallPosition()
270: + browseInfo.getResultCount(), getPreviousPageURL(
271: params, info), getNextPageURL(params, info));
272: }
273:
274: // Reference all the browsed items
275: ReferenceSet referenceSet = results.addReferenceSet(
276: "browse-by-" + type, ReferenceSet.TYPE_SUMMARY_LIST,
277: type, null);
278:
279: // Are we browsing items, or unique metadata?
280: if (isItemBrowse(info)) {
281: // Add the items to the browse results
282: for (BrowseItem item : (java.util.List<BrowseItem>) info
283: .getResults()) {
284: referenceSet.addReference(item);
285: }
286: } else // browsing a list of unique metadata entries
287: {
288: // Create a table for the results
289: Table singleTable = results.addTable("browse-by-" + type
290: + "-results", browseInfo.getResultCount() + 1, 1);
291:
292: // Add the column heading
293: singleTable.addRow(Row.ROLE_HEADER).addCell().addContent(
294: message("xmlui.ArtifactBrowser.ConfigurableBrowse."
295: + type + ".column_heading"));
296:
297: // Iterate each result
298: for (String singleEntry : browseInfo.getStringResults()) {
299: // Create a Map of the query parameters for the link
300: Map<String, String> queryParams = new HashMap<String, String>();
301: queryParams.put(BrowseParams.TYPE, URLEncode(type));
302: queryParams.put(BrowseParams.FILTER_VALUE,
303: URLEncode(singleEntry));
304:
305: // Create an entry in the table, and a linked entry
306: Cell cell = singleTable.addRow().addCell();
307: cell.addXref(super .generateURL(WITHDRAWN_URL_BASE,
308: queryParams), singleEntry);
309: }
310: }
311: }
312:
313: /**
314: * Recycle
315: */
316: public void recycle() {
317: this .validity = null;
318: this .userParams = null;
319: this .browseInfo = null;
320: this .titleMessage = null;
321: this .trailMessage = null;
322: super .recycle();
323: }
324:
325: /**
326: * Makes the jump-list navigation for the results
327: *
328: * @param div
329: * @param info
330: * @param params
331: * @throws WingException
332: */
333: private void addBrowseJumpNavigation(Division div, BrowseInfo info,
334: BrowseParams params) throws WingException {
335: // Get the name of the index
336: String type = info.getBrowseIndex().getName();
337:
338: // Prepare a Map of query parameters required for all links
339: Map<String, String> queryParams = new HashMap<String, String>();
340: queryParams.putAll(params.getCommonParameters());
341: queryParams.putAll(params.getControlParameters());
342:
343: // Navigation aid (really this is a poor version of pagination)
344: Division jump = div.addInteractiveDivision("browse-navigation",
345: WITHDRAWN_URL_BASE, Division.METHOD_POST,
346: "secondary navigation");
347:
348: // Add all the query parameters as hidden fields on the form
349: for (String key : queryParams.keySet())
350: jump.addHidden(key).setValue(queryParams.get(key));
351:
352: // If this is a date based browse, render the date navigation
353: if (isSortedByDate(info)) {
354: Para jumpForm = jump.addPara();
355:
356: // Create a select list to choose a month
357: jumpForm.addContent(T_jump_select);
358: Select month = jumpForm.addSelect(BrowseParams.MONTH);
359: month.addOption(false, "-1", T_choose_month);
360: for (int i = 1; i <= 12; i++) {
361: month.addOption(false, String.valueOf(i), DCDate
362: .getMonthName(i, Locale.getDefault()));
363: }
364:
365: // Create a select list to choose a year
366: Select year = jumpForm.addSelect(BrowseParams.YEAR);
367: year.addOption(false, "-1", T_choose_year);
368: int currentYear = DCDate.getCurrent().getYear();
369: int i = currentYear;
370:
371: // Calculate where to move from 1, 5 to 10 year jumps
372: int oneYearBreak = ((currentYear - ONE_YEAR_LIMIT) / 5) * 5;
373: int fiveYearBreak = ((currentYear - FIVE_YEAR_LIMIT) / 10) * 10;
374: int tenYearBreak = (currentYear - TEN_YEAR_LIMIT);
375: do {
376: year.addOption(false, String.valueOf(i), String
377: .valueOf(i));
378:
379: if (i <= fiveYearBreak)
380: i -= 10;
381: else if (i <= oneYearBreak)
382: i -= 5;
383: else
384: i--;
385: } while (i > tenYearBreak);
386:
387: // Create a free text entry box for the year
388: jumpForm = jump.addPara();
389: jumpForm.addContent(T_jump_year);
390: jumpForm.addText("start_with").setHelp(T_jump_year_help);
391:
392: jumpForm.addButton("submit").setValue(T_go);
393: } else {
394: // Create a clickable list of the alphabet
395: List jumpList = jump.addList("jump-list", List.TYPE_SIMPLE,
396: "alphabet");
397: for (char c = 'A'; c <= 'Z'; c++) {
398: Map<String, String> cQuery = new HashMap<String, String>(
399: queryParams);
400: cQuery.put(BrowseParams.STARTS_WITH, Character
401: .toString(c));
402: jumpList.addItemXref(super .generateURL(
403: WITHDRAWN_URL_BASE, cQuery), Character
404: .toString(c));
405: }
406:
407: // Create a free text field for the initial characters
408: Para jumpForm = jump.addPara();
409: jumpForm.addContent(T_starts_with);
410: jumpForm.addText(BrowseParams.STARTS_WITH).setHelp(
411: T_starts_with_help);
412:
413: jumpForm.addButton("submit").setValue(T_go);
414: }
415: }
416:
417: /**
418: * Add the controls to changing sorting and display options.
419: *
420: * @param div
421: * @param info
422: * @param params
423: * @throws WingException
424: */
425: private void addBrowseControls(Division div, BrowseInfo info,
426: BrowseParams params) throws WingException {
427: // Prepare a Map of query parameters required for all links
428: Map<String, String> queryParams = new HashMap<String, String>();
429:
430: queryParams.putAll(params.getCommonParameters());
431:
432: Division controls = div.addInteractiveDivision(
433: "browse-controls", WITHDRAWN_URL_BASE,
434: Division.METHOD_POST, "browse controls");
435:
436: // Add all the query parameters as hidden fields on the form
437: for (String key : queryParams.keySet())
438: controls.addHidden(key).setValue(queryParams.get(key));
439:
440: Para controlsForm = controls.addPara();
441:
442: // If we are browsing a list of items
443: if (isItemBrowse(info)) // && info.isSecondLevel()
444: {
445: try {
446: // Create a drop down of the different sort columns available
447: Set<SortOption> sortOptions = SortOption
448: .getSortOptions();
449:
450: // Only generate the list if we have multiple columns
451: if (sortOptions.size() > 1) {
452: controlsForm.addContent(T_sort_by);
453: Select sortSelect = controlsForm
454: .addSelect(BrowseParams.SORT_BY);
455:
456: for (SortOption so : sortOptions) {
457: sortSelect
458: .addOption(
459: so.equals(info.getSortOption()),
460: so.getNumber(),
461: message("xmlui.ArtifactBrowser.ConfigurableBrowse.sort_by."
462: + so.getName()));
463: }
464: }
465: } catch (SortException se) {
466: throw new WingException("Unable to get sort options",
467: se);
468: }
469: }
470:
471: // Create a control to changing ascending / descending order
472: controlsForm.addContent(T_order);
473: Select orderSelect = controlsForm.addSelect(BrowseParams.ORDER);
474: orderSelect.addOption("ASC".equals(params.scope.getOrder()),
475: "ASC", T_order_asc);
476: orderSelect.addOption("DESC".equals(params.scope.getOrder()),
477: "DESC", T_order_desc);
478:
479: // Create a control for the number of records to display
480: controlsForm.addContent(T_rpp);
481: Select rppSelect = controlsForm
482: .addSelect(BrowseParams.RESULTS_PER_PAGE);
483: for (int i = 5; i <= 100; i += 5) {
484: rppSelect.addOption((i == info.getResultsPerPage()), i,
485: Integer.toString(i));
486: }
487:
488: // Create a control for the number of authors per item to display
489: // FIXME This is currently disabled, as the supporting functionality
490: // is not currently present in xmlui
491: //if (isItemBrowse(info))
492: //{
493: // controlsForm.addContent(T_etal);
494: // Select etalSelect = controlsForm.addSelect(BrowseParams.ETAL);
495: //
496: // etalSelect.addOption((info.getEtAl() < 0), 0, T_etal_all);
497: // etalSelect.addOption(1 == info.getEtAl(), 1, Integer.toString(1));
498: //
499: // for (int i = 5; i <= 50; i += 5)
500: // {
501: // etalSelect.addOption(i == info.getEtAl(), i, Integer.toString(i));
502: // }
503: //}
504:
505: controlsForm.addButton("update").setValue(T_update);
506: }
507:
508: /**
509: * The URL query string of of the previous page.
510: *
511: * Note: the query string does not start with a "?" or "&" those need to be
512: * added as appropriate by the caller.
513: */
514: private String getPreviousPageURL(BrowseParams params,
515: BrowseInfo info) throws SQLException, UIException {
516: // Don't create a previous page link if this is the first page
517: if (info.isFirst())
518: return null;
519:
520: Map<String, String> parameters = new HashMap<String, String>();
521: parameters.putAll(params.getCommonParameters());
522: parameters.putAll(params.getControlParameters());
523:
524: if (info.hasPrevPage()) {
525: parameters.put(BrowseParams.OFFSET, URLEncode(String
526: .valueOf(info.getPrevOffset())));
527: }
528:
529: return super .generateURL(WITHDRAWN_URL_BASE, parameters);
530:
531: }
532:
533: /**
534: * The URL query string of of the next page.
535: *
536: * Note: the query string does not start with a "?" or "&" those need to be
537: * added as appropriate by the caller.
538: */
539: private String getNextPageURL(BrowseParams params, BrowseInfo info)
540: throws SQLException, UIException {
541: // Don't create a next page link if this is the last page
542: if (info.isLast())
543: return null;
544:
545: Map<String, String> parameters = new HashMap<String, String>();
546: parameters.putAll(params.getCommonParameters());
547: parameters.putAll(params.getControlParameters());
548:
549: if (info.hasNextPage()) {
550: parameters.put(BrowseParams.OFFSET, URLEncode(String
551: .valueOf(info.getNextOffset())));
552: }
553:
554: return super .generateURL(WITHDRAWN_URL_BASE, parameters);
555: }
556:
557: /**
558: * Get the query parameters supplied to the browse.
559: *
560: * @return
561: * @throws SQLException
562: * @throws UIException
563: */
564: private BrowseParams getUserParams() throws SQLException,
565: UIException {
566: if (this .userParams != null)
567: return this .userParams;
568:
569: Context context = ContextUtil.obtainContext(objectModel);
570: Request request = ObjectModelHelper.getRequest(objectModel);
571:
572: BrowseParams params = new BrowseParams();
573:
574: params.month = request.getParameter(BrowseParams.MONTH);
575: params.year = request.getParameter(BrowseParams.YEAR);
576: params.etAl = RequestUtils.getIntParameter(request,
577: BrowseParams.ETAL);
578:
579: params.scope = new BrowserScope(context);
580:
581: // Are we in a community or collection?
582: DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
583: if (dso instanceof Community)
584: params.scope.setCommunity((Community) dso);
585: if (dso instanceof Collection)
586: params.scope.setCollection((Collection) dso);
587:
588: try {
589: int sortBy = RequestUtils.getIntParameter(request,
590: BrowseParams.SORT_BY);
591:
592: BrowseIndex bi = BrowseIndex.getWithdrawnBrowseIndex();
593:
594: // If we don't have a sort column
595: if (sortBy == -1) {
596: // Get the default one
597: SortOption so = bi.getSortOption();
598: if (so != null) {
599: sortBy = so.getNumber();
600: }
601: }
602:
603: params.scope.setBrowseIndex(bi);
604: params.scope.setSortBy(sortBy);
605:
606: params.scope.setJumpToItem(RequestUtils.getIntParameter(
607: request, BrowseParams.JUMPTO_ITEM));
608: params.scope.setOrder(request
609: .getParameter(BrowseParams.ORDER));
610: params.scope.setOffset(RequestUtils.getIntParameter(
611: request, BrowseParams.OFFSET));
612: params.scope.setResultsPerPage(RequestUtils
613: .getIntParameter(request,
614: BrowseParams.RESULTS_PER_PAGE));
615: params.scope.setStartsWith(request
616: .getParameter(BrowseParams.STARTS_WITH));
617: params.scope.setFilterValue(request
618: .getParameter(BrowseParams.FILTER_VALUE));
619: params.scope.setJumpToValue(request
620: .getParameter(BrowseParams.JUMPTO_VALUE));
621: params.scope.setJumpToValueLang(request
622: .getParameter(BrowseParams.JUMPTO_VALUE_LANG));
623: params.scope.setFilterValueLang(request
624: .getParameter(BrowseParams.FILTER_VALUE_LANG));
625:
626: // Filtering to a value implies this is a second level browse
627: if (params.scope.getFilterValue() != null)
628: params.scope.setBrowseLevel(1);
629:
630: // if year and perhaps month have been selected, we translate these
631: // into "startsWith"
632: // if startsWith has already been defined then it is overwritten
633: if (params.year != null && !"".equals(params.year)
634: && !"-1".equals(params.year)) {
635: String startsWith = params.year;
636: if ((params.month != null)
637: && !"-1".equals(params.month)
638: && !"".equals(params.month)) {
639: // subtract 1 from the month, so the match works
640: // appropriately
641: if ("ASC".equals(params.scope.getOrder())) {
642: params.month = Integer.toString((Integer
643: .parseInt(params.month) - 1));
644: }
645:
646: // They've selected a month as well
647: if (params.month.length() == 1) {
648: // Ensure double-digit month number
649: params.month = "0" + params.month;
650: }
651:
652: startsWith = params.year + "-" + params.month;
653:
654: if ("ASC".equals(params.scope.getOrder())) {
655: startsWith = startsWith + "-32";
656: }
657: }
658:
659: params.scope.setStartsWith(startsWith);
660: }
661: } catch (BrowseException bex) {
662: throw new UIException("Unable to create browse parameters",
663: bex);
664: }
665:
666: this .userParams = params;
667: return params;
668: }
669:
670: /**
671: * Get the results of the browse. If the results haven't been generated yet,
672: * then this will perform the browse.
673: *
674: * @return
675: * @throws SQLException
676: * @throws UIException
677: */
678: private BrowseInfo getBrowseInfo() throws SQLException, UIException {
679: if (this .browseInfo != null)
680: return this .browseInfo;
681:
682: Context context = ContextUtil.obtainContext(objectModel);
683:
684: // Get the parameters we will use for the browse
685: // (this includes a browse scope)
686: BrowseParams params = getUserParams();
687:
688: try {
689: // Create a new browse engine, and perform the browse
690: BrowseEngine be = new BrowseEngine(context);
691: this .browseInfo = be.browse(params.scope);
692:
693: // figure out the setting for author list truncation
694: if (params.etAl < 0) {
695: // there is no limit, or the UI says to use the default
696: int etAl = ConfigurationManager
697: .getIntProperty("webui.browse.author-limit");
698: if (etAl != 0) {
699: this .browseInfo.setEtAl(etAl);
700: }
701:
702: } else if (params.etAl == 0) // 0 is the user setting for unlimited
703: {
704: this .browseInfo.setEtAl(-1); // but -1 is the application
705: // setting for unlimited
706: } else
707: // if the user has set a limit
708: {
709: this .browseInfo.setEtAl(params.etAl);
710: }
711: } catch (BrowseException bex) {
712: throw new UIException("Unable to process browse", bex);
713: }
714:
715: return this .browseInfo;
716: }
717:
718: /**
719: * Is this a browse on a list of items, or unique metadata values?
720: *
721: * @param info
722: * @return
723: */
724: private boolean isItemBrowse(BrowseInfo info) {
725: return info.getBrowseIndex().isItemIndex()
726: || info.isSecondLevel();
727: }
728:
729: /**
730: * Is this browse sorted by date?
731: * @param info
732: * @return
733: */
734: private boolean isSortedByDate(BrowseInfo info) {
735: return info.getSortOption().isDate()
736: || (info.getBrowseIndex().isDate() && info
737: .getSortOption().isDefault());
738: }
739:
740: private Message getTitleMessage(BrowseInfo info) {
741: if (titleMessage == null) {
742: BrowseIndex bix = info.getBrowseIndex();
743:
744: // For a second level browse (ie. items for author),
745: // get the value we are focussing on (ie. author).
746: // (empty string if none).
747: String value = (info.hasValue() ? "\"" + info.getValue()
748: + "\"" : "");
749:
750: // Get the name of any scoping element (collection / community)
751: String scopeName = "";
752:
753: if (info.getBrowseContainer() != null)
754: scopeName = info.getBrowseContainer().getName();
755: else
756: scopeName = "";
757:
758: if (bix.isMetadataIndex()) {
759: titleMessage = message(
760: "xmlui.ArtifactBrowser.ConfigurableBrowse.title.metadata."
761: + bix.getName()).parameterize(
762: scopeName, value);
763: } else if (info.getSortOption() != null) {
764: titleMessage = message(
765: "xmlui.ArtifactBrowser.ConfigurableBrowse.title.item."
766: + info.getSortOption().getName())
767: .parameterize(scopeName, value);
768: } else {
769: titleMessage = message(
770: "xmlui.ArtifactBrowser.ConfigurableBrowse.title.item."
771: + bix.getSortOption().getName())
772: .parameterize(scopeName, value);
773: }
774: }
775:
776: return titleMessage;
777: }
778:
779: private Message getTrailMessage(BrowseInfo info) {
780: if (trailMessage == null) {
781: BrowseIndex bix = info.getBrowseIndex();
782:
783: // Get the name of any scoping element (collection / community)
784: String scopeName = "";
785:
786: if (info.getBrowseContainer() != null)
787: scopeName = info.getBrowseContainer().getName();
788: else
789: scopeName = "";
790:
791: if (bix.isMetadataIndex()) {
792: titleMessage = message(
793: "xmlui.ArtifactBrowser.ConfigurableBrowse.trail.metadata."
794: + bix.getName())
795: .parameterize(scopeName);
796: } else if (info.getSortOption() != null) {
797: titleMessage = message(
798: "xmlui.ArtifactBrowser.ConfigurableBrowse.trail.item."
799: + info.getSortOption().getName())
800: .parameterize(scopeName);
801: } else {
802: titleMessage = message(
803: "xmlui.ArtifactBrowser.ConfigurableBrowse.trail.item."
804: + bix.getSortOption().getName())
805: .parameterize(scopeName);
806: }
807: }
808:
809: return trailMessage;
810: }
811: }
812:
813: /*
814: * Helper class to track browse parameters
815: */
816: class BrowseParams {
817: String month;
818:
819: String year;
820:
821: int etAl;
822:
823: BrowserScope scope;
824:
825: final static String MONTH = "month";
826:
827: final static String YEAR = "year";
828:
829: final static String ETAL = "etal";
830:
831: final static String TYPE = "type";
832:
833: final static String JUMPTO_ITEM = "focus";
834:
835: final static String JUMPTO_VALUE = "vfocus";
836:
837: final static String JUMPTO_VALUE_LANG = "vfocus_lang";
838:
839: final static String ORDER = "order";
840:
841: final static String OFFSET = "offset";
842:
843: final static String RESULTS_PER_PAGE = "rpp";
844:
845: final static String SORT_BY = "sort_by";
846:
847: final static String STARTS_WITH = "starts_with";
848:
849: final static String FILTER_VALUE = "value";
850:
851: final static String FILTER_VALUE_LANG = "value_lang";
852:
853: /*
854: * Creates a map of the browse options common to all pages (type / value /
855: * value language)
856: */
857: Map<String, String> getCommonParameters() throws UIException {
858: Map<String, String> paramMap = new HashMap<String, String>();
859:
860: if (scope.getFilterValue() != null) {
861: paramMap.put(BrowseParams.FILTER_VALUE,
862: AbstractDSpaceTransformer.URLEncode(scope
863: .getFilterValue()));
864: }
865:
866: if (scope.getFilterValueLang() != null) {
867: paramMap.put(BrowseParams.FILTER_VALUE_LANG,
868: AbstractDSpaceTransformer.URLEncode(scope
869: .getFilterValueLang()));
870: }
871:
872: return paramMap;
873: }
874:
875: /*
876: * Creates a Map of the browse control options (sort by / ordering / results
877: * per page / authors per item)
878: */
879: Map<String, String> getControlParameters() throws UIException {
880: Map<String, String> paramMap = new HashMap<String, String>();
881:
882: paramMap.put(BrowseParams.SORT_BY, Integer.toString(this .scope
883: .getSortBy()));
884: paramMap.put(BrowseParams.ORDER, AbstractDSpaceTransformer
885: .URLEncode(this .scope.getOrder()));
886: paramMap.put(BrowseParams.RESULTS_PER_PAGE, Integer
887: .toString(this .scope.getResultsPerPage()));
888: paramMap.put(BrowseParams.ETAL, Integer.toString(this .etAl));
889:
890: return paramMap;
891: }
892:
893: String getKey() {
894: try {
895: String key = "";
896:
897: key += "-" + scope.getBrowseIndex().getName();
898: key += "-" + scope.getBrowseLevel();
899: key += "-" + scope.getStartsWith();
900: key += "-" + scope.getResultsPerPage();
901: key += "-" + scope.getSortBy();
902: key += "-" + scope.getSortOption().getNumber();
903: key += "-" + scope.getOrder();
904: key += "-" + scope.getOffset();
905: key += "-" + scope.getJumpToItem();
906: key += "-" + scope.getFilterValue();
907: key += "-" + scope.getFilterValueLang();
908: key += "-" + scope.getJumpToValue();
909: key += "-" + scope.getJumpToValueLang();
910: key += "-" + etAl;
911:
912: return key;
913: } catch (Exception e) {
914: return null; // ignore exception and return no key
915: }
916: }
917: };
|