001: /******************************************************************
002: * File: Util.java
003: * Created by: Dave Reynolds
004: * Created on: 11-Apr-2003
005: *
006: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
007: * [See end of file]
008: * $Id: Util.java,v 1.30 2008/01/02 12:07:48 andy_seaborne Exp $
009: *****************************************************************/package com.hp.hpl.jena.reasoner.rulesys;
010:
011: import com.hp.hpl.jena.graph.*;
012: import com.hp.hpl.jena.graph.impl.*;
013: import com.hp.hpl.jena.rdf.model.*;
014: import com.hp.hpl.jena.reasoner.Finder;
015: import com.hp.hpl.jena.reasoner.IllegalParameterException;
016: import com.hp.hpl.jena.reasoner.TriplePattern;
017: import com.hp.hpl.jena.util.FileUtils;
018: import com.hp.hpl.jena.util.iterator.ClosableIterator;
019: import com.hp.hpl.jena.vocabulary.RDF;
020: import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
021:
022: import java.io.*;
023: import java.util.*;
024:
025: //Thanks to Bradley Schatz (Bradley@greystate.com) for code patches
026: //to support XSDDateTime comparisons
027:
028: /**
029: * A small random collection of utility functions used by the rule systems.
030: *
031: * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
032: * @version $Revision: 1.30 $ on $Date: 2008/01/02 12:07:48 $
033: */
034: public class Util {
035:
036: /**
037: * Check whether a Node is a numeric (integer) value
038: */
039: public static boolean isNumeric(Node n) {
040: return n.isLiteral() && n.getLiteralValue() instanceof Number;
041: }
042:
043: /**
044: * Return the integer value of a literal node
045: */
046: public static int getIntValue(Node n) {
047: return ((Number) n.getLiteralValue()).intValue();
048: }
049:
050: /**
051: * Compare two numeric nodes.
052: * @param n1 the first numeric valued literal node
053: * @param n2 the second numeric valued literal node
054: * @return -1 if n1 is less than n2, 0 if n1 equals n2 and +1 if n1 greater than n2
055: * @throws ClassCastException if either node is not numeric
056: */
057: public static int compareNumbers(Node n1, Node n2) {
058: if (n1.isLiteral() && n2.isLiteral()) {
059: Object v1 = n1.getLiteralValue();
060: Object v2 = n2.getLiteralValue();
061: if (v1 instanceof Number && v2 instanceof Number) {
062: if (v1 instanceof Float || v1 instanceof Double
063: || v2 instanceof Float || v2 instanceof Double) {
064: double d1 = ((Number) v1).doubleValue();
065: double d2 = ((Number) v2).doubleValue();
066: return (d1 < d2) ? -1 : ((d1 == d2) ? 0 : +1);
067: } else {
068: long l1 = ((Number) v1).longValue();
069: long l2 = ((Number) v2).longValue();
070: return (l1 < l2) ? -1 : ((l1 == l2) ? 0 : +1);
071: }
072: }
073: }
074: throw new ClassCastException(
075: "Non-numeric literal in compareNumbers");
076: }
077:
078: /**
079: * Check whether a Node is an Instant (DateTime) value
080: */
081: public static boolean isInstant(Node n) {
082: if (n.isLiteral()) {
083: Object o = n.getLiteralValue();
084: return (o instanceof XSDDateTime);
085: } else {
086: return false;
087: }
088: }
089:
090: /**
091: * Compare two time Instant nodes.
092: * @param n1 the first time instant (XSDDateTime) valued literal node
093: * @param n2 the second time instant (XSDDateTime) valued literal node
094: * @return -1 if n1 is less than n2, 0 if n1 equals n2 and +1 if n1 greater than n2
095: * @throws ClassCastException if either not is not numeric
096: */
097: public static int compareInstants(Node n1, Node n2) {
098: if (n1.isLiteral() && n2.isLiteral()) {
099: Object v1 = n1.getLiteralValue();
100: Object v2 = n2.getLiteralValue();
101: if (v1 instanceof XSDDateTime && v2 instanceof XSDDateTime) {
102: XSDDateTime a = (XSDDateTime) v1;
103: XSDDateTime b = (XSDDateTime) v2;
104: return a.compare(b);
105: }
106: }
107: throw new ClassCastException(
108: "Non-numeric literal in compareNumbers");
109: }
110:
111: /**
112: * Helper - returns the (singleton) value for the given property on the given
113: * root node in the data graph.
114: */
115: public static Node getPropValue(Node root, Node prop, Finder context) {
116: return doGetPropValue(context.find(new TriplePattern(root,
117: prop, null)));
118: }
119:
120: /**
121: * Helper - returns the (singleton) value for the given property on the given
122: * root node in the data graph.
123: */
124: public static Node getPropValue(Node root, Node prop, Graph context) {
125: return doGetPropValue(context.find(root, prop, null));
126: }
127:
128: /**
129: * Helper - returns the (singleton) value for the given property on the given
130: * root node in the data graph.
131: */
132: public static Node getPropValue(Node root, Node prop,
133: RuleContext context) {
134: return doGetPropValue(context.find(root, prop, null));
135: }
136:
137: /**
138: * Internall implementation of all the getPropValue variants.
139: */
140: private static Node doGetPropValue(ClosableIterator it) {
141: Node result = null;
142: if (it.hasNext()) {
143: result = ((Triple) it.next()).getObject();
144: }
145: it.close();
146: return result;
147: }
148:
149: /**
150: * Convert an (assumed well formed) RDF list to a java list of Nodes
151: * @param root the root node of the list
152: * @param context the graph containing the list assertions
153: */
154: public static List convertList(Node root, RuleContext context) {
155: return convertList(root, context, new LinkedList());
156: }
157:
158: /**
159: * Convert an (assumed well formed) RDF list to a java list of Nodes
160: */
161: private static List convertList(Node node, RuleContext context,
162: List sofar) {
163: if (node == null || node.equals(RDF.nil.asNode()))
164: return sofar;
165: Node next = getPropValue(node, RDF.first.asNode(), context);
166: if (next != null) {
167: sofar.add(next);
168: return convertList(getPropValue(node, RDF.rest.asNode(),
169: context), context, sofar);
170: } else {
171: return sofar;
172: }
173: }
174:
175: /**
176: * Construct a new integer valued node
177: */
178: public static Node makeIntNode(int value) {
179: return Node.createLiteral(new LiteralLabel(new Integer(value)));
180: }
181:
182: /**
183: * Construct a new long valued node
184: */
185: public static Node makeLongNode(long value) {
186: if (value > Integer.MAX_VALUE) {
187: return Node
188: .createLiteral(new LiteralLabel(new Long(value)));
189: } else {
190: return Node.createLiteral(new LiteralLabel(new Integer(
191: (int) value)));
192: }
193: }
194:
195: /**
196: * Construct a new double valued node
197: */
198: public static Node makeDoubleNode(double value) {
199: return Node.createLiteral(new LiteralLabel(new Double(value)));
200: }
201:
202: /**
203: * Construct an RDF list from the given array of nodes and assert it
204: * in the graph returning the head of the list.
205: */
206: public static Node makeList(Node[] nodes, Graph graph) {
207: return doMakeList(nodes, 0, graph);
208: }
209:
210: /**
211: * Internals of makeList.
212: */
213: private static Node doMakeList(Node[] nodes, int next, Graph graph) {
214: if (next < nodes.length) {
215: Node listNode = Node.createAnon();
216: graph
217: .add(new Triple(listNode, RDF.Nodes.first,
218: nodes[next]));
219: graph.add(new Triple(listNode, RDF.Nodes.rest, doMakeList(
220: nodes, next + 1, graph)));
221: return listNode;
222: } else {
223: return RDF.Nodes.nil;
224: }
225: }
226:
227: /**
228: * Open a resource file and read it all into a single string.
229: * Treats lines starting with # as comment lines, as per stringFromReader.
230: * @deprecated Use loadRuleParserFromResourceFile
231: */
232: public static String loadResourceFile(String filename) {
233: return Rule.rulesStringFromReader(FileUtils
234: .openResourceFile(filename));
235: }
236:
237: /**
238: * Open a resource file and read it all into a single string.
239: * Treats lines starting with # as comment lines, as per stringFromReader
240: */
241: public static Rule.Parser loadRuleParserFromResourceFile(
242: String filename) {
243: return Rule.rulesParserFromReader(FileUtils
244: .openResourceFile(filename));
245: }
246:
247: /**
248: * Open a file defined by a URL and read all of it into a single string.
249: * If the URL fails it will try a plain file name as well.
250: */
251: public static String loadURLFile(String urlStr) throws IOException {
252: BufferedReader dataReader = FileUtils.readerFromURL(urlStr);
253: StringWriter sw = new StringWriter(1024);
254: char buff[] = new char[1024];
255: while (dataReader.ready()) {
256: int l = dataReader.read(buff);
257: if (l <= 0)
258: break;
259: sw.write(buff, 0, l);
260: }
261: dataReader.close();
262: sw.close();
263: return sw.toString();
264: }
265:
266: /**
267: * Helper method - extracts the truth of a boolean configuration
268: * predicate.
269: * @param predicate the predicate to be tested
270: * @param configuration the configuration node
271: * @return null if there is no setting otherwise a Boolean giving the setting value
272: */
273: public static Boolean checkBinaryPredicate(Property predicate,
274: Resource configuration) {
275: StmtIterator i = configuration.listProperties(predicate);
276: if (i.hasNext()) {
277: return new Boolean(i.nextStatement().getObject().toString()
278: .equalsIgnoreCase("true"));
279: } else {
280: return null;
281: }
282: }
283:
284: /**
285: * Helper method - extracts the value of an integer configuration
286: * predicate.
287: * @param predicate the predicate to be tested
288: * @param configuration the configuration node
289: * @return null if there is no such configuration parameter otherwise the value as an integer
290: */
291: public static Integer getIntegerPredicate(Property predicate,
292: Resource configuration) {
293: StmtIterator i = configuration.listProperties(predicate);
294: if (i.hasNext()) {
295: RDFNode lit = i.nextStatement().getObject();
296: if (lit instanceof Literal) {
297: return new Integer(((Literal) lit).getInt());
298: }
299: }
300: return null;
301: }
302:
303: /**
304: * Convert the value of a boolean configuration parameter to a boolean value.
305: * Allows the value to be specified using a String or Boolean.
306: * @param parameter the configuration property being set (to help with error messages)
307: * @param value the parameter value
308: * @return the converted value
309: * @throws IllegalParameterException if the value can't be converted
310: */
311: public static boolean convertBooleanPredicateArg(
312: Property parameter, Object value) {
313: if (value instanceof Boolean) {
314: return ((Boolean) value).booleanValue();
315: } else if (value instanceof String) {
316: return ((String) value).equalsIgnoreCase("true");
317: } else {
318: throw new IllegalParameterException("Illegal type for "
319: + parameter + " setting - use a Boolean");
320: }
321:
322: }
323:
324: /**
325: * Convert the value of an integer configuration parameter to an int value.
326: * Allows the value to be specified using a String or Number.
327: * @param parameter the configuration property being set (to help with error messages)
328: * @param value the parameter value
329: * @return the converted value
330: * @throws IllegalParameterException if the value can't be converted
331: */
332: public static int convertIntegerPredicateArg(Property parameter,
333: Object value) {
334: if (value instanceof Number) {
335: return ((Number) value).intValue();
336: } else if (value instanceof String) {
337: try {
338: return Integer.parseInt((String) value);
339: } catch (NumberFormatException e) {
340: throw new IllegalParameterException("Illegal type for "
341: + parameter + " setting - use an integer");
342: }
343: } else {
344: throw new IllegalParameterException("Illegal type for "
345: + parameter + " setting - use an integer");
346: }
347: }
348:
349: /**
350: * Replace the value for a given parameter on the resource by a new value.
351: * @param config the resource whose values are to be updated
352: * @param parameter a predicate defining the parameter to be set
353: * @param value the new value
354: */
355: public static void updateParameter(Resource config,
356: Property parameter, Object value) {
357: for (StmtIterator i = config.listProperties(parameter); i
358: .hasNext();) {
359: i.next();
360: i.remove();
361: }
362: config.addProperty(parameter, value.toString());
363: }
364: }
365:
366: /*
367: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
368: * All rights reserved.
369: *
370: * Redistribution and use in source and binary forms, with or without
371: * modification, are permitted provided that the following conditions
372: * are met:
373: * 1. Redistributions of source code must retain the above copyright
374: * notice, this list of conditions and the following disclaimer.
375: * 2. Redistributions in binary form must reproduce the above copyright
376: * notice, this list of conditions and the following disclaimer in the
377: * documentation and/or other materials provided with the distribution.
378: * 3. The name of the author may not be used to endorse or promote products
379: * derived from this software without specific prior written permission.
380: *
381: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
382: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
383: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
384: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
385: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
386: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
387: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
388: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
389: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
390: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
391: */
|