Package org.dspace.app.xmlui.aspect.administrative

Source Code of org.dspace.app.xmlui.aspect.administrative.FlowItemUtils

/*
* FlowItemUtils.java
*
* Version: $Revision: 4500 $
*
* Date: $Date: 2009-11-03 02:15:38 +0000 (Tue, 03 Nov 2009) $
*
* Copyright (c) 2002-2009, The DSpace Foundation.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the DSpace Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.xmlui.aspect.administrative;

import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;

import org.apache.cocoon.environment.Request;
import org.apache.cocoon.servlet.multipart.Part;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.content.Bitstream;
import org.dspace.content.BitstreamFormat;
import org.dspace.content.Bundle;
import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject;
import org.dspace.content.FormatIdentifier;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema;
import org.dspace.content.authority.Choices;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.handle.HandleManager;

/**
* Utility methods to processes actions on Groups. These methods are used
* exclusivly from the administrative flow scripts.
*
* @author Jay Paz
* @author Scott Phillips
*/
public class FlowItemUtils
{

  /** Language Strings */
  private static final Message T_metadata_updated = new Message("default","The Item's metadata was successfully updated.");
  private static final Message T_metadata_added = new Message("default","New metadata was added.");
  private static final Message T_item_withdrawn = new Message("default","The item has been withdrawn.");
  private static final Message T_item_reinstated = new Message("default","The item has been reinstated.");
    private static final Message T_item_moved = new Message("default","The item has been moved.");
    private static final Message T_item_move_destination_not_found = new Message("default","The selected destination collection could not be found.");
  private static final Message T_bitstream_added = new Message("default","The new bitstream was successfully uploaded.");
  private static final Message T_bitstream_failed = new Message("default","Error while uploading file.");
  private static final Message T_bitstream_updated = new Message("default","The bitstream has been updated.");
  private static final Message T_bitstream_delete = new Message("default","The selected bitstreams have been deleted.");
 
 
  /**
   * Resolve the given identifier to an item. The identifier may be either an
   * internal ID or a handle. If an item is found then the result the internal
   * ID of the item will be placed in the result "itemID" parameter.
   *
   * If the identifier was unable to be resolved to an item then the "identifier"
   * field is placed in error.
   *
   * @param context The current DSpace context.
   * @param identifier An Internal ID or a handle
   * @return A flow result
   */
  public static FlowResult resolveItemIdentifier(Context context, String identifier) throws SQLException
  {
    FlowResult result = new FlowResult();
    result.setContinue(false);
   
    //    Check whether it's a handle or internal id (by check ing if it has a slash inthe string)
    if (identifier.contains("/"))
    {
      DSpaceObject dso = HandleManager.resolveToObject(context, identifier);
 
      if (dso != null && dso.getType() == Constants.ITEM)
      {
        result.setParameter("itemID", dso.getID());
        result.setParameter("type", Constants.ITEM);
        result.setContinue(true);
        return result;
      }
    }
    else
    {
   
      Item item = null;
      try {
        item = Item.find(context, Integer.valueOf(identifier));
      } catch (NumberFormatException e) {
        // ignoring the exception
      }

      if (item != null)
      {
        result.setParameter("itemID", item.getID());
        result.setParameter("type", Constants.ITEM);
        result.setContinue(true);
        return result;
      }
    }

    result.addError("identifier");
    return result;
  }
 
