juneau-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamesbog...@apache.org
Subject [27/51] [partial] incubator-juneau git commit: Rename project directories.
Date Tue, 09 Aug 2016 19:54:00 GMT
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/jena/RdfCommonContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jena/RdfCommonContext.java b/juneau-core/src/main/java/org/apache/juneau/jena/RdfCommonContext.java
new file mode 100644
index 0000000..0220c3d
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/jena/RdfCommonContext.java
@@ -0,0 +1,386 @@
+/***************************************************************************************************************************
+ * 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.juneau.jena;
+
+import java.util.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.jena.annotation.*;
+import org.apache.juneau.xml.*;
+import org.apache.juneau.xml.annotation.*;
+
+/**
+ * Configurable properties common to both the {@link RdfSerializer} and {@link RdfParser} classes.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@SuppressWarnings("serial")
+public interface RdfCommonContext {
+// TODO - RENAME?
+	/**
+	 * Maps RDF writer names to property prefixes that apply to them.
+	 */
+	final static Map<String,String> LANG_PROP_MAP = new HashMap<String,String>() {{
+		put("RDF/XML","rdfXml.");
+		put("RDF/XML-ABBREV","rdfXml.");
+		put("N3","n3.");
+		put("N3-PP","n3.");
+		put("N3-PLAIN","n3.");
+		put("N3-TRIPLES","n3.");
+		put("TURTLE","n3.");
+		put("N-TRIPLE","ntriple.");
+	}};
+
+	/**
+	 * The RDF language to serialize to ({@link String}, default=<js>"RDF/XML-ABBREV"</js>).
+	 * <p>
+	 * 	Can be any of the following:
+	 * <ul class='spaced-list'>
+	 * 	<li><js>"RDF/XML"</js>
+	 * 	<li><js>"RDF/XML-ABBREV"</js>
+	 * 	<li><js>"N-TRIPLE"</js>
+	 * 	<li><js>"N3"</js> - General name for the N3 writer.
+	 * 		Will make a decision on exactly which writer to use (pretty writer, plain writer or simple writer) when created.
+	 * 		Default is the pretty writer but can be overridden with system property	<code>com.hp.hpl.jena.n3.N3JenaWriter.writer</code>.
+	 * 	<li><js>"N3-PP"</js> - Name of the N3 pretty writer.
+	 * 		The pretty writer uses a frame-like layout, with prefixing, clustering like properties and embedding one-referenced bNodes.
+	 * 	<li><js>"N3-PLAIN"</js> - Name of the N3 plain writer.
+	 * 		The plain writer writes records by subject.
+	 * 	<li><js>"N3-TRIPLES"</js> - Name of the N3 triples writer.
+	 * 		This writer writes one line per statement, like N-Triples, but does N3-style prefixing.
+	 * 	<li><js>"TURTLE"</js> -  Turtle writer.
+	 * 		http://www.dajobe.org/2004/01/turtle/
+	 * </ul>
+	 */
+	public static final String RDF_language = "Rdf.language";
+
+	/**
+	 * The XML namespace for Juneau properties ({@link Namespace}, default=<js>{j:'http://www.ibm.com/juneau/'}</js>).
+	 */
+	public static final String RDF_juneauNs = "Rdf.juneauNs";
+
+	/**
+	 * The default XML namespace for bean properties ({@link Namespace}, default=<js>{j:'http://www.ibm.com/juneaubp/'}</js>).
+	 */
+	public static final String RDF_juneauBpNs = "Rdf.juneauBpNs";
+
+	/**
+	 * Reuse XML namespaces when RDF namespaces not specified ({@link Boolean}, default=<jk>true</jk>).
+	 * <p>
+	 * 	When specified, namespaces defined using {@link XmlNs} and {@link Xml} will be inherited by the RDF serializers.
+	 * 	Otherwise, namespaces will be defined using {@link RdfNs} and {@link Rdf}.
+	 */
+	public static final String RDF_useXmlNamespaces = "Rdf.useXmlNamespaces";
+
+	/**
+	 * RDF/XML property: <code>iri_rules</code> ({@link String}, default=<js>"lax"</js>).
+	 * <p>
+	 *  	Set the engine for checking and resolving.
+	 * <p>
+	 * 	Possible values:
+	 * <ul class='spaced-list'>
+	 * 	<li><js>"lax"</js> - The rules for RDF URI references only, which does permit spaces although the use of spaces is not good practice.
+	 * 	<li><js>"strict"</js> - Sets the IRI engine with rules for valid IRIs, XLink and RDF; it does not permit spaces in IRIs.
+	 * 	<li><js>"iri"</js> - Sets the IRI engine to IRI (<a href='http://www.ietf.org/rfc/rfc3986.txt'>RFC 3986</a>, <a href='http://www.ietf.org/rfc/rfc3987.txt'>RFC 3987</a>).
+	 * </ul>
+	 */
+	public static final String RDF_arp_iriRules = "Rdf.jena.rdfXml.iri-rules";
+
+	/**
+	 * RDF/XML ARP property: <code>error-mode</code> ({@link String}, default=<js>"lax"</js>).
+	 * <p>
+	 * 	This allows a coarse-grained approach to control of error handling.
+	 * <p>
+	 * 	Possible values:
+	 * <ul>
+	 * 	<li><js>"default"</js>
+	 * 	<li><js>"lax"</js>
+	 * 	<li><js>"strict"</js>
+	 * 	<li><js>"strict-ignore"</js>
+	 * 	<li><js>"strict-warning"</js>
+	 * 	<li><js>"strict-error"</js>
+	 * 	<li><js>"strict-fatal"</js>
+	 * </ul>
+	 * <p>
+	 * 	See also:
+	 * <ul class='spaced-list'>
+	 * 	<li><a href='http://jena.sourceforge.net/javadoc/com/hp/hpl/jena/rdf/arp/ARPOptions.html#setDefaultErrorMode()'>ARPOptions.setDefaultErrorMode()</a>
+	 * 	<li><a href='http://jena.sourceforge.net/javadoc/com/hp/hpl/jena/rdf/arp/ARPOptions.html#setLaxErrorMode()'>ARPOptions.setLaxErrorMode()</a>
+	 * 	<li><a href='http://jena.sourceforge.net/javadoc/com/hp/hpl/jena/rdf/arp/ARPOptions.html#setStrictErrorMode()'>ARPOptions.setStrictErrorMode()</a>
+	 * 	<li><a href='http://jena.sourceforge.net/javadoc/com/hp/hpl/jena/rdf/arp/ARPOptions.html#setStrictErrorMode(int)'>ARPOptions.setStrictErrorMode(int)</a>
+	 * </ul>
+	 */
+	public static final String RDF_arp_errorMode = "Rdf.jena.rdfXml.error-mode";
+
+	/**
+	 * RDF/XML ARP property: <code>embedding</code> ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 * 	Sets ARP to look for RDF embedded within an enclosing XML document.
+	 * <p>
+	 * 	See also:
+	 * <ul class='spaced-list'>
+	 * 	<li><a href='http://jena.sourceforge.net/javadoc/com/hp/hpl/jena/rdf/arp/ARPOptions.html#setEmbedding(boolean)'>ARPOptions.setEmbedding(boolean)</a>
+	 * </ul>
+	 */
+	public static final String RDF_arp_embedding = "Rdf.jena.rdfXml.embedding";
+
+	/**
+	 * RDF/XML ARP property: <code>ERR_xxx</code> ({@link String}).
+	 * <p>
+	 * 	Provides fine-grained control over detected error conditions.
+	 * <p>
+	 * 	Possible values:
+	 * <ul>
+	 * 	<li><js>"EM_IGNORE"</js>
+	 * 	<li><js>"EM_WARNING"</js>
+	 * 	<li><js>"EM_ERROR"</js>
+	 * 	<li><js>"EM_FATAL"</js>
+	 * </ul>
+	 * <p>
+	 * 	See also:
+	 * <ul class='spaced-list'>
+	 * 	<li><a href='http://jena.sourceforge.net/javadoc/com/hp/hpl/jena/rdf/arp/ARPErrorNumbers.html'>ARPErrorNumbers</a>
+	 * 	<li><a href='http://jena.sourceforge.net/javadoc/com/hp/hpl/jena/rdf/arp/ARPOptions.html#setErrorMode(int,%20int)'>ARPOptions.setErrorMode(int, int)</a>
+	 * </ul>
+	 */
+	public static final String RDF_arp_err_ = "Rdf.jena.rdfXml.ERR_";
+
+	/**
+	 * RDF/XML ARP property: <code>WARN_xxx</code> ({@link String}).
+	 * <p>
+	 * 	See {@link #RDF_arp_err_} for details.
+	 */
+	public static final String RDF_arp_warn_ = "Rdf.jena.rdfXml.WARN_";
+
+	/**
+	 * RDF/XML ARP property: <code>IGN_xxx</code> ({@link String}).
+	 * <p>
+	 * 	See {@link #RDF_arp_err_} for details.
+	 */
+	public static final String RDF_arp_ign_ = "Rdf.jena.rdfXml.IGN_";
+
+	/**
+	 * RDF/XML property: <code>xmlbase</code> ({@link String}, default=<jk>null</jk>).
+	 * <p>
+	 * 	The value to be included for an <xa>xml:base</xa> attribute on the root element in the file.
+	 */
+	public static final String RDF_rdfxml_xmlBase = "Rdf.jena.rdfXml.xmlbase";
+
+	/**
+	 * RDF/XML property: <code>longId</code> ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 *  	Whether to use long ID's for anon resources.
+	 *  	Short ID's are easier to read, but can run out of memory on very large models.
+	 */
+	public static final String RDF_rdfxml_longId = "Rdf.jena.rdfXml.longId";
+
+	/**
+	 * RDF/XML property: <code>allowBadURIs</code> ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 * 	URIs in the graph are, by default, checked prior to serialization.
+	 */
+	public static final String RDF_rdfxml_allowBadUris = "Rdf.jena.rdfXml.allowBadURIs";
+
+	/**
+	 * RDF/XML property: <code>relativeURIs</code> ({@link String}).
+	 * <p>
+	 * 	What sort of relative URIs should be used.
+	 * <p>
+	 * 	A comma separate list of options:
+	 * <ul class='spaced-list'>
+	 * 	<li><js>"same-document"</js> - Same-document references (e.g. <js>""</js> or <js>"#foo"</js>)
+	 * 	<li><js>"network"</js>  - Network paths (e.g. <js>"//example.org/foo"</js> omitting the URI scheme)
+	 * 	<li><js>"absolute"</js> - Absolute paths (e.g. <js>"/foo"</js> omitting the scheme and authority)
+	 * 	<li><js>"relative"</js> - Relative path not begining in <js>"../"</js>
+	 * 	<li><js>"parent"</js> - Relative path begining in <js>"../"</js>
+	 * 	<li><js>"grandparent"</js> - Relative path begining in <js>"../../"</js>
+	 * </ul>
+	 * <p>
+	 * 	The default value is <js>"same-document, absolute, relative, parent"</js>.
+	 * 	To switch off relative URIs use the value <js>""</js>.
+	 * 	Relative URIs of any of these types are output where possible if and only if the option has been specified.
+	 */
+	public static final String RDF_rdfxml_relativeUris = "Rdf.jena.rdfXml.relativeURIs";
+
+	/**
+	 * RDF/XML property: <code>showXmlDeclaration</code> ({@link String}, default=<js>"default"</js>).
+	 * <p>
+	 * 	Possible values:
+	 * <ul class='spaced-list'>
+	 * 	<li><js>"true"</js> - Add XML Declaration to the output.
+	 * 	<li><js>"false"</js> - Don't add XML Declaration to the output.
+	 * 	<li><js>"default"</js> - Only add an XML Declaration when asked to write to an <code>OutputStreamWriter</code> that uses some encoding other than <code>UTF-8</code> or <code>UTF-16</code>.
+	 * 		In this case the encoding is shown in the XML declaration.
+	 * </ul>
+	 */
+	public static final String RDF_rdfxml_showXmlDeclaration = "Rdf.jena.rdfXml.showXmlDeclaration";
+
+	/**
+	 * RDF/XML property: <code>showDoctypeDeclaration</code> ({@link Boolean}, default=<jk>true</jk>).
+	 * <p>
+	 * 	If true, an XML Doctype declaration is included in the output.
+	 * 	This declaration includes a <code>!ENTITY</code> declaration for each prefix mapping in the model, and any attribute value that starts with the URI of that mapping is written as starting with the corresponding entity invocation.
+	 */
+	public static final String RDF_rdfxml_showDoctypeDeclaration = "Rdf.jena.rdfXml.showDoctypeDeclaration";
+
+	/**
+	 * RDF/XML property: <code>tab</code> ({@link Integer}, default=<code>2</code>).
+	 * <p>
+	 * 	The number of spaces with which to indent XML child elements.
+	 */
+	public static final String RDF_rdfxml_tab = "Rdf.jena.rdfXml.tab";
+
+	/**
+	 * RDF/XML property: <code>attributeQuoteChar</code> ({@link Character}, default=<js>'"'</js>).
+	 * <p>
+	 * 	The XML attribute quote character.
+	 */
+	public static final String RDF_rdfxml_attributeQuoteChar = "Rdf.jena.rdfXml.attributeQuoteChar";
+
+	/**
+	 * RDF/XML property: <code>blockRules</code> ({@link String}, default=<js>""</js>).
+	 * <p>
+	 * 	A list of <code>Resource</code> or a <code>String</code> being a comma separated list of fragment IDs from <a href='http://www.w3.org/TR/rdf-syntax-grammar'>RDF Syntax Grammar</a> indicating grammar rules that will not be used.
+	 */
+	public static final String RDF_rdfxml_blockRules = "Rdf.jena.rdfXml.blockRules";
+
+	/**
+	 * N3/Turtle property: <code>minGap</code> ({@link Integer}, default=<code>1</code>).
+	 * <p>
+	 * 	Minimum gap between items on a line.
+	 */
+	public static final String RDF_n3_minGap = "Rdf.jena.n3.minGap";
+
+	/**
+	 * N3/Turtle property: <code>objectLists</code> ({@link Boolean}, default=<jk>true</jk>).
+	 * <p>
+	 * 	Print object lists as comma separated lists.
+	 */
+	public static final String RDF_n3_objectLists = "Rdf.jena.n3.objectLists";
+
+	/**
+	 * N3/Turtle property: <code>subjectColumn</code> ({@link Integer}, default=indentProperty).
+	 * <p>
+	 * 	If the subject is shorter than this value, the first property may go on the same line.
+	 */
+	public static final String RDF_n3_subjectColumn = "Rdf.jena.n3.subjectColumn";
+
+	/**
+	 * N3/Turtle property: <code>propertyColumn</code> ({@link Integer}, default=<code>8</code>).
+	 * <p>
+	 *  	Width of the property column.
+	 */
+	public static final String RDF_n3_propertyColumn = "Rdf.jena.n3.propertyColumn";
+
+	/**
+	 * N3/Turtle property: <code>indentProperty</code> ({@link Integer}, default=<code>6</code>).
+	 * <p>
+	 * 	Width to indent properties.
+	 */
+	public static final String RDF_n3_indentProperty = "Rdf.jena.n3.indentProperty";
+
+	/**
+	 * N3/Turtle property: <code>widePropertyLen</code> ({@link Integer}, default=<code>20</code>).
+	 * <p>
+	 * 	Width of the property column.
+	 * 	Must be longer than <code>propertyColumn</code>.
+	 */
+	public static final String RDF_n3_widePropertyLen = "Rdf.jena.n3.widePropertyLen";
+
+	/**
+	 * N3/Turtle property: <code>abbrevBaseURI</code> ({@link Boolean}, default=<jk>true</jk>).
+	 * <p>
+	 * 	Control whether to use abbreviations <code>&lt;&gt;</code> or <code>&lt;#&gt;</code>.
+	 */
+	public static final String RDF_n3_abbrevBaseUri = "Rdf.jena.n3.abbrevBaseURI";
+
+	/**
+	 * N3/Turtle property: <code>usePropertySymbols</code> ({@link Boolean}, default=<jk>true</jk>).
+	 * <p>
+	 * 	Control whether to use <code>a</code>, <code>=</code> and <code>=&gt;</code> in output
+	 */
+	public static final String RDF_n3_usePropertySymbols = "Rdf.jena.n3.usePropertySymbols";
+
+	/**
+	 * N3/Turtle property: <code>useTripleQuotedStrings</code> ({@link Boolean}, default=<jk>true</jk>).
+	 * <p>
+	 * 	Allow the use of <code>"""</code> to delimit long strings.
+	 */
+	public static final String RDF_n3_useTripleQuotedStrings = "Rdf.jena.n3.useTripleQuotedStrings";
+
+	/**
+	 * N3/Turtle property: <code>useDoubles</code> ({@link Boolean}, default=<jk>true</jk>).
+	 * <p>
+	 * 	Allow the use doubles as <code>123.456</code>.
+	 */
+	public static final String RDF_n3_useDoubles = "Rdf.jena.n3.useDoubles";
+
+	/**
+	 * The RDF format for representing collections and arrays.  ({@link String}, default=<js>"DEFAULT"</js>).
+	 * <p>
+	 * 	Possible values:
+	 * 	<ul class='spaced-list'>
+	 * 		<li><js>"DEFAULT"</js> - Default format.  The default is an RDF Sequence container.
+	 * 		<li><js>"SEQ"</js> - RDF Sequence container.
+	 * 		<li><js>"BAG"</js> - RDF Bag container.
+	 * 		<li><js>"LIST"</js> - RDF List container.
+	 * 		<li><js>"MULTI_VALUED"</js> - Multi-valued properties.
+	 * 	</ul>
+	 *	</p>
+	 *	<p>
+	 *		Important Note:  If you use <js>"BAG"</js> or <js>"MULTI_VALUED"</js>, the order of the elements
+	 *		in the collection will get lost.
+	 */
+	public static final String RDF_collectionFormat = "Rdf.collectionFormat";
+
+	/**
+	 * Specifies that collections should be serialized and parsed as loose collections.  ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 * When specified, collections of resources are handled as loose collections of resources in RDF instead of
+	 * resources that are children of an RDF collection (e.g. Sequence, Bag).
+	 * <p>
+	 * Note that this setting is specialized for RDF syntax, and is incompatible with the concept of
+	 * losslessly representing POJO models, since the tree structure of these POJO models are lost
+	 * when serialized as loose collections.
+	 *	<p>
+	 *	This setting is typically only useful if the beans being parsed into do not have a bean property
+	 *	annotated with {@link BeanProperty#beanUri @BeanProperty(beanUri=true)}.
+	 *
+	 * <dl>
+	 * 	<dt>Example:</dt>
+	 * 	<dd>
+	 * <p class='bcode'>
+	 * 	WriterSerializer s = <jk>new</jk> RdfSerializer.XmlAbbrev().setProperty(<jsf>RDF_looseCollection</jsf>, <jk>true</jk>);
+	 * 	ReaderParser p = <jk>new</jk> RdfParser.Xml().setProperty(<jsf>RDF_looseCollection</jsf>, <jk>true</jk>);
+	 *
+	 * 	List&lt;MyBean&gt; l = createListOfMyBeans();
+	 *
+	 * 	<jc>// Serialize to RDF/XML as loose resources</jc>
+	 * 	String rdfXml = s.serialize(l);
+	 *
+	 *		<jc>// Parse back into a Java collection</jc>
+	 * 	l = p.parseCollection(rdfXml, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
+	 *
+	 * 	MyBean[] b = createArrayOfMyBeans();
+	 *
+	 * 	<jc>// Serialize to RDF/XML as loose resources</jc>
+	 * 	String rdfXml = s.serialize(b);
+	 *
+	 *		<jc>// Parse back into a bean array</jc>
+	 * 	b = p.parse(rdfXml, MyBean[].<jk>class</jk>);
+	 * </p>
+	 * 	</dd>
+	 * </dl>
+	 */
+	public static final String RDF_looseCollection = "Rdf.looseCollection";
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/jena/RdfParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jena/RdfParser.java b/juneau-core/src/main/java/org/apache/juneau/jena/RdfParser.java
new file mode 100644
index 0000000..0cb097b
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/jena/RdfParser.java
@@ -0,0 +1,498 @@
+/***************************************************************************************************************************
+ * 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.juneau.jena;
+
+import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.jena.Constants.*;
+import static org.apache.juneau.jena.RdfCommonContext.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.transform.*;
+
+import com.hp.hpl.jena.rdf.model.*;
+import com.hp.hpl.jena.util.iterator.*;
+
+/**
+ * Parses RDF into POJOs.
+ *
+ *
+ * <h6 class='topic'>Configurable properties</h6>
+ * <p>
+ * 	Refer to <a class='doclink' href='package-summary.html#ParserConfigurableProperties'>Configurable Properties</a>
+ * 		for the entire list of configurable properties.
+ *
+ *
+ * <h6 class='topic'>Behavior-specific subclasses</h6>
+ * <p>
+ * 	The following direct subclasses are provided for language-specific parsers:
+ * <ul class='spaced-list'>
+ * 	<li>{@link RdfParser.Xml} - RDF/XML and RDF/XML-ABBREV.
+ * 	<li>{@link RdfParser.NTriple} - N-TRIPLE.
+ * 	<li>{@link RdfParser.Turtle} - TURTLE.
+ * 	<li>{@link RdfParser.N3} - N3.
+ * </ul>
+ *
+ *
+ * <h6 class='topic'>Additional Information</h6>
+ * <p>
+ * 	See <a class='doclink' href='package-summary.html#TOC'>RDF Overview</a> for an overview of RDF support in Juneau.
+ *
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@Consumes(value="text/xml+rdf")
+public class RdfParser extends ReaderParser {
+
+	/** Default XML parser, all default settings.*/
+	public static final RdfParser DEFAULT_XML = new RdfParser.Xml().lock();
+
+	/** Default Turtle parser, all default settings.*/
+	public static final RdfParser DEFAULT_TURTLE = new RdfParser.Turtle().lock();
+
+	/** Default N-Triple parser, all default settings.*/
+	public static final RdfParser DEFAULT_NTRIPLE = new RdfParser.NTriple().lock();
+
+	/** Default N3 parser, all default settings.*/
+	public static final RdfParser DEFAULT_N3 = new RdfParser.N3().lock();
+
+
+	/** Consumes RDF/XML input */
+	@Consumes("text/xml+rdf")
+	public static class Xml extends RdfParser {
+		/** Constructor */
+		public Xml() {
+			setProperty(RDF_language, LANG_RDF_XML);
+		}
+	}
+
+	/** Consumes N-Triple input */
+	@Consumes(value="text/n-triple")
+	public static class NTriple extends RdfParser {
+		/** Constructor */
+		public NTriple() {
+			setProperty(RDF_language, LANG_NTRIPLE);
+		}
+	}
+
+	/** Consumes Turtle input */
+	@Consumes(value="text/turtle")
+	public static class Turtle extends RdfParser {
+		/** Constructor */
+		public Turtle() {
+			setProperty(RDF_language, LANG_TURTLE);
+		}
+	}
+
+	/** Consumes N3 input */
+	@Consumes(value="text/n3")
+	public static class N3 extends RdfParser {
+		/** Constructor */
+		public N3() {
+			setProperty(RDF_language, LANG_N3);
+		}
+	}
+
+
+	@SuppressWarnings({"unchecked", "rawtypes"})
+	@Override /* ReaderParser */
+	protected <T> T doParse(ParserSession session, ClassMeta<T> type) throws Exception {
+
+		RdfParserSession s = (RdfParserSession)session;
+
+		type = session.getBeanContext().normalizeClassMeta(type);
+
+		Model model = s.getModel();
+		RDFReader r = s.getRdfReader();
+		r.read(model, session.getReader(), null);
+		BeanContext bc = session.getBeanContext();
+
+		List<Resource> roots = getRoots(s, model);
+
+		// Special case where we're parsing a loose collection of resources.
+		if (s.isLooseCollection() && (type.isCollection() || type.isArray())) {
+			Collection c = null;
+			if (type.isArray())
+				c = new ArrayList();
+			else
+				c = (type.canCreateNewInstance(session.getOuter()) ? (Collection<?>)type.newInstance(session.getOuter()) : new ObjectList(bc));
+			for (Resource resource : roots)
+				c.add(parseAnything(s, type.getElementType(), resource, session.getOuter()));
+
+			if (type.isArray())
+				return (T)bc.toArray(type, c);
+			return (T)c;
+		}
+
+		if (roots.isEmpty())
+			return null;
+		if (roots.size() > 1)
+			throw new ParseException(session, "Too many root nodes found in model:  {0}", roots.size());
+		Resource resource = roots.get(0);
+
+		return parseAnything(s, type, resource, session.getOuter());
+	}
+
+	/*
+	 * Finds the roots in the model using either the "root" property to identify it,
+	 * 	or by resorting to scanning the model for all nodes with no incoming predicates.
+	 */
+	private List<Resource> getRoots(RdfParserSession session, Model m) {
+		List<Resource> l = new LinkedList<Resource>();
+
+		// First try to find the root using the "http://www.ibm.com/juneau/root" property.
+		Property root = m.createProperty(session.getJuneauNsUri(), RDF_juneauNs_ROOT);
+		for (ResIterator i  = m.listResourcesWithProperty(root); i.hasNext();)
+			l.add(i.next());
+
+		if (! l.isEmpty())
+			return l;
+
+		// Otherwise, we need to find all resources that aren't objects.
+		// We want to explicitly ignore statements where the subject
+		// and object are the same node.
+		Set<RDFNode> objects = new HashSet<RDFNode>();
+		for (StmtIterator i = m.listStatements(); i.hasNext();) {
+			Statement st = i.next();
+			RDFNode subject = st.getSubject();
+			RDFNode object = st.getObject();
+			if (object.isResource() && ! object.equals(subject))
+				objects.add(object);
+		}
+		for (ResIterator i = m.listSubjects(); i.hasNext();) {
+			Resource r = i.next();
+			if (! objects.contains(r))
+				l.add(r);
+		}
+		return l;
+	}
+
+	private <T> BeanMap<T> parseIntoBeanMap(RdfParserSession session, Resource r2, BeanMap<T> m) throws Exception {
+		BeanMeta<T> bm = m.getMeta();
+		if (bm.hasBeanUriProperty() && r2.getURI() != null)
+			m.putBeanUri(r2.getURI());
+		Property subTypeIdProperty = null;
+		BeanPropertyMeta<T> stp = bm.getSubTypeIdProperty();
+		if (stp != null) {
+			subTypeIdProperty = session.getProperty(stp.getName());
+			Statement st = r2.getProperty(subTypeIdProperty);
+			if (st == null)
+				throw new ParseException(session, "Could not find subtype ID property for bean of type ''{0}''", m.getClassMeta());
+			String subTypeId = st.getLiteral().getString();
+			stp.set(m, subTypeId);
+		}
+		for (StmtIterator i = r2.listProperties(); i.hasNext();) {
+			Statement st = i.next();
+			Property p = st.getPredicate();
+			if (p.equals(subTypeIdProperty))
+				continue;
+			String key = session.decodeString(p.getLocalName());
+			BeanPropertyMeta<T> pMeta = m.getPropertyMeta(key);
+			session.setCurrentProperty(pMeta);
+			if (pMeta != null) {
+				RDFNode o = st.getObject();
+				ClassMeta<?> cm = pMeta.getClassMeta();
+				if ((cm.isArray() || cm.isCollection()) && isMultiValuedCollections(session, pMeta)) {
+					ClassMeta<?> et = cm.getElementType();
+					Object value = parseAnything(session, et, o, m.getBean(false));
+					setName(et, value, key);
+					pMeta.add(m, value);
+				} else {
+					Object value = parseAnything(session, cm, o, m.getBean(false));
+					setName(cm, value, key);
+					pMeta.set(m, value);
+				}
+			} else if (! (p.equals(session.getRootProperty()) || p.equals(session.getClassProperty()) || p.equals(subTypeIdProperty))) {
+				if (bm.isSubTyped()) {
+					RDFNode o = st.getObject();
+					Object value = parseAnything(session, object(), o, m.getBean(false));
+					m.put(key, value);
+				} else {
+					onUnknownProperty(session, key, m, -1, -1);
+				}
+			}
+			session.setCurrentProperty(null);
+		}
+		return m;
+	}
+
+	private boolean isMultiValuedCollections(RdfParserSession session, BeanPropertyMeta<?> pMeta) {
+		if (pMeta != null && pMeta.getRdfMeta().getCollectionFormat() != RdfCollectionFormat.DEFAULT)
+			return pMeta.getRdfMeta().getCollectionFormat() == RdfCollectionFormat.MULTI_VALUED;
+		return session.getCollectionFormat() == RdfCollectionFormat.MULTI_VALUED;
+	}
+
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	private <T> T parseAnything(RdfParserSession session, ClassMeta<T> nt, RDFNode n, Object outer) throws Exception {
+
+		BeanContext bc = session.getBeanContext();
+
+		if (nt == null)
+			nt = (ClassMeta<T>)object();
+		PojoTransform<T,Object> transform = (PojoTransform<T,Object>)nt.getPojoTransform();
+		ClassMeta<?> ft = nt.getTransformedClassMeta();
+		session.setCurrentClass(ft);
+
+		if (! ft.canCreateNewInstance(outer)) {
+			if (n.isResource()) {
+				Statement st = n.asResource().getProperty(session.getClassProperty());
+				if (st != null) {
+ 					String c = st.getLiteral().getString();
+					ft = nt = (ClassMeta<T>)bc.getClassMetaFromString(c);
+				}
+			}
+		}
+
+		Object o = null;
+		if (n.isResource() && n.asResource().getURI() != null && n.asResource().getURI().equals(RDF_NIL)) {
+			// Do nothing.  Leave o == null.
+		} else if (ft.isObject()) {
+			if (n.isLiteral()) {
+				o = n.asLiteral().getValue();
+				if (o instanceof String) {
+					o = session.decodeString(o);
+				}
+			}
+			else if (n.isResource()) {
+				Resource r = n.asResource();
+				if (session.wasAlreadyProcessed(r))
+					o = r.getURI();
+				else if (r.getProperty(session.getValueProperty()) != null) {
+					o = parseAnything(session, object(), n.asResource().getProperty(session.getValueProperty()).getObject(), outer);
+				} else if (isSeq(session, r)) {
+					o = new ObjectList(bc);
+					parseIntoCollection(session, r.as(Seq.class), (Collection)o, ft.getElementType());
+				} else if (isBag(session, r)) {
+					o = new ObjectList(bc);
+					parseIntoCollection(session, r.as(Bag.class), (Collection)o, ft.getElementType());
+				} else if (r.canAs(RDFList.class)) {
+					o = new ObjectList(bc);
+					parseIntoCollection(session, r.as(RDFList.class), (Collection)o, ft.getElementType());
+				} else {
+					// If it has a URI and no child properties, we interpret this as an
+					// external resource, and convert it to just a URL.
+					String uri = r.getURI();
+					if (uri != null && ! r.listProperties().hasNext()) {
+						o = r.getURI();
+					} else {
+						o = new ObjectMap(bc);
+						parseIntoMap(session, r, (Map)o, null, null);
+					}
+				}
+			} else {
+				throw new ParseException(session, "Unrecognized node type ''{0}'' for object", n);
+			}
+		} else if (ft.isBoolean()) {
+			o = bc.convertToType(getValue(session, n, outer), boolean.class);
+		} else if (ft.isCharSequence()) {
+			o = session.decodeString(getValue(session, n, outer));
+		} else if (ft.isChar()) {
+			o = session.decodeString(getValue(session, n, outer)).charAt(0);
+		} else if (ft.isNumber()) {
+			o = parseNumber(getValue(session, n, outer).toString(), (Class<? extends Number>)ft.getInnerClass());
+		} else if (ft.isMap()) {
+			Resource r = n.asResource();
+			if (session.wasAlreadyProcessed(r))
+				return null;
+			Map m = (ft.canCreateNewInstance(outer) ? (Map)ft.newInstance(outer) : new ObjectMap(bc));
+			o = parseIntoMap(session, r, m, nt.getKeyType(), nt.getValueType());
+		} else if (ft.isCollection() || ft.isArray()) {
+			if (ft.isArray())
+				o = new ArrayList();
+			else
+				o = (ft.canCreateNewInstance(outer) ? (Collection<?>)ft.newInstance(outer) : new ObjectList(bc));
+			Resource r = n.asResource();
+			if (session.wasAlreadyProcessed(r))
+				return null;
+			if (isSeq(session, r)) {
+				parseIntoCollection(session, r.as(Seq.class), (Collection)o, ft.getElementType());
+			} else if (isBag(session, r)) {
+				parseIntoCollection(session, r.as(Bag.class), (Collection)o, ft.getElementType());
+			} else if (r.canAs(RDFList.class)) {
+				parseIntoCollection(session, r.as(RDFList.class), (Collection)o, ft.getElementType());
+			} else {
+				throw new ParseException("Unrecognized node type ''{0}'' for collection", n);
+			}
+			if (ft.isArray())
+				o = bc.toArray(ft, (Collection)o);
+		} else if (ft.canCreateNewInstanceFromObjectMap(outer)) {
+			Resource r = n.asResource();
+			if (session.wasAlreadyProcessed(r))
+				return null;
+			Map m = new ObjectMap(bc);
+			parseIntoMap(session, r, m, nt.getKeyType(), nt.getValueType());
+			o = ft.newInstanceFromObjectMap(outer, (ObjectMap)m);
+		} else if (ft.canCreateNewBean(outer)) {
+			Resource r = n.asResource();
+			if (session.wasAlreadyProcessed(r))
+				return null;
+			BeanMap<?> bm = bc.newBeanMap(outer, ft.getInnerClass());
+			o = parseIntoBeanMap(session, r, bm).getBean();
+		} else if (ft.isUri() && n.isResource()) {
+			o = ft.newInstanceFromString(outer, session.decodeString(n.asResource().getURI()));
+		} else if (ft.canCreateNewInstanceFromString(outer)) {
+			o = ft.newInstanceFromString(outer, session.decodeString(getValue(session, n, outer)));
+		} else if (ft.canCreateNewInstanceFromNumber(outer)) {
+			o = ft.newInstanceFromNumber(outer, parseNumber(getValue(session, n, outer).toString(), ft.getNewInstanceFromNumberClass()));
+		} else {
+			throw new ParseException("Class ''{0}'' could not be instantiated.  Reason: ''{1}''", ft.getInnerClass().getName(), ft.getNotABeanReason());
+		}
+
+		if (transform != null && o != null)
+			o = transform.normalize(o, nt);
+
+		if (outer != null)
+			setParent(nt, o, outer);
+
+		return (T)o;
+	}
+
+	private boolean isSeq(RdfParserSession session, RDFNode n) {
+		if (n.isResource()) {
+			Statement st = n.asResource().getProperty(session.getTypeProperty());
+			if (st != null)
+				return RDF_SEQ.equals(st.getResource().getURI());
+		}
+		return false;
+	}
+
+	private boolean isBag(RdfParserSession session, RDFNode n) {
+		if (n.isResource()) {
+			Statement st = n.asResource().getProperty(session.getTypeProperty());
+			if (st != null)
+				return RDF_BAG.equals(st.getResource().getURI());
+		}
+		return false;
+	}
+
+	private Object getValue(RdfParserSession session, RDFNode n, Object outer) throws Exception {
+		if (n.isLiteral())
+			return n.asLiteral().getValue();
+		if (n.isResource()) {
+			Statement st = n.asResource().getProperty(session.getValueProperty());
+			if (st != null) {
+				n = st.getObject();
+				if (n.isLiteral())
+					return n.asLiteral().getValue();
+				return parseAnything(session, object(), st.getObject(), outer);
+			}
+		}
+		throw new ParseException(session, "Unknown value type for node ''{0}''", n);
+	}
+
+	private <K,V> Map<K,V> parseIntoMap(RdfParserSession session, Resource r, Map<K,V> m, ClassMeta<K> keyType, ClassMeta<V> valueType) throws Exception {
+		// Add URI as "uri" to generic maps.
+		if (r.getURI() != null) {
+			K uri = convertAttrToType(session, m, "uri", keyType);
+			V value = convertAttrToType(session, m, r.getURI(), valueType);
+			m.put(uri, value);
+		}
+		for (StmtIterator i = r.listProperties(); i.hasNext();) {
+			Statement st = i.next();
+			Property p = st.getPredicate();
+			String key = p.getLocalName();
+			if (! (key.equals("root") && p.getURI().equals(session.getJuneauNsUri()))) {
+				key = session.decodeString(key);
+				RDFNode o = st.getObject();
+				K key2 = convertAttrToType(session, m, key, keyType);
+				V value = parseAnything(session, valueType, o, m);
+				setName(valueType, value, key);
+				m.put(key2, value);
+			}
+
+		}
+		// TODO Auto-generated method stub
+		return m;
+	}
+
+	private <E> Collection<E> parseIntoCollection(RdfParserSession session, Container c, Collection<E> l, ClassMeta<E> et) throws Exception {
+		for (NodeIterator ni = c.iterator(); ni.hasNext();) {
+			E e = parseAnything(session, et, ni.next(), l);
+			l.add(e);
+		}
+		return l;
+	}
+
+	private <E> Collection<E> parseIntoCollection(RdfParserSession session, RDFList list, Collection<E> l, ClassMeta<E> et) throws Exception {
+		for (ExtendedIterator<RDFNode> ni = list.iterator(); ni.hasNext();) {
+			E e = parseAnything(session, et, ni.next(), l);
+			l.add(e);
+		}
+		return l;
+	}
+
+	//--------------------------------------------------------------------------------
+	// Overridden methods
+	//--------------------------------------------------------------------------------
+
+	@Override /* Parser */
+	public RdfParserSession createSession(Object input, ObjectMap op, Method javaMethod, Object outer) {
+		return new RdfParserSession(getContext(RdfParserContext.class), getBeanContext(), input, op, javaMethod, outer);
+	}
+
+	@Override /* CoreApi */
+	public RdfParser setProperty(String property, Object value) throws LockedException {
+		super.setProperty(property, value);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public RdfParser setProperties(ObjectMap properties) throws LockedException {
+		super.setProperties(properties);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public RdfParser addNotBeanClasses(Class<?>...classes) throws LockedException {
+		super.addNotBeanClasses(classes);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public RdfParser addTransforms(Class<?>...classes) throws LockedException {
+		super.addTransforms(classes);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public <T> RdfParser addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) throws LockedException {
+		super.addImplClass(interfaceClass, implClass);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public RdfParser setClassLoader(ClassLoader classLoader) throws LockedException {
+		super.setClassLoader(classLoader);
+		return this;
+	}
+
+	@Override /* Lockable */
+	public RdfParser lock() {
+		super.lock();
+		return this;
+	}
+
+	@Override /* Lockable */
+	public RdfParser clone() {
+		try {
+			RdfParser c = (RdfParser)super.clone();
+			return c;
+		} catch (CloneNotSupportedException e) {
+			throw new RuntimeException(e); // Shouldn't happen
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/jena/RdfParserContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jena/RdfParserContext.java b/juneau-core/src/main/java/org/apache/juneau/jena/RdfParserContext.java
new file mode 100644
index 0000000..417b2ff
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/jena/RdfParserContext.java
@@ -0,0 +1,71 @@
+/***************************************************************************************************************************
+ * 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.juneau.jena;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.xml.*;
+
+/**
+ * Configurable properties on the {@link RdfParser} class.
+ * <p>
+ * Context properties are set by calling {@link ContextFactory#setProperty(String, Object)} on the context factory
+ * returned {@link CoreApi#getContextFactory()}.
+ * <p>
+ * The following convenience methods are also provided for setting context properties:
+ * <ul>
+ * 	<li>{@link RdfParser#setProperty(String,Object)}
+ * 	<li>{@link RdfParser#setProperties(ObjectMap)}
+ * 	<li>{@link RdfParser#addNotBeanClasses(Class[])}
+ * 	<li>{@link RdfParser#addTransforms(Class[])}
+ * 	<li>{@link RdfParser#addImplClass(Class,Class)}
+ * </ul>
+ * <p>
+ * See {@link ContextFactory} for more information about context properties.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class RdfParserContext extends ParserContext implements RdfCommonContext {
+
+	/**
+	 * Trim whitespace from text elements ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 * If <jk>true</jk>, whitespace in text elements will be automatically trimmed.
+	 */
+	public static final String RDF_trimWhitespace = "RdfParser.trimWhitespace";
+
+	final boolean trimWhitespace, looseCollection;
+	final String rdfLanguage;
+	final Namespace juneauNs, juneauBpNs;
+	final RdfCollectionFormat collectionFormat;
+	final Map<String,Object> jenaSettings = new HashMap<String,Object>();
+
+	/**
+	 * Constructor.
+	 * <p>
+	 * Typically only called from {@link ContextFactory#getContext(Class)}.
+	 *
+	 * @param cf The factory that created this context.
+	 */
+	public RdfParserContext(ContextFactory cf) {
+		super(cf);
+		trimWhitespace = cf.getProperty(RDF_trimWhitespace, boolean.class, false);
+		looseCollection = cf.getProperty(RDF_looseCollection, boolean.class, false);
+		rdfLanguage = cf.getProperty(RDF_language, String.class, "RDF/XML-ABBREV");
+		juneauNs = cf.getProperty(RDF_juneauNs, Namespace.class, new Namespace("j", "http://www.ibm.com/juneau/"));
+		juneauBpNs = cf.getProperty(RDF_juneauBpNs, Namespace.class, new Namespace("j", "http://www.ibm.com/juneaubp/"));
+		collectionFormat = cf.getProperty(RDF_collectionFormat, RdfCollectionFormat.class, RdfCollectionFormat.DEFAULT);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/jena/RdfParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jena/RdfParserSession.java b/juneau-core/src/main/java/org/apache/juneau/jena/RdfParserSession.java
new file mode 100644
index 0000000..f61a3b1
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/jena/RdfParserSession.java
@@ -0,0 +1,233 @@
+/***************************************************************************************************************************
+ * 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.juneau.jena;
+
+import static org.apache.juneau.jena.Constants.*;
+import static org.apache.juneau.jena.RdfCommonContext.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.xml.*;
+
+import com.hp.hpl.jena.rdf.model.*;
+
+/**
+ * Session object that lives for the duration of a single use of {@link RdfParser}.
+ * <p>
+ * This class is NOT thread safe.  It is meant to be discarded after one-time use.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public class RdfParserSession extends ParserSession {
+
+	private final String rdfLanguage;
+	private final Namespace juneauNs, juneauBpNs;
+	private final Property pRoot, pValue, pClass, pType;
+	private final Model model;
+	private final boolean trimWhitespace, looseCollection;
+	private final RDFReader rdfReader;
+	private final Set<Resource> urisVisited = new HashSet<Resource>();
+	private final RdfCollectionFormat collectionFormat;
+
+	/**
+	 * Create a new session using properties specified in the context.
+	 *
+	 * @param ctx The context creating this session object.
+	 * 	The context contains all the configuration settings for this object.
+	 * @param beanContext The bean context being used.
+	 * @param input The input.  Can be any of the following types:
+	 * 	<ul>
+	 * 		<li><jk>null</jk>
+	 * 		<li>{@link Reader}
+	 * 		<li>{@link CharSequence}
+	 * 		<li>{@link InputStream} containing UTF-8 encoded text.
+	 * 		<li>{@link File} containing system encoded text.
+	 * 	</ul>
+	 * @param op The override properties.
+	 * 	These override any context properties defined in the context.
+	 * @param javaMethod The java method that called this parser, usually the method in a REST servlet.
+	 * @param outer The outer object for instantiating top-level non-static inner classes.
+	 */
+	protected RdfParserSession(RdfParserContext ctx, BeanContext beanContext, Object input, ObjectMap op, Method javaMethod, Object outer) {
+		super(ctx, beanContext, input, op, javaMethod, outer);
+		ObjectMap jenaSettings = new ObjectMap();
+		jenaSettings.putAll(ctx.jenaSettings);
+		if (op == null || op.isEmpty()) {
+			this.rdfLanguage = ctx.rdfLanguage;
+			this.juneauNs = ctx.juneauNs;
+			this.juneauBpNs = ctx.juneauBpNs;
+			this.trimWhitespace = ctx.trimWhitespace;
+			this.collectionFormat = ctx.collectionFormat;
+			this.looseCollection = ctx.looseCollection;
+		} else {
+			this.rdfLanguage = op.getString(RDF_language, ctx.rdfLanguage);
+			this.juneauNs = (op.containsKey(RDF_juneauNs) ? NamespaceFactory.parseNamespace(op.get(RDF_juneauNs)) : ctx.juneauNs);
+			this.juneauBpNs = (op.containsKey(RDF_juneauBpNs) ? NamespaceFactory.parseNamespace(op.get(RDF_juneauBpNs)) : ctx.juneauBpNs);
+			this.trimWhitespace = op.getBoolean(RdfParserContext.RDF_trimWhitespace, ctx.trimWhitespace);
+			this.collectionFormat = RdfCollectionFormat.valueOf(op.getString(RDF_collectionFormat, "DEFAULT"));
+			this.looseCollection = op.getBoolean(RDF_looseCollection, ctx.looseCollection);
+		}
+		this.model = ModelFactory.createDefaultModel();
+		addModelPrefix(juneauNs);
+		addModelPrefix(juneauBpNs);
+		this.pRoot = model.createProperty(juneauNs.getUri(), RDF_juneauNs_ROOT);
+		this.pValue = model.createProperty(juneauNs.getUri(), RDF_juneauNs_VALUE);
+		this.pClass = model.createProperty(juneauNs.getUri(), RDF_juneauNs_CLASS);
+		this.pType = model.createProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
+		rdfReader = model.getReader(rdfLanguage);
+
+		// Note: NTripleReader throws an exception if you try to set any properties on it.
+		if (! rdfLanguage.equals(LANG_NTRIPLE)) {
+			for (Map.Entry<String,Object> e : jenaSettings.entrySet())
+				rdfReader.setProperty(e.getKey(), e.getValue());
+		}
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this resource was already visited.
+	 *
+	 * @param r The resource to check.
+	 * @return <jk>true</jk> if this resource was already visited.
+	 */
+	public final boolean wasAlreadyProcessed(Resource r) {
+		return ! urisVisited.add(r);
+	}
+
+	/**
+	 * Returns the root property.
+	 *
+	 * @return The root property.
+	 */
+	public final Property getRootProperty() {
+		return pRoot;
+	}
+
+	/**
+	 * Returns the RDF property identifier <js>"value"</js>.
+	 *
+	 * @return The RDF property identifier <js>"value"</js>.
+	 */
+	public final Property getValueProperty() {
+		return pValue;
+	}
+
+	/**
+	 * Returns the RDF property identifier <js>"class"</js>.
+	 *
+	 * @return The RDF property identifier <js>"class"</js>.
+	 */
+	public final Property getClassProperty() {
+		return pClass;
+	}
+
+	/**
+	 * Returns the RDF property identifier <js>"type"</js>.
+	 *
+	 * @return The RDF property identifier <js>"type"</js>.
+	 */
+	public final Property getTypeProperty() {
+		return pType;
+	}
+
+	/**
+	 * Returns the RDF model being parsed into.
+	 *
+	 * @return The RDF model being parsed into.
+	 */
+	public final Model getModel() {
+		return model;
+	}
+
+	/**
+	 * Returns the RDF reader that's reading the model.
+	 *
+	 * @return The RDF reader that's reading the model.
+	 */
+	public final RDFReader getRdfReader() {
+		return rdfReader;
+	}
+
+	/**
+	 * Returns the {@link RdfCommonContext#RDF_collectionFormat} setting value for this session.
+	 *
+	 * @return The {@link RdfCommonContext#RDF_collectionFormat} setting value for this session.
+	 */
+	public final RdfCollectionFormat getCollectionFormat() {
+		return collectionFormat;
+	}
+
+	/**
+	 * Returns the {@link RdfCommonContext#RDF_looseCollection} setting value for this session.
+	 *
+	 * @return The {@link RdfCommonContext#RDF_looseCollection} setting value for this session.
+	 */
+	public final boolean isLooseCollection() {
+		return looseCollection;
+	}
+
+	/**
+	 * Returns the Juneau namespace URI.
+	 *
+	 * @return The Juneau namespace URI.
+	 */
+	public final String getJuneauNsUri() {
+		return juneauNs.getUri();
+	}
+
+	/**
+	 * Adds the specified namespace as a model prefix.
+	 *
+	 * @param ns The XML namespace.
+	 */
+	public final void addModelPrefix(Namespace ns) {
+		model.setNsPrefix(ns.getName(), ns.getUri());
+	}
+
+	/**
+	 * Constructs a <code>Property</code> in the Juneau Bean namespace in this mode.
+	 *
+	 * @param name The property name.
+	 * @return The new property object.
+	 */
+	public final Property getProperty(String name) {
+		return model.createProperty(juneauBpNs.getUri(), name);
+	}
+
+	/**
+	 * Decodes the specified string.
+	 * <p>
+	 * If {@link RdfParserContext#RDF_trimWhitespace} is <jk>true</jk>, the resulting string is trimmed before decoding.
+	 * <p>
+	 * If {@link #isTrimStrings()} is <jk>true</jk>, the resulting string is trimmed after decoding.
+	 *
+	 * @param o The string to trim.
+	 * @return The trimmed string, or <jk>null</jk> if the string was <jk>null</jk>.
+	 */
+	public final String decodeString(Object o) {
+		if (o == null)
+			return null;
+		String s = o.toString();
+		if (s.isEmpty())
+			return s;
+		if (trimWhitespace)
+			s = s.trim();
+		s = XmlUtils.decode(s);
+		if (isTrimStrings())
+			s = s.trim();
+		return s;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializer.java b/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializer.java
new file mode 100644
index 0000000..d5d97ee
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializer.java
@@ -0,0 +1,452 @@
+/***************************************************************************************************************************
+ * 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.juneau.jena;
+
+import static org.apache.juneau.jena.Constants.*;
+import static org.apache.juneau.jena.RdfCommonContext.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.transform.*;
+import org.apache.juneau.xml.*;
+
+import com.hp.hpl.jena.rdf.model.*;
+
+/**
+ * Serializes POJOs to RDF.
+ *
+ *
+ * <h6 class='topic'>Configurable properties</h6>
+ * <p>
+ * 	Refer to <a class='doclink' href='package-summary.html#SerializerConfigurableProperties'>Configurable Properties</a>
+ * 		for the entire list of configurable properties.
+ *
+ *
+ * <h6 class='topic'>Behavior-specific subclasses</h6>
+ * <p>
+ * 	The following direct subclasses are provided for language-specific serializers:
+ * <ul>
+ * 	<li>{@link RdfSerializer.Xml} - RDF/XML.
+ * 	<li>{@link RdfSerializer.XmlAbbrev} - RDF/XML-ABBREV.
+ * 	<li>{@link RdfSerializer.NTriple} - N-TRIPLE.
+ * 	<li>{@link RdfSerializer.Turtle} - TURTLE.
+ * 	<li>{@link RdfSerializer.N3} - N3.
+ * </ul>
+ *
+ *
+ * <h6 class='topic'>Additional Information</h6>
+ * <p>
+ * 	See <a class='doclink' href='package-summary.html#TOC'>RDF Overview</a> for an overview of RDF support in Juneau.
+ *
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@SuppressWarnings({ "rawtypes", "unchecked" })
+@Produces(value="text/xml+rdf+abbrev", contentType="text/xml+rdf")
+public class RdfSerializer extends WriterSerializer {
+
+	/** Default RDF/XML serializer, all default settings.*/
+	public static final RdfSerializer DEFAULT_XML = new RdfSerializer.Xml().lock();
+
+	/** Default Abbreviated RDF/XML serializer, all default settings.*/
+	public static final RdfSerializer DEFAULT_XMLABBREV = new RdfSerializer.XmlAbbrev().lock();
+
+	/** Default Turtle serializer, all default settings.*/
+	public static final RdfSerializer DEFAULT_TURTLE = new RdfSerializer.Turtle().lock();
+
+	/** Default N-Triple serializer, all default settings.*/
+	public static final RdfSerializer DEFAULT_NTRIPLE = new RdfSerializer.NTriple().lock();
+
+	/** Default N3 serializer, all default settings.*/
+	public static final RdfSerializer DEFAULT_N3 = new RdfSerializer.N3().lock();
+
+
+	/** Produces RDF/XML output */
+	@Produces("text/xml+rdf")
+	public static class Xml extends RdfSerializer {
+		/** Constructor */
+		public Xml() {
+			setProperty(RDF_language, LANG_RDF_XML);
+		}
+	}
+
+	/** Produces Abbreviated RDF/XML output */
+	@Produces(value="text/xml+rdf+abbrev", contentType="text/xml+rdf")
+	public static class XmlAbbrev extends RdfSerializer {
+		/** Constructor */
+		public XmlAbbrev() {
+			setProperty(RDF_language, LANG_RDF_XML_ABBREV);
+		}
+	}
+
+	/** Produces N-Triple output */
+	@Produces("text/n-triple")
+	public static class NTriple extends RdfSerializer {
+		/** Constructor */
+		public NTriple() {
+			setProperty(RDF_language, LANG_NTRIPLE);
+		}
+	}
+
+	/** Produces Turtle output */
+	@Produces("text/turtle")
+	public static class Turtle extends RdfSerializer {
+		/** Constructor */
+		public Turtle() {
+			setProperty(RDF_language, LANG_TURTLE);
+		}
+	}
+
+	/** Produces N3 output */
+	@Produces("text/n3")
+	public static class N3 extends RdfSerializer {
+		/** Constructor */
+		public N3() {
+			setProperty(RDF_language, LANG_N3);
+		}
+	}
+
+
+	@Override /* Serializer */
+	protected void doSerialize(SerializerSession session, Object o) throws Exception {
+
+		RdfSerializerSession s = (RdfSerializerSession)session;
+
+		Model model = s.getModel();
+		Resource r = null;
+
+		ClassMeta<?> cm = s.getBeanContext().getClassMetaForObject(o);
+		if (s.isLooseCollection() && cm != null && (cm.isCollection() || cm.isArray())) {
+			Collection c = s.sort(cm.isCollection() ? (Collection)o : toList(cm.getInnerClass(), o));
+			for (Object o2 : c)
+				serializeAnything(s, o2, false, object(), "root", null, null);
+		} else {
+			RDFNode n = serializeAnything(s, o, false, object(), "root", null, null);
+			if (n.isLiteral()) {
+				r = model.createResource();
+				r.addProperty(s.getValueProperty(), n);
+			} else {
+				r = n.asResource();
+			}
+
+			if (s.isAddRootProperty())
+				r.addProperty(s.getRootProperty(), "true");
+		}
+
+		s.getRdfWriter().write(model, session.getWriter(), "http://unknown/");
+	}
+
+	private RDFNode serializeAnything(RdfSerializerSession session, Object o, boolean isURI, ClassMeta<?> eType, String attrName, BeanPropertyMeta bpm, Resource parentResource) throws SerializeException {
+		Model m = session.getModel();
+		BeanContext bc = session.getBeanContext();
+
+		ClassMeta<?> aType = null;       // The actual type
+		ClassMeta<?> wType = null;       // The wrapped type
+		ClassMeta<?> gType = object();   // The generic type
+
+		aType = session.push(attrName, o, eType);
+
+		if (eType == null)
+			eType = object();
+
+		// Handle recursion
+		if (aType == null) {
+			o = null;
+			aType = object();
+		}
+
+		if (o != null) {
+
+			if (aType.isDelegate()) {
+				wType = aType;
+				aType = ((Delegate)o).getClassMeta();
+			}
+
+			gType = aType.getTransformedClassMeta();
+
+			// Transform if necessary
+			PojoTransform transform = aType.getPojoTransform();
+			if (transform != null) {
+				o = transform.transform(o);
+
+				// If the transforms getTransformedClass() method returns Object, we need to figure out
+				// the actual type now.
+				if (gType.isObject())
+					gType = bc.getClassMetaForObject(o);
+			}
+		} else {
+			gType = eType.getTransformedClassMeta();
+		}
+
+		RDFNode n = null;
+
+		if (o == null || gType.isChar() && ((Character)o).charValue() == 0) {
+			if (bpm != null) {
+				if (! session.isTrimNulls()) {
+					n = m.createResource(RDF_NIL);
+				}
+			} else {
+				n = m.createResource(RDF_NIL);
+			}
+
+		} else if (gType.isUri() || isURI) {
+			n = m.createResource(getUri(session, o, null));
+
+		} else if (gType.isCharSequence() || gType.isChar()) {
+			n = m.createLiteral(session.encodeTextInvalidChars(o));
+
+		} else if (gType.isNumber() || gType.isBoolean()) {
+			if (! session.isAddLiteralTypes())
+				n = m.createLiteral(o.toString());
+			else
+				n = m.createTypedLiteral(o);
+
+		} else if (gType.isMap() || (wType != null && wType.isMap())) {
+			if (o instanceof BeanMap) {
+				BeanMap bm = (BeanMap)o;
+				String uri = getUri(session, bm.getBeanUri(), null);
+				n = m.createResource(uri);
+				serializeBeanMap(session, bm, (Resource)n);
+			} else {
+				Map m2 = (Map)o;
+				n = m.createResource();
+				serializeMap(session, m2, (Resource)n, gType);
+			}
+
+		} else if (gType.hasToObjectMapMethod()) {
+			Map m2 = gType.toObjectMap(o);
+			n = m.createResource();
+			serializeMap(session, m2, (Resource)n, gType);
+
+		} else if (gType.isBean()) {
+			BeanMap bm = bc.forBean(o);
+			String uri = getUri(session, bm.getBeanUri(), null);
+			n = m.createResource(uri);
+			serializeBeanMap(session, bm, (Resource)n);
+
+		} else if (gType.isCollection() || gType.isArray() || (wType != null && wType.isCollection())) {
+			Collection c = session.sort(gType.isCollection() ? (Collection)o : toList(gType.getInnerClass(), o));
+			RdfCollectionFormat f = session.getCollectionFormat();
+			if (gType.getRdfMeta().getCollectionFormat() != RdfCollectionFormat.DEFAULT)
+				f = gType.getRdfMeta().getCollectionFormat();
+			if (bpm != null && bpm.getRdfMeta().getCollectionFormat() != RdfCollectionFormat.DEFAULT)
+				f = bpm.getRdfMeta().getCollectionFormat();
+			switch (f) {
+				case BAG: n = serializeToContainer(session, c, gType, m.createBag()); break;
+				case LIST: n = serializeToList(session, c, gType); break;
+				case MULTI_VALUED: serializeToMultiProperties(session, c, gType, bpm, attrName, parentResource); break;
+				default: n = serializeToContainer(session, c, gType, m.createSeq());
+			}
+		} else {
+			n = m.createLiteral(session.encodeTextInvalidChars(session.toString(o)));
+		}
+
+		if (session.isAddClassAttrs() && n != null && n.isResource()) {
+			if (o != null && ! eType.equals(aType))
+				n.asResource().addProperty(session.getClassProperty(), aType.toString());
+			else if (o == null)
+				n.asResource().addProperty(session.getClassProperty(), eType.toString());
+		}
+
+		session.pop();
+
+		return n;
+	}
+
+	private String getUri(RdfSerializerSession session, Object uri, Object uri2) {
+		String s = null;
+		if (uri != null)
+			s = uri.toString();
+		if ((s == null || s.isEmpty()) && uri2 != null)
+			s = uri2.toString();
+		if (s == null)
+			return null;
+		if (s.indexOf("://") == -1) {
+			String aUri = session.getAbsolutePathUriBase();
+			String rUri = session.getRelativeUriBase();
+			if (StringUtils.startsWith(s, '/')) {
+				if (aUri != null)
+					return aUri + s;
+			} else {
+				if (rUri != null) {
+					if (rUri.equals("/"))
+						return '/' + s;
+					return rUri + '/' + s;
+				}
+			}
+		}
+		return s;
+	}
+
+	private void serializeMap(RdfSerializerSession session, Map m, Resource r, ClassMeta<?> type) throws SerializeException {
+
+		m = session.sort(m);
+
+		ClassMeta<?> keyType = type.getKeyType(), valueType = type.getValueType();
+
+		ArrayList<Map.Entry<Object,Object>> l = new ArrayList<Map.Entry<Object,Object>>(m.entrySet());
+		Collections.reverse(l);
+		for (Map.Entry<Object,Object> me : l) {
+			Object value = me.getValue();
+
+			Object key = session.generalize(me.getKey(), keyType);
+
+			Namespace ns = session.getJuneauBpNs();
+			Model model = session.getModel();
+			Property p = model.createProperty(ns.getUri(), session.encodeElementName(session.toString(key)));
+			RDFNode n = serializeAnything(session, value, false, valueType, key == null ? null : session.toString(key), null, r);
+			if (n != null)
+				r.addProperty(p, n);
+		}
+	}
+
+	private void serializeBeanMap(RdfSerializerSession session, BeanMap<?> m, Resource r) throws SerializeException {
+		List<BeanPropertyValue> l = m.getValues(false, session.isTrimNulls());
+		Collections.reverse(l);
+		for (BeanPropertyValue bpv : l) {
+			BeanPropertyMeta pMeta = bpv.getMeta();
+			ClassMeta<?> cm = pMeta.getClassMeta();
+
+			if (pMeta.isBeanUri())
+				continue;
+
+			String key = bpv.getName();
+			Object value = bpv.getValue();
+			Throwable t = bpv.getThrown();
+			if (t != null)
+				session.addBeanGetterWarning(pMeta, t);
+
+			if (session.canIgnoreValue(cm, key, value))
+				continue;
+
+			BeanPropertyMeta bpm = bpv.getMeta();
+			Namespace ns = bpm.getRdfMeta().getNamespace();
+			if (ns == null && session.isUseXmlNamespaces())
+				ns = bpm.getXmlMeta().getNamespace();
+			if (ns == null)
+				ns = session.getJuneauBpNs();
+			else if (session.isAutoDetectNamespaces())
+				session.addModelPrefix(ns);
+
+			Property p = session.getModel().createProperty(ns.getUri(), session.encodeElementName(key));
+			RDFNode n = serializeAnything(session, value, pMeta.isUri(), cm, key, pMeta, r);
+			if (n != null)
+				r.addProperty(p, n);
+		}
+	}
+
+
+	private Container serializeToContainer(RdfSerializerSession session, Collection c, ClassMeta<?> type, Container list) throws SerializeException {
+
+		ClassMeta<?> elementType = type.getElementType();
+		for (Object e : c) {
+			RDFNode n = serializeAnything(session, e, false, elementType, null, null, null);
+			list = list.add(n);
+		}
+		return list;
+	}
+
+	private RDFList serializeToList(RdfSerializerSession session, Collection c, ClassMeta<?> type) throws SerializeException {
+		ClassMeta<?> elementType = type.getElementType();
+		List<RDFNode> l = new ArrayList<RDFNode>(c.size());
+		for (Object e : c) {
+			l.add(serializeAnything(session, e, false, elementType, null, null, null));
+		}
+		return session.getModel().createList(l.iterator());
+	}
+
+	private void serializeToMultiProperties(RdfSerializerSession session, Collection c, ClassMeta<?> gType, BeanPropertyMeta bpm, String attrName, Resource parentResource) throws SerializeException {
+		ClassMeta<?> elementType = gType.getElementType();
+		for (Object e : c) {
+			Namespace ns = null;
+			if (bpm != null) {
+				ns = bpm.getRdfMeta().getNamespace();
+				if (ns == null && session.isUseXmlNamespaces())
+					ns = bpm.getXmlMeta().getNamespace();
+			}
+			if (ns == null)
+				ns = session.getJuneauBpNs();
+			else if (session.isAutoDetectNamespaces())
+				session.addModelPrefix(ns);
+			RDFNode n2 = serializeAnything(session, e, false, elementType, null, null, null);
+			Property p = session.getModel().createProperty(ns.getUri(), session.encodeElementName(attrName));
+			parentResource.addProperty(p, n2);
+		}
+
+	}
+
+	//--------------------------------------------------------------------------------
+	// Overridden methods
+	//--------------------------------------------------------------------------------
+
+	@Override /* Serializer */
+	public RdfSerializerSession createSession(Object output, ObjectMap properties, Method javaMethod) {
+		return new RdfSerializerSession(getContext(RdfSerializerContext.class), getBeanContext(), output, properties, javaMethod);
+	}
+
+	@Override /* CoreApi */
+	public RdfSerializer setProperty(String property, Object value) throws LockedException {
+		super.setProperty(property, value);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public RdfSerializer setProperties(ObjectMap properties) throws LockedException {
+		super.setProperties(properties);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public RdfSerializer addNotBeanClasses(Class<?>...classes) throws LockedException {
+		super.addNotBeanClasses(classes);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public RdfSerializer addTransforms(Class<?>...classes) throws LockedException {
+		super.addTransforms(classes);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public <T> RdfSerializer addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) throws LockedException {
+		super.addImplClass(interfaceClass, implClass);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public RdfSerializer setClassLoader(ClassLoader classLoader) throws LockedException {
+		super.setClassLoader(classLoader);
+		return this;
+	}
+
+	@Override /* Lockable */
+	public RdfSerializer lock() {
+		super.lock();
+		return this;
+	}
+
+	@Override /* Lockable */
+	public RdfSerializer clone() {
+		try {
+			return (RdfSerializer)super.clone();
+		} catch (CloneNotSupportedException e) {
+			throw new RuntimeException(e); // Shouldn't happen
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializerContext.java
new file mode 100644
index 0000000..8ed8ba4
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializerContext.java
@@ -0,0 +1,107 @@
+/***************************************************************************************************************************
+ * 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.juneau.jena;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.xml.*;
+
+/**
+ * Configurable properties on the {@link RdfSerializer} class.
+ * <p>
+ * Context properties are set by calling {@link ContextFactory#setProperty(String, Object)} on the context factory
+ * returned {@link CoreApi#getContextFactory()}.
+ * <p>
+ * The following convenience methods are also provided for setting context properties:
+ * <ul>
+ * 	<li>{@link RdfSerializer#setProperty(String,Object)}
+ * 	<li>{@link RdfSerializer#setProperties(ObjectMap)}
+ * 	<li>{@link RdfSerializer#addNotBeanClasses(Class[])}
+ * 	<li>{@link RdfSerializer#addTransforms(Class[])}
+ * 	<li>{@link RdfSerializer#addImplClass(Class,Class)}
+ * </ul>
+ * <p>
+ * See {@link ContextFactory} for more information about context properties.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class RdfSerializerContext extends SerializerContext implements RdfCommonContext {
+
+	/**
+	 * Add XSI data types to non-<code>String</code> literals ({@link Boolean}, default=<jk>false</jk>).
+	 */
+	public static final String RDF_addLiteralTypes = "RdfSerializer.addLiteralTypes";
+
+	/**
+	 * Add RDF root identifier property to root node ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 * When enabled an RDF property <code>http://www.ibm.com/juneau/root</code> is added with a value of <js>"true"</js>
+	 * 	to identify the root node in the graph.
+	 * This helps locate the root node during parsing.
+	 * <p>
+	 * If disabled, the parser has to search through the model to find any resources without
+	 * 	incoming predicates to identify root notes, which can introduce a considerable performance
+	 * 	degradation.
+	 */
+	public static final String RDF_addRootProperty = "RdfSerializer.addRootProperty";
+
+	/**
+	 * Auto-detect namespace usage ({@link Boolean}, default=<jk>true</jk>).
+	 * <p>
+	 * Detect namespace usage before serialization.
+	 * <p>
+	 * If enabled, then the data structure will first be crawled looking for
+	 * namespaces that will be encountered before the root element is
+	 * serialized.
+	 */
+	public static final String RDF_autoDetectNamespaces = "RdfSerializer.autoDetectNamespaces";
+
+	/**
+	 * Default namespaces (<code>List&lt;Namespace&gt;</code>, default=<code>Namespace[0]</code>).
+	 * <p>
+	 * The default list of namespaces associated with this serializer.
+	 */
+	public static final String RDF_namespaces = "RdfSerializer.namespaces.list";
+
+
+	final boolean addLiteralTypes, addRootProperty, useXmlNamespaces, looseCollection, autoDetectNamespaces;
+	final String rdfLanguage;
+	final Namespace juneauNs;
+	final Namespace juneauBpNs;
+	final RdfCollectionFormat collectionFormat;
+	final Map<String,Object> jenaSettings = new HashMap<String,Object>();
+	final Namespace[] namespaces;
+
+	/**
+	 * Constructor.
+	 * <p>
+	 * Typically only called from {@link ContextFactory#getContext(Class)}.
+	 *
+	 * @param cf The factory that created this context.
+	 */
+	public RdfSerializerContext(ContextFactory cf) {
+		super(cf);
+		addLiteralTypes = cf.getProperty(RDF_addLiteralTypes, boolean.class, false);
+		addRootProperty = cf.getProperty(RDF_addRootProperty, boolean.class, false);
+		useXmlNamespaces = cf.getProperty(RDF_useXmlNamespaces, boolean.class, true);
+		looseCollection = cf.getProperty(RDF_looseCollection, boolean.class, false);
+		autoDetectNamespaces = cf.getProperty(RDF_autoDetectNamespaces, boolean.class, true);
+		rdfLanguage = cf.getProperty(RDF_language, String.class, "RDF/XML-ABBREV");
+		juneauNs = cf.getProperty(RDF_juneauNs, Namespace.class, new Namespace("j", "http://www.ibm.com/juneau/"));
+		juneauBpNs = cf.getProperty(RDF_juneauBpNs, Namespace.class, new Namespace("jp", "http://www.ibm.com/juneaubp/"));
+		collectionFormat = cf.getProperty(RDF_collectionFormat, RdfCollectionFormat.class, RdfCollectionFormat.DEFAULT);
+		namespaces = cf.getProperty(RDF_namespaces, Namespace[].class, new Namespace[0]);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
new file mode 100644
index 0000000..b4a852d
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
@@ -0,0 +1,270 @@
+/***************************************************************************************************************************
+ * 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.juneau.jena;
+
+import static org.apache.juneau.jena.Constants.*;
+import static org.apache.juneau.jena.RdfCommonContext.*;
+import static org.apache.juneau.jena.RdfSerializerContext.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.xml.*;
+
+import com.hp.hpl.jena.rdf.model.*;
+
+/**
+ * Session object that lives for the duration of a single use of {@link RdfSerializer}.
+ * <p>
+ * This class is NOT thread safe.  It is meant to be discarded after one-time use.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public final class RdfSerializerSession extends SerializerSession {
+
+	private final String rdfLanguage;
+	private final Namespace juneauNs, juneauBpNs;
+	private final boolean addLiteralTypes, addRootProperty, useXmlNamespaces, looseCollection, autoDetectNamespaces;
+	private final Property pRoot, pValue, pClass;
+	private final Model model;
+	private final RDFWriter writer;
+	private final RdfCollectionFormat collectionFormat;
+	private final Namespace[] namespaces;
+
+	/**
+	 * Create a new session using properties specified in the context.
+	 *
+	 * @param ctx The context creating this session object.
+	 * 	The context contains all the configuration settings for this object.
+	 * @param beanContext The bean context being used.
+	 * @param output The output object.  See {@link JsonSerializerSession#getWriter()} for valid class types.
+	 * @param op The override properties.
+	 * 	These override any context properties defined in the context.
+	 * @param javaMethod The java method that called this parser, usually the method in a REST servlet.
+	 */
+	protected RdfSerializerSession(RdfSerializerContext ctx, BeanContext beanContext, Object output, ObjectMap op, Method javaMethod) {
+		super(ctx, beanContext, output, op, javaMethod);
+		ObjectMap jenaSettings = new ObjectMap();
+		jenaSettings.put("rdfXml.tab", isUseIndentation() ? 2 : 0);
+		jenaSettings.put("rdfXml.attributeQuoteChar", Character.toString(getQuoteChar()));
+		jenaSettings.putAll(ctx.jenaSettings);
+		if (op == null || op.isEmpty()) {
+			this.rdfLanguage = ctx.rdfLanguage;
+			this.juneauNs = ctx.juneauNs;
+			this.juneauBpNs = ctx.juneauBpNs;
+			this.addLiteralTypes = ctx.addLiteralTypes;
+			this.addRootProperty = ctx.addRootProperty;
+			this.collectionFormat = ctx.collectionFormat;
+			this.looseCollection = ctx.looseCollection;
+			this.useXmlNamespaces = ctx.useXmlNamespaces;
+			this.autoDetectNamespaces = ctx.autoDetectNamespaces;
+			this.namespaces = ctx.namespaces;
+		} else {
+			this.rdfLanguage = op.getString(RDF_language, ctx.rdfLanguage);
+			this.juneauNs = (op.containsKey(RDF_juneauNs) ? NamespaceFactory.parseNamespace(op.get(RDF_juneauNs)) : ctx.juneauNs);
+			this.juneauBpNs = (op.containsKey(RDF_juneauBpNs) ? NamespaceFactory.parseNamespace(op.get(RDF_juneauBpNs)) : ctx.juneauBpNs);
+			this.addLiteralTypes = op.getBoolean(RDF_addLiteralTypes, ctx.addLiteralTypes);
+			this.addRootProperty = op.getBoolean(RDF_addRootProperty, ctx.addRootProperty);
+			for (Map.Entry<String,Object> e : op.entrySet()) {
+				String key = e.getKey();
+				if (key.startsWith("Rdf.jena."))
+					jenaSettings.put(key.substring(9), e.getValue());
+			}
+			this.collectionFormat = RdfCollectionFormat.valueOf(op.getString(RDF_collectionFormat, "DEFAULT"));
+			this.looseCollection = op.getBoolean(RDF_looseCollection, ctx.looseCollection);
+			this.useXmlNamespaces = op.getBoolean(RDF_useXmlNamespaces, ctx.useXmlNamespaces);
+			this.autoDetectNamespaces = op.getBoolean(RDF_autoDetectNamespaces, ctx.autoDetectNamespaces);
+			this.namespaces = op.get(Namespace[].class, RDF_namespaces, ctx.namespaces);
+		}
+		this.model = ModelFactory.createDefaultModel();
+		addModelPrefix(juneauNs);
+		addModelPrefix(juneauBpNs);
+		for (Namespace ns : this.namespaces)
+			addModelPrefix(ns);
+		this.pRoot = model.createProperty(juneauNs.getUri(), RDF_juneauNs_ROOT);
+		this.pValue = model.createProperty(juneauNs.getUri(), RDF_juneauNs_VALUE);
+		this.pClass = model.createProperty(juneauNs.getUri(), RDF_juneauNs_CLASS);
+		writer = model.getWriter(rdfLanguage);
+
+		// Only apply properties with this prefix!
+		String propPrefix = RdfCommonContext.LANG_PROP_MAP.get(rdfLanguage);
+		if (propPrefix == null)
+			throw new RuntimeException("Unknown RDF language encountered: '"+rdfLanguage+"'");
+
+		for (Map.Entry<String,Object> e : jenaSettings.entrySet())
+			if (e.getKey().startsWith(propPrefix))
+				writer.setProperty(e.getKey().substring(propPrefix.length()), e.getValue());
+	}
+
+	/**
+	 * Adds the specified namespace as a model prefix.
+	 *
+	 * @param ns The XML namespace.
+	 */
+	public void addModelPrefix(Namespace ns) {
+		model.setNsPrefix(ns.getName(), ns.getUri());
+	}
+
+	/**
+	 * Returns the {@link RdfCommonContext#RDF_collectionFormat} setting value for this session.
+	 *
+	 * @return The {@link RdfCommonContext#RDF_collectionFormat} setting value for this session.
+	 */
+	public final RdfCollectionFormat getCollectionFormat() {
+		return collectionFormat;
+	}
+
+	/**
+	 * Returns the {@link RdfCommonContext#RDF_useXmlNamespaces} setting value for this session.
+	 *
+	 * @return The {@link RdfCommonContext#RDF_useXmlNamespaces} setting value for this session.
+	 */
+	public final boolean isUseXmlNamespaces() {
+		return useXmlNamespaces;
+	}
+
+	/**
+	 * Returns the {@link RdfCommonContext#RDF_looseCollection} setting value for this session.
+	 *
+	 * @return The {@link RdfCommonContext#RDF_looseCollection} setting value for this session.
+	 */
+	public final boolean isLooseCollection() {
+		return looseCollection;
+	}
+
+	/**
+	 * Returns the {@link RdfCommonContext#RDF_language} setting value for this session.
+	 *
+	 * @return The {@link RdfCommonContext#RDF_language} setting value for this session.
+	 */
+	public final String getRdfLanguage() {
+		return rdfLanguage;
+	}
+
+	/**
+	 * Returns the {@link RdfCommonContext#RDF_juneauNs} setting value for this session.
+	 *
+	 * @return The {@link RdfCommonContext#RDF_juneauNs} setting value for this session.
+	 */
+	public final Namespace getJuneauNs() {
+		return juneauNs;
+	}
+
+	/**
+	 * Returns the {@link RdfCommonContext#RDF_juneauBpNs} setting value for this session.
+	 *
+	 * @return The {@link RdfCommonContext#RDF_juneauBpNs} setting value for this session.
+	 */
+	public final Namespace getJuneauBpNs() {
+		return juneauBpNs;
+	}
+
+	/**
+	 * Returns the {@link RdfSerializerContext#RDF_addLiteralTypes} setting value for this session.
+	 *
+	 * @return The {@link RdfSerializerContext#RDF_addLiteralTypes} setting value for this session.
+	 */
+	public final boolean isAddLiteralTypes() {
+		return addLiteralTypes;
+	}
+
+	/**
+	 * Returns the {@link RdfSerializerContext#RDF_addRootProperty} setting value for this session.
+	 *
+	 * @return The {@link RdfSerializerContext#RDF_addRootProperty} setting value for this session.
+	 */
+	public final boolean isAddRootProperty() {
+		return addRootProperty;
+	}
+
+	/**
+	 * Returns the {@link RdfSerializerContext#RDF_autoDetectNamespaces} setting value for this session.
+	 *
+	 * @return The {@link RdfSerializerContext#RDF_autoDetectNamespaces} setting value for this session.
+	 */
+	public final boolean isAutoDetectNamespaces() {
+		return autoDetectNamespaces;
+	}
+
+	/**
+	 * Returns the RDF property that identifies the root node in the RDF model.
+	 *
+	 * @return The RDF property that identifies the root node in the RDF model.
+	 */
+	public final Property getRootProperty() {
+		return pRoot;
+	}
+
+	/**
+	 * Returns the RDF property that represents a value in the RDF model.
+	 *
+	 * @return The RDF property that represents a value in the RDF model.
+	 */
+	public final Property getValueProperty() {
+		return pValue;
+	}
+
+	/**
+	 * Returns the RDF property that represents a class in the RDF model.
+	 *
+	 * @return The RDF property that represents a class in the RDF model.
+	 */
+	public final Property getClassProperty() {
+		return pClass;
+	}
+
+	/**
+	 * Returns the RDF model being serialized.
+	 *
+	 * @return The RDF model being serialized.
+	 */
+	public final Model getModel() {
+		return model;
+	}
+
+	/**
+	 * Returns the RDF writer that's being serialized to.
+	 *
+	 * @return The RDF writer that's being serialized to.
+	 */
+	public final RDFWriter getRdfWriter() {
+		return writer;
+	}
+
+	/**
+	 * XML-encodes the specified string using the {@link XmlUtils#encodeTextInvalidChars(Object)} method.
+	 *
+	 * @param o The string being encoded.
+	 * @return The encoded string, or <jk>null</jk> if the input was <jk>null</jk>.
+	 */
+	public final String encodeTextInvalidChars(Object o) {
+		if (o == null)
+			return null;
+		String s = toString(o);
+		return XmlUtils.encodeTextInvalidChars(s);
+	}
+
+	/**
+	 * XML-encoded the specified element name using the {@link XmlUtils#encodeElementName(Object)} method.
+	 *
+	 * @param o The string being encoded.
+	 * @return The encoded string.
+	 */
+	public final String encodeElementName(Object o) {
+		String s = toString(o);
+		return XmlUtils.encodeElementName(s);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/jena/RdfUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jena/RdfUtils.java b/juneau-core/src/main/java/org/apache/juneau/jena/RdfUtils.java
new file mode 100644
index 0000000..fd9dcb1
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/jena/RdfUtils.java
@@ -0,0 +1,91 @@
+/***************************************************************************************************************************
+ * 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.juneau.jena;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.jena.annotation.*;
+import org.apache.juneau.xml.*;
+
+/**
+ * Utility classes.
+ */
+public class RdfUtils {
+
+	/**
+	 * Find the namespace given a list of <ja>@Rdf</ja> and <ja>@RdfSchema</ja> annotations.
+	 * The annotations should be a child-to-parent ordering of annotations found on
+	 * 	a class or method.
+	 *
+	 * @param rdfs The <code>@Rdf</code> annotations to search.
+	 * @param schemas The list of known RDF schemas.
+	 * @return The resolved namespace, or <jk>null</jk> if the namespace could not be resolved.
+	 */
+	public static Namespace findNamespace(List<Rdf> rdfs, List<RdfSchema> schemas) {
+
+		for (Rdf rdf : rdfs) {
+			Namespace ns = findNamespace(rdf.prefix(), rdf.namespace(), rdfs, schemas);
+			if (ns != null)
+				return ns;
+		}
+
+		for (RdfSchema schema : schemas) {
+			Namespace ns = findNamespace(schema.prefix(), schema.namespace(), null, schemas);
+			if (ns != null)
+				return ns;
+		}
+
+		return null;
+	}
+
+	private static Namespace findNamespace(String prefix, String ns, List<Rdf> rdfs, List<RdfSchema> schemas) {
+
+		// If both prefix and namespace specified, use that Namespace mapping.
+		if (! (prefix.isEmpty() || ns.isEmpty()))
+			return NamespaceFactory.get(prefix, ns);
+
+		// If only prefix specified, need to search for namespaceURI.
+		if (! prefix.isEmpty()) {
+			if (rdfs != null)
+				for (Rdf rdf2 : rdfs)
+					if (rdf2.prefix().equals(prefix) && ! rdf2.namespace().isEmpty())
+						return NamespaceFactory.get(prefix, rdf2.namespace());
+			for (RdfSchema schema : schemas) {
+				if (schema.prefix().equals(prefix) && ! schema.namespace().isEmpty())
+					return NamespaceFactory.get(prefix, schema.namespace());
+				for (RdfNs rdfNs : schema.rdfNs())
+					if (rdfNs.prefix().equals(prefix))
+						return NamespaceFactory.get(prefix, rdfNs.namespaceURI());
+			}
+			throw new BeanRuntimeException("Found @Rdf.prefix annotation with no matching URI.  prefix='"+prefix+"'");
+		}
+
+		// If only namespaceURI specified, need to search for prefix.
+		if (! ns.isEmpty()) {
+			if (rdfs != null)
+				for (Rdf rdf2 : rdfs)
+					if (rdf2.namespace().equals(ns) && ! rdf2.prefix().isEmpty())
+						return NamespaceFactory.get(rdf2.prefix(), ns);
+			for (RdfSchema schema : schemas) {
+				if (schema.namespace().equals(ns) && ! schema.prefix().isEmpty())
+					return NamespaceFactory.get(schema.prefix(), ns);
+				for (RdfNs rdfNs : schema.rdfNs())
+					if (rdfNs.namespaceURI().equals(ns))
+						return NamespaceFactory.get(rdfNs.prefix(), ns);
+			}
+		}
+
+		return null;
+	}
+}


Mime
View raw message