/**
 *	Copyright 2002-2006 by Earth Resource Mapping Ltd.  All rights reserved.
 *	Image Integration Framework generated pages may only be served by organizations that have
 *	a license for the Image Integration Framework product. Image Integration Framework may only be used by
 *	Application Service Providers (ASPs) with a license for the Image Integration Framework ASP Edition product.
 *
 *  @fileoverview Contains the SIX.Access.ArcXML access class
 */

SIX.ArcXMLServiceInfoCache = new SIX.ServiceInfoCache();
 
/**
* @class Interfaces to map servers such as ESRI’s ArcIMS that use the ArcXML style interface.
* @constructor
* @base SIX.Access
*/
SIX.Access.ArcXML = function (service) {
	SIX.Access.call(this, service);
	this.name = "ArcXML (ArcIMS)";
	this.version = "1.0";
	this.hasMetadata = false;
	this.hasLegend = false;
	this.hasSearch = false;		// may be set later
	this.hasQuery = false;
	this.canReorder = false;
	this.nNumInvalidRequests = 0;
	this.tMapTimer = null;
	this.nTimeout = 500;
	this.bMoreResults = false;
	this.bGotResults = false;
	this.nNumRequests = 0;
	this.nNumResponses = 0;
	this.dSelectedResultLabelX = 0.0;
	this.dSelectedResultLabelY = 0.0;
	this.aSelectedResultLabel = new Array();
	this.sSelectedResultId = "";
	this.nSelectedResultQuery = -1;
	this.aHighlightedResults = new Object();//Associative array for storing layer highlights
	this.sOldUrl = "";
	this.xml = new SIX.Xml();
}
SIX.Util.extend(SIX.Access.ArcXML, SIX.Access);

SIX.Access.ArcXML.prototype.getScale = function (map)
{
	//ArcIMS assumes the Earth is an exact sphere with a circumference of 40030.174 km. 
	//One degree is 111.195 km (40030.174/360 degrees) or 111195 meters.
	var dScreenMetresPerPixel = (0.0254 / SIX.Util.getScreenXDPI());
	var dWidthWorldCoords = map.brx - map.tlx;
	var dWidthMetres = map.isGeodetic() ? (111195 * dWidthWorldCoords) : dWidthWorldCoords; 
	var aDimensions = this.service.getMapDimensions(map);
	var dScale = dWidthMetres / (aDimensions[0] * dScreenMetresPerPixel);
	return dScale;
}

SIX.Access.ArcXML.prototype.loadMap = function (map)
{
	var access = this;
	var bValid = false;
	
	this.service.nMapLoadState = SIX.eMapLoadState.NOT_LOADED;
	if( !this.service.loaded || !map.loaded || !this.service.active || this.service.bFeatureServer || (this.service.nLayersLoadState != SIX.eLayersLoadState.LOADED))
		return;

	var svc = this.service;
	if (svc.bGroupedService)
	{
		var bAllLayersTurnedOff = true;
		for (var i=0; i<svc.layers.length; i++)
		{
			var layer = svc.layers[i];
			if (layer.bSelected && layer.bInList && layer.bInScale)
			{
				bAllLayersTurnedOff = false;
				break;
			}
		}
		if (bAllLayersTurnedOff)
		{
			if (map.setLayerParameter(svc.uid, "url="))
				svc.nMapLoadState = SIX.eMapLoadState.LOADED;	
			return;
		}
	}

	this.service.nMapLoadState = SIX.eMapLoadState.NOT_LOADED;
	if( !this.service.loaded || !map.loaded || !this.service.active || this.service.bFeatureServer || (this.service.nLayersLoadState != SIX.eLayersLoadState.LOADED))
	{
		return;
	}
	this.service.busy(true);
	var control = document[map.uid];

	while (this.xml.rootXml.hasChildNodes())
            this.xml.rootXml.removeChild(this.xml.rootXml.lastChild);

	var piXML = this.xml.rootXml.createProcessingInstruction("xml", "version='1.0'");
	this.xml.rootXml.appendChild(piXML);

    var nodeArcXML = this.xml.rootXml.createElement("ARCXML");
    nodeArcXML.setAttribute("version","1.1");
    
    var nodeRequest = this.xml.rootXml.createElement("REQUEST");
    nodeArcXML.appendChild(nodeRequest);
    
    var nodeGetImage = this.xml.rootXml.createElement("GET_IMAGE");
    nodeRequest.appendChild(nodeGetImage);
    
    var nodeProperties = this.xml.rootXml.createElement("PROPERTIES");
    nodeGetImage.appendChild(nodeProperties);
     
    var nodeEnvelope = this.xml.rootXml.createElement("ENVELOPE");
  
    var sEPSG = "";
    var sDefinitionString = "";
    var sProjection = map.projection();
    var sDatum = map.datum();
		
	var nEPSGCode = GDTEPSGMappings.getEPSGCode(sDatum, sProjection);
	if (nEPSGCode && this.service.supportsEPSG(nEPSGCode))
		sEPSG = "" + nEPSGCode;
	else
	{
		var sWKT = GDTEPSGMappings.getEPSGWKTFromDatumProjection(sDatum, sProjection);
		if (sWKT)
			sDefinitionString = sWKT;
	}
    
    var nodeFilterCoordSys = this.xml.rootXml.createElement("FILTERCOORDSYS");
    var nodeFeatureCoordSys = this.xml.rootXml.createElement("FEATURECOORDSYS");
    
    if (sEPSG != "") 
    {
		nodeFilterCoordSys.setAttribute("id", sEPSG);
		nodeFeatureCoordSys.setAttribute("id", sEPSG);
	}
	else if (sDefinitionString != "")
	{
		nodeFilterCoordSys.setAttribute("string", sDefinitionString);
		nodeFeatureCoordSys.setAttribute("string", sDefinitionString);	
	}
    
    if ((sEPSG == "") && (sDefinitionString == "")) 
    { 
		nodeEnvelope.setAttribute("minx", map.getTopLeftLongitude());
		nodeEnvelope.setAttribute("miny", map.getBottomRightLatitude());
		nodeEnvelope.setAttribute("maxx", map.getBottomRightLongitude());
		nodeEnvelope.setAttribute("maxy", map.getTopLeftLatitude());	
	}
	else
	{
		nodeEnvelope.setAttribute("minx", map.tlx);
		nodeEnvelope.setAttribute("miny", map.bry);
		nodeEnvelope.setAttribute("maxx", map.brx);
		nodeEnvelope.setAttribute("maxy", map.tly);
	         
		nodeProperties.appendChild(nodeFilterCoordSys); 
		nodeProperties.appendChild(nodeFeatureCoordSys); 		
	}
    
    nodeProperties.appendChild(nodeEnvelope); 
    
    var nodeImageSize = this.xml.rootXml.createElement("IMAGESIZE");

    var aDimensions = this.service.getMapDimensions(map);
    var nMapWidth = aDimensions[0];
    var nMapHeight = aDimensions[1];   
 
    nodeImageSize.setAttribute("width", nMapWidth);
    nodeImageSize.setAttribute("height", nMapHeight);  
    nodeImageSize.setAttribute("dpi", SIX.Util.getScreenXDPI());    
    nodeProperties.appendChild(nodeImageSize); 
    
    if (this.service.sBackgroundColor)
    {
        var aBackgroundRGB = SIX.Util.hexToRgb(this.service.sBackgroundColor);
        var sBackgroundRGB = aBackgroundRGB.toString();
        var nodeBackground = this.xml.rootXml.createElement("BACKGROUND");
        nodeBackground.setAttribute("color", sBackgroundRGB);
        nodeProperties.appendChild(nodeBackground);
    }    
    
    var nodeOutput = this.xml.rootXml.createElement("OUTPUT");
    nodeOutput.setAttribute("type", "PNG");
    nodeProperties.appendChild(nodeOutput); 
    	
	if( this.service.needLegend() )
	{
		var nodeLegend = this.xml.rootXml.createElement("LEGEND");
		nodeLegend.setAttribute("autoextend", "true");
		nodeLegend.setAttribute("backgroundcolor", "222,222,222");
		nodeProperties.appendChild(nodeLegend); 
	}

	var layerList = "";
	
	var nodeLayerList = this.xml.rootXml.createElement("LAYERLIST");
		
	//If service has no layers, then set the LAYERLIST nodefault attribute
	//to ensure default layers are not displayed.
	if (!this.service.layers.length)
		nodeLayerList.setAttribute("nodefault", "true");	
		
	nodeProperties.appendChild(nodeLayerList);
	
	//Need to maintain a list of the layers in this.service.aExcludedLayers that aren't included in the service. 
	//The main reason being that ArcIMS layers defaulted to visible in the ArcIMS service will still display 
	//even when they are not specified in the LAYERLIST of the GET_IMAGE request.  While the "nodefault" 
	//attribute can be set to "true" so only layers defined in the LAYERLIST are displayed, this
	//prevents feature highlights from displaying.  Hence, we instead explicitly define all layers 
	//in the LAYERLIST and set the "visible" attribute of those layers in this.service.aExcludedLayers to "false".
 	for (var i=0; i<this.service.aExcludedLayers.length; i++)
	{
		var nodeLayer = this.xml.rootXml.createElement("LAYERDEF");
		nodeLayer.setAttribute("id", this.service.aExcludedLayers[i]);
		nodeLayer.setAttribute("visible", "false");	
		nodeLayerList.appendChild(nodeLayer); 
	}
	 
	if( this.service.layers.length ) 
	{
		var aSingleHighlights = new Array();
		for( var i=0; i<this.service.layers.length; i++ ) 
		{
			var layer = this.service.layers[this.service.layersOrder[i]];
			var nodeLayer = this.xml.rootXml.createElement("LAYERDEF");
			var bVisible = (layer.bSelected && layer.bInList && layer.bInScale);
			if (bVisible) 
				bValid = true;
			nodeLayer.setAttribute("id", layer.id);
			nodeLayer.setAttribute("visible", (bVisible ? "true" : "false"));
			var sSelectedResultId = "";
			var sHighlightColor = "255,0,0";
			var dSelectedResultLabelX = 0.0;
			var dSelectedResultLabelY = 0.0;
			var aSelectedResultLabel = null;			
			
			var sMapServiceIdField = "";
			var sMapServiceLayer = "";
			var sImageLayer = layer.id.toLowerCase();
			
			if (this.service.catalog.currentSearchService && (this.service.catalog.currentSearchService.currentSearch > -1))
			{
				var search = this.service.catalog.currentSearchService.searches[this.service.catalog.currentSearchService.currentSearch];
				if (search.mapService == this.service)
				{
					//Search layer name is of the form Address_Label_1, while themes layer name is of the form Address
					var sSearchLayer = search.sMapServiceLayer.toLowerCase();
					
					if (sSearchLayer == sImageLayer)
					{
						search.decodeForm();
						if  ((search.resultsField.value != "") && 
							(this.service.catalog.currentSearchService.access.sSelectedResultId != ""))
						{
							sSelectedResultId = this.service.catalog.currentSearchService.access.sSelectedResultId;							
							dSelectedResultLabelX = this.service.catalog.currentSearchService.access.dSelectedResultLabelX;
							dSelectedResultLabelY = this.service.catalog.currentSearchService.access.dSelectedResultLabelY;

							if (sProjection.toLowerCase() != "geodetic") 
							{
								var aCoordinate = map.getENPoint(dSelectedResultLabelX, dSelectedResultLabelY, sDatum, sProjection);
								dSelectedResultLabelX = aCoordinate[0];
								dSelectedResultLabelY = aCoordinate[1];
							}

							aSelectedResultLabel = this.service.catalog.currentSearchService.access.aSelectedResultLabel;									
							sMapServiceLayer = search.sMapServiceLayer;
							sMapServiceIdField = search.sMapServiceIdField;
							bValid = true;
						}
					}
				}
			}
			
			if ((sSelectedResultId == "") &&
				(this.service.catalog.currentQueryService) && 
				(this.service.catalog.currentQueryService.access.nSelectedResultQuery > -1) &&
				(this.service.catalog.currentQueryService.access.sSelectedResultId != "") && 
				this.service.catalog.currentQueryService.queries)
			{
				var currentQueryService = this.service.catalog.currentQueryService;
				var query = currentQueryService.queries.aQueries[currentQueryService.access.nSelectedResultQuery];
				if (query.mapService == this.service)
				{
				
					dSelectedResultLabelX = currentQueryService.access.dSelectedResultLabelX;
					dSelectedResultLabelY = currentQueryService.access.dSelectedResultLabelY;

					if (sProjection.toLowerCase() != "geodetic") 
					{
						var aCoordinate = map.getENPoint(dSelectedResultLabelX, dSelectedResultLabelY, sDatum, sProjection);
						dSelectedResultLabelX = aCoordinate[0];
						dSelectedResultLabelY = aCoordinate[1];
					}				
				
					aSelectedResultLabel = currentQueryService.access.aSelectedResultLabel;	
					sSelectedResultId = currentQueryService.access.sSelectedResultId;
					sMapServiceLayer = query.sMapServiceLayer;
					sMapServiceIdField = query.sMapServiceIdField;
					var aHighlightColor = SIX.Util.hexToRgb(query.sHighlightColor);
					sHighlightColor = "" + aHighlightColor[0] + "," + aHighlightColor[1] + "," + aHighlightColor[2];
					bValid = true;
				}
			}

			//Query result highlights	
			if (this.aHighlightedResults[layer.id] && ((layer.featureType == "point") || (layer.featureType == "line") || (layer.featureType == "polygon")))
			{
				var nodeHighlightLayer = this.xml.rootXml.createElement("LAYER");
				nodeHighlightLayer.setAttribute("id", sImageLayer + "_HighlightedResults");
				nodeHighlightLayer.setAttribute("visible", "true");
				nodeHighlightLayer.setAttribute("name", sImageLayer + "_HighlightedResults");
				nodeHighlightLayer.setAttribute("type", "featureclass");
				
				var nodeDataset = this.xml.rootXml.createElement("DATASET");
				nodeDataset.setAttribute("fromlayer", layer.id);
				nodeHighlightLayer.appendChild(nodeDataset);
				
				var sSelectedResults = "";
				var aFieldValues = this.aHighlightedResults[layer.id].aFieldValues;
				for (var j=0; j<aFieldValues.length; j++)
				{
					if (!aFieldValues[j].bSelected || (aFieldValues[j].sValue == sSelectedResultId))
						continue;
					sSelectedResults += (sSelectedResults == "" ? "" : ",") + "'" + aFieldValues[j].sValue + "'";
					bValid = true;
				}
				var sWhereInClause = this.aHighlightedResults[layer.id].sFieldName + " IN (" + sSelectedResults + ")";

				var nodeSpatialQuery = this.xml.rootXml.createElement("SPATIALQUERY");
				nodeSpatialQuery.setAttribute("where", sWhereInClause);
				nodeHighlightLayer.appendChild(nodeSpatialQuery);	
				
				var nodeSimpleRenderer = this.xml.rootXml.createElement("SIMPLERENDERER");
				
				switch(layer.featureType)
				{
					case "polygon":
						var nodeSimplePolygonSymbol = this.xml.rootXml.createElement("SIMPLEPOLYGONSYMBOL");
						nodeSimplePolygonSymbol.setAttribute("boundarycolor", "0,255,0");
						nodeSimplePolygonSymbol.setAttribute("filltransparency", "0.0");
						nodeSimplePolygonSymbol.setAttribute("boundarywidth", "2");
						nodeSimpleRenderer.appendChild(nodeSimplePolygonSymbol);
						break;
					case "point":
						var nodeSimpleMarkerSymbol = this.xml.rootXml.createElement("SIMPLEMARKERSYMBOL");
						nodeSimpleMarkerSymbol.setAttribute("color", "0,255,0");
						nodeSimpleMarkerSymbol.setAttribute("width", "20");
						nodeSimpleRenderer.appendChild(nodeSimpleMarkerSymbol);
						break;
					case "line":
						var nodeSimpleLineSymbol = this.xml.rootXml.createElement("SIMPLELINESYMBOL");
						nodeSimpleLineSymbol.setAttribute("color", sHighlightColor);
						nodeSimpleLineSymbol.setAttribute("width", "2");
						nodeSimpleRenderer.appendChild(nodeSimpleLineSymbol);
						break;					
					default:
						break;
				}					
				nodeHighlightLayer.appendChild(nodeSimpleRenderer);		
				nodeGetImage.appendChild(nodeHighlightLayer);
			}
			
			if ((sSelectedResultId != "") && (sMapServiceLayer.toLowerCase() == sImageLayer) && 
				((layer.featureType == "point") || (layer.featureType == "line") || (layer.featureType == "polygon")))
			{		
				bValid = true;
				var nodeHighlightLayer = this.xml.rootXml.createElement("LAYER");
				nodeHighlightLayer.setAttribute("id", sImageLayer + "_SelectedResultHighlight");
				nodeHighlightLayer.setAttribute("visible", "true");
				nodeHighlightLayer.setAttribute("name", sImageLayer + "_SelectedResultHighlight");
				nodeHighlightLayer.setAttribute("type", "featureclass");
				
				var nodeDataset = this.xml.rootXml.createElement("DATASET");
				nodeDataset.setAttribute("fromlayer", layer.id);
				nodeHighlightLayer.appendChild(nodeDataset);
				
				var nodeSpatialQuery = this.xml.rootXml.createElement("SPATIALQUERY");
				nodeSpatialQuery.setAttribute("where", sMapServiceIdField + "=" + sSelectedResultId);
				nodeHighlightLayer.appendChild(nodeSpatialQuery);	
												
				var nodeSimpleRenderer = this.xml.rootXml.createElement("SIMPLERENDERER");
				
				switch(layer.featureType)
				{
					case "polygon":
						var nodeSimplePolygonSymbol = this.xml.rootXml.createElement("SIMPLEPOLYGONSYMBOL");
						nodeSimplePolygonSymbol.setAttribute("boundarycolor", sHighlightColor);
						nodeSimplePolygonSymbol.setAttribute("filltransparency", "0.0");
						nodeSimplePolygonSymbol.setAttribute("boundarywidth", "2");
						nodeSimpleRenderer.appendChild(nodeSimplePolygonSymbol);
						break;
					case "point":
						var nodeSimpleMarkerSymbol = this.xml.rootXml.createElement("SIMPLEMARKERSYMBOL");
						nodeSimpleMarkerSymbol.setAttribute("color", sHighlightColor);
						nodeSimpleMarkerSymbol.setAttribute("width", "20");
						nodeSimpleRenderer.appendChild(nodeSimpleMarkerSymbol);
						break;
					case "line":
						var nodeSimpleLineSymbol = this.xml.rootXml.createElement("SIMPLELINESYMBOL");
						nodeSimpleLineSymbol.setAttribute("color", sHighlightColor);
						nodeSimpleLineSymbol.setAttribute("width", "2");
						nodeSimpleRenderer.appendChild(nodeSimpleLineSymbol);
						break;						
					default:
						break;
				}	
								
				nodeHighlightLayer.appendChild(nodeSimpleRenderer);				
				//nodeGetImage.appendChild(nodeHighlightLayer);
				aSingleHighlights[aSingleHighlights.length] = nodeHighlightLayer;

				if (aSelectedResultLabel && aSelectedResultLabel.length)
				{
					var nFontSize = 11;//pts
					var nFontSizeInches = nFontSize / 72;
					var dViewHeightInches = map.height / SIX.Util.getScreenYDPI();
					var dLabelHeightWorldCoords = (map.tly - map.bry) * nFontSizeInches / dViewHeightInches;

					var sHorizontalAlignment = "center";
					if (dSelectedResultLabelX < (map.tlx + (map.brx - map.tlx)/3))
						sHorizontalAlignment = "right";
					else if (dSelectedResultLabelX > (map.brx - (map.brx - map.tlx)/3))
						sHorizontalAlignment = "left";

					var dLabelOriginY = 0.0;
					if (dSelectedResultLabelY < (map.bry + (map.tly - map.bry)/3))
						dLabelOrigin = dSelectedResultLabelY + dLabelHeightWorldCoords * aSelectedResultLabel.length;
					else if (dSelectedResultLabelY > (map.tly - (map.tly - map.bry)/3))
						dLabelOrigin = dSelectedResultLabelY;
					else
						dLabelOrigin = dSelectedResultLabelY + (dLabelHeightWorldCoords * aSelectedResultLabel.length) / 2;	
				
					var nodeLabelLayer = this.xml.rootXml.createElement("LAYER");
					nodeLabelLayer.setAttribute("id", sImageLayer + "_Acetate");
					nodeLabelLayer.setAttribute("name", sImageLayer + "_Acetate");
					nodeLabelLayer.setAttribute("type", "acetate");
					nodeGetImage.appendChild(nodeLabelLayer);	
									
					for (var j=0; j<aSelectedResultLabel.length; j++)
					{				
						var nodeObject = this.xml.rootXml.createElement("OBJECT");
						nodeObject.setAttribute("units", "database");
						nodeLabelLayer.appendChild(nodeObject);
						
						var nodeText = this.xml.rootXml.createElement("TEXT");
						
						nodeText.setAttribute("coords", "" + dSelectedResultLabelX + " " + (dLabelOrigin - j * dLabelHeightWorldCoords));
						nodeText.setAttribute("label", aSelectedResultLabel[j]);
						nodeObject.appendChild(nodeText);
						
						var nodeTextMarkerSymbol = this.xml.rootXml.createElement("TEXTMARKERSYMBOL");
						nodeTextMarkerSymbol.setAttribute("font", "Arial");
						nodeTextMarkerSymbol.setAttribute("fontsize", nFontSize);
						nodeTextMarkerSymbol.setAttribute("fontstyle", "bold");
						nodeTextMarkerSymbol.setAttribute("printmode", "titlecaps");
						
						nodeTextMarkerSymbol.setAttribute("halignment", sHorizontalAlignment);
						nodeTextMarkerSymbol.setAttribute("valignment", "bottom");
						nodeTextMarkerSymbol.setAttribute("fontcolor", "254,254,254");
						nodeTextMarkerSymbol.setAttribute("glowing", "0,0,255");
						nodeTextMarkerSymbol.setAttribute("antialiasing", "true");
						nodeTextMarkerSymbol.setAttribute("outline", "1,1,1");
						nodeTextMarkerSymbol.setAttribute("overlap", "false");
						nodeText.appendChild(nodeTextMarkerSymbol);	
					}				
				}						
			}
		
			nodeLayerList.appendChild(nodeLayer); 
		}
		
		for (var i=0; i<aSingleHighlights.length; i++)
			nodeGetImage.appendChild(aSingleHighlights[i]);
	}
	
	this.xml.rootXml.appendChild(nodeArcXML);	
	
	//Need to clean up xml before passing it to the NCSLayeredView control
	var sXML = this.xml.rootXml.xml;

	var nStartIndex = sXML.indexOf("xml version");
	var nEndIndex = sXML.indexOf("</PROPERTIES>");
	if ((nStartIndex != -1) && (nEndIndex != -1))
	{
		var sSubStr1 = sXML.substring(0, nStartIndex); 
		var sSubStr2 = sXML.substring(nStartIndex, nEndIndex);
		var sSubStr3 = sXML.substring(nEndIndex, sXML.length);
		var re = new RegExp ('"', 'gi');
		sSubStr2 = sSubStr2.replace(re, '\'');	
		re = new RegExp ('&quot;', 'gi');
		sSubStr2 = sSubStr2.replace(re, '\"');	
		sXML = sSubStr1 + sSubStr2 + sSubStr3;			
	}		
	
	var	 url  = 'mode=0;action=POST;';
		 url += 'worldTLX=' + map.tlx + ';worldTLY=' + map.tly + ';worldBRX=' + map.brx + ';worldBRY=' + map.bry + ';';
		 url += 'url=http://' + this.service.host + '/servlet/com.esri.esrimap.Esrimap?ServiceName=' + this.service.service + ';HEADER=;';
		 url += 'body=' + sXML;

	var bUpdateProgress = false;
	if (bValid)
	{
		if (this.sOldUrl == url)
		{
			map.setLayerParameter(this.service.uid, "visibility=true");
			this.service.nMapLoadState = SIX.eMapLoadState.LOADED;
			bUpdateProgress = true;
		}
		else if (map.setLayerParameter(this.service.uid, url))
		{
			this.sOldUrl = url;
			this.service.nMapLoadState = SIX.eMapLoadState.LOADING;
		}
	}
	else
	{
		bUpdateProgress = true;
		map.setLayerParameter(this.service.uid, "visibility=false");
		this.service.nMapLoadState = SIX.eMapLoadState.LOADED;	
	}
	
	if (bUpdateProgress)
	{
		var objGISOverlayMapsLoadStats = map.getGISOverlayMapsLoadStats();
		var nPercent = Math.round(100 * objGISOverlayMapsLoadStats.nNumGISOverlayMapsLoaded/objGISOverlayMapsLoadStats.nNumGISOverlayMapsRequested);

		if (map.tGISOverlayProgress != null)
		{
			clearTimeout(map.tGISOverlayProgress);
			map.tGISOverlayProgress = null;
		}	
		map.tGISOverlayProgress = setTimeout("" + map.myself + ".setGISOverlayProgress(" + nPercent + ")", 500);			
	}
}

