/******************************************************************************* * 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.regex.Pattern; 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 org.vivoweb.harvester.util.repo.MemJenaConnect; import com.hp.hpl.jena.rdf.model.Literal; 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.rdf.model.StmtIterator; import com.hp.hpl.jena.shared.Lock; /** * Changes the namespace for all matching uris * @author Cornell University VIVO Team (Algorithm) * @author Christopher Haines (hainesc@ctrip.ufl.edu) (Harvester Tool) */ public class SplitProperty { /** * SLF4J Logger */ private static Logger log = LoggerFactory.getLogger(SplitProperty.class); /** * model to split property values in */ private JenaConnect model; /** * regex to split oldPropertyURI value on */ private String splitRegex; /** * old property uri (to be split) */ private String oldPropertyURI; /** * new property uri (to store split values in) */ private String newPropertyURI; /** * trim() the new values */ private boolean trim; /** * Constructor * @param args commandline arguments * @throws IOException error creating task * @throws UsageException user requested usage message */ private SplitProperty(String[] args) throws IOException, UsageException { this(getParser().parse(args)); } /** * Constructor * @param model model to split property values in * @param splitRegex regex to split oldPropertyURI value on * @param oldPropertyURI old property uri (to be split) * @param newPropertyURI new property uri (to store split values in) * @param trim trim() the new values */ public SplitProperty(JenaConnect model, String splitRegex, String oldPropertyURI, String newPropertyURI, boolean trim) { if(model == null) { throw new IllegalArgumentException("No model provided! Must provide a model"); } this.model = model; this.splitRegex = splitRegex; this.oldPropertyURI = oldPropertyURI; this.newPropertyURI = newPropertyURI; this.trim = trim; } /** * Constructor * @param argList parsed argument list * @throws IOException error reading config */ private SplitProperty(ArgList argList) throws IOException { this( JenaConnect.parseConfig(argList.get("i"), argList.getValueMap("I")), argList.get("r"), argList.get("u"), argList.get("n"), argList.has("t") ); } /** * Splits values for a given data property URI on a supplied regex and * asserts each value using newPropertyURI. New statements returned in * a Jena Model. Split values may be optionally trim()ed. * @param model model to split property values in * @param splitRegex regex to split oldPropertyURI value on * @param oldPropertyURI old property uri (to be split) * @param newPropertyURI new property uri (to store split values in) * @param trim trim() the new values * @return outModel */ public static JenaConnect splitPropertyValues(JenaConnect model, String oldPropertyURI, String splitRegex, String newPropertyURI, boolean trim) { JenaConnect outModel = new MemJenaConnect(); Pattern delimiterPattern = Pattern.compile(splitRegex); Property theProp = ResourceFactory.createProperty(oldPropertyURI); Property newProp = ResourceFactory.createProperty(newPropertyURI); model.getJenaModel().enterCriticalSection(Lock.READ); try { StmtIterator stmtIt = model.getJenaModel().listStatements( (Resource)null, theProp, (RDFNode)null ); try { while(stmtIt.hasNext()) { Statement stmt = stmtIt.nextStatement(); Resource subj = stmt.getSubject(); RDFNode obj = stmt.getObject(); if (obj.isLiteral()) { Literal lit = (Literal) obj; String unsplitStr = lit.getLexicalForm(); String[] splitPieces = delimiterPattern.split(unsplitStr); for (int i=0; i<splitPieces.length; i++) { String newLexicalForm = splitPieces[i]; if (trim) { newLexicalForm = newLexicalForm.trim(); } if (newLexicalForm.length() > 0) { Literal newLiteral = null; if (lit.getDatatype() != null) { newLiteral = outModel.getJenaModel().createTypedLiteral(newLexicalForm, lit.getDatatype()); } else { if (lit.getLanguage() != null) { newLiteral = outModel.getJenaModel().createLiteral(newLexicalForm, lit.getLanguage()); } else { newLiteral = outModel.getJenaModel().createLiteral(newLexicalForm); } } outModel.getJenaModel().add(subj,newProp,newLiteral); } } } } } finally { stmtIt.close(); } } finally { model.getJenaModel().leaveCriticalSection(); } return outModel; } /** * Split Property Values */ public void execute() { this.model.loadRdfFromJC(splitPropertyValues(this.model, this.splitRegex, this.oldPropertyURI, this.newPropertyURI, this.trim)); this.model.sync(); } /** * Get the ArgParser for this task * @return the ArgParser */ private static ArgParser getParser() { ArgParser parser = new ArgParser("SplitProperty"); // Inputs parser.addArgument(new ArgDef().setShortOption('i').setLongOpt("inputModel").withParameter(true, "CONFIG_FILE").setDescription("config file for jena model").setRequired(false)); parser.addArgument(new ArgDef().setShortOption('I').setLongOpt("inputModelOverride").withParameterValueMap("JENA_PARAM", "VALUE").setDescription("override the JENA_PARAM of jena model config using VALUE").setRequired(false)); // Params parser.addArgument(new ArgDef().setShortOption('r').setLongOpt("regex").withParameter(true, "SPLIT_REGEX").setDescription("regex to split oldPropertyURI value on").setRequired(true)); parser.addArgument(new ArgDef().setShortOption('u').setLongOpt("oldPropertyURI").withParameter(true, "OLD_PREDICATE").setDescription("old property uri (to be split)").setRequired(true)); parser.addArgument(new ArgDef().setShortOption('n').setLongOpt("newPropertyURI").withParameter(true, "NEW_PREDICATE").setDescription("new property uri (to store split values in)").setRequired(true)); parser.addArgument(new ArgDef().setShortOption('t').setLongOpt("trim").setDescription("trim() the new values").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 SplitProperty(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); } } } }