View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *  http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.any23.extractor.rdf;
19  
20  import java.util.Map.Entry;
21  import java.util.UUID;
22  
23  import org.apache.any23.extractor.ExtractionResult;
24  import org.eclipse.rdf4j.model.IRI;
25  import org.eclipse.rdf4j.model.Resource;
26  import org.eclipse.rdf4j.model.Value;
27  import org.eclipse.rdf4j.model.ValueFactory;
28  import com.github.jsonldjava.core.JsonLdConsts;
29  import com.github.jsonldjava.core.JsonLdTripleCallback;
30  import com.github.jsonldjava.core.RDFDataset;
31  
32  /**
33   * @author Hans Brende (hansbrende@apache.org)
34   */
35  class JSONLDJavaSink implements JsonLdTripleCallback {
36  
37      private static final String BNODE_PREFIX = JsonLdConsts.BLANK_NODE_PREFIX;
38  
39      private final ExtractionResult handler;
40      private final ValueFactory valueFactory;
41      private final String bNodeUniquifier;
42  
43      JSONLDJavaSink(ExtractionResult handler, ValueFactory valueFactory) {
44          this.handler = handler;
45          this.valueFactory = valueFactory;
46          this.bNodeUniquifier = "n" + UUID.randomUUID().toString().replace("-", "") + "x";
47      }
48  
49      private Resource createResource(RDFDataset.Node resource) {
50          String value = resource == null ? null : resource.getValue();
51          if (value != null && value.startsWith(BNODE_PREFIX)) {
52              String bNodeId = value.substring(BNODE_PREFIX.length());
53  
54              if (bNodeId.length() < 32) { // not globally unique; will collide with other blank node ids
55                  if (bNodeId.isEmpty()) {
56                      bNodeId = Integer.toHexString(System.identityHashCode(resource));
57                  }
58                  bNodeId = bNodeUniquifier + bNodeId;
59              }
60  
61              return valueFactory.createBNode(bNodeId);
62          }
63          return valueFactory.createIRI(value);
64      }
65  
66      private void writeQuad(RDFDataset.Node sNode, RDFDataset.Node pNode, Value o, String graphName) {
67          if (graphName != null && graphName.startsWith(BNODE_PREFIX)) {
68              // TODO support blank node graph names in Any23
69              return;
70          }
71          Resource s = createResource(sNode);
72          IRI p = valueFactory.createIRI(pNode == null ? null : pNode.getValue());
73          if (s == null || p == null || o == null) {
74              return;
75          }
76          if (graphName == null || graphName.isEmpty() || JsonLdConsts.DEFAULT.equalsIgnoreCase(graphName)) {
77              handler.writeTriple(s, p, o);
78          } else {
79              handler.writeTriple(s, p, o, valueFactory.createIRI(graphName));
80          }
81      }
82  
83      @Override
84      public Object call(final RDFDataset dataset) {
85          for (Entry<String, String> nextNamespace : dataset.getNamespaces().entrySet()) {
86              handler.writeNamespace(nextNamespace.getKey(), nextNamespace.getValue());
87          }
88          for (String graphName : dataset.keySet()) {
89              for (RDFDataset.Quad quad : dataset.getQuads(graphName)) {
90                  RDFDataset.Node s = quad.getSubject();
91                  RDFDataset.Node p = quad.getPredicate();
92                  RDFDataset.Node o = quad.getObject();
93                  if (o == null || !o.isLiteral()) {
94                      writeQuad(s, p, createResource(o), graphName);
95                  } else {
96                      String lang = o.getLanguage();
97                      String datatype = o.getDatatype();
98                      String literal = o.getValue();
99                      if (lang != null && !lang.isEmpty()
100                             && (datatype == null || datatype.indexOf(':') < 0
101                                     || JsonLdConsts.RDF_LANGSTRING.equalsIgnoreCase(datatype)
102                                     || JsonLdConsts.XSD_STRING.equalsIgnoreCase(datatype))) {
103                         writeQuad(s, p, valueFactory.createLiteral(literal, lang), graphName);
104                     } else if (datatype != null && !datatype.isEmpty()) {
105                         writeQuad(s, p, valueFactory.createLiteral(literal, valueFactory.createIRI(datatype)),
106                                 graphName);
107                     } else {
108                         writeQuad(s, p, valueFactory.createLiteral(literal), graphName);
109                     }
110                 }
111             }
112         }
113         return null;
114     }
115 }