SIX.Access.ArcXML.prototype.loadLayers = function (map)
{
	if( !this.service.loaded || !map.loaded || !this.service.isOnline || this.service.bFeatureServer)
	{
		this.service.nLayersLoadState = SIX.eLayersLoadState.NOT_LOADED;
		return;
	}

	this.service.busy(true);
	var control = document[map.uid];
	
	while (this.xml.rootXml.hasChildNodes())
            this.xml.rootXml.removeChild(this.xml.rootXml.lastChild);

	var piXML = this.xml.rootXml.createProcessingInstruction("xml", "version='1.0'");
	this.xml.rootXml.appendChild(piXML);

    var nodeArcXML = this.xml.rootXml.createElement("ARCXML");
    nodeArcXML.setAttribute("version","1.1");
    this.xml.rootXml.appendChild(nodeArcXML);
    
    var nodeRequest = this.xml.rootXml.createElement("REQUEST");
    nodeArcXML.appendChild(nodeRequest);
    
    var nodeGetServiceInfo = this.xml.rootXml.createElement("GET_SERVICE_INFO");
    nodeGetServiceInfo.setAttribute("renderer","true");
    nodeGetServiceInfo.setAttribute("extensions","false");
    nodeGetServiceInfo.setAttribute("fields","false");
    nodeGetServiceInfo.setAttribute("envelope","true");
    nodeRequest.appendChild(nodeGetServiceInfo);
    	
    var sUrl = 'http://' + this.service.host + '/servlet/com.esri.esrimap.Esrimap?ServiceName=' + this.service.service;
	var sBody = this.xml.rootXml.xml;
	var sAction = 'POST';
	var	sParams = 'mode=0;action=' + sAction + ';';
		sParams += 'worldTLX=' + map.tlx + ';worldTLY=' + map.tly + ';worldBRX=' + map.brx + ';worldBRY=' + map.bry + ';';
		sParams += 'url=' + sUrl + ';HEADER=;';
		sParams += 'body=' + sBody;

	SIX.ArcXMLServiceInfoCache.getServiceInfo(map, this.service, sParams, sUrl, sBody, sAction);
}

SIX.Access.ArcXML.prototype.showHideQueryResultDetail = function (nodeAnchor)
{
	if (!this.service.loaded || !this.service.queries || !this.service.queries.aQueries.length)
		return;
	
	var queries = this.service.queries;
	var nodeRow = getParent(nodeAnchor, "tr");
		
	if (queries.aRowToFeatureMappings[nodeRow.id])
	{
		var nResponseIndex = queries.aRowToFeatureMappings[nodeRow.id][0];
		var nFeatureIndex = queries.aRowToFeatureMappings[nodeRow.id][1];	
		var query = queries.aQueries[nResponseIndex];	
		query.sOptionalFeatureDetailsRowId = nodeRow.id;	
		
		if (query.sIdField)
		{	
			//Need Id field to retrieve feature.
			query.nFeatureIndex = nFeatureIndex;
			var sFeatureId = this.getQueryResultId(nResponseIndex, nFeatureIndex);
			if (sFeatureId != "")
			{
				if (query.aOptionalFeatureDetails[sFeatureId])
				{
					query.aOptionalFeatureDetails[sFeatureId].bDetailVisible = !query.aOptionalFeatureDetails[sFeatureId].bDetailVisible;
					
					if (query.aOptionalFeatureDetails[sFeatureId].bDetailVisible)
						nodeAnchor.innerHTML = query.sHideDetailLabel;
					else
						nodeAnchor.innerHTML = query.sShowDetailLabel;

					query.showHideDetail(sFeatureId);
				}
				else
				{								
					this.query(nResponseIndex, sFeatureId, true);
				}
			}
		}
	}
}

SIX.Access.ArcXML.prototype.query = function (nIndex, sFeatureId, bIncludeOptionalFields)
{
	var catalog = this.service.catalog;
	var map = catalog.maps[0];
	
	if (!this.service.queries || (this.service.queries.aQueries.length < nIndex))
		return;
		
	var query = this.service.queries.aQueries[nIndex];
	
	catalog.currentQueryService = this.service;
	if (query.mapService && query.mapService.catalog)			
        query.mapService.catalog.currentQueryService = this.service;	

	
	while (this.xml.rootXml.hasChildNodes())
			this.xml.rootXml.removeChild(this.xml.rootXml.lastChild);

	var piXML = this.xml.rootXml.createProcessingInstruction("xml", "version='1.0'");
	this.xml.rootXml.appendChild(piXML);

	var nodeArcXML = this.xml.rootXml.createElement("ARCXML");
	nodeArcXML.setAttribute("version","1.1");
	this.xml.rootXml.appendChild(nodeArcXML);
	
	var nodeRequest = this.xml.rootXml.createElement("REQUEST");
	nodeArcXML.appendChild(nodeRequest);
		
	var nodeGetFeatures = this.xml.rootXml.createElement("GET_FEATURES");
	nodeGetFeatures.setAttribute("featurelimit",1);  
	nodeGetFeatures.setAttribute("beginrecord",0);
	nodeGetFeatures.setAttribute("outputmode","newxml");
	nodeGetFeatures.setAttribute("geometry","false");
	nodeGetFeatures.setAttribute("envelope","true");
	nodeGetFeatures.setAttribute("compact","true");
	nodeRequest.appendChild(nodeGetFeatures);

	var nodeLayer = this.xml.rootXml.createElement("LAYER");
	
	nodeLayer.setAttribute("id", query.key);
	nodeGetFeatures.appendChild(nodeLayer); 
	
	var sSubFields = "";
	var bGotIdField = false;		
	for( var j=0; j<query.fields.length; j++ ) 
	{		
		if (query.fields[j].bRequest)
		{
			if (query.fields[j].key == query.sIdField)
				bGotIdField = true;
			
			sSubFields += ((j == 0) ? "" : " ") + query.fields[j].key;
		}
	}	

	if (bIncludeOptionalFields)
	{
		for( var j=0; j<query.aOptionalFields.length; j++ ) 
		{		
			if (query.aOptionalFields[j].bRequest)
				sSubFields += ((sSubFields == "") ? "" : " ") + query.aOptionalFields[j].key; 
		}			
	}
	
	if (query.sIdField && !bGotIdField)
		sSubFields += " " + query.sIdField; 
	
	var nodeSpatialQuery = this.xml.rootXml.createElement("SPATIALQUERY");			
	nodeSpatialQuery.setAttribute("subfields", sSubFields + " #SHAPE#");
	
	var sWhereClause = "";
	
	if (sFeatureId && (sFeatureId != ""))
	{
		sWhereClause = query.sIdField + "=" + sFeatureId;
	}
	else
	{	
		for (var j=0; j<query.fields.length; j++)
		{
			if (query.fields[j].value && (query.fields[j].value != "") && query.fields[j].bRequest)
				sWhereClause += ((sWhereClause == "") ? "" : " AND ") + query.fields[j].key + " = '" + query.fields[j].value + "'";	
		}
	}
	
	nodeSpatialQuery.setAttribute("where", sWhereClause);
		
	nodeGetFeatures.appendChild(nodeSpatialQuery);	

	var sHost = (query.sHost ? query.sHost : this.service.host); 
	var sService = (query.sService ? query.sService : this.service.service);

	var	 url  = 'mode=0;action=POST;';
		url += 'worldTLX=' + map.tlx + ';worldTLY=' + map.tly + ';worldBRX=' + map.brx + ';worldBRY=' + map.bry + ';';
		url += 'url=http://' + sHost + '/servlet/com.esri.esrimap.Esrimap?ServiceName=' + sService + '&CustomService=query;HEADER=;';
		url += 'body=' + this.xml.rootXml.xml;
	
	var control = document[map.uid];
	
	var result = map.setLayerParameter(query.uid, url);
}

