1   package eu.fbk.dkm.pikes.kv;
2   
3   import java.util.Collection;
4   import java.util.List;
5   import java.util.Objects;
6   import java.util.Set;
7   import java.util.function.Predicate;
8   
9   import javax.annotation.Nullable;
10  
11  import com.google.common.collect.ImmutableSet;
12  import com.google.common.collect.Lists;
13  import com.google.common.collect.Sets;
14  
15  import org.eclipse.rdf4j.model.Statement;
16  import org.eclipse.rdf4j.model.Value;
17  import org.eclipse.rdf4j.rio.RDFHandler;
18  import org.eclipse.rdf4j.rio.RDFHandlerException;
19  
20  import eu.fbk.rdfpro.AbstractRDFHandlerWrapper;
21  import eu.fbk.rdfpro.RDFHandlers;
22  import eu.fbk.rdfpro.util.QuadModel;
23  
24  public interface KeyQuadSource {
25  
26      default QuadModel get(final Value key) {
27          Objects.requireNonNull(key);
28          final QuadModel model = QuadModel.create();
29          get(key, model);
30          return model;
31      }
32  
33      boolean get(Value key, RDFHandler handler) throws RDFHandlerException;
34  
35      default boolean get(final Value key, final Collection<Statement> model) {
36          Objects.requireNonNull(key);
37          Objects.requireNonNull(model);
38          try {
39              return get(key, RDFHandlers.wrap(model));
40          } catch (final RDFHandlerException ex) {
41              throw new Error(ex);
42          }
43      }
44  
45      default QuadModel getAll(final Iterable<? extends Value> keys) {
46          Objects.requireNonNull(keys);
47          final QuadModel model = QuadModel.create();
48          getAll(keys, model);
49          return model;
50      }
51  
52      default int getAll(final Iterable<? extends Value> keys, final RDFHandler handler)
53              throws RDFHandlerException {
54          Objects.requireNonNull(keys);
55          Objects.requireNonNull(handler);
56          int result = 0;
57          for (final Value key : keys instanceof Set ? keys : ImmutableSet.copyOf(keys)) {
58              final boolean found = get(key, handler);
59              result += found ? 1 : 0;
60          }
61          return result;
62      }
63  
64      default int getAll(final Iterable<? extends Value> keys, final Collection<Statement> model) {
65          Objects.requireNonNull(keys);
66          Objects.requireNonNull(model);
67          try {
68              return getAll(keys, RDFHandlers.wrap(model));
69          } catch (final RDFHandlerException ex) {
70              throw new Error(ex);
71          }
72      }
73  
74      default QuadModel getRecursive(final Iterable<? extends Value> keys,
75              @Nullable final Predicate<Value> matcher) {
76          Objects.requireNonNull(keys);
77          final QuadModel model = QuadModel.create();
78          getRecursive(keys, matcher, model);
79          return model;
80      }
81  
82      default int getRecursive(final Iterable<? extends Value> keys,
83              @Nullable final Predicate<Value> matcher, final RDFHandler handler)
84              throws RDFHandlerException {
85  
86          Objects.requireNonNull(keys);
87  
88          final Set<Value> visited = Sets.newHashSet();
89          final List<Value> queue = Lists.newLinkedList(keys);
90  
91          final RDFHandler sink = new AbstractRDFHandlerWrapper(handler) {
92  
93              @Override
94              public void handleStatement(final Statement stmt) throws RDFHandlerException {
95                  super.handleStatement(stmt);
96                  enqueueIfMatches(stmt.getSubject());
97                  enqueueIfMatches(stmt.getPredicate());
98                  enqueueIfMatches(stmt.getObject());
99                  enqueueIfMatches(stmt.getContext());
100             }
101 
102             private void enqueueIfMatches(@Nullable final Value value) {
103                 if (value != null && (matcher == null || matcher.test(value))) {
104                     queue.add(value);
105                 }
106             }
107 
108         };
109 
110         int result = 0;
111         while (!queue.isEmpty()) {
112             final Value key = queue.remove(0);
113             if (visited.add(key)) {
114                 final boolean found = get(key, sink);
115                 result += found ? 1 : 0;
116             }
117         }
118         return result;
119     }
120 
121     default int getRecursive(final Iterable<? extends Value> keys,
122             @Nullable final Predicate<Value> matcher, final Collection<Statement> model) {
123         Objects.requireNonNull(keys);
124         Objects.requireNonNull(model);
125         try {
126             return getRecursive(keys, matcher, RDFHandlers.wrap(model));
127         } catch (final RDFHandlerException ex) {
128             throw new Error(ex);
129         }
130     }
131 
132 }