Beispiel #1
0
  /**
   * Return a url to the DSpace object, either use the official handle for the item or build a url
   * based upon the current server.
   *
   * <p>If the dspaceobject is null then a local url to the repository is generated.
   *
   * @param request current servlet request
   * @param dso The object to reference, null if to the repository.
   * @return URL
   */
  protected String resolveURL(HttpServletRequest request, DSpaceObject dso) {
    // If no object given then just link to the whole repository,
    // since no offical handle exists so we have to use local resolution.
    if (dso == null) {
      if (baseURL == null) {
        if (request == null) {
          baseURL = ConfigurationManager.getProperty("dspace.url");
        } else {
          baseURL = (request.isSecure()) ? "https://" : "http://";
          baseURL += ConfigurationManager.getProperty("dspace.hostname");
          baseURL += ":" + request.getServerPort();
          baseURL += request.getContextPath();
        }
      }
      return baseURL;
    }

    // return a link to handle in repository
    else if (ConfigurationManager.getBooleanProperty("webui.feed.localresolve")) {
      return resolveURL(request, null) + "/handle/" + dso.getHandle();
    }

    // link to the Handle server or other persistent URL source
    else {
      return HandleServiceFactory.getInstance()
          .getHandleService()
          .getCanonicalForm(dso.getHandle());
    }
  }
  /**
   * See if is necessary and possible to get the backup file from cloud.
   *
   * @param context DSpace context
   * @param ref ID of the object
   * @param type type of the object DSpace
   * @return true if it is necessary or possible to get the backup from cloud or false if not
   */
  private Boolean couldGetFileFromCloud(Context context, int ref, int type) {
    // get the corresponding Dspace Object
    DSpaceObject obj = this.getDSpaceObject(context, type, ref);

    // if Object DSpace doesn't exist, return false
    if (obj == null) return false;

    // see if backup file exists in cloud, if not return false
    if (this.filesInCloud.containsKey(obj.getHandle())) {
      BackupProcess backupPro = new BackupProcess();
      String ETagSaved = backupPro.getETag(context, obj.getHandle());

      // see if ETag of file in cloud, has equal to the last send, if not return false
      if (ETagSaved.compareTo(this.filesInCloud.get(obj.getHandle())) == 0) {
        // see if exists backup file locally
        Backup backup = new Backup();
        String filename = backup.getFileNameObj(obj);
        Boolean existLocalFile = backup.existFile(filename);

        // if not exist file locally return true
        if (existLocalFile == true) {
          // get MD5 of local file
          String md5LocalFile = backup.getMD5File(filename);
          // get MD5 of the last file sent to cloud
          String md5FileSentCloud = backupPro.getSentMD5(context, obj.getHandle());

          // if files equal, there is no necessity to get file from cloud, then return false
          if (md5LocalFile.compareTo(md5FileSentCloud) == 0) return false;
          else return true;
        } else return true;
      } else return false;
    } else return false;
  }
