/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.xml.xsd.typeprovider.xmlsorter;
import gw.internal.xml.xsd.typeprovider.XmlSchemaIndex;
import gw.internal.xml.xsd.typeprovider.schema.XmlSchemaAny;
import gw.xml.XmlElement;
import gw.xml.XmlSortException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* Sort handler representing an xsd:any. This handler matches a single element, but there are loose restrictions
* on what type of element it matches, as defined by the XML Schema specification. minOccurs/maxOccurs is handled
* by the XmlSchemaObjectPluralityXmlSortHandler.
*/
public class XmlSchemaAnyXmlSortHandler extends XmlSortHandler {
private XmlElement _currentElement = null;
private Set<XmlElement> _triedElements = new HashSet<XmlElement>();
private XmlSchemaAny _any;
// This constructor is called reflectively
public XmlSchemaAnyXmlSortHandler( XmlSchemaAny any ) {
super( any );
_any = any;
}
@Override
protected List<XmlElement> sortDirect( LinkedList<XmlElement> remainingChildren, boolean preferredOnly, List<XmlSchemaIndex> requiredSchemas, Set<XmlElement> mustMatch ) {
if ( _currentElement == null ) {
for ( XmlElement element : remainingChildren ) {
if ( ! _triedElements.contains( element ) ) {
_triedElements.add( element );
if ( _any.accept( element.getQName() ) ) {
_currentElement = element;
break;
}
}
if ( preferredOnly ) {
throwNoMatches();
}
}
}
if ( _currentElement == null ) {
return throwNoMatches();
}
final ArrayList<XmlElement> sortedChildren = new ArrayList<XmlElement>( 1 ); // this list will be modified
sortedChildren.add( _currentElement );
return sortedChildren;
}
private List<XmlElement> throwNoMatches() {
throw new XmlSortException( "No matches for xsd:any, namespace = \"" + _any.getNamespaceSpec() + "\", targetNamespace = [" + _any.getTargetNamespace() + "]" );
}
@Override
protected boolean selectNextChoiceDirect() {
if ( _currentElement == null ) {
return false;
}
else {
_currentElement = null;
return true;
}
}
@Override
public void _reset() {
_triedElements.clear();
_currentElement = null;
}
@Override
protected void checkMissingRequiredElements( LinkedList<XmlElement> remainingChildren, List<XmlSchemaIndex> requiredSchemas ) {
// TODO?
}
@Override
public void match( Set<XmlElement> children, List<XmlSchemaIndex> requiredSchemas ) {
Iterator<XmlElement> iter = children.iterator();
while ( iter.hasNext() ) {
XmlElement child = iter.next();
if ( _any.accept( child.getQName() ) ) {
iter.remove();
}
}
}
}