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 org.apache.commons.rdf.api.*;
21 import org.apache.commons.rdf.simple.SimpleRDF.SimpleRDFTerm;
22
23 import java.util.HashSet;
24 import java.util.Set;
25 import java.util.function.Predicate;
26 import java.util.stream.Collectors;
27 import java.util.stream.Stream;
28
29
30
31
32
33
34
35
36 final class GraphImpl implements Graph {
37
38 private static final int TO_STRING_MAX = 10;
39 private final Set<Triple> triples = new HashSet<>();
40 private final SimpleRDF factory;
41
42 GraphImpl(final SimpleRDF simpleRDF) {
43 this.factory = simpleRDF;
44 }
45
46 @Override
47 public void add(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
48 final BlankNodeOrIRI newSubject = (BlankNodeOrIRI) internallyMap(subject);
49 final IRI newPredicate = (IRI) internallyMap(predicate);
50 final RDFTerm newObject = internallyMap(object);
51 final Triple result = factory.createTriple(newSubject, newPredicate, newObject);
52 triples.add(result);
53 }
54
55 @Override
56 public void add(final Triple triple) {
57 triples.add(internallyMap(triple));
58 }
59
60 private <T extends RDFTerm> RDFTerm internallyMap(final T object) {
61 if (object == null || object instanceof SimpleRDFTerm) {
62
63
64
65
66 return object;
67 }
68 if (object instanceof BlankNode) {
69 final BlankNode blankNode = (BlankNode) object;
70
71
72
73
74 return factory.createBlankNode(blankNode.uniqueReference());
75 } else if (object instanceof IRI) {
76 final IRI iri = (IRI) object;
77 return factory.createIRI(iri.getIRIString());
78 } else if (object instanceof Literal) {
79 final Literal literal = (Literal) object;
80 if (literal.getLanguageTag().isPresent()) {
81 return factory.createLiteral(literal.getLexicalForm(), literal.getLanguageTag().get());
82 } else {
83 return factory.createLiteral(literal.getLexicalForm(), (IRI) internallyMap(literal.getDatatype()));
84 }
85 } else {
86 throw new IllegalArgumentException("RDFTerm was neither a BlankNode, IRI nor Literal: " + object);
87 }
88 }
89
90 private Triple internallyMap(final Triple triple) {
91 final BlankNodeOrIRI newSubject = (BlankNodeOrIRI) internallyMap(triple.getSubject());
92 final IRI newPredicate = (IRI) internallyMap(triple.getPredicate());
93 final RDFTerm newObject = internallyMap(triple.getObject());
94
95
96 if (newSubject == triple.getSubject() && newPredicate == triple.getPredicate()
97 && newObject == triple.getObject()) {
98 return triple;
99 } else {
100 return factory.createTriple(newSubject, newPredicate, newObject);
101 }
102 }
103
104 @Override
105 public void clear() {
106 triples.clear();
107 }
108
109 @Override
110 public boolean contains(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
111 return stream(subject, predicate, object).findFirst().isPresent();
112 }
113
114 @Override
115 public boolean contains(final Triple triple) {
116 return triples.contains(internallyMap(triple));
117 }
118
119 @Override
120 public Stream<Triple> stream() {
121 return triples.parallelStream().unordered();
122 }
123
124 @Override
125 public Stream<Triple> stream(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
126 final BlankNodeOrIRI newSubject = (BlankNodeOrIRI) internallyMap(subject);
127 final IRI newPredicate = (IRI) internallyMap(predicate);
128 final RDFTerm newObject = internallyMap(object);
129
130 return getTriples(t -> {
131
132
133 if (subject != null && !t.getSubject().equals(newSubject)) {
134 return false;
135 }
136 if (predicate != null && !t.getPredicate().equals(newPredicate)) {
137 return false;
138 }
139 if (object != null && !t.getObject().equals(newObject)) {
140 return false;
141 }
142 return true;
143 });
144 }
145
146 private Stream<Triple> getTriples(final Predicate<Triple> filter) {
147 return stream().filter(filter);
148 }
149
150 @Override
151 public void remove(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
152 final Stream<Triple> toRemove = stream(subject, predicate, object);
153 for (final Triple t : toRemove.collect(Collectors.toList())) {
154
155 remove(t);
156 }
157 }
158
159 @Override
160 public void remove(final Triple triple) {
161 triples.remove(internallyMap(triple));
162 }
163
164 @Override
165 public long size() {
166 return triples.size();
167 }
168
169 @Override
170 public String toString() {
171 final String s = stream().limit(TO_STRING_MAX).map(Object::toString).collect(Collectors.joining("\n"));
172 if (size() > TO_STRING_MAX) {
173 return s + "\n# ... +" + (size() - TO_STRING_MAX) + " more";
174 } else {
175 return s;
176 }
177 }
178
179 }