Beispiel #1
0
  public void replaceMetadataValue(DCValue oldValue, DCValue newValue) {
    // check both dcvalues are for the same field
    if (oldValue.hasSameFieldAs(newValue)) {

      String schema = oldValue.schema;
      String element = oldValue.element;
      String qualifier = oldValue.qualifier;

      // Save all metadata for this field
      DCValue[] dcvalues = getMetadata(schema, element, qualifier, Item.ANY);
      clearMetadata(schema, element, qualifier, Item.ANY);
      for (DCValue dcvalue : dcvalues) {
        if (dcvalue.equals(oldValue)) {
          addMetadata(
              schema,
              element,
              qualifier,
              newValue.language,
              newValue.value,
              newValue.authority,
              newValue.confidence);
        } else {
          addMetadata(
              schema,
              element,
              qualifier,
              dcvalue.language,
              dcvalue.value,
              dcvalue.authority,
              dcvalue.confidence);
        }
      }
    }
  }
Beispiel #2
0
    List<DCValue> get(Context c, int resourceId, int resourceTypeId, Logger log)
        throws SQLException {
      if (metadata == null) {
        metadata = new ArrayList<DCValue>();

        // Get Dublin Core metadata
        TableRowIterator tri = retrieveMetadata(resourceId, resourceTypeId);

        if (tri != null) {
          try {
            while (tri.hasNext()) {
              TableRow resultRow = tri.next();

              // Get the associated metadata field and schema information
              int fieldID = resultRow.getIntColumn("metadata_field_id");
              MetadataField field = MetadataField.find(c, fieldID);

              if (field == null) {
                log.error("Loading item - cannot find metadata field " + fieldID);
              } else {
                MetadataSchema schema = MetadataSchema.find(c, field.getSchemaID());
                if (schema == null) {
                  log.error(
                      "Loading item - cannot find metadata schema "
                          + field.getSchemaID()
                          + ", field "
                          + fieldID);
                } else {
                  // Make a DCValue object
                  DCValue dcv = new DCValue();
                  dcv.element = field.getElement();
                  dcv.qualifier = field.getQualifier();
                  dcv.value = resultRow.getStringColumn("text_value");
                  dcv.language = resultRow.getStringColumn("text_lang");
                  // dcv.namespace = schema.getNamespace();
                  dcv.schema = schema.getName();
                  dcv.authority = resultRow.getStringColumn("authority");
                  dcv.confidence = resultRow.getIntColumn("confidence");

                  // Add it to the list
                  metadata.add(dcv);
                }
              }
            }
          } finally {
            // close the TableRowIterator to free up resources
            if (tri != null) {
              tri.close();
            }
          }
        }
      }

      return metadata;
    }
Beispiel #3
0
  /**
   * Get metadata for the DSpace Object in a chosen schema. See <code>MetadataSchema</code> for more
   * information about schemas. Passing in a <code>null</code> value for <code>qualifier</code> or
   * <code>lang</code> only matches metadata fields where that qualifier or languages is actually
   * <code>null</code>. Passing in <code>DSpaceObject.ANY</code> retrieves all metadata fields with
   * any value for the qualifier or language, including <code>null</code>
   *
   * <p>Examples:
   *
   * <p>Return values of the unqualified "title" field, in any language. Qualified title fields
   * (e.g. "title.uniform") are NOT returned:
   *
   * <p><code>dspaceobject.getMetadataByMetadataString("dc", "title", null, DSpaceObject.ANY );
   * </code>
   *
   * <p>Return all US English values of the "title" element, with any qualifier (including
   * unqualified):
   *
   * <p><code>dspaceobject.getMetadataByMetadataString("dc, "title", DSpaceObject.ANY, "en_US" );
   * </code>
   *
   * <p>The ordering of values of a particular element/qualifier/language combination is
   * significant. When retrieving with wildcards, values of a particular element/qualifier/language
   * combinations will be adjacent, but the overall ordering of the combinations is indeterminate.
   *
   * @param schema the schema for the metadata field. <em>Must</em> match the <code>name</code> of
   *     an existing metadata schema.
   * @param element the element name. <code>DSpaceObject.ANY</code> matches any element. <code>null
   *     </code> doesn't really make sense as all metadata must have an element.
   * @param qualifier the qualifier. <code>null</code> means unqualified, and <code>DSpaceObject.ANY
   *     </code> means any qualifier (including unqualified.)
   * @param lang the ISO639 language code, optionally followed by an underscore and the ISO3166
   *     country code. <code>null</code> means only values with no language are returned, and <code>
   *     DSpaceObject.ANY</code> means values with any country code or no country code are returned.
   * @return metadata fields that match the parameters
   */
  public DCValue[] getMetadata(String schema, String element, String qualifier, String lang) {
    // Build up list of matching values
    List<DCValue> values = new ArrayList<DCValue>();
    for (DCValue dcv : getMetadata()) {
      if (match(schema, element, qualifier, lang, dcv)) {
        // We will return a copy of the object in case it is altered
        DCValue copy = new DCValue();
        copy.element = dcv.element;
        copy.qualifier = dcv.qualifier;
        copy.value = dcv.value;
        copy.language = dcv.language;
        copy.schema = dcv.schema;
        copy.authority = dcv.authority;
        copy.confidence = dcv.confidence;
        values.add(copy);
      }
    }

    // Create an array of matching values
    DCValue[] valueArray = new DCValue[values.size()];
    valueArray = (DCValue[]) values.toArray(valueArray);

    return valueArray;
  }
