001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.jena; 014 015import static org.apache.juneau.internal.CollectionUtils.*; 016 017import java.util.*; 018 019import org.apache.juneau.*; 020import org.apache.juneau.annotation.*; 021import org.apache.juneau.parser.*; 022import org.apache.juneau.xml.*; 023 024/** 025 * Parses RDF into POJOs. 026 * 027 * <h5 class='topic'>Behavior-specific subclasses</h5> 028 * 029 * The following direct subclasses are provided for language-specific parsers: 030 * <ul class='spaced-list'> 031 * <li> 032 * {@link RdfXmlParser} - RDF/XML and RDF/XML-ABBREV. 033 * <li> 034 * {@link NTripleParser} - N-TRIPLE. 035 * <li> 036 * {@link TurtleParser} - TURTLE. 037 * <li> 038 * {@link N3Parser} - N3. 039 * </ul> 040 * 041 * <ul class='seealso'> 042 * <li class='link'>{@doc juneau-marshall-rdf} 043 * </ul> 044 */ 045@ConfigurableContext(prefixes={RdfCommon.PREFIX,RdfParser.PREFIX}) 046public class RdfParser extends ReaderParser implements RdfCommon { 047 048 private static final Namespace 049 DEFAULT_JUNEAU_NS = Namespace.create("j", "http://www.apache.org/juneau/"), 050 DEFAULT_JUNEAUBP_NS = Namespace.create("jp", "http://www.apache.org/juneaubp/"); 051 052 //------------------------------------------------------------------------------------------------------------------- 053 // Configurable properties 054 //------------------------------------------------------------------------------------------------------------------- 055 056 static final String PREFIX = "RdfParser"; 057 058 /** 059 * Configuration property: Trim whitespace from text elements. 060 * 061 * <h5 class='section'>Property:</h5> 062 * <ul> 063 * <li><b>Name:</b> <js>"RdfParser.trimWhitespace.b"</js> 064 * <li><b>Data type:</b> <c>Boolean</c> 065 * <li><b>Default:</b> <jk>false</jk> 066 * <li><b>Session property:</b> <jk>false</jk> 067 * <li><b>Methods:</b> 068 * <ul> 069 * <li class='jm'>{@link RdfParserBuilder#trimWhitespace(boolean)} 070 * <li class='jm'>{@link RdfParserBuilder#trimWhitespace()} 071 * </ul> 072 * </ul> 073 * 074 * <h5 class='section'>Description:</h5> 075 * <p> 076 * If <jk>true</jk>, whitespace in text elements will be automatically trimmed. 077 * 078 * <h5 class='section'>Example:</h5> 079 * <p class='bcode w800'> 080 * <jc>// Create an RDF parser that trims whitespace.</jc> 081 * ReaderParser p = RdfParser 082 * .<jsm>create</jsm>() 083 * .xml() 084 * .trimWhitespace() 085 * .build(); 086 * 087 * <jc>// Same, but use property.</jc> 088 * ReaderParser p = RdfParser 089 * .<jsm>create</jsm>() 090 * .xml() 091 * .set(<jsf>RDF_trimWhitespace</jsf>, <jk>true</jk>) 092 * .build(); 093 * </p> 094 */ 095 public static final String RDF_trimWhitespace = PREFIX + ".trimWhitespace.b"; 096 097 //------------------------------------------------------------------------------------------------------------------- 098 // Instance 099 //------------------------------------------------------------------------------------------------------------------- 100 101 private final boolean trimWhitespace, looseCollections; 102 private final String rdfLanguage; 103 private final Namespace juneauNs, juneauBpNs; 104 private final RdfCollectionFormat collectionFormat; 105 106 final Map<String,Object> jenaProperties; 107 108 /** 109 * Constructor. 110 * 111 * @param ps The property store containing all the settings for this object. 112 * @param consumes The list of media types that this parser consumes (e.g. <js>"application/json"</js>). 113 */ 114 public RdfParser(PropertyStore ps, String...consumes) { 115 super(ps, consumes); 116 trimWhitespace = getBooleanProperty(RDF_trimWhitespace, false); 117 looseCollections = getBooleanProperty(RDF_looseCollections, false); 118 rdfLanguage = getStringProperty(RDF_language, "RDF/XML-ABBREV"); 119 juneauNs = getInstanceProperty(RDF_juneauNs, Namespace.class, DEFAULT_JUNEAU_NS); 120 juneauBpNs = getInstanceProperty(RDF_juneauBpNs, Namespace.class, DEFAULT_JUNEAUBP_NS); 121 collectionFormat = getProperty(RDF_collectionFormat, RdfCollectionFormat.class, RdfCollectionFormat.DEFAULT); 122 123 Map<String,Object> m = new TreeMap<>(); 124 for (String k : getPropertyKeys("RdfCommon")) 125 if (k.startsWith("jena.")) 126 m.put(k.substring(5), getProperty("RdfCommon." + k)); 127 jenaProperties = unmodifiableMap(m); 128 } 129 130 /** 131 * Constructor. 132 * 133 * @param ps The property store containing all the settings for this object. 134 */ 135 public RdfParser(PropertyStore ps) { 136 this(ps, "text/xml+rdf"); 137 } 138 139 @Override /* Context */ 140 public RdfParserBuilder builder() { 141 return new RdfParserBuilder(getPropertyStore()); 142 } 143 144 /** 145 * Instantiates a new clean-slate {@link RdfParserBuilder} object. 146 * 147 * <p> 148 * This is equivalent to simply calling <code><jk>new</jk> RdfParserBuilder()</code>. 149 * 150 * <p> 151 * Note that this method creates a builder initialized to all default settings, whereas {@link #builder()} copies 152 * the settings of the object called on. 153 * 154 * @return A new {@link RdfParserBuilder} object. 155 */ 156 public static RdfParserBuilder create() { 157 return new RdfParserBuilder(); 158 } 159 160 @Override /* Parser */ 161 public RdfParserSession createSession() { 162 return createSession(createDefaultSessionArgs()); 163 } 164 165 @Override /* Parser */ 166 public RdfParserSession createSession(ParserSessionArgs args) { 167 return new RdfParserSession(this, args); 168 } 169 170 //----------------------------------------------------------------------------------------------------------------- 171 // Common properties 172 //----------------------------------------------------------------------------------------------------------------- 173 174 /** 175 * Configuration property: RDF format for representing collections and arrays. 176 * 177 * @see #RDF_collectionFormat 178 * @return 179 * RDF format for representing collections and arrays. 180 */ 181 protected final RdfCollectionFormat getCollectionFormat() { 182 return collectionFormat; 183 } 184 185 /** 186 * Configuration property: Default XML namespace for bean properties. 187 * 188 * @see #RDF_juneauBpNs 189 * @return 190 * Default XML namespace for bean properties. 191 */ 192 protected final Namespace getJuneauBpNs() { 193 return juneauBpNs; 194 } 195 196 /** 197 * Configuration property: XML namespace for Juneau properties. 198 * 199 * @see #RDF_juneauNs 200 * @return 201 * XML namespace for Juneau properties. 202 */ 203 protected final Namespace getJuneauNs() { 204 return juneauNs; 205 } 206 207 /** 208 * Configuration property: RDF language. 209 * 210 * @see #RDF_language 211 * @return 212 * The RDF language to use. 213 */ 214 protected final String getLanguage() { 215 return rdfLanguage; 216 } 217 218 /** 219 * Configuration property: Collections should be serialized and parsed as loose collections. 220 * 221 * @see #RDF_looseCollections 222 * @return 223 * <jk>true</jk> if collections of resources are handled as loose collections of resources in RDF instead of 224 * resources that are children of an RDF collection (e.g. Sequence, Bag). 225 */ 226 protected final boolean isLooseCollections() { 227 return looseCollections; 228 } 229 230 //----------------------------------------------------------------------------------------------------------------- 231 // Jena properties 232 //----------------------------------------------------------------------------------------------------------------- 233 234 /** 235 * Configuration property: All Jena-related configuration properties. 236 * 237 * @return 238 * A map of all Jena-related configuration properties. 239 */ 240 protected final Map<String,Object> getJenaProperties() { 241 return jenaProperties; 242 } 243 244 //----------------------------------------------------------------------------------------------------------------- 245 // Properties 246 //----------------------------------------------------------------------------------------------------------------- 247 248 /** 249 * Configuration property: Trim whitespace from text elements. 250 * 251 * @see #RDF_trimWhitespace 252 * @return 253 * <jk>true</jk> if whitespace in text elements will be automatically trimmed. 254 */ 255 protected final boolean isTrimWhitespace() { 256 return trimWhitespace; 257 } 258 259 //----------------------------------------------------------------------------------------------------------------- 260 // Other methods 261 //----------------------------------------------------------------------------------------------------------------- 262 263 @Override /* Context */ 264 public ObjectMap toMap() { 265 return super.toMap() 266 .append("RdfParser", new DefaultFilteringObjectMap() 267 .append("trimWhitespace", trimWhitespace) 268 .append("looseCollections", looseCollections) 269 .append("rdfLanguage", rdfLanguage) 270 .append("juneauNs", juneauNs) 271 .append("juneauBpNs", juneauBpNs) 272 .append("collectionFormat", collectionFormat) 273 ); 274 } 275}