www.pudn.com > sxg.rar > MibRepositoryHandler.java


/*
 * Copyright (c) 2003 Jens Mueller
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/**
 	Singleton class representing MIB-Information for
	OID <-> XML mapping. XML-Schemes referenced in the main container-schema are
 	parsed and stored in a hashtable.

 	@author jens mueller
 */

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL; 
import java.util.StringTokenizer;
import java.util.*;

import org.dom4j.Document;
import org.dom4j.Attribute;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.Node;
import org.dom4j.DocumentException;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import org.omg.CosNaming.NamingContextExtPackage.URLStringHelper;
import org.xml.sax.InputSource;
import org.dom4j.datatype.SchemaParser;

public class MibRepositoryHandler
{
	
	/**
	 	Private class representing a XML-Schema. Instances of this class
	 	are put to the Hashtable _schemaTable
	 */
	private class Schema
	{
		private String _namespacePrefix;
		private String _schemaLocation;
		private Document _schemaDocument;
		
		Schema( String namespacePrefix, String location, Document document )
		{
			_namespacePrefix = namespacePrefix;
			_schemaLocation = location;
			_schemaDocument = document;
		}
		
		String getNamespacePrefix()
		{
			return _namespacePrefix;
		}
		
		String getLocation()
		{
			return _schemaLocation;
		}

		Document getDocument()
		{
			return _schemaDocument;
		}		
	}
	
	/**
	 	An instance of this private class represents an accessible MIB-Objectname,
	 	parsed from the container-schema.
	 */
	private class XmlSnmpElement
	{
		private String _typeNamespacePrefix;
		private String _typeSchemaLocation;
		private String _name;
		private String _typeName;
		
		XmlSnmpElement( 	String name, String typeName, 
									String typeNamespacePrefix, 
									String typeSchemaLocation )
		{
			_name = name;
			_typeName = typeName;
			_typeNamespacePrefix = typeNamespacePrefix;
			_typeSchemaLocation = typeSchemaLocation ;
		}
		
		String getTypeNamespacePrefix()
		{
			return _typeNamespacePrefix;
		}
		
		String getTypeSchemalocation()
		{
			return _typeSchemaLocation;
		}

		String getName()
		{
			return _name;
		}

		String getTypeName()
		{
			return _typeName;
		}
	}

	
	
	private static MibRepositoryHandler _instance;
	private Document _document;
	private Vector _XmlSnmpElementsVector;
	private Hashtable _schemaTable;
	//debug
	String debugstr;
	//debug
	
	private MibRepositoryHandler()
	{
		_XmlSnmpElementsVector = new Vector();
		_schemaTable = new Hashtable( 200 );
		//debug
		debugstr = "DEBUGSTR:  ";
		//debug
		
	}
	
	/**
	 	checks if the singleton instance has been instantiated. If not, it instantiates a new
	 	MibRepositoryHandler. Otherwise it returnes the already instantiated instance. 
	 	@return the instance of the MibRepositoryHandler 	 	@throws DocumentException 	 	@throws MalformedURLException 	 	@throws IOException 	 */
	public static synchronized MibRepositoryHandler getInstance() 
											throws DocumentException, MalformedURLException, IOException
	{
		if ( _instance == null )
		{
			_instance = new MibRepositoryHandler();
			_instance.parseRepository( GatewayConf.getRepositoryUrl() );
		}
		return _instance;
	}
	
