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

📄 basexmlwriter.java

📁 jena2.5.4推理机系统的一种最基本实现 HP实验室出品
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 *  (c) Copyright 2000, 2001, 2002, 2002, 2003, 2004, 2005, 2006, 2007 Hewlett-Packard Development Company, LP
 *  All rights reserved.
 *  [See end of file]
 *  $Id: BaseXMLWriter.java,v 1.66 2007/06/07 17:07:01 jeremy_carroll Exp $
*/

package com.hp.hpl.jena.xmloutput.impl;

import java.io.*;
import java.util.*;
import java.util.regex.Pattern;

import org.apache.commons.logging.*;
import org.apache.xerces.util.XMLChar;

import com.hp.hpl.jena.JenaRuntime;
import com.hp.hpl.jena.iri.*;
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.rdf.model.impl.RDFDefaultErrorHandler;
import com.hp.hpl.jena.rdf.model.impl.ResourceImpl;
import com.hp.hpl.jena.rdf.model.impl.Util;
import com.hp.hpl.jena.shared.*;
import com.hp.hpl.jena.util.CharEncoding;
import com.hp.hpl.jena.util.FileUtils;
import com.hp.hpl.jena.vocabulary.*;
import com.hp.hpl.jena.xmloutput.RDFXMLWriterI;

/** 
 * This is not part of the public API.
 * Base class for XML serializers.
 * All methods with side-effects should be synchronized in this class and its
 * subclasses. (i. e. XMLWriters assume that the world is not changing around
 * them while they are writing).
 * 
 * Functionality:
 * 
 * <ul>
 * <li>setProperty etc
 * <li>namespace prefixes
 * <li>xmlbase
 * <li>relative URIs
 * <li>encoding issues
 * <li>anonymous node presentationall
 * <li>errorHandler
 * </ul>
 *
 * @author  jjcnee
 * @version   Release='$Name:  $' Revision='$Revision: 1.66 $' Date='$Date: 2007/06/07 17:07:01 $'
*/
abstract public class BaseXMLWriter implements RDFXMLWriterI {
    
    private static final String newline = 
        JenaRuntime.getSystemProperty( "line.separator" );
    
    public BaseXMLWriter() {
        setupMaps();
    }
    
	private static Log xlogger = LogFactory.getLog( BaseXMLWriter.class );
    
    protected static SimpleLogger logger = new SimpleLogger() {
      	public void warn(String s) {
      		xlogger.warn(s);
      	}
      	public void warn(String s, Exception e) {
      		xlogger.warn(s,e);
      	}
  };
  
  public static SimpleLogger setLogger(SimpleLogger lg) {
  	SimpleLogger old = logger;
  	logger= lg;
  	return old;
  }
  
    abstract protected void unblockAll();
    
    abstract protected void blockRule(Resource r);

    abstract protected void writeBody
        ( Model mdl, PrintWriter pw, String baseUri, boolean inclXMLBase );

	static private Set badRDF = new HashSet();
    
    /**
        Counter used for allocating Jena transient namespace declarations.
    */
	private int jenaPrefixCount;
    
	static String RDFNS = RDF.getURI();
    
    
	static private Pattern jenaNamespace;
    
	static {
	    jenaNamespace =
				Pattern.compile("j\\.([1-9][0-9]*|cook\\.up)");
		
		badRDF.add("RDF");
		badRDF.add("Description");
		badRDF.add("li");
		badRDF.add("about");
		badRDF.add("aboutEach");
		badRDF.add("aboutEachPrefix");
		badRDF.add("ID");
		badRDF.add("nodeID");
		badRDF.add("parseType");
		badRDF.add("datatype");
		badRDF.add("bagID");
		badRDF.add("resource");
	}

	String xmlBase = null;

    private IRI baseURI;
        
	boolean longId = false;
    
    private boolean demandGoodURIs = true;
    
	int tabSize = 2;
    
	int width = 60;

	HashMap anonMap = new HashMap();
    
	int anonCount = 0;
    
	static private RDFDefaultErrorHandler defaultErrorHandler =
		new RDFDefaultErrorHandler();
        
	RDFErrorHandler errorHandler = defaultErrorHandler;

	Boolean showXmlDeclaration = null;
    
    protected Boolean showDoctypeDeclaration = Boolean.FALSE;

	/*
	 * There are two sorts of id's for anonymous resources.  Short id's are the
	 * default, but require a mapping table.  The mapping table means that
	 * serializing a large model could run out of memory.  Long id's require no
	 * mapping table, but are less readable.
	 */

	String anonId(Resource r)  {
		return longId ? longAnonId( r ) : shortAnonId( r );
	}

