/**
   * Authorizes user access to a subject resource.
   *
   * @param context the assertion operation context
   * @throws CatalogIndexException indicates an I/O error with the resource index
   * @throws AsnInsufficientPrivilegeException if the user has insufficient privilege
   */
  private void authorizeResourceAccess(AsnContext context)
      throws CatalogIndexException, AsnInsufficientPrivilegeException {

    String resourceId = context.getOperation().getSystemPart().getResourceId();
    if ((resourceId == null) || (resourceId.length() == 0)) {
      return;
    }

    // ensure acl access
    RequestContext rContext = context.getRequestContext();
    AuthenticationStatus auth = rContext.getUser().getAuthenticationStatus();
    boolean bAdmin = auth.getAuthenticatedRoles().hasRole("gptAdministrator");
    if (!bAdmin) {
      MetadataAcl acl = new MetadataAcl(rContext);
      if (!acl.isPolicyUnrestricted()) {
        LuceneIndexAdapter adapter = new LuceneIndexAdapter(rContext);
        String[] resourceAcls = adapter.queryAcls(resourceId);
        if ((resourceAcls != null) && (resourceAcls.length > 0)) {

          String[] userAcls = acl.makeUserAcl();
          if ((userAcls != null) && (userAcls.length > 0)) {
            for (String resourcePrincipal : resourceAcls) {
              for (String userPrincipal : userAcls) {
                if (resourcePrincipal.equalsIgnoreCase(userPrincipal)) {
                  return;
                }
              }
            }
          }
          throw new AsnInsufficientPrivilegeException();
        }
      }
    }

    // ensure the existence of a local resource id
    if (!context.getOperation().getAuthPolicy().getAllowNonLocalResourceIds()) {
      LuceneIndexAdapter adapter = new LuceneIndexAdapter(rContext);
      Timestamp ts = adapter.queryModifiedDate(resourceId);
      if (ts == null) {
        throw new CatalogIndexException("Invalid resource id: " + resourceId);
      }
    }
  }
  /**
   * Reads record data.
   *
   * @param rs result set to read from
   * @param record record to write to
   * @throws SQLException if accessing database fails
   * @throws ParserConfigurationException if unable to reach parser configuration
   * @throws IOException if unable to perform IO operation
   * @throws SAXException if unable to parse XML data
   */
  private void readRecord(ResultSet rs, MmdRecord record)
      throws SQLException, ParserConfigurationException, IOException, SAXException {
    int n = 1;

    // set the title and uuid
    record.setTitle(rs.getString(n++));
    record.setUuid(rs.getString(n++));
    record.setSiteUuid(rs.getString(n++));
    if (getActionCriteria().getSelectedRecordIdSet().contains(record.getUuid())) {
      record.setIsSelected(true);
    }

    // set the owner, approval status and publication method
    record.setOwnerName(rs.getString(n++));
    record.setApprovalStatus(rs.getString(n++));
    record.setPublicationMethod(rs.getString(n++));

    // set the update date,
    Timestamp ts = rs.getTimestamp(n++);
    if (ts != null) {
      record.setSystemUpdateDate(ts);
      record.setFormattedUpdateDate(DateProxy.formatDate(ts));
    }

    // set the ACL
    String aclXml = rs.getString(n++);
    if (aclXml != null && aclXml.trim().length() > 0) {
      record.setMetadataAccessPolicyType("Restricted");
      MetadataAcl acl = new MetadataAcl(getRequestContext());
      record.setCurrentMetadataAccessPolicy(acl.makeGroupsfromXml(allGroups, aclXml));
      record.setCurrentMetadataAccessPolicyKeys(acl.makeGroupsKeysfromXml(allGroups, aclXml));
    } else {
      record.setMetadataAccessPolicyType("Unrestricted");
      record.setCurrentMetadataAccessPolicy("Unrestricted");
      record.setCurrentMetadataAccessPolicyKeys("Unrestricted");
    }

    // set harvesting specific data
    record.setLocalId(rs.getInt(n++));
    record.setHostUrl(rs.getString(n++));
    String frequency = Val.chkStr(rs.getString(n++));
    if (frequency.length() > 0)
      record.setHarvestFrequency(HarvestFrequency.checkValueOf(frequency));
    record.setSendNotification(Val.chkBool(rs.getString(n++), false));
    String protocol = Val.chkStr(rs.getString(n++));
    if (protocol.length() > 0)
      record.setProtocol(
          getApplicationConfiguration().getProtocolFactories().parseProtocol(protocol));

    // set the editable status
    boolean isEditor =
        record.getPublicationMethod().equalsIgnoreCase(PublicationMethod.editor.name());
    boolean isSEditor =
        record.getPublicationMethod().equalsIgnoreCase(PublicationMethod.seditor.name());
    boolean isProtocol = record.getProtocol() != null;
    boolean isOwner = hmEditablePublishers.containsKey(record.getOwnerName().toLowerCase());
    record.setCanEdit(
        (isEditor || isSEditor || isProtocol) && (isOwner || (isProtocol && isGptAdministrator)));

    // TODO remove as this is a temporary fix
    boolean isOther =
        record.getPublicationMethod().equalsIgnoreCase(PublicationMethod.other.name());
    if (isOther && isProtocol) {
      record.setPublicationMethod(PublicationMethod.registration.name());
    }

    record.setFindable(Val.chkBool(rs.getString(n++), false));
    record.setSearchable(Val.chkBool(rs.getString(n++), false));
    record.setSynchronizable(Val.chkBool(rs.getString(n++), false));
  }