1   /*
2    * RDFpro - An extensible tool for building stream-oriented RDF processing libraries.
3    * 
4    * Written in 2014 by Francesco Corcoglioniti with support by Marco Amadori, Michele Mostarda,
5    * Alessio Palmero Aprosio and Marco 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;
15  
16  import java.util.Map;
17  import java.util.Objects;
18  import java.util.concurrent.ConcurrentHashMap;
19  
20  import javax.annotation.Nullable;
21  
22  import org.openrdf.model.Literal;
23  import org.openrdf.model.Statement;
24  import org.openrdf.model.URI;
25  import org.openrdf.model.Value;
26  import org.openrdf.rio.RDFHandler;
27  import org.openrdf.rio.RDFHandlerException;
28  
29  import eu.fbk.rdfpro.util.Namespaces;
30  
31  final class ProcessorPrefix implements RDFProcessor {
32  
33      private final Map<String, String> sourceNsToPrefixMap; // ns -> prefix map
34  
35      ProcessorPrefix(@Nullable final Map<String, String> nsToPrefixMap) {
36          this.sourceNsToPrefixMap = nsToPrefixMap != null ? nsToPrefixMap //
37                  : Namespaces.DEFAULT.prefixMap();
38      }
39  
40      @Override
41      public RDFHandler wrap(final RDFHandler handler) {
42          return new Handler(Objects.requireNonNull(handler));
43      }
44  
45      private final class Handler extends AbstractRDFHandlerWrapper {
46  
47          private Map<String, String> collectedNs; // emitted ns, used as set
48  
49          Handler(final RDFHandler handler) {
50              super(handler);
51              this.collectedNs = new ConcurrentHashMap<String, String>();
52          }
53  
54          @Override
55          public void handleNamespace(final String prefix, final String uri)
56                  throws RDFHandlerException {
57              if (this.collectedNs.put(uri, uri) == null) {
58                  String p = ProcessorPrefix.this.sourceNsToPrefixMap.get(uri);
59                  if (p == null) {
60                      p = prefix;
61                  }
62                  super.handleNamespace(p, uri);
63              }
64          }
65  
66          @Override
67          public void handleStatement(final Statement statement) throws RDFHandlerException {
68              emitNamespacesFor(statement.getSubject());
69              emitNamespacesFor(statement.getPredicate());
70              emitNamespacesFor(statement.getObject());
71              emitNamespacesFor(statement.getContext());
72              super.handleStatement(statement);
73          }
74  
75          @Override
76          public void endRDF() throws RDFHandlerException {
77              super.endRDF();
78              this.collectedNs.clear();
79          }
80  
81          @Override
82          public void close() {
83              super.close();
84              this.collectedNs = null;
85          }
86  
87          private void emitNamespacesFor(final Value value) throws RDFHandlerException {
88              if (value instanceof URI) {
89                  final URI uri = (URI) value;
90                  emitNamespace(uri.getNamespace());
91              } else if (value instanceof Literal) {
92                  final Literal literal = (Literal) value;
93                  final URI uri = literal.getDatatype();
94                  if (uri != null) {
95                      emitNamespace(uri.getNamespace());
96                  }
97              }
98          }
99  
100         private void emitNamespace(final String namespace) throws RDFHandlerException {
101             if (this.collectedNs.put(namespace, namespace) == null) {
102                 final String prefix = ProcessorPrefix.this.sourceNsToPrefixMap.get(namespace);
103                 if (prefix != null) {
104                     super.handleNamespace(prefix, namespace);
105                 }
106             }
107         }
108 
109     }
110 
111 }