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

Reply via email to