Project

General

Profile

Download (15 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2015 EDIT
3
 * European Distributed Institute of Taxonomy
4
 * http://www.e-taxonomy.eu
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version 1.1
7
 * See LICENSE.TXT at the top of this package for the full license terms.
8
 */
9
package org.bgbm.biovel.drf.query;
10

    
11
import java.net.URI;
12
import java.net.URISyntaxException;
13
import java.util.ArrayList;
14
import java.util.List;
15
import java.util.NoSuchElementException;
16

    
17
import org.apache.jena.rdf.model.Model;
18
import org.apache.jena.rdf.model.Property;
19
import org.apache.jena.rdf.model.RDFNode;
20
import org.apache.jena.rdf.model.Resource;
21
import org.apache.jena.rdf.model.StmtIterator;
22
import org.bgbm.biovel.drf.checklist.DRFChecklistException;
23
import org.bgbm.biovel.drf.checklist.EEA_BDC_Client.RdfSchema;
24
import org.bgbm.biovel.drf.store.Neo4jStore;
25
import org.neo4j.graphdb.Node;
26
import org.neo4j.graphdb.index.AutoIndexer;
27
import org.neo4j.graphdb.index.IndexHits;
28
import org.openrdf.query.BindingSet;
29
import org.openrdf.query.MalformedQueryException;
30
import org.openrdf.query.QueryEvaluationException;
31
import org.openrdf.query.QueryLanguage;
32
import org.openrdf.query.TupleQuery;
33
import org.openrdf.query.TupleQueryResult;
34
import org.openrdf.repository.RepositoryException;
35
import org.openrdf.repository.sail.SailRepositoryConnection;
36
import org.slf4j.Logger;
37
import org.slf4j.LoggerFactory;
38

    
39
import com.tinkerpop.blueprints.Direction;
40
import com.tinkerpop.blueprints.Graph;
41
import com.tinkerpop.blueprints.Vertex;
42
import com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Graph;
43
import com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Vertex;
44
import com.tinkerpop.blueprints.oupls.sail.GraphSail;
45
import com.tinkerpop.gremlin.java.GremlinPipeline;
46
import com.tinkerpop.pipes.PipeFunction;
47
import com.tinkerpop.pipes.util.FastNoSuchElementException;
48

    
49
/**
50
 *
51
 * Developer links:
52
 * <ul>
53
 * <li>https://github.com/tinkerpop/blueprints/wiki/Sail-Ouplementation</li>
54
 * <li>https://github.com/tinkerpop/gremlin/wiki</li>
55
 * <li>
56
 * http://rdf4j.org/sesame/2.7/docs/users.docbook?view#section-repository-api3</li>
57
 * <li>https://github.com/tinkerpop/gremlin/wiki/SPARQL-vs.-Gremlin</li>
58
 * <li>https://github.com/tinkerpop/gremlin/wiki/Using-Gremlin-through-Java</li>
59
 * <li>
60
 * http://markorodriguez.com/2011/06/15/graph-pattern-matching-with-gremlin-1-1/
61
 * </li>
62
 * <li>https://github.com/datablend/neo4j-sail-test</li>
63
 * </ul>
64
 *
65
 * @author a.kohlbecker
66
 * @date Sep 30, 2015
67
 *
68
 */
69
public class TinkerPopClient implements IQueryClient {
70

    
71
    public static final String KIND = GraphSail.KIND;
72

    
73
    public static final String VALUE = GraphSail.VALUE;
74

    
75
    public static final Object URI = GraphSail.URI;
76

    
77
    protected Logger logger = LoggerFactory.getLogger(TinkerPopClient.class);
78

    
79
    private final String baseUri = null;
80

    
81
    private Neo4jStore tripleStore = null;
82

    
83
    /**
84
     * @param tripleStore
85
     */
86
    public TinkerPopClient(Neo4jStore tripleStore) {
87
        this.tripleStore = tripleStore;
88
    }
89

    
90
    public GremlinPipeline<Graph, Graph> newPipe() {
91
        GremlinPipeline<Graph, Object> pipe = new GremlinPipeline<Graph, Object>();
92
        return pipe.start(graph());
93
    }
94

    
95
    public Graph graph() {
96
        return tripleStore.graph();
97
    }
98

    
99
    /**
100
     * @param sparql
101
     * @return
102
     * @throws MalformedQueryException
103
     * @throws RepositoryException
104
     * @throws QueryEvaluationException
105
     *
106
     * @deprecated directly use connection() and do not forget to close is after
107
     *             doing the query. See
108
     *             {@link org.openrdf.repository.sail.SailRepository#getConnection()}
109
     */
110
    @Deprecated
111
    public TupleQueryResult execute(String sparql) throws MalformedQueryException, RepositoryException,
112
            QueryEvaluationException {
113
        TupleQuery query = connection().prepareTupleQuery(QueryLanguage.SPARQL, sparql);
114
        TupleQueryResult result = query.evaluate();
115
        return result;
116
    }
117

    
118
    /**
119
     * See {@link org.openrdf.repository.sail.SailRepository#getConnection()}
120
     *
121
     * @return
122
     * @throws RepositoryException
123
     */
124
    public SailRepositoryConnection connection() throws RepositoryException {
125
        SailRepositoryConnection connection = tripleStore.getSailRepo().getConnection();
126
        return connection;
127
    }
128

    
129
    public PipeFunction<Vertex, Boolean> createRegexMatchFilter(final String regex) {
130
        return new PipeFunction<Vertex, Boolean>() {
131

    
132
            @Override
133
            public Boolean compute(Vertex v) {
134
                return v.toString().matches(regex);
135
            }
136
        };
137
    }
138

    
139
    public PipeFunction<Vertex, Boolean> createEqualsFilter(final String string) {
140
        return new PipeFunction<Vertex, Boolean>() {
141

    
142
            @Override
143
            public Boolean compute(Vertex v) {
144
                return v.toString().equals(string);
145
            }
146
        };
147
    }
148

    
149
    public PipeFunction<Vertex, Boolean> createStarttWithFilter(final String string) {
150
        return new PipeFunction<Vertex, Boolean>() {
151

    
152
            @Override
153
            public Boolean compute(Vertex v) {
154
                return v.toString().startsWith(string);
155
            }
156
        };
157
    }
158

    
159
    public Model describe(String queryString) throws DRFChecklistException, QueryEvaluationException {
160

    
161
        // directly execute SPARQL queries in Gremlin over Sail-based graphs
162
        // using the method SailGraph.executeSparql().
163

    
164
        TupleQuery qe = executionFor(queryString);
165
        TupleQueryResult result = qe.evaluate();
166
        System.err.println(result.toString());
167

    
168
        if (result != null && logger.isDebugEnabled()) {
169
            StringBuilder msg = new StringBuilder();
170
            msg.append("subjects in response:\n");
171
            int i = 1;
172
            try {
173
                for (; result.hasNext(); ++i) {
174
                    BindingSet res = result.next();
175
                    msg.append("    " + i + ": " + res.toString() + "\n");
176
                }
177
            } catch (QueryEvaluationException e) {
178
                // TODO Auto-generated catch block
179
                e.printStackTrace();
180
            }
181
            logger.debug(msg.toString());
182
        }
183

    
184
        return null; // FIXME result;
185
    }
186

    
187
    /**
188
     * @param queryString
189
     * @return
190
     */
191
    private TupleQuery executionFor(String queryString) {
192

    
193
        if (baseUri != null) {
194
            // see
195
            // https://github.com/tinkerpop/blueprints/wiki/Sail-Implementation
196
            // FIXME
197
            throw new RuntimeException("Mode unsupported");
198
            // Graph graph = new SparqlRepositorySailGraph(baseUri);
199
            // return QueryExecutionFactory.sparqlService(baseUri, query);
200
        }
201
        if (tripleStore != null) {
202
            // local TDB Store
203
            try {
204
                SailRepositoryConnection connection = connection();
205
                return connection.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
206
            } catch (MalformedQueryException | RepositoryException e) {
207
                // TODO Auto-generated catch block
208
                logger.error("Error while perparing query", e);
209
            }
210

    
211
        }
212

    
213
        return null;
214
    }
215

    
216
    /**
217
     * @param subject
218
     * @param nameSpace
219
     * @param localName
220
     * @return
221
     */
222
    public RDFNode asSingleObject(Resource subject, RdfSchema nameSpace, String localName) {
223
        RDFNode node = null;
224
        StmtIterator propertyIt = null;
225
        Resource _subject = subject;
226
        try {
227

    
228
            Model _model = _subject.getModel();
229
            Property property = _model.getProperty(nameSpace.schemaUri(), localName);
230
            propertyIt = _subject.listProperties(property);
231

    
232
            boolean propertyInGraph = propertyIt.hasNext();
233
            if (!propertyInGraph) {
234
                _subject = getFromUri(subject.getURI());
235
                propertyIt = _subject.listProperties(property);
236
            }
237

    
238
            node = propertyIt.next().getObject();
239
        } catch (NoSuchElementException e) {
240
            if (logger.isTraceEnabled()) {
241
                logger.debug(_subject.getURI() + " " + nameSpace + ":" + localName + " not found in current graph");
242
                printProperties(_subject);
243
            }
244
        }
245
        return node;
246
    }
247

    
248
    /**
249
     * @param subject
250
     * @param nameSpace
251
     * @param localName
252
     * @return
253
     */
254
    public StmtIterator listProperties(Resource subject, RdfSchema nameSpace, String localName) {
255
        RDFNode node = null;
256
        StmtIterator propertyIt = null;
257
        Resource _subject = subject;
258
        try {
259

    
260
            Model _model = _subject.getModel();
261
            Property property = _model.getProperty(nameSpace.schemaUri(), localName);
262
            propertyIt = _subject.listProperties(property);
263

    
264
            boolean propertyInGraph = propertyIt.hasNext();
265
            if (!propertyInGraph) {
266
                _subject = getFromUri(subject.getURI());
267
                propertyIt = _subject.listProperties(property);
268
            }
269

    
270
        } catch (NoSuchElementException e) {
271
            if (logger.isTraceEnabled()) {
272
                logger.debug(_subject.getURI() + " " + nameSpace + ":" + localName + " not found in current graph");
273
                printProperties(_subject);
274
            }
275
        }
276
        return propertyIt;
277
    }
278

    
279
    public List<RDFNode> listObjects(Resource subject, RdfSchema nameSpace, String localName) {
280

    
281
        List<RDFNode> list = new ArrayList<RDFNode>();
282
        StmtIterator it = listProperties(subject, nameSpace, localName);
283
        while (it.hasNext()) {
284
            list.add(it.next().getObject());
285
        }
286
        return list;
287
    }
288

    
289
    /**
290
     * @param subject
291
     * @param nameSpace
292
     * @param localName
293
     * @return
294
     */
295
    public String relatedVertexValue(GremlinPipeline<Graph, Vertex> pipe, RdfSchema nameSpace, String localName) {
296
        String txt = null;
297
        String edgeLabel = nameSpace.propertyURI(localName);
298
        try {
299
            txt = pipe.outE(1, edgeLabel).inV().next().getProperty("value");
300
        } catch (FastNoSuchElementException e) {
301
            try {
302
                txt = pipe.inE(1, edgeLabel).inV().next().getProperty("value");
303
            } catch (FastNoSuchElementException e1) {
304
                logger.warn("edge with '" + edgeLabel + "' not found");
305
                if (logger.isDebugEnabled()) {
306
                    logger.debug("Vertices in pipe:");
307
                    StringBuffer out = new StringBuffer();
308
                    for (Vertex v : pipe.toList()) {
309
                        logger.debug("    " + v);
310
                    }
311
                }
312
            }
313
        }
314

    
315
        return txt;
316
    }
317

    
318
    public String relatedVertexValue(Vertex v, RdfSchema nameSpace, String localName) {
319
        String txt = null;
320
        String edgeLabel = nameSpace.propertyURI(localName);
321
        try {
322
            txt = v.getEdges(Direction.OUT, edgeLabel).iterator().next().getVertex(Direction.IN)
323
                    .getProperty(GraphSail.VALUE);
324
        } catch (NoSuchElementException e) {
325
            try {
326
                txt = v.getEdges(Direction.IN, edgeLabel).iterator().next().getVertex(Direction.OUT)
327
                        .getProperty(GraphSail.VALUE);
328
            } catch (NoSuchElementException e1) {
329
                logger.warn("edge with '" + edgeLabel + "' not found for " + v);
330

    
331
            }
332
        }
333

    
334
        return txt;
335
    }
336

    
337
    //
338

    
339
    /**
340
     * @param subject
341
     * @param nameSpace
342
     * @param localName
343
     * @return
344
     */
345
    public Resource objectAsResource(Resource subject, RdfSchema nameSpace, String localName) {
346
        Resource resource = null;
347
        RDFNode node = asSingleObject(subject, nameSpace, localName);
348
        if (node != null) {
349
            node.isResource();
350
            resource = node.asResource();
351
        }
352
        return resource;
353
    }
354

    
355
    /**
356
     * @param subject
357
     * @param nameSpace
358
     * @param localName
359
     * @return
360
     * @deprecated unused
361
     */
362
    @Deprecated
363
    public URI relatedVertexURI(GremlinPipeline<Graph, Vertex> pipe, RdfSchema nameSpace, String localName) {
364
        URI uri = null;
365
        String edgeLabel = nameSpace.propertyURI(localName);
366
        try {
367
            Vertex v = pipe.outE(1, edgeLabel).inV().next();
368
            if (v.getProperty(GraphSail.KIND).equals(GraphSail.URI)) {
369
                uri = (URI) v.getProperty(GraphSail.VALUE);
370
            } else {
371
                logger.warn("target vertex of '" + edgeLabel + "' is not an URI");
372
            }
373
        } catch (FastNoSuchElementException e) {
374
            logger.warn("edge with '" + edgeLabel + "' not found");
375
        }
376

    
377
        return uri;
378
    }
379

    
380
    /**
381
     * @param subject
382
     * @param nameSpace
383
     * @param localName
384
     * @return
385
     * @deprecated possibly broken
386
     */
387
    @Deprecated
388
    public URI relatedVertexURI(Vertex v, RdfSchema nameSpace, String localName) {
389
        URI uri = null;
390
        String edgeLabel = nameSpace.propertyURI(localName);
391
        try {
392
            if (v.getProperty(GraphSail.KIND).equals(GraphSail.URI)) {
393
                uri = new URI(v.getProperty(GraphSail.VALUE).toString());
394
            } else {
395
                logger.warn("target vertex of '" + edgeLabel + "' is not an URI");
396
            }
397
        } catch (NoSuchElementException e) {
398
            logger.warn("edge with '" + edgeLabel + "' not found");
399
        } catch (URISyntaxException e) {
400
            logger.error("Invalid URI id in " + v, e);
401
        }
402

    
403
        return uri;
404
    }
405

    
406
    /**
407
     * by using the Neo4j index directly it is possible to
408
     * take full advantage of the underlying Lucene search engine
409
     *
410
     * @param luceneQuery
411
     * @return
412
     */
413
    public ArrayList<Vertex> vertexIndexQuery(String luceneQuery) {
414
        Neo4j2Graph graph = (Neo4j2Graph)graph();
415
        AutoIndexer<Node> nodeAutoIndex = graph.getRawGraph().index().getNodeAutoIndexer();
416
        IndexHits<Node> nodes = nodeAutoIndex.getAutoIndex().query(luceneQuery);
417
        ArrayList<Vertex> hitVs = new ArrayList<Vertex>();
418
        while(nodes.hasNext()) {
419
            hitVs.add(new Neo4j2Vertex(nodes.next(), graph));
420
        }
421
        return hitVs;
422
    }
423

    
424
    /**
425
     * @param subject
426
     */
427
    private void printProperties(Resource subject) {
428
        for (StmtIterator it = subject.listProperties(); it.hasNext();) {
429
            System.err.println(it.next().toString());
430
        }
431
    }
432

    
433
    /**
434
     * @param matchedResourceURI
435
     * @return
436
     * @throws DRFChecklistException
437
     */
438
    public Resource getFromUri(URI matchedResourceURI) {
439
        return getFromUri(matchedResourceURI.toString());
440
    }
441

    
442
    public Resource getFromUri(String uri) {
443

    
444
        // not needed
445
        return null;
446

    
447
    }
448

    
449
    public void showResults(TupleQueryResult result) throws QueryEvaluationException {
450
        int i = 0;
451
        while (result.hasNext()) {
452
            System.err.println(".");
453
            BindingSet bindingSet = result.next();
454
            System.err.println("+");
455
            for (String colName : result.getBindingNames()) {
456
                System.err.println(colName + ":" + bindingSet.getValue(colName));
457
            }
458
            System.err.println("|");
459
            i++;
460
        }
461
        System.err.println("We found " + i + " results");
462
        System.err.flush();
463
    }
464
}
(6-6/6)