You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2012/02/26 19:59:42 UTC

svn commit: r1293912 - in /incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader: Langs.java ReaderRIOTBase.java WebReader2.java

Author: andy
Date: Sun Feb 26 18:59:42 2012
New Revision: 1293912

URL: http://svn.apache.org/viewvc?rev=1293912&view=rev
Log:
Tidy up.

Modified:
    incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/Langs.java
    incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/ReaderRIOTBase.java
    incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/WebReader2.java

Modified: incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/Langs.java
URL: http://svn.apache.org/viewvc/incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/Langs.java?rev=1293912&r1=1293911&r2=1293912&view=diff
==============================================================================
--- incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/Langs.java (original)
+++ incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/Langs.java Sun Feb 26 18:59:42 2012
@@ -22,8 +22,8 @@ import java.io.InputStream ;
 import java.util.HashMap ;
 import java.util.Map ;
 
+import org.openjena.atlas.lib.DS ;
 import org.openjena.atlas.lib.MultiMap ;
-import org.openjena.atlas.lib.NotImplemented ;
 import org.openjena.atlas.lib.Sink ;
 import org.openjena.riot.ContentType ;
 import org.openjena.riot.Lang ;
@@ -33,7 +33,6 @@ import org.openjena.riot.lang.LangRIOT ;
 
 import com.hp.hpl.jena.graph.Triple ;
 import com.hp.hpl.jena.sparql.core.Quad ;
-import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.util.Context ;
 
 public class Langs
@@ -71,49 +70,20 @@ public class Langs
     static Lang2 langNQuads     = Lang2.create(WebContent.contentTypeNQuads) ;
     static Lang2 langTriG       = Lang2.create(WebContent.contentTypeTriG) ;
 
+    private static Map<Lang2, ReaderRIOTFactory<Triple>> langToTriples = DS.map() ;
+    private static Map<Lang2, ReaderRIOTFactory<Quad>> langToQuads = DS.map() ;
+    private static Map<String, Lang2> mapContentTypeToLang = new HashMap<String, Lang2>() ;
+    private static MultiMap<Lang2, String> langToExt = MultiMap.createMapList() ;
+    private static Map<String, Lang2> extToLang = DS.map() ;
+    private static Map<String, Lang2> jenaName = DS.map() ;
+   
     // This code understands different types fo things it can read:
     //   triples, quads, result sets, unknown
     // These form (disjoint) value spaces static ReaderFactory<Triple> pfTriples = new ReaderFactory<Triple>() {
     // This is needed because we need to determine the output type of the reading process.
     // The decision is driven by the Content-Type.
-    // Up until the response header, the code does not need to know but given the content type,
-    // it needs to determine the class of parser that's going to be needed.
-    // (We won't need to do this if we could pass in the type information at runtime.) 
-
-//    private static String BASE = "http://jena.apastatic ReaderFactory<Triple> pfTriples = new ReaderFactory<Triple>() {che.org/parserType/" ;
-//    // Open enum.  Allows extensibility but what the use case?
-//    private Symbol TRIPLES = Symbol.create(BASE+"triples") ;
-//    private Symbol QUADS = Symbol.create(BASE+"quads") ;
-//    private Symbol RESULTSET = Symbol.create(BASE+"table") ;
-//  private Symbol OTHER = Symbol.create(BASE+"unknown") ;
-    
-    enum DataClass { TRIPLES, QUADS, RESULTSET }
-    
-    static Map<Lang2, DataClass> langToDataClass = new HashMap<Lang2, DataClass>() ;
-    static {
-        // See WebContent.mapContentTypeToLang
-        register(langRDFXML, DataClass.TRIPLES) ;
-        register(langTurtle, DataClass.TRIPLES) ;
-        register(langNTriples, DataClass.TRIPLES) ;
-        register(langN3, DataClass.TRIPLES) ;
-        register(langRDFJSON, DataClass.TRIPLES) ;
-        
-        register(langNQuads, DataClass.QUADS) ;
-        register(langTriG, DataClass.QUADS) ;   
-    }
-    
-    static DataClass dataClass(Lang2 lang)
-    {
-        return langToDataClass.get(lang) ;
-    }
-    
-    private static void register(Lang2 lang, DataClass dataClass)
-    {
-        
-    }
 