Beispiel #3
0
  /**
   * Generate the unique caching key. This key must be unique inside the space of this component.
   */
  public Serializable getKey() {
    try {
      String key = "";

      // Page Parameter
      key += "-" + getParameterPage();
      key += "-" + getParameterRpp();
      key += "-" + getParameterSortBy();
      key += "-" + getParameterOrder();
      key += "-" + getParameterEtAl();

      // What scope the search is at
      DSpaceObject scope = getScope();
      if (scope != null) {
        key += "-" + scope.getHandle();
      }

      // The actual search query.
      key += "-" + getQuery();

      return HashUtil.hash(key);
    } catch (RuntimeException re) {
      throw re;
    } catch (Exception e) {
      // Ignore all errors and just don't cache.
      return "0";
    }
  }
 /**
  * Make URI path element for a DSpaceObject.
  *
  * @param dso the DSpaceObject, which needs to have a valid Handle.
  * @return path element string or null if no handle.
  */
 protected static String getPathElt(DSpaceObject dso) {
   String handle = dso.getHandle();
   if (handle == null) {
     return null;
   }
   return getPathElt(handle);
 }
  private static String formatMessage(DSpaceObject object) {
    try {
      String objText = Constants.typeText[object.getType()].toLowerCase();
      String handle = object.getHandle();

      /* Emulate Item logger */
      if (handle != null && object instanceof Item) {
        return "handle=" + object.getHandle();
      } else {
        return objText + "_id=" + object.getID();
      }

    } catch (Exception e) {

    }
    return "";
  }
  /**
   * Generate the unique caching key. This key must be unique inside the space of this component.
   */
  public Serializable getKey() {
    try {
      DSpaceObject dso = HandleUtil.obtainHandle(objectModel);

      if (dso == null) return "0";

      return HashUtil.hash(dso.getHandle());
    } catch (SQLException sqle) {
      // Ignore all errors and just return that the component is not
      // cachable.
      return "0";
    }
  }
  public Serializable getKey() {
    try {
      BrowseParams params = getUserParams();

      String key = params.getKey();

      if (key != null) {
        DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
        if (dso != null) key += "-" + dso.getHandle();

        return HashUtil.hash(key);
      }
    } catch (Exception e) {
      // Ignore all errors and just don't cache.
    }

    return "0";
  }
Beispiel #8
0
  /**
   * Process sets of objects to add, update, and delete in index. Correct for interactions between
   * the sets -- e.g. objects which were deleted do not need to be added or updated, new objects
   * don't also need an update, etc.
   */
  public void end(Context ctx) throws Exception {

    if (objectsToUpdate != null && handlesToDelete != null) {

      // update the changed Items not deleted because they were on create list
      for (DSpaceObject iu : objectsToUpdate) {
        /* we let all types through here and
         * allow the search DSIndexer to make
         * decisions on indexing and/or removal
         */
        String hdl = iu.getHandle();
        if (hdl != null && !handlesToDelete.contains(hdl)) {
          try {
            DSIndexer.indexContent(ctx, iu, true);
            log.debug(
                "Indexed "
                    + Constants.typeText[iu.getType()]
                    + ", id="
                    + String.valueOf(iu.getID())
                    + ", handle="
                    + hdl);
          } catch (Exception e) {
            log.error("Failed while indexing object: ", e);
          }
        }
      }

      for (String hdl : handlesToDelete) {
        try {
          DSIndexer.unIndexContent(ctx, hdl);
          if (log.isDebugEnabled()) {
            log.debug("UN-Indexed Item, handle=" + hdl);
          }
        } catch (Exception e) {
          log.error("Failed while UN-indexing object: " + hdl, e);
        }
      }
    }

    // "free" the resources
    objectsToUpdate = null;
    handlesToDelete = null;
  }
Beispiel #9
0
  /**
   * Add the basic navigational options:
   *
   * <p>Search - advanced search
   *
   * <p>browse - browse by Titles - browse by Authors - browse by Dates
   *
   * <p>language FIXME: add languages
   *
   * <p>context no context options are added.
   *
   * <p>action no action options are added.
   */
  public void addOptions(Options options)
      throws SAXException, WingException, UIException, SQLException, IOException,
          AuthorizeException {
    /* Create skeleton menu structure to ensure consistent order between aspects,
     * even if they are never used
     */
    List browse = options.addList("browse");
    options.addList("account");
    options.addList("context");
    options.addList("administrative");

    browse.setHead(T_head_browse);

    List browseGlobal = browse.addList("global");
    List browseContext = browse.addList("context");

    browseGlobal.setHead(T_head_all_of_dspace);

    browseGlobal.addItemXref(contextPath + "/community-list", T_communities_and_collections);

    // Add the configured browse lists for 'top level' browsing
    addBrowseOptions(browseGlobal, contextPath + "/browse");

    DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
    if (dso != null) {
      if (dso instanceof Item) {
        // If we are an item change the browse scope to the parent
        // collection.
        dso = ((Item) dso).getOwningCollection();
      }

      if (dso instanceof Collection) {
        browseContext.setHead(T_head_this_collection);
      }
      if (dso instanceof Community) {
        browseContext.setHead(T_head_this_community);
      }

      // Add the configured browse lists for scoped browsing
      String handle = dso.getHandle();
      addBrowseOptions(browseContext, contextPath + "/handle/" + handle + "/browse");
    }
  }
