1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.rdf.simple;
19
20 import java.util.HashSet;
21 import java.util.Objects;
22 import java.util.Optional;
23 import java.util.Set;
24 import java.util.function.Predicate;
25 import java.util.stream.Collectors;
26 import java.util.stream.Stream;
27
28 import org.apache.commons.rdf.api.BlankNode;
29 import org.apache.commons.rdf.api.BlankNodeOrIRI;
30 import org.apache.commons.rdf.api.Dataset;
31 import org.apache.commons.rdf.api.Graph;
32 import org.apache.commons.rdf.api.IRI;
33 import org.apache.commons.rdf.api.Literal;
34 import org.apache.commons.rdf.api.Quad;
35 import org.apache.commons.rdf.api.RDFTerm;
36 import org.apache.commons.rdf.simple.SimpleRDF.SimpleRDFTerm;
37
38
39
40
41
42
43
44
45 final class DatasetImpl implements Dataset {
46
47 private static final int TO_STRING_MAX = 10;
48 private final Set<Quad> quads = new HashSet<>();
49 private final SimpleRDF factory;
50
51 DatasetImpl(final SimpleRDF simpleRDF) {
52 this.factory = simpleRDF;
53 }
54
55 @Override
56 public void add(final BlankNodeOrIRI graphName, final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
57 final BlankNodeOrIRI newGraphName = (BlankNodeOrIRI) internallyMap(graphName);
58 final BlankNodeOrIRI newSubject = (BlankNodeOrIRI) internallyMap(subject);
59 final IRI newPredicate = (IRI) internallyMap(predicate);
60 final RDFTerm newObject = internallyMap(object);
61 final Quad result = factory.createQuad(newGraphName, newSubject, newPredicate, newObject);
62 quads.add(result);
63 }
64
65 @Override
66 public void add(final Quad quad) {
67 final BlankNodeOrIRI newGraph = (BlankNodeOrIRI) internallyMap(quad.getGraphName().orElse(null));
68 final BlankNodeOrIRI newSubject = (BlankNodeOrIRI) internallyMap(quad.getSubject());
69 final IRI newPredicate = (IRI) internallyMap(quad.getPredicate());
70 final RDFTerm newObject = internallyMap(quad.getObject());
71
72
73 if (newGraph == quad.getGraphName().orElse(null) && newSubject == quad.getSubject()
74 && newPredicate == quad.getPredicate() && newObject == quad.getObject()) {
75 quads.add(quad);
76 } else {
77
78 final Quad result = factory.createQuad(newGraph, newSubject, newPredicate, newObject);
79 quads.add(result);
80 }
81 }
82
83 private <T extends RDFTerm> RDFTerm internallyMap(final T object) {
84 if (object == null || object instanceof SimpleRDFTerm) {
85 return object;
86 }
87 if (object instanceof BlankNode && !(object instanceof BlankNodeImpl)) {
88 final BlankNode blankNode = (BlankNode) object;
89
90
91
92
93 return factory.createBlankNode(blankNode.uniqueReference());
94 } else if (object instanceof IRI && !(object instanceof IRIImpl)) {
95 final IRI iri = (IRI) object;
96 return factory.createIRI(iri.getIRIString());
97 } else if (object instanceof Literal && !(object instanceof LiteralImpl)) {
98 final Literal literal = (Literal) object;
99 if (literal.getLanguageTag().isPresent()) {
100 return factory.createLiteral(literal.getLexicalForm(), literal.getLanguageTag().get());
101 } else {
102 return factory.createLiteral(literal.getLexicalForm(), (IRI) internallyMap(literal.getDatatype()));
103 }
104 } else {
105 throw new IllegalArgumentException("Not a BlankNode, IRI or Literal: " + object);
106 }
107 }
108
109 @Override
110 public void clear() {
111 quads.clear();
112 }
113
114 @Override
115 public boolean contains(final Optional<BlankNodeOrIRI> graphName, final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
116 return stream(graphName, subject, predicate, object).findAny().isPresent();
117 }
118
119 @Override
120 public boolean contains(final Quad quad) {
121 return quads.contains(Objects.requireNonNull(quad));
122 }
123
124 @Override
125 public Stream<Quad> stream() {
126 return quads.parallelStream().unordered();
127 }
128
129 @Override
130 public Stream<Quad> stream(final Optional<BlankNodeOrIRI> graphName, final BlankNodeOrIRI subject, final IRI predicate,
131 final RDFTerm object) {
132 final Optional<BlankNodeOrIRI> newGraphName;
133 if (graphName == null) {
134
135 newGraphName = null;
136 } else {
137 newGraphName = graphName.map(g -> (BlankNodeOrIRI) internallyMap(g));
138 }
139 final BlankNodeOrIRI newSubject = (BlankNodeOrIRI) internallyMap(subject);
140 final IRI newPredicate = (IRI) internallyMap(predicate);
141 final RDFTerm newObject = internallyMap(object);
142
143 return getQuads(t -> {
144 if (newGraphName != null && !t.getGraphName().equals(newGraphName)) {
145
146 return false;
147 }
148 if (subject != null && !t.getSubject().equals(newSubject)) {
149 return false;
150 }
151 if (predicate != null && !t.getPredicate().equals(newPredicate)) {
152 return false;
153 }
154 if (object != null && !t.getObject().equals(newObject)) {
155 return false;
156 }
157 return true;
158 });
159 }
160
161 private Stream<Quad> getQuads(final Predicate<Quad> filter) {
162 return stream().filter(filter);
163 }
164
165 @Override
166 public void remove(final Optional<BlankNodeOrIRI> graphName, final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
167 final Stream<Quad> toRemove = stream(graphName, subject, predicate, object);
168 for (final Quad t : toRemove.collect(Collectors.toList())) {
169
170 remove(t);
171 }
172 }
173
174 @Override
175 public void remove(final Quad quad) {
176 quads.remove(Objects.requireNonNull(quad));
177 }
178
179 @Override
180 public long size() {
181 return quads.size();
182 }
183
184 @Override
185 public String toString() {
186 final String s = stream().limit(TO_STRING_MAX).map(Object::toString).collect(Collectors.joining("\n"));
187 if (size() > TO_STRING_MAX) {
188 return s + "\n# ... +" + (size() - TO_STRING_MAX) + " more";
189 } else {
190 return s;
191 }
192 }
193
194 @Override
195 public void close() {
196 }
197
198 @Override
199 public Graph getGraph() {
200 return getGraph(null).get();
201 }
202
203 @Override
204 public Optional<Graph> getGraph(final BlankNodeOrIRI graphName) {
205 return Optional.of(new DatasetGraphView(this, graphName));
206 }
207
208 @Override
209 public Stream<BlankNodeOrIRI> getGraphNames() {
210
211 return stream().map(Quad::getGraphName).filter(Optional::isPresent).map(Optional::get).distinct();
212 }
213
214 }