KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > n3 > N3JenaWriterCommon


1 /*
2  * (c) Copyright 2001, 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
3  * [See end of file]
4  */

5
6 package com.hp.hpl.jena.n3;
7
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10
11 import com.hp.hpl.jena.util.iterator.* ;
12 import com.hp.hpl.jena.rdf.model.*;
13 import com.hp.hpl.jena.shared.JenaException;
14 import com.hp.hpl.jena.vocabulary.OWL ;
15 import com.hp.hpl.jena.vocabulary.XSD ;
16 import com.hp.hpl.jena.vocabulary.RDF ;
17
18 import java.util.* ;
19 import java.io.* ;
20 import java.text.* ;
21
22 /** Common framework for implementing N3 writers.
23  *
24  * @author Andy Seaborne
25  * @version $Id: N3JenaWriterCommon.java,v 1.30 2005/02/21 12:04:04 andy_seaborne Exp $
26  */

27
28 public class N3JenaWriterCommon implements RDFWriter
29 {
30     static Log logger = LogFactory.getLog(N3JenaWriterCommon.class) ;
31     
32     // N3 writing proceeds in 2 stages.
33
// First, it analysis the model to be written to extract information
34
// that is going to be specially formatted (RDF lists, one ref anon nodes)
35
// Second do the writing walk.
36

37     // The simple N3 writer does nothing during preparation.
38

39     Map writerPropertyMap = null ;
40
41     final boolean doAbbreviatedBaseURIref = getBooleanValue("abbrevBaseURI", true) ;
42     boolean alwaysAllocateBNodeLabel = false ;
43     
44     // Common variables
45
RDFErrorHandler errorHandler = null;
46
47     static final String JavaDoc NS_W3_log = "http://www.w3.org/2000/10/swap/log#" ;
48
49     Map prefixMap = new HashMap() ; // Prefixes to actually use
50
Map bNodesMap = null ; // BNodes seen.
51
int bNodeCounter = 0 ;
52
53     // Specific properties that have a short form.
54
static Map wellKnownPropsMap = new HashMap() ;
55     static {
56         wellKnownPropsMap.put(NS_W3_log+"implies", "=>" ) ;
57         wellKnownPropsMap.put(OWL.sameAs.getURI(), "=" ) ;
58         wellKnownPropsMap.put(RDF.type.getURI(), "a" ) ;
59     }
60
61     // Work variables controlling the output
62
IndentedWriter out = null ;
63     String JavaDoc baseURIref = null ;
64     String JavaDoc baseURIrefHash = null ;
65
66     // Min spacing of items
67
int minGap = getIntValue("minGap", 1) ;
68     String JavaDoc minGapStr = pad(minGap) ;
69
70     // Gap from subject to property
71
int indentProperty = getIntValue("indentProperty", 6) ;
72     
73     // Width of property before wrapping.
74
// This is not necessarily a control of total width
75
// e.g. the pretty writer may be writing properties inside indented one ref bNodes
76
int widePropertyLen = getIntValue("widePropertyLen", 20) ;
77     
78     // Column for property when an object follows a property on the same line
79
int propertyCol = getIntValue("propertyColumn", 8) ;
80     
81     // Minimum gap from property to object when object on a new line.
82
int indentObject = propertyCol ;
83     
84     // If a subject is shorter than this, the first property may go on same line.
85
int subjectColumn = getIntValue("subjectColumn", indentProperty) ;
86     // Require shortSubject < subjectCol (strict less than)
87
int shortSubject = subjectColumn-minGap;
88     
89     boolean useWellKnownPropertySymbols = getBooleanValue("usePropertySymbols", true) ;
90     
91     boolean allowTripleQuotedStrings = getBooleanValue("useTripleQuotedStrings", true) ;
92     boolean allowDoubles = getBooleanValue("useDoubles", true) ;
93     
94     // ----------------------------------------------------
95
// Jena RDFWriter interface
96

97     public RDFErrorHandler setErrorHandler(RDFErrorHandler errHandler)
98     {
99         RDFErrorHandler old = errorHandler;
100         errorHandler = errHandler;
101         return old;
102     }
103
104     public Object JavaDoc setProperty(String JavaDoc propName, Object JavaDoc propValue)
105     {
106         if ( ! ( propValue instanceof String JavaDoc ) )
107         {
108             logger.warn("N3.setProperty: Property for '"+propName+"' is not a string") ;
109             propValue = propValue.toString() ;
110         }
111         
112         // Store absolute name of property
113
propName = absolutePropName(propName) ;
114         if ( writerPropertyMap == null )
115             writerPropertyMap = new HashMap() ;
116         Object JavaDoc oldValue = writerPropertyMap.get(propName);
117         writerPropertyMap.put(propName, propValue);
118         return oldValue;
119    }
120
121     /** Write the model out in N3. The writer should be one suitable for UTF-8 which
122     * excludes a PrintWriter or a FileWriter which use default character set.
123     *
124     * Examples:
125     * <pre>
126     * try {
127     * Writer w = new BufferedWriter(new OutputStreamWriter(output, "UTF-8")) ;
128     * model.write(w, base) ;
129     * try { w.flush() ; } catch (IOException ioEx) {}
130     * } catch (java.io.UnsupportedEncodingException ex) {} //UTF-8 is required so can't happen
131     * </pre>
132     * or
133     * <pre>
134     * try {
135     * OutputStream out = new FileOutputStream(file) ;
136     * Writer w = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")) ;
137     * model.write(w, base) ;
138     * }
139     * catch (java.io.UnsupportedEncodingException ex) {}
140     * catch (java.io.FileNotFoundException noFileEx) { ... }
141     * </pre>
142     * @see #write(Model,Writer,String)
143     */

144
145     public void write(Model baseModel, Writer _out, String JavaDoc base)
146     {
147         if (!(_out instanceof BufferedWriter))
148             _out = new BufferedWriter(_out);
149         out = new IndentedWriter(_out);
150
151         // Base is (should be) a URI, not a URI ref.
152

153         if ( base != null )
154         {
155             baseURIref = base ;
156             if ( !base.endsWith("#"))
157                 baseURIrefHash = baseURIref+"#" ;
158         }
159         
160         processModel(baseModel) ;
161     }
162     
163     /** Write the model out in N3, encoded in in UTF-8
164      * @see #write(Model,Writer,String)
165      */

166
167     public synchronized void write(Model model, OutputStream output, String JavaDoc base)
168     {
169         try {
170             Writer w = new BufferedWriter(new OutputStreamWriter(output, "UTF-8")) ;
171             write(model, w, base) ;
172             try { w.flush() ; } catch (IOException ioEx) {}
173         } catch (java.io.UnsupportedEncodingException JavaDoc ex)
174         {
175             System.err.println("Failed to create UTF-8 writer") ;
176         }
177     }
178
179     // ----------------------------------------------------
180
// The assumed processing model is:
181
// Writing N3 involves ordering the graph into:
182
// -- Subjects
183
// -- Property lists within subjects
184
// -- Object lists with in properties
185

186     // A derived class may choose to intercept and implement at any of these levels.
187

188     // Standard layout is:
189
// subject
190
// property1 value1 ;
191
// property2 value2 ;
192
// property3 value3 .
193

194     // Normal hook points for subclasses.
195

196     protected void startWriting() {}
197     protected void finishWriting() {}
198     protected void prepare(Model model) {}
199     
200     protected void processModel(Model baseModel)
201     {
202         prefixMap = baseModel.getNsPrefixMap() ;
203         Model model = ModelFactory.withHiddenStatements( baseModel );
204         bNodesMap = new HashMap() ;
205
206         // If no base defined for the model, but one given to writer,
207
// then use this.
208
String JavaDoc base2 = (String JavaDoc)prefixMap.get("") ;
209         
210         if ( base2 == null && baseURIrefHash != null )
211             prefixMap.put("", baseURIrefHash) ;
212
213         for ( Iterator iter = prefixMap.keySet().iterator() ; iter.hasNext() ; )
214         {
215             String JavaDoc prefix = (String JavaDoc)iter.next() ;
216             if ( prefix.indexOf('.') != -1 )
217                 iter.remove() ;
218         }
219         
220         startWriting() ;
221         prepare(model) ;
222
223         writeHeader(model) ;
224         writePrefixes(model) ;
225         
226         if (prefixMap.size() != 0)
227             out.println();
228
229         // Do the output.
230
writeModel(model) ;
231
232         // Release intermediate memory - allows reuse of a writer
233
finishWriting() ;
234         bNodesMap = null ;
235     }
236
237     protected void writeModel(Model model)
238     {
239        // Needed only for no prefixes, no blank first line.
240
boolean doingFirst = true;
241         ResIterator rIter = model.listSubjects();
242         for (; rIter.hasNext();)
243         {
244             // Subject:
245
// First - it is something we will write out as a structure in an object field?
246
// That is, a RDF list or the object of exactly one statement.
247
Resource subject = rIter.nextResource();
248             if ( skipThisSubject(subject) )
249             {
250                 if (N3JenaWriter.DEBUG)
251                     out.println("# Skipping: " + formatResource(subject));
252                 continue;
253             }
254
255             // We really are going to print something via writeTriples
256
if (doingFirst)
257                 doingFirst = false;
258             else
259                 out.println();
260
261             writeOneGraphNode(subject) ;
262             
263             
264         }
265         rIter.close();
266     }
267
268     protected void writeOneGraphNode(Resource subject)
269     {
270         // New top level item.
271
// Does not take effect until newline.
272
out.incIndent(indentProperty) ;
273         writeSubject(subject);
274         writePropertiesForSubject(subject) ;
275         out.decIndent(indentProperty) ;
276         out.println(" .");
277     }
278
279     protected void writePropertiesForSubject(Resource subj)
280     {
281         ClosableIterator iter = preparePropertiesForSubject(subj);
282         // For each property.
283
for (; iter.hasNext();)
284         {
285             Property property = (Property) iter.next();
286
287             // Object list
288
writeObjectList(subj, property);
289
290             if (iter.hasNext())
291                 out.println(" ;");
292         }
293         iter.close();
294     }
295
296     // Hook called on every resource.
297
// Since there is spacing bewteen resource frames, need to know
298
// whether an item will cause any output.
299
protected boolean skipThisSubject(Resource r) { return false ; }
300
301
302     // This is the hook called within writeModel.
303
// NB May not be at the top level (indent = 0)
304

305     protected void writeSubject(Resource subject)
306     {
307         String JavaDoc subjStr = formatResource(subject);
308         out.print(subjStr);
309         // May be very short : if so, stay on this line.
310

311         // Currently at end of subject.
312
// NB shortSubject is (subjectColumn-minGap) so there is a gap.
313

314         if (subjStr.length() < shortSubject )
315         {
316             out.print(pad(subjectColumn - subjStr.length()) );
317         }
318         else
319             // Does not fit this line.
320
out.println();
321     }
322     
323     protected void writeHeader(Model model)
324     {
325         if (baseURIref != null && !baseURIref.equals("") )
326             out.println("# Base: " + baseURIref);
327     }
328     
329     protected void writePrefixes(Model model)
330     {
331         for (Iterator pIter = prefixMap.keySet().iterator(); pIter.hasNext();)
332         {
333             String JavaDoc p = (String JavaDoc) pIter.next();
334             String JavaDoc u = (String JavaDoc) prefixMap.get(p);
335
336             // Special cases: N3 handling of base names.
337
if (doAbbreviatedBaseURIref && p.equals(""))
338             {
339                 if (baseURIrefHash != null && u.equals(baseURIrefHash))
340                     u = "#";
341                 if (baseURIref != null && u.equals(baseURIref))
342                     u = "";
343             }
344
345             String JavaDoc tmp = "@prefix " + p + ": ";
346             out.print(tmp);
347             out.print(pad(16 - tmp.length()));
348             // NB Starts with a space to ensure a gap.
349
out.println(" <" + u + "> .");
350         }
351
352     }
353     
354     protected void writeObjectList(Resource resource, Property property)
355     {
356         String JavaDoc propStr = formatProperty(property) ;
357
358 // if (wellKnownPropsMap.containsKey(property.getURI()))
359
// propStr = (String) wellKnownPropsMap.get(property.getURI());
360
// else
361
// propStr = formatResource(property);
362

363         // Write with object lists as clusters of statements with the same property
364
// Looks more like a machine did it but fewer bad cases.
365

366         StmtIterator sIter = resource.listProperties(property);
367         for (; sIter.hasNext();)
368         {
369             Statement stmt = sIter.nextStatement() ;
370             String JavaDoc objStr = formatNode(stmt.getObject()) ;
371             
372             out.print(propStr);
373             out.incIndent(indentObject);
374
375             if ( (propStr.length()+minGap) <= widePropertyLen )
376             {
377                 // Property col allows for min gap but widePropertyLen > propertyCol
378
// (which looses alignment - this is intentional.
379
// Ensure there is at least min gap.
380

381                 int padding = calcPropertyPadding(propStr) ;
382                 out.print(pad(padding)) ;
383                 
384 // if ( propStr.length() < propertyWidth )
385
// out.print( pad(propertyCol-minGap-propStr.length()) ) ;
386
// out.print(minGapStr) ;
387
}
388             else
389                 // Does not fit this line.
390
out.println();
391
392             // Write one object - simple writing.
393

394             out.print(objStr) ;
395             out.decIndent(indentObject);
396
397             if ( sIter.hasNext() )
398             {
399                 out.println(" ;") ;
400             }
401         }
402         sIter.close() ;
403
404     }
405
406     protected String JavaDoc formatNode(RDFNode node)
407     {
408         if (node instanceof Literal)
409             return formatLiteral((Literal) node);
410         else
411             return formatResource((Resource)node) ;
412     }
413
414     protected void writeObject(RDFNode node)
415     {
416         if (node instanceof Literal)
417         {
418             writeLiteral((Literal) node);
419             return;
420         }
421
422         Resource rObj = (Resource) node;
423
424         out.print(formatResource(rObj));
425     }
426     
427     protected void writeLiteral(Literal literal)
428     {
429         out.print(formatLiteral(literal)) ;
430     }
431     
432     protected ClosableIterator preparePropertiesForSubject(Resource r)
433     {
434         // Properties to do.
435
Set properties = new HashSet() ;
436
437         StmtIterator sIter = r.listProperties();
438         for ( ; sIter.hasNext() ; )
439             properties.add(sIter.nextStatement().getPredicate()) ;
440         sIter.close() ;
441         return WrappedIterator.create(properties.iterator()) ;
442     }
443     
444     
445     // Utility operations
446
protected String JavaDoc formatResource(Resource r)
447     {
448         if ( r.isAnon() )
449         {
450             if ( ! alwaysAllocateBNodeLabel )
451             {
452                 // Does anything point to it?
453
StmtIterator sIter = r.getModel().listStatements(null, null, r) ;
454     
455                 if ( ! sIter.hasNext() )
456                 {
457                     sIter.close() ;
458                     // This bNode is not referenced so don't need the bNode Id.
459
// Must be a subject - indent better be zero!
460
// This only happens for subjects because object bNodes
461
// referred to once (the other case for [] syntax)
462
// are handled elsewhere (by oneRef set)
463

464                     // Later: use [ prop value ] for this.
465
return "[]" ;
466                 }
467                 sIter.close() ;
468             }
469             if ( ! bNodesMap.containsKey(r) )
470                 bNodesMap.put(r, "_:b"+(++bNodeCounter)) ;
471             return (String JavaDoc)bNodesMap.get(r) ;
472
473         }
474
475         // It has a URI.
476

477         if ( r.equals(RDF.nil) )
478             return "()" ;
479
480         return formatURI(r.getURI()) ;
481     }
482
483     protected String JavaDoc formatLiteral(Literal literal)
484     {
485         String JavaDoc datatype = literal.getDatatypeURI() ;
486         String JavaDoc lang = literal.getLanguage() ;
487         String JavaDoc s = literal.getLexicalForm() ;
488     
489         if ( datatype != null )
490         {
491             // Special form we know how to handle?
492
// Assume valid text
493
if ( datatype.equals(XSD.integer.getURI()) )
494             {
495                 try {
496                     new java.math.BigInteger JavaDoc(s) ;
497                     return s ;
498                 } catch (NumberFormatException JavaDoc nfe) {}
499                 // No luck. Continue.
500
// Continuing is always safe.
501
}
502                 
503             if ( this.allowDoubles && datatype.equals(XSD.xdouble.getURI()) )
504             {
505                 // Must have an '.' or 'e' or 'E'
506
if ( s.indexOf('.') >= 0 ||
507                      s.indexOf('e') >= 0 ||
508                      s.indexOf('E') >= 0 )
509                 {
510                     try {
511                         Double.parseDouble(s) ;
512                         return s ;
513                     } catch (NumberFormatException JavaDoc nfe) {}
514                     // No luck. Continue.
515
}
516             }
517         }
518         // Format the text - with escaping.
519
StringBuffer JavaDoc sbuff = new StringBuffer JavaDoc() ;
520         boolean singleQuoteLiteral = true ;
521         
522         String JavaDoc quoteMarks = "\"" ;
523         
524         // Things that force the use of """ strings
525
if ( this.allowTripleQuotedStrings &&
526              ( s.indexOf("\n") != -1 ||
527                s.indexOf("\r") != -1 ||
528                s.indexOf("\f") != -1 ) )
529         {
530             quoteMarks = "\"\"\"" ;
531             singleQuoteLiteral = false ;
532         }
533         
534         sbuff.append(quoteMarks);
535         string(sbuff, s, singleQuoteLiteral) ;
536         sbuff.append(quoteMarks);
537     
538         // Format the language tag
539
if ( lang != null && lang.length()>0)
540         {
541             sbuff.append("@") ;
542             sbuff.append(lang) ;
543         }
544         
545         // Format the datatype
546
if ( datatype != null )
547         {
548             sbuff.append("^^") ;
549             sbuff.append(formatURI(datatype)) ;
550         }
551         return sbuff.toString() ;
552     }
553     
554     protected String JavaDoc formatProperty(Property p)
555     {
556         String JavaDoc prop = p.getURI() ;
557         if ( this.useWellKnownPropertySymbols && wellKnownPropsMap.containsKey(prop) )
558             return (String JavaDoc)wellKnownPropsMap.get(prop);
559
560         return formatURI(prop) ;
561     }
562     
563     protected String JavaDoc formatURI(String JavaDoc uriStr)
564     {
565         String JavaDoc matchURI = "" ;
566         String JavaDoc matchPrefix = null ;
567
568         if ( doAbbreviatedBaseURIref && uriStr.equals(baseURIref) )
569             return "<>" ;
570
571         // Try for a prefix and write as qname. Find the longest if several.
572
// Possible optimization: split URI and have URI=> ns: map.
573
// Ordering prefixes by length, then first hit is better.
574
//
575
// Also: could just assume that the split is on / or #
576
// Means we need to find a prefix just once.
577
for ( Iterator pIter = prefixMap.keySet().iterator() ; pIter.hasNext() ; )
578         {
579             String JavaDoc p = (String JavaDoc)pIter.next() ;
580             String JavaDoc u = (String JavaDoc)prefixMap.get(p) ;
581             if ( uriStr.startsWith(u) )
582                 if ( matchURI.length() < u.length() )
583                 {
584                     matchPrefix = p ;
585                     matchURI = u ;
586                 }
587         }
588         if ( matchPrefix != null )
589         {
590             String JavaDoc localname = uriStr.substring(matchURI.length()) ;
591             
592             if ( checkQName(matchPrefix, localname) )
593                 return matchPrefix+":"+localname ;
594
595             // Continue and return quoted URIref
596
}
597
598         // Not as a qname - write as a quoted URIref
599
// Should we unicode escape here?
600
// It should be right - the writer should be UTF-8 on output.
601
return "<"+uriStr+">" ;
602     }
603
604     // Qnames in N3 aren't really qnames
605
// No dots; digit can be first
606
// These tests must agree, or be more restrictive, than the parser.
607
static boolean checkQName(String JavaDoc ns, String JavaDoc local)
608     {
609         return checkQNameNamespace(ns) && checkQNameLocalname(local) ;
610     }
611     
612     static boolean checkQNameNamespace(String JavaDoc s)
613     {
614         return checkQNamePart(s) ;
615     }
616     static boolean checkQNameLocalname(String JavaDoc s)
617     {
618         return checkQNamePart(s) ;
619     }
620
621     
622     static boolean checkQNamePart(String JavaDoc s)
623     {
624         boolean isOK = true ;
625         CharacterIterator cIter = new StringCharacterIterator(s) ;
626         
627         for ( char ch = cIter.first() ;
628               ch != java.text.CharacterIterator.DONE ;
629               ch = cIter.next() )
630         {
631             if ( Character.isLetterOrDigit(ch) )
632                 continue ;
633             switch (ch)
634             {
635                 case '_': case '-':
636                     continue ;
637             }
638             // Not an acceptable characters
639
isOK = false ;
640             break ;
641         }
642         return isOK ;
643     }
644     
645     final static String JavaDoc WS = "\n\r\t" ;
646
647     protected static void string(StringBuffer JavaDoc sbuff, String JavaDoc s, boolean singleQuoteLiteral)
648     {
649         for (int i = 0; i < s.length(); i++) {
650             char c = s.charAt(i);
651
652             // Escape escapes and quotes
653
if (c == '\\' || c == '"' )
654             {
655                 sbuff.append('\\') ;
656                 sbuff.append(c) ;
657                 continue ;
658             }
659             
660             // Characters to literally output.
661
// This would generate 7-bit safe files
662
// if (c >= 32 && c < 127)
663
// {
664
// sbuff.append(c) ;
665
// continue;
666
// }
667

668             // Whitespace
669
if ( singleQuoteLiteral && ( c == '\n' || c == '\r' || c == '\f' ) )
670             {
671                 if (c == '\n') sbuff.append("\\n");
672                 if (c == '\t') sbuff.append("\\t");
673                 if (c == '\r') sbuff.append("\\r");
674                 if (c == '\f') sbuff.append("\\f");
675                 continue ;
676             }
677             
678             // Output as is (subject to UTF-8 encoding on output that is)
679
sbuff.append(c) ;
680             
681 // // Unicode escapes
682
// // c < 32, c >= 127, not whitespace or other specials
683
// String hexstr = Integer.toHexString(c).toUpperCase();
684
// int pad = 4 - hexstr.length();
685
// sbuff.append("\\u");
686
// for (; pad > 0; pad--)
687
// sbuff.append("0");
688
// sbuff.append(hexstr);
689
}
690     }
691     
692     protected int calcPropertyPadding(String JavaDoc propStr)
693     {
694         int padding = propertyCol - propStr.length();
695         if (padding < minGap)
696             padding = minGap;
697         return padding ;
698     }
699      
700     protected static String JavaDoc pad(int cols)
701     {
702         StringBuffer JavaDoc sb = new StringBuffer JavaDoc() ;
703         for ( int i = 0 ; i < cols ; i++ )
704             sb.append(' ') ;
705         return sb.toString() ;
706     }
707
708     // Utilities
709

710     protected int countProperties(Resource r)
711     {
712         int numProp = 0 ;
713         StmtIterator sIter = r.listProperties() ;
714         for ( ; sIter.hasNext() ; )
715         {
716             sIter.nextStatement() ;
717             numProp++ ;
718         }
719         sIter.close() ;
720         return numProp ;
721     }
722
723     protected int countProperties(Resource r, Property p)
724     {
725         int numProp = 0 ;
726         StmtIterator sIter = r.listProperties(p) ;
727         for ( ; sIter.hasNext() ; )
728         {
729             sIter.nextStatement() ;
730             numProp++ ;
731         }
732         sIter.close() ;
733         return numProp ;
734     }
735
736
737     protected int countArcsTo(Resource resource)
738     {
739         return countArcsTo(null, resource) ;
740     }
741
742     protected int countArcsTo(Property prop, Resource resource)
743     {
744         int numArcs = 0 ;
745         StmtIterator sIter = resource.getModel().listStatements(null, prop, resource) ;
746         for ( ; sIter.hasNext() ; )
747         {
748             sIter.nextStatement() ;
749             numArcs++ ;
750         }
751         sIter.close() ;
752         return numArcs ;
753     }
754
755
756     protected Iterator rdfListIterator(Resource r)
757     {
758         List list = new ArrayList() ;
759
760         for ( ; ! r.equals(RDF.nil); )
761         {
762             StmtIterator sIter = r.getModel().listStatements(r, RDF.first, (RDFNode)null) ;
763             list.add(sIter.nextStatement().getObject()) ;
764             if ( sIter.hasNext() )
765                 // @@ need to cope with this (unusual) case
766
throw new JenaException("N3: Multi valued list item") ;
767             sIter = r.getModel().listStatements(r, RDF.rest, (RDFNode)null) ;
768             r = (Resource)sIter.nextStatement().getObject() ;
769             if ( sIter.hasNext() )
770                 throw new JenaException("N3: List has two tails") ;
771         }
772         return list.iterator() ;
773     }
774     
775     // Convenience operations for accessing system properties.
776

777     protected String JavaDoc getStringValue(String JavaDoc prop, String JavaDoc defaultValue)
778     {
779         String JavaDoc p = getPropValue(prop) ;
780         
781         if ( p == null )
782             return defaultValue ;
783         return p ;
784     }
785      
786     protected boolean getBooleanValue(String JavaDoc prop, boolean defaultValue)
787     {
788         String JavaDoc p = getPropValue(prop) ;
789         
790         if ( p == null )
791             return defaultValue ;
792             
793         if ( p.equalsIgnoreCase("true") )
794             return true ;
795         
796         if ( p.equals("1") )
797             return true ;
798             
799         return false ;
800     }
801
802     protected int getIntValue(String JavaDoc prop, int defaultValue)
803     {
804         String JavaDoc p = getPropValue(prop) ;
805         if ( p == null )
806             return defaultValue ;
807         try {
808             return Integer.parseInt(p) ;
809         } catch (NumberFormatException JavaDoc ex)
810         {
811             logger.warn("Format error for property: "+prop) ;
812             return defaultValue ;
813         }
814     }
815     
816     // May be the absolute or local form of the property name
817

818     protected String JavaDoc getPropValue(String JavaDoc prop)
819     {
820         prop = absolutePropName(prop) ;
821         if ( writerPropertyMap != null && writerPropertyMap.containsKey(prop) )
822         {
823             Object JavaDoc obj = writerPropertyMap.get(prop) ;
824             if ( ! ( obj instanceof String JavaDoc ) )
825                 logger.warn("getPropValue: N3 Property for '"+prop+"' is not a string") ;
826             return (String JavaDoc)obj ;
827         }
828         String JavaDoc s = System.getProperty(prop) ;
829         if ( s == null )
830             s = System.getProperty(localPropName(prop)) ;
831         return s ;
832     }
833     
834     protected String JavaDoc absolutePropName(String JavaDoc propName)
835     {
836         if ( propName.indexOf(':') == -1 )
837             return N3JenaWriter.propBase + propName ;
838         return propName ;
839     }
840     
841     protected String JavaDoc localPropName(String JavaDoc propName)
842     {
843         if ( propName.startsWith(N3JenaWriter.propBase) )
844             propName = propName.substring(N3JenaWriter.propBase.length()) ;
845         return propName ;
846     }
847     
848     
849 }
850
851 /*
852  * (c) Copyright 2001, 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
853  * All rights reserved.
854  *
855  * Redistribution and use in source and binary forms, with or without
856  * modification, are permitted provided that the following conditions
857  * are met:
858  * 1. Redistributions of source code must retain the above copyright
859  * notice, this list of conditions and the following disclaimer.
860  * 2. Redistributions in binary form must reproduce the above copyright
861  * notice, this list of conditions and the following disclaimer in the
862  * documentation and/or other materials provided with the distribution.
863  * 3. The name of the author may not be used to endorse or promote products
864  * derived from this software without specific prior written permission.
865  *
866  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
867  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
868  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
869  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
870  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
871  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
872  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
873  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
874  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
875  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
876  */

877
Popular Tags