  /**
   * Process the request parameters to update the item's metadata and remove any selected bitstreams.
   *
   * Each metadata entry will have three fields "name_X", "value_X", and "language_X" where X is an
   * integer that relates all three of the fields together. The name parameter stores the metadata name
   * that is used by the entry (i.e schema_element_qualifier). The value and language paramaters are user
   * inputed fields. If the optional parameter "remove_X" is given then the metadata value is removed.
   *
   * To support AJAX operations on this page an aditional parameter is considered, the "scope". The scope
   * is the set of metadata entries that are being updated during this request. It the metadata name,
   * schema_element_qualifier, only fields that have this name are considered! If all fields are to be
   * considered then scope should be set to "*".
   *
   * When creating an AJAX query include all the name_X, value_X, language_X, and remove_X for the fields
   * in the set, and then set the scope parameter to be the metadata field.
   *
   * @param context The current DSpace context
   * @param itemID  internal item id
   * @param request the Cocoon request
   * @return A flow result
   */
  public static FlowResult processEditItem(Context context, int itemID, Request request) throws SQLException, AuthorizeException, UIException, IOException
  {
    FlowResult result = new FlowResult();
    result.setContinue(false);

    Item item = Item.find(context, itemID);
   
   
    // STEP 1:
    // Clear all metadata within the scope
    // Only metadata values within this scope will be considered. This
    // is so ajax request can operate on only a subset of the values.
    String scope = request.getParameter("scope");
    if ("*".equals(scope))
    {
      item.clearMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
    }
    else
    {
      String[] parts = parseName(scope);
      item.clearMetadata(parts[0],parts[1],parts[2],Item.ANY);
    }
   
    // STEP 2:
    // First determine all the metadata fields that are within
    // the scope parameter
    ArrayList<Integer> indexes = new ArrayList<Integer>();
    Enumeration parameters = request.getParameterNames();
    while(parameters.hasMoreElements())
    {

      // Only consider the name_ fields
      String parameterName = (String) parameters.nextElement();
      if (parameterName.startsWith("name_"))
      {
        // Check if the name is within the scope
        String parameterValue = request.getParameter(parameterName);
        if ("*".equals(scope) || scope.equals(parameterValue))
        {
          // Extract the index from the name.
          String indexString = parameterName.substring("name_".length());
          Integer index = Integer.valueOf(indexString);
          indexes.add(index);
        }
      }
    }
   
    // STEP 3:
    // Iterate over all the indexes within the scope and add them back in.
    for (Integer index=1; index <= indexes.size(); ++index)
    {
      String name = request.getParameter("name_"+index);
      String value = request.getParameter("value_"+index);
                        String authority = request.getParameter("value_"+index+"_authority");
                        String confidence = request.getParameter("value_"+index+"_confidence");
      String lang = request.getParameter("language_"+index);
      String remove = request.getParameter("remove_"+index);
     
      // the user selected the remove checkbox.
      if (remove != null)
        continue;
     
      // get the field's name broken up
      String[] parts = parseName(name);
     
                        // probe for a confidence value
                        int iconf = Choices.CF_UNSET;
                        if (confidence != null && confidence.length() > 0)
                            iconf = Choices.getConfidenceValue(confidence);
                        // upgrade to a minimum of NOVALUE if there IS an authority key
                        if (authority != null && authority.length() > 0 && iconf == Choices.CF_UNSET)
                            iconf = Choices.CF_NOVALUE;
                        item.addMetadata(parts[0], parts[1], parts[2], lang,
                                             value, authority, iconf);
    }
   
    item.update();
    context.commit();
   
    result.setContinue(true);
   
    result.setOutcome(true);
    result.setMessage(T_metadata_updated);
   
    return result;
  }
 
  /**
   * Process the request paramaters to add a new metadata entry for the item.
   *
   * @param context The current DSpace context
   * @param itemID  internal item id
   * @param request the Cocoon request
   * @return A flow result
   */
  public static FlowResult processAddMetadata(Context context, int itemID, Request request) throws SQLException, AuthorizeException, UIException, IOException
  {
    FlowResult result = new FlowResult();
    result.setContinue(false);

    Item item = Item.find(context, itemID);
   
   
    String fieldID = request.getParameter("field");
    String value = request.getParameter("value");
    String language = request.getParameter("language");
   
    MetadataField field = MetadataField.find(context,Integer.valueOf(fieldID));
    MetadataSchema schema = MetadataSchema.find(context,field.getSchemaID());
   
    item.addMetadata(schema.getName(), field.getElement(), field.getQualifier(), language, value);
   
    item.update();
    context.commit();
   
    result.setContinue(true);
   
    result.setOutcome(true);
    result.setMessage(T_metadata_added);
   
    return result;
  }


