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); } } } }
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; }
/** * 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; }
/** * 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; } }
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; } }