Even with auto-save, I still lost my post before submitting. I worked on it for an hour!Anyway, I started work on a Delphi API for ArcGIS Server. What it does is communicate with ArcGIS Server through the REST API using JSON objects. In Delphi I have classes and types for almost 100 of those ArcGIS objects exposed in the REST API. If I continue this work, there's lost more to do.The unit is pretty bad in it's version 0.1 state. I don't use a lot of memory clean-up, it's poorly documented, and could be organized a lot better. The thing is, it already does what *I* need it to do, which isn't even the tip of the iceberg. What I'm asking you guys is if you want me to continue work on the API or not, or perhaps you don't care.Here is an example that compiles when you add the ArcGISServer unit to the uses clause:
function GoArcGIS( X, Y: Double; Catalog, MapService, MapLayer, FieldName: String ): String;
/// You can try calling this function with the following values:
/// 1945785.00909788, 715764.111071926, '',
var
pConnection: TArcGISServer;
pGeocodedPt: TAGSPoint;
pCatalog: TAGSCatalog;
pMapService: TAGSMapService;
pBriefLayer: TAGSBriefLayer;
pMapLayer: TAGSLayerOrTable;
pQueryResults: TAGSFeatureSet;
bFound: Boolean;
const
ServerProtocol = 'http';
ServerHost = 'sampleserver1.arcgisonline.com';
ArcGISServerInstance = 'ArcGIS';
begin
//Initializations to keep the compiler happy since I'm calling Free in the finally clause
pCatalog := nil;
pMapService := nil;
pMapLayer := nil;
pQueryResults := nil;
pConnection := TArcGISServer.Create( nil );
pGeocodedPt := TAGSPoint.Create;
pGeocodedPt.X := X;
pGeocodedPt.Y := Y;
pGeocodedPt.SpatialReference.Wkid := 32043; //NAD 27 Utah Central
try
pCatalog := pConnection.GetCatalog( ServerProtocol, ServerHost, ArcGISServerInstance, Catalog );
if pCatalog = nil then
Result := ''
else
begin
pMapService := pCatalog.GetMapService( pConnection, MapService );
if pMapService = nil then
Result := ''
else
begin
bFound := False;
for pBriefLayer in pMapService.Layers do
if not bFound and ( pBriefLayer.Name = MapLayer ) then
begin
bFound := True;
pMapLayer := pMapService.GetLayerOrTable( pConnection, pBriefLayer.Id );
if pMapLayer = nil then
Result := ''
else
begin
pQueryResults := pMapLayer.Query( pConnection, '', pGeocodedPt, nil, esriSpatialRelIntersects, '', '', '', FieldName, False );
if pQueryResults = nil then
Result := ''
else
if pQueryResults.Features.Count = 0 then
Result := ''
else
if pQueryResults.Features[ 0 ].Attributes = nil then
Result := ''
else
if not pQueryResults.Features[ 0 ].Attributes.ContainsKey( FieldName ) then
Result := ''
else
Result := pQueryResults.Features[ 0 ].Attributes[ FieldName ];
end;
end;
if not bFound then
Result := '';
end;
end;
finally
pConnection.Free;
pGeocodedPt.Free;
pCatalog.Free;
pMapService.Free;
pMapLayer.Free;
pQueryResults.Free;
end;
end;
If you call the above function with these values, you should get the value Utah, since the provided point is Orem's City Center, which is in Utah County of the state of Utah.
GoArcGIS( 1945785.00909788, 715764.111071926, 'Specialty', 'ESRI_StateCityHighway_USA', 'counties', 'NAME' );
Because it's Delphi code, you could easily make a Desktop application that harnesses ArcGIS Server's REST API, or a Web Broker application, or a DLL, or an ActiveX component, or some VCL components, or whatever else you wanted with Delphi's IDE. The trick is that you should have a fairly current version of Delphi (I wrote it in XE2) and you should have the Enterprise version, since JSON object units don't exist in the Professional version (or so I'm told).Let me know what you guys think. Also, I really want to get back to documenting how to create ActiveX components for use inside ArcGIS Desktop programs with Delphi XE2. But there is yet another COM bug in Delphi that prevents it from compiling correctly, specifically bug QC 104063."Roj"