Beispiel #10
0
  /**
   * Generate the unique caching key. This key must be unique inside the space of this component.
   */
  public Serializable getKey() {
    try {
      Request request = ObjectModelHelper.getRequest(objectModel);
      String key =
          request.getScheme()
              + request.getServerName()
              + request.getServerPort()
              + request.getSitemapURI()
              + request.getQueryString();

      DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
      if (dso != null) {
        key += "-" + dso.getHandle();
      }

      return HashUtil.hash(key);
    } catch (SQLException sqle) {
      // Ignore all errors and just return that the component is not cachable.
      return "0";
    }
  }
  /**
   * Return the metadata URL of the supplied object, assuming it's a DSpace item, community or
   * collection.
   */
  public String getObjectURL(Object object) throws WingException {
    if (object instanceof DSpaceObject) {
      DSpaceObject dso = (DSpaceObject) object;
      String handle = dso.getHandle();

      // If the object has a handle then refrence it by it's handle.
      if (handle != null) {
        return "/metadata/handle/" + handle + "/mets.xml";
      } else {
        // No handle then refrence it by an internal ID.
        if (dso instanceof Item || dso instanceof BrowseItem) {
          return "/metadata/internal/item/" + dso.getID() + "/mets.xml";
        } else if (object instanceof Collection) {
          return "/metadata/internal/collection/" + dso.getID() + "/mets.xml";
        } else if (object instanceof Community) {
          return "/metadata/internal/community/" + dso.getID() + "/mets.xml";
        }
      }
    }

    return null;
  }
