| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package jena; |
| |
| |
| import static org.apache.jena.atlas.logging.LogCtl.setCmdLogging; |
| |
| import java.util.*; |
| import java.io.*; |
| |
| import org.apache.commons.cli.CommandLine; |
| import org.apache.commons.cli.CommandLineParser; |
| import org.apache.commons.cli.DefaultParser; |
| import org.apache.commons.cli.Options; |
| import org.apache.jena.graph.* ; |
| import org.apache.jena.rdf.model.* ; |
| import org.apache.jena.reasoner.Reasoner ; |
| import org.apache.jena.reasoner.rulesys.* ; |
| import org.apache.jena.reasoner.rulesys.builtins.BaseBuiltin ; |
| import org.apache.jena.util.FileManager ; |
| import org.apache.jena.util.FileUtils ; |
| |
| /** |
| * General command line utility to process one RDF file into another |
| * by application of a set of forward chaining rules. |
| * <pre> |
| * Usage: RuleMap [-il inlang] [-ol outlang] [-d] rulefile infile |
| * </pre> |
| * The resulting RDF data is written to stdout in format <code>outlang</code> |
| * (default N3). If <code>-d</code> is given then only the deductions |
| * generated by the rules are output. Otherwise all data including any input |
| * data (other than any removed triples) is output. |
| * <p> |
| * Rules are permitted an additional action "deduce" which forces triples |
| * to be added to the deductions graph even if they are already known (for use |
| * in deductions only mode). |
| * </p> |
| */ |
| public class RuleMap { |
| static { setCmdLogging() ; } |
| |
| /** |
| * Load a set of rule definitions including processing of |
| * comment lines and any initial prefix definition lines. |
| * Also notes the prefix definitions for adding to a later inf model. |
| */ |
| public static List<Rule> loadRules(String filename, Map<String, String> prefixes) { |
| String fname = filename; |
| if (fname.startsWith("file:///")) { |
| fname = File.separator + fname.substring(8); |
| } else if (fname.startsWith("file:/")) { |
| fname = File.separator + fname.substring(6); |
| } else if (fname.startsWith("file:")) { |
| fname = fname.substring(5); |
| } |
| |
| BufferedReader src = FileUtils.openResourceFile(fname); |
| return loadRules(src, prefixes); |
| } |
| |
| /** |
| * Load a set of rule definitions including processing of |
| * comment lines and any initial prefix definition lines. |
| * Also notes the prefix definitions for adding to a later inf model. |
| */ |
| public static List<Rule> loadRules(BufferedReader src, Map<String, String> prefixes) { |
| Rule.Parser parser = Rule.rulesParserFromReader(src); |
| List<Rule> rules = Rule.parseRules(parser); |
| prefixes.putAll(parser.getPrefixMap()); |
| return rules; |
| } |
| |
| /** |
| * Internal implementation of the "deduce" primitve. |
| * This takes the form <code> ... -> deduce(s, p, o)</code> |
| */ |
| static class Deduce extends BaseBuiltin { |
| |
| /** |
| * Return a name for this builtin, normally this will be the name of the |
| * functor that will be used to invoke it. |
| */ |
| @Override |
| public String getName() { |
| return "deduce"; |
| } |
| |
| /** |
| * Return the expected number of arguments for this functor or 0 if the number is flexible. |
| */ |
| @Override |
| public int getArgLength() { |
| return 3; |
| } |
| |
| /** |
| * This method is invoked when the builtin is called in a rule head. |
| * Such a use is only valid in a forward rule. |
| * @param args the array of argument values for the builtin, this is an array |
| * of Nodes. |
| * @param length the length of the argument list, may be less than the length of the args array |
| * for some rule engines |
| * @param context an execution context giving access to other relevant data |
| */ |
| @Override |
| public void headAction(Node[] args, int length, RuleContext context) { |
| if (context.getGraph() instanceof FBRuleInfGraph) { |
| Triple t = new Triple(args[0], args[1], args[2]); |
| ((FBRuleInfGraph)context.getGraph()).addDeduction(t); |
| } else { |
| throw new BuiltinException(this, context, "Only usable in FBrule graphs"); |
| } |
| } |
| } |
| |
| /** |
| * General command line utility to process one RDF file into another |
| * by application of a set of forward chaining rules. |
| * <pre> |
| * Usage: RuleMap [-il inlang] [-ol outlang] -d infile rulefile |
| * </pre> |
| */ |
| public static void main(String[] args) { |
| try { |
| |
| // Parse the command line |
| String usage = "Usage: RuleMap [-il inlang] [-ol outlang] [-d] rulefile infile (- for stdin)"; |
| final CommandLineParser parser = new DefaultParser(); |
| Options options = new Options().addOption("il", "inputLang", true, "input language") |
| .addOption("ol", "outputLang", true, "output language").addOption("d", "Deductions only?"); |
| CommandLine cl = parser.parse(options, args); |
| final List<String> filenameArgs = cl.getArgList(); |
| if (filenameArgs.size() != 2) { |
| System.err.println(usage); |
| System.exit(1); |
| } |
| |
| String inLang = cl.getOptionValue("inputLang"); |
| String fname = filenameArgs.get(1); |
| Model inModel = null; |
| if (fname.equals("-")) { |
| inModel = ModelFactory.createDefaultModel(); |
| inModel.read(System.in, null, inLang); |
| } else { |
| inModel = FileManager.get().loadModel(fname, inLang); |
| } |
| |
| String outLang = cl.hasOption("outputLang") ? cl.getOptionValue("outputLang") : "N3"; |
| |
| boolean deductionsOnly = cl.hasOption('d'); |
| |
| // Fetch the rule set and create the reasoner |
| BuiltinRegistry.theRegistry.register(new Deduce()); |
| Map<String, String> prefixes = new HashMap<>(); |
| List<Rule> rules = loadRules(filenameArgs.get(0), prefixes); |
| Reasoner reasoner = new GenericRuleReasoner(rules); |
| |
| // Process |
| InfModel infModel = ModelFactory.createInfModel(reasoner, inModel); |
| infModel.prepare(); |
| infModel.setNsPrefixes(prefixes); |
| |
| // Output |
| try ( PrintWriter writer = new PrintWriter(System.out) ) { |
| if (deductionsOnly) { |
| Model deductions = infModel.getDeductionsModel(); |
| deductions.setNsPrefixes(prefixes); |
| deductions.setNsPrefixes(inModel); |
| deductions.write(writer, outLang); |
| } else { |
| infModel.write(writer, outLang); |
| } |
| } |
| } catch (Throwable t) { |
| System.err.println("An error occured: \n" + t); |
| t.printStackTrace(); |
| } |
| } |
| |
| } |