SIX.Access.ArcXML.prototype.queryLayers = function (map, bResetQueries) 
{
	if( !this.service.loaded || !map.loaded || !this.service.queries || !this.service.queries.aQueries.length)
		return;
	
	if ((map.queryPoints.length < 1) && (map.nQueryType != SIX.eQueryTypes.POLYGON))
		return;
		
	this.service.busy(true);
	this.service.nLayersLoadState = SIX.eLayersLoadState.LOADED;
	
	var queries = this.service.queries;
	
	if ((map.queryPoints.length == 1) && SIX.App.bMouseDownWithCtrlKey)
	{
		for (var i=0; i<queries.aQueries.length; i++)
		{
			var query = queries.aQueries[i];
			if (map.aQueryPolygonCollections[query.sPolygonCollectionId])
			{
				var aGeoPoint = map.getGeoPoint(map.queryPoints[0].worldX, map.queryPoints[0].worldY);
				var queryPolygonCollection = map.aQueryPolygonCollections[query.sPolygonCollectionId];
				var point = new SIX.Point(aGeoPoint[0], aGeoPoint[1]);
				for (var j in queryPolygonCollection.aPolygons)
				{
					if (queryPolygonCollection.aPolygons.hasOwnProperty(j))
					{
						var polygon = queryPolygonCollection.aPolygons[j];
						if (polygon.containsPoint(point))
						{
							queryPolygonCollection.aPolygonsSelectionState[j] = !queryPolygonCollection.aPolygonsSelectionState[j];
							this.sSelectedResultId = queryPolygonCollection.aPolygonsSelectionState[j] ? j : "";
							this.nSelectedResultQuery = i;				
							this.service.catalog.currentQueryService = this.service;
							if (query.mapService && query.mapService.catalog)			
								query.mapService.catalog.currentQueryService = this.service;	
							
							var nFeatureIndex = query.aFeatureIndices[j];
							this.setQueryResultSelectionState(i, nFeatureIndex, queryPolygonCollection.aPolygonsSelectionState[j]);		
							
							if (query.mapService.access.aHighlightedResults[query.sMapServiceLayer])
							{
								var aFieldValues = query.mapService.access.aHighlightedResults[query.sMapServiceLayer].aFieldValues;
								for (var k=0; k<aFieldValues.length; k++)
								{
									if (aFieldValues[k].sValue == j)
										aFieldValues[k].bSelected = queryPolygonCollection.aPolygonsSelectionState[j];
								}
							}
							this.highlightQueryResults();
							break;
						}	
					}	
				}
			}
		}
		return;
	}	
	
	this.bMoreResults = false;
	if (arguments.length < 2) 
	{
		bResetQueries = true;
		queries.nCurrentQueryType = map.nQueryType;
	}
	this.bGotResults = !bResetQueries;
	this.nNumRequests = 0;
	this.nNumResponses = 0;
	var bFirstRequest = true;
	
	this.nSelectedResultQuery = -1;
	
	//Reset column totals
	var aColumnTotals = queries.aColumnTotals;
	for (var i=0; i<aColumnTotals.length; i++)
		aColumnTotals[i] = null;
	
	for (var i=0; i<queries.aQueries.length; i++)  
	{
		var query = queries.aQueries[i];

		query.sOptionalFeatureDetailsRowId = null;
		query.aOptionalFeatureDetails = new Object();
		
		if (bResetQueries)
			query.nQueryOffset = 0;
		
		if (query.mapService) 
		{
			var mapService = query.mapService;
			query.bCanQuery = false;
			if (query.bAlwaysOn == true)
				query.bCanQuery = true;
			for (var j=0; j<mapService.layers.length; j++)
			{
				var layer = mapService.layers[j];
				if (query.sMapServiceLayer == layer.id)
				{
					if (query.bAlwaysOn ||
						((query.bQueryOutOfScale || layer.bInScale) && (query.bQueryUnselected || layer.bSelected)))
					{
						this.nNumRequests++;	
						query.bCanQuery = true;
					}
					break;
				}			
			}
		}	
	}
	   
	for (var i=0; i<queries.aQueries.length; i++)	    
	{		
		var query = queries.aQueries[i];
		if (query.bCanQuery == false)
			continue;
		while (this.xml.rootXml.hasChildNodes())
				this.xml.rootXml.removeChild(this.xml.rootXml.lastChild);

		var piXML = this.xml.rootXml.createProcessingInstruction("xml", "version='1.0'");
		this.xml.rootXml.appendChild(piXML);

		var nodeArcXML = this.xml.rootXml.createElement("ARCXML");
		nodeArcXML.setAttribute("version","1.1");
		this.xml.rootXml.appendChild(nodeArcXML);
		
		var nodeRequest = this.xml.rootXml.createElement("REQUEST");
		nodeArcXML.appendChild(nodeRequest);
		    
		var nodeGetFeatures = this.xml.rootXml.createElement("GET_FEATURES");
		nodeGetFeatures.setAttribute("featurelimit",query.nQueryCount);  
		nodeGetFeatures.setAttribute("beginrecord", query.nQueryOffset);
		nodeGetFeatures.setAttribute("outputmode","newxml");
		nodeGetFeatures.setAttribute("geometry",((query.sPolygonCollectionId || query.bGeometry) ? "true" : "false"));
		nodeGetFeatures.setAttribute("envelope","true");
		nodeGetFeatures.setAttribute("compact","true");
		nodeRequest.appendChild(nodeGetFeatures);

		if (query.sPolygonCollectionId)
		{
			if (map.aQueryPolygonCollections[query.sPolygonCollectionId])
			{
				delete map.aQueryPolygonCollections[query.sPolygonCollectionId];
				map.aQueryPolygonCollections[query.sPolygonCollectionId] = new SIX.QueryPolygonCollection();
			}
			delete query.aFeatureIndices;
			query.aFeatureIndices = new Object();
		}

		if (bFirstRequest) 
		{
			queries.deleteResults();
			queries.addLoadingResultsRow();
			bFirstRequest = false;
		}
		var nodeLayer = this.xml.rootXml.createElement("LAYER");
		var sLayerId = query.key;
		nodeLayer.setAttribute("id", sLayerId);
		nodeGetFeatures.appendChild(nodeLayer); 
		
		var nodeQuery = this.xml.rootXml.createElement("SPATIALQUERY");
		var sSubFields = "";
		var sWhereClause = "";
		
		for( var j=0; j<query.fields.length; j++ ) 
		{		
			if (query.fields[j].bRequest)
				sSubFields += ((j == 0) ? "" : " ") + query.fields[j].key;
		}	
		
		if (query.sIdField)
		{
			sSubFields += " " + query.sIdField; 
		} 
			
		switch(this.service.queries.nCurrentQueryType)
		{
			case SIX.eQueryTypes.POINT_LABEL :
			{
				var nodeSpatialFilter = this.xml.rootXml.createElement("SPATIALFILTER");
				nodeSpatialFilter.setAttribute("relation","area_intersection");

				if (map.queryPoints.length == 1)
				{			
					var aGeoPoint = map.getGeoPoint(map.queryPoints[0].worldX, map.queryPoints[0].worldY);
					var nodeMultiPoint = this.xml.rootXml.createElement("MULTIPOINT");
					var nodePoint = this.xml.rootXml.createElement("POINT");
					nodePoint.setAttribute("x", aGeoPoint[0]);
					nodePoint.setAttribute("y", aGeoPoint[1]);
					nodeMultiPoint.appendChild(nodePoint);
					nodeSpatialFilter.appendChild(nodeMultiPoint);
					nodeQuery.appendChild(nodeSpatialFilter);
				}	
			}					
			break;
			case SIX.eQueryTypes.POINT :
			case SIX.eQueryTypes.RECTANGLE :
			case SIX.eQueryTypes.POINT_OR_RECTANGLE :
			{
				var nodeSpatialFilter = this.xml.rootXml.createElement("SPATIALFILTER");
				nodeSpatialFilter.setAttribute("relation","area_intersection");

				if (map.queryPoints.length == 1)
				{
					var aGeoPoint = map.getGeoPoint(map.queryPoints[0].worldX, map.queryPoints[0].worldY);
					var nodeMultiPoint = this.xml.rootXml.createElement("MULTIPOINT");
					var nodePoint = this.xml.rootXml.createElement("POINT");
					nodePoint.setAttribute("x", aGeoPoint[0]);
					nodePoint.setAttribute("y", aGeoPoint[1]);
					nodeMultiPoint.appendChild(nodePoint);
					nodeSpatialFilter.appendChild(nodeMultiPoint);
					nodeQuery.appendChild(nodeSpatialFilter);						
				}
				else if (map.queryPoints.length == 2)
				{
					var sDatum = map.datum();
					var sProjection = map.projection();
					var aCoords = map.convertCoords(sDatum, sProjection, [[map.queryPoints[0].worldX, map.queryPoints[0].worldY], [map.queryPoints[1].worldX, map.queryPoints[1].worldY]], sDatum, "geodetic");
					var dMinX = aCoords[0][0];
					var dMaxY = aCoords[0][1];	
					var dMaxX = aCoords[1][0];
					var dMinY = aCoords[1][1];	
			
					var nodeSpatialFilterEnvelope = this.xml.rootXml.createElement("ENVELOPE");
					nodeSpatialFilterEnvelope.setAttribute("minx", dMinX);
					nodeSpatialFilterEnvelope.setAttribute("miny", dMinY);
					nodeSpatialFilterEnvelope.setAttribute("maxx", dMaxX);
					nodeSpatialFilterEnvelope.setAttribute("maxy", dMaxY);	
					nodeSpatialFilter.appendChild(nodeSpatialFilterEnvelope);
					nodeQuery.appendChild(nodeSpatialFilter);	
				}
			}
			break;
			case SIX.eQueryTypes.POLYGON :
			{
				var bGotPolygon = false;
				if (map.aQueryPolygonCollections[queries.sPolygonCollectionId])
				{	
					var aQueryPolygonCollection = map.aQueryPolygonCollections[queries.sPolygonCollectionId];
					var nodePolygon = this.xml.rootXml.createElement("POLYGON");
					for (var sFeatureId in aQueryPolygonCollection.aPolygons)
					{
						if (aQueryPolygonCollection.aPolygons.hasOwnProperty(sFeatureId))
						{
							if (aQueryPolygonCollection.aPolygonsSelectionState[sFeatureId])
							{
								bGotPolygon = true;
								var polygon = aQueryPolygonCollection.aPolygons[sFeatureId];
								for (var j=0; j<polygon.aRings.length; j++)
								{
									var nodeRing = this.polygonRingToNode(polygon.aRings[j]);
									nodePolygon.appendChild(nodeRing);
								}
							}
						}
					}
				}
			
				if (!bGotPolygon)
				{
					queries.deleteResults();
					queries.addNoResultsRow();
					return;
				}
				var nodeSpatialFilter = this.xml.rootXml.createElement("SPATIALFILTER");
				nodeSpatialFilter.setAttribute("relation","area_intersection");
				nodeSpatialFilter.appendChild(nodePolygon);
				nodeQuery.appendChild(nodeSpatialFilter);
			}
			break;			
			case SIX.eQueryTypes.ZONES :
			{
				var nodeSpatialFilter = this.xml.rootXml.createElement("SPATIALFILTER");
				nodeSpatialFilter.setAttribute("relation","area_intersection");

				if (this.service.queries.nCurrentQueryZone < 0)
					this.service.queries.nCurrentQueryZone = 0;			
			
				var sEPSG = "";
				var sDefinitionString = "";
				var sProjection = map.projection();
				var sDatum = map.datum();
					
				var nEPSGCode = GDTEPSGMappings.getEPSGCode(sDatum, sProjection);
				if (nEPSGCode && this.service.supportsEPSG(nEPSGCode))
					sEPSG = "" + nEPSGCode;
				else
				{
					var sWKT = GDTEPSGMappings.getEPSGWKTFromDatumProjection(sDatum, sProjection);
					if (sWKT)
						sDefinitionString = sWKT;
				}
			    
				var nodeFilterCoordSys = this.xml.rootXml.createElement("FILTERCOORDSYS");
				var nodeFeatureCoordSys = this.xml.rootXml.createElement("FEATURECOORDSYS");
			    
				if (sEPSG != "") 
				{
					nodeFilterCoordSys.setAttribute("id", sEPSG);
					nodeFeatureCoordSys.setAttribute("id", sEPSG);
				}
				else if (sDefinitionString != "")
				{
					nodeFilterCoordSys.setAttribute("string", sDefinitionString);
					nodeFeatureCoordSys.setAttribute("string", sDefinitionString);	
				}
			    
				if ((sEPSG != "") || (sDefinitionString != "")) 
				{ 
					nodeQuery.appendChild(nodeFilterCoordSys); 
					nodeQuery.appendChild(nodeFeatureCoordSys); 		
				}	    			
			
				//Can't do ArcXML queries within a buffer zone of an arc, so need to approximate arc with pol
				var nNumCircleToPolylinePoints = 65;//Points = Vertices + 1;
				var dCenterRadius = map.aQueryZones[this.service.queries.nCurrentQueryZone].dInnerRadius + (map.aQueryZones[this.service.queries.nCurrentQueryZone].dOuterRadius - map.aQueryZones[this.service.queries.nCurrentQueryZone].dInnerRadius) / 2;
				var aPolygonPoints = SIX.Util.circleToPolyline(map.pointQueryZonesCenter.worldX, map.pointQueryZonesCenter.worldY, dCenterRadius , 360, 0, 1, nNumCircleToPolylinePoints);
				
				var nodePath = this.xml.rootXml.createElement("PATH");
				
				var nodePolyline = this.xml.rootXml.createElement("POLYLINE");
				
				
				for (var j=0; j<aPolygonPoints.length; j++)
				{
					var nodePoint = this.xml.rootXml.createElement("POINT");
					nodePoint.setAttribute("x", aPolygonPoints[j].x);
					nodePoint.setAttribute("y", aPolygonPoints[j].y);
					nodePath.appendChild(nodePoint);
				}						
				
				nodePolyline.appendChild(nodePath);
				nodeSpatialFilter.appendChild(nodePolyline);
				
				var nodeBuffer = this.xml.rootXml.createElement("BUFFER");
				nodeBuffer.setAttribute("distance", map.dQueryZonesIntervalDistance / 2);
				nodeBuffer.setAttribute("bufferunits", "meters");
				nodeSpatialFilter.appendChild(nodeBuffer);
				
				nodeQuery.appendChild(nodeSpatialFilter);
			}					
			break;
			default: 
			break;
		}
		
		nodeQuery.setAttribute("subfields", sSubFields + " #SHAPE#");
		 	
		nodeGetFeatures.appendChild(nodeQuery);	

		//Need to clean up xml before passing it to the NCSLayeredView control
		var sXML = this.xml.rootXml.xml;
		var nStartIndex = sXML.indexOf("xml version");
		var nEndIndex = sXML.indexOf("</SPATIALQUERY>");

		if ((nStartIndex != -1) && (nEndIndex != -1))
		{
			var sSubStr1 = sXML.substring(0, nStartIndex); 
			var sSubStr2 = sXML.substring(nStartIndex, nEndIndex);
			var sSubStr3 = sXML.substring(nEndIndex, sXML.length);
			var re = new RegExp ('"', 'gi');
			sSubStr2 = sSubStr2.replace(re, '\'');	
			re = new RegExp ('&quot;', 'gi');
			sSubStr2 = sSubStr2.replace(re, '\"');	
			sXML = sSubStr1 + sSubStr2 + sSubStr3;			
		}		
		    
		var	 url  = 'mode=0;action=POST;';
			url += 'worldTLX=' + map.tlx + ';worldTLY=' + map.tly + ';worldBRX=' + map.brx + ';worldBRY=' + map.bry + ';';
			url += 'url=http://' + (query.sHost ? query.sHost : this.service.host) + '/servlet/com.esri.esrimap.Esrimap?ServiceName=' + (query.sService ? query.sService : this.service.service) + '&CustomService=query;HEADER=;';
			url += 'body=' + sXML;
				
		var queryMap = this.service.catalog.maps[0];
	    var result = queryMap.setLayerParameter(query.uid, url);
	}
}