  /**
   * Withdraw the specified item, this method assumes that the action has been confirmed.
   *
   * @param context The DSpace context
   * @param itemID The id of the to-be-withdrawn item.
   * @return A result object
   */
  public static FlowResult processWithdrawItem(Context context, int itemID) throws SQLException, AuthorizeException, IOException
  {
    FlowResult result = new FlowResult();
    result.setContinue(false);
   
    Item item = Item.find(context, itemID);
    item.withdraw();
    context.commit();

    result.setContinue(true);
        result.setOutcome(true);
        result.setMessage(T_item_withdrawn);
       
    return result;
  }
 
 
  /**
   * Reinstate the specified item, this method assumes that the action has been confirmed.
   *
   * @param context The DSpace context
   * @param itemID The id of the to-be-reinstated item.
   * @return A result object
   */
  public static FlowResult processReinstateItem(Context context, int itemID) throws SQLException, AuthorizeException, IOException
  {
    FlowResult result = new FlowResult();
    result.setContinue(false);
   
    Item item = Item.find(context, itemID);
    item.reinstate();
    context.commit();

    result.setContinue(true);
        result.setOutcome(true);
        result.setMessage(T_item_reinstated);
       
    return result;
  }
 
 
    /**
     * Move the specified item to another collection.
     *
     * @param context The DSpace context
     * @param itemID The id of the to-be-moved item.
     * @param collectionID The id of the destination collection.
     * @return A result object
     */
    public static FlowResult processMoveItem(Context context, int itemID, int collectionID) throws SQLException, AuthorizeException, IOException
    {
        FlowResult result = new FlowResult();
        result.setContinue(false);

        Item item = Item.find(context, itemID);

        if(AuthorizeManager.isAdmin(context, item))
        {
          //Add a policy giving this user *explicit* admin permissions on the item itself.
          //This ensures that the user will be able to call item.update() even if he/she
          // moves it to a Collection that he/she doesn't administer.
          AuthorizeManager.addPolicy(context, item, Constants.ADMIN, context.getCurrentUser());

          Collection destination = Collection.find(context, collectionID);
          if (destination == null)
          {
              result.setOutcome(false);
              result.setContinue(false);
              result.setMessage(T_item_move_destination_not_found);
              return result;
          }

          Collection owningCollection = item.getOwningCollection();
          if (destination.equals(owningCollection))
          {
              // nothing to do
              result.setOutcome(false);
              result.setContinue(false);
              return result;
          }

          // note: an item.move() method exists, but does not handle several cases:
          // - no preexisting owning collection (first arg is null)
          // - item already in collection, but not an owning collection
          //   (works, but puts item in collection twice)

          // Don't re-add the item to a collection it's already in.
          boolean alreadyInCollection = false;
          for (Collection collection : item.getCollections())
          {
              if (collection.equals(destination))
              {
                  alreadyInCollection = true;
                  break;
              }
          }

          // Remove item from its owning collection and add to the destination
          if (!alreadyInCollection)
              destination.addItem(item);

          if (owningCollection != null)
              owningCollection.removeItem(item);

          item.setOwningCollection(destination);
          item.update();
          context.commit();

          result.setOutcome(true);
          result.setContinue(true);
          result.setMessage(T_item_moved);
        }

        return result;
    }