Beispiel #4
0
  /**
   * Add metadata fields. These are appended to existing values. Use <code>clearDC</code> to remove
   * values. The ordering of values passed in is maintained.
   *
   * @param schema the schema for the metadata field. <em>Must</em> match the <code>name</code> of
   *     an existing metadata schema.
   * @param element the metadata element name
   * @param qualifier the metadata qualifier name, or <code>null</code> for unqualified
   * @param lang the ISO639 language code, optionally followed by an underscore and the ISO3166
   *     country code. <code>null</code> means the value has no language (for example, a date).
   * @param values the values to add.
   * @param authorities the external authority key for this value (or null)
   * @param confidences the authority confidence (default 0)
   */
  public void addMetadata(
      String schema,
      String element,
      String qualifier,
      String lang,
      String[] values,
      String authorities[],
      int confidences[]) {
    List<DCValue> dublinCore = getMetadata();
    MetadataAuthorityManager mam = MetadataAuthorityManager.getManager();
    boolean authorityControlled = mam.isAuthorityControlled(schema, element, qualifier);
    boolean authorityRequired = mam.isAuthorityRequired(schema, element, qualifier);
    String fieldName = schema + "." + element + ((qualifier == null) ? "" : "." + qualifier);

    // We will not verify that they are valid entries in the registry
    // until update() is called.
    for (int i = 0; i < values.length; i++) {
      DCValue dcv = new DCValue();
      dcv.schema = schema;
      dcv.element = element;
      dcv.qualifier = qualifier;
      dcv.language = (lang == null ? null : lang.trim());

      // Logic to set Authority and Confidence:
      //  - normalize an empty string for authority to NULL.
      //  - if authority key is present, use given confidence or NOVALUE if not given
      //  - otherwise, preserve confidence if meaningful value was given since it may document a
      // failed authority lookup
      //  - CF_UNSET signifies no authority nor meaningful confidence.
      //  - it's possible to have empty authority & CF_ACCEPTED if e.g. user deletes authority key
      if (authorityControlled) {
        if (authorities != null && authorities[i] != null && authorities[i].length() > 0) {
          dcv.authority = authorities[i];
          dcv.confidence = confidences == null ? Choices.CF_NOVALUE : confidences[i];
        } else {
          dcv.authority = null;
          dcv.confidence = confidences == null ? Choices.CF_UNSET : confidences[i];
        }
        // authority sanity check: if authority is required, was it supplied?
        // XXX FIXME? can't throw a "real" exception here without changing all the callers to expect
        // it, so use a runtime exception
        if (authorityRequired && (dcv.authority == null || dcv.authority.length() == 0)) {
          throw new IllegalArgumentException(
              "The metadata field \""
                  + fieldName
                  + "\" requires an authority key but none was provided. Vaue=\""
                  + dcv.value
                  + "\"");
        }
      }
      if (values[i] != null) {
        // remove control unicode char
        String temp = values[i].trim();
        char[] dcvalue = temp.toCharArray();
        for (int charPos = 0; charPos < dcvalue.length; charPos++) {
          if (Character.isISOControl(dcvalue[charPos])
              && !String.valueOf(dcvalue[charPos]).equals("\u0009")
              && !String.valueOf(dcvalue[charPos]).equals("\n")
              && !String.valueOf(dcvalue[charPos]).equals("\r")) {
            dcvalue[charPos] = ' ';
          }
        }
        dcv.value = String.valueOf(dcvalue);
      } else {
        dcv.value = null;
      }
      dublinCore.add(dcv);
      addDetails(fieldName);
    }

    if (values.length > 0) {
      modifiedMetadata = true;
    }
  }
