/*******************************************************************************
* Copyright (c) 2010-2011 VIVO Harvester Team. For full list of contributors, please see the AUTHORS file provided.
* All rights reserved.
* This program and the accompanying materials are made available under the terms of the new BSD license which accompanies this distribution, and is available at http://www.opensource.org/licenses/bsd-license.html
******************************************************************************/
package org.vivoweb.harvester.qualify;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vivoweb.harvester.util.InitLog;
import org.vivoweb.harvester.util.args.ArgDef;
import org.vivoweb.harvester.util.args.ArgList;
import org.vivoweb.harvester.util.args.ArgParser;
import org.vivoweb.harvester.util.args.UsageException;
import org.vivoweb.harvester.util.repo.JenaConnect;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.util.iterator.ClosableIterator;
/**
* Find nodes with no name and give them a name
* @author Michael Barbieri (mbarbier@ufl.edu)
*/
public class RenameBlankNodes {
/**
* SLF4J Logger
*/
private static Logger log = LoggerFactory.getLogger(RenameBlankNodes.class);
/**
* The model to perform rename in
*/
private final JenaConnect inJC;
/**
* The model to contain renamed nodes
*/
private final JenaConnect outJC;
/**
* The part of the namespace between the base and the ID number
*/
private final String namespaceEtc;
/**
* deduplication test model
*/
private final JenaConnect dedupJC;
/**
* pattern
*/
private final String pattern;
/**
* property
*/
private final String property;
/**
* Constructor
* @param args commandline arguments
* @throws IOException error creating task
* @throws UsageException user requested usage message
*/
private RenameBlankNodes(String[] args) throws IOException, UsageException {
this(getParser().parse(args));
}
/**
* Constructor
* @param inJC The model to perform rename in
* @param outJC The model to write output to
* @param namespaceEtc The part of the namespace between the base and the ID number
* @param dedupJC deduplication test model
* @param pattern pattern
* @param property property
*/
public RenameBlankNodes(JenaConnect inJC, JenaConnect outJC, String namespaceEtc, JenaConnect dedupJC, String pattern, String property) {
this.inJC = inJC;
this.outJC = outJC;
this.namespaceEtc = namespaceEtc;
this.dedupJC = dedupJC;
this.pattern = pattern;
this.property = property;
if(this.inJC == null) {
throw new IllegalArgumentException("Must provide an input jena model");
}
if(this.outJC == null) {
throw new IllegalArgumentException("Must provide an output jena model");
}
}
/**
* Constructor
* @param argList parsed argument list
* @throws IOException error reading config
*/
private RenameBlankNodes(ArgList argList) throws IOException {
this(
JenaConnect.parseConfig(argList.get("i"), argList.getValueMap("I")),
JenaConnect.parseConfig(argList.get("o"), argList.getValueMap("O")),
argList.get("n"),
JenaConnect.parseConfig(argList.get("d"), argList.getValueMap("D")),
argList.get("t"),
argList.get("p")
);
}
/**
* Rename blank nodes
* @param inJC The model to perform rename in
* @param outJC The model to write output to
* @param namespaceEtc The part of the namespace between the base and the ID number
* @param dedupJC deduplication test model
* @param pattern pattern
* @param property property
*/
public static void renameBNodes(JenaConnect inJC, JenaConnect outJC, String namespaceEtc, JenaConnect dedupJC, String pattern, String property) {
Model inModel = inJC.getJenaModel();
Model outModel = outJC.getJenaModel();
Model dedupModel = dedupJC.getJenaModel();
Property propertyRes = ResourceFactory.createProperty(property);
OntModel dedupUnionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); // we're not using OWL here, just the OntModel submodel infrastructure
dedupUnionModel.addSubModel(outModel);
if (dedupModel != null) {
dedupUnionModel.addSubModel(dedupModel);
}
// the dedupUnionModel is so we can guard against reusing a URI in an
// existing model, as well as in the course of running this process
inModel.enterCriticalSection(Lock.READ);
Set<String> doneSet = new HashSet<String>();
try {
outJC.loadRdfFromJC(inJC);
ClosableIterator<Resource> closeIt = inModel.listSubjects();
try {
for (Iterator<Resource> it = closeIt; it.hasNext();) {
Resource res = it.next();
if (res.isAnon() && !(doneSet.contains(res.getId()))) {
// now we do something hacky to get the same resource in the outModel, since there's no getResourceById();
ClosableIterator<Statement> closfIt = outModel.listStatements(res,propertyRes,(RDFNode)null);
Statement stmt = null;
try {
if (closfIt.hasNext()) {
stmt = closfIt.next();
}
} finally {
closfIt.close();
}
if (stmt != null) {
Resource outRes = stmt.getSubject();
if(stmt.getObject().isLiteral()){
RenameResources.renameResource(outRes,namespaceEtc+pattern+"_"+stmt.getObject().toString());
}
doneSet.add(res.getId().toString());
}
}
}
} finally {
closeIt.close();
}
} finally {
inModel.leaveCriticalSection();
}
}
/**
* Rename blank nodes
*/
public void execute() {
renameBNodes(this.inJC, this.outJC, this.namespaceEtc, this.dedupJC, this.pattern, this.property);
this.inJC.sync();
this.outJC.sync();
}
/**
* Get the ArgParser for this task
* @return the ArgParser
*/
private static ArgParser getParser() {
ArgParser parser = new ArgParser("RenameBlankNodes");
parser.addArgument(new ArgDef().setShortOption('i').setLongOpt("inputModel").withParameter(true, "CONFIG_FILE").setDescription("config file for input jena model").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('I').setLongOpt("inputModelOverride").withParameterValueMap("JENA_PARAM", "VALUE").setDescription("override the JENA_PARAM of input jena model config using VALUE").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('o').setLongOpt("outputModel").withParameter(true, "CONFIG_FILE").setDescription("config file for output jena model").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('O').setLongOpt("outputModelOverride").withParameterValueMap("JENA_PARAM", "VALUE").setDescription("override the JENA_PARAM of output jena model config using VALUE").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('d').setLongOpt("dedupModel").withParameter(true, "CONFIG_FILE").setDescription("optional: config file for deduplication test jena model").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('D').setLongOpt("dedupModelOverride").withParameterValueMap("JENA_PARAM", "VALUE").setDescription("override the JENA_PARAM of deduplication test jena model config using VALUE").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('n').setLongOpt("namespaceEtc").withParameter(true, "NAMESPACE_ETC").setDescription("part of the namespace between the base and the ID number").setRequired(true));
parser.addArgument(new ArgDef().setShortOption('t').setLongOpt("pattern").withParameter(true, "PATTERN").setDescription("pattern").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('p').setLongOpt("property").withParameter(true, "PROPERTY").setDescription("property").setRequired(false));
return parser;
}
/**
* Main method
* @param args commandline arguments
*/
public static void main(String... args) {
Exception error = null;
try {
InitLog.initLogger(args, getParser());
log.info(getParser().getAppName() + ": Start");
new RenameBlankNodes(args).execute();
} catch(IllegalArgumentException e) {
log.error(e.getMessage());
log.debug("Stacktrace:",e);
System.out.println(getParser().getUsage());
error = e;
} catch(UsageException e) {
log.info("Printing Usage:");
System.out.println(getParser().getUsage());
error = e;
} catch(Exception e) {
log.error(e.getMessage());
log.debug("Stacktrace:",e);
error = e;
} finally {
log.info(getParser().getAppName() + ": End");
if(error != null) {
System.exit(1);
}
}
}
}