	/*
	 * A shortAnonId is computed by maintaining a mapping table from the internal
	 * id's of anon resources.  The short id is the index into the table of the
	 * internal id.
	 */
	private String shortAnonId(Resource r)  {
		String result = (String) anonMap.get(r.getId());
		if (result == null) {
			result = "A" + Integer.toString(anonCount++);
			anonMap.put(r.getId(), result);
		}
		return result;
	}

	/*
	 * A longAnonId is the internal id of the anon resource expressed as a
	 * character string.
	 *
	 * This code makes no assumptions about the characters used in the
	 * implementation of an anon id.  It checks if they are valid namechar
	 * characters and escapes the id if not.
	 */

	private String longAnonId(Resource r)  {
		String rid = r.getId().toString();
        return XMLChar.isValidNCName( rid ) ? rid : escapedId( rid );
	}

    /**
        true means all namespaces defined in the model prefixes will be noted in xmlns
        declarations; false means only "required" ones will be noted. Hook for configuration.
    */
    private boolean writingAllModelPrefixNamespaces = true;
        
    private Relation nameSpaces = new Relation();
    
    private Map ns;
    
    private PrefixMapping modelPrefixMapping;
        
	private Set namespacesNeeded;
    
	void addNameSpace(String uri) {
		namespacesNeeded.add(uri);
	}

    boolean isDefaultNamespace( String uri ) {
        return "".equals( ns.get( uri ) );
    }
        
    private void addNameSpaces( Model model )  {
        NsIterator nsIter = model.listNameSpaces();
        while (nsIter.hasNext()) this.addNameSpace( nsIter.nextNs() );
    }
    
    private void primeNamespace( Model model )
        {
        Map m = model.getNsPrefixMap();
        Iterator it  = m.entrySet().iterator();
        while (it.hasNext())
            {
            Map.Entry e = (Map.Entry) it.next();
//            String key = (String) e.getKey();
            String value = (String) e.getValue();
            String already = this.getPrefixFor( value );
            if (already == null) 
                { this.setNsPrefix( model.getNsURIPrefix( value ), value ); 
                if (writingAllModelPrefixNamespaces) this.addNameSpace( value ); }
            }
        }

    void setupMaps() {
        nameSpaces.set11(RDF.getURI(), "rdf");
        nameSpaces.set11(RDFS.getURI(), "rdfs");
        nameSpaces.set11(DC.getURI(), "dc");
        nameSpaces.set11(RSS.getURI(), "rss");
        nameSpaces.set11("http://www.daml.org/2001/03/daml+oil.daml#", "daml");
        nameSpaces.set11(VCARD.getURI(), "vcard");
        nameSpaces.set11("http://www.w3.org/2002/07/owl#", "owl");
    }
                
	void workOutNamespaces() {
		if (ns == null) {
    		ns = new HashMap();
    		Set prefixesUsed = new HashSet();
			setFromWriterSystemProperties( ns, prefixesUsed );
            setFromGivenNamespaces( ns, prefixesUsed );
        }
	}

    private void setFromWriterSystemProperties( Map ns, Set prefixesUsed ) {
        Iterator it = namespacesNeeded.iterator();
        while (it.hasNext()) {
            String uri = (String) it.next();
            String val = JenaRuntime.getSystemProperty( RDFWriter.NSPREFIXPROPBASE + uri );
            if (val != null && checkLegalPrefix( val ) && !prefixesUsed.contains( val )) {
                ns.put(uri, val);
                prefixesUsed.add(val);
            }
        }
    }

    private void setFromGivenNamespaces( Map ns, Set prefixesUsed ) {
		Iterator it = namespacesNeeded.iterator();
		while (it.hasNext()) {
			String uri = (String) it.next();
			if (ns.containsKey(uri))
				continue;
			String val = null;
			Set s = nameSpaces.forward(uri);
			if (s != null) {
				Iterator it2 = s.iterator();
				if (it2.hasNext())
					val = (String) it2.next();
				if (prefixesUsed.contains(val))
					val = null;
			}
			if (val == null) {
		        // just in case the prefix has already been used, look for a free one.
		        // (the usual source of such prefixes is reading in a model we wrote out earlier)
				do { val = "j." + (jenaPrefixCount++); } while (prefixesUsed.contains( val ));
			}
			ns.put(uri, val);
			prefixesUsed.add(val);
		}
	}

	final synchronized public void setNsPrefix(String prefix, String ns) {
        if (checkLegalPrefix(prefix)) {
            nameSpaces.set11(ns, prefix);
        }
    }
    
    final public String getPrefixFor( String uri )
        {
        Set s = nameSpaces.backward( uri );
        if (s != null && s.size() == 1) return (String) s.iterator().next();
        return null; 
        }

