@Override
  public void unlink(Item item, Bundle bundle) throws AuthorizeException {
    if (!linked(item, bundle)) {
      return;
    }

    try {
      // Remove bundle mappings from DB
      DatabaseManager.updateQuery(
          context,
          "DELETE FROM item2bundle WHERE item_id= ? " + "AND bundle_id= ? ",
          item.getID(),
          bundle.getID());
    } catch (SQLException sqle) {
      throw new RuntimeException(sqle);
    }
  }
  @Override
  public List<Item> getParentItems(Bundle bundle) {
    try {
      // Get items
      TableRowIterator tri =
          DatabaseManager.queryTable(
              context,
              "item",
              "SELECT i.item_id FROM item i, item2bundle i2b "
                  + "WHERE i2b.item_id = i.item_id "
                  + "AND i2b.bundle_id = ? ",
              bundle.getID());

      return returnAsList(tri);
    } catch (SQLException sqle) {
      throw new RuntimeException(sqle);
    }
  }
  @Override
  public void link(Item item, Bundle bundle) throws AuthorizeException {
    if (linked(item, bundle)) {
      return;
    }

    try {
      TableRow row = DatabaseManager.create(context, "item2bundle");
      row.setColumn("item_id", item.getID());
      row.setColumn("bundle_id", bundle.getID());
      DatabaseManager.update(context, row);

      // If we're adding the Bundle to the Item, we bequeath our
      // policies unto it.
      AuthorizeManager.inheritPolicies(context, item, bundle);
    } catch (SQLException sqle) {
      throw new RuntimeException(sqle);
    }
  }
  /** Add rights information. This attaches an href to the URL of the item's licence file */
  protected void addRights() throws DSpaceSWORDException {
    try {
      // work our way up to the item
      List<Bundle> bundle2bitstreams = this.bitstream.getBundles();
      if (bundle2bitstreams.isEmpty()) {
        log.error("Found orphaned bitstream: " + bitstream.getID());
        throw new DSpaceSWORDException("Orphaned bitstream discovered");
      }
      Bundle bundle = bundle2bitstreams.get(0);
      List<Item> items = bundle.getItems();
      if (items.isEmpty()) {
        log.error("Found orphaned bundle: " + bundle.getID());
        throw new DSpaceSWORDException("Orphaned bundle discovered");
      }
      Item item = items.get(0);

      // now get the licence out of the item
      SWORDUrlManager urlManager = swordService.getUrlManager();
      StringBuilder rightsString = new StringBuilder();
      List<Bundle> lbundles = item.getBundles();
      for (Bundle lbundle : lbundles) {
        if (!Constants.LICENSE_BUNDLE_NAME.equals(lbundle.getName())) {
          // skip non-license bundles
          continue;
        }
        List<Bitstream> bss = lbundle.getBitstreams();
        for (Bitstream bs : bss) {
          String url = urlManager.getBitstreamUrl(bs);
          rightsString.append(url).append(" ");
        }
      }

      Rights rights = new Rights();
      rights.setContent(rightsString.toString());
      rights.setType(ContentType.TEXT);
      entry.setRights(rights);
      log.debug("Added rights entry to entity");
    } catch (SQLException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    }
  }
  @Override
  public boolean linked(Item item, Bundle bundle) {
    try {
      TableRowIterator tri =
          DatabaseManager.query(
              context,
              "SELECT id FROM item2bundle "
                  + " WHERE item_id="
                  + item.getID()
                  + " AND bundle_id="
                  + bundle.getID());

      boolean result = tri.hasNext();
      tri.close();

      return result;
    } catch (SQLException sqle) {
      throw new RuntimeException(sqle);
    }
  }
  public void addBody(Body body) throws SQLException, WingException {
    // Get our parameters and state
    int itemID = parameters.getParameterAsInteger("itemID", -1);
    Item item = Item.find(context, itemID);
    String baseURL = contextPath + "/admin/item?administrative-continue=" + knot.getId();

    // DIVISION: main div
    Division main =
        body.addInteractiveDivision(
            "edit-item-status",
            contextPath + "/admin/item",
            Division.METHOD_POST,
            "primary administrative item");
    main.setHead(T_option_head);

    // LIST: options
    List options = main.addList("options", List.TYPE_SIMPLE, "horizontal");
    options.addItem().addXref(baseURL + "&submit_status", T_option_status);
    options
        .addItem()
        .addHighlight("bold")
        .addXref(baseURL + "&submit_bitstreams", T_option_bitstreams);
    options.addItem().addXref(baseURL + "&submit_metadata", T_option_metadata);
    options.addItem().addXref(baseURL + "&view_item", T_option_view);

    // TABLE: Bitstream summary
    Table files = main.addTable("editItemBitstreams", 1, 1);

    files.setHead(T_head1);

    Row header = files.addRow(Row.ROLE_HEADER);
    header.addCellContent(T_column1);
    header.addCellContent(T_column2);
    header.addCellContent(T_column3);
    header.addCellContent(T_column4);
    header.addCellContent(T_column5);

    Bundle[] bundles = item.getBundles();

    for (Bundle bundle : bundles) {

      Cell bundleCell = files.addRow().addCell(1, 5);
      bundleCell.addContent(T_bundle_label.parameterize(bundle.getName()));

      Bitstream[] bitstreams = bundle.getBitstreams();

      for (Bitstream bitstream : bitstreams) {
        boolean primary = (bundle.getPrimaryBitstreamID() == bitstream.getID());
        String name = bitstream.getName();

        if (name != null && name.length() > 50) {
          // If the fiel name is too long the shorten it so that it will display nicely.
          String shortName = name.substring(0, 15);
          shortName += " ... ";
          shortName += name.substring(name.length() - 25, name.length());
          name = shortName;
        }

        String description = bitstream.getDescription();
        String format = null;
        BitstreamFormat bitstreamFormat = bitstream.getFormat();
        if (bitstreamFormat != null) format = bitstreamFormat.getShortDescription();
        String editURL =
            contextPath
                + "/admin/item?administrative-continue="
                + knot.getId()
                + "&bitstreamID="
                + bitstream.getID()
                + "&submit_edit";
        String viewURL =
            contextPath + "/bitstream/id/" + bitstream.getID() + "/" + bitstream.getName();

        Row row = files.addRow();
        CheckBox remove = row.addCell().addCheckBox("remove");
        remove.setLabel("remove");
        remove.addOption(bundle.getID() + "/" + bitstream.getID());
        if (!AuthorizeManager.authorizeActionBoolean(context, item, Constants.REMOVE)) {
          remove.setDisabled();
        }

        if (AuthorizeManager.authorizeActionBoolean(context, bitstream, Constants.WRITE)) {
          // The user can edit the bitstream give them a link.
          Cell cell = row.addCell();
          cell.addXref(editURL, name);
          if (primary) cell.addXref(editURL, T_primary_label);

          row.addCell().addXref(editURL, description);
          row.addCell().addXref(editURL, format);
        } else {
          // The user can't edit the bitstream just show them it.
          Cell cell = row.addCell();
          cell.addContent(name);
          if (primary) cell.addContent(T_primary_label);

          row.addCell().addContent(description);
          row.addCell().addContent(format);
        }

        Highlight highlight = row.addCell().addHighlight("fade");
        highlight.addContent("[");
        highlight.addXref(viewURL, T_view_link);
        highlight.addContent("]");
      }
    }

    if (AuthorizeManager.authorizeActionBoolean(context, item, Constants.ADD)) {
      Cell cell = files.addRow().addCell(1, 5);
      cell.addXref(
          contextPath + "/admin/item?administrative-continue=" + knot.getId() + "&submit_add",
          T_submit_add);
    } else {
      Cell cell = files.addRow().addCell(1, 5);
      cell.addHighlight("fade").addContent(T_no_upload);
    }

    // PARA: actions
    Para actions = main.addPara("editItemActionsP", "editItemActionsP");
    if (AuthorizeManager.authorizeActionBoolean(context, item, Constants.REMOVE))
      actions.addButton("submit_delete").setValue(T_submit_delete);
    else {
      Button button = actions.addButton("submit_delete");
      button.setValue(T_submit_delete);
      button.setDisabled();

      main.addPara().addHighlight("fade").addContent(T_no_remove);
    }
    actions.addButton("submit_return").setValue(T_submit_return);

    main.addHidden("administrative-continue").setValue(knot.getId());
  }