Web API Reference | MapGuide Open Source

- Overview
- Modules
- Classes

# Provider Capabilities
[Feature Service]

## Provider Capabilities

The MgFeatureService API delegates much of its functionality to FDO providers. The providers implement the storage and retrieval of feature data from a variety of RDBMS and file-based datastore technologies.

A set of provider capabilities has been defined, and each provider has been characterized according to what capabilities it supports. For example, the FDO Provider for Oracle supports the creation, description, and destruction of a schema definition, but the FDO Provider for ArcSDE supports only the description of a schema definition.

The capabilities are grouped in the following categories:

- Connection
- Schema
- Commands
- Expressions
- Filters
- Raster
- Topology

The MgFeatureService::GetCapabilities method returns an XML representation of a provider's capabilities. See FdoProviderCapabilities for the definition of the XML representation.

The capability characterization can be used to execute code conditionally depending on the provider being used and what capability is being executed.

## Example (C#)

The GetFeatureProviders method cyles through the list of provider names and creates a FeatureProvider object for each one.

The FeatureProvider constructor uses the MgFeatureService object to get the capabilities for the provider. The capabilities are in xml and the Extract methods use xpath expressions to extract the capability values from the xml.

The utility methods show the use of System Xml classes to extract values from the xml.

Here are a few of the capability strings generated by this code for the SDF provider.

