Ying created DS-1352:
------------------------
Summary: Itemimport replace issue
Key: DS-1352
URL: https://jira.duraspace.org/browse/DS-1352
Project: DSpace
Issue Type: Bug
Components: DSpace API
Affects Versions: 1.7.2
Reporter: Ying
We use DSpace batch import a lot and sometimes have to replace the
items to fix the metadata or content issues. However, we found the
replacement in itemimport is actually deleting the old item, adding a
new one and then having the old handles back to the item. It generates
several problems. First, it will delete all relationships, for
example, if the item is mapped to another collection, the mapping will
be gone after replacement. Also, when deleting the item, the item's
internal ID changed and it losts its connection with statistical
history. Some of our statistics will show replaced items internal ID
number since the ID changed and it can't match the item title.
Currently, we fixed that in our DSpace as below. Instead of delete-add items,
we cleared the metadata and contents of the items and replace that with given
info.
1. Defining a cleanItem method in Item.java
public void cleanItem() throws SQLException, AuthorizeException, IOException
{
// Check authorisation here. If we don't, it may happen that we remove
the
// metadata but when getting to the point of removing the bundles we
get an exception
// leaving the database in an inconsistent state
AuthorizeManager.authorizeAction(ourContext, this, Constants.ADD);
log.info(LogManager.getHeader(ourContext, "clean_item", "item_id=" +
getID()));
// Remove from cache
ourContext.removeCached(this, getID());
try
{
// Remove from indices and we will index the new data later
IndexBrowse ib = new IndexBrowse(ourContext);
ib.itemRemoved(this);
}
catch (BrowseException e)
{
log.error("caught exception: ", e);
throw new SQLException(e.getMessage(), e);
}
// Delete the metadata (in memory; will write to db when update is
called)
List<DCValue> values = new ArrayList<DCValue>();
setMetadata(values);
// Remove bundles
Bundle[] bunds = getBundles();
for (int i = 0; i < bunds.length; i++)
{
removeBundle(bunds[i]);
}
}
2. Add replaceItem in the ItemImport.java -
private void replaceItem(Context c, Item myitem, String path, String
itemname)
throws AuthorizeException, SQLException, IOException, SAXException,
ParserConfigurationException, TransformerException
{
System.out.println("Replacing item with directory " + itemname);
// before cleanup the metadata, save the fields that would normally be
generated by InstallItem.populateMetadata()
List<DCValue> saved = new ArrayList<DCValue>();
saved.addAll(Arrays.asList(myitem.getMetadata("dc","date","available",Item.ANY)));
saved.addAll(Arrays.asList(myitem.getMetadata("dc","date","accessioned",Item.ANY)));
saved.addAll(Arrays.asList(myitem.getMetadata("dc","date","issued",Item.ANY)));
saved.addAll(Arrays.asList(myitem.getMetadata("dc","description","provenance",Item.ANY)));
if (! isTest) {
myitem.cleanItem();
} else {
myitem = null;
}
// load replacement metadata
loadMetadata(c, myitem, path + File.separatorChar + itemname +
File.separatorChar);
// restore each saved metadata value
if (! isTest) {
for (DCValue val : saved) {
// disable special treatment of provenance
/*if (val.schema.equals("dc") &&
val.element.equals("description") && val.qualifier.equals("provenance")) {
// for provenance, always restore it unless the exact same
value is already present from replacement
boolean alreadyPresent = false;
for (DCValue existing :
myitem.getMetadata("dc","description","provenance",Item.ANY)) {
if (existing.value.equals(val.value)) {
alreadyPresent = true;
break;
}
}
if (! alreadyPresent) {
myitem.addMetadata(val.schema, val.element,
val.qualifier, val.language, val.value);
}
} else*/ if (myitem.getMetadata(val.schema, val.element,
val.qualifier, Item.ANY).length == 0) {
// for non-provenance, only restore if replacement didn't
have any values for this element
myitem.addMetadata(val.schema, val.element, val.qualifier,
val.language, val.value);
}
}
// make a new provenance item and add it
String now = DCDate.getCurrent().toString();
EPerson e = c.getCurrentUser();
String prov = "Item contents replaced by "+e.getFullName()+"
("+e.getEmail()+") on "+now+"\n";
myitem.addMetadata("dc", "description", "provenance", "en", prov);
}
// add replacement bitstreams
List<String> options = processContentsFile(c, myitem, path +
File.separatorChar + itemname, "contents");
// set permissions if specified in contents file
if (options.size() > 0)
{
System.out.println("Processing options");
processOptions(c, myitem, options);
}
if (! isTest) {
myitem.update();
c.addEvent(new Event(Event.MODIFY+Event.MODIFY_METADATA,
Constants.ITEM, myitem.getID(), myitem.getHandle()));
// set embargo lift date and take away read access if indicated.
DCDate liftDate = EmbargoManager.getEmbargoDate(c, myitem);
if (liftDate != null)
{
EmbargoManager.setEmbargo(c, myitem, liftDate);
}
}
c.commit();
return;
}
3. Change replaceItems in ItemImport.java as below
private void replaceItems(Context c, Collection[] mycollections,
String sourceDir, String mapFile, boolean template) throws Exception
{
// verify the source directory
File d = new java.io.File(sourceDir);
if (d == null)
{
System.out.println("Error, cannot open source directory "
+ sourceDir);
System.exit(1);
}
// read in HashMap first, to get list of handles & source dirs
Map<String, String> myHash = readMapFile(mapFile);
// for each handle, re-import the item, discard the new handle
// and re-assign the old handle
for (Map.Entry<String, String> mapEntry : myHash.entrySet())
{
// get the old handle
String newItemName = mapEntry.getKey();
String oldHandle = mapEntry.getValue();
Item oldItem = null;
if (oldHandle.indexOf('/') != -1)
{
System.out.println("\tReplacing: " + oldHandle);
// add new item, locate old one
oldItem = (Item) HandleManager.resolveToObject(c, oldHandle);
}
else
{
oldItem = Item.find(c, Integer.parseInt(oldHandle));
}
/* Rather than exposing public item methods to change handles --
* two handles can't exist at the same time due to key constraints
* so would require temp handle being stored, old being copied to
new and
* new being copied to old, all a bit messy -- a handle file is
written to
* the import directory containing the old handle, the existing
item is
* deleted and then the import runs as though it were loading an
item which
* had already been assigned a handle (so a new handle is not even
assigned).
* As a commit does not occur until after a successful add, it is
safe to
* do a delete as any error results in an aborted transaction
without harming
* the original item */
/*File handleFile = new File(sourceDir + File.separatorChar +
newItemName + File.separatorChar + "handle");
// SWB fix bug - param should be "false" to not append to existing
file if present
PrintWriter handleOut = new PrintWriter(new FileWriter(handleFile,
false));
// END SWB
if (handleOut == null)
{
throw new Exception("can't open handle file: " +
handleFile.getCanonicalPath());
}
handleOut.println(oldHandle);
handleOut.close();
/*deleteItem(c, oldItem);
addItem(c, mycollections, sourceDir, newItemName, null, template);*/
replaceItem(c, oldItem, sourceDir, newItemName);
c.clearCache();
}
}
Best,
Ying
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct
_______________________________________________
Dspace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/dspace-devel