All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javolution.xml.XMLReferenceResolver Maven / Gradle / Ivy

The newest version!
/*
 * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
 * Copyright (C) 2012 - Javolution (http://javolution.org/)
 * All rights reserved.
 * 
 * Permission to use, copy, modify, and distribute this software is
 * freely granted, provided that this notice is preserved.
 */
package javolution.xml;

import javolution.text.CharArray;
import javolution.text.TextBuilder;
import javolution.util.FastMap;
import javolution.util.FastTable;
import javolution.util.Index;
import javolution.util.function.Equalities;
import javolution.xml.stream.XMLStreamException;

/**
 * 

This class represents a resolver for XML cross references during * the marshalling/unmarshalling process.

* *

Instances of this class may only be shared by {@link XMLObjectReader}/ * {@link XMLObjectWriter} running sequentially (for cross references * spawning multiple documents).

* * @author Jean-Marie Dautelle * @version 4.0, September 4, 2006 */ public class XMLReferenceResolver { /** * Holds object to identifier (FastTable.Index) mapping. */ private FastMap _objectToId = new FastMap( Equalities.IDENTITY); /** * Holds the objects (index to object mapping). */ private FastTable _idToObject = new FastTable(); /** * Holds the id counter. */ private int _counter; /** * Holds the identifier attribute name. */ private String _idName = "id"; /** * Holds the identifier attribute URI if any. */ private String _idURI = null; /** * Holds the reference attribute name. */ private String _refName = "ref"; /** * Holds the reference attribute URI if any. */ private String _refURI = null; /** * Default constructor. */ public XMLReferenceResolver() {} /** * Sets the name of the identifier attribute (by default"id"). * If the name is null then the identifier attribute * is never read/written (which may prevent unmarshalling). * * @param name the name of the attribute or null. */ public void setIdentifierAttribute(String name) { setIdentifierAttribute(name, null); } /** * Sets the local name and namespace URI of the identifier attribute. * * @param localName the local name of the attribute or null. * @param uri the URI of the attribute or null if the attribute * has no namespace URI. */ public void setIdentifierAttribute(String localName, String uri) { _idName = localName; _idURI = uri; } /** * Sets the name of the reference attribute (by default"ref"). * If the name is null then the reference attribute * is never read/written (which may prevent unmarshalling). * * @param name the name of the attribute or null. */ public void setReferenceAttribute(String name) { setReferenceAttribute(name, null); } /** * Sets the local name and namespace URI of the identifier attribute. * * @param localName the local name of the attribute or null. * @param uri the URI of the attribute or null if the attribute * has no namespace URI. */ public void setReferenceAttribute(String localName, String uri) { _refName = localName; _refURI = uri; } /** * Writes a reference to the specified object into the specified XML * element. The default implementation writes the reference into the * reference attribute and for the first occurences an identifier * (counter starting at 1) is written into the identifier attribute. * * @param obj the object for which the reference is written. * @param xml the output XML element. * @return true if a reference is written; * false if a new identifier is written. */ public boolean writeReference(Object obj, XMLFormat.OutputElement xml) throws XMLStreamException { Index id = (Index) _objectToId.get(obj); if (id == null) { // New identifier. id = Index.valueOf(_counter++); _objectToId.put(obj, id); _tmp.clear().append(id.intValue()); if (_idURI == null) { xml.getStreamWriter().writeAttribute(_idName, _tmp); } else { xml.getStreamWriter().writeAttribute(_idURI, _idName, _tmp); } return false; } _tmp.clear().append(id.intValue()); if (_refURI == null) { xml._writer.writeAttribute(_refName, _tmp); } else { xml._writer.writeAttribute(_refURI, _refName, _tmp); } return true; } private TextBuilder _tmp = new TextBuilder(); /** * Reads the object referenced by the specified xml input element if any. * The default implementation reads the reference attribute to retrieve * the object. * * @param xml the input XML element. * @return the referenced object or null if the specified * XML input does not have a reference attribute. */ public Object readReference(XMLFormat.InputElement xml) throws XMLStreamException { CharArray value = xml._reader.getAttributeValue(_refURI, _refName); if (value == null) return null; int ref = value.toInt(); if (ref >= _idToObject.size()) throw new XMLStreamException("Reference: " + value + " not found"); return _idToObject.get(ref); } /** * Creates a reference for the specified object (the identifier * being specified by the input XML element). * The default implementation reads the identifier attribute (if any) * and associates it to the specified object. * * @param obj the object being referenced. * @param xml the input XML element holding the reference identifier. */ public void createReference(Object obj, XMLFormat.InputElement xml) throws XMLStreamException { CharArray value = xml._reader.getAttributeValue(_idURI, _idName); if (value == null) return; int i = value.toInt(); if (_idToObject.size() != i) throw new XMLStreamException("Identifier discontinuity detected " + "(expected " + _idToObject.size() + " found " + i + ")"); _idToObject.add(obj); } public void reset() { _idName = "id"; _idURI = null; _refName = "ref"; _refURI = null; _idToObject.clear(); _objectToId.clear(); _counter = 0; } }