- ConnectionCapabilities:ThreadCapability=PerConnectionThreaded;SpatialContextExtentType=Dynamic;
- CommandCapabilities:Commands=+Select+Insert+Delete+Update+DescribeSchema+ApplySchema+CreateSpatialContext+GetSpatialContexts+SelectAggregates;SelectExpressions;SelectFunctions;SelectDistinct;
- SchemaCapabilities:ClassType=+Class+FeatureClass;DataType=+Boolean+Byte+DateTime+Decimal+Double+Int16+Int32+Int64+Single+String;Inheritance;AssociationProperties;AutoIdGeneration;SupportedAutoGeneratedTypes=+Int32;SchemaModification;
- GeometryCapabilities:GeometryTypes=+Point+LineString+Polygon+MultiPoint+MultiLineString+MultiPolygon+MultiGeometry+CurveString+CurvePolygon+MultiCurveString+MultiCurvePolygon;ComponentType=+LinearRing+ArcSegment+LinearSegment+CurveRing;Dimensionality=XYZM;
- FilterCapabilities:ConditionType=+Comparison+Like+In+Null+Spatial;SpatialOperation=+Contains+Disjoint+Intersects+Within+Inside+EnvelopeIntersects;DistanceOperation=;
- ExpressionCapabilities:ExpressionType=+Basic+Function;FunctionDefinitions=+Concat+SpatialExtents+Ceil+Floor+Lower+Upper+Sum+Count+Min+Avg+Max;

    using OSGeo.MapGuide;
    // The MgFeatureService example code shows how the MgFeatureService object is created.
    private MgFeatureService featureService;
    private String providerNamesActual;
    private ListDictionary featureProviders;

    private void GetProviderNames()
    {
    	System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo(0x0409);
    	String[] names;
    	MgByteReader byteReader = featureService.GetFeatureProviders();
    	String xmlContent = byteReader.ToString();
    	names = GetXpathValuesRtnStrArr(xmlContent,
    		"//FeatureProviderRegistry/FeatureProvider/Name");
    	providerCountActual = names.GetLength(0);
    	Array.Sort(names, StringComparer.Create(culture, false));
    	providerNamesActual = StringArrayToString(names);
    }

    private void GetFeatureProviders()
    {
    	featureProviders = new ListDictionary();
    	FeatureProvider featureProvider;
    	String providerName;
    	string[] names = providerNamesActual.Split();
    	for (int i = 0; i < providerCountActual; i++)
    	{
    		providerName = names[i];
    		featureProvider = new FeatureProvider(logger, providerName,
    			featureService, utilities, timings);
    		featureProviders.Add(providerName, featureProvider);
    	}
    }

    class FeatureProvider
    {
    	public FeatureProvider(...
    		MgFeatureService featureService,
    		Utilities utilities,
    		...)
    	{
    		...
    		MgByteReader byteReader = featureService.GetCapabilities(providerName);
            xmlContent = byteReader.ToString();
            ExtractConnectionCapabilities();
            ExtractSchemaCapabilities();
            ExtractCommandCapabilities();
            ExtractFilterCapabilities();
            ExtractExpressionCapabilities();
            ExtractRasterCapabilities();
            ExtractTopologyCapabilities();
            ExtractGeometryCapabilities();
        }
        private MgFeatureService featureService;
        private String xmlContent;
        private String connectionCapabilitiesToStr;
        private String schemaCapabilitiesToStr;
        private String commandCapabilitiesToStr;
        private String filterCapabilitiesToStr;
        private String expressionCapabilitiesToStr;
        private String rasterCapabilitiesToStr;
        private String topologyCapabilitiesToStr;
        private String geometryCapabilitiesToStr;
        private StringBuilder sb;
        private const int sblength = 640;
        private Boolean multipleSchema;

    	// public property declarations to expose capability strings

    	private void ExtractConnectionCapabilities()
    	{
    		sb = new StringBuilder(sblength);
    		sb.Append("ConnectionCapabilities:");
    		String ThreadCapability = utilities.GetXpathValuesRtnStr(xmlContent, "Connection/ThreadCapability");
    		sb.Append("ThreadCapability=" + ThreadCapability + ';');
    		String SpatialContextExtentType = utilities.GetXpathValuesRtnStr(xmlContent, "Connection/SpatialContextExtent/Type");
    		sb.Append("SpatialContextExtentType=" + SpatialContextExtentType + ';');
    		String SupportsLocking = utilities.GetXpathValuesRtnStr(xmlContent, "Connection/SupportsLocking");
    		if (SupportsLocking.Equals("true"))
    		{
    			sb.Append("Locking;");
    		}
    		String SupportsTimeout = utilities.GetXpathValuesRtnStr(xmlContent, "Connection/SupportsTimeout");
    		if (SupportsTimeout.Equals("true"))
    		{
    			sb.Append("Timeout;");
    		}
    		String SupportsTransactions = utilities.GetXpathValuesRtnStr(xmlContent, "Connection/SupportsTransactions");
    		if (SupportsTransactions.Equals("true"))
    		{
    			sb.Append("Transactions;");
    		}
    		String SupportsLongTransactions = utilities.GetXpathValuesRtnStr(xmlContent, "Connection/SupportsLongTransactions");
    		if (SupportsLongTransactions.Equals("true"))
    		{
    			sb.Append("LongTransactions;");
    		}
    		String SupportsSQL = utilities.GetXpathValuesRtnStr(xmlContent, "Connection/SupportsSQL");
    		if (SupportsSQL.Equals("true"))
    		{
    			sb.Append("SQL;");
    		}
    		String SupportsConfiguration = utilities.GetXpathValuesRtnStr(xmlContent, "Connection/SupportsConfiguration");
    		if (SupportsConfiguration.Equals("true"))
    		{
    			sb.Append("Configuration;");
    		}
    		connectionCapabilitiesToStr = sb.ToString();
    	}
    	private void ExtractSchemaCapabilities()
    	{
    		String value;
    		sb = new StringBuilder(sblength);
    		sb.Append("SchemaCapabilities:");
    		MgStringCollection ClassType = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Schema/Class/Type");
    		sb.Append("ClassType=");
    		int classCount = ClassType.GetCount();
    		for (int i = 0; i < classCount; i++)
    		{
    			sb.Append("+" + ClassType.GetItem(i));
    		}
    		sb.Append(";");
    		MgStringCollection DataType = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Schema/Data/Type");
    		sb.Append("DataType=");
    		int dataCount = DataType.GetCount();
    		for (int i = 0; i < dataCount; i++)
    		{
    			sb.Append("+" + DataType.GetItem(i));
    		}
    		sb.Append(";");
    		String SupportsInheritance = utilities.GetXpathValuesRtnStr(xmlContent, "Schema/SupportsInheritance");
    		if (SupportsInheritance.Equals("true"))
    		{
    			sb.Append("Inheritance;");
    		}
    		String SupportsMultipleSchemas = utilities.GetXpathValuesRtnStr(xmlContent, "Schema/SupportsMultipleSchemas");
    		if (SupportsMultipleSchemas.Equals("true"))
    		{
    			sb.Append("MultipleSchemas;");
    			multipleSchema = true;
    		}
    		else
    		{
    			multipleSchema = false;
    		}
    		String SupportsObjectProperties = utilities.GetXpathValuesRtnStr(xmlContent, "Schema/SupportsObjectProperties");
    		if (SupportsObjectProperties.Equals("true"))
    		{
    			sb.Append("ObjectProperties;");
    		}
    		String SupportsAssociationProperties = utilities.GetXpathValuesRtnStr(xmlContent, "Schema/SupportsAssociationProperties");
    		if (SupportsAssociationProperties.Equals("true"))
    		{
    			sb.Append("AssociationProperties;");
    		}
    		String SupportsSchemaOverrides = utilities.GetXpathValuesRtnStr(xmlContent, "Schema/SupportsSchemaOverrides");
    		if (SupportsSchemaOverrides.Equals("true"))
    		{
    			sb.Append("SchemaOverrides;");
    		}
    		String SupportsNetworkModel = utilities.GetXpathValuesRtnStr(xmlContent, "Schema/SupportsNetworkModel");
    		if (SupportsNetworkModel.Equals("true"))
    		{
    			sb.Append("NetworkModel;");
    		}
    		String SupportsAutoIdGeneration = utilities.GetXpathValuesRtnStr(xmlContent, "Schema/SupportsAutoIdGeneration");
    		if (SupportsAutoIdGeneration.Equals("true"))
    		{
    			sb.Append("AutoIdGeneration;");
    		}
    		String SupportsDataStoreUniqueIdGeneration = utilities.GetXpathValuesRtnStr(xmlContent, "Schema/SupportsDataStoreUniqueIdGeneration");
    		if (SupportsDataStoreUniqueIdGeneration.Equals("true"))
    		{
    			sb.Append("DataStoreUniqueIdGeneration;");
    		}
    		MgStringCollection SupportedAutoGeneratedTypes = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Schema/SupportedAutoGeneratedTypes/Type");
    		sb.Append("SupportedAutoGeneratedTypes=");
    		int autoGenTypeCount = SupportedAutoGeneratedTypes.GetCount();
    		for (int i = 0; i < autoGenTypeCount; i++)
    		{
    			value = SupportedAutoGeneratedTypes.GetItem(i);
    			if (value != "")
    			{
    				sb.Append("+" + value);
    			}
    		}
    		sb.Append(";");
    		String SupportsSchemaModification = utilities.GetXpathValuesRtnStr(xmlContent, "Schema/SupportsSchemaModification");
    		if (SupportsSchemaModification.Equals("true"))
    		{
    			sb.Append("SchemaModification;");
    		}
    		schemaCapabilitiesToStr = sb.ToString();
    	}
    	private void ExtractCommandCapabilities()
    	{
    		sb = new StringBuilder(sblength);
    		sb.Append("CommandCapabilities:");
    		MgStringCollection Commands = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Command/SupportedCommands/Name");
    		sb.Append("Commands=");
    		int cmdCount = Commands.GetCount();
    		for (int i = 0; i < cmdCount; i++)
    		{
    			sb.Append("+" + Commands.GetItem(i));
    		}
    		sb.Append(";");
    		String SupportsParameters = utilities.GetXpathValuesRtnStr(xmlContent, "Command/SupportsParameters");
    		if (SupportsParameters.Equals("true"))
    		{
    			sb.Append("Parameters;");
    		}
    		String SupportsTimeout = utilities.GetXpathValuesRtnStr(xmlContent, "Command/SupportsTimeout");
    		if (SupportsTimeout.Equals("true"))
    		{
    			sb.Append("Timeout;");
    		}
    		String SupportsSelectExpressions = utilities.GetXpathValuesRtnStr(xmlContent, "Command/SupportsSelectExpressions");
    		if (SupportsSelectExpressions.Equals("true"))
    		{
    			sb.Append("SelectExpressions;");
    		}
    		String SupportsSelectFunctions = utilities.GetXpathValuesRtnStr(xmlContent, "Command/SupportsSelectFunctions");
    		if (SupportsSelectFunctions.Equals("true"))
    		{
    			sb.Append("SelectFunctions;");
    		}
    		String SupportsSelectDistinct = GetXpathValuesRtnStr(xmlContent, "Command/SupportsSelectDistinct");
    		if (SupportsSelectDistinct.Equals("true"))
    		{
    			sb.Append("SelectDistinct;");
    		}
    		String SupportsSelectOrdering = utilities.GetXpathValuesRtnStr(xmlContent, "Command/SupportsSelectOrdering");
    		if (SupportsSelectOrdering.Equals("true"))
    		{
    			sb.Append("SelectOrdering;");
    		}
    		String SupportsSelectGrouping = utilities.GetXpathValuesRtnStr(xmlContent, "Command/SupportsSelectGrouping");
    		if (SupportsSelectGrouping.Equals("true"))
    		{
    			sb.Append("SelectGrouping;");
    		}
    		commandCapabilitiesToStr = sb.ToString();
    	}
    	private void ExtractFilterCapabilities()
    	{
    		String value;
    		sb = new StringBuilder(sblength);
    		sb.Append("FilterCapabilities:");
    		MgStringCollection ConditionType = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Filter/Condition/Type");
    		sb.Append("ConditionType=");
    		int conditionCount = ConditionType.GetCount();
    		for (int i = 0; i < conditionCount; i++)
    		{
    			value = ConditionType.GetItem(i);
    			if (value != "")
    			{
    				sb.Append("+" + value);
    			}
    		}
    		sb.Append(";");
    		MgStringCollection SpatialOperation = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Filter/Spatial/Operation");
    		sb.Append("SpatialOperation=");
    		int spatialOpCount = SpatialOperation.GetCount();
    		for (int i = 0; i < spatialOpCount; i++)
    		{
    			value = SpatialOperation.GetItem(i);
    			if (value != "")
    			{
    				sb.Append("+" + value);
    			}
    		}
    		sb.Append(";");
    		MgStringCollection DistanceOperation = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Filter/Distance/Operation");
    		sb.Append("DistanceOperation=");
    		int distanceOpCount = DistanceOperation.GetCount();
    		for (int i = 0; i < distanceOpCount; i++)
    		{
    			value = DistanceOperation.GetItem(i);
    			if (value != "")
    			{
    				sb.Append("+" + value);
    			}
    		}
    		sb.Append(";");
    		String SupportsGeodesicDistance = utilities.GetXpathValuesRtnStr(xmlContent, "Filter/SupportsGeodesicDistance");
    		if (SupportsGeodesicDistance.Equals("true"))
    		{
    			sb.Append("GeodesicDistance;");
    		}
    		String SupportsNonLinearGeometricOperations = utilities.GetXpathValuesRtnStr(xmlContent, "Filter/SupportsNonLinearGeometricOperations");
    		if (SupportsNonLinearGeometricOperations.Equals("true"))
    		{
    			sb.Append("NonLinearGeometricOperations;");
    		}
    		filterCapabilitiesToStr = sb.ToString();
    	}
    	private void ExtractExpressionCapabilities()
    	{
    		String value;
    		sb = new StringBuilder(sblength);
    		sb.Append("ExpressionCapabilities:");
    		MgStringCollection ExpressionType = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Expression/Type/Name");
    		sb.Append("ExpressionType=");
    		int typeCount = ExpressionType.GetCount();
    		for (int i = 0; i < typeCount; i++)
    		{
    			sb.Append("+" + ExpressionType.GetItem(i));
    		}
    		sb.Append(";");
    		MgStringCollection FunctionDefinitions = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Expression/FunctionDefinitionCollection/FunctionDefinition/Name");
    		sb.Append("FunctionDefinitions=");
    		int functionCount = FunctionDefinitions.GetCount();
    		for (int i = 0; i < functionCount; i++)
    		{
    			value = FunctionDefinitions.GetItem(i);
    			if (value != "")
    			{
    				sb.Append("+" + value);
    			}
    		}
    		sb.Append(";");
    		expressionCapabilitiesToStr = sb.ToString();
    	}
    	private void ExtractRasterCapabilities()
    	{
    		sb = new StringBuilder(sblength);
    		sb.Append("RasterCapabilities:");
    		String SupportsRaster = utilities.GetXpathValuesRtnStr(xmlContent, "Raster/SupportsRaster");
    		if (SupportsRaster.Equals("true"))
    		{
    			sb.Append("Raster;");
    		}
    		String SupportsStitching = utilities.GetXpathValuesRtnStr(xmlContent, "Raster/SupportsStitching");
    		if (SupportsStitching.Equals("true"))
    		{
    			sb.Append("Stitching;");
    		}
    		String SupportsSubsmpling = utilities.GetXpathValuesRtnStr(xmlContent, "Raster/SupportsSubsmpling");
    		if (SupportsSubsmpling.Equals("true"))
    		{
    			sb.Append("Subsmpling;");
    		}
    		rasterCapabilitiesToStr = sb.ToString();
    	}
    	private void ExtractTopologyCapabilities()
    	{
    		sb = new StringBuilder(sblength);
    		sb.Append("TopologyCapabilities:");
    		String SupportsTopology = utilities.GetXpathValuesRtnStr(xmlContent, "Topology/SupportsTopology");
    		if (SupportsTopology.Equals("true"))
    		{
    			sb.Append("Topology;");
    		}
    		String SupportsTopologicalHierarchy = utilities.GetXpathValuesRtnStr(xmlContent, "Topology/SupportsTopologicalHierarchy");
    		if (SupportsTopologicalHierarchy.Equals("true"))
    		{
    			sb.Append("TopologicalHierarchy;");
    		}
    		String BreaksCurveCrossingsAutomatically = utilities.GetXpathValuesRtnStr(xmlContent, "Topology/BreaksCurveCrossingsAutomatically");
    		if (BreaksCurveCrossingsAutomatically.Equals("true"))
    		{
    			sb.Append("BreaksCurveCrossingsAutomatically;");
    		}
    		String ActivatesTopologyByArea = utilities.GetXpathValuesRtnStr(xmlContent, "Topology/ActivatesTopologyByArea");
    		if (ActivatesTopologyByArea.Equals("true"))
    		{
    			sb.Append("ActivatesTopologyByArea;");
    		}
    		String ConstrainsFeatureMovements = utilities.GetXpathValuesRtnStr(xmlContent, "Topology/ConstrainsFeatureMovements");
    		if (ConstrainsFeatureMovements.Equals("true"))
    		{
    			sb.Append("ConstrainsFeatureMovements;");
    		}
    		topologyCapabilitiesToStr = sb.ToString();
    	}
    	private void ExtractGeometryCapabilities()
    	{
    		sb = new StringBuilder(sblength);
    		sb.Append("GeometryCapabilities:");
    		MgStringCollection GeometryTypes = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Geometry/Types/Type");
    		sb.Append("GeometryTypes=");
    		int geomTypeCount = GeometryTypes.GetCount();
    		for (int i = 0; i < geomTypeCount; i++)
    		{
    			sb.Append("+" + GeometryTypes.GetItem(i));
    		}
    		sb.Append(";");
    		MgStringCollection ComponentType = utilities.GetXpathValuesRtnMgStrColl(xmlContent, "Geometry/Components/Type");
    		sb.Append("ComponentType=");
    		int compTypeCount = ComponentType.GetCount();
    		for (int i = 0; i < compTypeCount; i++)
    		{
    			sb.Append("+" + ComponentType.GetItem(i));
    		}
    		sb.Append(";");
    		String Dimensionality = utilities.GetXpathValuesRtnStr(xmlContent, "Geometry/Dimensionality");
    		sb.Append("Dimensionality=" + MgCoordinateDimensionToStr(Convert.ToInt32(Dimensionality)) + ';');
    		geometryCapabilitiesToStr = sb.ToString();
    	}
    }

    public String[] GetXpathValuesRtnStrArr(String xmlContent, String xpath)
    {
    	System.Collections.ArrayList strList = new System.Collections.ArrayList(10);
    	String[] strArr;
    	System.Xml.XmlDocument xmlDocument = new XmlDocument();
    	xmlDocument.LoadXml(xmlContent);
    	XmlNodeList nodeList;
    	XmlElement root = xmlDocument.DocumentElement;
    	nodeList = root.SelectNodes(xpath);
    	int count = nodeList.Count;
    	if (count == 0)
    	{
    		strArr = new String[] { "" };
    		return strArr;
    	}
    	XmlNode node;
    	for (int i = 0; i < count; i++)
    	{
    		node = nodeList.Item(i);
    		strList.Add(node.FirstChild.Value);
    	}
    	strArr = (String[])strList.ToArray(typeof(string));
    	return strArr;
    }

    public String GetXpathValuesRtnStr(String xmlContent, String xpath)
    {
    	String value;
    	System.Xml.XmlDocument xmlDocument = new XmlDocument();
    	xmlDocument.LoadXml(xmlContent);
    	XmlElement root = xmlDocument.DocumentElement;
    	XmlNode node;
    	node = root.SelectSingleNode(xpath);
    	if (node == null)
    	{
    		value = "";
    		return value;
    	}
    	value = node.FirstChild.Value;
    	return value;
    }

    public MgStringCollection GetXpathValuesRtnMgStrColl(String xmlContent, String xpath)
    {
    	MgStringCollection strings = new MgStringCollection();
    	System.Xml.XmlDocument xmlDocument = new XmlDocument();
    	xmlDocument.LoadXml(xmlContent);
    	XmlNodeList nodeList;
    	XmlElement root = xmlDocument.DocumentElement;
    	nodeList = root.SelectNodes(xpath);
    	int count = nodeList.Count;
    	if (count == 0)
    	{
    		strings.Add("");
    		return strings;
    	}
    	XmlNode node;
    	for (int i = 0; i < count; i++)
    	{
    		node = nodeList.Item(i);
    		strings.Add(node.FirstChild.Value);
    	}
    	return strings;
    }