-    // Triples
-    // Generic parser factory.
+    // Triples : Generic parser factory.
     static ReaderRIOTFactory<Triple> pfTriples = new ReaderRIOTFactory<Triple>() {
         @Override
         public ReaderRIOT<Triple> create(final Lang2 language)
@@ -127,24 +97,11 @@ public class Langs
                     LangRIOT parser = RiotReader.createParserTriples(in, lang, baseURI, sink) ;
                     parser.parse() ;
                 }
+            } ;
+        }
+    } ;
 
-               
-                {}} ;
-        }} ;
-
-    static Map<Lang2, ReaderRIOTFactory<Triple>> langToTriples = new HashMap<Lang2, ReaderRIOTFactory<Triple>>() ;
-    static {
-        langToTriples.put(langRDFXML, pfTriples) ;
-        langToTriples.put(langTurtle, pfTriples) ;
-        langToTriples.put(langNTriples, pfTriples) ;
-        langToTriples.put(langN3, pfTriples) ;
-        langToTriples.put(langRDFJSON, pfTriples) ;
-        langToTriples.put(langTurtle, pfTriples) ;
-        // JSON-LD
-    }
-    
-    // Triples
-    // Generic parser factory.
+    // Quads : Generic parser factory.
     static ReaderRIOTFactory<Quad> pfQuads = new ReaderRIOTFactory<Quad>() {
         @Override
         public ReaderRIOT<Quad> create(final Lang2 language)
@@ -158,69 +115,132 @@ public class Langs
                     LangRIOT parser = RiotReader.createParserQuads(in, lang, baseURI, sink) ;
                     parser.parse() ;
                 }} ;
-        }} ;
+        }
+    } ;
 
-    static Map<Lang2, ReaderRIOTFactory<Quad>> langToQuads = new HashMap<Lang2, ReaderRIOTFactory<Quad>>() ;
-    static {
-        langToQuads.put(langNQuads, pfQuads) ;
-        langToQuads.put(langTriG, pfQuads) ;
-    }
+    static { initStandard(); }
     