	/**
	 	loads a XML-Schema, parses it, puts it into the Hashtable and starts parsing of all imported
	 	schemes recursively. 
	 	@param prefix   the namespace prefix with which this schema was referenced 	 	@param location   the URL where the schema resides 	 	@throws DocumentException 	 	@throws MalformedURLException 	 	@throws IOException 	 */
	private void parseSchema( String prefix, String location )
											throws DocumentException, MalformedURLException, IOException
	{
		debugstr += "parseSchema: "+prefix+" "+location;
		if ( _schemaTable.get( prefix ) == null )
		{
			debugstr += "  not in table, processing 
"; SAXReader reader = new SAXReader(); reader.setValidation( false ); URL schemaUrl = new URL( location ); java.net.URLConnection mibSite = schemaUrl.openConnection(); InputStream bytestream = mibSite.getInputStream(); InputStreamReader streamReader = new InputStreamReader( bytestream ); InputSource insrc = new InputSource( streamReader ); Document schemaDocument = reader.read( insrc ); // adding current schema to hashtable _schemaTable.put( prefix, new Schema( prefix, location, schemaDocument ) ); List declaredNamespaces = schemaDocument.getRootElement().declaredNamespaces(); List importedNamespaces = schemaDocument.selectNodes( "/xsd:schema/xsd:import" ); // parsing imported namespaces with their declares prefixes for ( Iterator iterator = importedNamespaces.iterator(); iterator.hasNext(); ) { Element currImportedNamespace = ( Element )iterator.next(); String currNamespaceString = currImportedNamespace.attribute( "namespace" ).getValue(); String currNamespaceLocation = currImportedNamespace.attribute( "schemaLocation" ).getValue(); for ( Iterator iter = declaredNamespaces.iterator(); iter.hasNext(); ) { Namespace currDeclaredNamespace = ( Namespace )iter.next(); if ( currDeclaredNamespace.getURI().equals( currNamespaceString ) ) // adding imported schema via recursive call parseSchema( currDeclaredNamespace.getPrefix(), currNamespaceLocation ); } } } else debugstr += " already hashed in
"; } /** loads the container-schema, parses it and starts parsing of all referenced schemes by calling parseSchema. @param path the URL where the container-schema resides. Configured via the parameter "repositoryURL" in the servlet's deployment descriptor. @throws DocumentException @throws MalformedURLException @throws IOException */ private void parseRepository( String path ) throws DocumentException, MalformedURLException, IOException { SAXReader reader = new SAXReader(); reader.setValidation( false ); URL repositoryUrl = new URL( path ); java.net.URLConnection mibSite = repositoryUrl.openConnection(); InputStream bytestream = mibSite.getInputStream(); InputStreamReader streamReader = new InputStreamReader( bytestream ); InputSource insrc = new InputSource( streamReader ); _document = reader.read( insrc ); List elementsList = _document.selectNodes( "/xsd:schema/xsd:element[@name=" + "\"snmp-data\"]/xsd:complexType/" + "xsd:sequence/xsd:element[@name= "+ "\"context\"]/xsd:complexType/" + "xsd:sequence/xsd:element" ); debugstr += "
parsed "+elementsList.size()+ " elementdeclarations from "+path+""; for ( Iterator elementsIterator = elementsList.iterator(); elementsIterator.hasNext(); ) { Element currElement = ( Element )elementsIterator.next(); Attribute nameAttr = currElement.attribute( "name" ); Attribute typeAttr = currElement.attribute( "type" ); String name = nameAttr.getValue(); String type = typeAttr.getValue(); StringTokenizer strtok = new StringTokenizer( type, ":" ); if ( strtok.countTokens() != 2 ) throw new DocumentException( type ); String typePrefix = strtok.nextToken(); type = strtok.nextToken(); String typeSchemaLocation = ""; Namespace ns = _document.getRootElement().getNamespaceForPrefix( typePrefix ); List importedNamespaces = _document.selectNodes( "/xsd:schema/xsd:import" ); for ( Iterator iterator = importedNamespaces.iterator(); iterator.hasNext(); ) { Element currImportedNamespace = ( Element )iterator.next(); String currNamespaceString = currImportedNamespace.attribute( "namespace" ).getValue(); String currNamespaceLocation = currImportedNamespace.attribute( "schemaLocation" ).getValue(); if ( currImportedNamespace.attribute( "namespace" ).getValue().equals( ns.getURI() ) ) { typeSchemaLocation = currImportedNamespace.attribute( "schemaLocation" ).getValue(); } } /* XmlSnmpElement testelem = new XmlSnmpElement( name, type, typePrefix, typeSchemaLocation ); debugstr += "
Found Element: "+name+" of type: "+type + ". Starting recursive parse-in of "+typePrefix + " @ "+typeSchemaLocation+"
"; */ parseSchema( typePrefix, typeSchemaLocation ); _XmlSnmpElementsVector.add( new XmlSnmpElement( name, type, typePrefix, typeSchemaLocation) ); } } /** searches in the container-schema for a single MIB-Object referenced by its name and namespace-prefix. If found, builds the GwComplexType for that MIB-Object by calling getType( Element element, Schema declSchema )This Method provides address' translation for set-requests. @param name the name of the searched object @param namespacePrefix the prefix with which the name was referenced @return GwComplexType */ public synchronized GwComplexType getType( String name, String namespacePrefix ) { List elementsList = _document.selectNodes( "/xsd:schema/xsd:element[@name=" + "\"snmp-data\"]/xsd:complexType/" + "xsd:sequence/xsd:element[@name=" + "\"context\"]/xsd:complexType" + "/xsd:sequence/xsd:element" + "[@name=\""+name+"\"]" ); for ( Iterator iterator = elementsList.iterator(); iterator.hasNext(); ) { Element currElem = ( Element )iterator.next(); Attribute type = currElem.attribute( "type" ); if ( type != null ) { StringTokenizer strtok = new StringTokenizer( type.getValue(), ":" ); if( strtok.countTokens() == 2 && strtok.nextToken().equals( namespacePrefix ) ) { return ( GwComplexType )getType( currElem, new Schema( "", "", _document ) ); } } } return null; } /** main parse method for translating object structure defined by schemas into application's internal data structure. Recursively builds the corresponding structure representing the XML derivation tree. @param element the XML-Element which is processed @param declSchema the schema in which the XML-Element ist declared @return Object */ private synchronized Object getType( Element element, Schema declSchema ) { Element elem = element; Attribute nameAttr = elem.attribute( "name" ); String name = ""; if ( nameAttr != null ) name = nameAttr.getValue(); String currChildElementName = elem.getName(); Attribute elementType = elem.attribute( "type" ); Document defDocument = null; Schema currDefSchema = declSchema; if ( elementType != null ) // element is referencing its type { String typeName = null; StringTokenizer strtok = new StringTokenizer( elementType.getValue(), ":" ); if ( strtok.countTokens() == 1 ) // declaration within the same schema, typedeclaration: type="typename" { defDocument = elem.getDocument(); } else if ( strtok.countTokens() == 2 ) // declaration in other schema, typedeclaration: type="SCHEMAPREFIX:typename" { currDefSchema = ( Schema )_schemaTable.get( strtok.nextToken() ); defDocument = currDefSchema.getDocument(); } else return null; typeName = strtok.nextToken(); Element complexBaseType = ( Element )defDocument.selectSingleNode( "//xsd:complexType[@name=\"" + typeName +"\"]" ); if ( complexBaseType != null ) // found a complex basetype { GwComplexType complexType; List elementList = complexBaseType.selectNodes( "//xsd:complexType[@name=\"" + typeName +"\"]/xsd:sequence/xsd:element" ); List attributeList = complexBaseType.selectNodes( "//xsd:complexType[@name=\"" + typeName +"\"]/xsd:attribute" ); if ( complexBaseType.selectSingleNode( "//xsd:complexType[@name=\"" + typeName +"\"]/xsd:annotation" ) == null ) //scalargroup { Element appinfoNode = ( Element )complexBaseType.selectSingleNode( "//xsd:complexType" + "[@name=\""+ typeName +"\"]/xsd:sequence/xsd:element[1]" + "/xsd:annotation/xsd:appinfo" ); Element oidNode = appinfoNode.element( "oid" ); complexType = new GwComplexType( typeName, name, new GwOID( oidNode.getText() ), false, currDefSchema.getLocation(), currDefSchema.getNamespacePrefix() ); } else //table { Element appinfoNode = ( Element )complexBaseType.selectSingleNode( "//xsd:complexType[@name=\"" + typeName +"\"]/xsd:annotation/xsd:appinfo" ); Element oidNode = appinfoNode.element( "oid" ); Element accessNode = appinfoNode.element( "maxAccess" ); Element statusNode = appinfoNode.element( "status" ); complexType = new GwComplexType( typeName, name, new GwOID( oidNode.getText() ), true, currDefSchema.getLocation(), currDefSchema.getNamespacePrefix() ); if ( accessNode != null ) { complexType.setMaxAccess( accessNode.getText() ); } if ( statusNode != null ) { complexType.setStatus( statusNode.getText() ); } } for ( Iterator elementIter = elementList.iterator(); elementIter.hasNext(); ) { Element curr = ( Element )elementIter.next(); complexType._typeElements.add( getType( curr, currDefSchema ) ); } for ( Iterator attributeIter = attributeList.iterator(); attributeIter.hasNext(); ) { Element curr = ( Element )attributeIter.next(); complexType._typeAttributes.add( getType( curr, currDefSchema ) ); } return complexType; } else // xsd:element, xsd:attribute or xsd:simpleType with derivation via type-attribute { if ( elem.getName().equals( "element" ) || elem.getName().equals( "attribute" ) ) { Element appinfoNode = null; Element oidNode = null; Element accessNode = null; Element statusNode = null; Attribute useAttr = null; try { appinfoNode = ( Element )elem.selectSingleNode( "//xsd:"+elem.getName() + "[@name=\""+ name +"\"]/xsd:annotation/xsd:appinfo" ); oidNode = appinfoNode.element( "oid" ); accessNode = appinfoNode.element( "maxAccess" ); statusNode = appinfoNode.element( "status" ); useAttr = elem.attribute( "use" ); } catch (NullPointerException e) { throw new NullPointerException("selectSingleNode: //xsd:"+elem.getName() + "[@name=\""+ name +"\"]/xsd:annotation/xsd:appinfo returned null:"+e.toString()); } GwElement gwElement = new GwElement( name, new GwOID( oidNode.getText() ), elem.getName().equals( "element" ) ); if ( accessNode != null ) { gwElement.setMaxAccess( accessNode.getText() ); } if ( statusNode != null ) { gwElement.setStatus( statusNode.getText() ); } if ( useAttr != null ) { gwElement.setUse( useAttr.getValue() ); } Element defSimpleType = ( Element )defDocument.selectSingleNode( "//xsd:simpleType[@name=\""+typeName+"\"]" ); gwElement.setAncestor( ( GwType )getType( defSimpleType, currDefSchema ) ); return gwElement; } if ( elem.getName().equals( "simpleType" ) ) { // simple types only derived via restriction } return null; } } else // element declares own simple type or is derived via restriction/list/union { GwElement gwElement = null; Element parentElement = null; if ( elem.getName().equals( "element" ) || elem.getName().equals( "attribute" ) ) { Element appinfoNode = ( Element )elem.selectSingleNode( "//xsd:"+elem.getName() + "[@name=\""+name+"\"]/xsd:annotation/xsd:appinfo" ); Element oidNode = appinfoNode.element( "oid" ); Element accessNode = appinfoNode.element( "maxAccess" ); Element statusNode = appinfoNode.element( "status" ); Attribute useAttr = elem.attribute( "use" ); gwElement = new GwElement( name, new GwOID( oidNode.getText() ), elem.getName().equals( "element" ) ); if ( accessNode != null ) { gwElement.setMaxAccess( accessNode.getText() ); } if ( statusNode != null ) { gwElement.setStatus( statusNode.getText() ); } if ( useAttr != null ) { gwElement.setUse( useAttr.getValue() ); } parentElement = elem; elem = ( Element )elem.selectSingleNode( "//xsd:"+elem.getName() + "[@name=\""+name+"\"]/xsd:simpleType" ); } if ( elem.getName().equals( "simpleType" ) )//|| gwElement != null ) { GwType simpleType = new GwType( name ); Element appInfo = null; //parse in display hint if ( gwElement != null ) { appInfo = ( Element )elem.selectSingleNode( "//xsd:"+parentElement.getName() + "[@name=\""+gwElement.getName()+"\"]/xsd:simpleType/xsd:annotation/xsd:appinfo" ); } else { appInfo = ( Element )elem.selectSingleNode( "//xsd:simpleType" + "[@name=\""+name+"\"]/xsd:annotation/xsd:appinfo" ); } if (appInfo != null) { Element displayHint = appInfo.element( "displayHint" ); if ( displayHint != null ) simpleType.setDisplayHint( displayHint.getText() ); } Element restrictionType; if ( gwElement != null ) { restrictionType = ( Element )elem.selectSingleNode( "//xsd:" + parentElement.getName()+"[@name=\""+gwElement.getName() + "\"]/xsd:simpleType/xsd:restriction" ); } else { restrictionType = ( Element )elem.selectSingleNode( "//xsd:simpleType" + "[@name=\""+name+"\"]/xsd:restriction" ); } if ( restrictionType != null ) { // parse in enumerations List enumerationList = restrictionType.elements( "enumeration" ); for ( Iterator enumIter = enumerationList.iterator(); enumIter.hasNext(); ) { Element enumElement = ( Element )enumIter.next(); Attribute valueAttr = enumElement.attribute( "value" ); String intVal = null; Element enumAppinfo = null; Element intValElement = null; if ( gwElement != null ) { enumAppinfo = ( Element )enumElement.selectSingleNode( "//xsd:" + parentElement.getName()+"[@name=\""+gwElement.getName() + "\"]/xsd:simpleType/xsd:restriction/xsd:enumeration[@value=\""+ valueAttr.getValue()+"\"]/xsd:annotation/xsd:appinfo" ); } else { enumAppinfo = ( Element )enumElement.selectSingleNode( "//xsd:simpleType" + "[@name=\""+name+"\"]/xsd:restriction/xsd:enumeration[@value=\"" + valueAttr.getValue()+"\"]/xsd:annotation/xsd:appinfo" ); } if ( enumAppinfo != null ) { intValElement = enumAppinfo.element( "intVal" ); } if ( intValElement != null ) intVal = intValElement.getText(); simpleType._enum.add( new EnumElement( valueAttr.getValue(), intVal ) ); } //parse in length-restrictions Element minLength = restrictionType.element( "minLength" ); Element maxLength = restrictionType.element( "maxLength" ); if ( minLength != null ) simpleType.setMinLength( minLength.attribute( "value" ).getValue() ); if ( maxLength != null ) simpleType.setMaxLength( maxLength.attribute( "value" ).getValue() ); //parse in value-restrictions Element minInclusive = restrictionType.element( "minInclusive" ); Element maxInclusive = restrictionType.element( "maxInclusive" ); if ( minInclusive != null ) simpleType.setMinInclusive( minInclusive.attribute( "value" ).getValue() ); if ( maxInclusive != null ) simpleType.setMaxInclusive( maxInclusive.attribute( "value" ).getValue() ); String baseType = restrictionType.attribute( "base" ).getValue(); StringTokenizer baseStrTok = new StringTokenizer( baseType, ":" ); if ( baseStrTok.countTokens() == 2 ) { String defPrefix = baseStrTok.nextToken(); if ( defPrefix.equals( "xsd" ) ) // end of recursion, this simpleType is derived of a schema-basetype { simpleType.setXsdBaseType( baseStrTok.nextToken() ); } else { Schema defSchema = ( Schema )_schemaTable.get( defPrefix ); Element simpleBaseType = ( Element )defSchema.getDocument().selectSingleNode( "//xsd:" + "simpleType[@name=\""+ baseStrTok.nextToken() +"\"]" ); simpleType._ancestors.add( getType( simpleBaseType, defSchema ) ); } if ( gwElement != null ) { gwElement.setAncestor( simpleType ); return gwElement; } else return simpleType; } else if ( baseStrTok.countTokens() == 1 ) { Element simpleBaseType = ( Element )declSchema.getDocument().selectSingleNode( "//xsd:" + "simpleType[@name=\""+ baseStrTok.nextToken() +"\"]" ); simpleType._ancestors.add( getType( simpleBaseType, declSchema ) ); if ( gwElement != null ) { gwElement.setAncestor( simpleType ); return gwElement; } else return simpleType; } else return null; } else // no restriction found: check for list- or union-derivation { Element unionType = null; if ( gwElement != null ) { unionType = ( Element )elem.selectSingleNode( "//xsd:" + parentElement.getName()+"[@name=\""+gwElement.getName() + "\"]/xsd:simpleType/xsd:union" ); } else { unionType = ( Element )elem.selectSingleNode( "//xsd:simpleType" + "[@name=\""+name+"\"]/xsd:union" ); } if ( unionType != null ) // union { StringTokenizer unionStrTok = new StringTokenizer( unionType.attribute( "memberTypes" ).getValue(), " " ); while ( unionStrTok.hasMoreTokens() ) { StringTokenizer baseStrTok = new StringTokenizer( unionStrTok.nextToken(), ":" ); if ( baseStrTok.countTokens() == 2 ) { String defPrefix = baseStrTok.nextToken(); if ( defPrefix.equals( "xsd" ) ) // end of recursion, this simpleType is derived of a schema-basetype { simpleType.setXsdBaseType( baseStrTok.nextToken() ); } else { Schema defSchema = ( Schema )_schemaTable.get( defPrefix ); Element simpleBaseType = ( Element )defSchema.getDocument().selectSingleNode( "//xsd:" + "simpleType[@name=\""+ baseStrTok.nextToken() +"\"]" ); simpleType._ancestors.add( getType( simpleBaseType, defSchema ) ); } } else if ( baseStrTok.countTokens() == 1 ) { Element simpleBaseType = ( Element )declSchema.getDocument().selectSingleNode( "//xsd:" + "simpleType[@name=\""+ baseStrTok.nextToken() +"\"]" ); simpleType._ancestors.add( getType( simpleBaseType, declSchema ) ); } } if ( gwElement != null ) { gwElement.setAncestor( simpleType ); return gwElement; } else return simpleType; } Element listType; if ( gwElement != null ) { listType = ( Element )elem.selectSingleNode( "//xsd:"+parentElement.getName() + "[@name=\""+gwElement.getName()+"\"]/xsd:simpleType/xsd:list" ); } else { listType = ( Element )elem.selectSingleNode( "//xsd:simpleType" + "[@name=\""+name+"\"]/xsd:list" ); } if ( listType != null ) // list { simpleType.setList( true ); StringTokenizer baseStrTok = new StringTokenizer( listType.attribute( "itemType" ).getValue(), ":" ); if ( baseStrTok.countTokens() == 2 ) { String defPrefix = baseStrTok.nextToken(); if ( defPrefix.equals( "xsd" ) ) // end of recursion, this simpleType is derived of a schema-basetype { simpleType.setXsdBaseType( baseStrTok.nextToken() ); } else { Schema defSchema = ( Schema )_schemaTable.get( defPrefix ); Element simpleBaseType = ( Element )defSchema.getDocument().selectSingleNode( "//xsd:" + "simpleType[@name=\""+ baseStrTok.nextToken() +"\"]" ); simpleType._ancestors.add( getType( simpleBaseType, defSchema ) ); } if ( gwElement != null ) { gwElement.setAncestor( simpleType ); return gwElement; } else return simpleType; } else if ( baseStrTok.countTokens() == 1 ) { Element simpleBaseType = ( Element )declSchema.getDocument().selectSingleNode( "//xsd:" + "simpleType[@name=\""+ baseStrTok.nextToken() +"\"]" ); simpleType._ancestors.add( getType( simpleBaseType, declSchema ) ); if ( gwElement != null ) { gwElement.setAncestor( simpleType ); return gwElement; } else return simpleType; } else return null; } } } } return null; } /** searches in the container-schema for all MIB-Objects with matching name. If found, builds the GwComplexType for all MIB-Objects by calling getType( Element element, Schema declSchema )This Method provides address' translation for get-requests. @param name the name of to be sarched MIB-Objects @return Vector results of the getType call as Objects. Because these results all represent MIB-Objects as found in the container-schema, it ist safe to cast them to GwComplexType */ public synchronized Vector getTypes( String name ) { Vector resultVector = new Vector(); debugstr += "
trying to resolve "+name+" from container-schema
"; List elementsList = _document.selectNodes( "/xsd:schema/xsd:element[@name=" + "\"snmp-data\"]/xsd:complexType/xsd:sequence/xsd:element[@name" + "=\"context\"]/xsd:complexType/xsd:sequence/xsd:element[@name=\""+name+"\"]" ); for ( Iterator iterator = elementsList.iterator(); iterator.hasNext(); ) { Element curr = ( Element )iterator.next(); debugstr += "
found element "+name+" in container-schema, " + "starting recursive getType
"; resultVector.add( getType( curr, new Schema( "", "", _document ) ) ); } return resultVector; } }