/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.xml; import gw.internal.xml.xsd.typeprovider.XmlSchemaIndex; import gw.lang.reflect.IType; import gw.util.ScopedMap; import gw.xml.XmlElement; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.TreeSet; import javax.xml.XMLConstants; public class XmlSerializationContext { private static final ScopedMap<String,String> _basePrefixToNamespaceUri = new ScopedMap<String, String>(); private static final ScopedMap<String,TreeSet<String>> _baseNamespaceUriToPrefix = new ScopedMap<String, TreeSet<String>>(); static { _basePrefixToNamespaceUri.put( XMLConstants.DEFAULT_NS_PREFIX, XMLConstants.NULL_NS_URI ); _baseNamespaceUriToPrefix.put( XMLConstants.NULL_NS_URI, new TreeSet<String>( Collections.singletonList( XMLConstants.DEFAULT_NS_PREFIX ) ) ); _basePrefixToNamespaceUri.put( XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI ); _baseNamespaceUriToPrefix.put( XMLConstants.XML_NS_URI, new TreeSet<String>( Collections.singletonList( XMLConstants.XML_NS_PREFIX ) ) ); _basePrefixToNamespaceUri.put( XMLConstants.XMLNS_ATTRIBUTE, XMLConstants.XMLNS_ATTRIBUTE_NS_URI); _baseNamespaceUriToPrefix.put( XMLConstants.XMLNS_ATTRIBUTE_NS_URI, new TreeSet<String>( Collections.singletonList( XMLConstants.XMLNS_ATTRIBUTE ) ) ); } private ScopedMap<String,String> _prefixToNamespaceUri = _basePrefixToNamespaceUri.pushScope(); private ScopedMap<String,TreeSet<String>> _namespaceUriToPrefix = _baseNamespaceUriToPrefix.pushScope(); private Map<XmlElement,String> _idByElement = new HashMap<XmlElement, String>(); private Set<String> _usedIds = new HashSet<String>(); private int _nextAutomaticId = 0; private XmlElement _currentElement; private SortedMap<String, XmlSchemaIndex> _requiredSchemas = new TreeMap<String, XmlSchemaIndex>(); public XmlSerializationContext() { } public ScopedMap<String, String> getPrefixToNamespaceUriMap() { return _prefixToNamespaceUri; } public ScopedMap<String, TreeSet<String>> getNamespaceUriToPrefixMap() { return _namespaceUriToPrefix; } public void pushScope() { _prefixToNamespaceUri = _prefixToNamespaceUri.pushScope(); _namespaceUriToPrefix = _namespaceUriToPrefix.pushScope(); } public void popScope() { _prefixToNamespaceUri = _prefixToNamespaceUri.popScope(); _namespaceUriToPrefix = _namespaceUriToPrefix.popScope(); } public void setCurrentElement( XmlElement currentElement ) { _currentElement = currentElement; } public XmlElement getCurrentElement() { return _currentElement; } public String makeUniqueId( XmlElement element, String suggestedValue ) { String id = _idByElement.get( element ); if ( id == null ) { id = suggestedValue == null ? "ID" : suggestedValue; while ( ! _usedIds.add( id ) ) { id = "ID" + _nextAutomaticId++; } _idByElement.put( element, id ); } return id; } // Add a schema that is required for parsing this XML document. For example: // Element A exists in schema A. There is a substitution group member B in schema B. // When creating an instance, you actually substitute a B for an A. When serializing the XML, // you must realize that since element B ( from schema B ) is included in the instance, // the actual schema for element B must be included in the list of schemas to be validated // against, or the instance document will not be considered valid. This goes for xsi:types as // well, since the xsi:type qname will only resolve if the schema containing the type referenced // by the xsi:type is included in the list of schemas at validation time. public void addRequiredSchema( IType type ) { if ( type != null ) { // schemas can refer to some of the simple types in the schema schema without referencing that schema in any way. // Referencing anything else in the schema schema requires an explicit import. if ( ! XmlSchemaIndex.isBuiltInDatatype( type ) ) { XmlSchemaIndex<?> schemaIndex = XmlSchemaIndex.getSchemaIndexByType( type ); if ( schemaIndex != null ) { _requiredSchemas.put( schemaIndex.getPackageName(), schemaIndex ); } } } } public List<XmlSchemaIndex> getRequiredSchemas() { return new ArrayList<XmlSchemaIndex>( _requiredSchemas.values() ); } }