1   package eu.fbk.knowledgestore.data;
2   
3   import java.util.List;
4   
5   import javax.xml.datatype.XMLGregorianCalendar;
6   
7   import com.google.common.collect.Iterables;
8   import com.google.common.collect.Lists;
9   
10  import org.jaxen.Context;
11  import org.jaxen.Function;
12  import org.jaxen.FunctionCallException;
13  import org.jaxen.XPathFunctionContext;
14  import org.jaxen.function.BooleanFunction;
15  import org.jaxen.function.CeilingFunction;
16  import org.jaxen.function.ConcatFunction;
17  import org.jaxen.function.ContainsFunction;
18  import org.jaxen.function.CountFunction;
19  import org.jaxen.function.FalseFunction;
20  import org.jaxen.function.FloorFunction;
21  import org.jaxen.function.IdFunction;
22  import org.jaxen.function.LangFunction;
23  import org.jaxen.function.LastFunction;
24  import org.jaxen.function.LocalNameFunction;
25  import org.jaxen.function.NameFunction;
26  import org.jaxen.function.NamespaceUriFunction;
27  import org.jaxen.function.NormalizeSpaceFunction;
28  import org.jaxen.function.NotFunction;
29  import org.jaxen.function.NumberFunction;
30  import org.jaxen.function.PositionFunction;
31  import org.jaxen.function.RoundFunction;
32  import org.jaxen.function.StartsWithFunction;
33  import org.jaxen.function.StringFunction;
34  import org.jaxen.function.StringLengthFunction;
35  import org.jaxen.function.SubstringAfterFunction;
36  import org.jaxen.function.SubstringBeforeFunction;
37  import org.jaxen.function.SubstringFunction;
38  import org.jaxen.function.SumFunction;
39  import org.jaxen.function.TranslateFunction;
40  import org.jaxen.function.TrueFunction;
41  import org.jaxen.function.ext.EndsWithFunction;
42  import org.jaxen.function.ext.EvaluateFunction;
43  import org.jaxen.function.ext.LowerFunction;
44  import org.jaxen.function.ext.UpperFunction;
45  import org.openrdf.model.URI;
46  
47  // TODO add subject(), predicate(), object(), context() functions to extract statement components
48  
49  abstract class XPathFunction implements Function {
50  
51      static final XPathFunctionContext CONTEXT;
52  
53      static {
54          CONTEXT = new XPathFunctionContext();
55  
56          // Functions on nodes and context
57          CONTEXT.registerFunction(null, "position", new PositionFunction()); // xpath1
58          CONTEXT.registerFunction(null, "last", new LastFunction()); // xpath1
59          CONTEXT.registerFunction(null, "id", new IdFunction()); // xpath1
60          CONTEXT.registerFunction(null, "name", new NameFunction()); // xpath1
61          CONTEXT.registerFunction(null, "local-name", new LocalNameFunction()); // xpath1
62          CONTEXT.registerFunction(null, "namespace-uri", new NamespaceUriFunction()); // xpath1
63          CONTEXT.registerFunction(null, "lang", new LangFunction()); // xpath1
64          CONTEXT.registerFunction(null, "evaluate", new EvaluateFunction()); // xpath2 jaxen
65  
66          // Function on RDF Values
67          CONTEXT.registerFunction(null, "uri", new URIFunction());
68          CONTEXT.registerFunction(null, "escape-uri", new EscapeURIFunction());
69          CONTEXT.registerFunction(null, "str", new StrFunction());
70          CONTEXT.registerFunction(null, "strdt", new StrdtFunction());
71          CONTEXT.registerFunction(null, "strlang", new StrlangFunction());
72  
73          // Functions on booleans
74          CONTEXT.registerFunction(null, "boolean", new BooleanFunction()); // xpath1
75          CONTEXT.registerFunction(null, "true", new TrueFunction()); // xpath1
76          CONTEXT.registerFunction(null, "false", new FalseFunction()); // xpath1
77          CONTEXT.registerFunction(null, "not", new NotFunction()); // xpath1
78          CONTEXT.registerFunction(null, "abs", new AbsFunction());
79          CONTEXT.registerFunction(null, "power", new PowerFunction());
80  
81          // Functions on numbers
82          CONTEXT.registerFunction(null, "number", new NumberFunction()); // xpath1
83          CONTEXT.registerFunction(null, "ceiling", new CeilingFunction()); // xpath1
84          CONTEXT.registerFunction(null, "floor", new FloorFunction()); // xpath1
85          CONTEXT.registerFunction(null, "round", new RoundFunction()); // xpath1
86  
87          // Functions on strings
88          CONTEXT.registerFunction(null, "concat", new ConcatFunction()); // xpath1
89          CONTEXT.registerFunction(null, "contains", new ContainsFunction()); // xpath1
90          CONTEXT.registerFunction(null, "normalize-space", new NormalizeSpaceFunction()); // xpath1
91          CONTEXT.registerFunction(null, "starts-with", new StartsWithFunction()); // xpath1
92          CONTEXT.registerFunction(null, "string", new StringFunction()); // xpath1
93          CONTEXT.registerFunction(null, "string-length", new StringLengthFunction()); // xpath1
94          CONTEXT.registerFunction(null, "substring-after", new SubstringAfterFunction()); // xpath1
95          CONTEXT.registerFunction(null, "substring-before", new SubstringBeforeFunction()); // xpath1
96          CONTEXT.registerFunction(null, "substring", new SubstringFunction()); // xpath1
97          CONTEXT.registerFunction(null, "translate", new TranslateFunction()); // xpath1
98          CONTEXT.registerFunction(null, "ends-with", new EndsWithFunction()); // xpath2 jaxen
99          CONTEXT.registerFunction(null, "lower-case", new LowerFunction()); // xpath2 jaxen
100         CONTEXT.registerFunction(null, "upper-case", new UpperFunction()); // xpath2 jaxen
101         CONTEXT.registerFunction(null, "compare", new CompareFunction());
102         CONTEXT.registerFunction(null, "string-join", new StringJoinFunction());
103         CONTEXT.registerFunction(null, "matches", new MatchesFunction());
104         CONTEXT.registerFunction(null, "replace", new ReplaceFunction());
105         CONTEXT.registerFunction(null, "tokenize", new TokenizeFunction());
106 
107         // Functions on dates
108         CONTEXT.registerFunction(null, "dateTime", new DateTimeFunction());
109         CONTEXT.registerFunction(null, "current-dateTime", new CurrentDateTimeFunction());
110         CONTEXT.registerFunction(null, "year-from-dateTime", new YearFromDateTimeFunction());
111         CONTEXT.registerFunction(null, "month-from-dateTime", new MonthFromDateTimeFunction());
112         CONTEXT.registerFunction(null, "day-from-dateTime", new DayFromDateTimeFunction());
113         CONTEXT.registerFunction(null, "hours-from-dateTime", new HoursFromDateTimeFunction());
114         CONTEXT.registerFunction(null, "minutes-from-dateTime", new MinutesFromDateTimeFunction());
115         CONTEXT.registerFunction(null, "seconds-from-dateTime", new SecondsFromDateTimeFunction());
116         CONTEXT.registerFunction(null, "timezone-from-dateTime",
117                 new TimeZoneFromDateTimeFunction());
118 
119         // Functions on sequences
120         CONTEXT.registerFunction(null, "count", new CountFunction()); // xpath1
121         CONTEXT.registerFunction(null, "sum", new SumFunction()); // xpath1
122         CONTEXT.registerFunction(null, "sequence", new SequenceFunction());
123         CONTEXT.registerFunction(null, "subsequence", new SubsequenceFunction());
124         CONTEXT.registerFunction(null, "index-of", new IndexOfFunction());
125         CONTEXT.registerFunction(null, "insert-before", new InsertBeforeFunction());
126         CONTEXT.registerFunction(null, "remove", new RemoveFunction());
127         CONTEXT.registerFunction(null, "reverse", new ReverseFunction());
128         CONTEXT.registerFunction(null, "distinct-values", new DistinctValuesFunction());
129         CONTEXT.registerFunction(null, "exists", new ExistsFunction());
130         CONTEXT.registerFunction(null, "empty", new EmptyFunction());
131         CONTEXT.registerFunction(null, "avg", new AvgFunction());
132         CONTEXT.registerFunction(null, "max", new MaxFunction());
133         CONTEXT.registerFunction(null, "min", new MinFunction());
134     }
135 
136     // FUNCTIONS ON URIS
137 
138     private static final class URIFunction extends XPathFunction {
139 
140         @Override
141         @SuppressWarnings("rawtypes")
142         public Object call(final Context context, final List args) throws FunctionCallException {
143 
144             if (args.size() != 1) {
145                 throw new FunctionCallException("uri() requires one argument");
146             }
147 
148             final String string = StringFunction.evaluate(args.get(0), context.getNavigator());
149             return Data.getValueFactory().createURI(string);
150         }
151 
152     }
153 
154     private static final class StrFunction extends XPathFunction {
155 
156         @SuppressWarnings("rawtypes")
157         @Override
158         public Object call(final Context context, final List args) throws FunctionCallException {
159 
160             if (args.size() != 1) {
161                 throw new FunctionCallException("str() requires one argument");
162             }
163 
164             final String label = StringFunction.evaluate(args.get(0), context.getNavigator());
165             return Data.getValueFactory().createLiteral(label);
166         }
167 
168     }
169 
170     private static final class StrdtFunction extends XPathFunction {
171 
172         @SuppressWarnings("rawtypes")
173         @Override
174         public Object call(final Context context, final List args) throws FunctionCallException {
175 
176             if (args.size() != 2) {
177                 throw new FunctionCallException("strdt() requires two arguments");
178             }
179 
180             final String label = StringFunction.evaluate(args.get(0), context.getNavigator());
181             final URI dt = args.get(1) instanceof URI ? (URI) args.get(1) : Data.getValueFactory()
182                     .createURI(StringFunction.evaluate(args.get(1), context.getNavigator()));
183             return Data.getValueFactory().createLiteral(label, dt);
184         }
185 
186     }
187 
188     private static final class StrlangFunction extends XPathFunction {
189 
190         @SuppressWarnings("rawtypes")
191         @Override
192         public Object call(final Context context, final List args) throws FunctionCallException {
193 
194             if (args.size() != 2) {
195                 throw new FunctionCallException("strlang() requires two arguments");
196             }
197 
198             final String label = StringFunction.evaluate(args.get(0), context.getNavigator());
199             final String lang = StringFunction.evaluate(args.get(1), context.getNavigator());
200             return Data.getValueFactory().createLiteral(label, lang);
201         }
202 
203     }
204 
205     private static final class EscapeURIFunction extends XPathFunction {
206 
207         @Override
208         @SuppressWarnings("rawtypes")
209         public Object call(final Context context, final List args) throws FunctionCallException {
210             throw new UnsupportedOperationException(); // TODO
211         }
212 
213     }
214 
215     // FUNCTIONS ON NUMBERS
216 
217     private static final class AbsFunction extends XPathFunction {
218 
219         @Override
220         @SuppressWarnings("rawtypes")
221         public Object call(final Context context, final List args) throws FunctionCallException {
222             throw new UnsupportedOperationException(); // TODO
223         }
224 
225     }
226 
227     private static final class PowerFunction extends XPathFunction {
228 
229         @Override
230         @SuppressWarnings("rawtypes")
231         public Object call(final Context context, final List args) throws FunctionCallException {
232             throw new UnsupportedOperationException(); // TODO
233         }
234 
235     }
236 
237     // FUNCTIONS ON STRINGS
238 
239     private static final class CompareFunction extends XPathFunction {
240 
241         @Override
242         @SuppressWarnings("rawtypes")
243         public Object call(final Context context, final List args) throws FunctionCallException {
244             throw new UnsupportedOperationException(); // TODO
245         }
246 
247     }
248 
249     private static final class StringJoinFunction extends XPathFunction {
250 
251         @Override
252         @SuppressWarnings("rawtypes")
253         public Object call(final Context context, final List args) throws FunctionCallException {
254             throw new UnsupportedOperationException(); // TODO
255         }
256 
257     }
258 
259     private static final class MatchesFunction extends XPathFunction {
260 
261         @Override
262         @SuppressWarnings("rawtypes")
263         public Object call(final Context context, final List args) throws FunctionCallException {
264             throw new UnsupportedOperationException(); // TODO
265         }
266 
267     }
268 
269     private static final class ReplaceFunction extends XPathFunction {
270 
271         @Override
272         @SuppressWarnings("rawtypes")
273         public Object call(final Context context, final List args) throws FunctionCallException {
274             throw new UnsupportedOperationException(); // TODO
275         }
276 
277     }
278 
279     private static final class TokenizeFunction extends XPathFunction {
280 
281         @Override
282         @SuppressWarnings("rawtypes")
283         public Object call(final Context context, final List args) throws FunctionCallException {
284             throw new UnsupportedOperationException(); // TODO
285         }
286 
287     }
288 
289     // FUNCTIONS ON DATES
290 
291     private static final class DateTimeFunction extends XPathFunction {
292 
293         @Override
294         @SuppressWarnings("rawtypes")
295         public Object call(final Context context, final List args) throws FunctionCallException {
296             return Data.convert(args.get(0), XMLGregorianCalendar.class);
297         }
298 
299     }
300 
301     private static final class CurrentDateTimeFunction extends XPathFunction {
302 
303         @Override
304         @SuppressWarnings("rawtypes")
305         public Object call(final Context context, final List args) throws FunctionCallException {
306             throw new UnsupportedOperationException(); // TODO
307         }
308 
309     }
310 
311     private static final class YearFromDateTimeFunction extends XPathFunction {
312 
313         @Override
314         @SuppressWarnings("rawtypes")
315         public Object call(final Context context, final List args) throws FunctionCallException {
316             throw new UnsupportedOperationException(); // TODO
317         }
318 
319     }
320 
321     private static final class MonthFromDateTimeFunction extends XPathFunction {
322 
323         @Override
324         @SuppressWarnings("rawtypes")
325         public Object call(final Context context, final List args) throws FunctionCallException {
326             throw new UnsupportedOperationException(); // TODO
327         }
328 
329     }
330 
331     private static final class DayFromDateTimeFunction extends XPathFunction {
332 
333         @Override
334         @SuppressWarnings("rawtypes")
335         public Object call(final Context context, final List args) throws FunctionCallException {
336             throw new UnsupportedOperationException(); // TODO
337         }
338 
339     }
340 
341     private static final class HoursFromDateTimeFunction extends XPathFunction {
342 
343         @Override
344         @SuppressWarnings("rawtypes")
345         public Object call(final Context context, final List args) throws FunctionCallException {
346             throw new UnsupportedOperationException(); // TODO
347         }
348 
349     }
350 
351     private static final class MinutesFromDateTimeFunction extends XPathFunction {
352 
353         @Override
354         @SuppressWarnings("rawtypes")
355         public Object call(final Context context, final List args) throws FunctionCallException {
356             throw new UnsupportedOperationException(); // TODO
357         }
358 
359     }
360 
361     private static final class SecondsFromDateTimeFunction extends XPathFunction {
362 
363         @Override
364         @SuppressWarnings("rawtypes")
365         public Object call(final Context context, final List args) throws FunctionCallException {
366             throw new UnsupportedOperationException(); // TODO
367         }
368 
369     }
370 
371     private static final class TimeZoneFromDateTimeFunction extends XPathFunction {
372 
373         @Override
374         @SuppressWarnings("rawtypes")
375         public Object call(final Context context, final List args) throws FunctionCallException {
376             throw new UnsupportedOperationException(); // TODO
377         }
378 
379     }
380 
381     // FUNCTIONS ON SEQUENCES
382 
383     private static final class SequenceFunction extends XPathFunction {
384 
385         @Override
386         @SuppressWarnings("rawtypes")
387         public Object call(final Context context, final List args) throws FunctionCallException {
388 
389             final List<Object> result = Lists.newArrayList();
390             for (final Object arg : args) {
391                 if (arg instanceof Iterable<?>) {
392                     Iterables.addAll(result, (Iterable<?>) arg);
393                 } else {
394                     result.add(arg);
395                 }
396             }
397             return result;
398         }
399 
400     }
401 
402     private static final class SubsequenceFunction extends XPathFunction {
403 
404         @Override
405         @SuppressWarnings("rawtypes")
406         public Object call(final Context context, final List args) throws FunctionCallException {
407             throw new UnsupportedOperationException(); // TODO
408         }
409 
410     }
411 
412     private static final class IndexOfFunction extends XPathFunction {
413 
414         @Override
415         @SuppressWarnings("rawtypes")
416         public Object call(final Context context, final List args) throws FunctionCallException {
417             throw new UnsupportedOperationException(); // TODO
418         }
419 
420     }
421 
422     private static final class InsertBeforeFunction extends XPathFunction {
423 
424         @Override
425         @SuppressWarnings("rawtypes")
426         public Object call(final Context context, final List args) throws FunctionCallException {
427             throw new UnsupportedOperationException(); // TODO
428         }
429 
430     }
431 
432     private static final class RemoveFunction extends XPathFunction {
433 
434         @Override
435         @SuppressWarnings("rawtypes")
436         public Object call(final Context context, final List args) throws FunctionCallException {
437             throw new UnsupportedOperationException(); // TODO
438         }
439 
440     }
441 
442     private static final class ReverseFunction extends XPathFunction {
443 
444         @Override
445         @SuppressWarnings("rawtypes")
446         public Object call(final Context context, final List args) throws FunctionCallException {
447             throw new UnsupportedOperationException(); // TODO
448         }
449 
450     }
451 
452     private static final class DistinctValuesFunction extends XPathFunction {
453 
454         @Override
455         @SuppressWarnings("rawtypes")
456         public Object call(final Context context, final List args) throws FunctionCallException {
457             throw new UnsupportedOperationException(); // TODO
458         }
459 
460     }
461 
462     private static final class ExistsFunction extends XPathFunction {
463 
464         @Override
465         @SuppressWarnings("rawtypes")
466         public Object call(final Context context, final List args) throws FunctionCallException {
467             throw new UnsupportedOperationException(); // TODO
468         }
469 
470     }
471 
472     private static final class EmptyFunction extends XPathFunction {
473 
474         @Override
475         @SuppressWarnings("rawtypes")
476         public Object call(final Context context, final List args) throws FunctionCallException {
477             throw new UnsupportedOperationException(); // TODO
478         }
479 
480     }
481 
482     private static final class AvgFunction extends XPathFunction {
483 
484         @Override
485         @SuppressWarnings("rawtypes")
486         public Object call(final Context context, final List args) throws FunctionCallException {
487             throw new UnsupportedOperationException(); // TODO
488         }
489 
490     }
491 
492     private static final class MaxFunction extends XPathFunction {
493 
494         @Override
495         @SuppressWarnings("rawtypes")
496         public Object call(final Context context, final List args) throws FunctionCallException {
497             throw new UnsupportedOperationException(); // TODO
498         }
499 
500     }
501 
502     private static final class MinFunction extends XPathFunction {
503 
504         @Override
505         @SuppressWarnings("rawtypes")
506         public Object call(final Context context, final List args) throws FunctionCallException {
507             throw new UnsupportedOperationException(); // TODO
508         }
509 
510     }
511 
512 }