SIX.Access.ArcXML.prototype.updateQueryResult = function ()
{
	var aSummary = new Array();
	var aDetail = new Array();
	var sFeatureId = "";
	var query = this.service.queries.aQueries[this.service.queries.currentQuery];

	var nodeFeatures  = this.xml.rootXml.getElementsByTagName("FEATURES")[0];
	{	
		var featureNode = nodeFeatures.getElementsByTagName("FEATURE")[0];
		if (featureNode)
		{										
			var nodeFields = featureNode.getElementsByTagName("FIELDS")[0];
			if (nodeFields)
			{
				var fieldNodes = nodeFields.getElementsByTagName("FIELD");

				for( var j=0; j<fieldNodes.length; j++ ) 
				{	
					var sFieldValue = fieldNodes[j].getAttribute("value");
					var sFieldName = fieldNodes[j].getAttribute("name");
	
					if ((sFieldName.toLowerCase() == query.sIdField.toLowerCase()) && (sFieldValue != ""))
						sFeatureId = sFieldValue;
						
					for (var k=0; k<query.fields.length; k++)
					{									
						var field = query.fields[k];
						if ((sFieldName.toLowerCase() == field.key.toLowerCase()) && (query.bDelimitEmptyFields || sFieldValue != ""))
						{
							var sFieldNameValue = (((query.fields.length == 1) || (field.name == "")) ? "" : field.name + ": ") + sFieldValue;								
							if ((query.sFieldDisplay == "horizontal") && (aSummary.length))
								sFieldNameValue = query.sSpacesBeforeDelimiter + query.sDelimiter + 
													(sFieldNameValue == "" ? "" : (query.sSpacesAfterDelimiter + sFieldNameValue));
							aSummary[aSummary.length] = sFieldNameValue;
						}
					}

					for (var k=0; k<query.aOptionalFields.length; k++)
					{		
						var field = query.aOptionalFields[k];							
						if ((sFieldName.toLowerCase() == field.key.toLowerCase()) && (query.bDelimitEmptyFields || sFieldValue != ""))
						{
							var sFieldNameValue = ((field.name == "") ? "" : field.name + ": ") + sFieldValue;
							if ((query.sFieldDisplay == "horizontal") && (aDetail.length))
								sFieldNameValue = query.sSpacesBeforeDelimiter + query.sDelimiter + 
												(sFieldNameValue == "" ? "" : (query.sSpacesAfterDelimiter + sFieldNameValue));
							aDetail[aDetail.length] = sFieldNameValue;
						}
					}					
				}
					
				if (sFeatureId != "")
				{
					if (!query.aOptionalFeatureDetails[sFeatureId])
					{
						query.aOptionalFeatureDetails[sFeatureId] = new Object();
						query.aOptionalFeatureDetails[sFeatureId].bDetailVisible = true;
					}
					
					query.aOptionalFeatureDetails[sFeatureId].aSummary = aSummary;
					query.aOptionalFeatureDetails[sFeatureId].aDetail = aDetail;
				}
			}
		}
	}

	query.showHideDetail(sFeatureId);
	query.sOptionalFeatureDetailsRowId = null;
}

/*
** Polygon feature can be made up of many rings.  Each ring can contain many holes.
*/

SIX.Access.ArcXML.prototype.polygonRingToNode = function (ring)
{
	var nodeRing = this.xml.rootXml.createElement("RING");
	
	for (var i=0; i<ring.aHoles.length; i++)
	{
		var hole = ring.aHoles[i];
		var nodeHole = this.xml.rootXml.createElement("HOLE");
		nodeRing.appendChild(nodeHole);
		this.addPointsToPolygonNode(nodeHole, hole.aPoints);
	}
	
	this.addPointsToPolygonNode(nodeRing, ring.aPoints);
	return nodeRing;
}

SIX.Access.ArcXML.prototype.addPointsToPolygonNode = function (node, aPoints)
{
	//Parameters passed to the NCSLayeredView control's SetLayerParameter() method are delimited by semi-colons.
	//Unfortunately, the semi-colons used to delimit coordinates in the COORDS node (when compact ArcXML notation 
	//is used) are incorrectly treated as layer parameter delimiters, so coordinates must be specified using
	//a series of individual POINT nodes which generates a larger request.
	var bCompact = false;
	if (bCompact) 
	{
		var nodeCoords = this.xml.rootXml.createElement("COORDS");
		node.appendChild(nodeCoords);
		var sCoords = "";
		for (var i=0; i<aPoints.length; i++)
		{
			var point = aPoints[i];
			sCoords += (i > 0 ? ";" : "") + point.x + " " + point.y;
		}
		var textNodeCoords = this.xml.rootXml.createTextNode(sCoords);
		nodeCoords.appendChild(textNodeCoords);
	}
	else
	{
		for (var i=0; i<aPoints.length; i++)
		{
			var point = aPoints[i];
			var nodePoint = this.xml.rootXml.createElement("POINT");
			nodePoint.setAttribute("x", point.x);
			nodePoint.setAttribute("y", point.y);
			node.appendChild(nodePoint);
		}
	}
}

SIX.Access.ArcXML.prototype.getEnvelope = function (nodeEnvelope)
{
	var envelope;
	var sAttrMinX = nodeEnvelope.getAttribute("minx");
	var sAttrMinY = nodeEnvelope.getAttribute("miny");	
	var sAttrMaxX = nodeEnvelope.getAttribute("maxx");	
	var sAttrMaxY = nodeEnvelope.getAttribute("maxy");

	if (sAttrMinX && sAttrMinY && sAttrMaxX && sAttrMaxY)
	{
		var dMinX = parseFloat(sAttrMinX);
		var dMinY = parseFloat(sAttrMinY);
		var dMaxX = parseFloat(sAttrMaxX);
		var dMaxY = parseFloat(sAttrMaxY);
		if (!isNaN(dMinX) && !isNaN(dMinY) && !isNaN(dMaxX) && !isNaN(dMaxY))
			envelope = new SIX.Envelope(dMinX, dMinY, dMaxX, dMaxY); 
	}
	return envelope;
}

SIX.Access.ArcXML.prototype.getPolygon = function (nodePolygon, nodeEnvelope)
{
	var polygon;
	var aPolygonRings = new Array();
	
	var envelope; 
	if (nodeEnvelope)
		envelope = this.getEnvelope(nodeEnvelope);
	
	var ringNodes = nodePolygon.getElementsByTagName("RING");
	if (ringNodes)
	{
		for (var i=0; i<ringNodes.length; i++) 
		{
			var nodeRing = ringNodes[i];
			var aRingPoints = this.getPointsFromNode(nodeRing);
			
			var aPolygonHoles = new Array();
			var holeNodes = nodeRing.getElementsByTagName("HOLE");
			for (var j=0; j<holeNodes.length; j++) 
			{
				var nodeHole = holeNodes[j];
				var aHolePoints = this.getPointsFromNode(nodeHole);
				aPolygonHoles[aPolygonHoles.length] = new SIX.PolygonHole(aHolePoints);
			}
			
			aPolygonRings[aPolygonRings.length] = new SIX.PolygonRing(aRingPoints, aPolygonHoles);
		}
	}	
	polygon = new SIX.Polygon(aPolygonRings, envelope);
	return(polygon);
}

/*
** Node can be either RING node or HOLE node
** Note: RING node can contain HOLE nodes which also contain points 
** so can't use getElementsByTagName(<"POINT" | "COORDS">).
*/
SIX.Access.ArcXML.prototype.getPointsFromNode = function (node)
{
	var aPoints = new Array();
	for (var i=0; i<node.childNodes.length; i++) 
	{
		var nodeChild = node.childNodes[i];
		var sNodeNameLowerCase = nodeChild.nodeName.toLowerCase();
		if (sNodeNameLowerCase == "coords") 
		{
			//Compact Arcxml uses 1 COORDS node to store points
			var sNodeValue = nodeChild.childNodes[0].nodeValue;
			var aCoords = sNodeValue.split(";");
			for (var j=0; j<aCoords.length; j++)
			{
				var aPoint = aCoords[j].split(" ");
				if (aPoint.length == 2)
				{
					var dX = parseFloat(aPoint[0]);
					var dY = parseFloat(aPoint[1]);
					if (!isNaN(dX) && !isNaN(dY))
						aPoints[j] = new SIX.Point(dX, dY);
				}
				if (!aPoints[j])
				{
					aPoints.length = 0;
					break;
				}
			}
			break;
		}
		else if (sNodeNameLowerCase == "point")
		{
			//Non-compact Arcxml uses individual POINT nodes to store points
			var sX = nodeChild.getAttribute("x");
			var sY = nodeChild.getAttribute("y");	
			var dX = parseFloat(sX);
			var dY = parseFloat(sY);
			if (!isNaN(dX) && !isNaN(dY))
			{
				aPoints[aPoints.length] = new SIX.Point(dX, dY);
			}
			else
			{
				aPoints.length = 0;
				break;
			}
		}
	}
	return aPoints;
}