Beispiel #12
0
  protected void dspaceDFS(DSpaceObject dso, Callback callback, boolean check, boolean reset)
      throws SQLException {
    if (dso.getType() != Constants.SITE
        && dso.getType() != Constants.COMMUNITY
        && dso.getType() != Constants.COLLECTION
        && dso.getType() != Constants.ITEM) {
      throw new IllegalArgumentException(
          contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso)
              + " is currently not supported as independent entity.");
    }

    if (reset) {
      this.processed.clear();
    }

    if (isProcessed(dso)) {
      log.debug(
          "Skipping processing of "
              + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso)
              + " "
              + dso.getID()
              + " (handle "
              + dso.getHandle()
              + "), already processed.");
      return;
    }
    markProcessed(dso);
    // this is useful to debug depth first search, but it is really noisy.
    // log.debug("Procesing " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) +
    // " " + dso.getID() + ":" + dso.getHandle() + ".");

    // if this method is used for conversion we should check if we have the
    // permissions to read a DSO before converting all of it decendents
    // (e.g. check read permission on a community before converting all of
    // its subcommunties and collections).
    // just skip items with missing permissions and report them.
    if (check) {
      try {
        RDFUtil.isPublic(context, dso);
      } catch (ItemNotArchivedException ex) {
        if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex);
        report(
            "Skipping processing of Item "
                + dso.getID()
                + " (handle "
                + dso.getHandle()
                + "): Item is not "
                + "archived.");
        return;
      } catch (ItemWithdrawnException ex) {
        if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex);
        report(
            "Skipping processing of Item "
                + dso.getID()
                + " (handle "
                + dso.getHandle()
                + "): Item is "
                + "withdrawn.");
        return;
      } catch (ItemNotDiscoverableException ex) {
        if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex);
        report(
            "Skipping processing of Item "
                + dso.getID()
                + " (handle "
                + dso.getHandle()
                + "): Item is not "
                + "discoverable.");
        return;
      } catch (AuthorizeException ex) {
        report(
            "Skipping processing of "
                + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso)
                + " "
                + dso.getID()
                + " (handle "
                + dso.getHandle()
                + ")"
                + ", not authorized: "
                + ex.getMessage());
        return;
      }
    }

    if (dso instanceof Site) {
      List<Community> communities = communityService.findAllTop(context);
      for (Community community : communities) {
        this.dspaceDFS(community, callback, check, false);
      }
    }

    if (dso instanceof Community) {
      List<Community> subcommunities = ((Community) dso).getSubcommunities();
      for (Community sub : subcommunities) {
        this.dspaceDFS(sub, callback, check, false);
      }
      List<Collection> collections = ((Community) dso).getCollections();
      for (Collection collection : collections) {
        this.dspaceDFS(collection, callback, check, false);
      }
    }

    if (dso instanceof Collection) {
      Iterator<Item> items = itemService.findAllByCollection(context, (Collection) dso);
      while (items.hasNext()) {
        Item item = items.next();
        this.dspaceDFS(item, callback, check, false);
      }
    }

    //        Currently Bundles and Bitsreams aren't supported as independent entities.
    //        They should be converted as part of an item. So we do not need to make
    //        the recursive call for them. An item itself will be converted as part
    //        of the callback call below.
    //        The following code is left here for the day, we decide to also convert
    //        bundles and/or bitstreams.
    //
    //        if (dso instanceof Item)
    //        {
    //            Bundle[] bundles = ((Item) dso).getBundles();
    //            for (Bundle bundle : bundles)
    //            {
    //                this.dspaceDFS(bundle, callback, check, false);
    //            }
    //        }
    //
    //        if (dso instanceof Bundle)
    //        {
    //            Bitstream[] bistreams = ((Bundle) dso).getBitstreams();
    //            for (Bitstream bitstream : bistreams)
    //            {
    //                this.dspaceDFS(bitstream, callback, check, false);
    //            }
    //        }

    callback.callback(dso);
    report(
        "Processed "
            + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso)
            + " "
            + dso.getID()
            + " (handle "
            + dso.getHandle()
            + ").");
  }
Beispiel #13
0
  /**
   * Consume a content event -- just build the sets of objects to add (new) to the index, update,
   * and delete.
   *
   * @param ctx DSpace context
   * @param event Content event
   */
  public void consume(Context ctx, Event event) throws Exception {

    if (objectsToUpdate == null) {
      objectsToUpdate = new HashSet<DSpaceObject>();
      handlesToDelete = new HashSet<String>();
    }

    int st = event.getSubjectType();
    if (!(st == Constants.ITEM
        || st == Constants.BUNDLE
        || st == Constants.COLLECTION
        || st == Constants.COMMUNITY)) {
      log.warn(
          "SearchConsumer should not have been given this kind of Subject in an event, skipping: "
              + event.toString());
      return;
    }

    DSpaceObject subject = event.getSubject(ctx);

    DSpaceObject object = event.getObject(ctx);

    // If event subject is a Bundle and event was Add or Remove,
    // transform the event to be a Modify on the owning Item.
    // It could be a new bitstream in the TEXT bundle which
    // would change the index.
    int et = event.getEventType();
    if (st == Constants.BUNDLE) {
      if ((et == Event.ADD || et == Event.REMOVE)
          && subject != null
          && "TEXT".equals(((Bundle) subject).getName())) {
        st = Constants.ITEM;
        et = Event.MODIFY;
        subject = ((Bundle) subject).getItems()[0];
        if (log.isDebugEnabled()) {
          log.debug("Transforming Bundle event into MODIFY of Item " + subject.getHandle());
        }
      } else {
        return;
      }
    }

    switch (et) {
      case Event.CREATE:
      case Event.MODIFY:
      case Event.MODIFY_METADATA:
        if (subject == null) {
          log.warn(
              event.getEventTypeAsString()
                  + " event, could not get object for "
                  + event.getSubjectTypeAsString()
                  + " id="
                  + String.valueOf(event.getSubjectID())
                  + ", perhaps it has been deleted.");
        } else {
          log.debug("consume() adding event to update queue: " + event.toString());
          objectsToUpdate.add(subject);
        }
        break;

      case Event.REMOVE:
      case Event.ADD:
        if (object == null) {
          log.warn(
              event.getEventTypeAsString()
                  + " event, could not get object for "
                  + event.getObjectTypeAsString()
                  + " id="
                  + String.valueOf(event.getObjectID())
                  + ", perhaps it has been deleted.");
        } else {
          log.debug("consume() adding event to update queue: " + event.toString());
          objectsToUpdate.add(object);
        }
        break;

      case Event.DELETE:
        String detail = event.getDetail();
        if (detail == null) {
          log.warn("got null detail on DELETE event, skipping it.");
        } else {
          log.debug("consume() adding event to delete queue: " + event.toString());
          handlesToDelete.add(detail);
        }
        break;
      default:
        log.warn(
            "SearchConsumer should not have been given a event of type="
                + event.getEventTypeAsString()
                + " on subject="
                + event.getSubjectTypeAsString());
        break;
    }
  }
Beispiel #14
0
  /** Insure that the context path is added to the page meta. */
  public void addPageMeta(PageMeta pageMeta)
      throws SAXException, WingException, UIException, SQLException, IOException,
          AuthorizeException {
    // FIXME: I don't think these should be set here, but there needed and I'm
    // not sure where else it could go. Perhaps the linkResolver?
    Request request = ObjectModelHelper.getRequest(objectModel);
    pageMeta.addMetadata("contextPath").addContent(contextPath);
    pageMeta.addMetadata("request", "queryString").addContent(request.getQueryString());
    pageMeta.addMetadata("request", "scheme").addContent(request.getScheme());
    pageMeta.addMetadata("request", "serverPort").addContent(request.getServerPort());
    pageMeta.addMetadata("request", "serverName").addContent(request.getServerName());
    pageMeta.addMetadata("request", "URI").addContent(request.getSitemapURI());

    String dspaceVersion = Util.getSourceVersion();
    if (dspaceVersion != null) {
      pageMeta.addMetadata("dspace", "version").addContent(dspaceVersion);
    }

    String analyticsKey = ConfigurationManager.getProperty("xmlui.google.analytics.key");
    if (analyticsKey != null && analyticsKey.length() > 0) {
      analyticsKey = analyticsKey.trim();
      pageMeta.addMetadata("google", "analytics").addContent(analyticsKey);
    }

    // add metadata for OpenSearch auto-discovery links if enabled
    if (ConfigurationManager.getBooleanProperty("websvc.opensearch.autolink")) {
      pageMeta
          .addMetadata("opensearch", "shortName")
          .addContent(ConfigurationManager.getProperty("websvc.opensearch.shortname"));
      pageMeta
          .addMetadata("opensearch", "context")
          .addContent(ConfigurationManager.getProperty("websvc.opensearch.svccontext"));
    }

    // Add metadata for quick searches:
    pageMeta.addMetadata("search", "simpleURL").addContent(contextPath + "/search");
    pageMeta.addMetadata("search", "advancedURL").addContent(contextPath + "/advanced-search");
    pageMeta.addMetadata("search", "queryField").addContent("query");

    pageMeta.addMetadata("page", "contactURL").addContent(contextPath + "/contact");
    pageMeta.addMetadata("page", "feedbackURL").addContent(contextPath + "/feedback");

    // Add the locale meta data including language dependant labels
    Locale[] locales = I18nUtil.getSupportedLocales();
    for (int i = 0; i < locales.length; i++) {
      pageMeta.addMetadata("page", "supportedLocale").addContent(locales[i].toString());
      // now add the appropriate labels
      pageMeta
          .addMetadata("supportedLocale", locales[i].toString())
          .addContent(locales[i].getDisplayName(locales[i]));
    }

    pageMeta.addMetadata("page", "currentLocale").addContent(context.getCurrentLocale().toString());

    DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
    if (dso != null) {
      if (dso instanceof Item) {
        pageMeta.addMetadata("focus", "object").addContent("hdl:" + dso.getHandle());
        this.getObjectManager().manageObject(dso);
        dso = ((Item) dso).getOwningCollection();
      }

      if (dso instanceof Collection || dso instanceof Community) {
        pageMeta.addMetadata("focus", "container").addContent("hdl:" + dso.getHandle());
        this.getObjectManager().manageObject(dso);
      }
    }
  }
Beispiel #15
0
  @Override
  public void addBody(Body body)
      throws SAXException, WingException, UIException, SQLException, IOException,
          AuthorizeException {

    Request request = ObjectModelHelper.getRequest(objectModel);

    DSpaceObject dso = HandleUtil.obtainHandle(objectModel);

    // Set up the major variables
    // Collection collection = (Collection) dso;

    // Build the collection viewer division.

    // Make sure we get our results
    queryResults = getQueryResponse(dso);
    if (this.queryResults != null) {

      Map<String, List<DiscoverResult.FacetResult>> facetFields =
          this.queryResults.getFacetResults();
      if (facetFields == null) {
        facetFields = new LinkedHashMap<String, List<DiscoverResult.FacetResult>>();
      }

      //            facetFields.addAll(this.queryResults.getFacetDates());

      if (facetFields.size() > 0) {
        String facetField =
            String.valueOf(facetFields.keySet().toArray(new String[facetFields.size()])[0]);
        java.util.List<DiscoverResult.FacetResult> values = facetFields.get(facetField);

        if (values != null && 0 < values.size()) {

          Division results = body.addDivision("browse-by-" + facetField + "-results", "primary");

          results.setHead(
              message(
                  "xmlui.ArtifactBrowser.AbstractSearch.type_"
                      + request.getParameter(FACET_FIELD)
                      + "_browse"));

          // Find our faceting offset
          int offSet = queryArgs.getFacetOffset();
          if (offSet == -1) {
            offSet = 0;
          }

          // Only show the nextpageurl if we have at least one result following our current results
          String nextPageUrl = null;
          if (values.size() == (DEFAULT_PAGE_SIZE + 1)) {
            nextPageUrl = getNextPageURL(request);
          }

          results.setSimplePagination(
              (int) queryResults.getDspaceObjects().size(),
              offSet + 1,
              (offSet + (values.size() - 1)),
              getPreviousPageURL(request),
              nextPageUrl);

          Table singleTable =
              results.addTable(
                  "browse-by-" + facetField + "-results",
                  (int) (queryResults.getDspaceObjects().size() + 1),
                  1);

          List<String> filterQueries = new ArrayList<String>();
          if (request.getParameterValues("fq") != null) {
            filterQueries = Arrays.asList(request.getParameterValues("fq"));
          }
          for (int i = 0; i < values.size(); i++) {
            DiscoverResult.FacetResult value = values.get(i);

            String displayedValue = value.getDisplayedValue();
            String filterQuery = value.getAsFilterQuery();

            //                        if(field.getGap() != null){
            //                            //We have a date get the year so we can display it
            //                            DateFormat simpleDateformat = new
            // SimpleDateFormat("yyyy");
            //                            displayedValue =
            // simpleDateformat.format(SolrServiceImpl.toDate(displayedValue));
            //                            filterQuery =
            // ClientUtils.escapeQueryChars(value.getFacetField().getName()) + ":" + displayedValue
            // + "*";
            //                        }

            Cell cell = singleTable.addRow().addCell();

            // No use in selecting the same filter twice
            if (filterQueries.contains(filterQuery)) {
              cell.addContent(displayedValue + " (" + value.getCount() + ")");
            } else {
              cell.addXref(
                  contextPath
                      + (dso == null ? "" : "/handle/" + dso.getHandle())
                      + "/discover?"
                      + "&fq="
                      + URLEncoder.encode(filterQuery, "UTF-8")
                      + (request.getQueryString() != null ? "&" + request.getQueryString() : ""),
                  displayedValue + " (" + value.getCount() + ")");
            }
          }
        }
      }
    }

    // DSpaceObject dso = HandleUtil.obtainHandle(objectModel);

    /*
    if (dso != null)
    {
        if (dso instanceof Collection)
        {
            browseContext.addItem().addXref(contextPath + "/discovery/?q=search.resourcetype%3A2+AND+location%3Al" + dso.getID(), T_head_this_collection );
        }
        if (dso instanceof Community)
        {
            browseContext.addItem().addXref(contextPath + "/discovery/?q=search.resourcetype%3A2+AND+location%3Am" + dso.getID(), T_head_this_community );
        }
    }

    browseGlobal.addItem().addXref(contextPath + "/discovery/?q=search.resourcetype%3A2", T_head_all_of_dspace );
    */
  }