Beispiel #5
0
  public void updateMetadata() throws SQLException, AuthorizeException {
    // Map counting number of values for each element/qualifier.
    // Keys are Strings: "element" or "element.qualifier"
    // Values are Integers indicating number of values written for a
    // element/qualifier
    Map<String, Integer> elementCount = new HashMap<String, Integer>();

    modifiedMetadata = false;

    // Arrays to store the working information required
    int[] placeNum = new int[getMetadata().size()];
    boolean[] storedDC = new boolean[getMetadata().size()];
    MetadataField[] dcFields = new MetadataField[getMetadata().size()];

    // Work out the place numbers for the in memory DC
    for (int dcIdx = 0; dcIdx < getMetadata().size(); dcIdx++) {
      DCValue dcv = getMetadata().get(dcIdx);

      // Work out the place number for ordering
      int current = 0;

      // Key into map is "element" or "element.qualifier"
      String key = dcv.element + ((dcv.qualifier == null) ? "" : ("." + dcv.qualifier));

      Integer currentInteger = elementCount.get(key);
      if (currentInteger != null) {
        current = currentInteger.intValue();
      }

      current++;
      elementCount.put(key, Integer.valueOf(current));

      // Store the calculated place number, reset the stored flag, and cache the metadatafield
      placeNum[dcIdx] = current;
      storedDC[dcIdx] = false;
      dcFields[dcIdx] = getMetadataField(dcv);
      if (dcFields[dcIdx] == null) {
        // Bad DC field, log and throw exception
        log.warn("Invalid metadata field: [" + dcv.getField() + "] : [" + dcv.value + "]");
        throw new SQLException("Invalid metadata field: [" + dcv.getField() + "]");
      }
    }

    // Now the precalculations are done, iterate through the existing metadata
    // looking for matches
    TableRowIterator tri = retrieveMetadata();
    if (tri != null) {
      try {
        while (tri.hasNext()) {
          TableRow tr = tri.next();
          // Assume that we will remove this row, unless we get a match
          boolean removeRow = true;

          // Go through the in-memory metadata, unless we've already decided to keep this row
          for (int dcIdx = 0; dcIdx < getMetadata().size() && removeRow; dcIdx++) {
            // Only process if this metadata has not already been matched to something in the DB
            if (!storedDC[dcIdx]) {
              boolean matched = true;
              DCValue dcv = getMetadata().get(dcIdx);

              // Check the metadata field is the same
              if (matched && dcFields[dcIdx].getFieldID() != tr.getIntColumn("metadata_field_id")) {
                matched = false;
              }

              // Check the place is the same
              if (matched && placeNum[dcIdx] != tr.getIntColumn("place")) {
                matched = false;
              }

              // Check the text is the same
              if (matched) {
                String text = tr.getStringColumn("text_value");
                if (dcv.value == null && text == null) {
                  matched = true;
                } else if (dcv.value != null && dcv.value.equals(text)) {
                  matched = true;
                } else {
                  matched = false;
                }
              }

              // Check the language is the same
              if (matched) {
                String lang = tr.getStringColumn("text_lang");
                if (dcv.language == null && lang == null) {
                  matched = true;
                } else if (dcv.language != null && dcv.language.equals(lang)) {
                  matched = true;
                } else {
                  matched = false;
                }
              }

              // check that authority and confidence match
              if (matched) {
                String auth = tr.getStringColumn("authority");
                int conf = tr.getIntColumn("confidence");
                if (!((dcv.authority == null && auth == null)
                    || (dcv.authority != null && auth != null && dcv.authority.equals(auth))
                        && dcv.confidence == conf)) {
                  matched = false;
                }
              }

              // If the db record is identical to the in memory values
              if (matched) {
                // Flag that the metadata is already in the DB
                storedDC[dcIdx] = true;

                // Flag that we are not going to remove the row
                removeRow = false;
              }
            }
          }

          // If after processing all the metadata values, we didn't find a match
          // delete this row from the DB
          if (removeRow) {
            DatabaseManager.delete(ourContext, tr);
            modifiedMetadata = true;
          }
        }
      } finally {
        tri.close();
      }
    }

    // Add missing in-memory DC
    for (int dcIdx = 0; dcIdx < getMetadata().size(); dcIdx++) {
      // Only write values that are not already in the db
      if (!storedDC[dcIdx]) {
        DCValue dcv = getMetadata().get(dcIdx);

        // Write DCValue
        MetadataValue metadata = new MetadataValue();
        metadata.setResourceId(getID());
        metadata.setResourceTypeId(getType());
        metadata.setFieldId(dcFields[dcIdx].getFieldID());
        metadata.setValue(dcv.value);
        metadata.setLanguage(dcv.language);
        metadata.setPlace(placeNum[dcIdx]);
        metadata.setAuthority(dcv.authority);
        metadata.setConfidence(dcv.confidence);
        metadata.create(ourContext);
        modifiedMetadata = true;
      }
    }

    if (modifiedMetadata) {
      ourContext.addEvent(
          new Event(
              Event.MODIFY_METADATA, getType(), getID(), getDetails(), getIdentifiers(ourContext)));
      modifiedMetadata = false;
    }
  }