	String xmlnsDecl() {
		workOutNamespaces();
		StringBuffer result = new StringBuffer();
		Iterator it = ns.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry ent = (Map.Entry) it.next();
			String prefix = (String) ent.getValue();
			String uri = (String) ent.getKey();
            result.append( newline ).append( "    xmlns" );
			if (prefix.length() > 0) result.append( ':' ).append( prefix );
			result.append( '=' ).append( substitutedAttribute( checkURI( uri ) ) );
		}
		return result.toString();
	}

	static final private int FAST = 1;
	static final private int START = 2;
	static final private int END = 3;
	static final private int ATTR = 4;
	static final private int FASTATTR = 5;
    
	String rdfEl(String local) {
		return tag(RDFNS, local, FAST, true);
	}
    
	String startElementTag(String uri, String local) {
		return tag(uri, local, START, false);
	}
    
	protected String startElementTag(String uriref) {
		return splitTag(uriref, START);
	}
    
	String attributeTag(String uriref) {
		return splitTag(uriref, ATTR);
	}
    
	String attributeTag(String uri, String local) {
		return tag(uri, local, ATTR, false);
	}
    
	String rdfAt(String local) {
		return tag(RDFNS, local, FASTATTR, true);
	}
    
	String endElementTag(String uri, String local) {
		return tag(uri, local, END, false);
	}
    
	protected String endElementTag(String uriref) {
		return splitTag(uriref, END);
	}
    
	String splitTag(String uriref, int type) {
		int split = Util.splitNamespace( uriref );
		if (split == uriref.length()) throw new InvalidPropertyURIException( uriref );
		return tag( uriref.substring( 0, split ), uriref.substring( split ), type, true );
    }
    
	static public boolean dbg = false;
    
	String tag( String namespace, String local, int type, boolean localIsQname)  {
		if (dbg)
			System.err.println(namespace + " - " + local);
		String prefix = (String) ns.get( namespace );
		if (type != FAST && type != FASTATTR) {
			if ((!localIsQname) && !XMLChar.isValidNCName(local))
				return splitTag(namespace + local, type);
			if (namespace.equals(RDFNS)) {
				// Description, ID, nodeID, about, aboutEach, aboutEachPrefix, li
				// bagID parseType resource datatype RDF
				if (badRDF.contains(local)) {
					logger.warn(	"The URI rdf:" + local + " cannot be serialized in RDF/XML." );
					throw new InvalidPropertyURIException( "rdf:" + local );
				}
			}
		}
		boolean cookUp = false;
		if (prefix == null) {
            checkURI( namespace );
			logger.warn(
				"Internal error: unexpected QName URI: <"
					+ namespace
					+ ">.  Fixing up with j.cook.up code.",
				new BrokenException( "unexpected QName URI " + namespace ));
			cookUp = true;
		} else if (prefix.length() == 0) {
			if (type == ATTR || type == FASTATTR)
				cookUp = true;
			else
				return local;
		}
		if (cookUp) return cookUpAttribution( type, namespace, local );
		return prefix + ":" + local;
	}
    
    private String cookUpAttribution( int type, String namespace, String local )
        {
        String prefix = "j.cook.up";
        switch (type) {
            case FASTATTR :
            case ATTR :
                return "xmlns:" + prefix + "=" + substitutedAttribute( namespace ) + " " + prefix + ":" + local;
            case START :
                return prefix  + ":" + local + " xmlns:" + prefix+ "=" + substitutedAttribute( namespace );
            default:
            case END :
                return prefix + ":" + local;
            case FAST :
              //  logger.fatal("Unreachable code - reached.");
                throw new BrokenException( "cookup reached final FAST" );
            }
        }

	/** Write out an XML serialization of a model.
	 * @param model the model to be serialized
	 * @param out the OutputStream to receive the serialization
	 * @param base The URL at which the file will be placed.
	 */
	final public void write(Model model, OutputStream out, String base)
		 { write( model, FileUtils.asUTF8(out), base ); }

	/** Serialize Model <code>model</code> to Writer <code>out</out>.
	 * @param out The Writer to which the serialization should be sent.
	 * @param baseModel The model to be written.
	 * @param base the base URI for relative URI calculations.  <code>
	 * null</code> means use only absolute URI's.
	 */
	synchronized public void write(Model baseModel, Writer out, String base)
		 {        
        Model model = ModelFactory.withHiddenStatements( baseModel );
		setupNamespaces( baseModel, model );
		PrintWriter pw = out instanceof PrintWriter ? (PrintWriter) out : new PrintWriter( out );
		if (!Boolean.FALSE.equals(showXmlDeclaration)) writeXMLDeclaration( out, pw );
		writeXMLBody( model, pw, base );
		pw.flush();
	}

    /**
     	@param baseModel
     	@param model
    */
    private void setupNamespaces( Model baseModel, Model model )
        {
        this.namespacesNeeded = new HashSet();
        this.ns = null;

⌨️ 快捷键说明

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