/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jena.riot.writer; import java.io.OutputStream ; import java.io.Writer ; import java.util.HashMap ; import java.util.HashSet ; import java.util.Map ; import java.util.Set ; import org.apache.jena.atlas.io.IndentedWriter ; import org.apache.jena.atlas.json.io.JSWriter ; import org.apache.jena.atlas.lib.Pair ; import org.apache.jena.graph.Graph ; import org.apache.jena.graph.GraphUtil ; import org.apache.jena.graph.Node ; import org.apache.jena.graph.Triple ; import org.apache.jena.riot.Lang ; import org.apache.jena.riot.RiotException ; import org.apache.jena.riot.system.PrefixMap ; import org.apache.jena.sparql.util.Context ; import org.apache.jena.sparql.util.NodeUtils ; import org.apache.jena.util.iterator.ExtendedIterator ; public class RDFJSONWriter extends WriterGraphRIOTBase { public RDFJSONWriter() {} public static void output(OutputStream out, Graph graph) { output(new JSWriter(out), graph ) ; } public static void output(Writer out, Graph graph) { output(new JSWriter(new IndentedWriterEx(out)), graph ) ; } @Override public Lang getLang() { return Lang.RDFJSON ; } @Override public void write(Writer out, Graph graph, PrefixMap prefixMap, String baseURI, Context context) { output(out, graph) ; } @Override public void write(OutputStream out, Graph graph, PrefixMap prefixMap, String baseURI, Context context) { output(out, graph) ; } private static void output(JSWriter out, Graph graph) { out.startOutput() ; out.startObject(); ExtendedIterator<Node> subjects = GraphUtil.listSubjects(graph, Node.ANY, Node.ANY) ; try { Map<Node, Set<Node>> predicates = new HashMap<>() ; while ( subjects.hasNext() ) { Node subject = subjects.next() ; ExtendedIterator<Triple> triples = graph.find(subject, Node.ANY, Node.ANY) ; try { while ( triples.hasNext() ) { Triple triple = triples.next() ; Node p = triple.getPredicate() ; if ( predicates.containsKey(p) ) { predicates.get(p).add(triple.getObject()) ; } else { Set<Node> objects = new HashSet<>() ; objects.add(triple.getObject()) ; predicates.put(p, objects) ; } } } finally { if ( triples != null ) triples.close() ; } send(out, new Pair<>(subject, predicates)) ; predicates.clear() ; } } finally { if ( subjects != null ) subjects.close() ; out.finishObject(); out.finishOutput() ; } } private static void send(JSWriter out, Pair<Node, Map<Node, Set<Node>>> item) { Node s = item.getLeft() ; if ( s.isBlank() ) { out.key("_:" + s.getBlankNodeLabel()) ; } else if ( s.isURI() ) { out.key(s.getURI()) ; } else { throw new RiotException ("Only URIs or blank nodes are legal subjects.") ; } out.startObject() ; // out.pair(key, value) ; Map<Node, Set<Node>> predicates = item.getRight() ; for (Node p : predicates.keySet() ) { out.key(p.getURI()) ; out.startArray() ; Set<Node> objects = predicates.get(p) ; int i = 0; for ( Node o : objects ) { out.startObject() ; if ( o.isBlank() ) { out.pair("type", "bnode") ; out.pair("value", "_:" + o.getBlankNodeLabel()) ; } else if ( o.isURI() ) { out.pair("type", "uri") ; out.pair("value", o.getURI()) ; } else if ( o.isLiteral() ) { String lex = o.getLiteralLexicalForm() ; out.pair("type", "literal") ; out.pair("value", lex) ; if ( NodeUtils.isSimpleString(o) ) { // No-op. } else if ( NodeUtils.isLangString(o) ) { String lang = o.getLiteralLanguage() ; out.pair("lang", lang) ; } else { // Datatype, nothing special. String dt = o.getLiteralDatatypeURI() ; out.pair("datatype", dt) ; } } out.finishObject() ; if (i < objects.size() - 1) { out.arraySep(); } i++; } out.finishArray() ; } out.finishObject() ; } private static class IndentedWriterEx extends IndentedWriter { public IndentedWriterEx(Writer writer) { super(writer); } } }