As of version 1.8, this feature is now part of DSpace XMLUI and doesn't require you to make any modifications to the code. This feature was added in . |
At Leiden University, The Netherlands, we needed a way to change the order of the bitstreams as they are displayed in an easy way.
By default in version 1.3 of DSpace, when you upload more than 1 bitstream for a single item, the bitstreams are presented in the reversed order they were uploaded.
This implementation let's administrators change the display order of bitstreams independedly from their upload order, in an easy way.
The order of bitstreams is defined by using the Basic RDF implementation. The bitstreams are semantically linked to eachother by using in "precedes" predicate. The special class BitstreamArranger manages the ordering of bitstreams.
The modifications were made to Dspace 1.3.2. This is also the version of DSpace where this functionality was tested extensively.
It should be possible to use this with another version of DSpace, and on first glance it should not be hard at all.
This installation does not change any functionality, but it adds functionality potentially.
If you want to use it, write code that makes use of the classes describted below, or implement the order of bitstreams.
See Basic RDF implementation for details on how to do this.
import java.util.ArrayList; import nl.leidenuniv.dspace.rdf.BitstreamArranger; import nl.leidenuniv.dspace.rdf.RDFpredicate; import nl.leidenuniv.dspace.rdf.RDFtriple; |
BitstreamArranger arranger = BitstreamArranger.getBitstreamArranger(); |
RDFpredicate predicate = arranger.precedesPredicate(context); RDFtriple triple = RDFtriple.find(context,bitstream,predicate,Bitstream.class); if (triple != null) { triple.delete(); } |
else if (p.equals("position")) // && AuthorizeManager.isAdmin(context)) { String[] values = request.getParameterValues(p); Bitstream[] newOrder = new Bitstream[values.length]; for (int i = 0;i<values.length;i++) { String v = values[i]; StringTokenizer st = new StringTokenizer(v, "_"); // should use: v.split("_") // Ignore "position" st.nextToken(); // Bundle ID and bitstream ID next int bundleID = Integer.parseInt(st.nextToken()); int bitstreamID = Integer.parseInt(st.nextToken()); String newPos = st.nextToken(); //Bundle bundle = Bundle.find(context, bundleID); Bitstream bitstream = Bitstream.find(context, bitstreamID); String key = String.valueOf(bundleID) + "_" + bitstreamID; if ( ! newPos.equals("N")) { int pos = Integer.parseInt(newPos); if (bitstream != null && newOrder[pos] == null && ! button.equals("submit_delete_bitstream_"+key)) { newOrder[pos] = bitstream; } } } int count = 0; for (int i=0; i<newOrder.length; i++) { if (newOrder[i] != null) count++; } Bitstream[] bitOrder = new Bitstream[count]; for (int i=0, j=0;i<newOrder.length;i++) { if (newOrder[i] != null) { bitOrder[j++] = newOrder[i]; } } arranger.orderListOfOriginalBitstreams(context,item,bitOrder); } |
import org.dspace.core.Context; import nl.leidenuniv.dspace.rdf.BitstreamArranger; |
for (int i = 0; i < bundles.length; i++) { Bitstream[] bitstreams = bundles[i].getBitstreams(); for (int k = 0; k < bitstreams.length; k++) { // Skip internal types if (!bitstreams[k].getFormat().isInternal()) { |
with this:
BitstreamArranger arranger = BitstreamArranger.getBitstreamArranger(); Context context = null; Bitstream[] bitstreams = null; try { context = UIUtil.obtainContext(request); bitstreams = arranger.getOrderedListOfOriginalBistreams(context,item); } catch (SQLException e) { // something wrong... throw new IOException(e.toString()); } for (int k = 0; k < bitstreams.length; k++) { |
and do not forget to balance the number of brackets (remove 2 brackets) near line 718
Make a local copy of this page if you did not do this already
<%@ page import="nl.leidenuniv.dspace.rdf.BitstreamArranger" %> <%@ page import="nl.leidenuniv.dspace.rdf.RDFtriple" %> <%@ page import="nl.leidenuniv.dspace.rdf.RDFpredicate" %> <%@ page import="java.sql.SQLException" %> <%@ page import="org.dspace.app.webui.util.UIUtil" %> <%@ page import="org.dspace.core.Context" %> <%@ page import="org.dspace.content.DSpaceObject" %> |
<th id="t10" class="oddRowOddCol"> </th> <th id="t11" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem6"/></strong></th> |
Bitstream[] bitstreams = bundles(i).getBitstreams();
" near line 335 with the following code:Bitstream[] bitstreams = new Bitstream[0]; boolean isOriginal = bundles[i].getName().equals("ORIGINAL"); int posKnownFrom = 0; int posKnownTill = -1; if (isOriginal) { BitstreamArranger arranger = BitstreamArranger.getBitstreamArranger(); try { Context context = UIUtil.obtainContext(request); bitstreams = arranger.getOrderedListOfOriginalBistreams(context,item); RDFpredicate predicate = arranger.initialPredicate(context); if (bitstreams.length > 0) { RDFtriple triple = RDFtriple.find(context,item,predicate,Bitstream.class); if (triple != null) { DSpaceObject first = triple.getObject(); for (int p=0; p<bitstreams.length; p++) { if (bitstreams[p].equals(first)) { posKnownFrom = p; posKnownTill = p; } } if (posKnownFrom >= 0) { predicate = arranger.precedesPredicate(context); for (int p=posKnownFrom; p<bitstreams.length-1; p++) { triple = RDFtriple.find(context,bitstreams[p],predicate,bitstreams[p+1]); if (triple == null) { break; } posKnownTill++; } } } } } catch (SQLException e) { // do nothing, maybe originals will be retrieved by getBitstreams below } } if (bitstreams.length == 0) { bitstreams = bundles[i].getBitstreams(); } |
<td headers="t10" class="<%= row %>RowEvenCol"> <a target="_blank" href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[j].getID() %>"><fmt:message key="jsp.tools.general.view"/></a> </td> <% if (isOriginal) { %> <td headers="t11" class="<%= row %>RowOddCol" align="center"> <SELECT name="position" onchange="reposition(this)"> <OPTION value="position_<%= key %>_N">-</OPTION> <% for (int k = 0; k < bitstreams.length; k++) { %> <OPTION value="position_<%= key %>_<%= k %>" <% if (j>=posKnownFrom && j<=posKnownTill && (j - posKnownFrom) == k) { %> selected <% } %> ><%= k+1 %></OPTION> <% } %> </SELECT> </TD> |
<td headers="t11" class="<%= row %>RowOddCol"> </td> <td headers="t11" class="<%= row %>RowEvenCol"> </td> |
<a target="_blank" href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[j].getID() %>"><fmt:message key="jsp.tools.general.view"/></a> <input type="submit" name="submit_delete_bitstream_<%= key %>" value="<fmt:message key="jsp.tools.general.remove"/>" /> |
with this:
<input type="submit" name="submit_delete_bitstream_<%= key %>" value="<fmt:message key="jsp.tools.general.remove"/>" /> |
<SCRIPT language="JavaScript"> var storedPos = new Array(); function reposition(anElement) { var allPosEl = document.getElementsByName('position'); var oldPos, newPos; var indexOfEl = 0; var hiPos = 0; for (var i=0;i<allPosEl.length;i++) { if (allPosEl[i] == anElement) { indexOfEl = i; } else { if (allPosEl[i].selectedIndex > hiPos) { hiPos = allPosEl[i].selectedIndex; } } } oldPos = storedPos[indexOfEl]; newPos = anElement.selectedIndex; if (oldPos == newPos) return; if (newPos > hiPos + 1) { anElement.selectedIndex = hiPos + 1; newPos = hiPos + 1; } if (newPos == 0) { for (var i=0;i<allPosEl.length;i++) { if (allPosEl[i] != anElement) { var pos = allPosEl[i].selectedIndex; if (pos > oldPos) { allPosEl[i].selectedIndex -= 1; } } } } else if (oldPos == 0) { for (var i=0;i<allPosEl.length;i++) { if (allPosEl[i] != anElement) { var pos = allPosEl[i].selectedIndex; if (pos >= newPos) { allPosEl[i].selectedIndex += 1; } } } } else { for (var i=0;i<allPosEl.length;i++) { if (allPosEl[i] != anElement) { var pos = allPosEl[i].selectedIndex; if (oldPos > newPos) { if (pos >= newPos && pos < oldPos) { allPosEl[i].selectedIndex += 1; } } else { if (pos > oldPos && pos <= newPos) { allPosEl[i].selectedIndex -= 1; } } } } } storePositions(); } function storePositions() { var allPosEl = document.getElementsByName('position'); for (var i=0;i<allPosEl.length;i++) { storedPos[i] = allPosEl[i].selectedIndex; } } storePositions(); </SCRIPT> |
Do the stuff you normally do when deploying a new version of DSpace.
Besides implementing new functionality using this basic RDF implementation, there are two obvious omissions:
If you need help, or have any comments, or you just want to inform me that you (are going to) use this, please contact me at schaik (at) library.leidenuniv.nl