View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.commons.rdf.rdf4j.impl;
19  
20  import java.util.Collections;
21  import java.util.ConcurrentModificationException;
22  import java.util.HashSet;
23  import java.util.Objects;
24  import java.util.Set;
25  import java.util.UUID;
26  import java.util.stream.Stream;
27  
28  import org.apache.commons.rdf.api.BlankNodeOrIRI;
29  import org.apache.commons.rdf.api.IRI;
30  import org.apache.commons.rdf.api.RDFTerm;
31  import org.apache.commons.rdf.api.Triple;
32  import org.apache.commons.rdf.rdf4j.ClosableIterable;
33  import org.apache.commons.rdf.rdf4j.RDF4JBlankNodeOrIRI;
34  import org.apache.commons.rdf.rdf4j.RDF4JGraph;
35  import org.apache.commons.rdf.rdf4j.RDF4JTriple;
36  import org.eclipse.rdf4j.common.iteration.Iterations;
37  import org.eclipse.rdf4j.model.Resource;
38  import org.eclipse.rdf4j.model.Statement;
39  import org.eclipse.rdf4j.model.Value;
40  import org.eclipse.rdf4j.repository.Repository;
41  import org.eclipse.rdf4j.repository.RepositoryConnection;
42  import org.eclipse.rdf4j.repository.RepositoryResult;
43  
44  class RepositoryGraphImpl extends AbstractRepositoryGraphLike<Triple> implements RDF4JGraph {
45  
46      private final Resource[] contextMask;
47  
48      RepositoryGraphImpl(final Repository repository, final UUID salt, final boolean handleInitAndShutdown, final boolean includeInferred,
49              final Resource... contextMask) {
50          super(repository, salt, handleInitAndShutdown, includeInferred);
51          this.contextMask = Objects.requireNonNull(contextMask);
52      }
53  
54      @Override
55      public void add(final Triple tripleLike) {
56          final Statement statement = rdf4jTermFactory.asStatement(tripleLike);
57          try (RepositoryConnection conn = getRepositoryConnection()) {
58              conn.add(statement, contextMask);
59              conn.commit();
60          }
61      }
62  
63      @Override
64      public boolean contains(final Triple tripleLike) {
65          final Statement statement = rdf4jTermFactory.asStatement(tripleLike);
66          try (RepositoryConnection conn = getRepositoryConnection()) {
67              return conn.hasStatement(statement, includeInferred, contextMask);
68          }
69      }
70  
71      @Override
72      public void remove(final Triple tripleLike) {
73          final Statement statement = rdf4jTermFactory.asStatement(tripleLike);
74          try (RepositoryConnection conn = getRepositoryConnection()) {
75              conn.remove(statement, contextMask);
76              conn.commit();
77          }
78      }
79  
80      @Override
81      public void clear() {
82          try (RepositoryConnection conn = getRepositoryConnection()) {
83              conn.clear(contextMask);
84              conn.commit();
85          }
86      }
87  
88      @Override
89      public long size() {
90          if (!includeInferred && contextMask.length == 0) {
91              try (RepositoryConnection conn = getRepositoryConnection()) {
92                  return conn.size();
93              }
94          }
95          try (Stream<RDF4JTriple> stream = stream()) {
96              return stream.count();
97          }
98      }
99  
100     @Override
101     public void add(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
102         final Resource subj = (Resource) rdf4jTermFactory.asValue(subject);
103         final org.eclipse.rdf4j.model.IRI pred = (org.eclipse.rdf4j.model.IRI) rdf4jTermFactory.asValue(predicate);
104         final Value obj = rdf4jTermFactory.asValue(object);
105         try (RepositoryConnection conn = getRepositoryConnection()) {
106             conn.add(subj, pred, obj, contextMask);
107             conn.commit();
108         }
109     }
110 
111     @Override
112     public boolean contains(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
113         final Resource subj = (Resource) rdf4jTermFactory.asValue(subject);
114         final org.eclipse.rdf4j.model.IRI pred = (org.eclipse.rdf4j.model.IRI) rdf4jTermFactory.asValue(predicate);
115         final Value obj = rdf4jTermFactory.asValue(object);
116         try (RepositoryConnection conn = getRepositoryConnection()) {
117             return conn.hasStatement(subj, pred, obj, includeInferred, contextMask);
118         }
119     }
120 
121     @Override
122     public void remove(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
123         final Resource subj = (Resource) rdf4jTermFactory.asValue(subject);
124         final org.eclipse.rdf4j.model.IRI pred = (org.eclipse.rdf4j.model.IRI) rdf4jTermFactory.asValue(predicate);
125         final Value obj = rdf4jTermFactory.asValue(object);
126         try (RepositoryConnection conn = getRepositoryConnection()) {
127             conn.remove(subj, pred, obj, contextMask);
128             conn.commit();
129         }
130     }
131 
132     @Override
133     public ClosableIterable<Triple> iterate() throws ConcurrentModificationException, IllegalStateException {
134         return iterate(null, null, null);
135     }
136 
137     @Override
138     public ClosableIterable<Triple> iterate(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object)
139             throws ConcurrentModificationException, IllegalStateException {
140         final Resource subj = (Resource) rdf4jTermFactory.asValue(subject);
141         final org.eclipse.rdf4j.model.IRI pred = (org.eclipse.rdf4j.model.IRI) rdf4jTermFactory.asValue(predicate);
142         final Value obj = rdf4jTermFactory.asValue(object);
143         return new ConvertedStatements<>(this::getRepositoryConnection, rdf4jTermFactory::asTriple, subj, pred,
144                 obj, contextMask);
145     }
146 
147     @Override
148     public Stream<RDF4JTriple> stream() {
149         return stream(null, null, null);
150     }
151 
152     @Override
153     public Stream<RDF4JTriple> stream(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) {
154         final Resource subj = (Resource) rdf4jTermFactory.asValue(subject);
155         final org.eclipse.rdf4j.model.IRI pred = (org.eclipse.rdf4j.model.IRI) rdf4jTermFactory.asValue(predicate);
156         final Value obj = rdf4jTermFactory.asValue(object);
157 
158         // NOTE: We can't do the usual try..with closing of the
159         // RepositoryConnection here as it will have to be closed outside
160         // by the user of the returned stream
161         final RepositoryConnection conn = getRepositoryConnection();
162         Stream<RDF4JTriple> stream = null;
163         try {
164             final RepositoryResult<Statement> statements = conn.getStatements(subj, pred, obj, includeInferred, contextMask);
165             // NOTE: Iterations.stream should close RepositoryResult as long as
166             // our caller closes the stream
167             stream = Iterations.stream(statements).map(this::asTripleLike);
168         } finally {
169             if (stream == null) {
170                 // Some exception before we made the stream, close connection
171                 // here
172                 conn.close();
173             }
174         }
175         // Make sure the RepositoryConnection is closed
176         return stream == null ? null : stream.onClose(conn::close);
177     }
178 
179     @Override
180     protected RDF4JTriple asTripleLike(final Statement statement) {
181         return rdf4jTermFactory.asTriple(statement);
182     }
183 
184     @Override
185     public Set<RDF4JBlankNodeOrIRI> getContextMask() {
186         final Set<RDF4JBlankNodeOrIRI> mask = new HashSet<>();
187         for (final Resource s : contextMask) {
188             mask.add(rdf4jTermFactory.asRDFTerm(s));
189         }
190         return Collections.unmodifiableSet(mask);
191     }
192 
193 }