## Capabilities for Autodesk.Oracle.2.0

What follows is a sample output from a PHP program used to get the capabilities for the Oracle provider. The program code follows the sample output. This program does the following:

- parses the XML returned by MgFeatureService::GetCapabilities()
- implements a set of boolean capability functions
- prints the values of the functions

    Connection
        ThreadCapability
            supportsSingleThreaded(): false
            supportsPerConnectionThreaded(): true
            supportsPerCommandThreaded(): false
            supportsMultiThreaded(): false
        SpatialContextExtent
            Type
                supportsDynamic(): false
                supportsStatic(): true
        supportsLocking(): true
        supportsConnectionTimeout(): false
        supportsTransactions(): true
        supportsLongTransactions(): true
        supportsSQL(): true
        supportsConfiguration(): false
    Schema
        Class
            Type
                supportsClass(): true
                supportsFeatureClass(): true
        Data
            Type
                supportsBoolean(): true
                supportsByte(): true
                supportsDateTime(): true
                supportsDecimal(): true
                supportsDouble(): true
                supportsInt16(): true
                supportsInt32(): true
                supportsInt64(): true
                supportsSingle(): true
                supportsString(): true
                supportsBLOB(): true
                supportsCLOB(): true
                supportsUniqueID(): false
        supportsInheritance(): true
        supportsMultipleSchemas(): true
        supportsObjectProperties(): true
        supportsAssociationProperties(): true
        supportsSchemaOverrides(): true
        supportsNetworkModel(): false
        supportsAutoIdGeneration(): true
        supportsDataStoreScopeUniqueIdGeneration(): true
        supportsSchemaModification(): true
    Command
        SupportedCommands
            Name
                supportsSelect(): true
                supportsInsert(): true
                supportsDelete(): true
                supportsUpdate(): true
                supportsSelectAggregates(): true
                supportsDescribeSchema(): true
                supportsDescribeSchemaMapping(): false
                supportsDestroySchema(): true
                supportsApplySchema(): true
                supportsActivateSpatialContext(): true
                supportsCreateSpatialContext(): true
                supportsDestroySpatialContext(): true
                supportsDestroySpatialContext(): true
                supportsCreateMeasureUnit(): false
                supportsDestroyMeasureUnit()t: false
                supportsGetMeasureUnits(): false
                supportsSQLCommand(): true
                supportsAcquireLock(): true
                supportsGetLockInfo(): true
                supportsGetLockedObjects(): true
                supportsGetLockOwners(): true
                supportsReleaseLock(): true
                supportsActivateLongTransaction(): true
                supportsCommitLongTransaction(): true
                supportsCreateLongTransaction(): true
                supportsGetLongTransactions(): true
                supportsFreezeLongTransaction(): false
                supportsRollbackLongTransaction(): true
                supportsActivateLongTransactionCheckpoint(): false
                supportsCreateLongTransactionCheckpoint(): false
                supportsGetLongTransactionCheckpoints(): false
                supportsRollbackLongTransactionCheckpoint(): false
                supportsChangeLongTransactionPrivileges(): false
                supportsGetLongTransactionPrivileges(): false
                supportsChangeLongTransactionSet(): false
                supportsGetLongTransactionsInSet(): false
                supportsFirstProviderCommand(): false
                supportsDeactivateLongTransaction(): true
        supportsParameters(): false
        supportsCommandTimeout(): false
        supportsSelectExpressions(): true
        supportsSelectFunctions(): true
        supportsSelectDistinct(): true
        supportsSelectOrdering(): true
        supportsSelectGrouping(): true
    Filter
        Condition
            Type
                supportsComparison(): true
                supportsLike(): true
                supportsIn(): true
                supportsNull(): true
                supportsSpatial(): true
                supportsDistance(): true
        Spatial
            Operation
                supportsContains(): false
                supportsCrosses(): false
                supportsDisjoint(): false
                supportsEquals(): false
                supportsIntersects(): true
                supportsOverlaps()s: false
                supportsTouches(): false
                supportsSpatialWithin(): false
                supportsCoveredBy(): true
                supportsInside(): true
                supportsEnvelopeIntersects(): true
        Distance
            Operation
                supportsDistanceWithin(): true
                supportsBeyond(): false
        supportsGeodesicDistance(): false
        supportsNonLiteralGeometricOperations(): false
    Expression
        Type
            Name
                supportsBasic(): true
                supportsFunction(): true
                supportsParameter(): true
        FunctionDefinitionCollection
            FunctionDefinition
                Name
                    supportsAvg(): true
                    supportsCeil(): true
                    supportsCLIP(): false
                    supportsConcat(): true
                    supportsCount(): true
                    supportsFloor(): true
                    supportsLower(): true
                    supportsMax(): true
                    supportsMin(): true
                    supportsMOSAIC(): false
                    supportsStdDev(): false
                    supportsSum(): true
                    supportsUpper(): true
    Raster
        supportsRaster(): false
        supportsStitching(): false
        supportsSubsampling(): false
    Topology
        supportsTopology(): false
        supportsTopologicalHierarchy(): false
        supportsBreaksCurveCrossingsAutomatically(): false
        supportsActivatesTopologyByArea(): false
        supportsConstrainsFeatureMovements(): false
    Geometry
        Type
            supportsPoint(): true
            supportsMultiPoint(): true
            supportsLineString(): true
            supportsMultiLineString(): true
            supportsPolygon(): true
            supportsMultiPolygon(): true
            supportsCurveString(): true
            supportsMultiCurveString(): true
            supportsCurvePolygon(): true
            supportsMultiCurvePolygon(): true
            supportsMultiGeometry(): false
        Components
            Type
                supportsLinearRing(): true
                supportsLinearSegment(): true
                supportsArcSegment(): true
                supportsCurveRing(): true
        dimensionality(): 3

## PHP Example Code

This code does the following:

- parses the XML returned by MgFeatureService::GetCapabilities()
- implements a set of boolean capability functions
- prints the values of the functions

