1   /*
2    * RDFpro - An extensible tool for building stream-oriented RDF processing libraries.
3    * 
4    * Written in 2015 by Francesco Corcoglioniti with support by Alessio Palmero Aprosio and Marco
5    * Rospocher. Contact info on http://rdfpro.fbk.eu/
6    * 
7    * To the extent possible under law, the authors have dedicated all copyright and related and
8    * neighboring rights to this software to the public domain worldwide. This software is
9    * distributed without any warranty.
10   * 
11   * You should have received a copy of the CC0 Public Domain Dedication along with this software.
12   * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13   */
14  package eu.fbk.rdfpro.util;
15  
16  import java.util.Iterator;
17  import java.util.Objects;
18  import java.util.Set;
19  
20  import javax.annotation.Nullable;
21  
22  import org.openrdf.model.Model;
23  import org.openrdf.model.Namespace;
24  import org.openrdf.model.Resource;
25  import org.openrdf.model.Statement;
26  import org.openrdf.model.URI;
27  import org.openrdf.model.Value;
28  import org.openrdf.model.impl.ContextStatementImpl;
29  import org.openrdf.model.util.ModelException;
30  
31  final class QuadModelModelAdapter extends QuadModel implements AutoCloseable {
32  
33      private static final long serialVersionUID = 1L;
34  
35      private final Model model;
36  
37      QuadModelModelAdapter(final Model model) {
38          this.model = Objects.requireNonNull(model);
39      }
40  
41      @Override
42      public void close() throws Exception {
43          IO.closeQuietly(this.model);
44      }
45  
46      @Override
47      protected Set<Namespace> doGetNamespaces() {
48          return this.model.getNamespaces();
49      }
50  
51      @Override
52      protected Namespace doGetNamespace(final String prefix) {
53          return this.model.getNamespace(prefix);
54      }
55  
56      @Override
57      protected Namespace doSetNamespace(final String prefix, @Nullable final String name) {
58          if (name == null) {
59              return this.model.removeNamespace(prefix);
60          } else {
61              final Namespace namespace = this.model.getNamespace(prefix);
62              this.model.setNamespace(prefix, name);
63              return namespace;
64          }
65      }
66  
67      @Override
68      protected int doSize(@Nullable final Resource subj, @Nullable final URI pred,
69              @Nullable final Value obj, final Resource[] ctxs) {
70          return subj == null && pred == null && obj == null && ctxs.length == 0 ? this.model.size()
71                  : this.model.filter(subj, pred, obj, ctxs).size();
72      }
73  
74      @Override
75      protected Iterator<Statement> doIterator(@Nullable final Resource subj,
76              @Nullable final URI pred, @Nullable final Value obj, final Resource[] ctxs) {
77          return this.model.filter(subj, pred, obj, ctxs).iterator();
78      }
79  
80      @Override
81      protected boolean doAdd(final Resource subj, final URI pred, final Value obj,
82              final Resource[] ctxs) {
83          if (ctxs.length == 0) {
84              return doAddHelper(subj, pred, obj, CTX_DEFAULT);
85          } else if (ctxs.length == 1) {
86              return doAddHelper(subj, pred, obj, ctxs);
87          } else {
88              boolean modified = false;
89              for (final Resource ctx : ctxs) {
90                  final boolean m = doAddHelper(subj, pred, obj, new Resource[] { ctx });
91                  modified |= m;
92              }
93              return modified;
94          }
95      }
96  
97      private boolean doAddHelper(final Resource subj, final URI pred, final Value obj,
98              final Resource[] ctx) {
99          final boolean added = this.model.add(subj, pred, obj, ctx);
100         if (!added) {
101             if (this.model.filter(subj, pred, obj, ctx).isEmpty()) {
102                 throw new ModelException("Model already contains statement "
103                         + new ContextStatementImpl(subj, pred, obj, ctx[0]));
104             }
105             return false;
106         }
107         return true;
108     }
109 
110     @Override
111     protected boolean doRemove(@Nullable final Resource subj, @Nullable final URI pred,
112             @Nullable final Value obj, final Resource[] ctxs) {
113         return this.model.remove(subj, pred, obj, ctxs);
114     }
115 
116 }