SIX.Access.ArcXML.prototype.queryResponse = function (map)
{
	var nodeFeatures  = this.xml.rootXml.getElementsByTagName("FEATURES")[0];
	if (nodeFeatures) 
	{
		var queries = this.service.queries;
		var query = queries.aQueries[queries.currentQuery];
				
		var aColumnTotals = queries.aColumnTotals;
		for (var i=0; i<query.fields.length; i++)
		{		
			if (query.fields[i].bShowTotal && (query.fields[i].name != ""))
			{
				
				if (!aColumnTotals[query.fields[i].nColumnIndex])
					aColumnTotals[query.fields[i].nColumnIndex] = new Object();
				if (!aColumnTotals[query.fields[i].nColumnIndex][query.fields[i].name])
					aColumnTotals[query.fields[i].nColumnIndex][query.fields[i].name] = 0.0;		
			}
		}

		if (query.sOptionalFeatureDetailsRowId)
		{
			//Update existing results with additional information.
			this.updateQueryResult();
			return;
		}
		
		if (query.bZoomToFirstFeature)
		{
			this.nSelectedResultQuery = queries.currentQuery;
			this.zoomToFeature(query.sIdField, 0, query.dMinZoomWidth, query.dMinZoomHeight);
			return;
		}

		var bGotResults = false;
		var bFirstResponse = !this.nNumResponses;
		this.nNumResponses++;		
		query.sResponse = this.xml.rootXml.xml;

		var nFeatureCount = 0;
		var nodeFeatureCount = nodeFeatures.getElementsByTagName("FEATURECOUNT")[0];					
		if (nodeFeatureCount) 
		{
			var sFeatureCount = nodeFeatureCount.getAttribute("count");
			if (!isNaN(parseInt(sFeatureCount)))
				nFeatureCount = parseInt(sFeatureCount);
		}

		var featureNodes = nodeFeatures.getElementsByTagName("FEATURE");
		
		if (bFirstResponse)
		{		
			queries.deleteResults();
			if (query.nQueryOffset)
				queries.addLastSetOfResultsRow();
			else if (queries.nCurrentQueryZone > 0)
				queries.addLastSetOfResultsRow();
				
			queries.addHeaders();					
		}
		
		if (nFeatureCount && featureNodes)
		{				
			var aFeatureLabel = null;	
			var aFieldValuesAndEnvelope = new Array();//Used to prevent duplicate query results.
		
			var sLastFeatureId = "";
		
			for (var i=0; i<featureNodes.length; i++) 
			{
				var nodeFeature = featureNodes[i];
				if (nodeFeature.childNodes.length < 1)
					continue;
				var sCurrentFeatureId = "";
				
				var aCurrentFeatureFieldsToTotal = new Array();
				for (var j=0; j<aColumnTotals.length; j++)
				{
					aCurrentFeatureFieldsToTotal[j] = new Object();
					for (var k in aColumnTotals[j])
					{
						if (aColumnTotals[j].hasOwnProperty(k))
							aCurrentFeatureFieldsToTotal[j][k] = 0.0;
					}	
				}	
						
				var aCurrentFeatureLabel = new Array();	
					
				var dTopLeftX = 0.0;
				var dTopLeftY = 0.0;
				var dBottomRightX = 0.0;
				var dBottomRightY = 0.0;				
				
				var nodeEnvelope = featureNodes[i].getElementsByTagName("ENVELOPE")[0];					
				if (nodeEnvelope) 
				{	
					var sAttrMinX = nodeEnvelope.getAttribute("minx");
					var sAttrMinY = nodeEnvelope.getAttribute("miny");	
					var sAttrMaxX = nodeEnvelope.getAttribute("maxx");	
					var sAttrMaxY = nodeEnvelope.getAttribute("maxy");

					if (sAttrMinX)
						dTopLeftX = parseFloat(sAttrMinX);
					if (sAttrMinY)
						dBottomRightY = parseFloat(sAttrMinY);
					if (sAttrMaxX)
						dBottomRightX = parseFloat(sAttrMaxX);
					if (sAttrMaxY)
						dTopLeftY = parseFloat(sAttrMaxY);
								
				}	
				
				var objFeature = new Object();	
				objFeature.dTopLeftX = dTopLeftX;
				objFeature.dTopLeftY = dTopLeftY;
				objFeature.dBottomRightX = dBottomRightX;
				objFeature.dBottomRightY = dBottomRightY;
				objFeature.aFieldValues = new Array();
				for (var j=0; j<query.fields.length; j++)
					objFeature.aFieldValues[j] = "";							
											
				var nodeFields = featureNodes[i].getElementsByTagName("FIELDS")[0];
				if (nodeFields)
				{
					var aMetadata = new Array();
					var bIncludeFeature = true;
					var fieldNodes = nodeFields.getElementsByTagName("FIELD");
					var aResult = new Array();
					aResult[0] = query.name;
					aResult[1] = (query.fields.length <= 1 ? "" : new Array());

					for( var j=0; j<fieldNodes.length; j++ ) 
					{	
						var sFieldValue = fieldNodes[j].getAttribute("value");
						var sFieldName = fieldNodes[j].getAttribute("name");
	
						if (sFieldName.toLowerCase() == query.sIdField.toLowerCase())
							sCurrentFeatureId = sFieldValue;
	
						for (var k=0; k<query.fields.length; k++)
						{	
							if (sFieldName.toLowerCase() == query.fields[k].key.toLowerCase())
							{
								objFeature.aFieldValues[k] = sFieldValue;
								var objNameValue = new Object();
								objNameValue.sName = sFieldName;
								objNameValue.sValue = sFieldValue;
								aMetadata[aMetadata.length] = objNameValue;
								break;
							}
						}		
					}
 
					for (var j=0; j<query.fields.length; j++)
					{	
						var field = query.fields[j];
						for( var k=0; k<fieldNodes.length; k++ ) 
						{	
							var sFieldValue = fieldNodes[k].getAttribute("value");
							var sFieldName = fieldNodes[k].getAttribute("name");
							
							if (!(field.bHideIfDuplicateFeatureId && (sCurrentFeatureId == sLastFeatureId)) && (sFieldName.toLowerCase() == field.key.toLowerCase()) && (query.bDelimitEmptyFields || sFieldValue != "") && !field.bHidden)
							{
								var nColumnIndex = field.nColumnIndex;
								
								if (field.bShowTotal)
								{
									var dValue = parseFloat(sFieldValue);
									if (!isNaN(dValue))
										aCurrentFeatureFieldsToTotal[field.nColumnIndex][field.name] = dValue;	
								}	
								
								if (field.aLookupTable)
								{
									var aLookupTable = field.aLookupTable;

									if (field.sPrimaryLookupFieldKey && 
										(field.sPrimaryLookupFieldKey.toLowerCase() != field.key.toLowerCase()))
									{
										for (var l=0; l<query.fields.length; l++)
										{
											if (query.fields[l].key.toLowerCase() == field.sPrimaryLookupFieldKey.toLowerCase()) 
											{
												var value = aLookupTable[objFeature.aFieldValues[l]];
												if (!value) value = aLookupTable["#" + objFeature.aFieldValues[l]];

												if (value && (typeof value == "object"))
													aLookupTable = value;

												break;
											}
										}
									}
									if (aLookupTable[sFieldValue])
										sFieldValue = aLookupTable[sFieldValue];
									else if (aLookupTable["#" + sFieldValue])
										sFieldValue = aLookupTable["#" + sFieldValue];	
								}
								
								if ((field.bConvertTimeStampToDate) && (sFieldValue != ""))
									sFieldValue = SIX.Util.timeStampToDate(sFieldValue, field.sDateFormat);
								
								if (field.fnGetValue)
									sFieldValue = field.fnGetValue(sFieldValue, objFeature.aFieldValues);
								
								if (query.fields.length == 1)
								{
									if (queries.bFieldNameColumn)
										aResult[nColumnIndex - 1] = field.name;							
								
									aResult[nColumnIndex] = sFieldValue;
									aCurrentFeatureLabel[0] = sFieldValue;
								}
								else
								{
									if (queries.bFieldNameColumn)
									{
										if (!aResult[nColumnIndex - 1])
											aResult[nColumnIndex - 1] = new Array();
										aResult[nColumnIndex - 1][aResult[nColumnIndex - 1].length] = field.name;		
									}		
								
									if (!aResult[nColumnIndex])
										aResult[nColumnIndex] = new Array();

									var sFieldNameValue = ((field.name == "" || !field.bShowLabel || queries.bFieldNameColumn) ? "" : field.name + ": ") + sFieldValue;
									if ((query.sFieldDisplay == "horizontal") && (aResult[nColumnIndex].length))
										sFieldNameValue = query.sSpacesBeforeDelimiter + query.sDelimiter + 
														(sFieldNameValue == "" ? "" : (query.sSpacesAfterDelimiter + sFieldNameValue));
									aResult[nColumnIndex][aResult[nColumnIndex].length] = sFieldNameValue;
									aCurrentFeatureLabel[aCurrentFeatureLabel.length] = sFieldNameValue;
								}
							}
						
							if (sFieldName.toLowerCase() == query.sIdField.toLowerCase())
							{							
								if (queries.nCurrentQueryZone >= 0)
								{	
									if (nodeEnvelope)	
									{											
										var dOuterRadius = map.aQueryZones[queries.nCurrentQueryZone].dOuterRadius;
										var dQueryZonesCenterX = map.queryPoints[0].worldX;
										var dQueryZonesCenterY = map.queryPoints[0].worldY;
					
										if (!((dOuterRadius < map.getDistanceBetweenCoords(dQueryZonesCenterX,dQueryZonesCenterY,dTopLeftX, dTopLeftY)) &&
											(dOuterRadius < map.getDistanceBetweenCoords(dQueryZonesCenterX,dQueryZonesCenterY,dBottomRightX, dTopLeftY)) &&
											(dOuterRadius < map.getDistanceBetweenCoords(dQueryZonesCenterX,dQueryZonesCenterY,dBottomRightX, dBottomRightY)) &&
											(dOuterRadius < map.getDistanceBetweenCoords(dQueryZonesCenterX,dQueryZonesCenterY,dTopLeftX, dBottomRightY))))
										{
											//Add to list of features that potentially cover multiple zone boundaries
											var aOuterBoundaryResults = map.aQueryZones[queries.nCurrentQueryZone].aOuterBoundaryResults;
											if (!aOuterBoundaryResults[query.sMapServiceLayer])
											{
												aOuterBoundaryResults[query.sMapServiceLayer] = new Object();
												aOuterBoundaryResults[query.sMapServiceLayer].aFieldValues = new Object();
											}
												
											aOuterBoundaryResults[query.sMapServiceLayer].sFieldName = query.sMapServiceIdField;								
												
											var aFieldValues = aOuterBoundaryResults[query.sMapServiceLayer].aFieldValues;
											aFieldValues[sFieldValue] = new Object();							
										}	
									}																	
									//Check previous zone outer boundary results
									//Note features may straddle more than 1 zone's outer boundary.
									if (queries.nCurrentQueryZone > 0)
									{
										var aInnerZoneOuterBoundaryResults = map.aQueryZones[queries.nCurrentQueryZone - 1].aOuterBoundaryResults;
										if (aInnerZoneOuterBoundaryResults[query.sMapServiceLayer] && 
											aInnerZoneOuterBoundaryResults[query.sMapServiceLayer].aFieldValues &&
											aInnerZoneOuterBoundaryResults[query.sMapServiceLayer].aFieldValues[sFieldValue])
										{
											bIncludeFeature = false;
											break;		
										}
									}								
								}		
														
								if (query.bHighlightResults && query.mapService && query.mapService.access.aHighlightedResults)
								{							
									//Highlights
									var aHighlightedResults = query.mapService.access.aHighlightedResults;
									if (!aHighlightedResults[query.sMapServiceLayer])
									{
										aHighlightedResults[query.sMapServiceLayer] = new Object();
										aHighlightedResults[query.sMapServiceLayer].aFieldValues = new Array();
									}
										
									aHighlightedResults[query.sMapServiceLayer].sFieldName = query.sMapServiceIdField;								
										
									var aFieldValues = aHighlightedResults[query.sMapServiceLayer].aFieldValues;
									var objFieldValue = new Object();
									objFieldValue.sValue = sFieldValue;
									objFieldValue.bSelected = true;
									
									aFieldValues[aFieldValues.length] = objFieldValue;														
								}
								if (query.bLabelResults && !aFeatureLabel)
								{
									if ((this.nSelectedResultQuery == -1) ||
										(queries.currentQuery <= this.nSelectedResultQuery)) 
									{
										//Lower index has priority for label tool
										//Clear highlight if same feature clicked again.
										if (this.sSelectedResultId == sFieldValue)
											this.sSelectedResultId = "";
										else
											this.sSelectedResultId = sFieldValue; 
										aFeatureLabel = aCurrentFeatureLabel;
									}
								}
								
								if (query.sPolygonCollectionId)
								{
									var nodePolygon = nodeFeature.getElementsByTagName("POLYGON")[0];
									if (nodePolygon && sFieldValue && (sFieldValue != ""))
									{
										if (map.aQueryPolygonCollections[query.sPolygonCollectionId])
										{
											var queryPolygonCollection = map.aQueryPolygonCollections[query.sPolygonCollectionId];
										}
										else
										{
											var queryPolygonCollection = new SIX.QueryPolygonCollection();
											map.aQueryPolygonCollections[query.sPolygonCollectionId] = queryPolygonCollection;
										}
										var nodeEnvelope = nodeFeature.getElementsByTagName("ENVELOPE")[0];
										queryPolygonCollection.aPolygons[sFieldValue] = this.getPolygon(nodePolygon, nodeEnvelope);
										queryPolygonCollection.aPolygonsSelectionState[sFieldValue] = true;
										queryPolygonCollection.aPolygonsMetadata[sFieldValue] = aMetadata;
										query.aFeatureIndices[sFieldValue] = i;
									}
								}
							}
						}
					}
					
					if (bIncludeFeature)
					{
						var bIsDuplicate = false;
						
						if (aFieldValuesAndEnvelope.length)
						{
							for (var j=0; j<(aFieldValuesAndEnvelope.length); j++)
							{	
								var objExistingFeature = aFieldValuesAndEnvelope[j];
								if ((objExistingFeature.dTopLeftX == objFeature.dTopLeftX) && 
									(objExistingFeature.dTopLeftY == objFeature.dTopLeftY) && 
									(objExistingFeature.dBottomRightX == objFeature.dBottomRightX))
								{
									for (var k=0; k<(objFeature.aFieldValues.length); k++)
									{
										if (objExistingFeature.aFieldValues[k] != objFeature.aFieldValues[k])
											break;
										else if (k == (objFeature.aFieldValues.length - 1))
											bIsDuplicate = true;	
									}
								}
								if (bIsDuplicate)
									break;
							}
						}
						
						if (!bIsDuplicate)
						{
							//Only add to total if it's not a duplicate.
							
							for (var j=0; j<aCurrentFeatureFieldsToTotal.length; j++)
							{
								for (var k in aCurrentFeatureFieldsToTotal[j])
								{
									if (aCurrentFeatureFieldsToTotal[j].hasOwnProperty(k))
										aColumnTotals[j][k] += aCurrentFeatureFieldsToTotal[j][k];	
								}
							}	
							
							aFieldValuesAndEnvelope[aFieldValuesAndEnvelope.length] = objFeature;
							if (query.bLabelResults && aFeatureLabel)
							{
								this.aSelectedResultLabel.length = 0;
								var aCoord = map.getGeoPoint(map.queryPoints[0].worldX, map.queryPoints[0].worldY);
								this.dSelectedResultLabelX = aCoord[0];	
								this.dSelectedResultLabelY = aCoord[1];
								this.aSelectedResultLabel = aFeatureLabel;	
								this.nSelectedResultQuery = queries.currentQuery;
								this.service.catalog.currentQueryService = this.service;
								if (query.mapService && query.mapService.catalog)			
									query.mapService.catalog.currentQueryService = this.service;
							}

							var sMoreInfoUrl = null;
							if (query.fnGetMoreInfoUrl)
								sMoreInfoUrl = query.fnGetMoreInfoUrl(objFeature.aFieldValues);					
							queries[queries.sAddResultFunction](aResult, queries.currentQuery, i, sMoreInfoUrl);

							bGotResults = true;
						}
					}
					sLastFeatureId = sCurrentFeatureId;
				}
			}
			
			if (bGotResults) 
			{
				var nodeFeatureCount = nodeFeatures.getElementsByTagName("FEATURECOUNT")[0];					
				if (nodeFeatureCount) 
				{	
					var sFeatureCount = nodeFeatureCount.getAttribute("count");
					var sHasMore = nodeFeatureCount.getAttribute("hasmore");
					if (sHasMore == "true")						
						this.bMoreResults = true;
				}
				this.bGotResults = true;
			}
		}	
	}

	if (this.nNumRequests == this.nNumResponses)
	{
		if (this.bGotResults || query.nQueryOffset)
		{
			var aResultColumnTotals = new Array();
			var aColumnTotals = queries.aColumnTotals;
			
			for (var i=0; i<aColumnTotals.length; i++)
			{
				var nIndex = 0;
				aResultColumnTotals[i] = new Array();
				for (var j in aColumnTotals[i])
				{
					if (aColumnTotals[i].hasOwnProperty(j))
					{
						//j is an associative array index which can be a string.
						aResultColumnTotals[i][nIndex] = "Total " + j + ": " + aColumnTotals[i][j];
						nIndex++;
					}
				}
			}
			queries[queries.sAddResultFunction](aResultColumnTotals);
		}
		
		if (this.bMoreResults || ((queries.nCurrentQueryZone >= 0) && 
				(queries.nCurrentQueryZone < (map.aQueryZones.length - 1))))
		{
			queries.addNextSetOfResultsRow();
		}
		else if ((query.nQueryOffset == 0) && (this.bGotResults == false))
		{
			queries.addNoResultsRow();
		}

		this.highlightQueryResults();
	}
}

