diff --git a/src/edu/ucsb/nceas/metacat/dataone/MNodeService.java b/src/edu/ucsb/nceas/metacat/dataone/MNodeService.java index 216920905..f4f25e427 100644 --- a/src/edu/ucsb/nceas/metacat/dataone/MNodeService.java +++ b/src/edu/ucsb/nceas/metacat/dataone/MNodeService.java @@ -2187,10 +2187,8 @@ public Identifier publish(Session session, Identifier originalIdentifier) throws logMetacat.info("MNodeService.publish - we find the old ore document "+potentialOreIdentifier+" for the metacat object "+originalIdentifier); Identifier newOreIdentifier = MNodeService.getInstance(request).generateIdentifier(session, MNodeService.UUID_SCHEME, null); ResourceMapModifier modifier = new ResourceMapModifier(potentialOreIdentifier, oreInputStream, newOreIdentifier); - Map obsoletedBys = new HashMap(); - obsoletedBys.put(originalIdentifier, newIdentifier); ByteArrayOutputStream out = new ByteArrayOutputStream(); - modifier.replaceObsoletedIds(obsoletedBys, out, session.getSubject()); + modifier.replaceObsoletedId(originalIdentifier, newIdentifier, out, session.getSubject()); String resourceMapString = out.toString("UTF-8"); // get the original ORE SM and update the values diff --git a/src/edu/ucsb/nceas/metacat/dataone/resourcemap/ResourceMapModifier.java b/src/edu/ucsb/nceas/metacat/dataone/resourcemap/ResourceMapModifier.java index 768258db5..d3e9b312b 100644 --- a/src/edu/ucsb/nceas/metacat/dataone/resourcemap/ResourceMapModifier.java +++ b/src/edu/ucsb/nceas/metacat/dataone/resourcemap/ResourceMapModifier.java @@ -58,6 +58,7 @@ /** * This class will create a new resource map by modifying a given resourceMap input stream. + * Note: this class can only be used on the mn.publish method since it will replace the all old pid existing places by the new id. It is only safe for the the mn.publish method. * @author tao * */ @@ -106,65 +107,71 @@ public ResourceMapModifier(Identifier oldResourceMapId, InputStream originalReso /** * Create new resource map by replacing obsoleted ids by new ids. - * @param obsoletedBys a map represents the ids' with the obsoletedBy relationship - the keys are the one need to be obsoleted (replaced); value are the new ones need to be used. They are all science metadata objects + * Note: this method can only be used on the mn.publish method since it will replace the all old pid existing places by the new id. It is only safe for the the mn.publish method. + * @param obsoletedId the pid will be replaced + * @param newId the pid will be used to replace the old pid * @param newResourceMap the place where the created new resource map will be written * @param subject the subject who generates the resource map * @throws UnsupportedEncodingException */ - public void replaceObsoletedIds(MapobsoletedBys, OutputStream newResourceMap, Subject subject) throws UnsupportedEncodingException { + public void replaceObsoletedId(Identifier obsoletedId, Identifier newId, OutputStream newResourceMap, Subject subject) throws UnsupportedEncodingException { //replace ids Vector oldURIs = new Vector(); //those uris (resource) shouldn't be aggregated into the new ore since they are obsoleted Vector newURIs = new Vector(); //those uris (resource) should be added into the new aggregation - if (obsoletedBys != null) { - Set ids = obsoletedBys.keySet(); - for (Identifier obsoletedId : ids) { - Vector needToRemove = new Vector(); - Identifier newId = obsoletedBys.get(obsoletedId); - Resource newResource = getResource(model, newId.getValue()); - if (newResource == null) { - newResource = generateNewComponent(model, newId.getValue()); - } - newURIs.add(newResource.getURI()); - Resource oldResource = getResource(model, obsoletedId.getValue()); - oldURIs.add(oldResource.getURI()); - if (oldResource != null) { - //replace the documents relationship - RDFNode node = null; - Selector selector = new SimpleSelector(oldResource, CITO.documents, node); - StmtIterator iterator = model.listStatements(selector); - while (iterator.hasNext()) { - Statement statement = iterator.nextStatement(); - RDFNode object = statement.getObject(); - //handle the case - oldId documents oldId + if (obsoletedId != null && newId != null) { + Vector needToRemove = new Vector(); + Resource newResource = getResource(model, newId.getValue()); + if (newResource == null) { + newResource = generateNewComponent(model, newId.getValue()); + } + newURIs.add(newResource.getURI()); + Resource oldResource = getResource(model, obsoletedId.getValue()); + oldURIs.add(oldResource.getURI()); + if (oldResource != null) { + //replace all subjects having the old pid resource + RDFNode node = null; + Property nullPredicate = null; + Selector selector = new SimpleSelector(oldResource, nullPredicate, node); + StmtIterator iterator = model.listStatements(selector); + while (iterator.hasNext()) { + Statement statement = iterator.nextStatement(); + RDFNode object = statement.getObject(); + Property predicate = statement.getPredicate(); + log.debug("ResourceMapModifer.replaceObsoletedIds - the statement with the predicate " + predicate.getLocalName() + " before replace"); + //we don't need to replace the relationship - DC_TERMS.identifier, just remove it + //handle the case - oldId predicates oldId + if(predicate == null || !predicate.equals(DC_TERMS.identifier)) { if (object.isResource()) { Resource objResource = (Resource) object; if (objResource.getURI().equals(oldResource.getURI())) { object = newResource; } } - Statement newStatement = ResourceFactory.createStatement(newResource, CITO.documents, object); - needToRemove.add(statement); - model.add(newStatement); - } - //replace the documentedBy relationship - Resource nullSubject = null; - selector = new SimpleSelector(nullSubject, CITO.isDocumentedBy, oldResource); - iterator = model.listStatements(selector); - while (iterator.hasNext()) { - Statement statement = iterator.nextStatement(); - Resource subj = statement.getSubject(); - //handle the case - oldId isDocumentBy oldId - if (subj.getURI().equals(oldResource.getURI())) { - subj = newResource; - } - Statement newStatement = ResourceFactory.createStatement(subj, CITO.isDocumentedBy, newResource); - needToRemove.add(statement); + log.debug("ResourceMapModifer.replaceObsoletedIds - the statement with the predicate " + predicate.getLocalName() + " has been replaced"); + Statement newStatement = ResourceFactory.createStatement(newResource, predicate, object); model.add(newStatement); } - //remove those old documents/isDocumentedBy relationships - for (Statement oldStatement : needToRemove) { - model.remove(oldStatement); + needToRemove.add(statement); + } + //replace all objects having the old pid resource + Resource nullSubject = null; + selector = new SimpleSelector(nullSubject, nullPredicate, oldResource); + iterator = model.listStatements(selector); + while (iterator.hasNext()) { + Statement statement = iterator.nextStatement(); + Resource subj = statement.getSubject(); + Property predicate = statement.getPredicate(); + //handle the case - oldId predicates oldId + if (subj.getURI().equals(oldResource.getURI())) { + subj = newResource; } + Statement newStatement = ResourceFactory.createStatement(subj, predicate, newResource); + model.add(newStatement); + needToRemove.add(statement); + } + //remove those old relationships + for (Statement oldStatement : needToRemove) { + model.remove(oldStatement); } } } diff --git a/test/edu/ucsb/nceas/metacat/dataone/resourcemap/ResourceMapModifierTest.java b/test/edu/ucsb/nceas/metacat/dataone/resourcemap/ResourceMapModifierTest.java index 6d806689c..eada5f1e8 100644 --- a/test/edu/ucsb/nceas/metacat/dataone/resourcemap/ResourceMapModifierTest.java +++ b/test/edu/ucsb/nceas/metacat/dataone/resourcemap/ResourceMapModifierTest.java @@ -115,16 +115,14 @@ public void testReplaceObsoletedIds() throws Exception { Identifier new_resourceMap_id = new Identifier(); new_resourceMap_id.setValue(NEW_RESOURCEMAP_PID); ResourceMapModifier modifier = new ResourceMapModifier(origin_resourceMap_id, resourceMapInputStream, new_resourceMap_id); - HashMap obsoletedBys = new HashMap(); Identifier origin_metadata_id = new Identifier(); origin_metadata_id.setValue(ORIGNAL_METADATA_PID); Identifier new_metadata_id = new Identifier(); new_metadata_id.setValue(NEW_METADATA_PID); - obsoletedBys.put(origin_metadata_id, new_metadata_id); ByteArrayOutputStream out = new ByteArrayOutputStream(); Subject subj = new Subject(); subj.setValue("foo"); - modifier.replaceObsoletedIds(obsoletedBys, out, subj); + modifier.replaceObsoletedId(origin_metadata_id, new_metadata_id, out, subj); String outStr = out.toString("UTF-8"); System.out.println(outStr); ByteArrayInputStream in = new ByteArrayInputStream(outStr.getBytes("UTF-8")); @@ -222,6 +220,26 @@ public void testReplaceObsoletedIds() throws Exception { for(Identifier id : dataFileIds) { assertTrue(id.getValue().equals(DATA_1_PID) || id.getValue().equals(DATA_2_PID) || id.getValue().equals(NEW_METADATA_PID)); } + + //no old ore triples + Resource oldOreResource = ResourceFactory.createResource("https://cn.dataone.org/cn/v2/resolve/urn%3Auuid%3Ae62c781c-643b-41f3-a0b0-9f6cbd80a708"); + subject = null; + predicate = null; + object = null; + selector = new SimpleSelector(oldOreResource, predicate, object); + iterator = model.listStatements(selector); + assertFalse(iterator.hasNext()); + selector = new SimpleSelector(subject, predicate, oldOreResource); + iterator = model.listStatements(selector); + assertFalse(iterator.hasNext()); + //no old metadata triples + Resource oldMetadataResource = ResourceFactory.createResource("https://cn.dataone.org/cn/v2/resolve/urn%3Auuid%3Ac0e0d342-7cc1-4eaa-9648-c6d9f7ed8b1f"); + selector = new SimpleSelector(oldMetadataResource, predicate, object); + iterator = model.listStatements(selector); + assertFalse(iterator.hasNext()); + selector = new SimpleSelector(subject, predicate, oldMetadataResource); + iterator = model.listStatements(selector); + assertFalse(iterator.hasNext()); resourceMapInputStream.close(); }