⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 n3jenawritercommon.java

📁 Jena推理机
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * (c) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Hewlett-Packard Development Company, LP
 * [See end of file]
 */

package com.hp.hpl.jena.n3;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.hp.hpl.jena.JenaRuntime;
import com.hp.hpl.jena.util.iterator.* ;
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.shared.JenaException;
import com.hp.hpl.jena.vocabulary.OWL ;
import com.hp.hpl.jena.vocabulary.XSD ;
import com.hp.hpl.jena.vocabulary.RDF ;

import java.util.* ;
import java.io.* ;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.* ;

/** Common framework for implementing N3 writers.
 *
 * @author		Andy Seaborne
 * @version 	$Id: N3JenaWriterCommon.java,v 1.36 2007/01/02 11:48:32 andy_seaborne Exp $
 */

public class N3JenaWriterCommon implements RDFWriter
{
    static Log logger = LogFactory.getLog(N3JenaWriterCommon.class) ;
    
	// N3 writing proceeds in 2 stages.
    // First, it analysis the model to be written to extract information
    // that is going to be specially formatted (RDF lists, one ref anon nodes)
    // Second do the writing walk.
    
    // The simple N3 writer does nothing during preparation.
    
    Map writerPropertyMap = null ;

    final boolean doAbbreviatedBaseURIref = getBooleanValue("abbrevBaseURI", true) ; 
    boolean alwaysAllocateBNodeLabel = false ;
    
    // Common variables
	RDFErrorHandler errorHandler = null;

	static final String NS_W3_log = "http://www.w3.org/2000/10/swap/log#" ;

	Map prefixMap 	   	= new HashMap() ;	// Prefixes to actually use
	Map	bNodesMap       = null ;		    // BNodes seen.
    int bNodeCounter    = 0 ;

    // Specific properties that have a short form.
	static Map wellKnownPropsMap = new HashMap() ;
	static {
		wellKnownPropsMap.put(NS_W3_log+"implies",		"=>" ) ;
		wellKnownPropsMap.put(OWL.sameAs.getURI(),	    "="  ) ;
		wellKnownPropsMap.put(RDF.type.getURI(),		"a"  ) ;
	}

	// Work variables controlling the output
	IndentedWriter out = null ;
	String baseURIref = null ;
    String baseURIrefHash = null ;

    // Min spacing of items    
    int minGap = getIntValue("minGap", 1) ;
    String minGapStr = pad(minGap) ;

    // Gap from subject to property
	int indentProperty = getIntValue("indentProperty", 6) ;
    
    // Width of property before wrapping.
    // This is not necessarily a control of total width
    // e.g. the pretty writer may be writing properties inside indented one ref bNodes 
    int widePropertyLen = getIntValue("widePropertyLen", 20) ;
    
    // Column for property when an object follows a property on the same line
    int propertyCol = getIntValue("propertyColumn", 8) ;
    
    // Minimum gap from property to object when object on a new line.
    int indentObject = propertyCol ;
    
    // If a subject is shorter than this, the first property may go on same line.
    int subjectColumn = getIntValue("subjectColumn", indentProperty) ; 
    // Require shortSubject < subjectCol (strict less than)
    int shortSubject = subjectColumn-minGap;
    
    boolean useWellKnownPropertySymbols = getBooleanValue("usePropertySymbols", true) ;
    
    boolean allowTripleQuotedStrings = getBooleanValue("useTripleQuotedStrings", true) ;
    boolean allowDoubles   = getBooleanValue("useDoubles", true) ;
    boolean allowDecimals  = getBooleanValue("useDecimals", true) ;
    
    // ----------------------------------------------------
    // Jena RDFWriter interface

	public RDFErrorHandler setErrorHandler(RDFErrorHandler errHandler)
	{
		RDFErrorHandler old = errorHandler;
		errorHandler = errHandler;
		return old;
	}

    public Object setProperty(String propName, Object propValue) 
    {
        if ( ! ( propValue instanceof String ) )
        {
            logger.warn("N3.setProperty: Property for '"+propName+"' is not a string") ;
            propValue = propValue.toString() ;
        }
        
        // Store absolute name of property 
        propName = absolutePropName(propName) ;
        if ( writerPropertyMap == null )
            writerPropertyMap = new HashMap() ;
        Object oldValue = writerPropertyMap.get(propName);
        writerPropertyMap.put(propName, propValue);
        return oldValue;
   }