/**
**	PURPOSE: sends search to Arcims server
**	ACCEPTS: map object, search object
*/ 
SIX.Access.ArcXML.prototype.searchMap = function (map, search, nSearchOffset)
{	
	if( !this.service.loaded || !map.loaded /*|| !this.service.isOnline */)
		return;
		
	this.service.busy(true);
	this.service.nLayersLoadState = SIX.eLayersLoadState.LOADED;
	
	if (arguments.length < 3) 
	{
		if (this.tMapTimer)
			clearTimeout(this.tMapTimer);	
		this.tMapTimer = setTimeout("" + this.myself + ".searchMap(" + map.myself + "," + search.myself + ",0)", this.nTimeout);
		return;
	}

	search.decodeForm();
	if (search.resultsField)
	{
		search.deleteResults();
		search.addResult(search.sLoadingResults);
	}
	
	if (nSearchOffset == 0)
		this.sSearchText = "";

	if (((search.fields.length - search.nNumHiddenFields) == 1) && (search.bSubmitOnLoad == false))
	{	
		if (nSearchOffset == 0)
		{
			var bGotStringField = false;
			var bHiddenFieldsEmpty = true;
			for (var i=0; i<search.fields.length; i++)
			{
				
				if (search.fields[i].style == "string")
				{
					this.sSearchText = search.fields[i].value;
					bGotStringField = true;
				}
				else if ((search.fields[i].style == "hidden") && (search.fields[i].value != ""))
				{
					bHiddenFieldsEmpty = false;
				}
			}
		
			if ((this.sSearchText == "") && bGotStringField && bHiddenFieldsEmpty)
			{
				if (this.tMapTimer)
					clearTimeout(this.tMapTimer);
				if (search.resultsField) 
				{
					search.deleteResults();
					search.addResult(search.sNoResults);	
				}
				return;
			}	
		}					
	}				
	
	search.nSearchOffset = nSearchOffset;
	
	while (this.xml.rootXml.hasChildNodes())
			this.xml.rootXml.removeChild(this.xml.rootXml.lastChild);

	var piXML = this.xml.rootXml.createProcessingInstruction("xml", "version='1.0'");
	this.xml.rootXml.appendChild(piXML);

	var nodeArcXML = this.xml.rootXml.createElement("ARCXML");
	nodeArcXML.setAttribute("version","1.1");
	this.xml.rootXml.appendChild(nodeArcXML);
	
	var nodeRequest = this.xml.rootXml.createElement("REQUEST");
	nodeArcXML.appendChild(nodeRequest);
	    
	var nodeGetFeatures = this.xml.rootXml.createElement("GET_FEATURES");
	nodeGetFeatures.setAttribute("featurelimit",search.nSearchCount);  
	nodeGetFeatures.setAttribute("beginrecord", search.nSearchOffset);
	nodeGetFeatures.setAttribute("outputmode","newxml");
	nodeGetFeatures.setAttribute("geometry","false");
	nodeGetFeatures.setAttribute("envelope","true");
	nodeGetFeatures.setAttribute("compact","true");
	nodeRequest.appendChild(nodeGetFeatures);
	    
	var nodeLayer = this.xml.rootXml.createElement("LAYER");
	var sLayerId = this.service.searches[this.service.currentSearch].key;
	nodeLayer.setAttribute("id", sLayerId);
	nodeGetFeatures.appendChild(nodeLayer); 
	
	var nodeQuery = this.xml.rootXml.createElement("SPATIALQUERY");
	var sSubFields = "";
	var sWhereClause = "";
	
	for( var i=0; i<search.fields.length; i++ ) 
	{				
		sSubFields += ((i == 0) ? "" : " ") + search.fields[i].key; 
		
		if (((search.fields[i].style == "hidden") && (search.fields[i].value != "")) ||
			((search.fields[i].style == "number") && (isNaN(search.fields[i].value) == false)))
		{
			sWhereClause += ((sWhereClause == "") ? "" : " AND ") + search.fields[i].key + " = " + search.fields[i].value;
		}
		else if ((search.fields[i].style == "string") && (search.fields[i].value != ""))	
		{	
			//Do pattern match search if no submit button.
			if (((search.fields.length - search.nNumHiddenFields) == 1) && (!search.submitField))
				sWhereClause += "(UPPER(" + search.fields[i].key + ") like UPPER('" + this.sSearchText + "%') OR UPPER(" + search.fields[i].key + ") like UPPER('% " + this.sSearchText + " %') OR UPPER(" + search.fields[i].key + ") like UPPER('% " + this.sSearchText + "'))";
			else
				sWhereClause += ((sWhereClause == "") ? "" : " AND ") + "UPPER(" + search.fields[i].key + ") = UPPER('" + search.fields[i].value + "')";	
		}
		else if ((search.fields[i].style == "choice") && (search.fields[i].value != ""))	
		{
			var aParts = new Array();
			var sFieldValue = search.fields[i].value;
			var nIndex = sFieldValue.indexOf("'");
			var nStartIndex = 0;
			while (nIndex > -1)
			{
				var sPartValue = sFieldValue.substring(nStartIndex, nIndex);
				for (var j=0; j<sFieldValue.length; j++)
				{
					if (j<nStartIndex)
						sPartValue = "_" + sPartValue;
					else if (j >= nIndex)
						sPartValue = sPartValue + "_";
				}
				aParts[aParts.length] = sPartValue;
				
				if (nIndex >= sFieldValue.length)
					nIndex = -1;
				else
				{
					nStartIndex = nIndex + 1;	
					var sTemp = sFieldValue.substring(nStartIndex, sFieldValue.length);
					var nTempIndex = sTemp.indexOf("'");
					if (nTempIndex > -1)
						nIndex = nTempIndex + nStartIndex;
					else
						nIndex = sFieldValue.length;					
				}		
			}
			if (aParts.length)
			{
				for (var j=0; j<aParts.length;j++)
				{
					sWhereClause += (j > 0 ? " AND " : "") + "UPPER(" + search.fields[i].key + ") like UPPER('" + aParts[j] + "')";	
				}
			}
			else
			{
				sWhereClause += ((sWhereClause == "") ? "" : " AND ") + "UPPER(" + search.fields[i].key + ") = UPPER('" + sFieldValue + "')";	
			}
		}			
	}			

	//Use results key if present
	if (search.resultsField)
		sSubFields += " " + search.sIdField;
	nodeQuery.setAttribute("subfields", sSubFields + " #SHAPE#");
		
	//Match start of name, or whole words occurring within name.
	nodeQuery.setAttribute("where", sWhereClause);
	 	
	nodeGetFeatures.appendChild(nodeQuery);	

	var	 url  = 'mode=0;action=POST;';
		url += 'worldTLX=' + map.tlx + ';worldTLY=' + map.tly + ';worldBRX=' + map.brx + ';worldBRY=' + map.bry + ';';
		url += 'url=http://' + this.service.host + '/servlet/com.esri.esrimap.Esrimap?ServiceName=' + this.service.service + '&CustomService=query;HEADER=;';
		url += 'body=' + this.xml.rootXml.xml;
	
	var control = document[map.uid];
	
	var result = map.setLayerParameter(this.service.uid, url);	
}

SIX.Access.ArcXML.prototype.onSelectSearchResult = function ()
{
	var catalog = this.service.catalog;
	var control = document[catalog.maps[0].uid];
	var sSelectedFeature = "";
	
	var search = this.service.searches[this.service.currentSearch];
	
	search.decodeForm();
	if (search.resultsField) 
	{
		sSelectedFeature = search.resultsField.value;
		
		if ((sSelectedFeature == "") || (sSelectedFeature == null))	
			return;
		
		if (sSelectedFeature == search.sNextSetOfResults)
		{
			search.nSearchOffset += search.nSearchCount;
			this.searchMap(catalog.maps[0], search, search.nSearchOffset);
		}
		else if (sSelectedFeature == search.sLastSetOfResults)
		{
			search.nSearchOffset -= search.nSearchCount;
			this.searchMap(catalog.maps[0], search, search.nSearchOffset);
		}	
		else 
		{
			//Clear query highlights.
			if (this.service.catalog.currentQueryService)
				this.service.catalog.currentQueryService.access.sSelectedResultId = "";				
		
			this.zoomToFeature(search.sIdField, sSelectedFeature, search.dMinZoomWidth, search.dMinZoomHeight);
		}
	}
}

SIX.Access.ArcXML.prototype.zoomToFeature = function (sIdField, sSelectedFeature, dMinZoomWidth, dMinZoomHeight)
{
	var catalog = this.service.catalog;
	var map = catalog.maps[0];
	var nPaddingFactor = 0.11;
	var dMinDeltaX = (dMinZoomWidth ? dMinZoomWidth : 0.015);
	var dMinDeltaY = (dMinZoomHeight ? dMinZoomHeight : 0.015);
	
	var nSelectedFeature = parseInt(sSelectedFeature);
	if (isNaN(nSelectedFeature) || (nSelectedFeature < 0))
		return;			

	var nodeFeatures  = this.xml.rootXml.getElementsByTagName("FEATURES")[0];
	if (nodeFeatures) 
	{
		var aSearchValues = new Array();
		var nFeatureCount = 0;
		var nodeFeatureCount = nodeFeatures.getElementsByTagName("FEATURECOUNT")[0];					
		if (nodeFeatureCount) 
		{
			var sFeatureCount = nodeFeatureCount.getAttribute("count");
			if (!isNaN(parseInt(sFeatureCount)))
				nFeatureCount = parseInt(sFeatureCount);
		}

		var featureNodes = nodeFeatures.getElementsByTagName("FEATURE");

		if (nFeatureCount && featureNodes && (nSelectedFeature < featureNodes.length))
		{	
			this.sSelectedResultId = "";
			
			var fieldNodes = featureNodes[nSelectedFeature].getElementsByTagName("FIELD");
			
			for( var j=0; j<fieldNodes.length; j++ ) 
			{					
				var sFieldValue = fieldNodes[j].getAttribute("value");
				var sFieldName = fieldNodes[j].getAttribute("name");
				
				if (sFieldName.toLowerCase() == sIdField.toLowerCase())
				{
					this.sSelectedResultId = sFieldValue;
					break;
				}
			}
		
			var dTopLeftX = 0.0;
			var dTopLeftY = 0.0;
			var dBottomRightX = 0.0;
			var dBottomRightY = 0.0;				
			
			var nodeEnvelope = featureNodes[nSelectedFeature].getElementsByTagName("ENVELOPE")[0];					
			if (nodeEnvelope) 
			{	
				var sAttrMinX = nodeEnvelope.getAttribute("minx");
				var sAttrMinY = nodeEnvelope.getAttribute("miny");	
				var sAttrMaxX = nodeEnvelope.getAttribute("maxx");	
				var sAttrMaxY = nodeEnvelope.getAttribute("maxy");

				if (sAttrMinX)
					dTopLeftX = parseFloat(sAttrMinX);
				if (sAttrMinY)
					dBottomRightY = parseFloat(sAttrMinY);
				if (sAttrMaxX)
					dBottomRightX = parseFloat(sAttrMaxX);
				if (sAttrMaxY)
					dTopLeftY = parseFloat(sAttrMaxY);
					
				var dCenterY = dBottomRightY + (dTopLeftY - dBottomRightY)/2;
				var dCenterX = dTopLeftX + (dBottomRightX - dTopLeftX)/2;

				var dLocalTopLeftX = dTopLeftX;
				var dLocalTopLeftY = dTopLeftY;
				var dLocalBottomRightX = dBottomRightX;
				var dLocalBottomRightY = dBottomRightY;	
				var dTopLeftXMinDelta = dCenterX - dMinDeltaX/2;
				var dTopLeftYMinDelta = dCenterY + dMinDeltaY/2;
				var dBottomRightXMinDelta = dCenterX + dMinDeltaX/2;
				var dBottomRightYMinDelta = dCenterY - dMinDeltaY/2;						
		
				var sLocalDatum = map.datum();
				var sLocalProjection = map.projection();
				
				if (sLocalProjection.toLowerCase() != "geodetic") 
				{
					var aGeoCoords = new Array();
					aGeoCoords[aGeoCoords.length] = new Array(dTopLeftX, dTopLeftY);
					aGeoCoords[aGeoCoords.length] = new Array(dBottomRightX, dBottomRightY);
					aGeoCoords[aGeoCoords.length] = new Array(dTopLeftXMinDelta, dTopLeftYMinDelta);
					aGeoCoords[aGeoCoords.length] = new Array(dBottomRightXMinDelta, dBottomRightYMinDelta);
					var aENCoords = map.convertCoords(sLocalDatum, "geodetic", aGeoCoords, sLocalDatum, sLocalProjection);
				
					var aTopLeftCoordinate = aENCoords[0];
					var aBottomRightCoordinate = aENCoords[1];
					
					dLocalTopLeftX = parseFloat(aTopLeftCoordinate[0]);
					dLocalTopLeftY = parseFloat(aTopLeftCoordinate[1]);
					dLocalBottomRightX = parseFloat(aBottomRightCoordinate[0]);
					dLocalBottomRightY = parseFloat(aBottomRightCoordinate[1]);		
					
					//Calculate dMinDeltaY in northings.
					var aTopLeftMinDelta = aENCoords[2];
					var aBottomRightMinDelta = aENCoords[3];
					
					dTopLeftXMinDelta = parseFloat(aTopLeftMinDelta[0]);
					dTopLeftYMinDelta = parseFloat(aTopLeftMinDelta[1]);
					dBottomRightXMinDelta = parseFloat(aBottomRightMinDelta[0]);
					dBottomRightYMinDelta = parseFloat(aBottomRightMinDelta[1]);	
					dMinDeltaX = dBottomRightXMinDelta - dTopLeftXMinDelta;
					dMinDeltaY = dTopLeftYMinDelta - dBottomRightYMinDelta;											
				}	
					
				var nDeltaX = dLocalBottomRightX - dLocalTopLeftX;
				var nDeltaY = dLocalTopLeftY - dLocalBottomRightY;									
				var nPaddingX = nPaddingFactor * nDeltaX;
				var nPaddingY = nPaddingFactor * nDeltaY;
				var nPaddedDeltaX = 2 * nPaddingX + nDeltaX;								
				var nPaddedDeltaY = 2 * nPaddingY + nDeltaY;
				
				if (nPaddedDeltaX < dMinDeltaX)
				{ 
					dLocalTopLeftX = dTopLeftXMinDelta;
					dLocalBottomRightX = dBottomRightXMinDelta;	
				}															
				if (nPaddedDeltaY < dMinDeltaY)
				{ 
					dLocalTopLeftY = dTopLeftYMinDelta;
					dLocalBottomRightY = dBottomRightYMinDelta;	
				}
				
				var dTopLeftXPadded = dLocalTopLeftX - nPaddingX;
				var dTopLeftYPadded = dLocalTopLeftY + nPaddingY;
				var dBottomRightXPadded = dLocalBottomRightX + nPaddingX;
				var dBottomRightYPadded = dLocalBottomRightY - nPaddingY;

				var dPaddedWidth = dBottomRightXPadded - dTopLeftXPadded;
				var dPaddedHeight = dTopLeftYPadded - dBottomRightYPadded;				

				var dZoomAspectRatio = dPaddedWidth/dPaddedHeight;
				var dViewAspectRatio = (map.brx - map.tlx)/(map.tly - map.bry);

				if (dViewAspectRatio > dZoomAspectRatio)
				{
					var dTopLeftXZoom = dTopLeftXPadded - 0.5 * dPaddedWidth * (dViewAspectRatio / dZoomAspectRatio - 1);
					var dTopLeftYZoom = dTopLeftYPadded;
					var dBottomRightXZoom = dBottomRightXPadded - 0.5 * dPaddedWidth * (dViewAspectRatio / dZoomAspectRatio - 1);
					var dBottomRightYZoom = dBottomRightYPadded;					
				}
				else
				{
					var dTopLeftXZoom = dTopLeftXPadded
					var dTopLeftYZoom = dTopLeftYPadded + 0.5 * dPaddedHeight * (dZoomAspectRatio / dViewAspectRatio - 1);
					var dBottomRightXZoom = dBottomRightXPadded;
					var dBottomRightYZoom = dBottomRightYPadded - 0.5 * dPaddedHeight * (dZoomAspectRatio / dViewAspectRatio - 1);							
				}

				var topMap = map.getTopMap();
                var control = document[topMap.uid];
				control.SetExtents(dTopLeftXZoom, 
							dTopLeftYZoom, 
							dBottomRightXZoom,
							dBottomRightYZoom);	
												
			}							
		}	
	}
}

SIX.Access.ArcXML.prototype.selectQueryResult = function (nQueryIndex, nFeatureIndex)
{
	var catalog = this.service.catalog;
	var map = catalog.maps[0];
	var control = document[map.uid];
	
	var query = this.service.queries.aQueries[nQueryIndex];
	
	catalog.currentQueryService = this.service;		
	if (query.mapService && query.mapService.catalog)			
        query.mapService.catalog.currentQueryService = this.service;	

	this.xml.loadXmlText(query.sResponse);
	
	var nodeFeatures  = this.xml.rootXml.getElementsByTagName("FEATURES")[0];
	if (nodeFeatures) 
	{
		var nFeatureCount = 0;
		var nodeFeatureCount = nodeFeatures.getElementsByTagName("FEATURECOUNT")[0];					
		if (nodeFeatureCount) 
		{
			var sFeatureCount = nodeFeatureCount.getAttribute("count");
			if (!isNaN(parseInt(sFeatureCount)))
				nFeatureCount = parseInt(sFeatureCount);
		}

		var featureNodes = nodeFeatures.getElementsByTagName("FEATURE");

		if (nFeatureCount && featureNodes && (nFeatureIndex < featureNodes.length))
		{	
			this.sSelectedResultId = "";
			var fieldNodes = featureNodes[nFeatureIndex].getElementsByTagName("FIELD");

			for( var i=0; i<fieldNodes.length; i++ ) 
			{					
				var sFieldValue = fieldNodes[i].getAttribute("value");
				var sFieldName = fieldNodes[i].getAttribute("name");
				if (sFieldName.toLowerCase() == query.sIdField.toLowerCase())
				{
					this.sSelectedResultId = sFieldValue;
					this.nSelectedResultQuery = nQueryIndex;
					
					for (var j=0; j<catalog.services.length; j++) 
					{
						var service = catalog.services[j];
								
						if (service.loaded && !service.bFeatureServer && !(service.access instanceof SIX.Access.ECWP))
						{
							service.loadMap(map);
						}
					}						
					
					break;
				}
			}
		}
	}
}