Beispiel #16
0
  /**
   * Utility method for obtaining a string representation of the browse. This is useful only for
   * debug
   */
  public String toString() {
    try {
      StringBuffer sb = new StringBuffer();

      // calculate the range for display
      String from = Integer.toString(overallPosition + 1);
      String to = Integer.toString(overallPosition + results.size());
      String of = Integer.toString(total);

      // report on the positional information of the browse
      sb.append("BrowseInfo String Representation: ");
      sb.append("Browsing " + from + " to " + to + " of " + of + " ");

      // insert the information about which index
      sb.append(
          "in index: "
              + browseIndex.getName()
              + " (data type: "
              + browseIndex.getDataType()
              + ", display type: "
              + browseIndex.getDisplayType()
              + ") ");

      sb.append("||");

      // report on the browse scope container
      String container = "all of DSpace";
      DSpaceObject theContainer = null;
      if (inCollection()) {
        container = "collection";
        theContainer = this.collection;
      } else if (inCommunity()) {
        container = "community";
        theContainer = this.community;
      }

      String containerID = "no id available/necessary";
      if (theContainer != null) {
        containerID =
            Integer.toString(theContainer.getID()) + " (" + theContainer.getHandle() + ")";
      }

      sb.append("Browsing in " + container + ": " + containerID);
      sb.append("||");

      // load the item list display configuration
      ItemListConfig config = new ItemListConfig();

      // some information about the columns to be displayed
      if (browseIndex.isItemIndex()) {
        sb.append("Listing over " + Integer.toString(config.numCols()) + " columns: ");
        for (int k = 1; k <= config.numCols(); k++) {
          if (k > 1) {
            sb.append(",");
          }
          String[] meta = config.getMetadata(k);
          sb.append(meta[0] + "." + meta[1] + "." + meta[2]);
        }

        if (value != null) {
          sb.append(" on value: ").append(value);
        }

        if (isStartsWith()) {
          sb.append(" sort column starting with: ").append(focus);
        } else if (hasFocus()) {
          sb.append(" sort column focus: ").append(focus);
        }
      } else if (browseIndex.isMetadataIndex()) {
        sb.append("Listing single column: ").append(browseIndex.getMetadata());
        if (isStartsWith()) {
          sb.append(" sort column starting with: ").append(focus);
        } else if (hasFocus()) {
          sb.append(" sort column focus: ").append(focus);
        }
      }

      sb.append("||");

      // some information about how the data is sorted
      String direction = (ascending ? "ASC" : "DESC");
      sb.append(
          "Sorting by: "
              + sortOption.getMetadata()
              + " "
              + direction
              + " (option "
              + Integer.toString(sortOption.getNumber())
              + ")");
      sb.append("||");

      // output the results
      if (browseIndex.isMetadataIndex() && !isSecondLevel()) {
        sb.append(valueListingString());
      } else if (browseIndex.isItemIndex() || isSecondLevel()) {
        sb.append(fullListingString(config));
      }

      sb.append("||");

      // tell us what the next and previous values are going to be
      sb.append("Top of next page: ");
      if (hasNextPage()) {
        sb.append("offset: ").append(Integer.toString(this.nextOffset));
      } else {
        sb.append("n/a");
      }
      sb.append(";");

      sb.append("Top of previous page: ");
      if (hasPrevPage()) {
        sb.append("offset: ").append(Integer.toString(this.prevOffset));
      } else {
        sb.append("n/a");
      }

      sb.append("||");

      return sb.toString();
    } catch (SQLException e) {
      return e.getMessage();
    } catch (BrowseException e) {
      return e.getMessage();
    }
  }
  /**
   * See if the last backup done is updated and if it is in cloud. DSpace Object could be community,
   * collection or item
   *
   * @param context DSpace context
   * @param ref ID of the object
   * @param type type of the object DSpace
   * @return true if the updated backup is in the cloud or false if not
   */
  private Boolean sendDone(Context context, int ref, int type) {
    // see if object is a community or collection
    if (type == Constants.COMMUNITY || type == Constants.COLLECTION) {
      // see if there is a modification registry in the db
      Logbackup logbackup = new Logbackup();
      Boolean existLog = logbackup.existsLog(context, ref, type);

      // if modification has been detected return false
      if (existLog == true) return false;
    }

    // get the DSpaceObject
    DSpaceObject obj = this.getDSpaceObject(context, type, ref);

    // if Object DSpace doesn't exist, return false
    if (obj == null) return false;

    // see if exist a regist of a backup in the table sthandfile
    BackupProcess backupProcess = new BackupProcess();
    Boolean existRegist = backupProcess.existRegist(context, obj.getHandle());

    // if doesn't exist a regist return false
    if (existRegist == false) return false;

    // see if object is an item
    if (type == Constants.ITEM) {
      // get the last modification date of the item
      Item item = null;
      try {
        item = Item.find(context, ref);
      } catch (SQLException ex) {
        Logger.getLogger(ActualContentManagement.class.getName()).log(Level.SEVERE, null, ex);
      }
      Date lastModification = item.getLastModified();

      // get the last backup date
      Date lastBackup = backupProcess.getLastBackupDate(context, obj.getHandle());

      // see if some modification happens after a backup
      if (lastModification.after(lastBackup) == true) return false;
    }

    // get the last send cloud dat
    Date lastSendCloud = backupProcess.getLastSendCloudDate(context, obj.getHandle());

    // if doesn't exist a date relative to the last send to cloud return false
    if (lastSendCloud == null) return false;

    // get the last backup date
    Date lastBackup = backupProcess.getLastBackupDate(context, obj.getHandle());

    // verify if a new backup happened
    if (lastSendCloud.before(lastBackup) == true) {
      // see if new md5 file backup is equal to the last md5 file backup sent to cloud
      Boolean equalFiles = backupProcess.equalsFiles(context, obj.getHandle());

      // if equal files return true
      if (equalFiles == false) return false;
    }

    // see if file exists in cloud, if not returns false
    if (this.filesInCloud.containsKey(obj.getHandle())) {
      // see if ETag is correct, if not returns false
      if (this.filesInCloud
              .get(obj.getHandle())
              .compareTo(backupProcess.getETag(context, obj.getHandle()))
          == 0) return true;
      else return false;
    } else return false;
  }