The constructor takes a provider name, a file handle, and an MgByteReader containing the provider capabilities. The provider name is obtained from MgFeatureService::GetFeatureProviders. The provider capabilities is obtained from MgFeatureService::GetCapabilities. The file handle is for logging.

    class ProviderCapabilities {
       var $logFileHandle;
       var $xpath;
       var $providerName;

       function ProviderCapabilities( $providerName, $logFileHandle, $byteReader ) {
          try {
         $this->providerName = $providerName;
         $this->logFileHandle = $logFileHandle;
         $doc = new DOMDocument();
         $byteSink = new MgByteSink($byteReader);
         $filePath = "temp_byte_reader_file.$providerName";
    //     fwrite($this->logFileHandle, "file path is \"$filePath\"\n");
         $byteSink->ToFile($filePath);
         $doc->load($filePath);
    //     unlink($filePath);
         $this->xpath = new DOMXPath($doc);
         $this->queryConnection();
         $this->querySchema();
         $this->queryCommand();
         $this->queryFilter();
         $this->queryExpression();
         $this->queryRaster();
         $this->queryTopology();
         $this->queryGeometry();
          } catch (Exception $e) {
         $msg = $e->GetMessage();
         fwrite($logFileHandle, "ProviderCapabilities PHP Exception: $msg\n");
          }
       }

       function prtBool($bool) {
          if ($bool) {
         return "true";
          } else {
         return "false";
          }
       }

       function queryBooleanElement($queryExpr, &$reference) {
          $domNodeList = $this->xpath->query($queryExpr);
          if ($domNodeList->length == 0) return;
          $domNode = $domNodeList->item(0);
          $value = $domNode->nodeValue;
          switch($value) {
         case "true" : $reference = TRUE; break;
         case "false" : $reference = FALSE; break;
         default : fwrite($this->logFileHandle, "queryExprunknown value:
    value\n");
          }
       }

    /*
       var $supports = FALSE;
       function supports() {
          return $this->supports;
       }
    \*/

       // CONNECTION CAPABILITIES
       // thread capability

       var $supportsSingleThreaded = FALSE;
       function supportsSingleThreaded() {
          return $this->supportsSingleThreaded;
       }

       var $supportsPerConnectionThreaded = FALSE;
       function supportsPerConnectionThreaded() {
          return $this->supportsPerConnectionThreaded;
       }

       var $supportsPerCommandThreaded = FALSE;
       function supportsPerCommandThreaded() {
          return $this->supportsPerCommandThreaded;
       }

       var $supportsMultiThreaded = FALSE;
       function supportsMultiThreaded() {
          return $this->supportsMultiThreaded;
       }

       // spatial context extent type

       var $supportsDynamic = FALSE;
       function supportsDynamic() {
          return $this->supportsDynamic;
       }

       var $supportsStatic = FALSE;
       function supportsStatic() {
          return $this->supportsStatic;
       }

       // rest of connection capabilities
       var $supportsLocking = FALSE;
       function supportsLocking() {
          return $this->supportsLocking;
       }

       var $supportsConnectionTimeout = FALSE;
       function supportsConnectionTimeout() {
          return $this->supportsConnectionTimeout;
       }

       var $supportsTransactions = FALSE;
       function supportsTransactions() {
          return $this->supportsTransactions;
       }

       var $supportsLongTransactions = FALSE;
       function supportsLongTransactions() {
          return $this->supportsLongTransactions;
       }

       var $supportsSQL = FALSE;
       function supportsSQL() {
          return $this->supportsSQL;
       }

       var $supportsConfiguration = FALSE;
       function supportsConfiguration() {
          return $this->supportsConfiguration;
       }

       function queryConnection() {
          $this->queryThreadCapability();
          $this->querySpatialContextExtentType();
          $this->queryBooleanElement("//FeatureProviderCapabilities/Connection/SupportsLocking", $this->supportsLocking);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Connection/SupportsTimeout", $this->supportsConnectionTimeout);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Connection/SupportsTransactions", $this->supportsTransactions);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Connection/SupportsLongTransactions", $this->supportsLongTransactions);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Connection/SupportsSQL", $this->supportsSQL);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Connection/SupportsConfiguration", $this->supportsConfiguration);
       }

       function queryThreadCapability() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Connection/ThreadCapability");
          if ($domNodeList->length == 0) return;
          $domNode = $domNodeList->item(0);
          $value = $domNode->nodeValue;
          switch($value) {
         case "PerConnectionThreaded" : $this->supportsPerConnectionThreaded = TRUE; break;
         case "SingleThreaded" : $this->supportsSingleThreaded = TRUE; break;
         case "PerCommandThreaded" : $this->supportsPerCommandThreaded = TRUE; break;
         case "MultiThreaded" : $this->supportsMultiThreaded = TRUE; break;
         default : fwrite($this->logFileHandle, "unknown thread type: $value\n");
          }
       }

       function querySpatialContextExtentType() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Connection/SpatialContextExtent/Type");
          if ($domNodeList->length == 0) return;
          $domNode = $domNodeList->item(0);
          $value = $domNode->nodeValue;
          switch($value) {
         case "Static" : $this->supportsStatic = TRUE; break;
         case "Dynamic" : $this->supportsDynamic = TRUE; break;
         default : fwrite($this->logFileHandle, "unknown spatial context extent type: $value\n");
          }
       }

       // SCHEMA
       // class type
       var $supportsFeatureClass = FALSE;
       function supportsFeatureClass() {
          return $this->supportsFeatureClass;
       }

       var $supportsClass = FALSE;
       function supportsClass() {
          return $this->supportsClass;
       }

       // data types
       var $supportsBoolean = FALSE;
       function supportsBoolean() {
          return $this->supportsBoolean;
       }

       var $supportsByte = FALSE;
       function supportsByte() {
          return $this->supportsByte;
       }

       var $supportsDateTime = FALSE;
       function supportsDateTime() {
          return $this->supportsDateTime;
       }

       var $supportsDecimal = FALSE;
       function supportsDecimal() {
          return $this->supportsDecimal;
       }

       var $supportsDouble = FALSE;
       function supportsDouble() {
          return $this->supportsDouble;
       }

       var $supportsInt16 = FALSE;
       function supportsInt16() {
          return $this->supportsInt16;
       }

       var $supportsInt32 = FALSE;
       function supportsInt32() {
          return $this->supportsInt32;
       }

       var $supportsInt64 = FALSE;
       function supportsInt64() {
          return $this->supportsInt64;
       }

       var $supportsSingle = FALSE;
       function supportsSingle() {
          return $this->supportsSingle;
       }

       var $supportsString = FALSE;
       function supportsString() {
          return $this->supportsString;
       }

       var $supportsBLOB = FALSE;
       function supportsBLOB() {
          return $this->supportsBLOB;
       }

       var $supportsCLOB = FALSE;
       function supportsCLOB() {
          return $this->supportsCLOB;
       }

       var $supportsUniqueID = FALSE;
       function supportsUniqueID() {
          return $this->supportsUniqueID;
       }

       // rest of schema

       var $supportsInheritance = FALSE;
       function supportsInheritance() {
          return $this->supportsInheritance;
       }

       var $supportsMultipleSchemas = FALSE;
       function supportsMultipleSchemas() {
          return $this->supportsMultipleSchemas;
       }

       var $supportsObjectProperties = FALSE;
       function supportsObjectProperties() {
          return $this->supportsObjectProperties;
       }

       var $supportsAssociationProperties = FALSE;
       function supportsAssociationProperties() {
          return $this->supportsAssociationProperties;
       }

       var $supportsSchemaOverrides = FALSE;
       function supportsSchemaOverrides() {
          return $this->supportsSchemaOverrides;
       }

       var $supportsNetworkModel = FALSE;
       function supportsNetworkModel() {
          return $this->supportsNetworkModel;
       }

       var $supportsAutoIdGeneration = FALSE;
       function supportsAutoIdGeneration() {
          return $this->supportsAutoIdGeneration;
       }

       var $supportsDataStoreScopeUniqueIdGeneration = FALSE;
       function supportsDataStoreScopeUniqueIdGeneration() {
          return $this->supportsDataStoreScopeUniqueIdGeneration;
       }

       var $supportsSchemaModification = FALSE;
       function supportsSchemaModification() {
          return $this->supportsSchemaModification;
       }

       function querySchema() {
          $this->queryClassTypes();
          $this->queryDataTypes();
          $this->queryBooleanElement("//FeatureProviderCapabilities/Schema/SupportsInheritance", $this->supportsInheritance);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Schema/SupportsMultipleSchemas", $this->supportsMultipleSchemas);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Schema/SupportsObjectProperties", $this->supportsObjectProperties);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Schema/SupportsAssociationProperties", $this->supportsAssociationProperties);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Schema/SupportsSchemaOverrides", $this->supportsSchemaOverrides);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Schema/SupportsNetworkModel", $this->supportsNetworkModel);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Schema/SupportsAutoIdGeneration", $this->supportsAutoIdGeneration);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Schema/SupportsDataStoreScopeUniqueIdGeneration", $this->supportsDataStoreScopeUniqueIdGeneration);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Schema/SupportsSchemaModification", $this->supportsSchemaModification);
       }

       function queryClassTypes() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Schema/Class/Type");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "Class" : $this->supportsClass = TRUE; break;
            case "FeatureClass" : $this->supportsFeatureClass = TRUE; break;
            default : fwrite($this->logFileHandle, "unknown schema class type: $value\n");
         }
          }
       }

       function queryDataTypes() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Schema/Data/Type");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "Boolean" : $this->supportsBoolean = TRUE; break;
            case "Byte" : $this->supportsByte = TRUE; break;
            case "DateTime" : $this->supportsDateTime = TRUE; break;
            case "Decimal" : $this->supportsDecimal = TRUE; break;
            case "Double" : $this->supportsDouble = TRUE; break;
            case "Int16" : $this->supportsInt16 = TRUE; break;
            case "Int32" : $this->supportsInt32 = TRUE; break;
            case "Int64" : $this->supportsInt64 = TRUE; break;
            case "Single" : $this->supportsSingle = TRUE; break;
            case "String" : $this->supportsString = TRUE; break;
            case "CLOB" : $this->supportsCLOB = TRUE; break;
            case "BLOB" : $this->supportsBLOB = TRUE; break;
            case "UniqueID" : $this->supportsUniqueID = TRUE; break;
            default : fwrite($this->logFileHandle, "unknown data type: $value\n");
         }
          }
       }

       // COMMAND

       var $supportsSelect = FALSE;
       function supportsSelect() {
          return $this->supportsSelect;
       }

       var $supportsSelectAggregates = FALSE;
       function supportsSelectAggregates() {
          return $this->supportsSelectAggregates;
       }

       var $supportsInsert = FALSE;
       function supportsInsert() {
          return $this->supportsInsert;
       }

       var $supportsDelete = FALSE;
       function supportsDelete() {
          return $this->supportsDelete;
       }

       var $supportsUpdate = FALSE;
       function supportsUpdate() {
          return $this->supportsUpdate;
       }

       var $supportsDescribeSchema = FALSE;
       function supportsDescribeSchema() {
          return $this->supportsDescribeSchema;
       }

       var $supportsDescribeSchemaMapping = FALSE;
       function supportsDescribeSchemaMapping() {
          return $this->supportsDescribeSchemaMapping;
       }

       var $supportsApplySchema = FALSE;
       function supportsApplySchema() {
          return $this->supportsApplySchema;
       }

       var $supportsDestroySchema = FALSE;
       function supportsDestroySchema() {
          return $this->supportsDestroySchema;
       }

       var $supportsActivateSpatialContext = FALSE;
       function supportsActivateSpatialContext() {
          return $this->supportsActivateSpatialContext;
       }
       var $supportsCreateSpatialContext = FALSE;
       function supportsCreateSpatialContext() {
          return $this->supportsCreateSpatialContext;
       }

       var $supportsDestroySpatialContext = FALSE;
       function supportsDestroySpatialContext() {
          return $this->supportsDestroySpatialContext;
       }

       var $supportsGetSpatialContexts = FALSE;
       function supportsGetSpatialContexts() {
          return $this->supportsGetSpatialContexts;
       }

       var $supportsCreateMeasureUnit = FALSE;
       function supportsCreateMeasureUnit() {
          return $this->supportsCreateMeasureUnit;
       }

       var $supportsDestroyMeasureUnit = FALSE;
       function supportsDestroyMeasureUnit() {
          return $this->supportsDestroyMeasureUnit;
       }

       var $supportsGetMeasureUnits = FALSE;
       function supportsGetMeasureUnits() {
          return $this->supportsGetMeasureUnits;
       }

       var $supportsSQLCommand = FALSE;
       function supportsSQLCommand() {
          return $this->supportsSQLCommand;
       }

       var $supportsAcquireLock = FALSE;
       function supportsAcquireLock() {
          return $this->supportsAcquireLock;
       }

       var $supportsGetLockInfo = FALSE;
       function supportsGetLockInfo() {
          return $this->supportsGetLockInfo;
       }

       var $supportsGetLockedObjects = FALSE;
       function supportsGetLockedObjects() {
          return $this->supportsGetLockedObjects;
       }

       var $supportsGetLockOwners = FALSE;
       function supportsGetLockOwners() {
          return $this->supportsGetLockOwners;
       }

       var $supportsReleaseLock = FALSE;
       function supportsReleaseLock() {
          return $this->supportsReleaseLock;
       }

       var $supportsActivateLongTransaction = FALSE;
       function supportsActivateLongTransaction() {
          return $this->supportsActivateLongTransaction;
       }

       var $supportsCommitLongTransaction = FALSE;
       function supportsCommitLongTransaction() {
          return $this->supportsCommitLongTransaction;
       }

       var $supportsCreateLongTransaction = FALSE;
       function supportsCreateLongTransaction() {
          return $this->supportsCreateLongTransaction;
       }

       var $supportsGetLongTransactions = FALSE;
       function supportsGetLongTransactions() {
          return $this->supportsGetLongTransactions;
       }

       var $supportsFreezeLongTransaction = FALSE;
       function supportsFreezeLongTransaction() {
          return $this->supportsFreezeLongTransaction;
       }

       var $supportsRollbackLongTransaction = FALSE;
       function supportsRollbackLongTransaction() {
          return $this->supportsRollbackLongTransaction;
       }

       var $supportsActivateLongTransactionCheckpoint = FALSE;
       function supportsActivateLongTransactionCheckpoint() {
          return $this->supportsActivateLongTransactionCheckpoint;
       }

       var $supportsCreateLongTransactionCheckpoint = FALSE;
       function supportsCreateLongTransactionCheckpoint() {
          return $this->supportsCreateLongTransactionCheckpoint;
       }

       var $supportsGetLongTransactionCheckpoints = FALSE;
       function supportsGetLongTransactionCheckpoints() {
          return $this->supportsGetLongTransactionCheckpoints;
       }

       var $supportsRollbackLongTransactionCheckpoint = FALSE;
       function supportsRollbackLongTransactionCheckpoint() {
          return $this->supportsRollbackLongTransactionCheckpoint;
       }

       var $supportsChangeLongTransactionPrivileges = FALSE;
       function supportsChangeLongTransactionPrivileges() {
          return $this->supportsChangeLongTransactionPrivileges;
       }

       var $supportsGetLongTransactionPrivileges = FALSE;
       function supportsGetLongTransactionPrivileges() {
          return $this->supportsGetLongTransactionPrivileges;
       }

       var $supportsChangeLongTransactionSet = FALSE;
       function supportsChangeLongTransactionSet() {
          return $this->supportsChangeLongTransactionSet;
       }

       var $supportsGetLongTransactionsInSet = FALSE;
       function supportsGetLongTransactionsInSet() {
          return $this->supportsGetLongTransactionsInSet;
       }

       var $supportsFirstProviderCommand = FALSE;
       function supportsFirstProviderCommand() {
          return $this->supportsFirstProviderCommand;
       }

       var $supportsDeactivateLongTransaction = FALSE;
       function supportsDeactivateLongTransaction() {
          return $this->supportsDeactivateLongTransaction;
       }

       // rest of Commands

       var $supportsParameters = FALSE;
       function supportsParameters() {
          return $this->supportsParameters;
       }

       var $supportsCommandTimeout = FALSE;
       function supportsCommandTimeout() {
          return $this->supportsCommandTimeout;
       }

       var $supportsSelectExpressions = FALSE;
       function supportsSelectExpressions() {
          return $this->supportsSelectExpressions;
       }

       var $supportsSelectFunctions = FALSE;
       function supportsSelectFunctions() {
          return $this->supportsSelectFunctions;
       }

       var $supportsSelectDistinct = FALSE;
       function supportsSelectDistinct() {
          return $this->supportsSelectDistinct;
       }

       var $supportsSelectOrdering = FALSE;
       function supportsSelectOrdering() {
          return $this->supportsSelectOrdering;
       }

       var $supportsSelectGrouping = FALSE;
       function supportsSelectGrouping() {
          return $this->supportsSelectGrouping;
       }

       function queryCommand() {
          $this->queryCommands();
          $this->queryBooleanElement("//FeatureProviderCapabilities/Command/SupportsParameters", $this->supportsParameters);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Command/SupportsTimeout", $this->supportsCommandTimeout);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Command/SupportsSelectExpressions", $this->supportsSelectExpressions);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Command/SupportsSelectFunctions", $this->supportsSelectFunctions);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Command/SupportsSelectDistinct", $this->supportsSelectDistinct);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Command/SupportsSelectOrdering", $this->supportsSelectOrdering);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Command/SupportsSelectGrouping", $this->supportsSelectGrouping);
       }

       function queryCommands() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Command/SupportedCommands/Name");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "Insert" : $this->supportsInsert = TRUE; break;
            case "Delete" : $this->supportsDelete = TRUE; break;
            case "Update" : $this->supportsUpdate = TRUE; break;
            case "Select" : $this->supportsSelect = TRUE; break;
            case "SelectAggregates" : $this->supportsSelectAggregates = TRUE; break;
            case "DescribeSchema" : $this->supportsDescribeSchema = TRUE; break;
            case "DescribeSchemaMapping" : $this->supportsDescribeSchemaMapping = TRUE; break;
            case "DestroySchema" : $this->supportsDestroySchema = TRUE; break;
            case "ApplySchema" : $this->supportsApplySchema = TRUE; break;
            case "SQLCommand" : $this->supportsSQLCommand = TRUE; break;
            case "ActivateSpatialContext" : $this->supportsActivateSpatialContext = TRUE; break;
            case "CreateSpatialContext" : $this->supportsCreateSpatialContext = TRUE; break;
            case "DestroySpatialContext" : $this->supportsDestroySpatialContext = TRUE; break;
            case "GetSpatialContexts" : $this->supportsGetSpatialContexts = TRUE; break;
            case "CreateMeasureUnit" : $this->supportsCreateMeasureUnit = TRUE; break;
            case "DestroyMeasureUnit" : $this->supportsDestroyMeasureUnit = TRUE; break;
            case "GetMeasureUnits" : $this->supportsGetMeasureUnits = TRUE; break;
            case "AcquireLock" : $this->supportsAcquireLock = TRUE; break;
            case "GetLockInfo" : $this->supportsGetLockInfo = TRUE; break;
            case "GetLockedObjects" : $this->supportsGetLockedObjects = TRUE; break;
            case "GetLockOwners" : $this->supportsGetLockOwners = TRUE; break;
            case "ReleaseLock" : $this->supportsReleaseLock = TRUE; break;
            case "ActivateLongTransaction" : $this->supportsActivateLongTransaction = TRUE; break;
            case "CommitLongTransaction" : $this->supportsCommitLongTransaction = TRUE; break;
            case "CreateLongTransaction" : $this->supportsCreateLongTransaction = TRUE; break;
            case "GetLongTransactions" : $this->supportsGetLongTransactions = TRUE; break;
            case "FreezeLongTransaction" : $this->supportsFreezeLongTransaction = TRUE; break;
            case "RollbackLongTransaction" : $this->supportsRollbackLongTransaction = TRUE; break;
            case "ActivateLongTransactionCheckpoint" : $this->supportsActivateLongTransactionCheckpoint = TRUE; break;
            case "CreateLongTransactionCheckpoint" : $this->supportsCreateLongTransactionCheckpoint = TRUE; break;
            case "GetLongTransactionCheckpoints" : $this->supportsGetLongTransactionCheckpoints = TRUE; break;
            case "RollbackLongTransactionCheckpoint" : $this->supportsRollbackLongTransactionCheckpoint = TRUE; break;
            case "ChangeLongTransactionPrivileges" : $this->supportsChangeLongTransactionPrivileges = TRUE; break;
            case "GetLongTransactionPrivileges" : $this->supportsGetLongTransactionPrivileges = TRUE; break;
            case "ChangeLongTransactionSet" : $this->supportsChangeLongTransactionSet = TRUE; break;
            case "GetLongTransactionsInSet" : $this->supportsGetLongTransactionsInSet = TRUE; break;
            case "FirstProviderCommand" : $this->supportsFirstProviderCommand = TRUE; break;
            case "DeactivateLongTransaction" : $this->supportsDeactivateLongTransaction = TRUE; break;
            default : fwrite($this->logFileHandle, "unknown command type: $value\n");
         }
          }
       }

       // FILTER

       // Condition types

       var $supportsComparison = FALSE;
       function supportsComparison() {
          return $this->supportsComparison;
       }

       var $supportsLike = FALSE;
       function supportsLike() {
          return $this->supportsLike;
       }

       var $supportsIn = FALSE;
       function supportsIn() {
          return $this->supportsIn;
       }

       var $supportsNull = FALSE;
       function supportsNull() {
          return $this->supportsNull;
       }

       var $supportsSpatial = FALSE;
       function supportsSpatial() {
          return $this->supportsSpatial;
       }

       var $supportsDistance = FALSE;
       function supportsDistance() {
          return $this->supportsDistance;
       }

       // Spatial types

       var $supportsContains = FALSE;
       function supportsContains() {
          return $this->supportsContains;
       }

       var $supportsCrosses = FALSE;
       function supportsCrosses() {
          return $this->supportsCrosses;
       }

       var $supportsDisjoint = FALSE;
       function supportsDisjoint() {
          return $this->supportsDisjoint;
       }

       var $supportsEquals = FALSE;
       function supportsEquals() {
          return $this->supportsEquals;
       }

       var $supportsIntersects = FALSE;
       function supportsIntersects() {
          return $this->supportsIntersects;
       }

       var $supportsOverlaps = FALSE;
       function supportsOverlaps() {
          return $this->supportsOverlaps;
       }

       var $supportsTouches = FALSE;
       function supportsTouches() {
          return $this->supportsTouches;
       }

       var $supportsSpatialWithin = FALSE;
       function supportsSpatialWithin() {
          return $this->supportsSpatialWithin;
       }

       var $supportsCoveredBy = FALSE;
       function supportsCoveredBy() {
          return $this->supportsCoveredBy;
       }

       var $supportsInside = FALSE;
       function supportsInside() {
          return $this->supportsInside;
       }

       var $supportsEnvelopeIntersects = FALSE;
       function supportsEnvelopeIntersects() {
          return $this->supportsEnvelopeIntersects;
       }

       // Distance types

       var $supportsBeyond = FALSE;
       function supportsBeyond() {
          return $this->supportsBeyond;
       }

       var $supportsDistanceWithin = FALSE;
       function supportsDistanceWithin() {
          return $this->supportsDistanceWithin;
       }

       // rest of Filter

       var $supportsGeodesicDistance = FALSE;
       function supportsGeodesicDistance() {
          return $this->supportsGeodesicDistance;
       }

       var $supportsNonLiteralGeometricOperations = FALSE;
       function supportsNonLiteralGeometricOperations() {
          return $this->supportsNonLiteralGeometricOperations;
       }

       function queryFilter() {
          $this->queryConditionType();
          $this->querySpatialOperations();
          $this->queryDistanceOperations();
          $this->queryBooleanElement("//FeatureProviderCapabilities/Filter/SupportsGeodesicDistance", $this->supportsGeodesicDistance);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Filter/SupportsNonLiteralGeometricOperations", $this->supportsNonLiteralGeometricOperations);
       }

       function queryConditionType() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Filter/Condition/Type");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "Comparison" : $this->supportsComparison = TRUE; break;
            case "Like" : $this->supportsLike = TRUE; break;
            case "In" : $this->supportsIn = TRUE; break;
            case "Null" : $this->supportsNull = TRUE; break;
            case "Spatial" : $this->supportsSpatial = TRUE; break;
            case "Distance" : $this->supportsDistance = TRUE; break;
    ; break;
            default : fwrite($this->logFileHandle, "unknown filter condition type: $value\n");
         }
          }
       }

       function querySpatialOperations() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Filter/Spatial/Operation");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "Contains" : $this->supportsContains = TRUE; break;
            case "Crosses" : $this->supportsCrosses = TRUE; break;
            case "Disjoint" : $this->supportsDisjoint = TRUE; break;
            case "Equals" : $this->supportsEquals = TRUE; break;
            case "Intersects" : $this->supportsIntersects = TRUE; break;
            case "Overlaps" : $this->supportsOverlaps = TRUE; break;
            case "Touches" : $this->supportsTouches = TRUE; break;
            case "Within" : $this->supportsSpatialWithin = TRUE; break;
            case "CoveredBy" : $this->supportsCoveredBy = TRUE; break;
            case "Inside" : $this->supportsInside = TRUE; break;
            case "EnvelopeIntersects" : $this->supportsEnvelopeIntersects = TRUE; break;
            default : fwrite($this->logFileHandle, "unknown filter spatial operation: $value\n");
         }
          }
       }

       function queryDistanceOperations() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Filter/Distance/Operation");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "Within" : $this->supportsDistanceWithin = TRUE; break;
            case "Beyond" : $this->supportsBeyond = TRUE; break;
            default : fwrite($this->logFileHandle, "unknown filter distance operation: $value\n");
         }
          }
       }

       // EXPRESSION

       // types

       var $supportsBasic = FALSE;
       function supportsBasic() {
          return $this->supportsBasic;
       }

       var $supportsFunction = FALSE;
       function supportsFunction() {
          return $this->supportsFunction;
       }

       var $supportsParameter = FALSE;
       function supportsParameter() {
          return $this->supportsParameter;
       }

       var $supportsAvg = FALSE;
       function supportsAvg() {
          return $this->supportsAvg;
       }

       var $supportsCeil = FALSE;
       function supportsCeil() {
          return $this->supportsCeil;
       }

       var $supportsCLIP = FALSE;
       function supportsCLIP() {
          return $this->supportsCLIP;
       }

       var $supportsConcat = FALSE;
       function supportsConcat() {
          return $this->supportsConcat;
       }

       var $supportsCount = FALSE;
       function supportsCount() {
          return $this->supportsCount;
       }

       var $supportsFloor = FALSE;
       function supportsFloor() {
          return $this->supportsFloor;
       }

       var $supportsLower = FALSE;
       function supportsLower() {
          return $this->supportsLower;
       }

       var $supportsMax = FALSE;
       function supportsMax() {
          return $this->supportsMax;
       }

       var $supportsMin = FALSE;
       function supportsMin() {
          return $this->supportsMin;
       }

       var $supportsMOSAIC = FALSE;
       function supportsMOSAIC() {
          return $this->supportsMOSAIC;
       }

       var $supportsStdDev = FALSE;
       function supportsStdDev() {
          return $this->supportsStdDev;
       }

       var $supportsSum = FALSE;
       function supportsSum() {
          return $this->supportsSum;
       }

       var $supportsUpper = FALSE;
       function supportsUpper() {
          return $this->supportsUpper;
       }

       function queryExpression() {
          $this->queryExpressionType();
          $this->queryFunctionDefinitions();
       }

       function queryExpressionType() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Expression/Type/Name");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "Basic" : $this->supportsBasic = TRUE; break;
            case "Function" : $this->supportsFunction = TRUE; break;
            case "Parameter" : $this->supportsParameter = TRUE; break;
            default : fwrite($this->logFileHandle, "unknown filter distance operation: $value\n");
         }
          }
       }

       function queryFunctionDefinitions() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Expression/FunctionDefinitionCollection/FunctionDefinition/Name");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "Avg" : $this->supportsAvg = TRUE; break;
            case "Ceil" : $this->supportsCeil = TRUE; break;
            case "CLIP" : $this->supportsCLIP = TRUE; break;
            case "Concat" : $this->supportsConcat = TRUE; break;
            case "Count" : $this->supportsCount = TRUE; break;
            case "Floor" : $this->supportsFloor = TRUE; break;
            case "Lower" : $this->supportsLower = TRUE; break;
            case "Max" : $this->supportsMax = TRUE; break;
            case "Min" : $this->supportsMin = TRUE; break;
            case "MOSAIC" : $this->supportsMOSAIC = TRUE; break;
            case "StdDev" : $this->supportsStdDev = TRUE; break;
            case "Sum" : $this->supportsSum = TRUE; break;
            case "Upper" : $this->supportsUpper = TRUE; break;
            default : fwrite($this->logFileHandle, "unknown expression function name: $value\n");
         }
          }
       }

       // RASTER

       var $supportsRaster = FALSE;
       function supportsRaster() {
          return $this->supportsRaster;
       }

       var $supportsStitching = FALSE;
       function supportsStitching() {
          return $this->supportsStitching;
       }

       var $supportsSubsampling = FALSE;
       function supportsSubsampling() {
          return $this->supportsSubsampling;
       }

       function queryRaster() {
          $this->queryBooleanElement("//FeatureProviderCapabilities/Raster/SupportsRaster", $this->supportsRaster);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Raster/SupportsStitching", $this->supportsStitching);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Raster/SupportsSubsampling", $this->supportsSubsampling);
       }

       // TOPOLOGY

       var $supportsTopology = FALSE;
       function supportsTopology() {
          return $this->supportsTopology;
       }

       var $supportsTopologicalHierarchy = FALSE;
       function supportsTopologicalHierarchy() {
          return $this->supportsTopologicalHierarchy;
       }

       var $supportsBreaksCurveCrossingsAutomatically = FALSE;
       function supportsBreaksCurveCrossingsAutomatically() {
          return $this->supportsBreaksCurveCrossingsAutomatically;
       }

       var $supportsActivatesTopologyByArea = FALSE;
       function supportsActivatesTopologyByArea() {
          return $this->supportsActivatesTopologyByArea;
       }

       var $supportsConstrainsFeatureMovements = FALSE;
       function supportsConstrainsFeatureMovements() {
          return $this->supportsConstrainsFeatureMovements;
       }

       function queryTopology() {
          $this->queryBooleanElement("//FeatureProviderCapabilities/Topology/SupportsTopology", $this->supportsTopology);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Topology/SupportsTopologicalHierarchy", $this->supportsTopologicalHierarchy);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Topology/BreaksCurveCrossingsAutomatically", $this->supportsBreaksCurveCrossingsAutomatically);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Topology/ActivatesTopologyByArea", $this->supportsActivatesTopologyByArea);
          $this->queryBooleanElement("//FeatureProviderCapabilities/Topology/ConstrainsFeatureMovements", $this->supportsConstrainsFeatureMovements);
       }

       // GEOMETRY

       var $supportsPoint = FALSE;
       function supportsPoint() {
          return $this->supportsPoint;
       }

       var $supportsMultiPoint = FALSE;
       function supportsMultiPoint() {
          return $this->supportsMultiPoint;
       }

       var $supportsLineString = FALSE;
       function supportsLineString() {
          return $this->supportsLineString;
       }

       var $supportsMultiLineString = FALSE;
       function supportsMultiLineString() {
          return $this->supportsMultiLineString;
       }

       var $supportsPolygon = FALSE;
       function supportsPolygon() {
          return $this->supportsPolygon;
       }

       var $supportsMultiPolygon = FALSE;
       function supportsMultiPolygon() {
          return $this->supportsMultiPolygon;
       }

       var $supportsCurveString = FALSE;
       function supportsCurveString() {
          return $this->supportsCurveString;
       }

       var $supportsMultiCurveString = FALSE;
       function supportsMultiCurveString() {
          return $this->supportsMultiCurveString;
       }

       var $supportsCurvePolygon = FALSE;
       function supportsCurvePolygon() {
          return $this->supportsCurvePolygon;
       }

       var $supportsMultiCurvePolygon = FALSE;
       function supportsMultiCurvePolygon() {
          return $this->supportsMultiCurvePolygon;
       }

       var $supportsMultiGeometry = FALSE;
       function supportsMultiGeometry() {
          return $this->supportsMultiGeometry;
       }

       var $supportsLinearRing = FALSE;
       function supportsLinearRing() {
          return $this->supportsLinearRing;
       }
       var $supportsLinearSegment = FALSE;
       function supportsLinearSegment() {
          return $this->supportsLinearSegment;
       }
       var $supportsArcSegment = FALSE;
       function supportsArcSegment() {
          return $this->supportsArcSegment;
       }
       var $supportsCurveRing = FALSE;
       function supportsCurveRing() {
          return $this->supportsCurveRing;
       }

       var $dimensionality = -1;
       function getDimensionality() {
          return $this->dimensionality;
       }

       function queryGeometry() {
          $this->queryGeometries();
          $this->queryComponents();
          $this->queryDimensionality();
       }

       function queryGeometries() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Geometry/Type");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "Point" : $this->supportsPoint = TRUE; break;
            case "MultiPoint" : $this->supportsMultiPoint = TRUE; break;
            case "LineString" : $this->supportsLineString = TRUE; break;
            case "MultiLineString" : $this->supportsMultiLineString = TRUE; break;
            case "Polygon" : $this->supportsPolygon = TRUE; break;
            case "MultiPolygon" : $this->supportsMultiPolygon = TRUE; break;
            case "CurveString" : $this->supportsCurveString = TRUE; break;
            case "MultiCurveString" : $this->supportsMultiCurveString = TRUE; break;
            case "CurvePolygon" : $this->supportsCurvePolygon = TRUE; break;
            case "MultiCurvePolygon" : $this->supportsMultiCurvePolygon = TRUE; break;
            case "MultiGeometry" : $this->supportsMultiGeometry = TRUE; break;
            default : fwrite($this->logFileHandle, "unknown geometry type: $value\n");
         }
          }
       }

       function queryComponents() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Geometry/Components/Type");
          $count = $domNodeList->length;
          for($i=0; $i<$count; $i++) {
         $domNode = $domNodeList->item($i);
         $value = $domNode->nodeValue;
         switch($value) {
            case "LinearRing" : $this->supportsLinearRing = TRUE; break;
            case "LinearSegment" : $this->supportsLinearSegment = TRUE; break;
            case "ArcSegment" : $this->supportsArcSegment = TRUE; break;
            case "CurveRing" : $this->supportsCurveRing = TRUE; break;
            default : fwrite($this->logFileHandle, "unknown geometry component type: $value\n");
         }
          }
       }

       function queryDimensionality() {
          $domNodeList = $this->xpath->query("//FeatureProviderCapabilities/Geometry/Dimensionality");
          if ($domNodeList->length == 0) return;
          $domNode = $domNodeList->item(0);
          $value = $domNode->nodeValue;
          $this->dimensionality = $value;
       }

       function logCapabilities() {
          fwrite($this->logFileHandle, "Capabilities for $this->providerName\n");
          fwrite($this->logFileHandle, "Connection\n");
          fwrite($this->logFileHandle, "\tThreadCapability\n");
          $logEntry = "\t\tsupportsSingleThreaded(): " . $this->prtBool($this->supportsSingleThreaded()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsPerConnectionThreaded(): " . $this->prtBool($this->supportsPerConnectionThreaded()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsPerCommandThreaded(): " . $this->prtBool($this->supportsPerCommandThreaded()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsMultiThreaded(): " . $this->prtBool($this->supportsMultiThreaded()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "\tSpatialContextExtent\n");
          fwrite($this->logFileHandle, "\t\tType\n");
          $logEntry = "\t\t\tsupportsDynamic(): " . $this->prtBool($this->supportsDynamic()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsStatic(): " . $this->prtBool($this->supportsStatic()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsLocking(): " . $this->prtBool($this->supportsLocking()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsConnectionTimeout(): " . $this->prtBool($this->supportsConnectionTimeout()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsTransactions(): " . $this->prtBool($this->supportsTransactions()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsLongTransactions(): " . $this->prtBool($this->supportsLongTransactions()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsSQL(): " . $this->prtBool($this->supportsSQL()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsConfiguration(): " . $this->prtBool($this->supportsConfiguration()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "Schema\n");
          fwrite($this->logFileHandle, "\tClass\n");
          fwrite($this->logFileHandle, "\t\tType\n");
         $logEntry = "\t\t\tsupportsClass(): " . $this->prtBool($this->supportsClass()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsFeatureClass(): " . $this->prtBool($this->supportsFeatureClass()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "\tData\n");
          fwrite($this->logFileHandle, "\t\tType\n");
          $logEntry = "\t\t\tsupportsBoolean(): " . $this->prtBool($this->supportsBoolean()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsByte(): " . $this->prtBool($this->supportsByte()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDateTime(): " . $this->prtBool($this->supportsDateTime()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDecimal(): " . $this->prtBool($this->supportsDecimal()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDouble(): " . $this->prtBool($this->supportsDouble()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsInt16(): " . $this->prtBool($this->supportsInt16()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsInt32(): " . $this->prtBool($this->supportsInt32()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsInt64(): " . $this->prtBool($this->supportsInt64()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsSingle(): " . $this->prtBool($this->supportsSingle()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsString(): " . $this->prtBool($this->supportsString()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsBLOB(): " . $this->prtBool($this->supportsBLOB()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsCLOB(): " . $this->prtBool($this->supportsCLOB()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsUniqueID(): " . $this->prtBool($this->supportsUniqueID()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsInheritance(): " . $this->prtBool($this->supportsInheritance()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsMultipleSchemas(): " . $this->prtBool($this->supportsMultipleSchemas()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsObjectProperties(): " . $this->prtBool($this->supportsObjectProperties()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsAssociationProperties(): " . $this->prtBool($this->supportsAssociationProperties()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsSchemaOverrides(): " . $this->prtBool($this->supportsSchemaOverrides()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsNetworkModel(): " . $this->prtBool($this->supportsNetworkModel()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsAutoIdGeneration(): " . $this->prtBool($this->supportsAutoIdGeneration()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsDataStoreScopeUniqueIdGeneration(): " . $this->prtBool($this->supportsDataStoreScopeUniqueIdGeneration()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsSchemaModification(): " . $this->prtBool($this->supportsSchemaModification()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "Command\n");
          fwrite($this->logFileHandle, "\tSupportedCommands\n");
          fwrite($this->logFileHandle, "\t\tName\n");
          $logEntry = "\t\t\tsupportsSelect(): " . $this->prtBool($this->supportsSelect()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsInsert(): " . $this->prtBool($this->supportsInsert()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDelete(): " . $this->prtBool($this->supportsDelete()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsUpdate(): " . $this->prtBool($this->supportsUpdate()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsSelectAggregates(): " . $this->prtBool($this->supportsSelectAggregates()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDescribeSchema(): " . $this->prtBool($this->supportsDescribeSchema()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDescribeSchemaMapping(): " . $this->prtBool($this->supportsDescribeSchemaMapping()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDestroySchema(): " . $this->prtBool($this->supportsDestroySchema()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsApplySchema(): " . $this->prtBool($this->supportsApplySchema()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsActivateSpatialContext(): " . $this->prtBool($this->supportsActivateSpatialContext()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsCreateSpatialContext(): " . $this->prtBool($this->supportsCreateSpatialContext()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDestroySpatialContext(): " . $this->prtBool($this->supportsDestroySpatialContext()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDestroySpatialContext(): " . $this->prtBool($this->supportsGetSpatialContexts) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsCreateMeasureUnit(): " . $this->prtBool($this->supportsCreateMeasureUnit()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDestroyMeasureUnit()t: " . $this->prtBool($this->supportsDestroyMeasureUnit()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsGetMeasureUnits(): " . $this->prtBool($this->supportsGetMeasureUnits()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsSQLCommand(): " . $this->prtBool($this->supportsSQLCommand()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsAcquireLock(): " . $this->prtBool($this->supportsAcquireLock()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsGetLockInfo(): " . $this->prtBool($this->supportsGetLockInfo()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsGetLockedObjects(): " . $this->prtBool($this->supportsGetLockedObjects()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsGetLockOwners(): " . $this->prtBool($this->supportsGetLockOwners()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsReleaseLock(): " . $this->prtBool($this->supportsReleaseLock()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsActivateLongTransaction(): " . $this->prtBool($this->supportsActivateLongTransaction()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsCommitLongTransaction(): " . $this->prtBool($this->supportsCommitLongTransaction()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsCreateLongTransaction(): " . $this->prtBool($this->supportsCreateLongTransaction()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsGetLongTransactions(): " . $this->prtBool($this->supportsGetLongTransactions()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsFreezeLongTransaction(): " . $this->prtBool($this->supportsFreezeLongTransaction()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsRollbackLongTransaction(): " . $this->prtBool($this->supportsRollbackLongTransaction()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsActivateLongTransactionCheckpoint(): " . $this->prtBool($this->supportsActivateLongTransactionCheckpoint()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsCreateLongTransactionCheckpoint(): " . $this->prtBool($this->supportsCreateLongTransactionCheckpoint()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsGetLongTransactionCheckpoints(): " . $this->prtBool($this->supportsGetLongTransactionCheckpoints()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsRollbackLongTransactionCheckpoint(): " . $this->prtBool($this->supportsRollbackLongTransactionCheckpoint()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsChangeLongTransactionPrivileges(): " . $this->prtBool($this->supportsChangeLongTransactionPrivileges()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsGetLongTransactionPrivileges(): " . $this->prtBool($this->supportsGetLongTransactionPrivileges()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsChangeLongTransactionSet(): " . $this->prtBool($this->supportsChangeLongTransactionSet()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsGetLongTransactionsInSet(): " . $this->prtBool($this->supportsGetLongTransactionsInSet()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsFirstProviderCommand(): " . $this->prtBool($this->supportsFirstProviderCommand()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDeactivateLongTransaction(): " . $this->prtBool($this->supportsDeactivateLongTransaction()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsParameters(): " . $this->prtBool($this->supportsParameters()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsCommandTimeout(): " . $this->prtBool($this->supportsCommandTimeout()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsSelectExpressions(): " . $this->prtBool($this->supportsSelectExpressions()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsSelectFunctions(): " . $this->prtBool($this->supportsSelectFunctions()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsSelectDistinct(): " . $this->prtBool($this->supportsSelectDistinct()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsSelectOrdering(): " . $this->prtBool($this->supportsSelectOrdering()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsSelectGrouping(): " . $this->prtBool($this->supportsSelectGrouping()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "Filter\n");
          fwrite($this->logFileHandle, "\tCondition\n");
          fwrite($this->logFileHandle, "\t\tType\n");
          $logEntry = "\t\t\tsupportsComparison(): " . $this->prtBool($this->supportsComparison()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsLike(): " . $this->prtBool($this->supportsLike()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsIn(): " . $this->prtBool($this->supportsIn()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsNull(): " . $this->prtBool($this->supportsNull()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsSpatial(): " . $this->prtBool($this->supportsSpatial()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDistance(): " . $this->prtBool($this->supportsDistance()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "\tSpatial\n");
          fwrite($this->logFileHandle, "\t\tOperation\n");
          $logEntry = "\t\t\tsupportsContains(): " . $this->prtBool($this->supportsContains()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsCrosses(): " . $this->prtBool($this->supportsCrosses()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsDisjoint(): " . $this->prtBool($this->supportsDisjoint()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsEquals(): " . $this->prtBool($this->supportsEquals()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsIntersects(): " . $this->prtBool($this->supportsIntersects()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsOverlaps()s: " . $this->prtBool($this->supportsOverlaps()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsTouches(): " . $this->prtBool($this->supportsTouches()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsSpatialWithin(): " . $this->prtBool($this->supportsSpatialWithin()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsCoveredBy(): " . $this->prtBool($this->supportsCoveredBy()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsInside(): " . $this->prtBool($this->supportsInside()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsEnvelopeIntersects(): " . $this->prtBool($this->supportsEnvelopeIntersects()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "\tDistance\n");
          fwrite($this->logFileHandle, "\t\tOperation\n");
          $logEntry = "\t\t\tsupportsDistanceWithin(): " . $this->prtBool($this->supportsDistanceWithin()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsBeyond(): " . $this->prtBool($this->supportsBeyond()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsGeodesicDistance(): " . $this->prtBool($this->supportsGeodesicDistance()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsNonLiteralGeometricOperations(): " . $this->prtBool($this->supportsNonLiteralGeometricOperations()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "Expression\n");
          fwrite($this->logFileHandle, "\tType\n");
          fwrite($this->logFileHandle, "\t\tName\n");
          $logEntry = "\t\t\tsupportsBasic(): " . $this->prtBool($this->supportsBasic()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsFunction(): " . $this->prtBool($this->supportsFunction()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsParameter(): " . $this->prtBool($this->supportsParameter()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "\tFunctionDefinitionCollection\n");
          fwrite($this->logFileHandle, "\t\tFunctionDefinition\n");
          fwrite($this->logFileHandle, "\t\t\tName\n");
          $logEntry = "\t\t\t\tsupportsAvg(): " . $this->prtBool($this->supportsAvg()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsCeil(): " . $this->prtBool($this->supportsCeil()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsCLIP(): " . $this->prtBool($this->supportsCLIP()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsConcat(): " . $this->prtBool($this->supportsConcat()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsCount(): " . $this->prtBool($this->supportsCount()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsFloor(): " . $this->prtBool($this->supportsFloor()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsLower(): " . $this->prtBool($this->supportsLower()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsMax(): " . $this->prtBool($this->supportsMax()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsMin(): " . $this->prtBool($this->supportsMin()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsMOSAIC(): " . $this->prtBool($this->supportsMOSAIC()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsStdDev(): " . $this->prtBool($this->supportsStdDev()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsSum(): " . $this->prtBool($this->supportsSum()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\t\tsupportsUpper(): " . $this->prtBool($this->supportsUpper()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "Raster\n");
          $logEntry = "\tsupportsRaster(): " . $this->prtBool($this->supportsRaster()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsStitching(): " . $this->prtBool($this->supportsStitching()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsSubsampling(): " . $this->prtBool($this->supportsSubsampling()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "Topology\n");
          $logEntry = "\tsupportsTopology(): " . $this->prtBool($this->supportsTopology()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsTopologicalHierarchy(): " . $this->prtBool($this->supportsTopologicalHierarchy()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsBreaksCurveCrossingsAutomatically(): " . $this->prtBool($this->supportsBreaksCurveCrossingsAutomatically()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsActivatesTopologyByArea(): " . $this->prtBool($this->supportsActivatesTopologyByArea()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tsupportsConstrainsFeatureMovements(): " . $this->prtBool($this->supportsConstrainsFeatureMovements()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "Geometry\n");
          fwrite($this->logFileHandle, "\tType\n");
          $logEntry = "\t\tsupportsPoint(): " . $this->prtBool($this->supportsPoint()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsMultiPoint(): " . $this->prtBool($this->supportsMultiPoint()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsLineString(): " . $this->prtBool($this->supportsLineString()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsMultiLineString(): " . $this->prtBool($this->supportsMultiLineString()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsPolygon(): " . $this->prtBool($this->supportsPolygon()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsMultiPolygon(): " . $this->prtBool($this->supportsMultiPolygon()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsCurveString(): " . $this->prtBool($this->supportsCurveString()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsMultiCurveString(): " . $this->prtBool($this->supportsMultiCurveString()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsCurvePolygon(): " . $this->prtBool($this->supportsCurvePolygon()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsMultiCurvePolygon(): " . $this->prtBool($this->supportsMultiCurvePolygon()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\tsupportsMultiGeometry(): " . $this->prtBool($this->supportsMultiGeometry()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          fwrite($this->logFileHandle, "\tComponents\n");
          fwrite($this->logFileHandle, "\t\tType\n");
          $logEntry = "\t\t\tsupportsLinearRing(): " . $this->prtBool($this->supportsLinearRing()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsLinearSegment(): " . $this->prtBool($this->supportsLinearSegment()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsArcSegment(): " . $this->prtBool($this->supportsArcSegment()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\t\t\tsupportsCurveRing(): " . $this->prtBool($this->supportsCurveRing()) . "\n";
          fwrite($this->logFileHandle, $logEntry);
          $logEntry = "\tdimensionality(): " . $this->getDimensionality() . "\n";
          fwrite($this->logFileHandle, $logEntry);
       }
    }

Comments or suggestions? Send us feedback.