SIX.Access.ArcXML.prototype.getQueryResultId = function (nResponseIndex, nFeatureIndex)
{
		var sQueryResultId = "";
		var query = this.service.queries.aQueries[nResponseIndex];
		this.xml.loadXmlText(query.sResponse);
		
		var nodeFeatures  = this.xml.rootXml.getElementsByTagName("FEATURES")[0];
		if (nodeFeatures) 
		{
			var nFeatureCount = 0;
			var nodeFeatureCount = nodeFeatures.getElementsByTagName("FEATURECOUNT")[0];					
			if (nodeFeatureCount) 
			{
				var sFeatureCount = nodeFeatureCount.getAttribute("count");
				if (!isNaN(parseInt(sFeatureCount)))
					nFeatureCount = parseInt(sFeatureCount);
			}

			var featureNodes = nodeFeatures.getElementsByTagName("FEATURE");

			if (nFeatureCount && featureNodes && (nFeatureIndex < featureNodes.length))
			{	
				var fieldNodes = featureNodes[nFeatureIndex].getElementsByTagName("FIELD");

				for( var i=0; i<fieldNodes.length; i++ ) 
				{					
					var sFieldValue = fieldNodes[i].getAttribute("value");
					var sFieldName = fieldNodes[i].getAttribute("name");
					if (sFieldName.toLowerCase() == query.sIdField.toLowerCase())
					{
						sQueryResultId = sFieldValue;
						break;
					}
				}
			}
		}
		return sQueryResultId;
}

SIX.Access.ArcXML.prototype.highlightQueryResults = function ()
{
	var catalog = this.service.catalog;
	var map = catalog.maps[0];
	
	//Clear take me to highlights.
	if (this.service.catalog.currentSearchService)
		this.service.catalog.currentSearchService.access.sSelectedResultId = "";
	
	for (var j=0; j<catalog.services.length; j++) 
	{
		var service = catalog.services[j];	
		if (service.loaded && !service.bFeatureServer && !(service.access instanceof SIX.Access.ECWP))
			service.loadMap(map);
	}						
}