  /**
   * Permanently delete the specified item, this method assumes that
   * the action has been confirmed.
   *
   * @param context The DSpace context
   * @param itemID The id of the to-be-deleted item.
   * @return A result object
   */
  public static FlowResult processDeleteItem(Context context, int itemID) throws SQLException, AuthorizeException, IOException
  {
    FlowResult result = new FlowResult();
    result.setContinue(false);
   
    Item item = Item.find(context, itemID);
     
        Collection[] collections = item.getCollections();

        // Remove item from all the collections it's in
        for (Collection collection : collections)
        {
            collection.removeItem(item);
       
       
        // Note: when removing an item from the last collection it will
        // be removed from the system. So there is no need to also call
        // an item.delete() method.       
       
        context.commit();
   
        result.setContinue(true);
       
    return result;
  }
 
 
  /**
   * Add a new bitstream to the item. The bundle, bitstream (aka file), and description
   * will be used to create a new bitstream. If the format needs to be adjusted then they
   * will need to access the edit bitstream form after it has been uploaded.
   *
   * @param context The DSpace content
   * @param itemID The item to add a new bitstream too
   * @param request The request.
   * @return A flow result
   */
  public static FlowResult processAddBitstream(Context context, int itemID, Request request) throws SQLException, AuthorizeException, IOException
  {
    FlowResult result = new FlowResult();
    result.setContinue(false);
   
    // Upload a new file
    Item item = Item.find(context, itemID);
   
   
    Object object = request.get("file");
    Part filePart = null;
    if (object instanceof Part)
      filePart = (Part) object;

    if (filePart != null && filePart.getSize() > 0)
    {
      InputStream is = filePart.getInputStream();

      String bundleName = request.getParameter("bundle");
     
      Bitstream bitstream;
      Bundle[] bundles = item.getBundles(bundleName);
      if (bundles.length < 1)
      {
        // set bundle's name to ORIGINAL
        bitstream = item.createSingleBitstream(is, bundleName);
       
        // set the permission as defined in the owning collection
        Collection owningCollection = item.getOwningCollection();
        if (owningCollection != null)
        {
            Bundle bnd = bitstream.getBundles()[0];
            bnd.inheritCollectionDefaultPolicies(owningCollection);
        }
      }
      else
      {
        // we have a bundle already, just add bitstream
        bitstream = bundles[0].createBitstream(is);
      }

      // Strip all but the last filename. It would be nice
      // to know which OS the file came from.
      String name = filePart.getUploadName();

      while (name.indexOf('/') > -1)
      {
        name = name.substring(name.indexOf('/') + 1);
      }

      while (name.indexOf('\\') > -1)
      {
        name = name.substring(name.indexOf('\\') + 1);
      }

      bitstream.setName(name);
      bitstream.setSource(filePart.getUploadName());
      bitstream.setDescription(request.getParameter("description"));

      // Identify the format
      BitstreamFormat format = FormatIdentifier.guessFormat(context, bitstream);
      bitstream.setFormat(format);

      // Update to DB
      bitstream.update();
      item.update();
     
      context.commit();
     
      result.setContinue(true);
          result.setOutcome(true);
          result.setMessage(T_bitstream_added);
    }
    else
    {
      result.setContinue(false);
          result.setOutcome(false);
          result.setMessage(T_bitstream_failed);
    }
    return result;
  }
 
 
  /**
   * Update a bitstream's metadata.
   *
   * @param context The DSpace content
   * @param itemID The item to which the bitstream belongs
   * @param bitstreamID The bitstream being updated.
   * @param description The new description of the bitstream
   * @param formatID The new format ID of the bitstream
   * @param userFormat Any user supplied formats.
   * @return A flow result object.
   */
  public static FlowResult processEditBitstream(Context context, int itemID, int bitstreamID, String primary, String description, int formatID, String userFormat) throws SQLException, AuthorizeException
  {
    FlowResult result = new FlowResult();
    result.setContinue(false);
   
    Bitstream bitstream = Bitstream.find(context, bitstreamID);
    BitstreamFormat currentFormat = bitstream.getFormat();

    //Step 1:
    // Update the bitstream's description
    if (description != null)
    {
      bitstream.setDescription(description);
    }
   
    //Step 2:
    // Check if the primary bitstream status has changed
    Bundle[] bundles = bitstream.getBundles();
    if (bundles != null && bundles.length > 0)
    {
      if (bitstreamID == bundles[0].getPrimaryBitstreamID())
      {
        // currently the bitstream is primary
        if ("no".equals(primary))
        {
          // However the user has removed this bitstream as a primary bitstream.
          bundles[0].unsetPrimaryBitstreamID();
          bundles[0].update();
        }
      }
      else
      {
        // currently the bitstream is non-primary
        if ("yes".equals(primary))
        {
          // However the user has set this bitstream as primary.
          bundles[0].setPrimaryBitstreamID(bitstreamID);
          bundles[0].update();
        }
      }
    }
   
   
    //Step 2:
    // Update the bitstream's format
    if (formatID > 0)
    {
      if (currentFormat == null || currentFormat.getID() != formatID)
      {
        BitstreamFormat newFormat = BitstreamFormat.find(context, formatID);
        if (newFormat != null)
        {
          bitstream.setFormat(newFormat);
        }
      }
    }
    else
    {
      if (userFormat != null && userFormat.length() > 0)
      {
        bitstream.setUserFormatDescription(userFormat);
      }
    }
   
    //Step 3:
    // Save our changes
    bitstream.update();
    context.commit();
   
     result.setContinue(true);
       result.setOutcome(true);
       result.setMessage(T_bitstream_updated);
         
   
    return result;
  }
 
  /**
   * Delete the given bitstreams from the bundle and item. If there are no more bitstreams
   * left in a bundle then also remove it.
   *
   * @param context Current dspace content
   * @param itemID The item id from which to remove bitstreams
   * @param bitstreamIDs A bundle slash bitstream id pair of bitstreams to be removed.
   * @return A flow result
   */
  public static FlowResult processDeleteBitstreams(Context context, int itemID, String[] bitstreamIDs) throws SQLException, AuthorizeException, IOException, UIException
  {
    FlowResult result = new FlowResult();
    result.setContinue(false);
   
    Item item = Item.find(context, itemID);
   
    for (String id : bitstreamIDs)
    {
      String[] parts = id.split("/");
     
      if (parts.length != 2)
        throw new UIException("Unable to parse id into bundle and bitstream id: "+id);
     
      int bundleID = Integer.valueOf(parts[0]);
      int bitstreamID = Integer.valueOf(parts[1]);
     
      Bundle bundle = Bundle.find(context, bundleID);
      Bitstream bitstream = Bitstream.find(context,bitstreamID);
     
      bundle.removeBitstream(bitstream);
     
      if (bundle.getBitstreams().length == 0)
      {
        item.removeBundle(bundle);
      }
    }
   
    item.update();
   
    context.commit();
   
    result.setContinue(true);
    result.setOutcome(true);
    result.setMessage(T_bitstream_delete);
   
    return result;
  }
 
 
  /**
   * Parse the given name into three parts, divided by an _. Each part should represent the
   * schema, element, and qualifier. You are guaranteed that if no qualifier was supplied the
   * third entry is null.
   *
   * @param name The name to be parsed.
   * @return An array of name parts.
   */
  private static String[] parseName(String name) throws UIException
  {
    String[] parts = new String[3];
   
    String[] split = name.split("_");
    if (split.length == 2) {
      parts[0] = split[0];
      parts[1] = split[1];
      parts[2] = null;
    } else if (split.length == 3) {
      parts[0] = split[0];
      parts[1] = split[1];
      parts[2] = split[2];
    } else {
      throw new UIException("Unable to parse metedata field name: "+name);
    }
    return parts;
  }
}
TOP

Related Classes of org.dspace.app.xmlui.aspect.administrative.FlowItemUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.