-    static ReaderRIOTFactory<Binding> pfBindings = new ReaderRIOTFactory<Binding>() {
-        @Override
-        public ReaderRIOT<Binding> create(Lang2 language)
-        {
-            throw new NotImplemented() ;
-        }} ;
-    static Map<Lang2, ReaderRIOTFactory<Binding>> langToBindings = new HashMap<Lang2, ReaderRIOTFactory<Binding>>() ;
-    static {
-        //langToBindings.put(????, pfBindings) ;
+    static void addLangTriplesFactory$(Lang2 lang, ReaderRIOTFactory<Triple> factory)
+    {
+        langToTriples.put(lang, factory) ;
     }
         
-    // ---- THE WORKERS
-    public static void readTriples(TypedInputStream2 in, Sink<Triple> dest)
+
+    static void addLangQuadFactory$(Lang2 lang, ReaderRIOTFactory<Quad> factory)
     {
-        Lang2 lang = contentTypeToLang(in.getContentType()) ;
-//        if ( ! lang.isTriples() )
-//            throw new RiotException() ;
-        ReaderRIOTFactory<Triple> rf = langToTriples.get(lang) ;
-        if ( rf == null )
-        {}
-        
-        ReaderRIOT<Triple> reader = rf.create(lang) ;
-        reader.read(in.getInput(), in.getBaseURI(), in.getMediaType(), dest, null) ;
+        langToQuads.put(lang, factory) ;
     }
     
-    // UPDATE IN WebContent
-    private static Map<String, Lang2> mapContentTypeToLang = new HashMap<String, Lang2>() ;
-    static {
-        // Or is code preferrable?
-        mapContentTypeToLang.put(WebContent.contentTypeRDFXML,         langRDFXML) ;
-        mapContentTypeToLang.put(WebContent.contentTypeTurtle,         langTurtle) ;
-        mapContentTypeToLang.put(WebContent.contentTypeTurtleAlt1,     langTurtle) ;
-        mapContentTypeToLang.put(WebContent.contentTypeTurtleAlt2,     langTurtle) ;
-        mapContentTypeToLang.put(WebContent.contentTypeNTriples,       langNTriples) ;   // text/plain
-        mapContentTypeToLang.put(WebContent.contentTypeNTriplesAlt,    langNTriples) ;
-        mapContentTypeToLang.put(WebContent.contentTypeRdfJson,        langRDFJSON) ;
-
-        mapContentTypeToLang.put(WebContent.contentTypeNQuads,         langNQuads) ;
-        mapContentTypeToLang.put(WebContent.contentTypeNQuadsAlt,      langNQuads) ;
-        mapContentTypeToLang.put(WebContent.contentTypeTriG,           langTriG) ;
-        mapContentTypeToLang.put(WebContent.contentTypeTriGAlt,        langTriG) ;
+    static ReaderRIOTFactory<Triple> getFactoryTriples(Lang2 language)
+    {
+        return langToTriples.get(language) ;
     }
     
+    static ReaderRIOTFactory<Quad> getFactoryQuads(Lang2 language)
+    {
+        return langToQuads.get(language) ;
+    }
+
+    private static void jenaName(String name, Lang2 lang)
+    {
+        jenaName.put(name, lang) ;
+    }
+
+    static void addTripleSyntax$(Lang2 language, String contentType, ReaderRIOTFactory<Triple> factory, String ... fileExt)
+    {
+        addTripleSyntax$(language, ContentType.parse(contentType), factory, fileExt) ;
+    }
+    
+    static void addTripleSyntax$(Lang2 language, ContentType contentType, ReaderRIOTFactory<Triple> factory, String ... fileExt)
+    { 
+        if ( fileExt != null )
+            extension(language, fileExt) ;
+        addLangTriplesFactory$(language, factory) ;
+        addContentTypeLang(contentType, language) ;
+    } 
     
-    static Lang2 contentTypeToLang(String contentType)
+    static void addQuadSyntax$(Lang2 language, String contentType, ReaderRIOTFactory<Quad> factory, String ... fileExt)
+    {
+        addQuadSyntax$(language, ContentType.parse(contentType), factory, fileExt) ;
+    }
+
+    static void addQuadSyntax$(Lang2 language, ContentType contentType, ReaderRIOTFactory<Quad> factory, String ... fileExt)
     {
-        return mapContentTypeToLang.get(contentType) ;
+        extension(language, fileExt) ;
+        addLangQuadFactory$(language, factory) ;
+        addContentTypeLang(contentType, language) ;
     }
     
-    static Lang2 contentTypeToLang(ContentType contentType)
+    private static void extension(Lang2 lang, String ... exts)
     {
-        return contentTypeToLang(contentType.getContentType()) ;
+        langToExt.putAll(lang, exts) ;
+        for ( String ext : exts )
+            extToLang.put(ext, lang) ;
     }
-    // ---- THE WORKERS
+
+    // Initialize standard setup.
+    // In Webreader2?
+    private static void initStandard()
+    {
+        // RDF/XML
+        addTripleSyntax$(langRDFXML, WebContent.contentTypeRDFXML, pfTriples,       "rdf", "owl", "xml") ;
+        
+        // Turtle
+        addTripleSyntax$(langTurtle, WebContent.contentTypeTurtle, pfTriples,       "ttl") ;
+        addContentTypeLang$(WebContent.contentTypeTurtleAlt1, langTurtle) ;
+        addContentTypeLang$(WebContent.contentTypeTurtleAlt2, langTurtle) ;
+
+        // N-triples
+        addTripleSyntax$(langNTriples, WebContent.contentTypeNTriples, pfTriples,   "nt") ;
+        addContentTypeLang$(WebContent.contentTypeNTriplesAlt, langNTriples) ;
+        
+        // N3 (redirect to Turtle)
+        addTripleSyntax$(langN3, WebContent.contentTypeN3, pfTriples,               "n3") ;
+
+        // RDF/JSON (this is not JSON-LD)
+        addTripleSyntax$(langRDFJSON, WebContent.contentTypeRDFJSON, pfTriples,     "rj", "json") ;
+        
+        // TriG
+        addQuadSyntax$(langTriG, WebContent.contentTypeTriG, pfQuads,               "trig") ;
+        addContentTypeLang$(WebContent.contentTypeTriGAlt, langTriG) ;
+
+        // N-Quads
+        addQuadSyntax$(langNQuads, WebContent.contentTypeNQuads, pfQuads,           "nq") ;
+        addContentTypeLang$(WebContent.contentTypeNQuadsAlt, langNQuads) ;
+        
+        // Reader name and variations to lang (compatibility)
+        jenaName("RDF/XML",         langRDFXML) ;
+        jenaName("RDF/XML-ABBREV",  langRDFXML) ;
         
+        jenaName("N-TRIPLE",        langNTriples) ;
+        jenaName("N-TRIPLES",       langNTriples) ;
+        jenaName("NTRIPLE",         langNTriples) ;
+        jenaName("NTRIPLES",        langNTriples) ;
+            
+        jenaName("TURTLE",          langNTriples) ;
+        jenaName("TTL",             langNTriples) ;
+
+        jenaName("N-QUADS",         langNQuads) ;
+        jenaName("NQUADS",          langNQuads) ;
+            
+        jenaName("TRIG",            langTriG) ;
+    }
+    
+    
+    private static void addContentTypeLang$(String contentType, Lang2 lang)
+    { addContentTypeLang(ContentType.parse(contentType), lang) ; }
+    
+    private static void addContentTypeLang(ContentType contentType, Lang2 lang)
+    { mapContentTypeToLang.put(contentType.getContentType(), lang) ; }
+    
+    private static Lang2 contentTypeToLang(String contentType)
+    { return mapContentTypeToLang.get(contentType) ; }
+    
+    static Lang2 contentTypeToLang(ContentType contentType)
+    { return contentTypeToLang(contentType.getContentType()) ; }
+
+    // ** Lang upgrade.
+    
     public static ContentType guessContentType(String filenameOrIRI)
     {
         Lang lang = Lang.guess(filenameOrIRI) ;
@@ -229,9 +249,19 @@ public class Langs
         return ContentType.create(contentType, charset) ;
     }
     
+    //** Merge with Lang.guess
+    public static Lang2 guess(String resourceIRI, Lang2 dftLang)
+    {
+        return convert(Lang.guess(resourceIRI, convert(dftLang))) ;
+    }
+    
+    public static Lang2 guess(String resourceIRI)
+    {
+        return convert(Lang.guess(resourceIRI)) ;
+    }
 
     // Temporary.
-    public static Lang2 convert(Lang lang)
+    private static Lang2 convert(Lang lang)
     {
         if (lang == null) return null ;
         switch(lang)
@@ -247,9 +277,8 @@ public class Langs
         return null ;
     }
 
-    // Temporary. static Lang2 langRDFXML     = Lang2.create(WebContent.contentTypeRDFXML) ;
-
-    public static Lang convert(Lang2 lang)
+    // Temporary.
+    private static Lang convert(Lang2 lang)
     {
         if ( lang == null) return null ;
         if ( lang.equals(langRDFXML) ) return Lang.RDFXML ;
@@ -263,65 +292,7 @@ public class Langs
         return null ;
     }
 
-    //** Merge with Lang.guess
-    public static Lang2 guess(String resourceIRI, Lang2 dftLang)
-    {
-        return convert(Lang.guess(resourceIRI, convert(dftLang))) ;
-    }
-    
-    public static Lang2 guess(String resourceIRI)
-    {
-        return convert(Lang.guess(resourceIRI)) ;
-    }
-    //** Merge with Lang.guess
-
-
-    
-    // MIME specific.
-    // Check for uniqueness.
-    
-    
-    
-    private static MultiMap<Lang2, String> extensions = MultiMap.createMapList() ;
-    static {
-        extension(langRDFXML,       "rdf", "owl", "xml") ;
-        extension(langTurtle,       "ttl") ;
-        extension(langNTriples,     "nt") ;
-        extension(langN3,           "n3") ;
-        extension(langRDFJSON,      "rj", "json") ;
-        extension(langNQuads,       "nq") ;
-        extension(langTriG,         "trig") ;
-    }
-    
-    // Reader name and variations to lang (compatibility)
-    private static Map<String, Lang2> jenaName = new HashMap<String, Lang2>() ;
-    static {
-        jenaName("RDF/XML",         langRDFXML) ;
-        jenaName("RDF/XML-ABBREV",  langRDFXML) ;
-        
-        jenaName("N-TRIPLE",        langNTriples) ;
-        jenaName("N-TRIPLES",       langNTriples) ;
-        jenaName("NTRIPLE",         langNTriples) ;
-        jenaName("NTRIPLES",        langNTriples) ;
-        
-        jenaName("TURTLE",          langNTriples) ;
-        jenaName("TTL",             langNTriples) ;
-
-        jenaName("N-QUADS",         langNQuads) ;
-        jenaName("NQUADS",          langNQuads) ;
-        
-        jenaName("TRIG",            langTriG) ;
-    }
-
-    private static void extension(Lang2 lang, String ... exts)
-    {
-        extensions.putAll(lang, exts) ;
-    }
 
-    private static void jenaName(String name, Lang2 lang)
-    {
-        jenaName.put(name, lang) ;
-    }
     
 
 }

Modified: incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/ReaderRIOTBase.java
URL: http://svn.apache.org/viewvc/incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/ReaderRIOTBase.java?rev=1293912&r1=1293911&r2=1293912&view=diff
==============================================================================
--- incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/ReaderRIOTBase.java (original)
+++ incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/ReaderRIOTBase.java Sun Feb 26 18:59:42 2012
@@ -27,7 +27,6 @@ import com.hp.hpl.jena.sparql.util.Conte
 
 public abstract class ReaderRIOTBase<T> implements ReaderRIOT<T>
 {
-
     @Override
     public void read(InputStream in, String baseURI, ContentType ct, Sink<T> sink, Context context)
     {

Modified: incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/WebReader2.java
URL: http://svn.apache.org/viewvc/incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/WebReader2.java?rev=1293912&r1=1293911&r2=1293912&view=diff
==============================================================================
--- incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/WebReader2.java (original)
+++ incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/riot/reader/WebReader2.java Sun Feb 26 18:59:42 2012
@@ -29,6 +29,7 @@ import org.openjena.riot.RiotLoader ;
 import org.openjena.riot.RiotNotFoundException ;
 import org.openjena.riot.SysRIOT ;
 import org.openjena.riot.WebContent ;
+import org.openjena.riot.lang.SinkQuadsToDataset ;
 import org.openjena.riot.lang.SinkTriplesToGraph ;
 import org.slf4j.Logger ;
 import org.slf4j.LoggerFactory ;
@@ -36,22 +37,39 @@ import riot.reader.fm2.FileManager2 ;
 
 import com.hp.hpl.jena.graph.Graph ;
 import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.query.Dataset ;
 import com.hp.hpl.jena.rdf.model.Model ;
 import com.hp.hpl.jena.rdf.model.ModelFactory ;
 import com.hp.hpl.jena.rdf.model.impl.RDFReaderFImpl ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Quad ;
 import com.hp.hpl.jena.sparql.util.Context ;
 import com.hp.hpl.jena.sparql.util.Symbol ;
 import com.hp.hpl.jena.sparql.util.Utils ;
 
-/** General purpose reader framework.
+/** <p>General purpose reader framework for RDF (triples and quads) syntaxes.</p>   
+ *  <ul>
+ *  <li>HTTP Content negotiation</li>
+ *  <li>File type hint in the extension</li>
+ *  <li>Application language hint</li>
+ *  </ul>
+ * <p>
+ *  It also provide a way to lookup names in different
+ *  locations and to remap URIs to other URIs. 
+ *  </p>
+ *  <p>
+ *  Extensible - a new syntax can be added to the framework. 
+ *  </p>
  */
 /*
  *  Design notes
- *    There are functions (static methods) for reading various kinds of "thing"
- *    streams of triples or quads, result sets, (other?)
+ *    There are functions (static methods) for reading various kinds of "thing",
+ *    streams of triples or quads.
+ *    
+ *    Later: result sets, (other?)
  *    
  *    The lifecycle of a "read" action is:
- *       open -> TypeStream
+ *       open -> TypeInputStream
  *       process
  *       ts.close
  *       
@@ -63,44 +81,28 @@ import com.hp.hpl.jena.sparql.util.Utils
  *    
  * To Do
  *   Sort out ContentType vs MediaType
- *   Sort out contants and naming
+ *   Sort out constants and naming
  *   Should this be "Lang" driven - make Lang extensible (use Symbol).
- *   TypesStream -> RDF Stream and include the final base URI 
  *   Pull in stuff (tables) from Langs.
- *   
- * FileManager
- *   remove cache (wrong place) 
- *   openTypedStream
- *   Locators to do the remapping?  No - nice that it's orthogical.
  */
 public class WebReader2
 {
     /* TODO
-     * 1/ ContentType vs MediaType
-     * 2/ TypedInputStream vs  TypedInputStream2 (issue is that TIS is an input stream, indirection via FilteredInputStream)
-     *     Drop this??, have getInputStream/getOutputStream
-     *     TypedInputStream uses MediaType
+     * 1/ ContentType vs MediaType  // ContentType - little used but better?
+     * 3/ static for global (singleton) and locally tailored. 
      */
     
-    // **** Additional to, and upgrade of, riot.WebReader
     static Logger log = LoggerFactory.getLogger(WebReader2.class) ;
+    private static String riotBase = "http://jena.apache.org/riot/" ; 
+    private static String fileManagerSymbolStr = riotBase+"filemanager" ; 
+    public static Symbol fileManagerSymbol = Symbol.create(fileManagerSymbolStr) ; 
+    
 
-    public static void main(String ... argv)
+    public static void wireIntoJena()
     {
-//        LocatorFile2 loc = new LocatorFile2("/DIR") ;
-//        
-//        System.out.println(loc.toFile("FILE").getAbsoluteFile()) ;
-//        System.out.println(loc.toFile("file:FILE").getAbsoluteFile()) ;
-//        
-//        System.exit(0) ;
-        
-        // TODO
-        // Language hints.
-        
-        SysRIOT.wireIntoJena() ;
-        // Wirein generic 
+        // Wire in generic 
         String readerRDF = RDFReaderRIOT.class.getName() ;
-        RDFReaderFImpl.setBaseReaderClassName("RDF/XML", readerRDF) ;           // And default
+        RDFReaderFImpl.setBaseReaderClassName("RDF/XML",    readerRDF) ;           // And default
         RDFReaderFImpl.setBaseReaderClassName("RDF/XML-ABBREV", readerRDF) ;
 
         RDFReaderFImpl.setBaseReaderClassName("N-TRIPLES",  readerRDF) ;
@@ -110,10 +112,21 @@ public class WebReader2
         RDFReaderFImpl.setBaseReaderClassName("Turtle",     readerRDF) ;
         RDFReaderFImpl.setBaseReaderClassName("TTL",        readerRDF) ;
         RDFReaderFImpl.setBaseReaderClassName("RDF/JSON",   readerRDF) ;
-        
+    }
+    
+    public static void resetJenaReaders()
+    {
+        SysRIOT.resetJenaReaders() ;
+    }
+    
+    public static void main(String ... argv)
+    {
+        wireIntoJena() ;
         Log.enable(WebReader2.class) ;
+
         Model m = ModelFactory.createDefaultModel() ;
         m.read("file:D.ttl", "RDF/XML") ;
+        
         System.out.println("triples = "+m.size()) ;
         System.out.println("DONE") ;
         System.exit(0) ;
@@ -124,56 +137,72 @@ public class WebReader2
         System.out.println("triples = "+m.size()) ;
     }
     
-    // >>>> **** Setup
-    // in Langs.
-    // CTstring -> Lang -> reader?
-    // Yes - provides a constant for a language
-    
-    // <<<< **** Setup
-
-    // **** See also HttpResponseLib (handler-dispatch style)
-    //      Merge here, and delete 
-    //      Specific to HTTP.
-    //      Can we use it's generalization for result set?
-    
-    //      How to have a registry --  
-    //         partly, WebContent.contentTypeToLang(in.getContentType()) ;
-    //         but why not content type -> reader?
-    
-    // Sort out riot.ContentType and riot.web.MediaType
-    // ContentType - little used but better?
-    
-    /** Read triples into a Model from the given location.
+    /** Read triples into a Model from the given location. 
+     * @see #read(Model,String,Context) 
      */
     public static void read(Model m, String uri)                    { read(m, uri, null, null) ; }
     
-    /** Read triples into a Model from the given location, with a ghint of the language (MIME type) */
+    /** Read triples into a Model from the given location, with a hint of the language (MIME type) 
+     *  @see #read(Model,String,Context) 
+     */
     public static void read(Model m, String uri, String hintLang)   { read(m, uri, hintLang, null) ; }
     
-    /** Read triples into a Model from the given location, with some parameters for the reader */ 
+    /** Read triples into a Model from the given location, with some parameters for the reader
+     *  @see #read(Model,String,Context) 
+     */ 
     public static void read(Model m, String uri, Context context)   { read(m, uri, null, context) ; }
     
     /** Read triples into a Model from the given location, with hint of langauge and the with some parameters for the reader 
-    *  Throws XYZ if the location is not found - the model is unchanged.
+    *  Throws {@link RiotNotFoundException} if the location is not found - the model is unchanged.
     *  Throws parse errors depending on the language and reader; the model maybe partially updated. 
     */
     public static void read(Model m, String uri, String hintLang, Context context)
     {
         Graph g = m.getGraph() ;
         Sink<Triple> sink = new SinkTriplesToGraph(g) ;
-        read(sink, uri, hintLang, context) ;
+        readTriples(sink, uri, hintLang, context) ;
     }
-        
-    private static String base = "http://jena.apache.org/riot/" ; 
-    private static String fileManagerSymbolStr = base+"filemanager" ; 
-    public static Symbol fileManagerSymbol = Symbol.create(fileManagerSymbolStr) ; 
+
+    /** Read quads into a Dataset from the given location, with hint of langauge and the with some parameters for the reader 
+     *  Throws {@link RiotNotFoundException} if the location is not found - the model is unchanged.
+     *  Throws parse errors depending on the language and reader; the model maybe partially updated. 
+     */
+    public static void read(Dataset dataset, String uri, String hintLang, Context context)
+    {
+        DatasetGraph dsg = dataset.asDatasetGraph() ;
+        Sink<Quad> sink = new SinkQuadsToDataset(dsg) ;
+        readQuads(sink, uri, hintLang, context) ;
+    }
+    
+    // Lang2 lang = Langs.contentTypeToLang(ct) ;
+    // ReaderRIOTFactory<Triple> r = Langs.langToTriples.get(lang) ; 
     
-    private static void read(Sink<Triple> sink, String uri, String hintLang, Context context)
+    public static void addTripleSyntax(Lang2 language, ContentType contentType, ReaderRIOTFactory<Triple> factory, String ... fileExt )
+    { 
+        Langs.addTripleSyntax$(language, contentType, factory, fileExt) ;
+    } 
+    
+    public static void addQuadSyntax(Lang2 language, ContentType contentType, ReaderRIOTFactory<Quad> factory, String ... fileExt )
+    {
+        Langs.addQuadSyntax$(language, contentType, factory, fileExt) ;
+    }
+    
+
+    public static void readTriples(Sink<Triple> sink, String uri, String hintLang, Context context)
+    {
+        TypedInputStream2 in = open(uri, context) ;
+        if ( in == null )
+            throw new RiotException("Not found: "+uri) ;
+        processTriples(sink, uri, in, hintLang, context) ;
+        in.close() ;
+    }
+    
+    public static void readQuads(Sink<Quad> sink, String uri, String hintLang, Context context)
     {
         TypedInputStream2 in = open(uri, context) ;
         if ( in == null )
             throw new RiotException("Not found: "+uri) ;
-        process(sink, uri, in, hintLang, context) ;
+        processQuads(sink, uri, in, hintLang, context) ;
         in.close() ;
     }
 
@@ -181,7 +210,7 @@ public class WebReader2
     public static TypedInputStream2 open(String filenameOrURI)
     { return open(filenameOrURI, (Context)null) ; }
     
-    static TypedInputStream2 open(String filenameOrURI, Context context)
+    public static TypedInputStream2 open(String filenameOrURI, Context context)
     {
         FileManager2 fMgr = FileManager2.get() ;
         if ( context != null )
@@ -194,7 +223,7 @@ public class WebReader2
         return open(filenameOrURI, fMgr) ;
     }
     
-    static TypedInputStream2 open(String filenameOrURI, FileManager2 fMgr)
+    private static TypedInputStream2 open(String filenameOrURI, FileManager2 fMgr)
     {
         TypedInputStream2 in = fMgr.open(filenameOrURI) ;
             
@@ -222,7 +251,7 @@ public class WebReader2
     // We could have had two step design - ReaderFactory-ReaderInstance
     // no - put the bruden on complicated readers, not everyone. 
     
-    private static void process(Sink<Triple> sink, String uri, TypedInputStream2 in, String hintLang, Context context)
+    private static void processTriples(Sink<Triple> sink, String uri, TypedInputStream2 in, String hintLang, Context context)
     {
         boolean isTextPlain = WebContent.contentTypeTextPlain.equals(in.getContentType()) ;
         
@@ -232,25 +261,51 @@ public class WebReader2
         if ( ( _ct == null || isTextPlain ) && hintLang != null )
             _ct = hintLang ;
         // Error? ....
-        ContentType ct = ContentType.parse(_ct) ;
+        ContentType ct = ContentType.parse(_ct) ;  // TODO Error
         if ( ct == null )
-        {}
+        {} // TODO Error
         ReaderRIOT<Triple> reader = getReaderTriples(ct) ;
         if ( reader == null )
-        {}
+        {}  // TODO Error
         reader.read(in.getInput(), uri, ct, sink, context) ;
     }
 
     private static ReaderRIOT<Triple> getReaderTriples(ContentType ct)
     {
         Lang2 lang = Langs.contentTypeToLang(ct) ;
-        ReaderRIOTFactory<Triple> r = Langs.langToTriples.get(lang) ;
+        ReaderRIOTFactory<Triple> r = Langs.getFactoryTriples(lang) ;
+        if ( r == null )
+            return null ;
+        return r.create(lang) ;
+    }
+    
+    private static void processQuads(Sink<Quad> sink, String uri, TypedInputStream2 in, String hintLang, Context context)
+    {
+        String _ct = null ;
+        if ( in.getMediaType() != null )
+            _ct = WebContent.contentTypeCanonical(in.getContentType()) ;
+        if ( _ct == null && hintLang != null )
+            _ct = hintLang ;
+        // Error? ....
+        ContentType ct = ContentType.parse(_ct) ;  // TODO Error
+        if ( ct == null )
+        {} // TODO Error
+        ReaderRIOT<Quad> reader = getReaderQuads(ct) ;
+        if ( reader == null )
+        {}  // TODO Error
+        reader.read(in.getInput(), uri, ct, sink, context) ;
+    }
+
+    private static ReaderRIOT<Quad> getReaderQuads(ContentType ct)
+    {
+        Lang2 lang = Langs.contentTypeToLang(ct) ;
+        ReaderRIOTFactory<Quad> r = Langs.getFactoryQuads(lang) ;
         if ( r == null )
             return null ;
         return r.create(lang) ;
     }
     
-    /** General rReadereader-of-triples for a fixed language */
+    /** General reader-of-triples for a fixed language */
     static class ReaderLangTriple implements ReaderRIOT<Triple>
     {
         private final Lang lang ;