/**
*	PURPOSE: Handles response.  Returns true on success, false on failure.
*/
SIX.Access.ArcXML.prototype.responseMap = function (map, layerName, url, body, action, tlx, tly, brx, bry, response)
{
	var retVal = true;
	if( response == "NCS_OVERLAY_SUCCESS" ) {
		this.service.busy(false);
		return true;
	}
	
	// replace any &amps - for image web server arcXML service
	var re = new RegExp ('&amp;', 'gi') ;
	var sResponse = response.replace(re, '&') ;
	
	//loadXML() fails when attributes contain ampersand characters.
	//Workaround this by replacing ' & ' with ' and '.
	var re2 = new RegExp (' & ', 'gi') ;
	var sResponse = sResponse.replace(re2, ' and ') ;		
	
	var control = document[map.uid];

	//The NCSLayeredView control incorrectly replaces single quotes (apostrophes)
	//in attribute values with double quotes.  This causes loadXML() to fail. The
	//following logic replaces double quotes in FIELD 'value' attributes with single
	//quotes to prevent loadXML() from failing.
	var nFieldIndex = sResponse.indexOf("<FIELD ");
	while (nFieldIndex > -1)
	{
		var sFieldPart = sResponse.substring(nFieldIndex, sResponse.length);
		var nEndIndex = sFieldPart.indexOf(">");
		if (nEndIndex < 0)
			nFieldIndex = -1;
		else
		{						
			var nIndexOfValue = sFieldPart.indexOf("value=\"");
			if (nIndexOfValue < 0)
				nIndexOfValue = sFieldPart.indexOf("VALUE=\"");
			if (nIndexOfValue < 0)
				nFieldIndex = -1;
			else
			{
				var nIndexOfFirstQuote = (nIndexOfValue + 6);
				var nIndexOfLastQuote = -1;
				var sValuePart = sFieldPart.substring(nIndexOfFirstQuote + 1, nEndIndex);
				var nIndexOfNextEquals = sValuePart.indexOf("=");
				if (nIndexOfNextEquals >= 0)
				{
					//If we find another '=' character, assume there is another attribute
					//between the 'value' attribute and the closing FIELD '>' character.
					nEndIndex = nIndexOfFirstQuote + 1 + nIndexOfNextEquals;
					sValuePart = sFieldPart.substring(nIndexOfFirstQuote + 1, nEndIndex);
				}
				nEndIndex += nFieldIndex;
				
				var nIndexOfQuote = sValuePart.indexOf("\"");
				
				//Convert double quotes between the first and last double quote to single 
				//quote characters (apostrophes).	
				while (nIndexOfQuote > -1)
				{
					nIndexOfLastQuote = nIndexOfQuote;
					sValuePart = sValuePart.substring(nIndexOfLastQuote + 1, sValuePart.length);
					nIndexOfQuote = sValuePart.indexOf("\"");
					if (nIndexOfQuote > -1)
						nIndexOfQuote += (nIndexOfLastQuote + 1);
				}
				
				if (nIndexOfLastQuote > -1)
				{
					nIndexOfFirstQuote += nFieldIndex;
					nIndexOfLastQuote += (nIndexOfFirstQuote + 1);
					
					var sOldValue = sResponse.substring(nIndexOfFirstQuote + 1, nIndexOfLastQuote);
					var sResponsePart1 = sResponse.substring(0, nIndexOfFirstQuote + 1);
					var sResponsePart2 = sOldValue.replace(/\"/g, "'");
					var sResponsePart3 = sResponse.substring(nIndexOfLastQuote, sResponse.length);
					sResponse = sResponsePart1 + sResponsePart2 + sResponsePart3;					
				}	
			}
		}
		var sTemp = sResponse.substring(nEndIndex + 1,sResponse.length);
		var nTempIndex = sTemp.indexOf("<FIELD ");
		if (nTempIndex > -1)
			nFieldIndex = nTempIndex + nEndIndex + 1;
		else
			nFieldIndex = -1;
	}
	

	this.xml.loadXmlText(sResponse);
	
	var valid = false;
	
	var nodeResponse = this.xml.rootXml.getElementsByTagName("RESPONSE")[0];
	
	if( nodeResponse )
	{
		var nodeServiceInfo = nodeResponse.getElementsByTagName("SERVICEINFO")[0];
		if (nodeServiceInfo)
		{
			SIX.ArcXMLServiceInfoCache.fireResponseMapCallbacks(url, response);
			var nodeEnvironment = nodeServiceInfo.getElementsByTagName("ENVIRONMENT")[0];
			if (nodeEnvironment) 
			{
				var nodeScreen = nodeEnvironment.getElementsByTagName("SCREEN")[0];
				if (nodeScreen)
				{
					var sDefaultDPI = nodeScreen.getAttribute("dpi");
					this.service.nDefaultDPI = parseFloat(sDefaultDPI);		
				}
					
				var nodeImageLimit = nodeEnvironment.getElementsByTagName("IMAGELIMIT")[0];
				if (nodeImageLimit)
				{
					var sPixelCount = nodeImageLimit.getAttribute("pixelcount");
					this.service.nMaxMapSize = parseFloat(sPixelCount);		
				}
			}

			var nodeGlobalEnvelope = null;
			var dGlobalEnvelopeMinX = 0.0;
			var dGlobalEnvelopeMinY = 0.0;
			var dGlobalEnvelopeMaxX = 0.0;
			var dGlobalEnvelopeMaxY = 0.0;
			var sMapUnits = "decimal_degrees";
			
			var nodeProperties = nodeServiceInfo.getElementsByTagName("PROPERTIES")[0];
			if (nodeProperties) 
			{
				var nodeMapUnits = nodeEnvironment.getElementsByTagName("MAPUNITS")[0];
				if (nodeMapUnits)
					sMapUnits = nodeMapUnits.getAttribute("units");
				
				nodeGlobalEnvelope = nodeServiceInfo.getElementsByTagName("ENVELOPE")[0];
				if (nodeGlobalEnvelope) 
				{	
					var sAttrMinX = nodeGlobalEnvelope.getAttribute("minx");
					var sAttrMinY = nodeGlobalEnvelope.getAttribute("miny");	
					var sAttrMaxX = nodeGlobalEnvelope.getAttribute("maxx");	
					var sAttrMaxY = nodeGlobalEnvelope.getAttribute("maxy");

					if (sAttrMinX)
						dGlobalEnvelopeMinX = parseFloat(sAttrMinX);
					if (sAttrMinY)
						dGlobalEnvelopeMinY = parseFloat(sAttrMinY);
					if (sAttrMaxX)
						dGlobalEnvelopeMaxX = parseFloat(sAttrMaxX);
					if (sAttrMaxY)
						dGlobalEnvelopeMaxY = parseFloat(sAttrMaxY);
				}								
			}
				
			this.service.deleteLayers(map);
					
			var layerNodes = nodeServiceInfo.getElementsByTagName("LAYERINFO");
			this.service.aExcludedLayers.length = 0;
			for( var i=0; i<layerNodes.length; i++ ) 
			{
				if ((layerNodes[i].childNodes.length < 1) || 
					(!layerNodes[i].getAttribute("type")))  
					continue;

				var featureType = "";
				var featureClassType = "";
				var minScale = 0;
				var maxScale = 0;
				var minx = 0;
				var miny = 0;
				var maxx = 0;
				var maxy = 0;
				var bSelected = true;
				var id;
				var name = "";
				var query = false;
				
				var sAttrId = layerNodes[i].getAttribute("id");
				var sAttrVisible = layerNodes[i].getAttribute("visible");	
				var sAttrName = layerNodes[i].getAttribute("name");	
				var sAttrMinScale = layerNodes[i].getAttribute("minscale");
				var sAttrMaxScale = layerNodes[i].getAttribute("maxscale");
				var sAttrType = layerNodes[i].getAttribute("type");
				
				if (sAttrId)
					id = sAttrId;
				else 
					id = "" + i;
				
				if (sAttrVisible && (sAttrVisible != "true"))
					bSelected = false;
				
				if (sAttrName)
					name = sAttrName;
					
				if (sAttrMinScale)
					minScale = parseFloat(sAttrMinScale);
					
				if (sAttrMaxScale)
					maxScale = parseFloat(sAttrMaxScale);
					
				if (sAttrType)
				{
					featureType = sAttrType;
					if (featureType == "featureclass")
					{
						var nodeFeatureClass = layerNodes[i].getElementsByTagName("FCLASS")[0];
						if (nodeFeatureClass)
						{
							var sAttrFeatureClassType = nodeFeatureClass.getAttribute("type");
							if (sAttrFeatureClassType)
								featureClassType = sAttrFeatureClassType;
						}
					}
				}
	
				var sColor = "";
				if (this.service.bColoredLayers)
				{
					var nodeScaleDependentRenderer = layerNodes[i].getElementsByTagName("SCALEDEPENDENTRENDERER")[0];
					if (nodeScaleDependentRenderer)
					{
						var nodeSimplePolygonSymbol = nodeScaleDependentRenderer.getElementsByTagName("SIMPLEPOLYGONSYMBOL")[0];
						if (nodeSimplePolygonSymbol)
						{
							var sBoundaryColor = nodeSimplePolygonSymbol.getAttribute("boundarycolor");
							if (sBoundaryColor)
							{
								var aRGBColor = new Array();
								var aBoundaryColor = sBoundaryColor.split(",");
								for (var j=0; j<aBoundaryColor.length; j++)
								{
									var nValue = parseInt(aBoundaryColor[j]);
									aRGBColor[j] = isNaN(nValue) ? 0 : nValue;
								}
								sColor = SIX.Util.rgbToHex(aRGBColor);
							}
						}
					}
				}	
					
				var nodeEnvelope = layerNodes[i].getElementsByTagName("ENVELOPE")[0];					
				if (nodeEnvelope) 
				{	
					var sAttrMinX = nodeEnvelope.getAttribute("minx");
					var sAttrMinY = nodeEnvelope.getAttribute("miny");	
					var sAttrMaxX = nodeEnvelope.getAttribute("maxx");	
					var sAttrMaxY = nodeEnvelope.getAttribute("maxy");

					if (sAttrMinX)
						minx = parseFloat(sAttrMinX);
					if (sAttrMinY)
						miny = parseFloat(sAttrMinY);
					if (sAttrMaxX)
						maxx = parseFloat(sAttrMaxX);
					if (sAttrMaxY)
						maxy = parseFloat(sAttrMaxY);
				}
				else if (nodeGlobalEnvelope)
				{
					minx = dGlobalEnvelopeMinX;
					miny = dGlobalEnvelopeMinY;
					maxx = dGlobalEnvelopeMaxX;
					maxy = dGlobalEnvelopeMaxY;
				}				
						
				if( name != "" ) 
				{
					var objLayerDefaults = this.service.filterLayer(id, name);
					if (!objLayerDefaults.bInList)
					{
						this.service.aExcludedLayers[this.service.aExcludedLayers.length] = id;
						continue;
					}
					bSelected = (this.service.bFilterIgnoreDefaultLayerSelections ? objLayerDefaults.bSelected : bSelected);
					var sParams = "selected=" + (bSelected ? "true" : "false") + ";doquery="  + (query ? "true" : "false"); 
					var layer = this.service.addLayer(new SIX.Layer(this.service,name,id,null,sParams));	
					layer.sColor = sColor;
					
					layer.featureType = featureClassType;
					var dRelMinScale = 0.0;
					var dRelMaxScale = 0.0;
				
					var dScreenMetresPerPixel = 0.0254 / this.service.nDefaultDPI;
					
					switch (sMapUnits)
					{
						case "feet":
							dRelMinScale = (minScale ? minScale/(3.28 * dScreenMetresPerPixel) : 0);
							dRelMaxScale = (maxScale ? maxScale/(3.28 * dScreenMetresPerPixel) : 0);
							break;					
						case "meters":
							dRelMinScale = (minScale ? minScale/dScreenMetresPerPixel : 0);
							dRelMaxScale = (maxScale ? maxScale/dScreenMetresPerPixel : 0);
							break;
						case "decimal_degrees":
						default:
							//The value 1.693 is a correction value for what seems to be a bug in ArcIMS
							dRelMinScale = (minScale ? (minScale * (111195/1.693) / dScreenMetresPerPixel) : 0);
							dRelMaxScale = (maxScale ? (maxScale * (111195/1.693) / dScreenMetresPerPixel) : 0);
							break;
					}
					
					layer.setScale(dRelMinScale, dRelMaxScale);
					
					if (nodeEnvelope || nodeGlobalEnvelope)
					{
						var dLocalMinX = minx;
						var dLocalMinY = miny;
						var dLocalMaxX = maxx;
						var dLocalMaxY = maxy;						
						var sLocalProjection = map.projection();
						var sLocalDatum = map.datum();
				
						if ((sMapUnits != "decimal_degrees") &&
							(sLocalProjection.toLowerCase() != "geodetic"))
						{
							var aTopLeftCoordinate = map.getGeoPoint(minx, maxy, sLocalDatum, sLocalProjection);
							var aBottomRightCoordinate = map.getGeoPoint(maxx, miny, sLocalDatum, sLocalProjection);
							
							dLocalMinX = parseFloat(aTopLeftCoordinate[0]);
							dLocalMaxY = parseFloat(aTopLeftCoordinate[1]);
							dLocalMaxX = parseFloat(aBottomRightCoordinate[0]);
							dLocalMinY = parseFloat(aBottomRightCoordinate[1]);							
						}	
					
						layer.setExtents(dLocalMaxY,dLocalMinX,dLocalMinY,dLocalMaxX);
					}
				}
			}
			// reverse order list as ArcXML puts lowest layer first in file, and set initial hidden state
			var j = this.service.layers.length-1;
			for( var i=0; i<this.service.layers.length; i++, j-- )
				this.service.layersOrder[i] = j;
				
			this.service.nLayersLoadState = SIX.eLayersLoadState.LOADED;

			map.hiddenLayers(this.service);
			this.service.update();
			this.service.busy(false);		
			
			if (this.service.parentService)
			{
				this.service.parentService.nLayersLoadState = SIX.eLayersLoadState.LOADED;
				
				for (var i=0; i<this.service.parentService.aServices.length; i++)
				{ 
					if (this.service.parentService.aServices[i].nLayersLoadState != SIX.eLayersLoadState.LOADED)
					{
						 this.service.parentService.nLayersLoadState = SIX.eLayersLoadState.LOADING;
						 break;
					}
				}
				if (this.service.parentService.nLayersLoadState == SIX.eLayersLoadState.LOADED)
				{				
					map.hiddenLayers(this.service.parentService);
					this.service.parentService.update();
					this.service.parentService.busy(false);							
				}
			}
			this.updateMap(map);
			return true;
		}	
	
		var nodeOutput = nodeResponse.getElementsByTagName("OUTPUT")[0];

		if( nodeOutput ) 
		{
			var sOutputUrl  = nodeOutput.getAttribute("url");	
		
			if (sOutputUrl) 
			{
				var sLayerUrl = 'mode=0;body=;action=GET;' +
			 					'worldTLX=' + tlx + ';worldTLY=' + tly + ';worldBRX=' + brx + ';worldBRY=' + bry + ';' +
								'url=' + sOutputUrl + ';';

				map.setLayerParameter(this.service.uid, sLayerUrl);
				valid = true;
			}
		}
		
		var nodeLegend  = nodeResponse.getElementsByTagName("LEGEND")[0];

		if( nodeLegend ) 
		{
			var sLegendUrl = nodeLegend.getAttribute("url");	
			if (sLegendUrl) 
			{
				this.service.setLegendUrl("<img src='" + sLegendUrl + "'>");	
				valid = true;
			}
		}	
		var nodeFeatures  = nodeResponse.getElementsByTagName("FEATURES")[0];
		if (nodeFeatures) 
		{
			if (this.service.queries)
			{
				for (var i=0; i<this.service.queries.aQueries.length; i++)
				{
					if (this.service.queries.aQueries[i].uid == layerName)
					{
						this.service.queries.currentQuery = i;
						break;
					}
				}
			}
			
			if (this.service.queries && (this.service.queries.currentQuery > -1))
			{
				this.service.queryResponse(map);	
				valid = true;	
			}	
			else if (this.service.currentSearch > -1)
			{
				this.service.searchResponse(map);
				valid = true;		
			}
		}
	}

	if (valid)
	{
		this.nNumInvalidRequests = 0;
	}
	else	
	{
		this.service.busy(false);
		this.nNumInvalidRequests++;
		if (this.nNumInvalidRequests == 1)
			SIX.App.popupAlert(this.service.name + " (" + this.service.access.name + ") Error.","The map server reported an error.",sResponse);
		retVal = false;
	}
	return retVal;
}

SIX.Access.ArcXML.prototype.searchResponse = function (map)
{
	var nodeFeatures  = this.xml.rootXml.getElementsByTagName("FEATURES")[0];
	
	if (nodeFeatures && (this.service.currentSearch > -1)) 
	{
		var search = this.service.searches[this.service.currentSearch];
		var sSearchField = "";
		var bGotResults = false;
		var aFieldValuesAndEnvelope = new Array();//Used to prevent duplicate query results.
		
		if (search.resultsField) 
		{
			search.deleteResults();					

			var nFeatureCount = 0;
			var nodeFeatureCount = nodeFeatures.getElementsByTagName("FEATURECOUNT")[0];					
			if (nodeFeatureCount) 
			{
				var sFeatureCount = nodeFeatureCount.getAttribute("count");
				if (!isNaN(parseInt(sFeatureCount)))
					nFeatureCount = parseInt(sFeatureCount);
			}

			var featureNodes = nodeFeatures.getElementsByTagName("FEATURE");

			if (nFeatureCount && featureNodes)
			{
				if (search.nSearchOffset) 
					search.addResult(search.sLastSetOfResults);
			
				for( var i=0; i<featureNodes.length; i++ ) 
				{
					if (featureNodes[i].childNodes.length < 1)
						continue;
						
					var dTopLeftX = 0.0;
					var dTopLeftY = 0.0;
					var dBottomRightX = 0.0;
					var dBottomRightY = 0.0;				
					
					var nodeEnvelope = featureNodes[i].getElementsByTagName("ENVELOPE")[0];					
					if (nodeEnvelope) 
					{	
						var sAttrMinX = nodeEnvelope.getAttribute("minx");
						var sAttrMinY = nodeEnvelope.getAttribute("miny");	
						var sAttrMaxX = nodeEnvelope.getAttribute("maxx");	
						var sAttrMaxY = nodeEnvelope.getAttribute("maxy");

						if (sAttrMinX)
							dTopLeftX = parseFloat(sAttrMinX);
						if (sAttrMinY)
							dBottomRightY = parseFloat(sAttrMinY);
						if (sAttrMaxX)
							dBottomRightX = parseFloat(sAttrMaxX);
						if (sAttrMaxY)
							dTopLeftY = parseFloat(sAttrMaxY);					
					}	
					
					var objFeature = new Object();		
					objFeature.dTopLeftX = dTopLeftX;
					objFeature.dTopLeftY = dTopLeftY;
					objFeature.dBottomRightX = dBottomRightX;		
					objFeature.dBottomRightY = dBottomRightY;		
					objFeature.aFieldValues = new Array();
					for (var j=0; j<search.resultsField.aFieldHeadings.length; j++)
						objFeature.aFieldValues[j] = "";
										
					var nodeFields = featureNodes[i].getElementsByTagName("FIELDS")[0];
					if (nodeFields)
					{
						var fieldNodes = nodeFields.getElementsByTagName("FIELD");
						var aResult = new Array();

						for (var k=0; k<search.resultsField.aFieldHeadings.length; k++)
						{
							aResult[k] = "";
							for( var j=0; j<fieldNodes.length; j++ ) 
							{					
								var sFieldValue = fieldNodes[j].getAttribute("value");
								var sFieldName = fieldNodes[j].getAttribute("name");

								if (sFieldName.toLowerCase() == search.resultsField.aFieldKeys[k].toLowerCase())	
								{
									var aFieldLookupTables = search.resultsField.aFieldLookupTables;
									if (aFieldLookupTables && aFieldLookupTables[k] && (sFieldValue != ""))
									{
										if (aFieldLookupTables[k]["#" + sFieldValue])
											sFieldValue = aFieldLookupTables[k]["#" + sFieldValue];	
									}
									aResult[k] = sFieldValue;
									objFeature.aFieldValues[k] = sFieldValue;
								}
							}
						}
						
						var bIsDuplicate = false;
						
						if (aFieldValuesAndEnvelope.length)
						{
							for (var j=0; j<(aFieldValuesAndEnvelope.length); j++)
							{	
								var objExistingFeature = aFieldValuesAndEnvelope[j];
								if ((objExistingFeature.dTopLeftX == objFeature.dTopLeftX) && 
									(objExistingFeature.dTopLeftY == objFeature.dTopLeftY) && 
									(objExistingFeature.dBottomRightX == objFeature.dBottomRightX))
								{
									for (var k=0; k<(objFeature.aFieldValues.length); k++)
									{
										if (objExistingFeature.aFieldValues[k] != objFeature.aFieldValues[k])
											break;
										else if (k == (objFeature.aFieldValues.length - 1))
											bIsDuplicate = true;	
									}
								}
								if (bIsDuplicate)
									break;
							}
						}
							
						if (!bIsDuplicate)					
						{
							aFieldValuesAndEnvelope[aFieldValuesAndEnvelope.length] = objFeature;
							search.addResult(aResult,i);
							bGotResults = true;
						}
					}
				}
				if (bGotResults) 
				{
					var nodeFeatureCount = nodeFeatures.getElementsByTagName("FEATURECOUNT")[0];					
					if (nodeFeatureCount) 
					{	
						var sFeatureCount = nodeFeatureCount.getAttribute("count");
						var sHasMore = nodeFeatureCount.getAttribute("hasmore");
						if (sHasMore == "true")
							search.addResult(search.sNextSetOfResults);
					}
					search.sortResults();
				}	
				else
				{
					search.addResult(search.sNoResults);
				}
				
				//Set focus back to first search field.
				var firstField = search.getFirstInputField();
				if (firstField) 
				{
					var elemFirstField = document.getElementById(firstField.uid);
					if (elemFirstField)
						elemFirstField.focus();	
				}
			}	
		}
	}
}

SIX.Access.ArcXML.prototype.onSelectAll = function (event)
{
	var evt = null;
	if (window.event) 
	{
		evt = window.event;
	}
	else if (event) 
	{
		evt = event;
	}
	else 
	{
		return true;
	}

 	var id = document.getElementById(this.service.queries.uid);
	var nodeTableBody = id.getElementsByTagName("tbody").item(0);
	var rowNodes = nodeTableBody.getElementsByTagName("tr");
 
	var eventSource = (evt.target) ? evt.target : evt.srcElement;
	
	for (var j=0;j<rowNodes.length;j++)
	{
		var cellNodes = rowNodes.item(j).getElementsByTagName("td");
		var cellNode = cellNodes.item(2);

		var inputs = cellNode.getElementsByTagName("input");
		for (var k=0; k<inputs.length; k++) 
		{
			if (inputs[k].type.toLowerCase() == 'checkbox') 
			{
				inputs[k].defaultChecked = inputs[k].checked = eventSource.checked;
			}
		}
	}	
		
	var sNodeName = eventSource.nodeName.toLowerCase();
	if ((sNodeName == "input") && (eventSource.type == "checkbox"))
	{
		for (var i=0; i<this.service.queries.aQueries.length; i++)
		{
			var query = this.service.queries.aQueries[i];	
			if (query.bHighlightResults && query.mapService && query.mapService.access.aHighlightedResults)
			{
				var aHighlightedResults = query.mapService.access.aHighlightedResults;	
				if (aHighlightedResults[query.sMapServiceLayer])
				{
					var aFieldValues = aHighlightedResults[query.sMapServiceLayer].aFieldValues;
					for (var j=0; j<aFieldValues.length; j++)
					{
						aFieldValues[j].bSelected = eventSource.checked;
						if (query.sPolygonCollectionId)
						{
							var map = this.service.catalog.maps[0];
							var queryPolygonCollection = map.aQueryPolygonCollections[query.sPolygonCollectionId];
							if (queryPolygonCollection && queryPolygonCollection.aPolygons[aFieldValues[j].sValue])
								queryPolygonCollection.aPolygonsSelectionState[aFieldValues[j].sValue] = aFieldValues[j].bSelected;
						}						
					}			
				}			
			}
		}
		this.highlightQueryResults();
	}	
	
	return false;
}

SIX.Access.ArcXML.prototype.onSelect = function (event)
{
	var evt = null;
	if (window.event) 
	{
		evt = window.event;
	}
	else if (event) 
	{
		evt = event;
	}
	else 
	{
		return true;
	}
 
	var eventSource = (evt.target) ? evt.target : evt.srcElement;
	
	var sNodeName = eventSource.nodeName.toLowerCase();
	if ((sNodeName == "input") && (eventSource.type == "checkbox"))
	{
		var nodeRow = getParent(eventSource, "tr");
		if (this.service.queries.aRowToFeatureMappings[nodeRow.id])
		{
			var nSelectedResponseIndex = this.service.queries.aRowToFeatureMappings[nodeRow.id][0];
			var nSelectedFeature = this.service.queries.aRowToFeatureMappings[nodeRow.id][1];		
		
			var query = this.service.queries.aQueries[nSelectedResponseIndex];	
		
			if (query.bHighlightResults && query.mapService && query.mapService.access.aHighlightedResults)
			{
				var aHighlightedResults = query.mapService.access.aHighlightedResults;	
				if (aHighlightedResults[query.sMapServiceLayer])
				{
					this.xml.loadXmlText(query.sResponse);
					var nodeFeatures  = this.xml.rootXml.getElementsByTagName("FEATURES")[0];
					if (nodeFeatures) 
					{
						var nFeatureCount = 0;
						var nodeFeatureCount = nodeFeatures.getElementsByTagName("FEATURECOUNT")[0];					
						if (nodeFeatureCount) 
						{
							var sFeatureCount = nodeFeatureCount.getAttribute("count");
							if (!isNaN(parseInt(sFeatureCount)))
								nFeatureCount = parseInt(sFeatureCount);
						}

						var featureNodes = nodeFeatures.getElementsByTagName("FEATURE");

						if (nFeatureCount && featureNodes && (nSelectedFeature < featureNodes.length))
						{			
							var fieldNodes = featureNodes[nSelectedFeature].getElementsByTagName("FIELD");

							for( var i=0; i<fieldNodes.length; i++ ) 
							{					
								var sFieldValue = fieldNodes[i].getAttribute("value");
								var sFieldName = fieldNodes[i].getAttribute("name");
								if (sFieldName.toLowerCase() == query.sIdField.toLowerCase())
								{
									var aFieldValues = aHighlightedResults[query.sMapServiceLayer].aFieldValues;
									for (var j=0; j<aFieldValues.length; j++)
									{
										if (aFieldValues[j].sValue == sFieldValue)
										{
											aFieldValues[j].bSelected = eventSource.checked;
											if (query.sPolygonCollectionId)
											{
												var map = this.service.catalog.maps[0];
												var queryPolygonCollection = map.aQueryPolygonCollections[query.sPolygonCollectionId];
												if (queryPolygonCollection && queryPolygonCollection.aPolygons[sFieldValue])
													queryPolygonCollection.aPolygonsSelectionState[sFieldValue] = aFieldValues[j].bSelected;
											}
											break;
										}
									}
									break;
								}
							}	
						}
					}			
				}
			}
		}
	}	
	
	return false;
}

SIX.Access.ArcXML.prototype.setQueryResultSelectionState = function (nQueryIndex, featureId, bSelected)
{
	var query = this.service.queries.aQueries[nQueryIndex];
	var sId = query.aFeatureIndexToRow[featureId];
	var nodeRow = document.getElementById(sId);
	if (nodeRow)
	{
		var cellNodes = nodeRow.getElementsByTagName("td");
		if (cellNodes.length >= 3)
		{
			var nodeCell = cellNodes.item(2);
			var nodeInput = nodeCell.getElementsByTagName("input")[0];
			if (nodeInput.type.toLowerCase() == 'checkbox') 
				nodeInput.defaultChecked = nodeInput.checked = bSelected;
		}
	}
}