    /** Write the model out in N3.  The writer should be one suitable for UTF-8 which
    * excludes a PrintWriter or a FileWriter which use default character set.
    *
    * Examples:
    * <pre>
    * try {
    *      Writer w =  new BufferedWriter(new OutputStreamWriter(output, "UTF-8")) ;
    *      model.write(w, base) ;
    *      try { w.flush() ; } catch (IOException ioEx) {}
    *  } catch (java.io.UnsupportedEncodingException ex) {} //UTF-8 is required so can't happen
    * </pre>
    * or
    * <pre>
    * try {
    *     OutputStream out = new FileOutputStream(file) ;
    *     Writer w =  new BufferedWriter(new OutputStreamWriter(out, "UTF-8")) ;
    *     model.write(w, base) ;
    * }
    * catch (java.io.UnsupportedEncodingException ex) {}
    * catch (java.io.FileNotFoundException noFileEx) { ... }
    * </pre>
    * @see #write(Model,Writer,String)
    */

    public void write(Model baseModel, Writer _out, String base) 
    {
        if (!(_out instanceof BufferedWriter))
            _out = new BufferedWriter(_out);
        out = new IndentedWriter(_out);

        if ( base != null )
        {
            baseURIref = base ;
            if ( !base.endsWith("#") &&! isOpaque(base) )
                baseURIrefHash = baseURIref+"#" ;
        }
        
        processModel(baseModel) ;
    }
    
	/** Write the model out in N3, encoded in in UTF-8
	 * @see #write(Model,Writer,String)
	 */

	public synchronized void write(Model model, OutputStream output, String base) 
	{
		try {
			Writer w =  new BufferedWriter(new OutputStreamWriter(output, "UTF-8")) ;
			write(model, w, base) ;
			try { w.flush() ; } catch (IOException ioEx) {}
		} catch (java.io.UnsupportedEncodingException ex)
		{
			System.err.println("Failed to create UTF-8 writer") ;
		}
	}

    // ----------------------------------------------------
    // The assumed processing model is:
    // Writing N3 involves ordering the graph into:
    // -- Subjects
    // -- Property lists within subjects
    // -- Object lists with in properties
    
    //  A derived class may choose to intercept and implement at any of these levels. 
     
    // Standard layout is:
    // subject
    //    property1 value1 ;
    //    property2 value2 ;
    //    property3 value3 .
    
    // Normal hook points for subclasses.

    protected void startWriting() {}
    protected void finishWriting() {}
    protected void prepare(Model model) {}
    
    protected void processModel(Model baseModel)
    {
        prefixMap = baseModel.getNsPrefixMap() ;
        Model model = ModelFactory.withHiddenStatements( baseModel );
        bNodesMap = new HashMap() ;

        // If no base defined for the model, but one given to writer,
        // then use this.
        String base2 = (String)prefixMap.get("") ;
        
        if ( base2 == null && baseURIrefHash != null )
            prefixMap.put("", baseURIrefHash) ;

        for ( Iterator iter = prefixMap.keySet().iterator() ; iter.hasNext() ; )
        {
            String prefix = (String)iter.next() ;
            if ( prefix.indexOf('.') != -1 )
                iter.remove() ;
        }
        
        startWriting() ;
        prepare(model) ;

        writeHeader(model) ;
        writePrefixes(model) ;
        
        if (prefixMap.size() != 0)
            out.println();

        // Do the output.
        writeModel(model) ;

        // Release intermediate memory - allows reuse of a writer
        finishWriting() ;
        bNodesMap = null ;
    }

    protected void writeModel(Model model)
    {
       // Needed only for no prefixes, no blank first line. 
        boolean doingFirst = true;
        ResIterator rIter = listSubjects(model);
        for (; rIter.hasNext();)
        {
            // Subject:
            // First - it is something we will write out as a structure in an object field?
            // That is, a RDF list or the object of exactly one statement.
            Resource subject = rIter.nextResource();
            if ( skipThisSubject(subject) )
            {
                if (N3JenaWriter.DEBUG)
                    out.println("# Skipping: " + formatResource(subject));
                continue;
            }

            // We really are going to print something via writeTriples
            if (doingFirst)
                doingFirst = false;
            else
                out.println();

            writeOneGraphNode(subject) ;
            
            
        }
        rIter.close();
    } 
    
    protected ResIterator listSubjects(Model model) { return model.listSubjects(); }

    protected void writeOneGraphNode(Resource subject)
    {
        // New top level item.
        // Does not take effect until newline.
        out.incIndent(indentProperty) ;
        writeSubject(subject);
        writePropertiesForSubject(subject) ;
        out.decIndent(indentProperty) ; 
        out.println(" .");
    }

    protected void writePropertiesForSubject(Resource subj)
    {
        ClosableIterator iter = preparePropertiesForSubject(subj);
        // For each property.
        for (; iter.hasNext();)
        {
            Property property = (Property) iter.next();

            // Object list
            writeObjectList(subj, property);

            if (iter.hasNext())
                out.println(" ;");
        }
        iter.close();
    }

    // Hook called on every resource.
    // Since there is spacing bewteen resource frames, need to know
    // whether an item will cause any output.   
    protected boolean skipThisSubject(Resource r) { return false ; }


    // This is the hook called within writeModel.  
    // NB May not be at the top level (indent = 0)
    
    protected void writeSubject(Resource subject)
    {
        String subjStr = formatResource(subject);
        out.print(subjStr);
        // May be very short : if so, stay on this line.
        
        // Currently at end of subject.
        // NB shortSubject is (subjectColumn-minGap) so there is a gap.

        if (subjStr.length() < shortSubject )
        {
            out.print(pad(subjectColumn - subjStr.length()) );
        }
        else
            // Does not fit this line.
            out.println();
    }
    
    protected void writeHeader(Model model)
    {
        if (baseURIref != null && !baseURIref.equals("") )
            out.println("# Base: " + baseURIref);
    }
    
    protected void writePrefixes(Model model)
    {
        for (Iterator pIter = prefixMap.keySet().iterator(); pIter.hasNext();)
        {
            String p = (String) pIter.next();
            String u = (String) prefixMap.get(p);

            // Special cases: N3 handling of base names.
            if (doAbbreviatedBaseURIref && p.equals(""))
            {
                if (baseURIrefHash != null && u.equals(baseURIrefHash))
                    u = "#";
                if (baseURIref != null && u.equals(baseURIref))
                    u = "";
            }

            String tmp = "@prefix " + p + ": ";
            out.print(tmp);
            out.print(pad(16 - tmp.length()));
            // NB Starts with a space to ensure a gap.
            out.println(" <" + u + "> .");
        }

    }
    
    protected void writeObjectList(Resource resource, Property property)
    {
        String propStr = formatProperty(property) ;

//        if (wellKnownPropsMap.containsKey(property.getURI()))
//            propStr = (String) wellKnownPropsMap.get(property.getURI());
//        else
//            propStr = formatResource(property);

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

        StmtIterator sIter = resource.listProperties(property);
        for (; sIter.hasNext();)
        {
            Statement stmt = sIter.nextStatement() ;
            String objStr = formatNode(stmt.getObject()) ;
            
            out.print(propStr);
            out.incIndent(indentObject);

            if ( (propStr.length()+minGap) <= widePropertyLen )
            {
                // Property col allows for min gap but widePropertyLen > propertyCol 
                // (which looses alignment - this is intentional.
                // Ensure there is at least min gap.
                
                int padding = calcPropertyPadding(propStr) ;
                out.print(pad(padding)) ;
                
//                if ( propStr.length() < propertyWidth ) 
//                    out.print( pad(propertyCol-minGap-propStr.length()) ) ;
//                out.print(minGapStr) ;
            }
            else
                // Does not fit this line.
                out.println();

            // Write one object - simple writing.
            
            out.print(objStr) ;
            out.decIndent(indentObject);

            if ( sIter.hasNext() )
            {
                out.println(" ;") ;
            }
        }
        sIter.close() ;

    }

    protected String formatNode(RDFNode node)
    {
        if (node instanceof Literal)
            return formatLiteral((Literal) node);
        else
            return formatResource((Resource)node) ;
    }

    protected void writeObject(RDFNode node)
    {
        if (node instanceof Literal)
        {
            writeLiteral((Literal) node);
            return;
        }

        Resource rObj = (Resource) node;

        out.print(formatResource(rObj));
    }
    
    protected void writeLiteral(Literal literal) 
    {
        out.print(formatLiteral(literal)) ;
    }
    
    protected ClosableIterator preparePropertiesForSubject(Resource r)
    {
        // Properties to do.
        Set properties = new HashSet() ;

        StmtIterator sIter = r.listProperties();
        for ( ; sIter.hasNext() ; )
            properties.add(sIter.nextStatement().getPredicate()) ;
        sIter.close() ;
        return WrappedIterator.create(properties.iterator()) ;
    }
    
    
    // Utility operations
    protected String formatResource(Resource r)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -