[mapguide-commits] r6318 - in trunk/MgDev/Doc: devguide/source samples samples/dotnetviewersample samples/dotnetviewersample/bin samples/dotnetviewersample/findaddress samples/dotnetviewersample/findaddress/templates samples/dotnetviewersample/images samples/dotnetviewersample/overview samples/dotnetviewersample/plot samples/dotnetviewersample/query samples/dotnetviewersample/query/classes samples/dotnetviewersample/query/templates samples/dotnetviewersample/styles samples/dotnetviewersample/theme samples/dotnetviewersample/theme/classes samples/dotnetviewersample/theme/templates samples/javaviewersample samples/javaviewersample/findaddress samples/javaviewersample/findaddress/templates samples/javaviewersample/images samples/javaviewersample/overview samples/javaviewersample/plot samples/javaviewersample/query samples/javaviewersample/query/classes samples/javaviewersample/query/templates samples/javaviewersample/styles samples/javaviewersample/theme samples/javaviewersample/theme/cla sses samples/javaviewersample/theme/templates samples/phpviewersample samples/phpviewersample/findaddress samples/phpviewersample/findaddress/templates samples/phpviewersample/images samples/phpviewersample/overview samples/phpviewersample/plot samples/phpviewersample/query samples/phpviewersample/query/classes samples/phpviewersample/query/templates samples/phpviewersample/styles samples/phpviewersample/theme samples/phpviewersample/theme/classes samples/phpviewersample/theme/templates

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Thu Dec 8 12:49:44 EST 2011


Author: jng
Date: 2011-12-08 09:49:44 -0800 (Thu, 08 Dec 2011)
New Revision: 6318

Added:
   trunk/MgDev/Doc/devguide/source/supplemental_development.rst
   trunk/MgDev/Doc/samples/dotnetviewersample/
   trunk/MgDev/Doc/samples/dotnetviewersample/ReadMe.txt
   trunk/MgDev/Doc/samples/dotnetviewersample/ajaxtiledviewersample.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/ajaxviewersample.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/bin/
   trunk/MgDev/Doc/samples/dotnetviewersample/bin/Jayrock.Json.dll
   trunk/MgDev/Doc/samples/dotnetviewersample/bin/Jayrock.dll
   trunk/MgDev/Doc/samples/dotnetviewersample/dwfviewersample.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/
   trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/clearaddressresults.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddress.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddressfunctions.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddressmain.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/gotopoint.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/templates/
   trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/templates/addressmarker.xml
   trunk/MgDev/Doc/samples/dotnetviewersample/images/
   trunk/MgDev/Doc/samples/dotnetviewersample/images/Thumbs.db
   trunk/MgDev/Doc/samples/dotnetviewersample/images/loader_inactive.gif
   trunk/MgDev/Doc/samples/dotnetviewersample/images/loader_pulse.gif
   trunk/MgDev/Doc/samples/dotnetviewersample/images/pushpin.jpg
   trunk/MgDev/Doc/samples/dotnetviewersample/images/pushpinblue.jpg
   trunk/MgDev/Doc/samples/dotnetviewersample/json.js
   trunk/MgDev/Doc/samples/dotnetviewersample/overview/
   trunk/MgDev/Doc/samples/dotnetviewersample/overview/overviewmain.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/plot/
   trunk/MgDev/Doc/samples/dotnetviewersample/plot/plot.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/plot/plotmain.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/query/
   trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/
   trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/command.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/feature.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/property.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/query.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/query/querycontroller.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/query/querymain.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/query/templates/
   trunk/MgDev/Doc/samples/dotnetviewersample/query/templates/filterlayerdefinition.xml
   trunk/MgDev/Doc/samples/dotnetviewersample/styles/
   trunk/MgDev/Doc/samples/dotnetviewersample/styles/gt.css
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/command.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/layerinfo.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/property.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/theme.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/templates/
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/templates/arearuletemplate.xml
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/themecontroller.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/theme/thememain.aspx
   trunk/MgDev/Doc/samples/dotnetviewersample/title.html
   trunk/MgDev/Doc/samples/dotnetviewersample/utilityfunctions.aspx
   trunk/MgDev/Doc/samples/javaviewersample/
   trunk/MgDev/Doc/samples/javaviewersample/ReadMe.txt
   trunk/MgDev/Doc/samples/javaviewersample/ajaxtiledviewersample.jsp
   trunk/MgDev/Doc/samples/javaviewersample/ajaxviewersample.jsp
   trunk/MgDev/Doc/samples/javaviewersample/dwfviewersample.jsp
   trunk/MgDev/Doc/samples/javaviewersample/findaddress/
   trunk/MgDev/Doc/samples/javaviewersample/findaddress/clearaddressresults.jsp
   trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddress.jsp
   trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddressfunctions.jsp
   trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddressmain.jsp
   trunk/MgDev/Doc/samples/javaviewersample/findaddress/gotopoint.jsp
   trunk/MgDev/Doc/samples/javaviewersample/findaddress/templates/
   trunk/MgDev/Doc/samples/javaviewersample/findaddress/templates/addressmarker.xml
   trunk/MgDev/Doc/samples/javaviewersample/images/
   trunk/MgDev/Doc/samples/javaviewersample/images/Thumbs.db
   trunk/MgDev/Doc/samples/javaviewersample/images/loader_inactive.gif
   trunk/MgDev/Doc/samples/javaviewersample/images/loader_pulse.gif
   trunk/MgDev/Doc/samples/javaviewersample/images/pushpin.jpg
   trunk/MgDev/Doc/samples/javaviewersample/images/pushpinblue.jpg
   trunk/MgDev/Doc/samples/javaviewersample/json.jar
   trunk/MgDev/Doc/samples/javaviewersample/json.js
   trunk/MgDev/Doc/samples/javaviewersample/overview/
   trunk/MgDev/Doc/samples/javaviewersample/overview/overviewmain.jsp
   trunk/MgDev/Doc/samples/javaviewersample/plot/
   trunk/MgDev/Doc/samples/javaviewersample/plot/plot.jsp
   trunk/MgDev/Doc/samples/javaviewersample/plot/plotmain.jsp
   trunk/MgDev/Doc/samples/javaviewersample/query/
   trunk/MgDev/Doc/samples/javaviewersample/query/classes/
   trunk/MgDev/Doc/samples/javaviewersample/query/classes/command.jsp
   trunk/MgDev/Doc/samples/javaviewersample/query/classes/feature.jsp
   trunk/MgDev/Doc/samples/javaviewersample/query/classes/property.jsp
   trunk/MgDev/Doc/samples/javaviewersample/query/classes/query.jsp
   trunk/MgDev/Doc/samples/javaviewersample/query/querycontroller.jsp
   trunk/MgDev/Doc/samples/javaviewersample/query/querymain.jsp
   trunk/MgDev/Doc/samples/javaviewersample/query/templates/
   trunk/MgDev/Doc/samples/javaviewersample/query/templates/filterlayerdefinition.xml
   trunk/MgDev/Doc/samples/javaviewersample/styles/
   trunk/MgDev/Doc/samples/javaviewersample/styles/gt.css
   trunk/MgDev/Doc/samples/javaviewersample/theme/
   trunk/MgDev/Doc/samples/javaviewersample/theme/classes/
   trunk/MgDev/Doc/samples/javaviewersample/theme/classes/command.jsp
   trunk/MgDev/Doc/samples/javaviewersample/theme/classes/layerinfo.jsp
   trunk/MgDev/Doc/samples/javaviewersample/theme/classes/property.jsp
   trunk/MgDev/Doc/samples/javaviewersample/theme/classes/theme.jsp
   trunk/MgDev/Doc/samples/javaviewersample/theme/templates/
   trunk/MgDev/Doc/samples/javaviewersample/theme/templates/arearuletemplate.xml
   trunk/MgDev/Doc/samples/javaviewersample/theme/themecontroller.jsp
   trunk/MgDev/Doc/samples/javaviewersample/theme/thememain.jsp
   trunk/MgDev/Doc/samples/javaviewersample/title.html
   trunk/MgDev/Doc/samples/javaviewersample/utilityfunctions.jsp
   trunk/MgDev/Doc/samples/phpviewersample/
   trunk/MgDev/Doc/samples/phpviewersample/JSON.php
   trunk/MgDev/Doc/samples/phpviewersample/ajaxtiledviewersample.php
   trunk/MgDev/Doc/samples/phpviewersample/ajaxviewersample.php
   trunk/MgDev/Doc/samples/phpviewersample/dwfviewersample.php
   trunk/MgDev/Doc/samples/phpviewersample/findaddress/
   trunk/MgDev/Doc/samples/phpviewersample/findaddress/clearaddressresults.php
   trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddress.php
   trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddressfunctions.php
   trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddressmain.php
   trunk/MgDev/Doc/samples/phpviewersample/findaddress/gotopoint.php
   trunk/MgDev/Doc/samples/phpviewersample/findaddress/kd_xmlrpc.php
   trunk/MgDev/Doc/samples/phpviewersample/findaddress/templates/
   trunk/MgDev/Doc/samples/phpviewersample/findaddress/templates/addressmarker.xml
   trunk/MgDev/Doc/samples/phpviewersample/images/
   trunk/MgDev/Doc/samples/phpviewersample/images/Thumbs.db
   trunk/MgDev/Doc/samples/phpviewersample/images/loader_inactive.gif
   trunk/MgDev/Doc/samples/phpviewersample/images/loader_pulse.gif
   trunk/MgDev/Doc/samples/phpviewersample/images/pushpin.jpg
   trunk/MgDev/Doc/samples/phpviewersample/images/pushpinblue.jpg
   trunk/MgDev/Doc/samples/phpviewersample/json.js
   trunk/MgDev/Doc/samples/phpviewersample/overview/
   trunk/MgDev/Doc/samples/phpviewersample/overview/overviewmain.php
   trunk/MgDev/Doc/samples/phpviewersample/plot/
   trunk/MgDev/Doc/samples/phpviewersample/plot/plot.php
   trunk/MgDev/Doc/samples/phpviewersample/plot/plotmain.php
   trunk/MgDev/Doc/samples/phpviewersample/query/
   trunk/MgDev/Doc/samples/phpviewersample/query/classes/
   trunk/MgDev/Doc/samples/phpviewersample/query/classes/feature.php
   trunk/MgDev/Doc/samples/phpviewersample/query/classes/property.php
   trunk/MgDev/Doc/samples/phpviewersample/query/classes/query.php
   trunk/MgDev/Doc/samples/phpviewersample/query/querycontroller.php
   trunk/MgDev/Doc/samples/phpviewersample/query/querymain.php
   trunk/MgDev/Doc/samples/phpviewersample/query/templates/
   trunk/MgDev/Doc/samples/phpviewersample/query/templates/filterlayerdefinition.xml
   trunk/MgDev/Doc/samples/phpviewersample/styles/
   trunk/MgDev/Doc/samples/phpviewersample/styles/gt.css
   trunk/MgDev/Doc/samples/phpviewersample/theme/
   trunk/MgDev/Doc/samples/phpviewersample/theme/classes/
   trunk/MgDev/Doc/samples/phpviewersample/theme/classes/layerinfo.php
   trunk/MgDev/Doc/samples/phpviewersample/theme/classes/property.php
   trunk/MgDev/Doc/samples/phpviewersample/theme/classes/theme.php
   trunk/MgDev/Doc/samples/phpviewersample/theme/templates/
   trunk/MgDev/Doc/samples/phpviewersample/theme/templates/arearuletemplate.xml
   trunk/MgDev/Doc/samples/phpviewersample/theme/themecontroller.php
   trunk/MgDev/Doc/samples/phpviewersample/theme/thememain.php
   trunk/MgDev/Doc/samples/phpviewersample/title.html
   trunk/MgDev/Doc/samples/phpviewersample/utilityfunctions.php
Removed:
   trunk/MgDev/Doc/devguide/source/maestroapi.rst
   trunk/MgDev/Doc/devguide/source/openlayers.rst
Modified:
   trunk/MgDev/Doc/devguide/source/custom_output.rst
   trunk/MgDev/Doc/devguide/source/fusion.rst
   trunk/MgDev/Doc/devguide/source/index.rst
   trunk/MgDev/Doc/devguide/source/mapagent.rst
Log:
#1614: Update the MapGuide Developer's Guide. Add a whole new section about Fusion (content copied from the wiki) and a summary of supplemental development options like OpenLayers and the Maestro API

Also check in the various viewer samples that are currently only available as zip downloads

Modified: trunk/MgDev/Doc/devguide/source/custom_output.rst
===================================================================
--- trunk/MgDev/Doc/devguide/source/custom_output.rst	2011-12-08 17:48:44 UTC (rev 6317)
+++ trunk/MgDev/Doc/devguide/source/custom_output.rst	2011-12-08 17:49:44 UTC (rev 6318)
@@ -50,6 +50,8 @@
    single: Rendering Service
    single: MgRenderingService
 
+.. _rendering-service:
+
 Rendering Service
 -----------------
 

Modified: trunk/MgDev/Doc/devguide/source/fusion.rst
===================================================================
--- trunk/MgDev/Doc/devguide/source/fusion.rst	2011-12-08 17:48:44 UTC (rev 6317)
+++ trunk/MgDev/Doc/devguide/source/fusion.rst	2011-12-08 17:49:44 UTC (rev 6318)
@@ -1,20 +1,519 @@
 .. index:
    single: fusion
 
-The Fusion Application Framework
-================================
+Fusion
+======
 
 Introduction
 ------------
 
+Fusion is a web-mapping application development framework for `MapGuide Open Source <http://mapguide.osgeo.org>`_ / `Autodesk Infrastructure Map Server <http://usa.autodesk.com/adsk/servlet/pc/index?id=16505474&siteID=123112>`_ that is built primarily in JavaScript.
+
+It allows non-spatial web developers to build rich mapping applications quickly and easily.
+
+Based on the defacto standard spatial javascript API `OpenLayers <http://www.openalayers.org>`_, you can extend it easily.
+
+Using widgets, developers are able to add, remove, or modify functionality using standard-compliant HTML and CSS.
+
+Fusion does not require any proprietary browser plug-ins and works in `all the major browsers on Windows, Mac, and Linux <http://trac.osgeo.org/fusion/wiki/TechSpecs>`_.
+
+Fusion is also referred to as Flexible Layouts inside Autodesk MapGuide Studio 
+
 Essential Concepts
 ------------------
 
-Widgets
--------
+It is very important that you understand how MapGuide works. MapGuide comes with its own extensive documentation. If you are not familiar with creating MapDefinition resources, please review the MapGuide documentation.
 
+Fusion is all about creating a web application. You will need some familiarity with HTML, JavaScript?, CSS.
+
+The primary development language for building Fusion applications is JavaScript, but if you need to add server-side functionality using the MapGuide API, then a knowledge of PHP is also required.
+
+Fusion makes extensive use of static and dynamically generated HTML. You need to be familiar with the Document Object Model (DOM) implemented by various browsers, and the subtle differences between the browsers in how scripting with the DOM works. Although it is possible to use Fusion without any DOM scripting, it is likely that most applications will need to use some scripting to achieve their desired functionality.
+
+Fusion makes extensive use of CSS to achieve its look and feel in a minimally intrusive way. The design principle behind much of the structure of the user interface components of Fusion is to let the browser do as much of the work as possible with its native layout engine. This is the most efficient and natural design for web pages, and reduces the amount of javascript code that needs to be executed by the client's browser. You will need to thoroughly understand CSS design and implementation concepts in order to fully customize the Fusion interface, but to use the default look and feel of Fusion with moderate customization does not require advanced CSS knowledge. 
+
+.. _hello-sheboygan:
+
+Hello Sheboygan - An example template
+-------------------------------------
+
+Creating a new Fusion application is really quite straight-forward. The simplest way to demonstrate the core concepts of Fusion is to build a small, working application. The Hello Sheboygan application is going to have a map and three navigation tools (zoom in, zoom out, and pan). It will be fully functional, albeit quite plain!
+
+<image of app here>
+
+.. note::
+
+    This section is simply to demonstrate the inner workings of a Fusion template. For practical purposes, you would probably be using the using one of the 5 available templates already provided by MapGuide: 
+    
+         * `Slate` 
+         * `Maroon`
+         * `Aqua`
+         * `LimeGold` 
+         * `TurquoiseYellow`
+         
+    In such cases, any such custom functionality you want to add into a Fusion application would be done through widgets. See :ref:`widget-basics` for more information.
+
+First, create a directory on your server to hold all the files required by the application. The directory needs to be in a web-accessible location. You can always create a directory in your www folder of your MapGuide Open Source installation if you don't know where else to put it. Call this directory hello.
+
+The next step is to decide what functionality, or widgets, are needed by the application. The list (from the description above) is:
+
+    * a Map widget
+    * a Zoom In widget
+    * a Zoom Out widget
+    * a Pan widget 
+
+These widgets need to be described in an ApplicationDefinition xml file. Fusion allows you to store the ApplicationDefinition resource in the MapGuide repository or as a separate XML file. For the purpose of this document, we will be assuming that you are storing the ApplicationDefinition resource as a separate XML file. There are instructions at the end of this document for using an ApplicationDefinition resource stored in a MapGuide repository.
+
+By convention, the name of the file is ApplicationDefinition.xml. So, create a new file in the hello directory and name it ApplicationDefinition.xml. For our very simple example, we need an ApplicationDefinition tag with a Title tag, a MapGroup tag, and a WidgetSet tag to hold our four widgets (see the ApplicationDefinition page for a more complete description). Individual widgets are represented as Widget tags inside the WidgetSet tag where the actual Widget is specified by the Type tag and the HTML element that the Widget will be created in is specified by the Name tag. Our four widgets each have a specific Widget tag with several options, most of which are not required for this example. The resulting XML for Hello Sheboygan is: 
+
+.. highlight:: xml
+.. code-block:: xml
+
+    <ApplicationDefinition 
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+          xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
+          xsi:noNamespaceSchemaLocation="ApplicationDefinition-1.0.0.xsd">
+      <Title>Hello Sheboygan</Title>
+      <MapGroup>
+        <Map xsi:type="MapGuideLayerType">
+          <Type>MapGuide</Type>
+          <SingleTile>true</SingleTile>
+          <Extension>
+            <ResourceId>Library://Samples/Sheboygan/Maps/Sheboygan.MapDefinition</ResourceId> 
+          </Extension>
+        </Map>
+      </MapGroup>
+      <WidgetSet>
+        <MapWidget>
+          <Name>Map</Name>
+          <Type>Map</Action>
+          <StatusText/>
+          <MapId>HelloSheboygan</MapId>
+        </Widget>
+        <Widget>
+          <Name>ZoomIn</Name>
+          <Type>Zoom</Type>
+          <StatusText/>
+          <Extension>
+            <Direction>in</Direction>
+          </Extension>
+          <ImageUrl>images/icons/zoom-in.png</ImageUrl>
+          <ImageClass/>
+          <Label/>
+          <Tooltip>Click or click and drag on the map to zoom in</Tooltip>
+          <Disabled/>
+        </Widget>
+        <Widget>
+          <Name>ZoomOut</Name>
+          <Type>Zoom</Type>
+          <StatusText/>
+          <Extension>
+            <Direction>out</Direction>
+          </Extension>
+          <ImageUrl>images/icons/zoom-out.png</ImageUrl>
+          <ImageClass/>
+          <Label/>
+          <Tooltip>Click on the map to zoom out</Tooltip>
+          <Disabled/>
+        </Widget>
+        <Widget>
+          <Name>Pan</Name>
+          <Type>Pan</Type>
+          <StatusText/>
+          <Extension/>
+          <ImageUrl>images/icons/pan.png</ImageUrl>
+          <ImageClass/>
+          <Label/>
+          <Tooltip>Click and drag the map to pan</Tooltip>
+          <Disabled/>
+        </Widget>    
+      </WidgetSet>
+      <Extension />
+    </ApplicationDefinition>
+
+The next thing that our `Hello World` application needs is a template, which is simply an html file. Create a new file in the `hello` directory and name it index.html. Here's the `index.html` file contents: 
+
+.. highlight:: html
+.. code-block:: html
+
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+    <html>
+    <head>
+    <title>Hello Sheboygan</title>
+    <!-- change the source of the following tag to point to your fusion installation -->
+    <script type="text/javascript" src="../fusion/lib/fusion.js"></script>
+    <script type="text/javascript">
+    window.onload = function() {
+        Fusion.initialize();
+    }
+    </script>
+    </head>
+    <body>
+    <div id="Toolbar" style="position: relative; width: 400px; height: 24px">
+        <div id="ZoomIn"></div>
+        <div id="ZoomOut"></div>
+        <div id="Pan"></div>
+    </div>
+    <div id="Map" style="position: relative; width: 400px; height: 400px"></div>
+    </body>
+    </html>
+
+It is highly recommended to use a valid doctype for your Fusion application template pages. If you omit the doctype or use an invalid doctype, most browsers will revert to a mode called `Quirks Mode`. Fusion will mostly function correctly, but you may notice some minor issues and your application may appear differently depending on the browser. By using a valid HTML or XHTML doctype, browsers will use a mode called `Standards Compliant Mode` and your application will work consistently between different browsers.
+
+You will need to make sure that the **src** of the script tag that points to `fusion.js` is a valid path, it can be relative (as in the example above) or absolute (starting with `http://`). If it is absolute, then the url must be pointing to the same server as the url you use to load the application.
+
+That is all that is needed to build a fully functional Fusion application. Save your files and then load the application by entering the URL to the `index.html` page in your web browser. If everything is set up correctly, you should see three buttoms appear, followed shortly by a square map image below the buttons. You can click any of the buttons to activate them, and use them on the map. 
+
+Under the hood
+^^^^^^^^^^^^^^
+
+As you can see, quite a lot of things are going on without a lot of code. Adding other widgets is as simple as adding an HTML container for them in the HTML page and adding a Widget in the WidgetSet. So how exactly does Fusion turn this small amount of HTML and XML into a functional web mapping application?
+
+The first important step is including fusion.js in your web page (the first script tag in the :ref:`hello-sheboygan` example). This makes Fusion available to your application. The second important step is invoking the `Fusion.initialize()` method during (or after) the **onload** event of the web page (the contents of the second script tag). `Fusion.initialize()` starts the process of getting the application running and the following steps happen:
+
+    * the Fusion configuration file (config.json) is loaded and parsed
+    * the ApplicationDefinition configuration file is loaded and parsed
+    * Widgets with associated HTML elements are identified
+    * the JavaScript file associated with each identified Widget is loaded
+    * any dependencies of the Widget are loaded
+    * when all Widgets (and their dependencies such as CSS files) are loaded, a new instance of each Widget is created for each HTML element.
+    * when all Widget have been initialized, the `FUSION_INITIALIZED` event is emitted. 
+
+An important step in this process is the loading of the MapWidget(s). After each MapWidget has been created, it:
+
+    * attempts to create a session with the server for that Map instance. All Map instances of the same Type will share the same session.
+    * if an initial Map is specified:
+        * issue a `MAP_LOADING` event
+        * attempt to load the Map (which will wait until the session has been created)
+        * issue a `MAP_LOADED` event when the map has finished loading 
+
+All Widgets in a WidgetSet are associated with the MapWidget of that WidgetSet. 
+
+How Fusion is integrated with MapGuide
+--------------------------------------
+
+MapGuide Open Source architecture is divided into three tiers:
+
+Server Tier:
+
+    This tier runs the MapGuide Open Source server. Fusion is not integrated into this tier.
+
+Web Extensions Tier:
+
+    This tier runs with a Web Server. Fusion is installed in this tier and makes use of the MapGuide Open Source Web Extensions API to implement some functionality.
+
+Client Tier:
+
+    This tier runs in the client's web browser. Most of Fusion exists in this tier, and it completely replaces the existing MapGuide Open Source client tier (known as the AJAX viewer).
+
+The Fusion Server components work directly with the MapGuide Open Source PHP API to implement specific functionality such as buffering features and working with selections.
+
+The Fusion JavaScript API and Widget are installed with the MapGuide Open Source Web Tier, but they are actually loaded up to and executed in the Client Tier. 
+
+Application Definitions, HTML and Widgets
+-----------------------------------------
+
+The API and Widget are linked to specific HTML elements within an HTML page through the ApplicationDefinition XML document. A Widget is the executable code (JavaScript class) that is loaded when Fusion identifies an HTML element id and Widget Name that are the same. The Type of the Widget identifies the exact JavaScript file to be loaded and the JavaScript object that needs to be instantiated to create a functional Widget. The runtime instance of the JavaScript object is the Widget.
+
+When the runtime instance is created, it uses the HTML element id to determine where in the HTML page it should display its user interface. Any custom configuration for the Widget is placed in the ApplicationDefinition Widget XML block as sub tags (each Widget has its own list of what customization is possible, see the Widget API Reference for details).
+
+If you are customizing the look and feel of a single Widget by overriding the CSS styling for the Widget, this is normally done by using the #<id> syntax to limit your changes to that specific Widget. 
+
+.. _widget-basics:
+
+Widget Basics
+-------------
+
+Widgets are the discrete pieces of functionality that your Fusion application is composed of. The standard fusion template provides a lot of widgets out of the box, and a new Application Definition created by an authoring tool like MapGuide Maestro will include many of these widgets for you. So a default application is already pretty rich in functionality.
+
+Whereas custom commands are the way to add new behaviour to an AJAX viewer application. Custom functionality in a Fusion application can be provided in the following forms:
+
+ * An :ref:`invoke-script-widget` widget
+ * An :ref:`invoke-url-widget` widget
+
+.. _invoke-script-widget:
+
+Invoke Script
+^^^^^^^^^^^^^
+
+Invoke Script widgets function like their counterpart in the AJAX viewer. The main difference is that your script code has to work against the Fusion API instead of the AJAX viewer API, if you are going to use such features. You will need to use an authoring tool like MapGuide Maestro or hack the Application Defintion XML document itself to modify the script code for a Invoke Script widget
+
+.. _invoke-url-widget:
+
+Invoke URL
+^^^^^^^^^^
+
+Invoke URL widgets function like their counterpart in the AJAX viewer. Just like the Invoke Script widget, the main difference is that any javascript code that you emit from the URL you are invoking that uses the AJAX viewer API will need to be converted to use the Fusion API instead. As Invoke URL widgets just simply invoke a URL, you can use any language (.net/Java/PHP) for the server page that is invoked when working with the MapGuide API.
+
+MapGuideViewerApi.js
+^^^^^^^^^^^^^^^^^^^^
+
+If you've worked with the AJAX viewer API, then the Fusion API will look completely different to you. The `MapGuideViewerApi.js` utility library is included in the Fusion framework which provides a subset of the AJAX viewer API to help ease the transition of your javascript code from the AJAX viewer API to Fusion.
+
+The `MapGuideViewerApi.js` file is located under the `layers\MapGuide` subdirectory of your Fusion directory
+
 Events
 ------
 
+The event code in Fusion is designed to provide an asynchronous notification mechanism that can be used to register for, and receive notification of, key events that happen asynchronously in Fusion. The following terms are used with respect to events:
+
+    * `event id`: a unique identifier for an event, represented by a javascript variable that is all in upper case (e.g `FUSION_INITIALIZED`)
+    * `trigger`: when an event occurs, it is 'triggered' and all the registered callback functions are notified
+    * `register`: provide a callback function that is called when an event is triggered
+    * `deregister`: remove a callback function that was previously registered
+    * `publish`: anything that can trigger an event must publish all the valid event ids 
+
+The event mechanism of Fusion is implemented by two functions: registerForEvent and deregisterForEvent. Both functions have the same signature, taking an event ID as the first parameter and a callback function pointer as the second parameter.
+
+The Fusion application object provides two specific events that can be used by applications to get notification of when Fusion initialization has completed and when an error occurs anywhere in Fusion. These events are:
+
+`Fusion.Event.FUSION_INITIALIZED:`
+
+    This is triggered when Fusion's initialization is complete and the application is running. This signals that it is safe for the application to communicate with specific Widgets. Note that the MapWidget, specifically, will be ready but may not have actually loaded the map. There is a separate event for that . Applications should register for this event before calling `Fusion.initialize()`.
+
+`Fusion.Event.FUSION_ERROR:`
+
+    This is triggered when an internal error happens. Details on the error are passed to the callback function. Applications should register for this event before calling `Fusion.initialize()` to ensure that they receive errors that happen during initialization.
+
+Widgets in Fusion also use and trigger events. Widgets are designed to be completely independent of one another, allowing them to be added to, or removed from, applications with little or no impact on the other Widgets in the application. However, there are cases (especially with the MapWidget) where it is important that Widgets be able to communicate with other Widgets or with the application as a whole. For these situations, there is an event mechanism built into Fusion that allows Widgets, and applications built on Fusion, to register for and trigger events. The event mechanism allows Widgets to be independent of each other, but still provide a high level of integration when required.
+
+To register a callback function for a Widget event, the application must first obtain a reference to the Widget through one of the methods of the `Fusion` object (`getWidgetById` typically) and then call `registerForEvent` passing one of the event IDs that is valid for that Widget. 
+
 Working With Maps
 -----------------
+
+In Fusion, the MapWidget is central to everything that is going on. It is not valid to design a Fusion application without a Map in it. The MapWidget is the primary interface between the application and the spatial data represented by the map. Most widgets in Fusion either display information about the map or allow the user to interact with the map in some way.
+
+The Map widget API is probably the most used one in Fusion. It is completely documented in the Command API reference, but the most used methods are described here.
+
+`loadMap(mapDefinition):`
+
+    This causes the Map widget to load the specified MapDefinition?.
+
+`reloadMap():`
+
+    This causes the Map widget to reload the current MapDefinition?. This is necessary when the map state has changed in certain ways (adding or removing layers in the map, for instance) and is primarily an internal function.
+
+`setExtents(minx, miny, maxx, maxy).` This is used to set the map extents to a particular bounding box programmatically. drawMap():
+
+    This is used to render a map image and load it in the browser. Normally, this is called automatically as required, but occasionally it may be required to be called programmatically when the state of the map has changed on the server without the knowledge of the Map widget.
+
+`query(options):`
+
+    This is described more completely in the Command API Reference, but the query method is used to query the Map in some way and create (or modify) a selection.
+
+`getSessionId():`
+
+    This returns the session id that is used with the server side support scripts for this map.
+
+When a Map is defined in the ApplicationDefinition file, it can have a default MapDefinition that is automatically loaded when the application is loaded. But it is not mandatory to specify a default map. When no default map is specified, the Map widget is still initialized. Loading of a MapDefinition is then done in response to a widget (such as the MapMenu? widget) or some application-specific code. Regardless of how it happens, when a MapDefinition has been loaded, the Map widget will trigger a `Fusion.Event.MAP_LOADED` event. Most widgets are not useful if there is no map loaded, so they use the `Fusion.Event.MAP_LOADED` event to determine when they should be enabled. This means that most widgets will appear initially disabled until the map has been loaded. There are some notable exceptions, including the Map Menu widget which is used to provide a drop-down menu of MapDefinitions that the user can pick from.
+
+Once the Map is loaded, many events may be triggered, including:
+
+`Fusion.Event.MAP_SESSION_CREATED:`
+
+    The Map widget is responsible for creating and maintaining a session with the server. When the session has been created, this event is triggered. Nothing can happen until this event has been triggered.
+
+`Fusion.Event.MAP_LOADING:`
+
+    The Map widget triggers this event when it is starting to load a new Map. This is primarily used by widgets to prepare themselves for the new map by discarding their current state and temporarily disabling themselves.
+
+`Fusion.Event.MAP_LOADED:`
+
+    The Map widget triggers this event when a map has been loaded and is ready.
+
+`Fusion.Event.MAP_RELOADED:`
+
+    The Map widget triggers this event when the current map has been reloaded and is ready.
+
+`Fusion.Event.MAP_EXTENTS_CHANGED:`
+
+    The Map widget triggers this event for any navigation that changes the current extents.
+
+`Fusion.Event.MAP_BUSY_CHANGED:`
+
+    The Map widget maintains a reference count of asynchronous events as they start and finish. An application can use this event to display a processing image so that the user is aware that some asynchronous activitity is happening.
+
+`Fusion.Event.MAP_RESIZED:`
+
+    The Map widget triggers this event when the size of the map is changed.
+
+`Fusion.Event.MAP_SELECTION_ON:`
+
+    The Map widget triggers this event when a new selection has been created.
+
+`Fusion.Event.MAP_SELECTION_OFF:`
+
+    The Map widget triggers this event when the current selection has been cleared.
+
+`Fusion.Event.MAP_ACTIVE_LAYER_CHANGED:`
+
+    The Map widget allows for a single layer to be marked as active by the application. This event is triggered when the active layer is changed.
+
+`Fusion.Event.MAP_GENERIC_EVENT:`
+
+    Most widgets rely directly on their Map widget for everything. In some cases, though, widgets need to be informed of changes in other widgets. In these cases, the Map widget can act as a broker for events through the `MAP_GENERIC_EVENT`. Widgets that employ the `Fusion.Event.MAP_GENERIC_EVENT` normally do so for a specific internal purpose, and the application should not normally register for this event.
+
+Working with Selections
+
+There are several widgets in Fusion that allow the user to interactively select features on the Map. Fusion takes care of updating the Map image with the current selection, if necessary, but does not display attributes of the selected features to the user. That is up to the application.
+
+Regardless of how the features are selected, the Map widget provides the API for an application to retrieve and work with the user's selection. There are two events that can be used by an application to know when the user selection has changed:
+
+`Fusion.Event.MAP_SELECTION_ON:`
+
+    The Map widget triggers this event when a new selection has been created.
+
+`Fusion.Event.MAP_SELECTION_OFF:`
+
+    The Map widget triggers this event when the current selection has been cleared.
+
+When the application receives a `Fusion.Event.MAP_SELECTION_ON` event from the Map widget, it can use the following functions to work with the selection:
+
+`hasSelection():`
+
+    This method returns a boolean value which indicates if there is currently a selection or not
+
+`getSelection(callback):`
+
+    This method retrieves the current selection. Retrieving the selection is potentially an asynchronous operation and so the callee provides a callback function that is called when the selection is ready. The callback function is passed a single argument, a Selection object, described below.
+
+`clearSelection():`
+
+    This method is used to clear the current selection. This removes the selection from the map and invalidates the current selection object.
+
+An application will typically call `getSelection()` in response to the `MAP_SELECTION_ON` event. Typical code for this might look like: 
+
+**JavaScript**
+
+.. highlight:: javascript
+.. code-block:: javascript
+
+    window.onload=function() {
+        Fusion.registerForEvent(Fusion.Event.FUSION_INITIALIZED, onInitialized);
+        Fusion.initialize();
+    }
+
+    var theMap;
+    function onInitialized() {
+        theMap = Fusion.getWidgetById('Map');
+        theMap.registerForEvent(Fusion.Event.MAP_SELECTION_ON, selectionOn);
+        theMap.registerForEvent(Fusion.Event.MAP_SELECTION_OFF, selectionOff);
+    }
+
+    function selectionOn() {
+        //a new selection has been made, request it
+        theMap.getSelection(displaySelection);
+    }
+
+    function displaySelection(selection) {
+        //display the selection to the user in some way ...
+    }
+
+    function selectionOff() {
+        //clear the selection results
+    }
+    
+A Selection object is used to access the selection results. It provides the following API:
+
+`getNumLayers():`
+
+    returns the number of layers that have features selected
+
+`getNumElements():`
+
+    returns the total number of features that are selected
+
+`getLowerLeftCoord():`
+
+    returns the lower, left coordinate of the bounding box of all selected features
+
+`getUpperRightCoord():`
+
+    returns the upper, right coordinate of the bounding box of all selected features
+
+`getLayerByName(name):`
+
+    gets the layer selection object for a layer from the name of the layer. This returns null if there is no layer with the requested name in the selection results
+
+`getLayer(index):`
+
+    gets the layer selection object for the requested layer where index is between 0 and one less that the value returned by `getNumLayers()`.
+
+An application will typically loop over the layers in a selection and retrieve individual results using the Layer Selection object returned by `getLayer()` or `getLayerByName()`. Layer selection objects have the following API
+
+`getName():`
+
+    returns the name of the layer that the selected features are in
+
+`getNumElements():`
+
+    returns the number of features selected in this layer
+
+`getNumProperties():`
+
+    returns the number of data properties, or attributes, of the features in this layer
+
+`getPropertyNames():`
+
+    returns an array of the names of each of the properties
+
+`getPropertyTypes():`
+
+    returns an array of the types of the properties
+
+`getElementValue(elementIndex, propertyIndex):`
+
+    returns the actual value of a given property for a given element
+
+The following code is an example of how to use the Selection and Layer Selection objects to create a tabular display of selected features. 
+
+**JavaScript**
+
+.. highlight:: javascript
+.. code-block:: javascript
+
+    function displaySelection(selection) {
+        //display the selection to the user in some way ...
+        //make sure something got selected ...
+        if (selection && selection.getNumElements() > 0) {
+           //obtain a reference to the HTML Element that the results
+           //will be placed in
+           var resultElm = $('selectionResultDiv');
+           for (var i=0; i<selection.getNumLayers(); i++) {
+              var selectionLayer = selection.getLayer(i);
+              var propNames = selectionLayer.getPropertyNames();
+              var span = document.createElement('span');
+              span.className = 'selectionResultsTitle';
+              span.innerHTML = 'Layer ' + selectionLayer.getName();
+              resultElm.appendChild(span);
+              var table = document.createElement('table');
+              table.className = 'selectionResultsTable';
+              resultElm.appendChild(table);
+              //set up the table header to be the property names         
+              var thead = document.createElement('thead');
+              table.appendChild(thead);
+              var tr = document.createElement('tr');
+              thead.appendChild(tr);
+              for (var j=0; j<propNames.length; j++) {
+                 var td = document.createElement('td');
+                 td.innerHTML = propNames[j];
+                 tr.appendChild(td);
+              }
+              //output the selection values
+              var tbody = document.createElement('tbody');
+              table.appendChild(tbody);
+              for (var j=0; j<selectionLayer.getNumElements(); j++) {
+                 var tr = document.createElement(tr);
+                 tbody.appendChild(tr);
+                 for (var k=0; k<propNames.length; k++) {
+                    var td = document.createElement('td');
+                    td.innerHTML = selectionLayer.getElementValue(j, k);
+                    tr.appendChild(td);
+                 }
+              }
+               }
+        } else {
+           //could display a message of some sort saying nothing was selected?
+        }
+    }
\ No newline at end of file

Modified: trunk/MgDev/Doc/devguide/source/index.rst
===================================================================
--- trunk/MgDev/Doc/devguide/source/index.rst	2011-12-08 17:48:44 UTC (rev 6317)
+++ trunk/MgDev/Doc/devguide/source/index.rst	2011-12-08 17:49:44 UTC (rev 6318)
@@ -23,11 +23,10 @@
    analyzing_features
    digitizing_and_redlining
    custom_output
-   openlayers
    fusion
    mapagent
-   maestroapi
    mapguide_advanced
+   supplemental_development
    mapguide_cookbook
 
 Indices and tables

Deleted: trunk/MgDev/Doc/devguide/source/maestroapi.rst
===================================================================
--- trunk/MgDev/Doc/devguide/source/maestroapi.rst	2011-12-08 17:48:44 UTC (rev 6317)
+++ trunk/MgDev/Doc/devguide/source/maestroapi.rst	2011-12-08 17:49:44 UTC (rev 6318)
@@ -1,20 +0,0 @@
-.. index:
-   single: maestro
-   
-Using the Maestro API
-=====================
-
-Introduction
-------------
-
-The Server Connection Interface
--------------------------------
-
-The Resource Object Model
--------------------------
-
-Resource Validation
--------------------
-
-Using the Official MapGuide API
--------------------------------
\ No newline at end of file

Modified: trunk/MgDev/Doc/devguide/source/mapagent.rst
===================================================================
--- trunk/MgDev/Doc/devguide/source/mapagent.rst	2011-12-08 17:48:44 UTC (rev 6317)
+++ trunk/MgDev/Doc/devguide/source/mapagent.rst	2011-12-08 17:49:44 UTC (rev 6318)
@@ -2,4 +2,25 @@
    single: mapagent
    
 The Map Agent
-=============
\ No newline at end of file
+=============
+
+The MapGuide API is only accessible from the web tier, and only communicates with the server tier. Client applications like the AJAX viewer do not use the MapGuide API to communicate with the MapGuide Server, instead they communicate with the MapGuide Server through a subset of the MapGuide API exposed by the `mapagent` over the standard http protocol.
+
+When the AJAX viewer renders a map, it is not using the :ref:`rendering-service` of the MapGuide API to do this. It is issuing a basic HTTP request to the mapagent to do this.
+
+The mapagent, exposes a pretty large set of the MapGuide API over http, that is available for client consumption. The only pieces of the MapGuide API that are not exposed are:
+
+ * Feature Service API that involve updating/inserting data and transactions
+    * UpdateFeatures
+    * ApplySchema
+    * BeginTransaction
+
+Because this functionality is exposed over http, you can programmatically communicate with the mapagent by making http requests to the mapagent url.
+
+.. note::
+
+    The mapagent URL is generally `http://yourservername:port/mapguide/mapagent/mapagent.fcgi`. On a default Apache installation, this port number is usually 8008
+    
+Unlike the MapGuide API, you can use any language that supports making http requests. In this respects, using the mapagent is a more flexible approach.
+
+For a strongly-typed client service interface to the mapagent, you can use the :ref:`maestroapi`.
\ No newline at end of file

Deleted: trunk/MgDev/Doc/devguide/source/openlayers.rst
===================================================================
--- trunk/MgDev/Doc/devguide/source/openlayers.rst	2011-12-08 17:48:44 UTC (rev 6317)
+++ trunk/MgDev/Doc/devguide/source/openlayers.rst	2011-12-08 17:49:44 UTC (rev 6318)
@@ -1,5 +0,0 @@
-.. index:
-   single: openlayers
-   
-Using OpenLayers with MapGuide
-==============================
\ No newline at end of file

Added: trunk/MgDev/Doc/devguide/source/supplemental_development.rst
===================================================================
--- trunk/MgDev/Doc/devguide/source/supplemental_development.rst	                        (rev 0)
+++ trunk/MgDev/Doc/devguide/source/supplemental_development.rst	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,38 @@
+Supplemental Development Options
+================================
+
+If the MapGuide Web Extensions and viewer APIs do not cover your development needs or you are looking for other available options for MapGuide application development, other options are available to you.
+
+.. _openlayers:
+
+OpenLayers
+----------
+
+OpenLayers is a free and open source javascript library that makes it easy to put a dynamic map in any web page. It can display map tiles, iamges and markers loaded from any source.
+
+OpenLayers includes a MapGuide layer type, allowing for your MapGuide maps to be integrated into the OpenLayers ecosystem with other Map Servers and other data sources.
+
+Visit `the OpenLayers homepage <http://www.openlayers.org>`_ for more information
+
+.. note::
+
+    Fusion is also built on top of OpenLayers, so any OpenLayers knowledge you have is also applicable here.
+
+.. _maestroapi:
+
+Maestro API
+-----------
+
+MapGuide Maestro is a free and open source authoring tool for MapGuide Open Source / Autodesk Infrastructure Map Server. It is an alternative to Autodesk MapGuide Studio.
+
+The Maestro API is a 100% fully managed .net class library that provides the following features:
+
+ * A strongly-typed service client interface to the http mapagent, that alleviates the need for boilerplate http request/response processing.
+ * An object model for working with resources in terms of classes and interfaces instead of raw XML content, with support for many different schema versions.
+ * A unified programming interface that can work with the mapagent or the MapGuide Server directly
+ * Easy integration with both web (ASP.net) and desktop (WinForms/WPF) enviroments
+ * Support for many different versions of MapGuide
+
+This library is used by the MapGuide Maestro application, and can be used in your own applications.
+
+Visit `the Maestro project homepage <http://trac.osgeo.org/mapguide/wiki/maestro>`_ for more information
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/dotnetviewersample/ReadMe.txt
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/ReadMe.txt	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/ReadMe.txt	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,7 @@
+SETUP GUIDE
+-----------
+
+1. Copy all DLLs from C:\Program Files\Autodesk\MapGuideEnterprise2008\WebServerExtensions\www\mapviewernet\bin to C:\Program Files\Autodesk\MapGuideEnterprise2008\WebServerExtensions\www\dotnetviewersample\bin
+2. Open the Internet Information Services application (available from Administrative Tools) and navigate to Default Web Site/mapguide2008.
+3. Configure dotnetviewersample as an application (right-click dotnetviewersample and select properties, then click Create).
+4. Click Ok to create the virtual directory.

Added: trunk/MgDev/Doc/samples/dotnetviewersample/ajaxtiledviewersample.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/ajaxtiledviewersample.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/ajaxtiledviewersample.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,61 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" Debug="true"%>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<!-- #Include File="utilityfunctions.aspx -->
+
+<script runat="server">
+String webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganAspTiled.WebLayout";
+String defaultUser = "Anonymous";
+String defaultPassword = "";
+String sessionId = "";
+</script>
+
+<%
+    try
+    {
+        // Initialize a session and register a variable to hold the
+        // session id, then initialize the Web Extensions, connect
+        // to the site, and create a session.
+
+        InitializeWebTier();
+
+        MgUserInformation userInfo = new MgUserInformation(defaultUser, defaultPassword);
+        MgSite site = new MgSite();
+        site.Open(userInfo);
+        sessionId = site.CreateSession();
+    }
+    catch (Exception e)
+    {
+        Response.Write(e.Message);
+    }
+%>
+
+<html>
+<head>
+	<title>Viewer Sample Application</title>
+</head>
+<frameset rows="30,*" frameborder="no" framespacing="0">
+	<frame id="titleFrame" frameborder="no" marginwidth="0" marginheight="0" scrolling="no" src="title.html">
+	<frame id="viewerFrame" frameborder="no" marginwidth="0" marginheight="0" scrolling="no" src="../mapviewernet/ajaxviewer.aspx?SESSION=<%=sessionId%>&WEBLAYOUT=<%=webLayout%>">
+</frameset>
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/ajaxviewersample.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/ajaxviewersample.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/ajaxviewersample.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,61 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" Debug="true"%>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<!-- #Include File="utilityfunctions.aspx -->
+
+<script runat="server">
+String webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganAsp.WebLayout";
+String defaultUser = "Anonymous";
+String defaultPassword = "";
+String sessionId = "";
+</script>
+
+<%
+    try
+    {
+        // Initialize a session and register a variable to hold the
+        // session id, then initialize the Web Extensions, connect
+        // to the site, and create a session.
+
+        InitializeWebTier();
+
+        MgUserInformation userInfo = new MgUserInformation(defaultUser, defaultPassword);
+        MgSite site = new MgSite();
+        site.Open(userInfo);
+        sessionId = site.CreateSession();
+    }
+    catch (Exception e)
+    {
+        Response.Write(e.Message);
+    }
+%>
+
+<html>
+<head>
+	<title>Viewer Sample Application</title>
+</head>
+<frameset rows="30,*" frameborder="no" framespacing="0">
+	<frame id="titleFrame" frameborder="no" marginwidth="0" marginheight="0" scrolling="no" src="title.html">
+	<frame id="viewerFrame" frameborder="no" marginwidth="0" marginheight="0" scrolling="no" src="../mapviewernet/ajaxviewer.aspx?SESSION=<%=sessionId%>&WEBLAYOUT=<%=webLayout%>">
+</frameset>
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/bin/Jayrock.Json.dll
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/dotnetviewersample/bin/Jayrock.Json.dll
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/dotnetviewersample/bin/Jayrock.dll
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/dotnetviewersample/bin/Jayrock.dll
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/dotnetviewersample/dwfviewersample.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/dwfviewersample.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/dwfviewersample.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,61 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" Debug="true"%>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<!-- #Include File="utilityfunctions.aspx -->
+
+<script runat="server">
+String webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganAsp.WebLayout";
+String defaultUser = "Anonymous";
+String defaultPassword = "";
+String sessionId = "";
+</script>
+
+<%
+    try
+    {
+        // Initialize a session and register a variable to hold the
+        // session id, then initialize the Web Extensions, connect
+        // to the site, and create a session.
+
+        InitializeWebTier();
+
+        MgUserInformation userInfo = new MgUserInformation(defaultUser, defaultPassword);
+        MgSite site = new MgSite();
+        site.Open(userInfo);
+        sessionId = site.CreateSession();
+    }
+    catch (Exception e)
+    {
+        Response.Write(e.Message);
+    }
+%>
+
+<html>
+<head>
+	<title>Viewer Sample Application</title>
+</head>
+<frameset rows="30,*" frameborder="no" framespacing="0">
+	<frame id="titleFrame" frameborder="no" marginwidth="0" marginheight="0" scrolling="no" src="title.html">
+	<frame id="viewerFrame" frameborder="no" marginwidth="0" marginheight="0" scrolling="no" src="../mapviewernet/dwfviewer.aspx?SESSION=<%=sessionId%>&WEBLAYOUT=<%=webLayout%>">
+</frameset>
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/clearaddressresults.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/clearaddressresults.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/clearaddressresults.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,96 @@
+<%--
+Copyright (C) 2004-2006  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" %>
+<%@ Import Namespace="System" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+<!-- #Include File="../utilityfunctions.aspx" -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<html>
+<head>
+    <title>Viewer Sample Application - Clear Address Results</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <meta http-equiv="content-script-type" content="text/javascript">
+</head>
+<%
+String mgSessionId = GetRequestParameters()["SESSION"];
+
+try
+{
+    // Initialize the web-extensions and connect to the Site using
+    // the session identifier stored
+
+    InitializeWebTier();
+
+    MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+    MgSiteConnection siteConnection = new MgSiteConnection();
+    siteConnection.Open(userInfo);
+
+
+    MgFeatureService featureService = siteConnection.CreateService(MgServiceType.FeatureService) as MgFeatureService;
+
+    MgResourceIdentifier addressMarkerDataResId = new MgResourceIdentifier("Session:" + mgSessionId + "//AddressMarker.FeatureSource");
+
+    MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
+    commands.Add(new MgDeleteFeatures("AddressMarker", "ID like '%'"));
+
+    featureService.UpdateFeatures(addressMarkerDataResId, commands, false);
+
+    // Create a ReserviceService object and use it to open the Map
+    // object from the sessions repository. Use the Map object to hide
+    // the "ParcelMarker" layer and then save the updated Map back to
+    // the session.
+
+    MgResourceService resourceService = siteConnection.CreateService(MgServiceType.ResourceService) as MgResourceService;
+    MgMap map = new MgMap();
+    map.Open(resourceService, "Sheboygan");
+
+    MgLayer layer = GetLayerByName(map, "AddressMarker");
+    layer.SetVisible(false);
+    layer.ForceRefresh();
+
+    map.Save(resourceService);
+}
+catch (MgException mge)
+{
+    Response.Write(mge.GetMessage());
+    Response.Write(mge.GetDetails());
+}
+catch (Exception exc)
+{
+    Response.Write(exc.Message);
+}
+%>
+
+<!-- Finally emit this function and assocate it with the onLoad event  -->
+<!-- for the page so that it gets executed when this page loads in the -->
+<!-- browser. The function calls the Refresh method on the Viewer      -->
+<!-- frame forcing the Viewer to update itself to match the state of   -->
+<!-- the Server-Side Map object.                                       -->
+
+<script language="javascript">
+function OnPageLoad()
+{
+   parent.Refresh();
+   parent.taskFrame.taskPaneFrame.location.href = "findaddressmain.aspx?SESSION=<%= mgSessionId %>";
+}
+</script>
+
+<body onload="OnPageLoad()">
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddress.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddress.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddress.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,165 @@
+<%--
+Copyright (C) 2004-2006  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" %>
+<%@ Import Namespace="System" %>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+
+<!-- #Include File="../utilityfunctions.aspx" -->
+<!-- #Include File="findaddressfunctions.aspx" -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<html>
+
+<head>
+    <title>Find Address</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+
+    <script language=javascript>
+        function InitDocument()
+        {
+            this.ZoomToResult();
+        }
+    </script>
+</head>
+
+<body onload="InitDocument()">
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Find Address<hr></td></tr>
+    <tr><td class="SubTitle">Search Results</td></tr>
+
+<%
+String mgSessionId = GetRequestParameters()["SESSION"];
+GeocodeAddress addr = null;
+bool success = false;
+
+try
+{
+    // Initialize the web-extensions and connect to the Site using
+    // the session identifier passed in the query string.
+
+    InitializeWebTier();
+
+    MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+    MgSiteConnection siteConnection = new MgSiteConnection();
+    siteConnection.Open(userInfo);
+
+    String address = GetRequestParameters()["address"] + ", Sheboygan, WI";
+
+    // Make the request to geocoder.us passing the address.
+    addr = requestGeocodeAddress(address);
+
+    if (addr != null && addr.lon.Length > 0 && addr.lat.Length > 0)
+    {
+        // The geocode successfully returned a location.
+        
+        Response.Write("<tr><td><img src=\"../images/pushpinblue.jpg\">");
+        Response.Write("<a href=\"gotopoint.aspx?X=" + addr.lon + "&Y=" + addr.lat + "&Scale=2000\" target=\"scriptFrame\">  " + addr.address1 + "</a></td></tr>");
+        Response.Write("<tr><td>" + addr.address2 + "</td></tr>");
+        Response.Write("<tr><td class=\"Spacer\"></td></tr>");
+        Response.Write("<tr><td>Longitude: " + addr.lon + "</td></tr>");
+        Response.Write("<tr><td>Latitude: " + addr.lat + "<hr></td></tr>");
+
+        // Create ResourceService and FeatureService objects and use
+        // the ResourceService object to open the map instance in
+        // session state.
+
+        MgResourceService resourceService = (MgResourceService)siteConnection.CreateService(MgServiceType.ResourceService);
+        MgFeatureService featureService = (MgFeatureService)siteConnection.CreateService(MgServiceType.FeatureService);
+
+        MgMap map = new MgMap();
+        map.Open(resourceService, "Sheboygan");
+
+        // Check the map for the AddressMarker layer. If it does not
+        // exist then create a feature source to store address results
+        // and a layer to display them.
+
+        MgResourceIdentifier addressMarkerDataResId = new MgResourceIdentifier("Session:" + mgSessionId + "//AddressMarker.FeatureSource");
+        MgLayer addressLayer = GetLayerByName(map, "AddressMarker");
+        if (addressLayer == null)
+        {
+            CreateAddressMarkerFeatureSource(featureService, addressMarkerDataResId);
+            addressLayer = CreateAddressMarkerLayer(resourceService, addressMarkerDataResId, mgSessionId);
+
+            map.GetLayers().Insert(0, addressLayer);
+        }
+        else if (addressLayer.GetVisible())
+        {
+            // If the layer exists and is visible, then display the
+            // previous results.
+
+            EmitAddressResults(featureService, addressMarkerDataResId, mgSessionId, Response);
+        }
+
+        // Insert the results of the Geo-Code into the temporary
+        // feature source and ensure the address marker layer
+        // is visible.
+
+        MgAgfReaderWriter geometryReaderWriter = new MgAgfReaderWriter();
+        MgGeometryFactory geometryFactory = new MgGeometryFactory();
+        MgPoint addrPoint = geometryFactory.CreatePoint(geometryFactory.CreateCoordinateXY(Convert.ToDouble(addr.lon), Convert.ToDouble(addr.lat)));
+
+        MgPropertyCollection properties = new MgPropertyCollection();
+        properties.Add(new MgStringProperty("Address", addr.address1));
+        properties.Add(new MgGeometryProperty("Location", geometryReaderWriter.Write(addrPoint)));
+
+        MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
+        commands.Add(new MgInsertFeatures("AddressMarker", properties));
+
+        featureService.UpdateFeatures(addressMarkerDataResId, commands, false);
+
+        addressLayer.SetVisible(true);
+        addressLayer.ForceRefresh();
+
+        map.Save(resourceService);
+
+        success = true;
+    }
+    else
+    {
+        Response.Write("<tr><td>Address not found: " + address + "<hr></td></tr>");
+    }
+}
+catch (MgException e)
+{
+    Response.Write("<tr><td>" + e.GetMessage()+ "</td></tr>");
+    Response.Write("<tr><td class=\"Spacer\"></td></tr>");
+    Response.Write("<tr><td>" + e.GetDetails() + "</td></tr>");
+}
+%>
+
+</table>
+
+Geocoding Provided by: <a href="http://geocoder.us/" target="_blank">geocoder.us</a>.<br>
+Locative Tecnologies offers the free geocoder.us web service for non commercial purposes. If you wish to use this geocoding web service in an production application you must sign up for a commercial license. Click the link above for more information.
+
+</body>
+
+<script language=javascript>
+function ZoomToResult()
+{
+    success = <%= success? "true": "false" %>;
+    if(success)
+        parent.parent.ZoomToView(<%= addr!=null? addr.lon: "0" %>, <%= addr!=null? addr.lat: "0" %>, 2000, true);
+}
+</script>
+
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddressfunctions.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddressfunctions.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddressfunctions.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,217 @@
+<%--
+Copyright (C) 2004-2006  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Import Namespace="System" %>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Net" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Xml" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<script language="c#" runat="server">
+
+/// <summary>
+/// Summary description for FindAddressFunctions.
+/// </summary>
+
+void EmitAddressResults(MgFeatureService featureService, MgResourceIdentifier addressMarkerDataResId, String mgSessionId, HttpResponse response)
+{
+    response.Write("<table class=\"RegText\" border=\"0\" cellspacing=\"0\" width=\"100%\">");
+    response.Write("<tr><td class=\"SubTitle\">Previous Results</td></tr>");
+
+    MgAgfReaderWriter geometryReaderWriter = new MgAgfReaderWriter();
+    MgFeatureReader featureReader = featureService.SelectFeatures(addressMarkerDataResId, "AddressMarker", null);
+
+    while (featureReader.ReadNext())
+    {
+        String address = featureReader.GetString("Address");
+        MgByteReader byteReader = featureReader.GetGeometry("Location");
+
+        MgPoint point = geometryReaderWriter.Read(byteReader) as MgPoint;
+        double x = point.GetCoordinate().GetX();
+        double y = point.GetCoordinate().GetY();
+
+        response.Write("<tr><td>");
+        response.Write("<img src=\"../images/pushpinblue.jpg\">");
+        response.Write("<a href=\"gotopoint.aspx?X="+x+"&Y="+y+"&Scale=2000\" target=\"scriptFrame\">" + address + "</a></td></tr>");
+    }
+    featureReader.Close();
+
+    response.Write("</table>");
+    response.Write("<form action=\"clearaddressresults.aspx\" method=\"get\" target=\"scriptFrame\">");
+    response.Write("<input type=\"hidden\" name=\"SESSION\" value=\"" + mgSessionId + "\">");
+    response.Write("<input type=\"button\" class=\"Ctrl\" value=\"Clear Results\" onClick=\"javascript:submit()\">");
+    response.Write("</form>");
+    response.Write("<hr>");
+}
+
+// Create a temporary Feature Source to store geocode results.
+
+    void CreateAddressMarkerFeatureSource(MgFeatureService featureService, MgResourceIdentifier addressMarkerDataResId)
+{
+    String ll84Wkt = "GEOGCS[\"WGS84 Lat/Long's, Degrees, -180 ==> +180\",DATUM[\"D_WGS_1984]\",SPHEROID[\"World_Geodetic_System_of_1984\",6378137,298.257222932867]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]]";
+
+    MgClassDefinition addressClass = new MgClassDefinition();
+    addressClass.SetName("AddressMarker");
+    MgPropertyDefinitionCollection properties = addressClass.GetProperties();
+
+    MgDataPropertyDefinition idProperty = new MgDataPropertyDefinition("ID");
+    idProperty.SetDataType(MgPropertyType.Int32);
+    idProperty.SetReadOnly(true);
+    idProperty.SetNullable(false);
+    idProperty.SetAutoGeneration(true);
+    properties.Add(idProperty);
+
+    MgDataPropertyDefinition addressProperty = new MgDataPropertyDefinition("Address");
+    addressProperty.SetDataType(MgPropertyType.String);
+    addressProperty.SetLength(512);
+    properties.Add(addressProperty);
+
+    MgGeometricPropertyDefinition locationProperty = new MgGeometricPropertyDefinition("Location");
+    locationProperty.SetGeometryTypes(MgGeometryType.Point);
+    locationProperty.SetHasElevation(false);
+    locationProperty.SetHasMeasure(false);
+    locationProperty.SetReadOnly(false);
+    locationProperty.SetSpatialContextAssociation("LL84");
+    properties.Add(locationProperty);
+
+    MgPropertyDefinitionCollection idProperties = addressClass.GetIdentityProperties();
+    idProperties.Add(idProperty);
+
+    addressClass.SetDefaultGeometryPropertyName("Location");
+
+    MgFeatureSchema addressSchema = new MgFeatureSchema();
+    addressSchema.SetName("AddressMarkerSchema");
+    addressSchema.GetClasses().Add(addressClass);
+
+    MgCreateSdfParams sdfParams = new MgCreateSdfParams("LL84", ll84Wkt, addressSchema);
+
+    featureService.CreateFeatureSource(addressMarkerDataResId, sdfParams);
+}
+
+// Create a temporary Layer to display geocode results.
+
+MgLayer CreateAddressMarkerLayer(MgResourceService resourceService, MgResourceIdentifier addressMarkerDataResId, String sessionId)
+{
+    // Load the AddressMarker layer definition template into
+    // a ASPX XML object, find the "ResourceId" element, and
+    // modify it's content to reference the temporary
+    // feature source.
+
+    XmlDocument doc = new XmlDocument();
+    doc.PreserveWhitespace = true;
+    doc.Load(Request.ServerVariables["APPL_PHYSICAL_PATH"] + "findaddress/templates/addressmarker.xml");
+    XmlNode featureSourceNode = doc.GetElementsByTagName("ResourceId").Item(0);
+    XmlNode resContent = doc.CreateTextNode(addressMarkerDataResId.ToString());
+    featureSourceNode.AppendChild(resContent);
+
+    // Get the updated layer definition from the DOM object
+    // and save it to the session repository using the
+    // ResourceService object.
+    MemoryStream xmlStream = new MemoryStream();
+    doc.Save(xmlStream);
+    byte [] layerDefinition = xmlStream.ToArray();
+    Encoding utf8 = Encoding.UTF8;
+    String layerDefStr = new String(utf8.GetChars(layerDefinition));
+    layerDefinition = new byte[layerDefStr.Length-1];
+    int byteCount = utf8.GetBytes(layerDefStr, 1, layerDefStr.Length-1, layerDefinition, 0);
+    MgByteSource byteSource = new MgByteSource(layerDefinition, layerDefinition.Length);
+    byteSource.SetMimeType(MgMimeType.Xml);
+
+    MgResourceIdentifier tempLayerResId = new MgResourceIdentifier("Session:" + sessionId + "//AddressMarker.LayerDefinition");
+
+    resourceService.SetResource(tempLayerResId, byteSource.GetReader(), null);
+
+    // Create an MgLayer object based on the new layer definition
+    // and return it to the caller.
+
+    MgLayer addressLayer = new MgLayer(tempLayerResId, resourceService);
+    addressLayer.SetName("AddressMarker");
+    addressLayer.SetLegendLabel("AddressMarker");
+    addressLayer.SetDisplayInLegend(false);
+    addressLayer.SetSelectable(false);
+
+    return addressLayer;
+}
+
+GeocodeAddress requestGeocodeAddress(String address)
+{
+    //Request the specified address to the geocode service using REST, the
+    // GET interface
+    //
+    String urlString = "http://geocoder.us/service/rest/geocode?address=" + Server.UrlEncode(address);
+    HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(urlString);
+    getRequest.Method = "GET";
+    WebResponse response = null;
+
+    try
+    {
+        response = getRequest.GetResponse();
+    }
+    catch (Exception exc)
+    {
+        return null;
+    }
+    Stream responseStream = response.GetResponseStream();
+
+
+    //Extract address elements from the XML response
+    //
+    //
+    GeocodeAddress addr = new GeocodeAddress();
+    try
+    {
+        XmlDocument doc = new XmlDocument();
+        doc.Load(responseStream);
+
+        //get the longitude and latitude
+        addr.lon = doc.GetElementsByTagName("geo:long").Item(0).FirstChild.Value;
+        addr.lat = doc.GetElementsByTagName("geo:lat").Item(0).FirstChild.Value;
+
+        //get and decompose address
+        address = doc.GetElementsByTagName("dc:description").Item(0).FirstChild.Value;
+        int sep = address.IndexOf(',');
+        if(sep != -1)
+        {
+            addr.address1 = address.Substring(0, sep);
+            addr.address2 = address.Substring(sep + 1);
+        }
+        else
+            addr.address1 = address;
+    }
+    catch (Exception e)
+    {
+        return null;
+    }
+    return addr;
+}
+
+class GeocodeAddress
+{
+    public GeocodeAddress()
+    {
+        address1 = "";
+        address2 = "";
+        lat = "";
+        lon = "";
+    }
+
+    public String address1;
+    public String address2;
+    public String lat;
+    public String lon;
+}
+</script>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddressmain.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddressmain.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/findaddressmain.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,128 @@
+<%--
+Copyright (C) 2004-2006  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" %>
+<%@ Import Namespace="System" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+<!-- #Include File="../utilityfunctions.aspx" -->
+<!-- #Include File="findaddressfunctions.aspx" -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+
+<html>
+
+<head>
+    <title>Find Address Task</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+    
+    <script language="javascript">
+    function Submit()
+    {
+    	var addressForm = document.getElementById("addressForm");
+    	var addressValue = document.getElementById("addressValue");
+    	var addressInput = document.getElementById("addressInput");
+    	
+    	addressValue.value = addressInput.value;
+    	addressForm.submit();
+    }
+    </script>
+</head>
+
+<body>
+
+<%
+String mgSessionId = GetRequestParameters()["SESSION"];
+bool showPreviousResults = false;
+MgSiteConnection siteConnection = null;
+
+try
+{
+    // Initialize the web-extensions and connect to the Site using
+    // the session identifier stored
+
+    InitializeWebTier();
+
+    MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+    siteConnection = new MgSiteConnection();
+    siteConnection.Open(userInfo);
+
+    // Create a ReserviceService object and use it to open the Map
+    // object from the sessions repository. Use the Map object to
+    // determine if the "AddressMarker" layer is visible.
+
+    MgResourceService resourceService = siteConnection.CreateService(MgServiceType.ResourceService) as MgResourceService;
+    MgMap map = new MgMap();
+    map.Open(resourceService, "Sheboygan");
+    MgLayer addressLayer = GetLayerByName(map, "AddressMarker");
+
+    if (addressLayer != null)
+    {
+        showPreviousResults = addressLayer.GetVisible();
+    }
+}
+catch (MgException mge)
+{
+    Response.Write(mge.GetMessage());
+    Response.Write(mge.GetDetails());
+}
+%>
+
+<form id="addressForm" action="findaddress.aspx" method="get" target="_self">
+    <input name="SESSION" type="hidden" value="<%= mgSessionId %>">
+    <input id="addressValue" name="address" type="hidden" value="">
+</form>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Find Address<hr></td></tr>
+    <tr><td class="SubTitle">Search for an Address</td></tr>
+    <tr><td>Address:</td></tr>
+    <tr>
+        <td class="RegText">
+            <input maxlength="100" class="Ctrl" id="addressInput" style="width: 95%">
+        </td>
+    </tr>
+    <tr><td><strong>Sheboygan, WI</strong></td></tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="button" onClick="Submit()" value="Find" style="width:60px">
+        </td>
+    </tr>
+
+    <tr><td><hr>Hint try:</td></tr>
+    <tr><td>&nbsp;&nbsp;601 North 5th Street</td></tr>
+    <tr><td>&nbsp;&nbsp;720 Riverfront Drive<hr></td></tr>
+</table>
+
+<%
+// If there are previous results, display them as hyperlinks and emit
+// a second form with a Clear Results button.
+
+if (showPreviousResults)
+{
+    MgFeatureService featureService = siteConnection.CreateService(MgServiceType.FeatureService) as MgFeatureService;
+    MgResourceIdentifier addressMarkerDataResId = new MgResourceIdentifier("Session:" + mgSessionId + "//AddressMarker.FeatureSource");
+
+    EmitAddressResults(featureService, addressMarkerDataResId, mgSessionId, Response);
+}
+
+%>
+
+Geocoding Provided by: <a href="http://geocoder.us/" target="_blank">geocoder.us</a>.<br>
+Locative Tecnologies offers the free geocoder.us web service for non commercial purposes. If you wish to use this geocoding web service in an production application you must sign up for a commercial license. Click the link above for more information.
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/gotopoint.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/gotopoint.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/gotopoint.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,47 @@
+<%--
+Copyright (C) 2004-2006  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#"%>
+<!-- #Include File="../utilityfunctions.aspx" -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<html>
+<head>
+    <title>Viewer Sample Application - Goto Point</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <meta http-equiv="content-script-type" content="text/javascript">
+</head>
+
+<!-- Emit this function and assocate it with the onLoad event for the -->
+<!-- page so that it gets executed when this page loads in the        -->
+<!-- browser. The function calls the ZoomToView method on the         -->
+<!-- Viewer frame forcing the Viewer to navigate to the specified     -->
+<!-- point and scale.                                                 -->
+
+<script language="javascript">
+
+function OnPageLoad()
+{
+    parent.ZoomToView(<%= GetRequestParameters()["X"] %>, <%= GetRequestParameters()["Y"] %>, <%= GetRequestParameters()["Scale"] %>, true);
+}
+
+</script>
+
+<body onLoad="OnPageLoad()">
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/templates/addressmarker.xml
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/templates/addressmarker.xml	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/findaddress/templates/addressmarker.xml	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<LayerDefinition version="1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="LayerDefinition-1.0.0.xsd">
+  <VectorLayerDefinition>
+    <ResourceId></ResourceId>
+    <FeatureName>AddressMarker</FeatureName>
+    <FeatureNameType>FeatureClass</FeatureNameType>
+    <Geometry>Location</Geometry>
+    <VectorScaleRange>
+      <MaxScale>10000</MaxScale>
+      <PointTypeStyle>
+        <DisplayAsText>false</DisplayAsText>
+        <AllowOverpost>false</AllowOverpost>
+        <PointRule>
+          <LegendLabel></LegendLabel>
+          <Label>
+            <Unit>Points</Unit>
+            <SizeContext>DeviceUnits</SizeContext>
+            <SizeX>7</SizeX>
+            <SizeY>10</SizeY>
+            <Text>Address</Text>
+            <FontName>Verdana</FontName>
+            <ForegroundColor>FF000000</ForegroundColor>
+            <BackgroundColor>FFFFFFFF</BackgroundColor>
+            <BackgroundStyle>Ghosted</BackgroundStyle>
+            <HorizontalAlignment>&apos;Center&apos;</HorizontalAlignment>
+            <VerticalAlignment>&apos;Baseline&apos;</VerticalAlignment>
+          </Label>
+          <PointSymbolization2D>
+            <W2D>
+              <Unit>Millimeters</Unit>
+              <SizeContext>DeviceUnits</SizeContext>
+              <SizeX>15</SizeX>
+              <SizeY>15</SizeY>
+              <W2DSymbol>
+                <ResourceId>Library://Samples/Sheboygan/Symbols/BasicSymbols.SymbolLibrary</ResourceId>
+                <LibraryItemName>PushPin - Blue</LibraryItemName>
+              </W2DSymbol>
+            </W2D>
+          </PointSymbolization2D>
+        </PointRule>
+      </PointTypeStyle>
+    </VectorScaleRange>
+    <VectorScaleRange>
+      <PointTypeStyle>
+        <DisplayAsText>false</DisplayAsText>
+        <AllowOverpost>false</AllowOverpost>
+        <PointRule>
+          <LegendLabel></LegendLabel>
+          <PointSymbolization2D>
+            <W2D>
+              <Unit>Millimeters</Unit>
+              <SizeContext>DeviceUnits</SizeContext>
+              <SizeX>15</SizeX>
+              <SizeY>15</SizeY>
+              <W2DSymbol>
+                <ResourceId>Library://Samples/Sheboygan/Symbols/BasicSymbols.SymbolLibrary</ResourceId>
+                <LibraryItemName>PushPin - Blue</LibraryItemName>
+              </W2DSymbol>
+            </W2D>
+          </PointSymbolization2D>
+        </PointRule>
+      </PointTypeStyle>
+    </VectorScaleRange>
+  </VectorLayerDefinition>
+</LayerDefinition>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/images/Thumbs.db
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/dotnetviewersample/images/Thumbs.db
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/dotnetviewersample/images/loader_inactive.gif
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/dotnetviewersample/images/loader_inactive.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/dotnetviewersample/images/loader_pulse.gif
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/dotnetviewersample/images/loader_pulse.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/dotnetviewersample/images/pushpin.jpg
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/dotnetviewersample/images/pushpin.jpg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/dotnetviewersample/images/pushpinblue.jpg
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/dotnetviewersample/images/pushpinblue.jpg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/dotnetviewersample/json.js
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/json.js	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/json.js	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,120 @@
+/*
+    json.js
+    2006-04-28
+
+    This file adds these methods to JavaScript:
+
+        object.toJSONString()
+
+            This method produces a JSON text from an object. The
+            object must not contain any cyclical references.
+
+        array.toJSONString()
+
+            This method produces a JSON text from an array. The
+            array must not contain any cyclical references.
+
+        string.parseJSON()
+
+            This method parses a JSON text to produce an object or
+            array. It will return false if there is an error.
+*/
+(function () {
+    var m = {
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        },
+        s = {
+            array: function (x) {
+                var a = ['['], b, f, i, l = x.length, v;
+                for (i = 0; i < l; i += 1) {
+                    v = x[i];
+                    f = s[typeof v];
+                    if (f) {
+                        v = f(v);
+                        if (typeof v == 'string') {
+                            if (b) {
+                                a[a.length] = ',';
+                            }
+                            a[a.length] = v;
+                            b = true;
+                        }
+                    }
+                }
+                a[a.length] = ']';
+                return a.join('');
+            },
+            'boolean': function (x) {
+                return String(x);
+            },
+            'null': function (x) {
+                return "null";
+            },
+            number: function (x) {
+                return isFinite(x) ? String(x) : 'null';
+            },
+            object: function (x) {
+                if (x) {
+                    if (x instanceof Array) {
+                        return s.array(x);
+                    }
+                    var a = ['{'], b, f, i, v;
+                    for (i in x) {
+                        v = x[i];
+                        f = s[typeof v];
+                        if (f) {
+                            v = f(v);
+                            if (typeof v == 'string') {
+                                if (b) {
+                                    a[a.length] = ',';
+                                }
+                                a.push(s.string(i), ':', v);
+                                b = true;
+                            }
+                        }
+                    }
+                    a[a.length] = '}';
+                    return a.join('');
+                }
+                return 'null';
+            },
+            string: function (x) {
+                if (/["\\\x00-\x1f]/.test(x)) {
+                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+                        var c = m[b];
+                        if (c) {
+                            return c;
+                        }
+                        c = b.charCodeAt();
+                        return '\\u00' +
+                            Math.floor(c / 16).toString(16) +
+                            (c % 16).toString(16);
+                    });
+                }
+                return '"' + x + '"';
+            }
+        };
+
+    Object.prototype.toJSONString = function () {
+        return s.object(this);
+    };
+
+    Array.prototype.toJSONString = function () {
+        return s.array(this);
+    };
+})();
+
+String.prototype.parseJSON = function () {
+    try {
+        return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
+                this.replace(/"(\\.|[^"\\])*"/g, ''))) &&
+            eval('(' + this + ')');
+    } catch (e) {
+        return false;
+    }
+};

Added: trunk/MgDev/Doc/samples/dotnetviewersample/overview/overviewmain.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/overview/overviewmain.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/overview/overviewmain.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,57 @@
+<%--
+Copyright (C) 2004-2006  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<html>
+
+<head>
+    <title>Resource - Welcome</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+</head>
+
+<body>
+
+<%
+String platform = Request.ServerVariables["SERVER_SOFTWARE"];
+%>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Overview<hr></td></tr>
+    <tr><td>
+        Welcome to the Sample Application.
+        
+        This sample demonstrates how to construct a
+        Viewer application using the Web Extensions APIs. The application is based on a subset
+        of the Sheboygan data set and shows how to:
+        
+        <ul>
+            <li>Connect to a Site and create a session.</li>
+            <li>Query feature data and work with geometry.</li>
+            <li>Change the view of a map from server-side script.</li>
+            <li>Read and manipulate XML based resources.</li>
+            <li>Store temporary resources within a session.</li>
+            <li>Plot a map as an EPlot DWF.</li>
+        </ul>
+    </td></tr>
+    <tr><td>Server Platform: <font color="#AA0000"><%= platform %></font></td></tr>
+</table>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/plot/plot.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/plot/plot.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/plot/plot.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,81 @@
+<%--
+Copyright (C) 2004-2006  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+<!-- #Include File="../utilityfunctions.aspx" -->
+
+<%
+String mgSessionId = GetRequestParameters()["SESSION"];
+
+try
+{
+    // Initialize the web-tier and connect to the Site using
+    // the session identifier stored in ASPX session state.
+
+    InitializeWebTier ();
+
+    MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+    MgSiteConnection siteConnection = new MgSiteConnection();
+    siteConnection.Open(userInfo);
+
+    // Create an instance of ResourceService and use that to open the
+    // current map instance stored in session state.
+
+    MgResourceService resourceService = siteConnection.CreateService(MgServiceType.ResourceService) as MgResourceService;
+    MgMap map = new MgMap();
+    map.Open(resourceService, "Sheboygan");
+
+    // Now create an instance of MappingService and use it to plot the
+    // current view of the map.
+
+    MgDwfVersion dwfVersion = new MgDwfVersion("6.01", "1.2");
+    MgPlotSpecification plotSpec = new MgPlotSpecification(8.5f, 11, MgPageUnitsType.Inches, 0f, 0f, 0f, 0f);
+    plotSpec.SetMargins(0.5f, 0.5f, 0.5f, 0.5f);
+
+    MgMappingService mappingService = siteConnection.CreateService(MgServiceType.MappingService) as MgMappingService;
+
+    MgLayout layout = null;
+    if ((null != GetRequestParameters()["UseLayout"]) && GetRequestParameters()["UseLayout"] == "true")
+    {
+        MgResourceIdentifier layoutRes = new MgResourceIdentifier("Library://Samples/Sheboygan/Layouts/SheboyganMap.PrintLayout");
+        layout =  new MgLayout(layoutRes, "City of Sheboygan", MgPageUnitsType.Inches);
+    }
+
+    double scale = Convert.ToDouble(GetRequestParameters()["Scale"]);
+    MgByteReader byteReader = null;
+    if (scale <= 0)
+    {
+        byteReader = mappingService.GeneratePlot(map, plotSpec, layout, dwfVersion);
+    }
+    else
+    {
+        MgCoordinate mapCenter = map.GetViewCenter().GetCoordinate();
+        byteReader = mappingService.GeneratePlot(map, mapCenter, scale, plotSpec, layout, dwfVersion);
+    }
+
+    // Now output the resulting DWF.
+
+    OutputReaderContent(Response, byteReader);
+}
+catch (MgException mge)
+{
+    String result = mge.GetMessage() + "<br><br>" + mge.GetDetails();
+
+    Response.ContentType = "text/html";
+    Response.Write(result);
+}
+%>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/plot/plotmain.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/plot/plotmain.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/plot/plotmain.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,166 @@
+<%--
+Copyright (C) 2004-2006  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" %>
+<%@ Import Namespace="System" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+<!-- #Include File="../utilityfunctions.aspx" -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<html>
+
+<head>
+    <title>Plot Task</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+    
+    <script language="javascript">
+    function Submit()
+    {
+        var plotForm = document.getElementById("plotForm");
+        var scaleValue = document.getElementById("scaleValue");
+        var useLayoutValue = document.getElementById("useLayoutValue");
+        var useLayoutSelect = document.getElementById("useLayoutSelect");
+        if(useLayoutSelect.checked)
+            useLayoutValue.value = "true";
+        else
+            useLayoutValue.value = "false";
+
+        scaleValue.value = "0";
+        plotForm.submit();
+    }
+    function SubmitAtScale()
+    {
+        var plotForm = document.getElementById("plotForm");
+        var scaleValue = document.getElementById("scaleValue");
+        var scaleSelect = document.getElementById("scaleSelect");
+        var useLayoutValue = document.getElementById("useLayoutValue");
+        var useLayoutAtScale = document.getElementById("useLayoutAtScale");
+        if(useLayoutAtScale.checked)
+            useLayoutValue.value = "true";
+        else
+            useLayoutValue.value = "false";
+        
+        scaleValue.value = scaleSelect.value;
+        plotForm.submit();
+    }
+    </script>
+</head>
+
+<body>
+<%
+// Display a couple of forms prompting the user to either
+// plot the current view of the map, or the current view of
+// the map at a specified scale. Submitting one of these forms
+// opens a new window containing an EPlot DWF. The EPlot DWF
+// is generated by the plot.aspx script.
+
+String mgSessionId = GetRequestParameters()["SESSION"];
+int currentScale = 0;
+NumberFormatInfo nf = new NumberFormatInfo();
+nf.NumberDecimalDigits = 3;
+MgPoint viewCenter = null;
+double viewScale = 0;
+
+try
+{
+    // Initialize the web- extensions and connect to the Site using
+    // the session identifier stored in PHP session state.
+
+    InitializeWebTier();
+
+    MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+    MgSiteConnection siteConnection = new MgSiteConnection();
+    siteConnection.Open(userInfo);
+
+    // Create a ReserviceService object and use it to open the Map
+    // object from the sessions repository. Use the Map object to
+    // determine the current scale of the map for display on this
+    // page.
+
+    MgResourceService resourceService = siteConnection.CreateService(MgServiceType.ResourceService) as MgResourceService;
+    MgMap map = new MgMap();
+    map.Open(resourceService, "Sheboygan");
+
+    viewCenter = map.GetViewCenter();
+    viewScale = map.GetViewScale();
+}
+catch (MgException mge)
+{
+    Response.Write(mge.GetMessage());
+    Response.Write(mge.GetDetails());
+}
+%>
+
+<form id="plotForm" action="plot.aspx" method="get" target="_blank">
+    <input name="SESSION" type="hidden" value="<%= mgSessionId %>">
+    <input name="Scale" id="scaleValue" type="hidden" value="0">
+    <input name="UseLayout" id="useLayoutValue" type="hidden" value="false">
+</form>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Plot as DWF<hr></td></tr>
+    <tr><td class="SubTitle">Plot a View of the Map</td></tr>
+    <tr><td>View Center X:  <%= viewCenter.GetCoordinate().GetX().ToString(nf) %></td></tr>
+    <tr><td>View Center Y:  <%= viewCenter.GetCoordinate().GetY().ToString(nf) %></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td>View Scale:     1:<%= ((int)viewScale).ToString(nf) %><hr></td></tr>
+    
+    <tr><td class="SubTitle">Plot the Current Map View</td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="button" onClick="Submit()" value="Plot" style="width:60px">
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="checkbox" id="useLayoutSelect">&nbsp;Use Print Layout<hr>
+        </td>
+    </tr>
+    
+    <tr><td class="SubTitle">Plot at a Specified Scale</td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr>
+        <td>
+            Scale:
+            <select size="1" class="Ctrl" id="scaleSelect" style="width:80px">
+                <option value="1000">1:1,000</option>
+                <option value="8000">1:8,000</option>
+                <option value="20000">1:20,000</option>
+                <option value="25000">1:25,000</option>
+            </select>
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="button" onClick="SubmitAtScale()" value="Plot" style="width:60px">
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="checkbox" id="useLayoutAtScale">&nbsp;Use Print Layout
+        </td>
+    </tr>
+</table>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/command.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/command.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/command.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,32 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<script language="c#" runat="server">
+    public class Command
+    {
+        public const int GETLAYERPROPERTIES 	= 1;
+        public const int TOGGLESPATIALFILTER = 2;
+        public const int SHOWSPATIALFILTER 	= 3;
+        public const int EXECUTEQUERY 		= 4;
+        public const int GETSELECTIONXML 	= 5;
+    }
+</script>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/feature.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/feature.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/feature.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,45 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<script language="c#" runat="server">
+    public class Feature : JsonObject
+    {
+        public String displayValue = null;
+        public double centerX = 0.0;
+        public double centerY = 0.0;
+        public Hashtable idList = null;
+        
+        public Feature(String displayValue, MgPoint centerPoint, Hashtable idList)
+    	{
+    	    this.displayValue = displayValue;
+    	    this.centerX = centerPoint.GetCoordinate().GetX();
+    	    this.centerY = centerPoint.GetCoordinate().GetY();
+    	    this.idList = new Hashtable(idList);
+    	    
+    	    //JSON Settings
+    	    Put("displayValue", this.displayValue);
+    	    Put("centerX", this.centerX);
+    	    Put("centerY", this.centerY);
+    	    Put("idList", this.idList);    	    
+    	}
+    }
+</script>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/property.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/property.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/property.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,39 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<script language="c#" runat="server">
+    public class Property : JsonObject
+    {
+        public String name = null;
+        public bool isString = false;
+        
+        public Property(String name, bool isString)
+    	{
+    	    this.name = name;
+    	    this.isString = isString;
+    	    
+    	    //JSON Settings
+    	    Put("name", this.name);
+    	    Put("isString", this.isString);
+    	}
+    }
+</script>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/query.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/query.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/query/classes/query.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,488 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+<%@ Import Namespace="Jayrock.Json" %>
+<%@ Import Namespace="Jayrock.Json.Conversion" %>
+
+<!-- #Include File="property.aspx -->
+<!-- #Include File="feature.aspx -->
+<!-- #Include File="../../utilityfunctions.aspx -->
+
+<script language="c#" runat="server">
+    public class Query
+    {
+        NameValueCollection args = null;
+        private MgSiteConnection site = null;
+        private String[] numOperators = null;
+        private String[] numExpressions = null;
+        private String[] strOperators = null;
+        private String[] strExpressions = null;
+        
+        public Query(NameValueCollection incomingArgs)
+        {
+            this.args = incomingArgs;
+            this.site = new MgSiteConnection();
+            this.site.Open(new MgUserInformation(GetParameter(this.args, "SESSION")));
+            this.numOperators = new String[] {"Equal to", "Not equal to", "Greater than", "Greater than or equal to", "Less than", "Less than or equal to"};
+            this.numExpressions = new String[] {" = %s", " != %s", " > %s", " >= %s", " < %s", " <= %s"};
+            this.strOperators = new String[] {"Begins with", "Contains", "Equal to"};
+            this.strExpressions = new String[] {" like '%s%%'", " like '%%%s%%'", " = '%s'"};
+        }
+        
+        public String getNumOp()
+        {
+            String jsonNumOps = JsonConvert.ExportToString(this.numOperators);
+            return jsonNumOps;
+        }
+
+        public String getStrOp()
+        {
+            String jsonStrOps = JsonConvert.ExportToString(this.strOperators);
+            return jsonStrOps;
+        }
+        
+        public ArrayList GetMapLayerNames()
+        {
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+            MgLayerCollection layers = map.GetLayers();
+            ArrayList layerNames = new ArrayList();
+
+            for(int i=0; i<layers.GetCount(); i++)
+            {
+                MgLayer layer = (MgLayer) layers.GetItem(i);
+
+                //TODO: Exclude Raster and Drawing Layers???
+                
+                if(!layer.GetName().StartsWith("_") && !layer.GetFeatureSourceId().ToUpper().StartsWith("SESSION"))
+                {
+                    layerNames.Add(layer.GetLegendLabel());
+                }
+            }
+            layerNames.Sort();
+
+            return layerNames;
+        }
+        
+        public ArrayList GetLayerProperties()
+        {
+            ArrayList properties = new ArrayList();
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+            MgLayer layer = (MgLayer) map.GetLayers().GetItem(GetParameter(this.args, "LAYERNAME"));
+
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            String[] schemaClass = layer.GetFeatureClassName().Split(new Char[]{':'});
+
+            MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+
+            for(int i=0; i<classDef.GetProperties().GetCount(); i++)
+            {
+                MgPropertyDefinition propertyDef = classDef.GetProperties().GetItem(i);
+
+                if(propertyDef.GetPropertyType() == MgFeaturePropertyType.DataProperty)
+                {
+                    MgDataPropertyDefinition propertyDataDef = (MgDataPropertyDefinition) propertyDef;
+                    int dataType = propertyDataDef.GetDataType();
+                    if(this.IsValidDataType(dataType))
+                    {
+                        properties.Add(new Property(propertyDataDef.GetName(), dataType == MgPropertyType.String));
+                    }
+                }
+            }
+            return properties;
+        }
+        
+        public bool ToggleSpatialFilter()
+        {
+            bool result = true;
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+
+            MgLayerCollection layers = map.GetLayers();
+            if(layers.Contains("_QuerySpatialFilter"))
+            {
+                MgLayer layer = (MgLayer) layers.GetItem("_QuerySpatialFilter");
+                if(GetParameter(this.args, "VISIBLE").Equals("true"))
+                    layer.SetVisible(true);
+                else
+                    layer.SetVisible(false);
+
+                map.Save(resourceService);
+            }
+
+            return result;
+        }
+
+        public bool ShowSpatialFilter()
+        {
+            bool result = true;
+            MgResourceIdentifier sdfResId = new MgResourceIdentifier("Session:"+ GetParameter(this.args, "SESSION")+"//Filter.FeatureSource");
+
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+
+            MgFeatureCommandCollection updateCommands = new MgFeatureCommandCollection();
+
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+
+            MgLayer layer = null;
+            MgLayerCollection layers = map.GetLayers();
+            if(layers.Contains("_QuerySpatialFilter"))
+            {
+                layer = (MgLayer) layers.GetItem("_QuerySpatialFilter");
+                updateCommands.Add(new MgDeleteFeatures("Filter", "ID like '%'"));
+            }
+            else
+            {
+                // Create the Feature Source (SDF)
+
+                MgFeatureSchema sdfSchema = this.CreateFilterSchema();
+                MgCreateSdfParams sdfParams = new MgCreateSdfParams("MAPCS", map.GetMapSRS(), sdfSchema);
+                featureService.CreateFeatureSource(sdfResId, sdfParams);
+
+                // Create the Layer
+
+                MgResourceIdentifier layerResId = new MgResourceIdentifier("Session:" + GetParameter(this.args, "SESSION") + "//Filter.LayerDefinition");
+                String layerDefinition = File.ReadAllText(GetQueryXmlTemplatePath());
+                layerDefinition = layerDefinition.Replace("%s", sdfResId.ToString());
+
+                MgByteReader reader = new MgByteReader(layerDefinition, "text/xml");
+                resourceService.SetResource(layerResId, reader, null);
+
+                layer = new MgLayer(layerResId, resourceService);
+
+                layer.SetName("_QuerySpatialFilter");
+                layer.SetLegendLabel("_QuerySpatialFilter");
+                layer.SetDisplayInLegend(false);
+                layer.SetSelectable(false);
+
+                layers.Insert(0, layer);
+            }
+
+            // Make the layer visible
+
+            layer.SetVisible(true);
+            map.Save(resourceService);
+
+            // Add the geometry to the filter feature source
+
+            MgPolygon polygon = this.CreatePolygonFromGeomText(GetParameter(this.args, "GEOMTEXT"));
+            MgAgfReaderWriter agfWriter = new MgAgfReaderWriter();
+            MgByteReader byteReader = agfWriter.Write(polygon);
+
+            MgPropertyCollection propertyValues = new MgPropertyCollection();
+            propertyValues.Add(new MgGeometryProperty("Geometry", byteReader));
+
+            updateCommands.Add(new MgInsertFeatures("Filter", propertyValues));
+
+            featureService.UpdateFeatures(sdfResId, updateCommands, false);
+
+            return result;
+        }
+        
+        public ArrayList Execute()
+        {
+            ArrayList result = new ArrayList();
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+            MgLayer layer = (MgLayer) map.GetLayers().GetItem(GetParameter(this.args, "LAYERNAME"));
+
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            String featureClass = layer.GetFeatureClassName();
+            String featureGeometry = layer.GetFeatureGeometryName();
+
+            // Initialize the coordinate system transform
+
+            String[] schemaClass = layer.GetFeatureClassName().Split(new Char[]{':'});
+            MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+            MgGeometricPropertyDefinition geomProp = (MgGeometricPropertyDefinition) classDef.GetProperties().GetItem(featureGeometry);
+            String spatialContext = geomProp.GetSpatialContextAssociation();
+
+            MgCoordinateSystemTransform csTransform = null;
+            MgCoordinateSystemTransform csInverseTransform = null;
+            MgCoordinateSystemFactory coordSysFactory = new MgCoordinateSystemFactory();
+
+            MgSpatialContextReader scReader = featureService.GetSpatialContexts(resId, false);
+            while(scReader.ReadNext() && csTransform==null)
+            {
+                if(spatialContext.Equals(scReader.GetName()))
+                {
+                    MgCoordinateSystem source = coordSysFactory.Create(scReader.GetCoordinateSystemWkt());
+                    MgCoordinateSystem target = coordSysFactory.Create(map.GetMapSRS());
+                    csTransform = coordSysFactory.GetTransform(source, target);
+                    csInverseTransform = coordSysFactory.GetTransform(target, source);
+                }
+            }
+            scReader.Close();
+
+            // Execute the query
+
+            int queryMax = Int32.Parse(GetParameter(this.args, "QUERYMAX"));
+            MgFeatureQueryOptions queryOptions = new MgFeatureQueryOptions();
+
+            if(GetParameter(this.args, "USEPROPERTYFILTER").Equals("true"))
+            {
+                String propertyFilter = GetParameter(this.args, "PROPERTYNAME");
+                int op = Int32.Parse(GetParameter(this.args, "OPERATOR"));
+                if(GetParameter(this.args, "ISSTRING").Equals("true"))
+                {
+                    propertyFilter = propertyFilter + this.strExpressions[op].Replace("%s", GetParameter(this.args, "VALUE"));
+                }
+                else
+                {
+                    propertyFilter = propertyFilter + this.numExpressions[op].Replace("%s", GetParameter(this.args, "VALUE"));
+                }
+                queryOptions.SetFilter(propertyFilter);
+            }
+
+            if(GetParameter(this.args, "USESPATIALFILTER").Equals("true"))
+            {
+                MgPolygon polygon = this.CreatePolygonFromGeomText(GetParameter(this.args, "GEOMTEXT"));
+                MgGeometry geometry = (MgGeometry) polygon.Transform(csInverseTransform);
+                queryOptions.SetSpatialFilter(featureGeometry, geometry, MgFeatureSpatialOperations.Intersects);
+            }
+
+            int count = 0;
+            MgAgfReaderWriter geometryReaderWriter = new MgAgfReaderWriter();
+            MgFeatureReader featureReader = featureService.SelectFeatures(resId, layer.GetFeatureClassName(), queryOptions);
+            while(featureReader.ReadNext() && (queryMax <= 0 || count < queryMax))
+            {
+                MgByteReader byteReader = featureReader.GetGeometry(featureGeometry);
+                MgGeometry geometry = geometryReaderWriter.Read(byteReader);
+                MgPoint centerPoint = geometry.GetCentroid();
+                centerPoint = (MgPoint) centerPoint.Transform(csTransform);
+                Hashtable idList = new Hashtable(this.GetFeatureIdList(featureReader));
+                String displayValue = GetFeaturePropertyValue(featureReader, GetParameter(this.args, "OUTPUTPROPERTY")); 
+                result.Add(new Feature(displayValue, centerPoint, idList));
+                count++;
+            }
+
+            return result;
+        }
+        
+        public String GetSelectionXML()
+        {
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+            MgLayer layer = (MgLayer) map.GetLayers().GetItem(GetParameter(this.args, "LAYERNAME"));
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            String featureClass = layer.GetFeatureClassName();
+
+            String[] schemaClass = layer.GetFeatureClassName().Split(new Char[]{':'});
+            MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+
+            MgPropertyCollection properties = new MgPropertyCollection();
+            MgDataPropertyDefinition dataPropDef = null;
+            String jsonIdList = GetParameter(this.args, "IDLIST");
+            JsonObject idList = JsonConvert.Import(jsonIdList) as JsonObject;
+            if(idList != null)
+            {
+                foreach(String key in idList.Names)
+                {
+                    String value = idList[key].ToString();
+                    dataPropDef = (MgDataPropertyDefinition) classDef.GetProperties().GetItem(key);
+                    switch(dataPropDef.GetDataType())
+                    {
+                        case MgPropertyType.Boolean :
+                            properties.Add(new MgBooleanProperty(key, Boolean.Parse(value)));
+                            break;
+                        case MgPropertyType.Byte :
+                            properties.Add(new MgByteProperty(key, Byte.Parse(value)));
+                            break;
+                        case MgPropertyType.Single :
+                            properties.Add(new MgSingleProperty(key, (float)Double.Parse(value)));
+                            break;
+                        case MgPropertyType.Double :
+                            properties.Add(new MgDoubleProperty(key, Double.Parse(value)));
+                            break;
+                        case MgPropertyType.Int16 :
+                            properties.Add(new MgInt16Property(key, Int16.Parse(value)));
+                            break;
+                        case MgPropertyType.Int32 :
+                            properties.Add(new MgInt32Property(key, Int32.Parse(value)));
+                            break;
+                        case MgPropertyType.Int64 :
+                            properties.Add(new MgInt64Property(key, Int64.Parse(value)));
+                            break;
+                        case MgPropertyType.String :
+                            properties.Add(new MgStringProperty(key, value));
+                            break;
+                        case MgPropertyType.DateTime :
+                        case MgPropertyType.Null :
+                        case MgPropertyType.Blob :
+                        case MgPropertyType.Clob :
+                        case MgPropertyType.Feature :
+                        case MgPropertyType.Geometry :
+                        case MgPropertyType.Raster :
+                            break;
+                    }
+                }
+            }
+
+            MgSelection selection = new MgSelection(map);
+            selection.AddFeatureIds(layer, featureClass, properties);
+
+            return selection.ToXml();
+        }
+                
+        private Hashtable GetFeatureIdList(MgFeatureReader featureReader)
+        {
+            MgClassDefinition classDef = featureReader.GetClassDefinition();
+            MgPropertyDefinitionCollection idProps = classDef.GetIdentityProperties();
+            Hashtable idList = new Hashtable();
+
+            for(int i=0; i<idProps.GetCount(); i++)
+            {
+                MgDataPropertyDefinition idProp = (MgDataPropertyDefinition) idProps.GetItem(i);
+                String propName = idProp.GetName();
+                switch(idProp.GetDataType())
+                {
+                    case MgPropertyType.Boolean :
+                        idList[propName] = featureReader.GetBoolean(propName);
+                        break;
+                    case MgPropertyType.Byte :
+                        idList[propName] = featureReader.GetByte(propName);
+                        break;
+                    case MgPropertyType.Single :
+                        idList[propName] = featureReader.GetSingle(propName);
+                        break;
+                    case MgPropertyType.Double :
+                        idList[propName] = featureReader.GetDouble(propName);
+                        break;
+                    case MgPropertyType.Int16 :
+                        idList[propName] = featureReader.GetInt16(propName);
+                        break;
+                    case MgPropertyType.Int32 :
+                        idList[propName] = featureReader.GetInt32(propName);
+                        break;
+                    case MgPropertyType.Int64 :
+                        idList[propName] = featureReader.GetInt64(propName);
+                        break;
+                    case MgPropertyType.String :
+                        idList[propName] = featureReader.GetString(propName);
+                        break;
+                    case MgPropertyType.DateTime :
+                        idList[propName] = featureReader.GetDateTime(propName);
+                        break;
+                    case MgPropertyType.Null :
+                    case MgPropertyType.Blob :
+                    case MgPropertyType.Clob :
+                    case MgPropertyType.Feature :
+                    case MgPropertyType.Geometry :
+                    case MgPropertyType.Raster :
+                    break;
+                }
+            }
+
+            return idList;
+        }
+        
+        private bool IsValidDataType(int type)
+        {
+            bool valid = true;
+
+            switch(type)
+            {
+                case MgPropertyType.Blob:
+                case MgPropertyType.Clob:
+                case MgPropertyType.Byte:
+                case MgPropertyType.Feature:
+                case MgPropertyType.Geometry:
+                case MgPropertyType.Null:
+                    valid = false;
+                    break;
+            }
+
+            return valid;
+        }
+        
+        private MgFeatureSchema CreateFilterSchema()
+        {
+            MgFeatureSchema filterSchema = new MgFeatureSchema();
+            filterSchema.SetName("FilterSchema");
+
+            MgClassDefinition filterClass = new MgClassDefinition();
+            filterClass.SetName("Filter");
+            MgPropertyDefinitionCollection properties = filterClass.GetProperties();
+
+            MgDataPropertyDefinition idProperty = new MgDataPropertyDefinition("ID");
+            idProperty.SetDataType(MgPropertyType.Int32);
+            idProperty.SetReadOnly(true);
+            idProperty.SetNullable(false);
+            idProperty.SetAutoGeneration(true);
+            properties.Add(idProperty);
+
+            MgGeometricPropertyDefinition geometryProperty = new MgGeometricPropertyDefinition("Geometry");
+            geometryProperty.SetGeometryTypes(MgFeatureGeometricType.Surface);
+            geometryProperty.SetHasElevation(false);
+            geometryProperty.SetHasMeasure(false);
+            geometryProperty.SetReadOnly(false);
+            geometryProperty.SetSpatialContextAssociation("MAPCS");
+            properties.Add(geometryProperty);
+
+            filterClass.GetIdentityProperties().Add(idProperty);
+            filterClass.SetDefaultGeometryPropertyName("Geometry");
+
+            filterSchema.GetClasses().Add(filterClass);
+
+            return filterSchema;
+        }
+        
+        private MgPolygon CreatePolygonFromGeomText(String geomText)
+        {
+            MgGeometryFactory geometryFactory = new MgGeometryFactory();
+
+            String[] vertices = geomText.Split(new Char[]{','});
+            int count = Int32.Parse(vertices[0]);
+
+            MgCoordinateCollection coords = new MgCoordinateCollection();
+            for(int i=0; i<count; i++)
+            {
+                MgCoordinate coord = geometryFactory.CreateCoordinateXY(Double.Parse(vertices[(i*2)+1]), Double.Parse(vertices[(i*2)+2]));
+                coords.Add(coord);
+            }
+
+            MgLinearRing linearRing = geometryFactory.CreateLinearRing(coords);
+            MgPolygon polygon = geometryFactory.CreatePolygon(linearRing, null);
+
+            return polygon;
+        }
+        
+        private String GetQueryXmlTemplatePath()
+        {
+            String xmlTemplatePath = GetBasePath() + "query\\templates\\filterlayerdefinition.xml";
+            return xmlTemplatePath;
+        }
+    }
+
+</script>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/query/querycontroller.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/query/querycontroller.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/query/querycontroller.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,69 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" debug="true"%>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+<%@ Import Namespace="Jayrock.Json" %>
+<%@ Import Namespace="Jayrock.Json.Conversion" %>
+
+<!-- #Include File="classes/query.aspx -->
+<!-- #Include File="classes/command.aspx -->
+
+<%
+    InitializeWebTier();
+
+    NameValueCollection args = GetRequestParameters();
+    Query query = new Query(args);
+    String responseType = "";
+    String responseString = "";
+
+    if(GetParameter(args, "COMMAND") != null)
+    {
+        int cmd = Int32.Parse(GetParameter(args, "COMMAND"));
+        switch (cmd)
+        {
+            case Command.GETLAYERPROPERTIES:
+                responseType = "text/plain";
+                ArrayList properties = query.GetLayerProperties();
+                responseString = JsonConvert.ExportToString(properties.ToArray());
+                break;
+            case Command.TOGGLESPATIALFILTER:
+                responseType = "text/plain";
+                responseString = JsonConvert.ExportToString(query.ToggleSpatialFilter());
+                break;
+            case Command.SHOWSPATIALFILTER:
+                responseType = "text/plain";
+                responseString = JsonConvert.ExportToString(query.ShowSpatialFilter());
+                break;
+            case Command.EXECUTEQUERY:
+                responseType = "text/plain";
+                ArrayList resultList = query.Execute();
+                responseString = JsonConvert.ExportToString(resultList.ToArray());
+                break;
+            case Command.GETSELECTIONXML:
+                responseType = "text/xml";
+                responseString = query.GetSelectionXML();
+                break;
+        }
+    }
+    Response.ContentType = responseType;
+    Response.Write(responseString);
+%>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/dotnetviewersample/query/querymain.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/query/querymain.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/query/querymain.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,467 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" Debug="true" %>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+
+<!-- #Include File="classes/query.aspx -->
+<!-- #Include File="classes/command.aspx -->
+
+<script runat="server">
+String errorMsg = null;
+String errorDetail = null;
+NameValueCollection args = null;
+Query query = null;
+ArrayList layerNames = null;
+</script>
+
+<%
+    try
+    {
+        InitializeWebTier();
+        args = GetRequestParameters();
+        query = new Query(args);
+        layerNames = query.GetMapLayerNames();
+    }
+    catch (MgException e)
+    {
+        errorMsg = e.GetMessage();
+        errorDetail = e.GetDetails();
+    }
+%>
+
+<html>
+<head>
+    <title>Query Features</title>
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+    <script language="javascript" src="../../viewerfiles/browserdetect.js"></script>
+    <script language="javascript" src="../json.js"></script>
+    <script language="javascript">
+
+        var READY_STATE_UNINITIALIZED   = 0;
+        var READY_STATE_LOADING     = 1;
+        var READY_STATE_LOADED      = 2;
+        var READY_STATE_INTERACTIVE     = 3;
+        var READY_STATE_COMPLETE    = 4;
+
+        var NOT_BUSY_IMAGE = "../images/loader_inactive.gif";
+        var BUSY_IMAGE = "../images/loader_pulse.gif";
+
+        var session = "<%= GetParameter(args, "SESSION") %>";
+        var mapName = "<%= GetParameter(args, "MAPNAME") %>";
+
+        var strOps = '<%= query.getStrOp() %>'.parseJSON();
+        var numOps = '<%= query.getNumOp() %>'.parseJSON();
+        var queryReqHandler = null;
+        var spatialFilterGeomText = null;
+        var properties = null;
+        var results;
+
+        function OnLayerChange()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var propertySelect = document.getElementById("propertySelect");
+            var outputSelect = document.getElementById("outputSelect");
+
+            reqParams = "COMMAND=<%=Command.GETLAYERPROPERTIES%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "querycontroller.aspx", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            reqHandler.send(reqParams);
+            properties = reqHandler.responseText.parseJSON();
+
+            propertySelect.options.length = 0;
+            outputSelect.options.length = 0;
+            for (var i = 0; i < properties.length; i++)
+            {
+                propertySelect.options[i] = new Option(properties[i].name, i, false, false);
+                outputSelect.options[i] = new Option(properties[i].name, i, false, false);
+            }
+            OnPropertyChange();
+        }
+
+        function OnPropertyChange()
+        {
+            var propertySelect = document.getElementById("propertySelect");
+            var operatorSelect = document.getElementById("operatorSelect");
+
+            operatorSelect.options.length = 0;
+            if (propertySelect.selectedIndex >= 0)
+            {
+                var ops = null;
+                if (properties[propertySelect.value].isString)
+                    ops = strOps;
+                else
+                    ops = numOps;
+
+                for (var i = 0; i < ops.length; i++)
+                {
+                    operatorSelect.options[i] = new Option(ops[i], i, false, false);
+                }
+            }
+
+        }
+
+        function OnToggleSpatialFilter()
+        {
+            if (spatialFilterGeomText != null)
+            {
+                ToggleSpatialFilter(document.getElementById("spatialFilter").checked);
+            }
+        }
+
+        function OnDigitizeRectangle()
+        {
+            parent.parent.mapFrame.DigitizeRectangle(OnRectangleDigitized);
+        }
+
+        function OnRectangleDigitized(rectangle)
+        {
+            var geomText = "5,"
+            + rectangle.Point1.X + "," + rectangle.Point1.Y + ","
+            + rectangle.Point2.X + "," + rectangle.Point1.Y + ","
+            + rectangle.Point2.X + "," + rectangle.Point2.Y + ","
+            + rectangle.Point1.X + "," + rectangle.Point2.Y + ","
+            + rectangle.Point1.X + "," + rectangle.Point1.Y;
+
+            ShowSpatialFilter(geomText);
+        }
+
+        function OnDigitizePolygon()
+        {
+            parent.parent.mapFrame.DigitizePolygon(OnPolyonDigitized);
+        }
+
+        function OnPolyonDigitized(polygon)
+        {
+            var geomText = polygon.Count;
+            for (var i = 0; i < polygon.Count; i++)
+            {
+                geomText += "," + polygon.Point(i).X + "," + polygon.Point(i).Y;
+            }
+
+            ShowSpatialFilter(geomText);
+        }
+
+        function OnClearSpatialFilter()
+        {
+            document.getElementById("spatialFilter").checked = false;
+            OnToggleSpatialFilter();
+
+            spatialFilterGeomText = null;
+        }
+
+        function ShowSpatialFilter(geomText)
+        {
+            reqParams = "COMMAND=<%=Command.SHOWSPATIALFILTER%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&GEOMTEXT=" + encodeURIComponent(geomText);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            if (msie)
+                reqHandler.open("POST", "querycontroller.aspx", false);
+            else
+                reqHandler.open("POST", "../dotnetviewersample/query/querycontroller.aspx", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+            reqHandler.send(reqParams);
+
+            spatialFilterGeomText = geomText;
+            document.getElementById("spatialFilter").checked = true;
+            parent.parent.Refresh();
+        }
+
+        function ToggleSpatialFilter(visible)
+        {
+            reqParams = "COMMAND=<%=Command.TOGGLESPATIALFILTER%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&VISIBLE=" + encodeURIComponent(visible);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "querycontroller.aspx", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+            reqHandler.send(reqParams);
+
+            parent.parent.Refresh();
+        }
+
+        function ExecuteQuery()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            
+            reqParams = "COMMAND=<%=Command.EXECUTEQUERY%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+
+            if (document.getElementById("propertyFilter").checked)
+            {
+                reqParams += "&USEPROPERTYFILTER=true";
+                property = properties[document.getElementById("propertySelect").value];
+                reqParams += "&PROPERTYNAME=" + encodeURIComponent(property.name);
+                reqParams += "&ISSTRING=" + encodeURIComponent(property.isString);
+                reqParams += "&OPERATOR=" + encodeURIComponent(document.getElementById("operatorSelect").value);
+                reqParams += "&VALUE=" + encodeURIComponent(document.getElementById("valueInput").value);
+            }
+            else
+            {
+                reqParams += "&USEPROPERTYFILTER=false";
+            }
+
+            if (document.getElementById("spatialFilter").checked && spatialFilterGeomText != null)
+            {
+                reqParams += "&USESPATIALFILTER=true";
+                reqParams += "&GEOMTEXT=" + encodeURIComponent(spatialFilterGeomText);
+            }
+            else
+            {
+                reqParams += "&USESPATIALFILTER=false";
+            }
+
+            reqParams += "&OUTPUTPROPERTY=" + encodeURIComponent(properties[document.getElementById("outputSelect").value].name);
+            reqParams += "&QUERYMAX=" + encodeURIComponent(document.getElementById("queryMax").value);
+
+            if (msie)
+                queryReqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                queryReqHandler = new XMLHttpRequest();
+
+            queryReqHandler.onreadystatechange = OnReadyStateChange;
+            queryReqHandler.open("POST", "querycontroller.aspx", true);
+            queryReqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            document.getElementById("executeBtn").disabled = true;
+            document.getElementById("busyImg").src = BUSY_IMAGE;
+
+            queryReqHandler.send(reqParams);
+        }
+
+        function SelectFeature()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var resultSelect = document.getElementById("resultSelect");
+
+            reqParams = "COMMAND=<%=Command.GETSELECTIONXML%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+            reqParams += "&IDLIST=" + results[resultSelect.value].idList.toJSONString();
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "querycontroller.aspx", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+            reqHandler.send(reqParams);
+            selectionXml = reqHandler.responseText;
+            parent.parent.mapFrame.SetSelectionXML(selectionXml);
+        }
+
+        function ZoomToFeature()
+        {
+            var resultSelect = document.getElementById("resultSelect");
+            var scaleInput = document.getElementById("scaleInput");
+            scale = scaleInput.value;
+            scale = ((scale == 0)? 10000 : scale);
+            scale = parseFloat(scale + String(".0"));
+
+            feature = results[resultSelect.value];
+            parent.parent.mapFrame.ZoomToView(feature.centerX, feature.centerY, scale, true);
+        }
+
+        function OnReadyStateChange()
+        {
+            var ready = queryReqHandler.readyState;
+
+            if (ready == READY_STATE_COMPLETE)
+            {
+                results = queryReqHandler.responseText.parseJSON();
+                var resultSelect = document.getElementById("resultSelect");
+                resultSelect.options.length = 0;
+                for (var i = 0; i < results.length; i++)
+                {
+                    resultSelect.options[i] = new Option(results[i].displayValue, i, false, false);
+                }
+                OnResultChange();
+
+                document.getElementById("executeBtn").disabled = false;
+                document.getElementById("busyImg").src = NOT_BUSY_IMAGE;
+                queryReqHandler = null;
+            }
+        }
+
+        function OnResultChange()
+        {
+            var resultSelect = document.getElementById("resultSelect");
+            var scaleInput = document.getElementById("scaleInput");
+            var zoomBtn = document.getElementById("zoomBtn");
+            var selectBtn = document.getElementById("selectBtn");
+
+            if (resultSelect.selectedIndex >= 0)
+            {
+                scaleInput.disabled = false;
+                zoomBtn.disabled = false;
+                selectBtn.disabled = false;
+            }
+            else
+            {
+                scaleInput.disabled = true;
+                zoomBtn.disabled = true;
+                selectBtn.disabled = true;
+            }
+        }
+
+        function OnLoad()
+        {
+            OnLayerChange();
+            OnResultChange();
+        }
+
+        function OnUnload()
+        {
+            ToggleSpatialFilter(false);
+        }
+
+    </script>
+
+</head>
+
+<body onLoad="OnLoad();" onUnload="OnUnload();" marginwidth=5 marginheight=5 leftmargin=5 topmargin=5 bottommargin=5 rightmargin=5>
+
+<% if(errorMsg==null) {%>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title"><img id="busyImg" src="../images/loader_inactive.gif" style="vertical-align:bottom">&nbsp;Query Features<hr></td></tr>
+    <tr><td class="SubTitle">Select a Layer</td></tr>
+    <tr><td>Layer:</td></tr>
+    <tr>
+        <td class="RegText">
+        <select size="1" class="Ctrl" id="layerSelect" onChange="OnLayerChange()" style="width: 100%">
+            <%
+            String selected = "selected";
+            foreach(String layerName in layerNames) {
+            %>
+            <option value="<%=layerName %>" <%=selected %> ><%=layerName %></option>
+            <%
+                selected = "";
+            }
+            %>
+        </select>
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td class="SubTitle"><input class="Ctrl" type="checkbox" id="propertyFilter" checked>&nbsp;Property Filter</td></tr>
+    <tr><td>Property:</td></tr>
+    <tr>
+        <td class="RegText">
+            <select size="1" class="Ctrl" id="propertySelect" onChange="OnPropertyChange()" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td>Operator:</td></tr>
+    <tr>
+        <td class="RegText">
+            <select size="1" class="Ctrl" id="operatorSelect" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td>Value:</td></tr>
+    <tr>
+        <td class="RegText">
+            <input maxlength="100" class="Ctrl" id="valueInput" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td class="SubTitle"><input class="Ctrl" type="checkbox" onChange="OnToggleSpatialFilter()" id="spatialFilter">&nbsp;Spatial Filter</td></tr>
+    <tr><td>Digitize:</td></tr>
+    <tr>
+        <td align="center">
+            <input type="button" name="" value="Rectangle" class="Ctrl" id="rectButton" onClick="OnDigitizeRectangle()" style="width: 30%">
+            <input type="button" name="" value="Polygon" class="Ctrl" id="polyButtton" onClick="OnDigitizePolygon()" style="width: 30%">
+            <input type="button" name="" value="Clear" class="Ctrl" id="clearButton" onClick="OnClearSpatialFilter()" style="width: 30%">
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td class="SubTitle">Output</td></tr>
+    <tr><td>Output property:</td></tr>
+    <tr>
+        <td class="RegText">
+            <select size="1" class="Ctrl" id="outputSelect" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td><hr></td></tr>
+    <tr>
+        <td>
+            <input id="executeBtn" class="Ctrl" name="" type="button" onClick="ExecuteQuery()" value="Execute" style="width:60px">
+            &nbsp;&nbsp;Max results:&nbsp;
+            <input name="" id="queryMax" class="Ctrl" type="text" value="100" size="5">
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td class="SubTitle">Results</td></tr>
+    <tr>
+        <td>
+            <select class="Ctrl" id="resultSelect" size="15" onChange="OnResultChange()" style="width: 100%"></select>
+        </td>
+    </tr>
+    <tr>
+        <td>
+            Scale:&nbsp;<input class="Ctrl" id="scaleInput" type="text" size="6" value="10000">
+            <input class="Ctrl" id="zoomBtn" type="button" onClick="ZoomToFeature()" value="Zoom" style="width:60px">
+            <input class="Ctrl" id="selectBtn" type="button" onClick="SelectFeature()" value="Select" style="width:60px">
+        </td>
+    </tr>
+
+</table>
+
+<% } else { %>
+
+<table class="RegText" border="0" cellspacing="0" width="100%%">
+    <tr><td class="Title">Error<hr></td></tr>
+    <tr><td><%=errorMsg%></td></tr>
+    <tr><td><%=errorDetail%></td></tr>
+</table>
+
+<% } %>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/query/templates/filterlayerdefinition.xml
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/query/templates/filterlayerdefinition.xml	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/query/templates/filterlayerdefinition.xml	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<LayerDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="LayerDefinition-1.0.0.xsd" version="1.0.0">
+  <VectorLayerDefinition>
+    <ResourceId>%s</ResourceId>
+    <FeatureName>FilterSchema:Filter</FeatureName>
+    <FeatureNameType>FeatureClass</FeatureNameType>
+    <Geometry>Geometry</Geometry>
+    <VectorScaleRange>
+      <AreaTypeStyle>
+        <AreaRule>
+          <LegendLabel></LegendLabel>
+          <AreaSymbolization2D>
+            <Fill>
+              <FillPattern>Solid</FillPattern>
+              <ForegroundColor>40FF0000</ForegroundColor>
+              <BackgroundColor>FF000000</BackgroundColor>
+            </Fill>
+            <Stroke>
+              <LineStyle>Solid</LineStyle>
+              <Thickness>0</Thickness>
+              <Color>FFFF0000</Color>
+              <Unit>Inches</Unit>
+            </Stroke>
+          </AreaSymbolization2D>
+        </AreaRule>
+      </AreaTypeStyle>
+    </VectorScaleRange>
+  </VectorLayerDefinition>
+</LayerDefinition>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/styles/gt.css
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/styles/gt.css	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/styles/gt.css	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,43 @@
+td.Title
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-weight: bold;
+	font-size: 13pt;
+}
+td.SubTitle
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-weight: bold;
+	font-size: 8pt;
+	background-color: #DCDCDC;
+	color: black;
+	height: 20px;
+}
+td.Spacer
+{
+    height: 4px;
+}
+.Swatch
+{
+	border: black 1px solid;
+	height: 16px;
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 10pt;
+}
+td.InfoText
+{
+	background-color: #FFFFCC;
+	color: #666666;
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}
+.RegText
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}
+.Ctrl
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}

Added: trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/command.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/command.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/command.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,25 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<script language="c#" runat="server">
+    public class Command
+    {
+        public const int GETLAYERINFO 	= 1;
+        public const int GETPROPERTYMINMAXCOUNT = 2;
+        public const int APPLYTHEME 	= 3;
+    }
+</script>
+

Added: trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/layerinfo.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/layerinfo.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/layerinfo.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,39 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<script language="c#" runat="server">
+    public class LayerInfo : JsonObject
+    {
+        public ArrayList properties = null;
+        public ArrayList scaleRanges = null;
+        
+        public LayerInfo(ArrayList properties, ArrayList scaleRanges)
+    	{
+    	    this.properties = new ArrayList(properties);
+    	    this.scaleRanges = new ArrayList(scaleRanges);
+    	    
+    	    //JSON Settings
+    	    Put("properties", this.properties);
+    	    Put("scaleRanges", this.scaleRanges);
+    	}
+    }
+</script>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/property.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/property.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/property.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,42 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<script language="c#" runat="server">
+    public class Property : JsonObject
+    {
+        public String name = null;
+        public int dataType = 0;
+        public ArrayList distroTypes = null;
+        
+        public Property(String name, int dataType, ArrayList distroTypes)
+    	{
+    	    this.name = name;
+    	    this.dataType = dataType;
+    	    this.distroTypes = new ArrayList(distroTypes);
+    	    
+    	    //JSON Settings
+    	    Put("name", this.name);
+    	    Put("dataType", this.dataType);
+    	    Put("distroTypes", this.distroTypes);
+    	}
+    }
+</script>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/theme.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/theme.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/theme/classes/theme.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,472 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Xml" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+<%@ Import Namespace="Jayrock.Json" %>
+<%@ Import Namespace="Jayrock.Json.Conversion" %>
+
+<!-- #Include File="property.aspx -->
+<!-- #Include File="layerinfo.aspx -->
+<!-- #Include File="../../utilityfunctions.aspx -->
+
+<script language="c#" runat="server">
+    public class Theme
+    {
+        NameValueCollection args = null;
+        private MgSiteConnection site = null;
+        private String[] distNameArray = null;
+        private String[] distValueArray = null;
+        
+        public Theme(NameValueCollection incomingArgs)
+        {
+            this.args = incomingArgs;
+            this.site = new MgSiteConnection();
+            this.site.Open(new MgUserInformation(GetParameter(this.args, "SESSION")));
+            this.distNameArray = new String[] {"Individual", "Equal", "Standard Deviation", "Quantile", "Jenks (Natural Breaks)"};
+            this.distValueArray = new String[] {"INDIV_DIST", "EQUAL_DIST", "STDEV_DIST", "QUANT_DIST", "JENK_DIST"};
+        }
+        
+        public String getNameArray()
+        {
+            String jsonDistNames = JsonConvert.ExportToString(this.distNameArray);
+            return jsonDistNames;
+        }
+
+        public String getValueArray()
+        {
+            String jsonDistValues = JsonConvert.ExportToString(this.distValueArray);
+            return jsonDistValues;
+        }
+        
+        public ArrayList GetMapLayerNames()
+        {
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+            
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+            MgLayerCollection layers = map.GetLayers();
+            ArrayList layerNames = new ArrayList();
+
+            for(int i=0; i<layers.GetCount(); i++)
+            {
+            MgLayer layer = (MgLayer) layers.GetItem(i);
+                if(!layer.GetName().StartsWith("_") && !layer.GetFeatureSourceId().ToUpper().StartsWith("SESSION"))
+                {
+                    MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+                    String[] schemaClass = layer.GetFeatureClassName().Split(new Char[]{':'});
+
+                    MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+                    MgPropertyDefinition propDef = classDef.GetProperties().GetItem(layer.GetFeatureGeometryName());
+                
+                    if(propDef.GetPropertyType() == MgFeaturePropertyType.GeometricProperty)
+                    {
+                        MgGeometricPropertyDefinition geomPropDef= (MgGeometricPropertyDefinition) propDef;
+
+                        if(geomPropDef.GetGeometryTypes() == MgFeatureGeometricType.Surface)
+                        {
+                            layerNames.Add(layer.GetLegendLabel());
+                        }
+                    }
+                }
+            }
+            layerNames.Sort();
+
+            return layerNames;
+        }
+        
+        public LayerInfo GetLayerInfo()
+        {
+            ArrayList properties = new ArrayList();
+            ArrayList scaleRanges = new ArrayList();
+            
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+            MgLayer layer = (MgLayer) map.GetLayers().GetItem(GetParameter(this.args, "LAYERNAME"));
+
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            String[] schemaClass = layer.GetFeatureClassName().Split(new Char[]{':'});
+
+            MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+
+            for(int i=0; i<classDef.GetProperties().GetCount(); i++)
+            {
+                MgPropertyDefinition propertyDef = classDef.GetProperties().GetItem(i);
+
+                if(propertyDef.GetPropertyType() == MgFeaturePropertyType.DataProperty)
+                {
+                    MgDataPropertyDefinition propertyDataDef = (MgDataPropertyDefinition) propertyDef;
+                    int dataType = propertyDataDef.GetDataType();
+                    ArrayList distroTypes = new ArrayList(this.GetDistributionsForDataType(dataType));
+                    if(distroTypes.Count > 0)
+                    {
+                        properties.Add(new Property(propertyDataDef.GetName(), dataType, distroTypes));
+                    }
+                }
+            }
+            
+            // Next get a list of all of the layers scale ranges.
+            
+            MgResourceIdentifier layerDefResId = layer.GetLayerDefinition();
+            MgByteReader byteReader = resourceService.GetResourceContent(layerDefResId);
+            
+            XmlDocument doc = new XmlDocument();
+            doc.LoadXml(byteReader.ToString());
+            XmlNodeList nodeList = doc.GetElementsByTagName("VectorScaleRange");
+            
+            foreach(XmlElement node in nodeList)
+            {
+                String range = null;
+                
+                XmlNodeList minNodeList = node.GetElementsByTagName("MinScale");
+                if(minNodeList.Count > 0)
+                {
+                    range = minNodeList.Item(0).FirstChild.Value;
+                }
+                else
+                {
+                    range = "0";
+                }
+                
+                XmlNodeList maxNodeList = node.GetElementsByTagName("MaxScale");
+                if(maxNodeList.Count > 0)
+                {
+                    range = range + " - " + maxNodeList.Item(0).FirstChild.Value;
+                }
+                else
+                {
+                    range = range + " - Infinity";
+                }
+                
+                scaleRanges.Add(range);
+            }
+            
+            return new LayerInfo(properties, scaleRanges);
+        }
+        
+        public ArrayList GetPropertyMinMaxCount()
+        {
+            ArrayList propertyMinMaxCount = new ArrayList();
+            
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+            MgLayer layer = (MgLayer) map.GetLayers().GetItem(GetParameter(this.args, "LAYERNAME"));
+
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            
+            String minValue = null;
+            String maxValue = null;
+            int count = 0;
+            
+            MgFeatureQueryOptions queryOptions = new MgFeatureQueryOptions();
+            queryOptions.AddFeatureProperty(GetParameter(this.args, "PROPERTYNAME"));
+            
+            MgFeatureReader featureReader = featureService.SelectFeatures(resId, layer.GetFeatureClassName(), queryOptions);
+            while(featureReader.ReadNext())
+            {
+                String value = GetFeaturePropertyValue(featureReader, GetParameter(this.args, "PROPERTYNAME"));
+                int propertyType = featureReader.GetPropertyType(GetParameter(this.args, "PROPERTYNAME"));
+                if(count == 0)
+                {
+                    maxValue = value;
+                    minValue = value;
+                }
+                switch(propertyType)
+                {
+                    case MgPropertyType.String :
+                        if(value.Length > 0)
+                        {
+                            if(value.CompareTo(maxValue) > 0)
+                                maxValue = value;
+                            if(value.CompareTo(minValue) < 0)
+                                minValue = value;
+                        }
+                        break;
+                    case MgPropertyType.Byte :
+                    case MgPropertyType.Int16 :
+                    case MgPropertyType.Int32 :
+                    case MgPropertyType.Int64 :
+                        if(value.Length > 0)
+                        {
+                            if(Int64.Parse(value) > Int64.Parse(maxValue))
+                                maxValue = value;
+                            if(Int64.Parse(value) < Int64.Parse(minValue))
+                                minValue = value;
+                        }
+                        break;
+                    case MgPropertyType.Single :
+                    case MgPropertyType.Double :
+                        if(value != null)
+                        {
+                            if(Double.Parse(value) > Double.Parse(maxValue))
+                                maxValue = value;
+                            if(Double.Parse(value) < Double.Parse(minValue))
+                                minValue = value;
+                        }
+                        count++;
+                        break;
+                    case MgPropertyType.Boolean :
+                    case MgPropertyType.DateTime :
+                    case MgPropertyType.Null :
+                    case MgPropertyType.Blob :
+                    case MgPropertyType.Clob :
+                    case MgPropertyType.Feature :
+                    case MgPropertyType.Geometry :
+                        break;
+                }
+                count++;
+            }
+            featureReader.Close();
+            
+            propertyMinMaxCount.Add(minValue.ToString());
+            propertyMinMaxCount.Add(maxValue.ToString());
+            propertyMinMaxCount.Add(count.ToString());
+            
+            return propertyMinMaxCount;
+        }
+        
+        public String ApplyTheme()
+        {
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+
+            MgMap map = new MgMap();
+            map.Open(resourceService, GetParameter(this.args, "MAPNAME"));
+            MgLayerCollection layers = map.GetLayers();
+            MgLayer layer = (MgLayer) layers.GetItem(GetParameter(this.args, "LAYERNAME"));
+            
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            MgResourceIdentifier layerDefResId = layer.GetLayerDefinition();
+            MgByteReader byteReader = resourceService.GetResourceContent(layerDefResId);
+            
+            // Load the Layer Definition and Navigate to the specified <VectorScaleRange>
+            
+            XmlDocument doc = new XmlDocument();
+            String xmlLayerDef = byteReader.ToString();
+            doc.LoadXml(xmlLayerDef);
+            XmlNodeList nodeList = doc.GetElementsByTagName("VectorScaleRange");
+                
+            XmlElement vectorScaleRangecElement = (XmlElement) nodeList.Item(Int32.Parse(GetParameter(this.args, "SCALERANGEINDEX")));
+            XmlElement areaTypeStyle = (XmlElement) vectorScaleRangecElement.GetElementsByTagName("AreaTypeStyle").Item(0);
+            
+            // Remove any existing <AreaRule> elements.
+            
+            XmlNodeList areaRuleList = areaTypeStyle.GetElementsByTagName("AreaRule");
+            int count = areaRuleList.Count;
+            for(int i = 0; i < count; i++)
+            {
+                //The areaRuleList shrinks as we remove items, so always
+                //remove the first item (don't use the index i)
+                areaTypeStyle.RemoveChild(areaRuleList.Item(0));
+            }
+            
+            // Now create the new <AreaRule> elements.
+            
+            String areaRuleTemplate = File.ReadAllText(GetThemeXmlTemplatePath());
+            MgFeatureAggregateOptions aggregateOptions = new MgFeatureAggregateOptions();
+            
+            String value = null;
+            String filterText = null;
+            String areaRuleXML = null;
+            XmlDocument areaDoc = null;
+            XmlNode areaNode = null;
+            double portion = 0.0;
+            int numRules = Int32.Parse(GetParameter(this.args, "NUMRULES"));
+            double increment = (numRules > 1)? 1.0 / (numRules - 1) : 1.0;
+            
+            if("INDIV_DIST".Equals(GetParameter(this.args, "DISTRO")))
+            {
+                aggregateOptions.AddFeatureProperty(GetParameter(this.args, "PROPERTYNAME"));
+                aggregateOptions.SelectDistinct(true);
+                
+                MgDataReader dataReader = featureService.SelectAggregate(resId, layer.GetFeatureClassName(), aggregateOptions);
+                while(dataReader.ReadNext())
+                {
+                    value = GetFeaturePropertyValue(dataReader, GetParameter(this.args, "PROPERTYNAME"));
+                    
+                    filterText = "&quot;" + GetParameter(this.args, "PROPERTYNAME") + "&quot; = ";
+                    if(Int32.Parse(GetParameter(this.args, "DATATYPE")) == MgPropertyType.String)
+                        filterText = filterText + "'" + value + "'";
+                    else
+                        filterText = filterText + value;
+
+                    areaRuleXML = String.Format(areaRuleTemplate,
+                                                GetParameter(this.args, "PROPERTYNAME") + ":" + value,
+                                                filterText,
+                                                this.InterpolateColor(portion, GetParameter(this.args, "FILLFROM"), GetParameter(this.args, "FILLTO"), Int32.Parse(GetParameter(this.args, "FILLTRANS"))),
+                                                this.InterpolateColor(portion, GetParameter(this.args, "LINEFROM"), GetParameter(this.args, "LINETO"), 0));
+                    areaDoc = new XmlDocument();
+                    areaDoc.LoadXml(areaRuleXML);
+                    areaNode = doc.ImportNode(areaDoc.DocumentElement, true);
+                    areaTypeStyle.AppendChild(areaNode);
+                    
+                    portion = portion + increment;
+                }
+                dataReader.Close();
+            }
+            else
+            {
+                ArrayList values = new ArrayList();
+                
+                aggregateOptions.AddComputedProperty("THEME_VALUE",
+                    GetParameter(this.args, "DISTRO") + "(\"" + GetParameter(this.args, "PROPERTYNAME") + "\"," + GetParameter(this.args, "NUMRULES") + "," + GetParameter(this.args, "MINVALUE") + "," + GetParameter(this.args, "MAXVALUE") + ")");
+                MgDataReader dataReader = featureService.SelectAggregate(resId, layer.GetFeatureClassName(), aggregateOptions);
+                while(dataReader.ReadNext())
+                {
+                    value = GetFeaturePropertyValue(dataReader, "THEME_VALUE");
+                    values.Add(value);
+                }
+                dataReader.Close();
+                
+                for(int i=0; i<values.Count - 1; i++)
+                {
+                    filterText = "&quot;" + GetParameter(this.args, "PROPERTYNAME") + "&quot; &gt;= " + values[i] + " AND &quot;" + GetParameter(this.args, "PROPERTYNAME");
+                    if(i == values.Count - 1)
+                        filterText = filterText + "&quot; &lt;= " + values[i+1];
+                    else
+                        filterText = filterText + "&quot; &lt; " + values[i+1];
+                    
+                    areaRuleXML = String.Format(areaRuleTemplate,
+                                                GetParameter(this.args, "PROPERTYNAME") + ":" + values[i] + " - " + values[i+1],
+                                                filterText,
+                                                this.InterpolateColor(portion, GetParameter(this.args, "FILLFROM"), GetParameter(this.args, "FILLTO"), Int32.Parse(GetParameter(this.args, "FILLTRANS"))),
+                                                this.InterpolateColor(portion, GetParameter(this.args, "LINEFROM"), GetParameter(this.args, "LINETO"), 0));
+                    
+                    areaDoc = new XmlDocument();
+                    areaDoc.LoadXml(areaRuleXML); 
+                    areaNode = doc.ImportNode(areaDoc.DocumentElement, true);
+                    areaTypeStyle.AppendChild(areaNode);
+                                
+                    portion = portion + increment;
+                }
+            }
+            
+            // Now save our new layer definition to the session and add it to the map.
+            
+            String xmlString = doc.DocumentElement.OuterXml;
+            String uniqueName = this.MakeUniqueLayerName(map, GetParameter(this.args, "LAYERNAME"), GetParameter(this.args, "THEMENAME"));
+            String legendLabel = layer.GetLegendLabel();
+            if(GetParameter(this.args, "THEMENAME").Length > 0)
+                legendLabel = legendLabel + " (" + GetParameter(this.args, "THEMENAME") + ")";
+            
+            MgResourceIdentifier layerResId = new MgResourceIdentifier("Session:" + GetParameter(this.args, "SESSION") + "//" + uniqueName + ".LayerDefinition");
+            resourceService.SetResource(layerResId, new MgByteReader(xmlString, "text/xml"), null);
+            
+            MgLayer newLayer = new MgLayer(layerResId, resourceService);
+            newLayer.SetName(uniqueName);
+            newLayer.SetLegendLabel(legendLabel);
+            newLayer.SetDisplayInLegend(layer.GetDisplayInLegend());
+            newLayer.SetVisible(true);
+            newLayer.SetSelectable(layer.GetSelectable());
+            layers.Insert(layers.IndexOf(layer), newLayer);
+            
+            map.Save(resourceService);
+
+            return uniqueName;
+        }
+        
+        private String InterpolateColor(double portion, String startColor, String endColor, int percentTransparent)
+        {
+            int alpha = (int)(255*(100.0 - percentTransparent)/100.0);
+            String result = "";
+            if(startColor.Equals(endColor))
+            {
+                result = String.Format("{0:X2}{1}", alpha, startColor);
+            }
+            else
+            {
+                int red = this.CalculateRGB(portion, startColor.Substring(0,2), endColor.Substring(0,2));
+                int green = this.CalculateRGB(portion, startColor.Substring(2,2), endColor.Substring(2,2));
+                int blue = this.CalculateRGB(portion, startColor.Substring(4,2), endColor.Substring(4,2));
+                result = String.Format("{0:X2}{1:X2}{2:X2}{3:X2}", alpha, red, green, blue);           
+            }
+            return result;
+        }
+        
+        private int CalculateRGB(double portion, String startRGB, String endRGB)
+        {
+            double result = Int32.Parse(startRGB, NumberStyles.HexNumber) + portion * (Int32.Parse(endRGB, NumberStyles.HexNumber) - Int32.Parse(startRGB, NumberStyles.HexNumber));
+            return (int) result;
+        }
+        
+        private ArrayList GetDistributionsForDataType(int type)
+        {
+            ArrayList distroTypes = new ArrayList();
+            
+            switch(type)
+            {
+                case MgPropertyType.String :
+                    distroTypes.Add(0);
+                    break;
+                case MgPropertyType.Byte :
+                case MgPropertyType.Int16 :
+                case MgPropertyType.Int32 :
+                case MgPropertyType.Int64 :
+                    distroTypes.Add(0);
+                    distroTypes.Add(1);
+                    distroTypes.Add(2);
+                    distroTypes.Add(3);
+                    distroTypes.Add(4);
+                    break;
+                case MgPropertyType.Single :
+                case MgPropertyType.Double :
+                    distroTypes.Add(1);
+                    distroTypes.Add(2);
+                    distroTypes.Add(3);
+                    distroTypes.Add(4);
+                    break;
+                case MgPropertyType.Boolean :
+                case MgPropertyType.DateTime :
+                case MgPropertyType.Blob :
+                case MgPropertyType.Clob :
+                case MgPropertyType.Feature :
+                case MgPropertyType.Geometry :
+                case MgPropertyType.Null :
+                    break;
+            }
+            return distroTypes;
+        }
+        
+        private String MakeUniqueLayerName(MgMap map, String layerName, String themeName) 
+        {
+            String desiredName = "_" + layerName + themeName;
+            String uniqueName = desiredName;
+            int index = 1;
+            
+            while(map.GetLayers().Contains(uniqueName))
+            {
+                uniqueName = desiredName + index.ToString();
+                index++;
+            }
+            return uniqueName;
+        }
+               
+        String GetThemeXmlTemplatePath()
+        {
+            String xmlTemplatePath = GetBasePath() + "theme\\templates\\arearuletemplate.xml";
+            return xmlTemplatePath;
+        }
+    }
+</script>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/theme/templates/arearuletemplate.xml
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/theme/templates/arearuletemplate.xml	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/theme/templates/arearuletemplate.xml	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,17 @@
+<AreaRule>
+ <LegendLabel>{0}</LegendLabel>
+ <Filter>{1}</Filter>
+ <AreaSymbolization2D>
+  <Fill>
+   <FillPattern>Solid</FillPattern>
+   <ForegroundColor>{2}</ForegroundColor>
+   <BackgroundColor>FF000000</BackgroundColor>
+  </Fill>
+  <Stroke>
+   <LineStyle>Solid</LineStyle>
+   <Thickness>0</Thickness>
+   <Color>{3}</Color>
+   <Unit>Inches</Unit>
+  </Stroke>
+ </AreaSymbolization2D>
+</AreaRule>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/theme/themecontroller.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/theme/themecontroller.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/theme/themecontroller.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,59 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" debug="true"%>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+<%@ Import Namespace="Jayrock.Json" %>
+<%@ Import Namespace="Jayrock.Json.Conversion" %>
+
+<!-- #Include File="classes/theme.aspx -->
+<!-- #Include File="classes/command.aspx -->
+
+<%
+    InitializeWebTier();
+
+    NameValueCollection args = GetRequestParameters();
+    Theme theme = new Theme(args);
+    String responseType = "";
+    String responseString = "";
+
+    if(GetParameter(args, "COMMAND") != null)
+    {
+        int cmd = Int32.Parse(GetParameter(args, "COMMAND"));
+        switch (cmd)
+        {
+            case Command.GETLAYERINFO:
+                responseType = "text/plain";
+                responseString = JsonConvert.ExportToString(theme.GetLayerInfo());
+                break;
+            case Command.GETPROPERTYMINMAXCOUNT:
+                responseType = "text/plain";
+                responseString = JsonConvert.ExportToString(theme.GetPropertyMinMaxCount());
+                break;
+            case Command.APPLYTHEME:
+                responseType = "text/plain";
+		        responseString = JsonConvert.ExportToString(theme.ApplyTheme());
+                break;
+        }
+    }
+    Response.ContentType = responseType;
+    Response.Write(responseString);
+%>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/dotnetviewersample/theme/thememain.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/theme/thememain.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/theme/thememain.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,458 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Page language="c#" Debug="true" %>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Globalization" %>
+
+<!-- #Include File="classes/theme.aspx -->
+<!-- #Include File="classes/command.aspx -->
+
+<script runat="server">
+String errorMsg = null;
+String errorDetail = null;
+NameValueCollection args = null;
+Theme theme = null;
+ArrayList layerNames = null;
+</script>
+
+<%        
+    try
+    {
+        InitializeWebTier();
+        args = GetRequestParameters();    
+        theme = new Theme(args);        
+        layerNames = theme.GetMapLayerNames();
+    }
+    catch (MgException e)
+    {
+        errorMsg = e.GetMessage();
+        errorDetail = e.GetDetails();
+    }
+%>
+<html>
+<head>
+    <title>Theme Layer</title>
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+    <script language="javascript" src="../../viewerfiles/browserdetect.js"></script>
+    <script language="javascript" src="../json.js"></script>
+
+    <script language="javascript">
+        var READY_STATE_UNINITIALIZED 	= 0;
+        var READY_STATE_LOADING 		= 1;
+        var READY_STATE_LOADED 			= 2;
+        var READY_STATE_INTERACTIVE 	= 3;
+        var READY_STATE_COMPLETE 		= 4;
+
+        var NOT_BUSY_IMAGE = "../images/loader_inactive.gif";
+        var BUSY_IMAGE = "../images/loader_pulse.gif";
+
+        var SET_FILL_FROM_COLOR 	= 1;
+        var SET_FILL_TO_COLOR 		= 2;
+        var SET_LINE_FROM_COLOR 	= 3;
+        var SET_LINE_TO_COLOR		= 4;
+
+        var fillFromColor = "FF0000";
+        var fillToColor = "0000FF";
+        var lineFromColor = "000000";
+        var lineToColor = "000000";
+
+        var session = "<%= GetParameter(args, "SESSION") %>";
+        var mapName = "<%= GetParameter(args, "MAPNAME") %>";
+
+        var distNameArray = '<%= theme.getNameArray() %>'.parseJSON();
+        var distValueArray = '<%= theme.getValueArray() %>'.parseJSON();
+
+        var themeReqHandler = null;
+        var layerInfo = null;
+
+        var featureCount = 0;
+        var ruleCount = 8;
+
+        function OnLayerChange()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var propertySelect = document.getElementById("propertySelect");
+            var scaleSelect = document.getElementById("scaleSelect");
+
+            reqParams = "COMMAND=<%=Command.GETLAYERINFO%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "themecontroller.aspx", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            reqHandler.send(reqParams);
+            layerInfo = reqHandler.responseText.parseJSON();
+                        
+            propertySelect.options.length = 0;
+            for (var i = 0; i < layerInfo.properties.length; i++)
+            {
+                propertySelect.options[i] = new Option(layerInfo.properties[i].name, i, false, false);
+            }
+            OnPropertyChange();
+            
+            scaleSelect.options.length = 0;
+            for (var i = 0; i < layerInfo.scaleRanges.length; i++)
+            {
+                scaleSelect.options[i] = new Option(layerInfo.scaleRanges[i], i, false, false);
+            }
+        }
+
+        function OnPropertyChange()
+        {
+            var propertySelect = document.getElementById("propertySelect");
+            var distroSelect = document.getElementById("distroSelect");
+
+            PopulateMinMaxCount(propertySelect.value);
+	    
+            distroSelect.options.length = 0;
+            if (propertySelect.selectedIndex >= 0)
+            {
+                for (var i = 0; i < layerInfo.properties[propertySelect.value].distroTypes.length; i++)
+                {
+                    distroSelect.options[i] = new Option(distNameArray[layerInfo.properties[propertySelect.value].distroTypes[i]], distValueArray[layerInfo.properties[propertySelect.value].distroTypes[i]], false, false);
+                }
+            }
+            OnDistroChange();
+        }
+
+        function OnDistroChange()
+        {
+            var distroSelect = document.getElementById("distroSelect");
+            var numRules = document.getElementById("numRules");
+	
+            if (distroSelect.value == distValueArray[0])
+            {
+                numRules.disabled = true;
+                numRules.value = featureCount;
+            }
+            else
+            {
+                numRules.disabled = false;
+                numRules.value = ruleCount;
+            }
+        }
+		
+
+        function PopulateMinMaxCount(propertyIndex)
+        {
+            var layerSelect = document.getElementById("layerSelect");
+
+            reqParams = "COMMAND=<%=Command.GETPROPERTYMINMAXCOUNT%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+            reqParams += "&PROPERTYNAME=" + encodeURIComponent(layerInfo.properties[propertyIndex].name);
+
+            if (msie)
+                themeReqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                themeReqHandler = new XMLHttpRequest();
+
+            themeReqHandler.onreadystatechange = OnGetMinMaxCountReadyStateChange;
+            themeReqHandler.open("POST", "themecontroller.aspx", true);
+            themeReqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            document.getElementById("busyImg").src = BUSY_IMAGE;
+
+            DisableControls(['layerSelect', 'propertySelect'], true);
+
+            themeReqHandler.send(reqParams);
+        }
+
+        function OnGetMinMaxCountReadyStateChange()
+        {
+            var ready = themeReqHandler.readyState;
+
+            if (ready == READY_STATE_COMPLETE)
+            {
+                minMaxCount = themeReqHandler.responseText.parseJSON();
+
+                document.getElementById("minValue").value = minMaxCount[0];
+                document.getElementById("maxValue").value = minMaxCount[1];
+                featureCount = minMaxCount[2];
+
+                OnDistroChange();
+
+                DisableControls(['layerSelect', 'propertySelect'], false);
+                document.getElementById("busyImg").src = NOT_BUSY_IMAGE;
+                themeReqHandler = null;
+            }
+        }
+
+        function DisableControls(ids, enable)
+        {
+            for (var i = 0; i < ids.length; i++)
+            {
+                document.getElementById(ids[i]).disabled = enable;
+            }
+        }
+
+        function PickColor(whichColor, allowTransparency, transparent)
+        {
+            var clr;
+            setColor = whichColor;
+
+            if (setColor == SET_FILL_FROM_COLOR)
+                clr = fillFromColor;
+            else if (setColor == SET_FILL_TO_COLOR)
+                clr = fillToColor;
+            else if (setColor == SET_LINE_FROM_COLOR)
+                clr = lineFromColor;
+            else if (setColor == SET_LINE_TO_COLOR)
+                clr = lineToColor;
+            else
+                return;
+
+            height = allowTransparency? 470: 445;
+            w = window.open("../../mapviewernet/colorpicker.aspx?LOCALE=en&CLR=" + clr + "&ALLOWTRANS=" + (allowTransparency? "1":"0") + "&TRANS=" + (transparent?"1":"0"), "colorPicker", "toolbar=no,status=no,width=355,height=" + height);
+            w.focus();
+        }
+
+        function OnColorPicked(clr, trans)
+        {
+            if (setColor == SET_FILL_FROM_COLOR)
+                fillFromColor = clr;
+            else if (setColor == SET_FILL_TO_COLOR)
+                fillToColor = clr;
+            else if (setColor == SET_LINE_FROM_COLOR)
+                lineFromColor = clr;
+            else if (setColor == SET_LINE_TO_COLOR)
+                lineToColor = clr;
+            else
+                return;
+
+            UpdateColors();
+        }
+
+        function UpdateColors()
+        {
+            var elt;
+
+            elt = document.getElementById("fillFromSwatch").style;
+            elt.backgroundColor = "#" + fillFromColor;
+            elt.color = "#" + fillFromColor;
+
+            elt = document.getElementById("fillToSwatch").style;
+            elt.backgroundColor = "#" + fillToColor;
+            elt.color = "#" + fillToColor;
+
+            elt = document.getElementById("lineFromSwatch").style;
+            elt.backgroundColor = "#" + lineFromColor;
+            elt.color = "#" + lineFromColor;
+
+            elt = document.getElementById("lineToSwatch").style;
+            elt.backgroundColor = "#" + lineToColor;
+            elt.color = "#" + lineToColor;
+        }
+
+        function ApplyTheme()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var propertySelect = document.getElementById("propertySelect");
+
+            reqParams = "COMMAND=<%=Command.APPLYTHEME%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+            reqParams += "&THEMENAME=" + encodeURIComponent(document.getElementById("themeName").value);
+            reqParams += "&PROPERTYNAME=" + encodeURIComponent(layerInfo.properties[propertySelect.value].name);
+            reqParams += "&DATATYPE=" + encodeURIComponent(layerInfo.properties[propertySelect.value].dataType);
+            reqParams += "&MINVALUE=" + encodeURIComponent(document.getElementById("minValue").value);
+            reqParams += "&MAXVALUE=" + encodeURIComponent(document.getElementById("maxValue").value);
+            reqParams += "&DISTRO=" + encodeURIComponent(document.getElementById("distroSelect").value);
+            reqParams += "&NUMRULES=" + encodeURIComponent(document.getElementById("numRules").value);
+            reqParams += "&SCALERANGEINDEX=" + encodeURIComponent(document.getElementById("scaleSelect").value);
+            reqParams += "&FILLTRANS=" + encodeURIComponent(document.getElementById("fillTrans").value);
+            reqParams += "&FILLFROM=" + encodeURIComponent(fillFromColor);
+            reqParams += "&FILLTO=" + encodeURIComponent(fillToColor);
+            reqParams += "&LINEFROM=" + encodeURIComponent(lineFromColor);
+            reqParams += "&LINETO=" + encodeURIComponent(lineToColor);
+
+            if (msie)
+                themeReqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                themeReqHandler = new XMLHttpRequest();
+
+            themeReqHandler.onreadystatechange = OnApplyThemeReadyStateChange;
+            themeReqHandler.open("POST", "themecontroller.aspx", true);
+            themeReqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            document.getElementById("busyImg").src = BUSY_IMAGE;
+
+            DisableControls(['layerSelect', 'propertySelect'], true);
+
+            themeReqHandler.send(reqParams);
+        }
+
+        function OnApplyThemeReadyStateChange()
+        {
+            var ready = themeReqHandler.readyState;
+
+            if (ready == READY_STATE_COMPLETE)
+            {
+                DisableControls(['layerSelect', 'propertySelect'], false);
+                document.getElementById("busyImg").src = NOT_BUSY_IMAGE;
+                themeReqHandler = null;
+
+                parent.parent.Refresh();
+            }
+        }
+
+        function OnLoad()
+	    {
+		    OnLayerChange();
+		    UpdateColors();
+	    }
+
+    </script>
+
+</head>
+
+<body onLoad="OnLoad()" marginwidth=5 marginheight=5 leftmargin=5 topmargin=5 bottommargin=5 rightmargin=5>
+
+<% if (errorMsg == null) { %>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td colspan="2" class="Title"><img id="busyImg" src="../images/loader_pulse.gif" style="vertical-align:bottom">&nbsp;Theme Layer<hr></td></tr>
+    <tr><td colspan="2" class="SubTitle">Select a Layer</td></tr>
+    <tr><td colspan="2">Layer:</td></tr>
+    <tr><tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="layerSelect" onChange="OnLayerChange()" style="width: 100%">
+            <%
+                String selected = "selected";
+                for(int i=0; i<layerNames.Count; i++) {
+            %>
+                    <option value="<%= layerNames[i] %>" <%=selected %> ><%= layerNames[i] %></option>
+            <%
+                    selected = "";
+                }
+            %>
+            </select>
+        </td>
+    </tr>
+    <tr><td colspan="2">Theme Name:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="100" class="Ctrl" id="themeName" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" class="SubTitle">Define Conditions</td></tr>
+    <tr><td colspan="2">Property:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="propertySelect" onChange="OnPropertyChange()" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td colspan="2">Min:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="100" class="Ctrl" id="minValue" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2">Max:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="100" class="Ctrl" id="maxValue" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2">Distribution:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="distroSelect" onChange="OnDistroChange()" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td colspan="2"># of Rules:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="10" class="Ctrl" id="numRules" value="8" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" class="SubTitle">Scale Range</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="scaleSelect" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" class="SubTitle">Style Ramp</td></tr>
+    <tr><td>Fill Transparency:</td></tr>
+    <tr>
+        <td  colspan="2" class="RegText">
+            <input class="Ctrl" id="fillTrans" type="text"  maxlength="3" value="0" style="width:90%">&nbsp;%
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td>Fill Color:</td></tr>
+    <tr>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;From:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="fillFromSwatch" style="color: #FF0000; background-color: #FF0000">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_FILL_FROM_COLOR,false,false)">
+        </td>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;To:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="fillToSwatch" style="color: #0000FF; background-color: #0000FF">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_FILL_TO_COLOR,false,false)">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td>Border Color:</td></tr>
+    <tr>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;From:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="lineFromSwatch" style="color: #000000; background-color: #000000">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_LINE_FROM_COLOR,false,false)">
+        </td>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;To:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="lineToSwatch" style="color: #000000; background-color: #000000">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_LINE_TO_COLOR,false,false)">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" ><hr></td></tr>
+    <tr><td colspan="2" align="right"><input class="Ctrl" type="button" value="Apply" style="width: 60px;" onClick="ApplyTheme()"></td></tr>
+</table>
+
+<% } else { %>
+
+<table class="RegText" border="0" cellspacing="0" width="100%%">
+    <tr><td class="Title">Error<hr></td></tr>
+    <tr><td><%=errorMsg %></td></tr>
+    <tr><td><%=errorDetail %></td></tr>
+</table>
+
+<% } %>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/title.html
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/title.html	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/title.html	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>Title Frame Content</title>
+<style type="text/css">
+<!--
+.apptitle {
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+	font-size: 16px;
+	font-style: normal;
+	color: #FFFFFF;
+	vertical-align: baseline;
+	height: 30px;
+	line-height: 30px;
+	margin-left: 6px;
+}
+-->
+</style>
+</head>
+<body bgcolor="#006633">
+<p class="apptitle">Viewer Sample Application</p>
+</body>
+</html>

Added: trunk/MgDev/Doc/samples/dotnetviewersample/utilityfunctions.aspx
===================================================================
--- trunk/MgDev/Doc/samples/dotnetviewersample/utilityfunctions.aspx	                        (rev 0)
+++ trunk/MgDev/Doc/samples/dotnetviewersample/utilityfunctions.aspx	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,138 @@
+<%--
+Copyright (C) 2004-2007  Autodesk, Inc.
+This library is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser
+General Public License as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ Import Namespace="System" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Specialized" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+
+<script runat="server">
+
+static String s_basePath = "";
+    
+void InitializeWebTier()
+{
+    // Initialize web tier with the site configuration file.  The config
+    // file should be in the same directory as this script.
+    s_basePath = Request.ServerVariables["APPL_PHYSICAL_PATH"];
+    MapGuideApi.MgInitializeWebTier(s_basePath + "../webconfig.ini");
+}
+
+NameValueCollection GetRequestParameters()
+{
+    if ("POST"== Request.HttpMethod)
+    {
+        return Request.Form;
+    }
+    else
+    {
+        return Request.QueryString;
+    }
+}
+    
+static String GetBasePath()
+{
+    return s_basePath;
+}
+
+static String GetParameter(NameValueCollection parameters, String name)
+{
+    String strval = parameters[name];
+    if (null == strval)
+        return "";
+
+    return strval.Trim();
+}
+
+static String GetFeaturePropertyValue(MgReader featureReader, String propName)
+{
+    String value = "";
+    int propertyType = featureReader.GetPropertyType(propName);
+    switch(propertyType)
+    {
+        case MgPropertyType.Boolean :
+            value = featureReader.GetBoolean(propName).ToString();
+            break;
+        case MgPropertyType.Byte :
+            value = featureReader.GetByte(propName).ToString();
+            break;
+        case MgPropertyType.Single :
+            value = featureReader.GetSingle(propName).ToString();
+            break;
+        case MgPropertyType.Double :
+            value = featureReader.GetDouble(propName).ToString();
+            break;
+        case MgPropertyType.Int16 :
+            value = featureReader.GetInt16(propName).ToString();
+            break;
+        case MgPropertyType.Int32 :
+            value = featureReader.GetInt32(propName).ToString();
+            break;
+        case MgPropertyType.Int64 :
+            value = featureReader.GetInt64(propName).ToString();
+            break;
+        case MgPropertyType.String :
+            value = featureReader.GetString(propName);
+            break;
+        case MgPropertyType.DateTime :
+        case MgPropertyType.Null :
+        case MgPropertyType.Blob :
+        case MgPropertyType.Clob :
+        case MgPropertyType.Feature :
+        case MgPropertyType.Geometry :
+        case MgPropertyType.Raster :
+            value = "[unsupported data type]";
+            break;
+    }
+    return value;
+}
+    
+// Searches the map for a layer with the specified name.
+MgLayer GetLayerByName(MgMap map, String layerName)
+{
+    MgLayer layer = null;
+    for (int i = 0; i < map.GetLayers().GetCount(); i++)
+    {
+        MgLayer nextLayer = (MgLayer) map.GetLayers().GetItem(i);
+        if (nextLayer.GetName().Equals(layerName))
+        {
+            layer = nextLayer;
+            break;
+        }
+    }
+    return layer;
+}
+
+void OutputReaderContent(HttpResponse response, MgByteReader byteReader)
+{
+    MemoryStream memBuf = new MemoryStream();
+
+    byte[] byteBuffer = new byte[1024];
+    int numBytes = byteReader.Read(byteBuffer, 1024);
+    while(numBytes > 0)
+    {
+        memBuf.Write(byteBuffer, 0, numBytes);
+        numBytes = byteReader.Read(byteBuffer, 1024);
+    }
+
+    response.ContentType = byteReader.GetMimeType();
+    byte [] content = memBuf.ToArray();
+    response.OutputStream.Write(content , 0, content.Length);
+}
+
+</script>
+

Added: trunk/MgDev/Doc/samples/javaviewersample/ReadMe.txt
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/ReadMe.txt	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/ReadMe.txt	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,10 @@
+SETUP GUIDE
+-----------
+
+1. Open the file C:\Program Files\Autodesk\MapGuideEnterprise2008\WebServerExtensions\Apache2\conf\httpd.conf. Add the following line at the end:
+
+   JkMount  /mapguide2008/javaviewersample/* worker1
+
+2. Save the changes.
+3. Restart the Apache2 service.
+4. Copy json.jar from C:\Program Files\Autodesk\MapGuideEnterprise2008\WebServerExtensions\www\javaviewersample to C:\Program Files\Autodesk\MapGuideEnterprise2008\WebServerExtensions\www\WEB-INF\lib
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/javaviewersample/ajaxtiledviewersample.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/ajaxtiledviewersample.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/ajaxtiledviewersample.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,53 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="utilityfunctions.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<%
+    // Initialize a JSP session and register a variable to hold the
+    // session id, then initialize the Web Extensions, and connect
+    // to the site, and create a session.
+
+    InitializeWebTier();
+
+    MgUserInformation userInfo = new MgUserInformation("Anonymous", "");
+    MgSite site = new MgSite();
+
+    site.Open(userInfo);
+
+    String sessionId = site.CreateSession();
+    String webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganJspTiled.WebLayout";
+%>
+<html>
+
+<head>
+    <title>Viewer Sample Application</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+</head>
+
+<frameset rows="50,*" frameborder="NO" border="0" framespacing="0">
+    <frame src="title.html?AppName=AJAX" name="TitleFrame" scrolling="NO" noresize>
+    <frame src="../mapviewerjava/ajaxviewer.jsp?SESSION=<%= sessionId %>&WEBLAYOUT=<%= webLayout %>" name="ViewerFrame">
+</frameset>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/ajaxviewersample.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/ajaxviewersample.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/ajaxviewersample.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,53 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="utilityfunctions.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<%
+    // Initialize a JSP session and register a variable to hold the
+    // session id, then initialize the Web Extensions, and connect
+    // to the site, and create a session.
+
+    InitializeWebTier();
+
+    MgUserInformation userInfo = new MgUserInformation("Anonymous", "");
+    MgSite site = new MgSite();
+
+    site.Open(userInfo);
+
+    String sessionId = site.CreateSession();
+    String webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganJsp.WebLayout";
+%>
+<html>
+
+<head>
+    <title>Viewer Sample Application</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+</head>
+
+<frameset rows="50,*" frameborder="NO" border="0" framespacing="0">
+    <frame src="title.html?AppName=AJAX" name="TitleFrame" scrolling="NO" noresize>
+    <frame src="../mapviewerjava/ajaxviewer.jsp?SESSION=<%= sessionId %>&WEBLAYOUT=<%= webLayout %>" name="ViewerFrame">
+</frameset>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/dwfviewersample.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/dwfviewersample.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/dwfviewersample.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,53 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="utilityfunctions.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<%
+    // Initialize a JSP session and register a variable to hold the
+    // session id, then initialize the Web Extensions, and connect
+    // to the site, and create a session.
+
+    InitializeWebTier();
+
+    MgUserInformation userInfo = new MgUserInformation("Anonymous", "");
+    MgSite site = new MgSite();
+
+    site.Open(userInfo);
+
+    String sessionId = site.CreateSession();
+    String webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganJsp.WebLayout";
+%>
+<html>
+
+<head>
+    <title>Viewer Sample Application</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+</head>
+
+<frameset rows="50,*" frameborder="NO" border="0" framespacing="0">
+    <frame src="title.html?AppName=AJAX" name="TitleFrame" scrolling="NO" noresize>
+    <frame src="../mapviewerjava/dwfviewer.jsp?SESSION=<%= sessionId %>&WEBLAYOUT=<%= webLayout %>" name="ViewerFrame">
+</frameset>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/findaddress/clearaddressresults.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/findaddress/clearaddressresults.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/findaddress/clearaddressresults.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,96 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Viewer Sample Application - Clear Address Results</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <meta http-equiv="content-script-type" content="text/javascript">
+</head>
+
+<%
+    String mgSessionId = request.getParameter("SESSION");
+
+    try
+    {
+        // Initialize the web-tier and connect to the Site using
+        // the session identifier stored
+
+        InitializeWebTier();
+
+        MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+        MgSiteConnection siteConnection = new MgSiteConnection();
+        siteConnection.Open(userInfo);
+
+        MgFeatureService featureService = (MgFeatureService)siteConnection.CreateService(MgServiceType.FeatureService);
+
+        MgResourceIdentifier addressMarkerDataResId = new MgResourceIdentifier("Session:" + mgSessionId + "//AddressMarker.FeatureSource");
+
+        MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
+        commands.Add(new MgDeleteFeatures("AddressMarker", "ID like '%'"));
+
+        featureService.UpdateFeatures(addressMarkerDataResId, commands, false);
+
+        // Create a ReserviceService object and use it to open the Map
+        // object from the sessions repository. Use the Map object to hide
+        // the "ParcelMarker" layer and then save the updated Map back to
+        // the session.
+
+        MgResourceService resourceService = (MgResourceService)siteConnection.CreateService(MgServiceType.ResourceService);
+        MgMap map = new MgMap();
+        map.Open(resourceService, "Sheboygan");
+
+        MgLayer layer = GetLayerByName(map, "AddressMarker");
+        layer.SetVisible(false);
+        layer.ForceRefresh();
+
+        map.Save(resourceService);
+    }
+    catch (MgException e)
+    {
+        out.write(e.GetMessage());
+        out.write(e.GetDetails());
+    }
+%>
+
+<!-- Finally emit this function and assocate it with the onLoad event  -->
+<!-- for the page so that it gets executed when this page loads in the -->
+<!-- browser. The function calls the Refresh method on the Viewer      -->
+<!-- frame forcing the Viewer to update itself to match the state of   -->
+<!-- the Server-Side Map object.                                       -->
+
+<script language=javascript>
+function OnPageLoad()
+{
+   parent.Refresh();
+   parent.taskFrame.taskPaneFrame.location.href = "findaddressmain.jsp?SESSION=<%= mgSessionId %>";
+}
+</script>
+
+<body onLoad="OnPageLoad()">
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddress.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddress.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddress.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,164 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+<%@ include file ="findaddressfunctions.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Find Address</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+
+    <script language=javascript>
+        function InitDocument()
+        {
+            this.ZoomToResult();
+        }
+    </script>
+</head>
+
+<body onload="InitDocument()">
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Find Address<hr></td></tr>
+    <tr><td class="SubTitle">Search Results</td></tr>
+
+<%
+    String mgSessionId = request.getParameter("SESSION");
+    GeocodeAddress addr = null;
+    boolean success = false;
+
+    try
+    {
+        // Initialize the Web Extensions and connect to the Tux Site using
+        // the session identifier stored in JSP session state.
+
+        InitializeWebTier();
+
+        MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+        MgSiteConnection siteConnection = new MgSiteConnection();
+        siteConnection.Open(userInfo);
+
+        String address = request.getParameter("address") + ", Sheboygan, WI";
+
+        // Make the request to geocoder.us passing the address.
+        addr = requestGeocodeAddress(address);
+
+        if (addr != null && addr.lon.length() > 0 && addr.lat.length() > 0)
+        {
+            // The geocode successfully returned a location.
+
+            out.write("<tr><td><img src=\"../images/pushpinblue.jpg\">");
+            out.write("<a href=\"gotopoint.jsp?X=" + addr.lon + "&Y=" + addr.lat + "&Scale=2000\" target=\"scriptFrame\">  " + addr.address1 + "</a></td></tr>");
+            out.write("<tr><td>" + addr.address2 + "</td></tr>");
+            out.write("<tr><td class=\"Spacer\"></td></tr>");
+            out.write("<tr><td>Longitude: " + addr.lon + "</td></tr>");
+            out.write("<tr><td>Latitude: " + addr.lat + "<hr></td></tr>");
+
+            // Create ResourceService and FeatureService objects and use
+            // the ResourceService object to open the map instance in
+            // session state.
+
+            MgResourceService resourceService = (MgResourceService)siteConnection.CreateService(MgServiceType.ResourceService);
+            MgFeatureService featureService = (MgFeatureService)siteConnection.CreateService(MgServiceType.FeatureService);
+
+            MgMap map = new MgMap();
+            map.Open(resourceService, "Sheboygan");
+
+            // Check the map for the AddressMarker layer. If it does not
+            // exist then create a feature source to store address results
+            // and a layer to display them.
+
+            MgResourceIdentifier addressMarkerDataResId = new MgResourceIdentifier("Session:" + mgSessionId + "//AddressMarker.FeatureSource");
+            MgLayer addressLayer = GetLayerByName(map, "AddressMarker");
+            if (addressLayer == null)
+            {
+                CreateAddressMarkerFeatureSource(featureService, addressMarkerDataResId);
+                addressLayer = CreateAddressMarkerLayer(resourceService, addressMarkerDataResId, mgSessionId);
+
+                map.GetLayers().Insert(0, addressLayer);
+            }
+            else if (addressLayer.GetVisible())
+            {
+                // If the layer exists and is visible, then display the
+                // previous results.
+
+                EmitAddressResults(out, featureService, addressMarkerDataResId, mgSessionId);
+            }
+
+            // Insert the results of the Geo-Code into the temporary
+            // feature source and ensure the address marker layer
+            // is visible.
+
+            MgAgfReaderWriter geometryReaderWriter = new MgAgfReaderWriter();
+            MgGeometryFactory geometryFactory = new MgGeometryFactory();
+            MgPoint addrPoint = geometryFactory.CreatePoint(geometryFactory.CreateCoordinateXY(Double.parseDouble(addr.lon), Double.parseDouble(addr.lat)));
+
+            MgPropertyCollection properties = new MgPropertyCollection();
+            properties.Add(new MgStringProperty("Address", addr.address1));
+            properties.Add(new MgGeometryProperty("Location", geometryReaderWriter.Write(addrPoint)));
+
+            MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
+            commands.Add(new MgInsertFeatures("AddressMarker", properties));
+
+            featureService.UpdateFeatures(addressMarkerDataResId, commands, false);
+
+            addressLayer.SetVisible(true);
+            addressLayer.ForceRefresh();
+
+            map.Save(resourceService);
+
+            success = true;
+        }
+        else
+        {
+            out.write("<tr><td>Address not found: " + address + "<hr></td></tr>");
+        }
+    }
+    catch (MgException e)
+    {
+        out.write("<tr><td>" + e.GetMessage()+ "</td></tr>");
+        out.write("<tr><td class=\"Spacer\"></td></tr>");
+        out.write("<tr><td>" + e.GetDetails() + "</td></tr>");
+    }
+%>
+
+</table>
+
+Geocoding Provided by: <a href="http://geocoder.us/" target="_blank">geocoder.us</a>.<br>
+Locative Tecnologies offers the free geocoder.us web service for non commercial purposes. If you wish to use this geocoding web service in an production application you must sign up for a commercial license. Click the link above for more information.
+
+</body>
+
+<script language=javascript>
+function ZoomToResult()
+{
+    success = <%= success? "true": "false" %>;
+    if(success)
+        parent.parent.ZoomToView(<%= addr!=null? addr.lon: "0" %>, <%= addr!=null? addr.lat: "0" %>, 2000, true);
+}
+</script>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddressfunctions.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddressfunctions.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddressfunctions.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,240 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.net.*" %>
+<%@ page import="javax.xml.parsers.*" %>
+<%@ page import="javax.xml.transform.*" %>
+<%@ page import="javax.xml.transform.dom.*" %>
+<%@ page import="javax.xml.transform.stream.*" %>
+<%@ page import="org.w3c.dom.*" %>
+<%!
+
+private class GeocodeAddress
+{
+    public GeocodeAddress()
+    {
+        address1 = "";
+        address2 = "";
+        lat = "";
+        lon = "";
+    }
+
+    public String address1;
+    public String address2;
+    public String lat;
+    public String lon;
+}
+
+
+void EmitAddressResults(JspWriter out, MgFeatureService featureService, MgResourceIdentifier addressMarkerDataResId, String mgSessionId) throws MgException, Exception
+{
+    out.write("<table class=\"RegText\" border=\"0\" cellspacing=\"0\" width=\"100%\">");
+    out.write("<tr><td class=\"SubTitle\">Previous Results</td></tr>");
+
+    MgAgfReaderWriter geometryReaderWriter = new MgAgfReaderWriter();
+    MgFeatureReader featureReader = (MgFeatureReader)featureService.SelectFeatures(addressMarkerDataResId, "AddressMarker", null);
+
+    while (featureReader.ReadNext())
+    {
+        String address = featureReader.GetString("Address");
+        MgByteReader byteReader = featureReader.GetGeometry("Location");
+
+        MgPoint point = (MgPoint)geometryReaderWriter.Read(byteReader);
+        double x = point.GetCoordinate().GetX();
+        double y = point.GetCoordinate().GetY();
+
+        out.write("<tr><td>");
+        out.write("<img src=\"../images/pushpinblue.jpg\">");
+        out.write("<a href=\"gotopoint.jsp?X=" + x + "&Y=" + y + "&Scale=2000\" target=\"scriptFrame\">  " + address + "</a></td></tr>");
+    }
+    featureReader.Close();
+
+    out.write("</table>");
+    out.write("<form action=\"clearaddressresults.jsp\" method=\"get\" target=\"scriptFrame\">");
+    out.write("<input type=\"hidden\" name=\"SESSION\" value=\"" + mgSessionId + "\">");
+    out.write("<input type=\"button\" class=\"Ctrl\" value=\"Clear Results\" onClick=\"javascript:submit()\">");
+    out.write("</form>");
+    out.write("<hr>");
+}
+
+// Create a temporary Feature Source to store geocode results.
+
+void CreateAddressMarkerFeatureSource(MgFeatureService featureService, MgResourceIdentifier addressMarkerDataResId) throws MgException
+{
+    String ll84Wkt = "GEOGCS[\"WGS84 Lat/Long's, Degrees, -180 ==> +180\",DATUM[\"D_WGS_1984]\",SPHEROID[\"World_Geodetic_System_of_1984\",6378137,298.257222932867]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]]";
+
+    MgClassDefinition addressClass = new MgClassDefinition();
+    addressClass.SetName("AddressMarker");
+    MgPropertyDefinitionCollection properties = addressClass.GetProperties();
+
+    MgDataPropertyDefinition idProperty = new MgDataPropertyDefinition("ID");
+    idProperty.SetDataType(MgPropertyType.Int32);
+    idProperty.SetReadOnly(true);
+    idProperty.SetNullable(false);
+    idProperty.SetAutoGeneration(true);
+    properties.Add(idProperty);
+
+    MgDataPropertyDefinition addressProperty = new MgDataPropertyDefinition("Address");
+    addressProperty.SetDataType(MgPropertyType.String);
+    addressProperty.SetLength(512);
+    properties.Add(addressProperty);
+
+    MgGeometricPropertyDefinition locationProperty = new MgGeometricPropertyDefinition("Location");
+    locationProperty.SetGeometryTypes(MgGeometryType.Point);
+    locationProperty.SetHasElevation(false);
+    locationProperty.SetHasMeasure(false);
+    locationProperty.SetReadOnly(false);
+    locationProperty.SetSpatialContextAssociation("LL84");
+    properties.Add(locationProperty);
+
+    MgPropertyDefinitionCollection idProperties = addressClass.GetIdentityProperties();
+    idProperties.Add(idProperty);
+
+    addressClass.SetDefaultGeometryPropertyName("Location");
+
+    MgFeatureSchema addressSchema = new MgFeatureSchema();
+    addressSchema.SetName("AddressMarkerSchema");
+    addressSchema.GetClasses().Add(addressClass);
+
+    MgCreateSdfParams sdfParams = new MgCreateSdfParams("LL84", ll84Wkt, addressSchema);
+
+    featureService.CreateFeatureSource(addressMarkerDataResId, sdfParams);
+}
+
+// Create a temporary Layer to display geocode results.
+
+MgLayer CreateAddressMarkerLayer(MgResourceService resourceService, MgResourceIdentifier addressMarkerDataResId, String sessionId) throws MgException, Exception
+{
+    // Load the AddressMarker layer definition template into
+    // a JSP DOM object, find the "ResourceId" element, and
+    // modify it's content to reference the temporary
+    // feature source.
+
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    DocumentBuilder builder = factory.newDocumentBuilder();
+    Document document = builder.parse(new File(getServletContext().getRealPath("/") + "javaviewersample//findaddress//templates" + File.separator + "addressmarker.xml"));
+    NodeList nodes = document.getElementsByTagName("ResourceId");
+    Node resNode = nodes.item(0);
+    Node resContent = document.createTextNode(addressMarkerDataResId.ToString());
+    resNode.appendChild(resContent);
+
+    // write the modified layer XML definition into a byte stream
+    //
+    TransformerFactory tFactory = TransformerFactory.newInstance();
+    Transformer transformer = tFactory.newTransformer();
+    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    DOMSource source = new DOMSource(document);
+    StreamResult result = new StreamResult(bos);
+    transformer.transform(source, result);
+
+    // Save the updated layer definition to the session repository using the
+    // ResourceService object.
+
+    byte[] layerDefinition = bos.toByteArray();
+    MgByteSource byteSource = new MgByteSource(layerDefinition, layerDefinition.length);
+    byteSource.SetMimeType(MgMimeType.Xml);
+
+    MgResourceIdentifier tempLayerResId = new MgResourceIdentifier("Session:" + sessionId + "//AddressMarker.LayerDefinition");
+
+    resourceService.SetResource(tempLayerResId, byteSource.GetReader(), null);
+
+    // Create an MgLayer object based on the new layer definition
+    // and return it to the caller.
+
+    MgLayer addressLayer = new MgLayer(tempLayerResId, resourceService);
+    addressLayer.SetName("AddressMarker");
+    addressLayer.SetLegendLabel("AddressMarker");
+    addressLayer.SetDisplayInLegend(false);
+    addressLayer.SetSelectable(false);
+
+    return addressLayer;
+}
+
+GeocodeAddress requestGeocodeAddress(String address)
+{
+    //Request the specified address to the geocode service using REST, the
+    // GET interface
+    //
+    String urlString;
+    URL url = null;
+    try
+    {
+        urlString = "http://geocoder.us/service/rest/geocode?address=" + URLEncoder.encode(address, "UTF-8");
+        url = new URL(urlString);
+    }
+    catch (Exception e)
+    {
+        return null;
+    }
+    URLConnection conn = null;
+    DataInputStream data = null;
+    String line;
+    StringBuffer buf = new StringBuffer();
+
+    try
+    {
+        conn = url.openConnection();
+        conn.connect();
+
+        data = new DataInputStream(new BufferedInputStream(conn.getInputStream()));
+        while ((line = data.readLine()) != null)
+        {
+            buf.append(line + "\n");
+        }
+        data.close();
+    }
+    catch (IOException e)
+    {
+        return null;
+    }
+
+    //Extract address elements from the XML response
+    //
+    //
+    GeocodeAddress addr = new GeocodeAddress();
+    try
+    {
+        ByteArrayInputStream bis = new ByteArrayInputStream(buf.toString().getBytes("UTF-8"));
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder builder = factory.newDocumentBuilder();
+        Document document = builder.parse(bis);
+
+        //get the longitude and latitude
+        addr.lon = document.getElementsByTagName("geo:long").item(0).getFirstChild().getNodeValue();
+        addr.lat = document.getElementsByTagName("geo:lat").item(0).getFirstChild().getNodeValue();
+
+        //get and decompose address
+        address = document.getElementsByTagName("dc:description").item(0).getFirstChild().getNodeValue();
+        int sep = address.indexOf(',');
+        if(sep != -1)
+        {
+            addr.address1 = address.substring(0, sep);
+            addr.address2 = address.substring(sep + 1);
+        }
+        else
+            addr.address1 = address;
+    }
+    catch (Exception e)
+    {
+        return null;
+    }
+    return addr;
+}
+
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddressmain.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddressmain.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/findaddress/findaddressmain.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,130 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+<%@ include file ="findaddressfunctions.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Find Address Task</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+    
+    <script language="javascript">
+    function Submit()
+    {
+    	var addressForm = document.getElementById("addressForm");
+    	var addressValue = document.getElementById("addressValue");
+    	var addressInput = document.getElementById("addressInput");
+    	
+    	addressValue.value = addressInput.value;
+    	addressForm.submit();
+    }
+    </script>
+</head>
+
+<body>
+
+<%
+    String mgSessionId = request.getParameter("SESSION");
+    boolean showPreviousResults = false;
+    MgSiteConnection siteConnection = null;
+
+    try
+    {
+        // Initialize the Web Extensions and connect to the Site using
+        // the session identifier stored in JSP session state.
+
+        InitializeWebTier();
+
+        MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+        siteConnection = new MgSiteConnection();
+        siteConnection.Open(userInfo);
+
+        // Create a ReserviceService object and use it to open the Map
+        // object from the sessions repository. Use the Map object to
+        // determine if the "AddressMarker" layer is visible.
+
+        MgResourceService resourceService = (MgResourceService)siteConnection.CreateService(MgServiceType.ResourceService);
+        MgMap map = new MgMap();
+        map.Open(resourceService, "Sheboygan");
+        MgLayer addressLayer = GetLayerByName(map, "AddressMarker");
+
+        if (addressLayer != null)
+        {
+            showPreviousResults = addressLayer.GetVisible();
+        }
+    }
+    catch (MgException e)
+    {
+        out.write(e.GetMessage());
+        out.write(e.GetDetails());
+    }
+%>
+
+<form id="addressForm" action="findaddress.jsp" method="get" target="_self">
+    <input name="SESSION" type="hidden" value="<%= mgSessionId %>">
+    <input id="addressValue" name="address" type="hidden" value="">
+</form>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Find Address<hr></td></tr>
+    <tr><td class="SubTitle">Search for an Address</td></tr>
+    <tr><td>Address:</td></tr>
+    <tr>
+        <td class="RegText">
+        <input maxlength="100" class="Ctrl" id="addressInput" style="width: 95%">
+        </td>
+    </tr>
+    <tr><td><strong>Sheboygan, WI</strong></td></tr>
+    <tr>
+        <td>
+        <input class="Ctrl" type="button" onClick="Submit()" value="Find" style="width:60px">
+        </td>
+    </tr>
+
+    <tr><td><hr>Hint try:</td></tr>
+    <tr><td>&nbsp;&nbsp;601 North 5th Street</td></tr>
+    <tr><td>&nbsp;&nbsp;720 Riverfront Drive<hr></td></tr>
+</table>
+
+<%
+    // If there are previous results, display them as hyperlinks and emit
+    // a second form with a Clear Results button.
+
+    if (showPreviousResults)
+    {
+        MgFeatureService featureService = (MgFeatureService)siteConnection.CreateService(MgServiceType.FeatureService);
+        MgResourceIdentifier addressMarkerDataResId = new MgResourceIdentifier("Session:" + mgSessionId + "//AddressMarker.FeatureSource");
+
+        EmitAddressResults(out, featureService, addressMarkerDataResId, mgSessionId);
+    }
+%>
+
+Geocoding Provided by: <a href="http://geocoder.us/" target="_blank">geocoder.us</a>.<br>
+Locative Tecnologies offers the free geocoder.us web service for non commercial purposes. If you wish to use this geocoding web service in an production application you must sign up for a commercial license. Click the link above for more information.
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/findaddress/gotopoint.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/findaddress/gotopoint.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/findaddress/gotopoint.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,53 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Viewer Sample Application - Goto Point</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <meta http-equiv="content-script-type" content="text/javascript">
+</head>
+
+<!-- Emit this function and assocate it with the onLoad event for the -->
+<!-- page so that it gets executed when this page loads in the        -->
+<!-- browser. The function calls the ZoomToView method on the         -->
+<!-- Viewer frame forcing the Viewer to navigate to the specified     -->
+<!-- point and scale.                                                 -->
+
+<script language="javascript">
+
+function OnPageLoad()
+{
+    parent.ZoomToView(<%= Double.parseDouble(request.getParameter("X")) %>, <%= Double.parseDouble(request.getParameter("Y")) %>, <%= Double.parseDouble(request.getParameter("Scale")) %>, true);
+}
+
+</script>
+
+<body onLoad="OnPageLoad()">
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/findaddress/templates/addressmarker.xml
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/findaddress/templates/addressmarker.xml	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/findaddress/templates/addressmarker.xml	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<LayerDefinition version="1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="LayerDefinition-1.0.0.xsd">
+  <VectorLayerDefinition>
+    <ResourceId></ResourceId>
+    <FeatureName>AddressMarker</FeatureName>
+    <FeatureNameType>FeatureClass</FeatureNameType>
+    <Geometry>Location</Geometry>
+    <VectorScaleRange>
+      <MaxScale>10000</MaxScale>
+      <PointTypeStyle>
+        <DisplayAsText>false</DisplayAsText>
+        <AllowOverpost>false</AllowOverpost>
+        <PointRule>
+          <LegendLabel></LegendLabel>
+          <Label>
+            <Unit>Points</Unit>
+            <SizeContext>DeviceUnits</SizeContext>
+            <SizeX>7</SizeX>
+            <SizeY>10</SizeY>
+            <Text>Address</Text>
+            <FontName>Verdana</FontName>
+            <ForegroundColor>FF000000</ForegroundColor>
+            <BackgroundColor>FFFFFFFF</BackgroundColor>
+            <BackgroundStyle>Ghosted</BackgroundStyle>
+            <HorizontalAlignment>&apos;Center&apos;</HorizontalAlignment>
+            <VerticalAlignment>&apos;Baseline&apos;</VerticalAlignment>
+          </Label>
+          <PointSymbolization2D>
+            <W2D>
+              <Unit>Millimeters</Unit>
+              <SizeContext>DeviceUnits</SizeContext>
+              <SizeX>15</SizeX>
+              <SizeY>15</SizeY>
+              <W2DSymbol>
+                <ResourceId>Library://Samples/Sheboygan/Symbols/BasicSymbols.SymbolLibrary</ResourceId>
+                <LibraryItemName>PushPin - Blue</LibraryItemName>
+              </W2DSymbol>
+            </W2D>
+          </PointSymbolization2D>
+        </PointRule>
+      </PointTypeStyle>
+    </VectorScaleRange>
+    <VectorScaleRange>
+      <PointTypeStyle>
+        <DisplayAsText>false</DisplayAsText>
+        <AllowOverpost>false</AllowOverpost>
+        <PointRule>
+          <LegendLabel></LegendLabel>
+          <PointSymbolization2D>
+            <W2D>
+              <Unit>Millimeters</Unit>
+              <SizeContext>DeviceUnits</SizeContext>
+              <SizeX>15</SizeX>
+              <SizeY>15</SizeY>
+              <W2DSymbol>
+                <ResourceId>Library://Samples/Sheboygan/Symbols/BasicSymbols.SymbolLibrary</ResourceId>
+                <LibraryItemName>PushPin - Blue</LibraryItemName>
+              </W2DSymbol>
+            </W2D>
+          </PointSymbolization2D>
+        </PointRule>
+      </PointTypeStyle>
+    </VectorScaleRange>
+  </VectorLayerDefinition>
+</LayerDefinition>

Added: trunk/MgDev/Doc/samples/javaviewersample/images/Thumbs.db
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/javaviewersample/images/Thumbs.db
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/javaviewersample/images/loader_inactive.gif
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/javaviewersample/images/loader_inactive.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/javaviewersample/images/loader_pulse.gif
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/javaviewersample/images/loader_pulse.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/javaviewersample/images/pushpin.jpg
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/javaviewersample/images/pushpin.jpg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/javaviewersample/images/pushpinblue.jpg
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/javaviewersample/images/pushpinblue.jpg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/javaviewersample/json.jar
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/javaviewersample/json.jar
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/javaviewersample/json.js
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/json.js	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/json.js	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,120 @@
+/*
+    json.js
+    2006-04-28
+
+    This file adds these methods to JavaScript:
+
+        object.toJSONString()
+
+            This method produces a JSON text from an object. The
+            object must not contain any cyclical references.
+
+        array.toJSONString()
+
+            This method produces a JSON text from an array. The
+            array must not contain any cyclical references.
+
+        string.parseJSON()
+
+            This method parses a JSON text to produce an object or
+            array. It will return false if there is an error.
+*/
+(function () {
+    var m = {
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        },
+        s = {
+            array: function (x) {
+                var a = ['['], b, f, i, l = x.length, v;
+                for (i = 0; i < l; i += 1) {
+                    v = x[i];
+                    f = s[typeof v];
+                    if (f) {
+                        v = f(v);
+                        if (typeof v == 'string') {
+                            if (b) {
+                                a[a.length] = ',';
+                            }
+                            a[a.length] = v;
+                            b = true;
+                        }
+                    }
+                }
+                a[a.length] = ']';
+                return a.join('');
+            },
+            'boolean': function (x) {
+                return String(x);
+            },
+            'null': function (x) {
+                return "null";
+            },
+            number: function (x) {
+                return isFinite(x) ? String(x) : 'null';
+            },
+            object: function (x) {
+                if (x) {
+                    if (x instanceof Array) {
+                        return s.array(x);
+                    }
+                    var a = ['{'], b, f, i, v;
+                    for (i in x) {
+                        v = x[i];
+                        f = s[typeof v];
+                        if (f) {
+                            v = f(v);
+                            if (typeof v == 'string') {
+                                if (b) {
+                                    a[a.length] = ',';
+                                }
+                                a.push(s.string(i), ':', v);
+                                b = true;
+                            }
+                        }
+                    }
+                    a[a.length] = '}';
+                    return a.join('');
+                }
+                return 'null';
+            },
+            string: function (x) {
+                if (/["\\\x00-\x1f]/.test(x)) {
+                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+                        var c = m[b];
+                        if (c) {
+                            return c;
+                        }
+                        c = b.charCodeAt();
+                        return '\\u00' +
+                            Math.floor(c / 16).toString(16) +
+                            (c % 16).toString(16);
+                    });
+                }
+                return '"' + x + '"';
+            }
+        };
+
+    Object.prototype.toJSONString = function () {
+        return s.object(this);
+    };
+
+    Array.prototype.toJSONString = function () {
+        return s.array(this);
+    };
+})();
+
+String.prototype.parseJSON = function () {
+    try {
+        return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
+                this.replace(/"(\\.|[^"\\])*"/g, ''))) &&
+            eval('(' + this + ')');
+    } catch (e) {
+        return false;
+    }
+};

Added: trunk/MgDev/Doc/samples/javaviewersample/overview/overviewmain.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/overview/overviewmain.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/overview/overviewmain.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,63 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Resource - Welcome</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+</head>
+
+<body>
+
+<%
+    String platform = "TODO: retrieve Platform";
+%>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Overview<hr></td></tr>
+    <tr><td>
+        Welcome to the Sample Application.
+        
+        This sample demonstrates how to construct a
+        Viewer application using the Web Extensions APIs. The application is based on a subset
+        of the Sheboygan data set and shows how to:
+        
+        <ul>
+            <li>Connect to a Site and create a session.</li>
+            <li>Query feature data and work with geometry.</li>
+            <li>Change the view of a map from server-side script.</li>
+            <li>Read and manipulate XML based resources.</li>
+            <li>Store temporary resources within a session.</li>
+            <li>Plot a map as an EPlot DWF.</li>
+        </ul>
+    </td></tr>
+    <tr><td>Server Platform: <font color="#AA0000"><%= platform %></font></td></tr>
+</table>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/plot/plot.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/plot/plot.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/plot/plot.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,90 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+
+<%
+    // This script plots the current view of the map, optionally
+    // using the Scale parameter if Scale > 0.
+
+    String mgSessionId = request.getParameter("SESSION");
+
+    try
+    {
+        // Initialize the Web Extensions and connect to the Site using
+        // the session identifier stored in JSP session state.
+
+        InitializeWebTier();
+
+        MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+        MgSiteConnection siteConnection = new MgSiteConnection();
+        siteConnection.Open(userInfo);
+
+        // Create an instance of ResourceService and use that to open the
+        // current map instance stored in session state.
+
+        MgResourceService resourceService = (MgResourceService)siteConnection.CreateService(MgServiceType.ResourceService);
+        MgMap map = new MgMap();
+        map.Open(resourceService, "Sheboygan");
+
+        // Now create an instance of MappingService and use it to plot the
+        // current view of the map.
+
+        MgDwfVersion dwfVersion = new MgDwfVersion("6.01", "1.2");
+        MgPlotSpecification plotSpec = new MgPlotSpecification(8.5f, 11.0f, MgPageUnitsType.Inches, 0f, 0f, 0f, 0f);
+        plotSpec.SetMargins(0.5f, 0.5f, 0.5f, 0.5f);
+
+        MgMappingService mappingService = (MgMappingService)siteConnection.CreateService(MgServiceType.MappingService);
+
+        MgLayout layout = null;
+        String useLayout = request.getParameter("UseLayout");
+        if (useLayout != null && useLayout.equals("true"))
+        {
+            MgResourceIdentifier layoutRes = new MgResourceIdentifier("Library://Samples/Sheboygan/Layouts/SheboyganMap.PrintLayout");
+            layout = new MgLayout(layoutRes, "City of Sheboygan", MgPageUnitsType.Inches);
+        }
+
+        double scale = Double.parseDouble(request.getParameter("Scale"));
+        MgByteReader byteReader = null;
+        if (scale <= 0)
+        {
+            byteReader = mappingService.GeneratePlot(map, plotSpec, layout, dwfVersion);
+        }
+        else
+        {
+            MgCoordinate mapCenter = map.GetViewCenter().GetCoordinate();
+            byteReader = mappingService.GeneratePlot(map, mapCenter, scale, plotSpec, layout, dwfVersion);
+        }
+
+        // Now output the resulting DWF.
+
+        OutputReaderContent(response, byteReader);
+    }
+    catch (MgException e)
+    {
+        String result = e.GetMessage() + "<br><br>" + e.GetDetails();
+
+        response.setContentType("text/html");
+        response.setContentLength(result.length());
+        out.write(result);
+    }
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/plot/plotmain.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/plot/plotmain.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/plot/plotmain.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,170 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Plot Task</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+    
+    <script language="javascript">
+    function Submit()
+    {
+        var plotForm = document.getElementById("plotForm");
+        var scaleValue = document.getElementById("scaleValue");
+        var useLayoutValue = document.getElementById("useLayoutValue");
+        var useLayoutSelect = document.getElementById("useLayoutSelect");
+        if(useLayoutSelect.checked)
+            useLayoutValue.value = "true";
+        else
+            useLayoutValue.value = "false";
+    	
+    	scaleValue.value = "0";
+        plotForm.submit();	
+    }
+    function SubmitAtScale()
+    {
+        var plotForm = document.getElementById("plotForm");
+        var scaleValue = document.getElementById("scaleValue");
+        var scaleSelect = document.getElementById("scaleSelect");
+        var useLayoutValue = document.getElementById("useLayoutValue");
+        var useLayoutAtScale = document.getElementById("useLayoutAtScale");
+        if(useLayoutAtScale.checked)
+            useLayoutValue.value = "true";
+        else
+            useLayoutValue.value = "false";
+        
+        scaleValue.value = scaleSelect.value;
+        plotForm.submit();
+    }
+    </script>
+</head>
+
+<body>
+
+<%
+    // Display a couple of forms prompting the user to either
+    // plot the current view of the map, or the current view of
+    // the map at a specified scale. Submitting one of these forms
+    // opens a new window containing an EPlot DWF. The EPlot DWF
+    // is generated by the plot.jsp script.
+
+    String mgSessionId = request.getParameter("SESSION");
+    double currentScale = 0;
+    NumberFormat nf = NumberFormat.getInstance();
+    nf.setMaximumFractionDigits(3);
+    MgPoint viewCenter = null;
+    double viewScale = 0;
+
+    try
+    {
+        // Initialize the web-tier and connect to the Site using
+        // the session identifier stored in JSP session state.
+
+        InitializeWebTier();
+
+        MgUserInformation userInfo = new MgUserInformation(mgSessionId);
+        MgSiteConnection siteConnection = new MgSiteConnection();
+        siteConnection.Open(userInfo);
+
+        // Create a ResourcService object and use it to open the Map
+        // object from the sessions repository. Use the Map object to
+        // determine the current scale of the map for display on this
+        // page.
+
+        MgResourceService resourceService = (MgResourceService)siteConnection.CreateService(MgServiceType.ResourceService);
+        MgMap map = new MgMap();
+        map.Open(resourceService, "Sheboygan");
+
+        viewCenter = map.GetViewCenter();
+        viewScale = map.GetViewScale();
+    }
+    catch (MgException e)
+    {
+        out.write(e.GetMessage());
+        out.write(e.GetDetails());
+        return;
+    }
+%>
+
+<form id="plotForm" action="plot.jsp" method="get" target="_blank">
+    <input name="SESSION" type="hidden" value="<%= mgSessionId %>">
+    <input name="Scale" id="scaleValue" type="hidden" value="0">
+    <input name="UseLayout" id="useLayoutValue" type="hidden" value="false">
+</form>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Plot as DWF<hr></td></tr>
+    <tr><td class="SubTitle">Plot a View of the Map</td></tr>
+    <tr><td>View Center X:  <%= nf.format(viewCenter.GetCoordinate().GetX()) %></td></tr>
+    <tr><td>View Center Y:  <%= nf.format(viewCenter.GetCoordinate().GetY()) %></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td>View Scale:     1:<%= nf.format((int)viewScale) %><hr></td></tr>
+    
+    <tr><td class="SubTitle">Plot the Current Map View</td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="button" onClick="Submit()" value="Plot" style="width:60px">
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="checkbox" id="useLayoutSelect">&nbsp;Use Print Layout<hr>
+        </td>
+    </tr>
+    
+    <tr><td class="SubTitle">Plot at a Specified Scale</td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr>
+        <td>
+            Scale:
+            <select size="1" class="Ctrl" id="scaleSelect" style="width:80px">
+                <option value="1000">1:1,000</option>
+                <option value="8000">1:8,000</option>
+                <option value="20000">1:20,000</option>
+                <option value="25000">1:25,000</option>
+            </select>
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="button" onClick="SubmitAtScale()" value="Plot" style="width:60px">
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="checkbox" id="useLayoutAtScale">&nbsp;Use Print Layout
+        </td>
+    </tr>
+</table>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/query/classes/command.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/query/classes/command.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/query/classes/command.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,33 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+
+<%!
+    public class Command
+    {
+        public static final int GETLAYERPROPERTIES 	= 1;
+        public static final int TOGGLESPATIALFILTER 	= 2;
+        public static final int SHOWSPATIALFILTER 	= 3;
+        public static final int EXECUTEQUERY 		= 4;
+        public static final int GETSELECTIONXML 	= 5;
+    }
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/query/classes/feature.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/query/classes/feature.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/query/classes/feature.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,40 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+
+<%!
+    public class Feature
+    {
+        public String displayValue = null;
+        public double centerX = 0.0;
+        public double centerY = 0.0;
+        public Map idList = null;
+        
+        public Feature(String displayValue, MgPoint centerPoint, Map idList) throws MgException
+    	{
+    	    this.displayValue = displayValue;
+    	    this.centerX = centerPoint.GetCoordinate().GetX();
+    	    this.centerY = centerPoint.GetCoordinate().GetY();
+    	    this.idList = new HashMap(idList);
+    	}
+    }
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/query/classes/property.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/query/classes/property.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/query/classes/property.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,36 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+
+<%!
+    public class Property
+    {
+        public String name = null;
+        public boolean isString = false;
+        
+        public Property(String name, boolean isString)
+    	{
+    	    this.name = name;
+    	    this.isString = isString;
+    	}
+    }
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/query/classes/query.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/query/classes/query.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/query/classes/query.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,536 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ page import="org.json.*" %>
+<%@ include file ="property.jsp" %>
+<%@ include file ="feature.jsp" %>
+
+<%!
+    public class Query
+    {
+    	Map<String, String> args = null;
+    	private MgSiteConnection site = null;
+    	private String[] numOperators = null;
+    	private String[] numExpressions = null;
+    	private String[] strOperators = null;
+    	private String[] strExpressions = null;
+    	
+    	public Query(Map<String, String> incomingArgs) throws MgException
+    	{
+    	    this.args = incomingArgs;
+    	    this.site = new MgSiteConnection();
+    	    this.site.Open(new MgUserInformation(this.args.get("SESSION")));
+    	    this.numOperators = new String[] {"Equal to", "Not equal to", "Greater than", "Greater than or equal to", "Less than", "Less than or equal to"};
+    	    this.numExpressions = new String[] {" = %s", " != %s", " > %s", " >= %s", " < %s", " <= %s"};
+    	    this.strOperators = new String[] {"Begins with", "Contains", "Equal to"};
+    	    this.strExpressions = new String[] {" like '%s%%'", " like '%%%s%%'", " = '%s'"};
+    	}
+    	
+    	public String getNumOp()
+	{
+	    JSONArray jsonArray = new JSONArray();
+	    for(int i=0;i<6;i++)
+	    {
+		jsonArray.put(numOperators[i]);
+	    }
+	    return jsonArray.toString();
+	}
+
+	public String getStrOp()
+	{
+	    JSONArray jsonArray = new JSONArray();
+	    for(int i=0;i<3;i++)
+	    {
+		jsonArray.put(strOperators[i]);
+	    }
+	    return jsonArray.toString();
+	}
+        
+        public ArrayList<String> GetMapLayerNames() throws MgException
+	{
+	    MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+	    MgMap map = new MgMap();
+	    map.Open(resourceService, this.args.get("MAPNAME"));
+	    MgLayerCollection layers = map.GetLayers();
+	    ArrayList<String> layerNames = new ArrayList<String>();
+
+	    for(int i=0; i<layers.GetCount(); i++)
+	    {
+		MgLayer layer = (MgLayer) layers.GetItem(i);
+
+		//TODO: Exclue Raster and Drawing Layers???
+		
+		if(!layer.GetName().startsWith("_") && !layer.GetFeatureSourceId().toUpperCase().startsWith("SESSION"))
+		    layerNames.add(layer.GetLegendLabel());
+	    }
+	    Collections.sort(layerNames);
+
+	    return layerNames;
+        }
+        
+	public ArrayList<Property> GetLayerProperties() throws MgException
+        {
+            ArrayList<Property> properties = new ArrayList<Property>();
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            MgMap map = new MgMap();
+            map.Open(resourceService, this.args.get("MAPNAME"));
+            MgLayer layer = (MgLayer) map.GetLayers().GetItem(this.args.get("LAYERNAME"));
+
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            String[] schemaClass = layer.GetFeatureClassName().split(":");
+
+            MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+
+            for(int i=0; i<classDef.GetProperties().GetCount(); i++)
+            {
+                MgPropertyDefinition propertyDef = classDef.GetProperties().GetItem(i);
+
+                if(propertyDef.GetPropertyType() == MgFeaturePropertyType.DataProperty)
+                {
+                    MgDataPropertyDefinition propertyDataDef = (MgDataPropertyDefinition) propertyDef;
+                    int dataType = propertyDataDef.GetDataType();
+                    if(this.IsValidDataType(dataType))
+                    {
+                        properties.add(new Property(propertyDataDef.GetName(), dataType == MgPropertyType.String));
+                    }
+                }
+            }
+            return properties;
+        }
+        
+        public boolean ToggleSpatialFilter() throws MgException
+	{
+	    boolean result = true;
+	    MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+	    MgMap map = new MgMap();
+	    map.Open(resourceService, this.args.get("MAPNAME"));
+
+	    MgLayerCollection layers = map.GetLayers();
+	    if(layers.Contains("_QuerySpatialFilter"))
+	    {
+		MgLayer layer = (MgLayer) layers.GetItem("_QuerySpatialFilter");
+		if(this.args.get("VISIBLE").equals("true"))
+		    layer.SetVisible(true);
+		else
+		    layer.SetVisible(false);
+
+		map.Save(resourceService);
+	    }
+
+	    return result;
+        }
+
+	public boolean ShowSpatialFilter() throws MgException, FileNotFoundException, IOException
+	{
+	    boolean result = true;
+	    MgResourceIdentifier sdfResId = new MgResourceIdentifier("Session:"+this.args.get("SESSION")+"//Filter.FeatureSource");
+
+	    MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+	    MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+
+	    MgFeatureCommandCollection updateCommands = new MgFeatureCommandCollection();
+
+	    MgMap map = new MgMap();
+	    map.Open(resourceService, this.args.get("MAPNAME"));
+
+	    MgLayer layer = null;
+	    MgLayerCollection layers = map.GetLayers();
+	    if(layers.Contains("_QuerySpatialFilter"))
+	    {
+		layer = (MgLayer) layers.GetItem("_QuerySpatialFilter");
+		updateCommands.Add(new MgDeleteFeatures("Filter", "ID like '%'"));
+	    }
+	    else
+	    {
+		// Create the Feature Source (SDF)
+
+		MgFeatureSchema sdfSchema = this.CreateFilterSchema();
+		MgCreateSdfParams sdfParams = new MgCreateSdfParams("MAPCS", map.GetMapSRS(), sdfSchema);
+		featureService.CreateFeatureSource(sdfResId, sdfParams);
+
+		// Create the Layer
+
+		MgResourceIdentifier layerResId = new MgResourceIdentifier("Session:"+this.args.get("SESSION")+"//Filter.LayerDefinition");
+
+		String lineSep = System.getProperty("line.separator");
+		BufferedReader buffReader = new BufferedReader(new FileReader(GetQueryXmlTemplatePath()));
+		String nextLine = "";
+		StringBuffer strBuffer = new StringBuffer();
+		while((nextLine = buffReader.readLine()) != null)
+		{
+		    strBuffer.append(nextLine);
+		    strBuffer.append(lineSep);
+		}
+		String layerDefinition = strBuffer.toString();
+		layerDefinition = layerDefinition.replaceAll("%s", sdfResId.ToString());
+
+		MgByteSource byteSource = new MgByteSource(layerDefinition.getBytes(), layerDefinition.length());
+		resourceService.SetResource(layerResId, byteSource.GetReader(), null);
+
+		layer = new MgLayer(layerResId, resourceService);
+
+		layer.SetName("_QuerySpatialFilter");
+		layer.SetLegendLabel("_QuerySpatialFilter");
+		layer.SetDisplayInLegend(false);
+		layer.SetSelectable(false);
+
+		layers.Insert(0, layer);
+	    }
+
+	    // Make the layer visible
+
+	    layer.SetVisible(true);
+	    map.Save(resourceService);
+
+	    // Add the geometry to the filter feature source
+
+	    MgPolygon polygon = this.CreatePolygonFromGeomText(this.args.get("GEOMTEXT"));
+	    MgAgfReaderWriter agfWriter = new MgAgfReaderWriter();
+	    MgByteReader byteReader = agfWriter.Write(polygon);
+
+	    MgPropertyCollection propertyValues = new MgPropertyCollection();
+	    propertyValues.Add(new MgGeometryProperty("Geometry", byteReader));
+
+	    updateCommands.Add(new MgInsertFeatures("Filter", propertyValues));
+
+	    featureService.UpdateFeatures(sdfResId, updateCommands, false);
+
+	    return result;
+        }
+        
+        public ArrayList<Feature> Execute() throws MgException
+	{
+	    ArrayList<Feature> result = new ArrayList<Feature>();
+	    MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+
+	    MgMap map = new MgMap();
+	    map.Open(resourceService, this.args.get("MAPNAME"));
+	    MgLayer layer = (MgLayer) map.GetLayers().GetItem(this.args.get("LAYERNAME"));
+
+	    MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+	    MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+	    String featureClass = layer.GetFeatureClassName();
+	    String featureGeometry = layer.GetFeatureGeometryName();
+
+	    // Initialize the coordinate system transform
+
+	    String[] schemaClass = layer.GetFeatureClassName().split(":");
+	    MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+	    MgGeometricPropertyDefinition geomProp = (MgGeometricPropertyDefinition) classDef.GetProperties().GetItem(featureGeometry);
+	    String spatialContext = geomProp.GetSpatialContextAssociation();
+
+	    MgCoordinateSystemTransform csTransform = null;
+	    MgCoordinateSystemTransform csInverseTransform = null;
+	    MgCoordinateSystemFactory coordSysFactory = new MgCoordinateSystemFactory();
+
+	    MgSpatialContextReader scReader = featureService.GetSpatialContexts(resId, false);
+	    while(scReader.ReadNext() && csTransform==null)
+	    {
+		if(spatialContext.equals(scReader.GetName()))
+		{
+		    MgCoordinateSystem source = coordSysFactory.Create(scReader.GetCoordinateSystemWkt());
+		    MgCoordinateSystem target = coordSysFactory.Create(map.GetMapSRS());
+		    csTransform = coordSysFactory.GetTransform(source, target);
+		    csInverseTransform = coordSysFactory.GetTransform(target, source);
+		}
+	    }
+	    scReader.Close();
+
+	    // Execute the query
+
+	    int queryMax = Integer.parseInt(this.args.get("QUERYMAX").trim());
+	    MgFeatureQueryOptions queryOptions = new MgFeatureQueryOptions();
+
+	    if(this.args.get("USEPROPERTYFILTER").equals("true"))
+	    {
+		String propertyFilter = this.args.get("PROPERTYNAME");
+		int operator = Integer.valueOf(this.args.get("OPERATOR"));
+		int count = 0;
+		if(this.args.get("ISSTRING").equals("true"))
+		{
+		    propertyFilter = propertyFilter + this.strExpressions[operator].replaceAll("%s", this.args.get("VALUE"));
+		}
+		else
+		{
+		    propertyFilter = propertyFilter + this.numExpressions[operator].replaceAll("%s", this.args.get("VALUE"));
+		}
+		queryOptions.SetFilter(propertyFilter);
+	    }
+
+	    if(this.args.get("USESPATIALFILTER").equals("true"))
+	    {
+		MgPolygon polygon = this.CreatePolygonFromGeomText(this.args.get("GEOMTEXT"));
+		MgGeometry geometry = (MgGeometry) polygon.Transform(csInverseTransform);
+		queryOptions.SetSpatialFilter(featureGeometry, geometry, MgFeatureSpatialOperations.Intersects);
+	    }
+
+	    int count = 0;
+	    MgAgfReaderWriter geometryReaderWriter = new MgAgfReaderWriter();
+	    MgFeatureReader featureReader = featureService.SelectFeatures(resId, layer.GetFeatureClassName(), queryOptions);
+	    String displayValue = null;
+	    while(featureReader.ReadNext() && (queryMax <= 0 || count < queryMax))
+	    {
+		MgByteReader byteReader = featureReader.GetGeometry(featureGeometry);
+		MgGeometry geometry = geometryReaderWriter.Read(byteReader);
+		MgPoint centerPoint = geometry.GetCentroid();
+		centerPoint = (MgPoint) centerPoint.Transform(csTransform);
+
+		Map idList = new HashMap(this.GetFeatureIdList(featureReader));
+		
+		int propertyType = featureReader.GetPropertyType(this.args.get("OUTPUTPROPERTY"));
+		switch(propertyType)
+		{
+		    case MgPropertyType.Boolean :
+			displayValue = String.valueOf(featureReader.GetBoolean(this.args.get("OUTPUTPROPERTY")));
+			break;
+		    case MgPropertyType.Byte :
+			displayValue = String.valueOf(featureReader.GetByte(this.args.get("OUTPUTPROPERTY")));
+			break;
+		    case MgPropertyType.Single :
+			displayValue = String.valueOf(featureReader.GetSingle(this.args.get("OUTPUTPROPERTY")));
+			break;
+		    case MgPropertyType.Double :
+			displayValue = String.valueOf(featureReader.GetDouble(this.args.get("OUTPUTPROPERTY")));
+			break;
+		    case MgPropertyType.Int16 :
+			displayValue = String.valueOf(featureReader.GetInt16(this.args.get("OUTPUTPROPERTY")));
+			break;
+		    case MgPropertyType.Int32 :
+			displayValue = String.valueOf(featureReader.GetInt32(this.args.get("OUTPUTPROPERTY")));
+			break;
+		    case MgPropertyType.Int64 :
+			displayValue = String.valueOf(featureReader.GetInt64(this.args.get("OUTPUTPROPERTY")));
+			break;
+		    case MgPropertyType.String :
+			displayValue = featureReader.GetString(this.args.get("OUTPUTPROPERTY"));
+			break;
+		    case MgPropertyType.DateTime :
+		    case MgPropertyType.Null :
+		    case MgPropertyType.Blob :
+		    case MgPropertyType.Clob :
+		    case MgPropertyType.Feature :
+		    case MgPropertyType.Geometry :
+		    case MgPropertyType.Raster :
+			displayValue = "[unsupported data type]";
+			break;
+		}
+		result.add(new Feature(displayValue, centerPoint, idList));
+		count++;
+	    }
+
+	    return result;
+        }
+
+	public String GetSelectionXML() throws MgException, JSONException
+	{
+	    MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+	    MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+
+	    MgMap map = new MgMap();
+	    map.Open(resourceService, this.args.get("MAPNAME"));
+	    MgLayer layer = (MgLayer) map.GetLayers().GetItem(this.args.get("LAYERNAME"));
+	    MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+	    String featureClass = layer.GetFeatureClassName();
+
+	    String[] schemaClass = layer.GetFeatureClassName().split(":");
+	    MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+
+	    MgPropertyCollection properties = new MgPropertyCollection();
+	    MgDataPropertyDefinition dataPropDef = null;
+	    JSONObject json = new JSONObject(this.args.get("IDLIST"));
+
+	    Iterator it = json.keys();
+	    while(it.hasNext())
+	    {
+		String key = (String) it.next();
+		Object value = json.get(key);
+		dataPropDef = (MgDataPropertyDefinition) classDef.GetProperties().GetItem(key);
+		switch(dataPropDef.GetDataType())
+		{
+		    case MgPropertyType.Boolean :
+			properties.Add(new MgBooleanProperty(key, Boolean.valueOf(value.toString())));
+			break;
+		    case MgPropertyType.Byte :
+			properties.Add(new MgByteProperty(key, Byte.valueOf(value.toString())));
+			break;
+		    case MgPropertyType.Single :
+			properties.Add(new MgSingleProperty(key, Float.valueOf(value.toString())));
+			break;
+		    case MgPropertyType.Double :
+			properties.Add(new MgDoubleProperty(key, Double.valueOf(value.toString())));
+			break;
+		    case MgPropertyType.Int16 :
+			properties.Add(new MgInt16Property(key, Short.valueOf(value.toString())));
+			break;
+		    case MgPropertyType.Int32 :
+			properties.Add(new MgInt32Property(key, Integer.valueOf(value.toString())));
+			break;
+		    case MgPropertyType.Int64 :
+			properties.Add(new MgInt64Property(key, Long.valueOf(value.toString())));
+			break;
+		    case MgPropertyType.String :
+			properties.Add(new MgStringProperty(key, value.toString()));
+			break;
+		    case MgPropertyType.DateTime :
+		    case MgPropertyType.Null :
+		    case MgPropertyType.Blob :
+		    case MgPropertyType.Clob :
+		    case MgPropertyType.Feature :
+		    case MgPropertyType.Geometry :
+		    case MgPropertyType.Raster :
+			break;
+		}
+	    }
+
+	    MgSelection selection = new MgSelection(map);
+	    selection.AddFeatureIds(layer, featureClass, properties);
+
+	    return selection.ToXml();
+        }
+        
+        private Map GetFeatureIdList(MgFeatureReader featureReader) throws MgException
+	{
+	    MgClassDefinition classDef = featureReader.GetClassDefinition();
+	    MgPropertyDefinitionCollection idProps = classDef.GetIdentityProperties();
+	    Map idList = new HashMap();
+
+	    for(int i=0; i<idProps.GetCount(); i++)
+	    {
+		MgDataPropertyDefinition idProp = (MgDataPropertyDefinition) idProps.GetItem(i);
+
+		switch(idProp.GetDataType())
+		{
+		    case MgPropertyType.Boolean :
+			idList.put(idProp.GetName(), featureReader.GetBoolean(idProp.GetName()));
+			break;
+		    case MgPropertyType.Byte :
+			idList.put(idProp.GetName(), featureReader.GetByte(idProp.GetName()));
+			break;
+		    case MgPropertyType.Single :
+			idList.put(idProp.GetName(), featureReader.GetSingle(idProp.GetName()));
+			break;
+		    case MgPropertyType.Double :
+			idList.put(idProp.GetName(), featureReader.GetDouble(idProp.GetName()));
+			break;
+		    case MgPropertyType.Int16 :
+			idList.put(idProp.GetName(), featureReader.GetInt16(idProp.GetName()));
+			break;
+		    case MgPropertyType.Int32 :
+			idList.put(idProp.GetName(), featureReader.GetInt32(idProp.GetName()));
+			break;
+		    case MgPropertyType.Int64 :
+			idList.put(idProp.GetName(), featureReader.GetInt64(idProp.GetName()));
+			break;
+		    case MgPropertyType.String :
+			idList.put(idProp.GetName(), featureReader.GetString(idProp.GetName()));
+			break;
+		    case MgPropertyType.DateTime :
+			idList.put(idProp.GetName(), featureReader.GetDateTime(idProp.GetName()));
+			break;
+		    case MgPropertyType.Null :
+		    case MgPropertyType.Blob :
+		    case MgPropertyType.Clob :
+		    case MgPropertyType.Feature :
+		    case MgPropertyType.Geometry :
+		    case MgPropertyType.Raster :
+			break;
+		}
+	    }
+
+	    return idList;
+        }
+        
+        private boolean IsValidDataType(int type)
+	{
+	    boolean valid = true;
+
+	    switch(type)
+	    {
+		case MgPropertyType.Blob:
+		case MgPropertyType.Clob:
+		case MgPropertyType.Byte:
+		case MgPropertyType.Feature:
+		case MgPropertyType.Geometry:
+		case MgPropertyType.Null:
+		    valid = false;
+		    break;
+	    }
+
+	    return valid;
+        }
+        
+        private MgFeatureSchema CreateFilterSchema() throws MgException
+	{
+	    MgFeatureSchema filterSchema = new MgFeatureSchema();
+	    filterSchema.SetName("FilterSchema");
+
+	    MgClassDefinition filterClass = new MgClassDefinition();
+	    filterClass.SetName("Filter");
+	    MgPropertyDefinitionCollection properties = filterClass.GetProperties();
+
+	    MgDataPropertyDefinition idProperty = new MgDataPropertyDefinition("ID");
+	    idProperty.SetDataType(MgPropertyType.Int32);
+	    idProperty.SetReadOnly(true);
+	    idProperty.SetNullable(false);
+	    idProperty.SetAutoGeneration(true);
+	    properties.Add(idProperty);
+
+	    MgGeometricPropertyDefinition geometryProperty = new MgGeometricPropertyDefinition("Geometry");
+	    geometryProperty.SetGeometryTypes(MgFeatureGeometricType.Surface);
+	    geometryProperty.SetHasElevation(false);
+	    geometryProperty.SetHasMeasure(false);
+	    geometryProperty.SetReadOnly(false);
+	    geometryProperty.SetSpatialContextAssociation("MAPCS");
+	    properties.Add(geometryProperty);
+
+	    filterClass.GetIdentityProperties().Add(idProperty);
+	    filterClass.SetDefaultGeometryPropertyName("Geometry");
+
+	    filterSchema.GetClasses().Add(filterClass);
+
+	    return filterSchema;
+        }
+        
+        private MgPolygon CreatePolygonFromGeomText(String geomText) throws MgException
+	{
+	    MgGeometryFactory geometryFactory = new MgGeometryFactory();
+
+	    String[] vertices = geomText.split(",");
+	    int count = Integer.valueOf(vertices[0]);
+
+	    MgCoordinateCollection coords = new MgCoordinateCollection();
+	    for(int i=0; i<count; i++)
+	    {
+		MgCoordinate coord = geometryFactory.CreateCoordinateXY(Double.valueOf(vertices[(i*2)+1]), Double.valueOf(vertices[(i*2)+2]));
+		coords.Add(coord);
+	    }
+
+	    MgLinearRing linearRing = geometryFactory.CreateLinearRing(coords);
+	    MgPolygon polygon = geometryFactory.CreatePolygon(linearRing, null);
+
+	    return polygon;
+        }
+
+    }
+
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/query/querycontroller.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/query/querycontroller.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/query/querycontroller.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,95 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ page import="org.json.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+<%@ include file ="classes/query.jsp" %>
+<%@ include file ="classes/command.jsp" %>
+
+<%
+    Map<String, String> args = new HashMap<String, String>();
+
+    Enumeration paramNames = request.getParameterNames();
+    while(paramNames.hasMoreElements())
+    {
+        String paramName = (String)paramNames.nextElement();
+        String paramValue = request.getParameter(paramName);
+        args.put(paramName, paramValue);
+    }
+
+    InitializeWebTier();
+
+    Query query = new Query(args);
+    JSONArray json = new JSONArray();
+    JSONObject jsonObj = new JSONObject();
+    String responseType = "";
+    String responseString = "";
+
+    if(args.get("COMMAND") != null)
+    {
+        int cmd = Integer.valueOf(args.get("COMMAND"));
+        switch (cmd)
+        {
+            case Command.GETLAYERPROPERTIES:
+                responseType = "text/plain";
+                ArrayList<Property> arrayList = query.GetLayerProperties();
+                for(int i=0;i<arrayList.size();i++)
+                {
+                    jsonObj.put("name", arrayList.get(i).name);
+                    jsonObj.put("isString", arrayList.get(i).isString);
+                    json.put(i, jsonObj.toString());
+                }
+                responseString = json.toString();
+                break;
+            case Command.TOGGLESPATIALFILTER:
+                responseType = "text/plain";
+                responseString = json.put(query.ToggleSpatialFilter()).toString();
+                break;
+            case Command.SHOWSPATIALFILTER:
+                responseType = "text/plain";
+                responseString = json.put(query.ShowSpatialFilter()).toString();
+                break;
+            case Command.EXECUTEQUERY:
+                responseType = "text/plain";
+		ArrayList<Feature> resultList = query.Execute();
+		for(int i=0;i<resultList.size();i++)
+		{
+		    jsonObj.put("displayValue", resultList.get(i).displayValue);
+		    jsonObj.put("centerX", resultList.get(i).centerX);
+		    jsonObj.put("centerY", resultList.get(i).centerY);
+		    jsonObj.put("idList", resultList.get(i).idList);
+		    json.put(i, jsonObj.toString());
+		}
+		responseString = json.toString();
+                break;
+            case Command.GETSELECTIONXML:
+                responseType = "text/xml";
+                responseString = query.GetSelectionXML();
+                break;
+        }
+    }
+    
+    response.setContentType(responseType);
+
+    out.print(responseString);
+    out.flush();
+%>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/javaviewersample/query/querymain.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/query/querymain.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/query/querymain.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,492 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+<%@ include file ="classes/query.jsp" %>
+<%@ include file ="classes/command.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<%
+    String errorMsg = null;
+    String errorDetail = null;
+    Map<String, String> args = new HashMap<String, String>();
+    Query query = null;
+    ArrayList<String> layerNames = null;
+    
+    Enumeration paramNames = request.getParameterNames();
+    while(paramNames.hasMoreElements())
+    {
+        String paramName = (String)paramNames.nextElement();
+        String paramValue = request.getParameter(paramName);
+        args.put(paramName, paramValue);
+    }
+    
+    try
+    {
+        InitializeWebTier();
+    
+        query = new Query(args);
+        
+        layerNames = query.GetMapLayerNames();
+    }
+    catch (MgException e)
+    {
+        errorMsg = e.GetMessage();
+        errorDetail = e.GetDetails();
+    }
+%>
+<html>
+<head>
+    <title>Query Features</title>
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+    <script language="javascript" src="../../viewerfiles/browserdetect.js"></script>
+    <script language="javascript" src="../json.js"></script>
+
+    <script language="javascript">
+        
+        var READY_STATE_UNINITIALIZED 	= 0;
+        var READY_STATE_LOADING 	= 1;
+        var READY_STATE_LOADED 		= 2;
+        var READY_STATE_INTERACTIVE 	= 3;
+        var READY_STATE_COMPLETE 	= 4;
+
+        var NOT_BUSY_IMAGE = "../images/loader_inactive.gif";
+        var BUSY_IMAGE = "../images/loader_pulse.gif";
+
+        var session = "<%= args.get("SESSION") %>";
+        var mapName = "<%= args.get("MAPNAME") %>";
+
+        var strOps = <%= query.getStrOp() %>;
+        var numOps = <%= query.getNumOp() %>;
+        var queryReqHandler = null;
+        var spatialFilterGeomText = null;
+        var properties = null;
+        var results;
+
+        function OnLayerChange()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var propertySelect = document.getElementById("propertySelect");
+            var outputSelect = document.getElementById("outputSelect");
+
+            reqParams = "COMMAND=<%=Command.GETLAYERPROPERTIES%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "querycontroller.jsp", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            reqHandler.send(reqParams);
+            properties = reqHandler.responseText.parseJSON();
+
+            for(var i = 0; i < properties.length; i++)
+            {
+                properties[i] = properties[i].parseJSON();
+            }
+
+            propertySelect.options.length = 0;
+            outputSelect.options.length = 0;
+            for (var i = 0; i < properties.length; i++)
+            {
+                propertySelect.options[i] = new Option(properties[i].name, i, false, false);
+                outputSelect.options[i] = new Option(properties[i].name, i, false, false);
+            }
+            OnPropertyChange();
+        }
+
+        function OnPropertyChange()
+        {
+            var propertySelect = document.getElementById("propertySelect");
+            var operatorSelect = document.getElementById("operatorSelect");
+
+            operatorSelect.options.length = 0;
+            if (propertySelect.selectedIndex >= 0)
+            {
+                var ops = null;
+                if (properties[propertySelect.value].isString)
+                    ops = strOps;
+                else
+                    ops = numOps;
+
+                for (var i = 0; i < ops.length; i++)
+                {
+                    operatorSelect.options[i] = new Option(ops[i], i, false, false);
+                }
+            }
+
+        }
+
+        function OnToggleSpatialFilter()
+        {
+            if (spatialFilterGeomText != null)
+            {
+                ToggleSpatialFilter(document.getElementById("spatialFilter").checked);
+            }
+        }
+
+        function OnDigitizeRectangle()
+        {
+            parent.parent.mapFrame.DigitizeRectangle(OnRectangleDigitized);
+        }
+
+        function OnRectangleDigitized(rectangle)
+        {
+            var geomText = "5,"
+            + rectangle.Point1.X + "," + rectangle.Point1.Y + ","
+            + rectangle.Point2.X + "," + rectangle.Point1.Y + ","
+            + rectangle.Point2.X + "," + rectangle.Point2.Y + ","
+            + rectangle.Point1.X + "," + rectangle.Point2.Y + ","
+            + rectangle.Point1.X + "," + rectangle.Point1.Y;
+
+            ShowSpatialFilter(geomText);
+        }
+
+        function OnDigitizePolygon()
+        {
+            parent.parent.mapFrame.DigitizePolygon(OnPolyonDigitized);
+        }
+
+        function OnPolyonDigitized(polygon)
+        {
+            var geomText = polygon.Count;
+            for (var i = 0; i < polygon.Count; i++)
+            {
+                geomText += "," + polygon.Point(i).X + "," + polygon.Point(i).Y;
+            }
+
+            ShowSpatialFilter(geomText);
+        }
+
+        function OnClearSpatialFilter()
+        {
+            document.getElementById("spatialFilter").checked = false;
+            OnToggleSpatialFilter();
+
+            spatialFilterGeomText = null;
+        }
+
+        function ShowSpatialFilter(geomText)
+        {
+            reqParams = "COMMAND=<%=Command.SHOWSPATIALFILTER%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&GEOMTEXT=" + encodeURIComponent(geomText);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            if (msie)
+                reqHandler.open("POST", "querycontroller.jsp", false);
+            else
+                reqHandler.open("POST", "../javaviewersample/query/querycontroller.jsp", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+            reqHandler.send(reqParams);
+
+            spatialFilterGeomText = geomText;
+            document.getElementById("spatialFilter").checked = true;
+            parent.parent.Refresh();
+        }
+
+        function ToggleSpatialFilter(visible)
+        {
+            reqParams = "COMMAND=<%=Command.TOGGLESPATIALFILTER%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&VISIBLE=" + encodeURIComponent(visible);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "querycontroller.jsp", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+            reqHandler.send(reqParams);
+
+            parent.parent.Refresh();
+        }
+
+        function ExecuteQuery()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            
+            reqParams = "COMMAND=<%=Command.EXECUTEQUERY%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+
+            if (document.getElementById("propertyFilter").checked)
+            {
+                reqParams += "&USEPROPERTYFILTER=true";
+                property = properties[document.getElementById("propertySelect").value];
+                reqParams += "&PROPERTYNAME=" + encodeURIComponent(property.name);
+                reqParams += "&ISSTRING=" + encodeURIComponent(property.isString);
+                reqParams += "&OPERATOR=" + encodeURIComponent(document.getElementById("operatorSelect").value);
+                reqParams += "&VALUE=" + encodeURIComponent(document.getElementById("valueInput").value);
+            }
+            else
+            {
+                reqParams += "&USEPROPERTYFILTER=false";
+            }
+
+            if (document.getElementById("spatialFilter").checked && spatialFilterGeomText != null)
+            {
+                reqParams += "&USESPATIALFILTER=true";
+                reqParams += "&GEOMTEXT=" + encodeURIComponent(spatialFilterGeomText);
+            }
+            else
+            {
+                reqParams += "&USESPATIALFILTER=false";
+            }
+
+            reqParams += "&OUTPUTPROPERTY=" + encodeURIComponent(properties[document.getElementById("outputSelect").value].name);
+            reqParams += "&QUERYMAX=" + encodeURIComponent(document.getElementById("queryMax").value);
+
+            if (msie)
+                queryReqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                queryReqHandler = new XMLHttpRequest();
+
+            queryReqHandler.onreadystatechange = OnReadyStateChange;
+            queryReqHandler.open("POST", "querycontroller.jsp", true);
+            queryReqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            document.getElementById("executeBtn").disabled = true;
+            document.getElementById("busyImg").src = BUSY_IMAGE;
+
+            queryReqHandler.send(reqParams);
+        }
+
+        function SelectFeature()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var resultSelect = document.getElementById("resultSelect");
+
+            reqParams = "COMMAND=<%=Command.GETSELECTIONXML%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+            reqParams += "&IDLIST=" + results[resultSelect.value].idList.toJSONString();
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "querycontroller.jsp", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+            reqHandler.send(reqParams);
+            selectionXml = reqHandler.responseText;
+
+            parent.parent.mapFrame.SetSelectionXML(TrimString(selectionXml));
+        }
+        
+        function TrimString(responseString)
+        {
+            responseString = responseString.replace( /^\s+/g, "" );
+            return responseString.replace( /\s+$/g, "" );
+        }
+
+        function ZoomToFeature()
+        {
+            var resultSelect = document.getElementById("resultSelect");
+            var scaleInput = document.getElementById("scaleInput");
+            scale = scaleInput.value;
+            scale = ((scale == 0)? 10000 : scale);
+            scale = parseFloat(scale + String(".0"));
+
+            feature = results[resultSelect.value];
+            parent.parent.mapFrame.ZoomToView(feature.centerX, feature.centerY, scale, true);
+        }
+
+        function OnReadyStateChange()
+        {
+            var ready = queryReqHandler.readyState;
+
+            if (ready == READY_STATE_COMPLETE)
+            {
+                results = queryReqHandler.responseText.parseJSON();
+                for(var i = 0; i < results.length; i++)
+                {
+                    results[i] = results[i].parseJSON();
+                }
+                var resultSelect = document.getElementById("resultSelect");
+                resultSelect.options.length = 0;
+                for (var i = 0; i < results.length; i++)
+                {
+                    resultSelect.options[i] = new Option(results[i].displayValue, i, false, false);
+                }
+                OnResultChange();
+
+                document.getElementById("executeBtn").disabled = false;
+                document.getElementById("busyImg").src = NOT_BUSY_IMAGE;
+                queryReqHandler = null;
+            }
+        }
+
+        function OnResultChange()
+        {
+            var resultSelect = document.getElementById("resultSelect");
+            var scaleInput = document.getElementById("scaleInput");
+            var zoomBtn = document.getElementById("zoomBtn");
+            var selectBtn = document.getElementById("selectBtn");
+
+            if (resultSelect.selectedIndex >= 0)
+            {
+                scaleInput.disabled = false;
+                zoomBtn.disabled = false;
+                selectBtn.disabled = false;
+            }
+            else
+            {
+                scaleInput.disabled = true;
+                zoomBtn.disabled = true;
+                selectBtn.disabled = true;
+            }
+        }
+
+        function OnLoad()
+        {
+            OnLayerChange();
+            OnResultChange();
+        }
+
+        function OnUnload()
+        {
+            ToggleSpatialFilter(false);
+        }
+
+    </script>
+
+</head>
+
+<body onLoad="OnLoad()" onUnload="OnUnload()" marginwidth=5 marginheight=5 leftmargin=5 topmargin=5 bottommargin=5 rightmargin=5>
+
+<% if(errorMsg==null) {%>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title"><img id="busyImg" src="../images/loader_inactive.gif" style="vertical-align:bottom">&nbsp;Query Features<hr></td></tr>
+    <tr><td class="SubTitle">Select a Layer</td></tr>
+    <tr><td>Layer:</td></tr>
+    <tr>
+        <td class="RegText">
+        <select size="1" class="Ctrl" id="layerSelect" onChange="OnLayerChange()" style="width: 100%">
+            <%
+            String selected = "selected";
+            for(int i=0; i<layerNames.size(); i++) {
+            %>
+            <option value="<%= layerNames.get(i) %>" <%=selected %> ><%= layerNames.get(i) %></option>
+            <%
+                selected = "";
+            }
+            %>
+        </select>
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td class="SubTitle"><input class="Ctrl" type="checkbox" id="propertyFilter" checked>&nbsp;Property Filter</td></tr>
+    <tr><td>Property:</td></tr>
+    <tr>
+        <td class="RegText">
+            <select size="1" class="Ctrl" id="propertySelect" onChange="OnPropertyChange()" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td>Operator:</td></tr>
+    <tr>
+        <td class="RegText">
+            <select size="1" class="Ctrl" id="operatorSelect" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td>Value:</td></tr>
+    <tr>
+        <td class="RegText">
+            <input maxlength="100" class="Ctrl" id="valueInput" style="width: 100%">
+        </td>
+	</tr>
+    <tr><td class="Spacer"></td></tr>
+	<tr><td class="SubTitle"><input class="Ctrl" type="checkbox" onChange="OnToggleSpatialFilter()" id="spatialFilter">&nbsp;Spatial Filter</td></tr>
+    <tr><td>Digitize:</td></tr>
+    <tr>
+        <td align="center">
+            <input type="button" name="" value="Rectangle" class="Ctrl" id="rectButton" onClick="OnDigitizeRectangle()" style="width: 30%">
+            <input type="button" name="" value="Polygon" class="Ctrl" id="polyButtton" onClick="OnDigitizePolygon()" style="width: 30%">
+            <input type="button" name="" value="Clear" class="Ctrl" id="clearButton" onClick="OnClearSpatialFilter()" style="width: 30%">
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td class="SubTitle">Output</td></tr>
+    <tr><td>Output property:</td></tr>
+    <tr>
+        <td class="RegText">
+            <select size="1" class="Ctrl" id="outputSelect" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td><hr></td></tr>
+    <tr>
+        <td>
+            <input id="executeBtn" class="Ctrl" name="" type="button" onClick="ExecuteQuery()" value="Execute" style="width:60px">
+            &nbsp;&nbsp;Max results:&nbsp;
+            <input name="" id="queryMax" class="Ctrl" type="text" value="100" size="5">
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td class="SubTitle">Results</td></tr>
+    <tr>
+        <td>
+            <select class="Ctrl" id="resultSelect" size="15" onChange="OnResultChange()" style="width: 100%"></select>
+        </td>
+    </tr>
+    <tr>
+        <td>	
+            Scale:&nbsp;<input class="Ctrl" id="scaleInput" type="text" size="6" value="10000">
+            <input class="Ctrl" id="zoomBtn" type="button" onClick="ZoomToFeature()" value="Zoom" style="width:60px">
+            <input class="Ctrl" id="selectBtn" type="button" onClick="SelectFeature()" value="Select" style="width:60px">
+        </td>
+    </tr>
+
+</table>
+
+<% } else { %>
+
+<table class="RegText" border="0" cellspacing="0" width="100%%">
+    <tr><td class="Title">Error<hr></td></tr>
+    <tr><td><% System.out.println(errorMsg); %></td></tr>
+    <tr><td><% System.out.println(errorDetail); %></td></tr>
+</table>
+
+<% } %>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/query/templates/filterlayerdefinition.xml
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/query/templates/filterlayerdefinition.xml	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/query/templates/filterlayerdefinition.xml	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<LayerDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="LayerDefinition-1.0.0.xsd" version="1.0.0">
+  <VectorLayerDefinition>
+    <ResourceId>%s</ResourceId>
+    <FeatureName>FilterSchema:Filter</FeatureName>
+    <FeatureNameType>FeatureClass</FeatureNameType>
+    <Geometry>Geometry</Geometry>
+    <VectorScaleRange>
+      <AreaTypeStyle>
+        <AreaRule>
+          <LegendLabel></LegendLabel>
+          <AreaSymbolization2D>
+            <Fill>
+              <FillPattern>Solid</FillPattern>
+              <ForegroundColor>40FF0000</ForegroundColor>
+              <BackgroundColor>FF000000</BackgroundColor>
+            </Fill>
+            <Stroke>
+              <LineStyle>Solid</LineStyle>
+              <Thickness>0</Thickness>
+              <Color>FFFF0000</Color>
+              <Unit>Inches</Unit>
+            </Stroke>
+          </AreaSymbolization2D>
+        </AreaRule>
+      </AreaTypeStyle>
+    </VectorScaleRange>
+  </VectorLayerDefinition>
+</LayerDefinition>

Added: trunk/MgDev/Doc/samples/javaviewersample/styles/gt.css
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/styles/gt.css	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/styles/gt.css	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,43 @@
+td.Title
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-weight: bold;
+	font-size: 13pt;
+}
+td.SubTitle
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-weight: bold;
+	font-size: 8pt;
+	background-color: #DCDCDC;
+	color: black;
+	height: 20px;
+}
+td.Spacer
+{
+    height: 4px;
+}
+.Swatch
+{
+	border: black 1px solid;
+	height: 16px;
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 10pt;
+}
+td.InfoText
+{
+	background-color: #FFFFCC;
+	color: #666666;
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}
+.RegText
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}
+.Ctrl
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}

Added: trunk/MgDev/Doc/samples/javaviewersample/theme/classes/command.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/theme/classes/command.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/theme/classes/command.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,31 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+
+<%!
+    public class Command
+    {
+        public static final int GETLAYERINFO 		= 1;
+        public static final int GETPROPERTYMINMAXCOUNT 	= 2;
+        public static final int APPLYTHEME 		= 3;
+    }
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/theme/classes/layerinfo.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/theme/classes/layerinfo.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/theme/classes/layerinfo.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,36 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+
+<%!
+    public class LayerInfo
+    {
+        public ArrayList<Property> properties = null;
+        public ArrayList<String> scaleRanges = null;
+        
+        public LayerInfo(ArrayList<Property> properties, ArrayList<String> scaleRanges)
+    	{
+    	    this.properties = new ArrayList(properties);
+    	    this.scaleRanges = new ArrayList(scaleRanges);
+    	}
+    }
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/theme/classes/property.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/theme/classes/property.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/theme/classes/property.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,38 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+
+<%!
+    public class Property
+    {
+        public String name = null;
+        public int dataType = 0;
+        public ArrayList<Integer> distroTypes = null;
+        
+        public Property(String name, int dataType, ArrayList<Integer> distroTypes)
+    	{
+    	    this.name = name;
+    	    this.dataType = dataType;
+    	    this.distroTypes = new ArrayList<Integer>(distroTypes);
+    	}
+    }
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/theme/classes/theme.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/theme/classes/theme.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/theme/classes/theme.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,536 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ page import="javax.xml.parsers.*" %>
+<%@ page import="javax.xml.transform.*" %>
+<%@ page import="javax.xml.transform.dom.*" %>
+<%@ page import="javax.xml.transform.stream.*" %>
+<%@ page import="org.w3c.dom.*" %>
+<%@ page import="org.xml.sax.*" %>
+<%@ page import="org.json.*" %>
+<%@ include file ="property.jsp" %>
+<%@ include file ="layerinfo.jsp" %>
+
+<%!
+    public class Theme
+    {
+    	Map<String, String> args = null;
+    	private MgSiteConnection site = null;
+    	private String[] distNameArray = null;
+    	private String[] distValueArray = null;
+    	
+    	public Theme(Map<String, String> incomingArgs) throws MgException
+    	{
+    	    this.args = incomingArgs;
+    	    this.site = new MgSiteConnection();
+    	    this.site.Open(new MgUserInformation(this.args.get("SESSION")));
+    	    this.distNameArray = new String[] {"Individual", "Equal", "Standard Deviation", "Quantile", "Jenks (Natural Breaks)"};
+    	    this.distValueArray = new String[] {"INDIV_DIST", "EQUAL_DIST", "STDEV_DIST", "QUANT_DIST", "JENK_DIST"};
+    	}
+    	
+    	public String getNameArray()
+	{
+	    JSONArray jsonArray = new JSONArray();
+	    for(int i=0;i<5;i++)
+	    {
+		jsonArray.put(distNameArray[i]);
+	    }
+	    return jsonArray.toString();
+	}
+
+	public String getValueArray()
+	{
+	    JSONArray jsonArray = new JSONArray();
+	    for(int i=0;i<5;i++)
+	    {
+		jsonArray.put(distValueArray[i]);
+	    }
+	    return jsonArray.toString();
+	}
+        
+        public ArrayList<String> GetMapLayerNames() throws MgException
+	{
+	    MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+	    MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+	    
+	    MgMap map = new MgMap();
+	    map.Open(resourceService, this.args.get("MAPNAME"));
+	    MgLayerCollection layers = map.GetLayers();
+	    ArrayList<String> layerNames = new ArrayList<String>();
+
+	    for(int i=0; i<layers.GetCount(); i++)
+	    {
+		MgLayer layer = (MgLayer) layers.GetItem(i);
+		if(!layer.GetName().startsWith("_") && !layer.GetFeatureSourceId().toUpperCase().startsWith("SESSION"))
+		{
+		    MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+		    String[] schemaClass = layer.GetFeatureClassName().split(":");
+		
+		    MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+		    MgPropertyDefinition propDef = classDef.GetProperties().GetItem(layer.GetFeatureGeometryName());
+		    
+		    if(propDef.GetPropertyType() == MgFeaturePropertyType.GeometricProperty)
+		    {
+			MgGeometricPropertyDefinition geomPropDef = (MgGeometricPropertyDefinition) propDef;
+			
+			if(geomPropDef.GetGeometryTypes() == MgFeatureGeometricType.Surface)
+			    layerNames.add(layer.GetLegendLabel());
+		    }
+		}
+	    }
+	    Collections.sort(layerNames);
+
+	    return layerNames;
+        }
+        
+	public LayerInfo GetLayerInfo() throws MgException, ParserConfigurationException, IOException, SAXException
+        {
+            ArrayList<Property> properties = new ArrayList<Property>();
+            ArrayList<String> scaleRanges = new ArrayList<String>();
+            
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            
+            MgMap map = new MgMap();
+            map.Open(resourceService, this.args.get("MAPNAME"));
+            MgLayer layer = (MgLayer) map.GetLayers().GetItem(this.args.get("LAYERNAME"));
+
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            String[] schemaClass = layer.GetFeatureClassName().split(":");
+
+            MgClassDefinition classDef = featureService.GetClassDefinition(resId, schemaClass[0], schemaClass[1]);
+
+            for(int i=0; i<classDef.GetProperties().GetCount(); i++)
+            {
+                MgPropertyDefinition propertyDef = classDef.GetProperties().GetItem(i);
+
+                if(propertyDef.GetPropertyType() == MgFeaturePropertyType.DataProperty)
+                {
+                    MgDataPropertyDefinition propertyDataDef = (MgDataPropertyDefinition) propertyDef;
+                    int dataType = propertyDataDef.GetDataType();
+                    ArrayList<Integer> distroTypes = new ArrayList(this.GetDistributionsForDataType(dataType));
+                    if(distroTypes.size() > 0)
+                    {
+                        properties.add(new Property(propertyDataDef.GetName(), dataType, distroTypes));
+                    }
+                }
+            }
+            
+            // Next get a list of all of the layers scale ranges.
+            
+            MgResourceIdentifier layerDefResId = layer.GetLayerDefinition();
+            MgByteReader byteReader = resourceService.GetResourceContent(layerDefResId);
+            
+            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+            Document doc = docBuilder.parse(new InputSource(new StringReader(byteReader.ToString())));
+            NodeList nodeList = doc.getElementsByTagName("VectorScaleRange");
+            
+            for(int i=0; i<nodeList.getLength(); i++)
+            {
+                Element currentNode = (Element) nodeList.item(i);
+                String range = null;
+                
+                NodeList minNodeList = currentNode.getElementsByTagName("MinScale");
+                if(minNodeList.getLength() > 0)
+                    range = minNodeList.item(0).getFirstChild().getNodeValue();
+                else
+                    range = "0";
+                
+                NodeList maxNodeList = currentNode.getElementsByTagName("MaxScale");
+                if(maxNodeList.getLength() > 0)
+                    range = range + " - " + maxNodeList.item(0).getFirstChild().getNodeValue();
+                else
+                    range = range + " - Infinity";
+                
+                scaleRanges.add(range);
+            }
+            
+            return new LayerInfo(properties, scaleRanges);
+        }
+        
+        public ArrayList<String> GetPropertyMinMaxCount() throws MgException
+        {
+            ArrayList<String> propertyMinMaxCount = new ArrayList<String>();
+            
+            MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+            
+            MgMap map = new MgMap();
+            map.Open(resourceService, this.args.get("MAPNAME"));
+            MgLayer layer = (MgLayer) map.GetLayers().GetItem(this.args.get("LAYERNAME"));
+
+            MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            
+            String minValue = null;
+            String maxValue = null;
+            boolean firstTime = true;
+            int count = 0;
+            
+            MgFeatureQueryOptions queryOptions = new MgFeatureQueryOptions();
+            queryOptions.AddFeatureProperty(this.args.get("PROPERTYNAME"));
+            
+            MgFeatureReader featureReader = featureService.SelectFeatures(resId, layer.GetFeatureClassName(), queryOptions);
+            while(featureReader.ReadNext())
+            {
+                String value = this.GetFeaturePropertyValue(featureReader, this.args.get("PROPERTYNAME"));
+                int propertyType = featureReader.GetPropertyType(this.args.get("PROPERTYNAME"));
+                if(firstTime)
+                {
+                    maxValue = value;
+                    minValue = value;
+                    firstTime = false;
+                }
+                switch(propertyType)
+                {
+                    case MgPropertyType.String :
+                        if(!value.equals(""))
+                        {
+                            if(value.compareTo(maxValue) > 0)
+                                maxValue = value;
+                            if(value.compareTo(minValue) < 0)
+                                minValue = value;
+                        }
+                        break;
+                    case MgPropertyType.Byte :
+                    case MgPropertyType.Int16 :
+                    case MgPropertyType.Int32 :
+                    case MgPropertyType.Int64 :
+                        if(!value.equals(""))
+                        {
+                            if(Integer.valueOf(value) > Integer.valueOf(maxValue))
+                                maxValue = value;
+                            if(Integer.valueOf(value) < Integer.valueOf(minValue))
+                                minValue = value;
+                        }
+                        break;
+                    case MgPropertyType.Single :
+                    case MgPropertyType.Double :
+                        if(value!=null)
+                        {
+                            if(Double.valueOf(value) > Double.valueOf(maxValue))
+                                maxValue = value;
+                            if(Double.valueOf(value) < Double.valueOf(minValue))
+                                minValue = value;
+                        }
+                        count++;
+                        break;
+                    case MgPropertyType.Boolean :
+                    case MgPropertyType.DateTime :
+                    case MgPropertyType.Null :
+                    case MgPropertyType.Blob :
+                    case MgPropertyType.Clob :
+                    case MgPropertyType.Feature :
+                    case MgPropertyType.Geometry :
+                        break;
+                }
+                count++;
+            }
+            featureReader.Close();
+            
+            propertyMinMaxCount.add(minValue.toString());
+            propertyMinMaxCount.add(maxValue.toString());
+            propertyMinMaxCount.add(String.valueOf(count));
+            
+            return propertyMinMaxCount;
+        }
+        
+        public String ApplyTheme() throws MgException, ParserConfigurationException, IOException, SAXException, TransformerConfigurationException, TransformerException
+        {
+    	    MgResourceService resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
+    	    MgFeatureService featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);
+
+    	    MgMap map = new MgMap();
+    	    map.Open(resourceService, this.args.get("MAPNAME"));
+    	    MgLayerCollection layers = map.GetLayers();
+            MgLayer layer = (MgLayer) layers.GetItem(this.args.get("LAYERNAME"));
+            
+            MgResourceIdentifier resId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+            MgResourceIdentifier layerDefResId = layer.GetLayerDefinition();
+            MgByteReader byteReader = resourceService.GetResourceContent(layerDefResId);
+            
+            // Load the Layer Definition and Navigate to the specified <VectorScaleRange>
+            
+            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+            Document doc = docBuilder.parse(new InputSource(new StringReader(byteReader.ToString())));
+
+            NodeList nodeList = doc.getElementsByTagName("VectorScaleRange");
+                
+            Element vectorScaleRangecElement = (Element) nodeList.item(Integer.valueOf(this.args.get("SCALERANGEINDEX")));
+            Element areaTypeStyle = (Element) vectorScaleRangecElement.getElementsByTagName("AreaTypeStyle").item(0);
+            
+            // Remove any existing <AreaRule> elements.
+            
+            NodeList areaRuleList = areaTypeStyle.getElementsByTagName("AreaRule");
+            int count = areaRuleList.getLength();
+            for(int i=0; i<count; i++)
+            {
+                areaTypeStyle.removeChild(areaRuleList.item(0));
+            }
+            
+            // Now create the new <AreaRule> elements.
+            
+            String lineSep = System.getProperty("line.separator");
+            BufferedReader buffReader = new BufferedReader(new FileReader(GetThemeXmlTemplatePath()));
+            String nextLine = "";
+            StringBuffer strBuffer = new StringBuffer();
+            while((nextLine = buffReader.readLine()) != null)
+            {
+                strBuffer.append(nextLine);
+                strBuffer.append(lineSep);
+            }
+            String areaRuleTemplate = strBuffer.toString();
+            MgFeatureAggregateOptions aggregateOptions = new MgFeatureAggregateOptions();
+            
+            String value = null;
+            String filterText = null;
+            String areaRuleXML = null;
+            Document areaDoc = null;
+            Node areaNode = null;
+            double portion = 0.0;
+            double increment = (Integer.valueOf(this.args.get("NUMRULES")) > 1)? 1.0 / (Integer.valueOf(this.args.get("NUMRULES"))-1) : 1.0;
+            
+            if("INDIV_DIST".equals(this.args.get("DISTRO")))
+            {
+                aggregateOptions.AddFeatureProperty(this.args.get("PROPERTYNAME"));
+                aggregateOptions.SelectDistinct(true);
+                
+                MgDataReader dataReader = featureService.SelectAggregate(resId, layer.GetFeatureClassName(), aggregateOptions);
+                while(dataReader.ReadNext())
+                {
+                    value = this.GetFeaturePropertyValue(dataReader, this.args.get("PROPERTYNAME"));
+                    
+                    filterText = "&quot;" + this.args.get("PROPERTYNAME") + "&quot; = ";
+                    if(Integer.valueOf(this.args.get("DATATYPE")) == MgPropertyType.String)
+                        filterText = filterText + "'" + value + "'";
+                    else
+                        filterText = filterText + value;
+
+                    areaRuleXML = String.format(areaRuleTemplate,
+                                                this.args.get("PROPERTYNAME") + ":" + value,
+                                                filterText,
+                                                this.InterpolateColor(portion, this.args.get("FILLFROM"), this.args.get("FILLTO"), Integer.valueOf(this.args.get("FILLTRANS"))),
+                                                this.InterpolateColor(portion, this.args.get("LINEFROM"), this.args.get("LINETO"), 0));
+                    docFactory = DocumentBuilderFactory.newInstance();
+                    docBuilder = docFactory.newDocumentBuilder();
+                    areaDoc = docBuilder.parse(new InputSource(new StringReader(areaRuleXML))); 
+
+                    areaNode = doc.importNode(areaDoc.getDocumentElement(), true);
+                    areaTypeStyle.appendChild(areaNode);
+                    
+                    portion = portion + increment;
+                }
+                dataReader.Close();
+            }
+            else
+            {
+                ArrayList<String> values = new ArrayList<String>();
+                
+                aggregateOptions.AddComputedProperty("THEME_VALUE",
+                    this.args.get("DISTRO") + "(\"" + this.args.get("PROPERTYNAME") + "\"," + this.args.get("NUMRULES") + "," + this.args.get("MINVALUE") + "," + this.args.get("MAXVALUE") + ")");
+                
+                MgDataReader dataReader = featureService.SelectAggregate(resId, layer.GetFeatureClassName(), aggregateOptions);
+                while(dataReader.ReadNext())
+                {
+                    value = this.GetFeaturePropertyValue(dataReader, "THEME_VALUE");
+                    values.add(value);
+                }
+                dataReader.Close();
+                
+                for(int i=0; i<values.size() - 1; i++)
+                {
+                    filterText = "&quot;" + this.args.get("PROPERTYNAME") + "&quot; &gt;= " + values.get(i) + " AND &quot;" + this.args.get("PROPERTYNAME");
+                    if(i == values.size() - 1)
+                        filterText = filterText + "&quot; &lt;= " + values.get(i+1);
+                    else
+                        filterText = filterText + "&quot; &lt; " + values.get(i+1);
+                    
+                    areaRuleXML = String.format(areaRuleTemplate,
+                                                this.args.get("PROPERTYNAME") + ":" + values.get(i) + " - " + values.get(i+1),
+                                                filterText,
+                                                this.InterpolateColor(portion, this.args.get("FILLFROM"), this.args.get("FILLTO"), Integer.valueOf(this.args.get("FILLTRANS"))),
+                                                this.InterpolateColor(portion, this.args.get("LINEFROM"), this.args.get("LINETO"), 0));
+                    
+                    docFactory = DocumentBuilderFactory.newInstance();
+                    docBuilder = docFactory.newDocumentBuilder();
+                    areaDoc = docBuilder.parse(new InputSource(new StringReader(areaRuleXML))); 
+
+                    areaNode = doc.importNode(areaDoc.getDocumentElement(), true);
+                    areaTypeStyle.appendChild(areaNode);
+		                        
+                    portion = portion + increment;
+                }
+            }
+            
+            // Now save our new layer definition to the session and add it to the map.
+            
+            DOMSource domSource = new DOMSource(doc);
+            StringWriter writer = new StringWriter();
+            StreamResult result = new StreamResult(writer);
+            TransformerFactory tf = TransformerFactory.newInstance();
+            Transformer transformer = tf.newTransformer();
+            transformer.transform(domSource, result);
+            String layerDefinition = writer.toString();
+            String uniqueName = this.MakeUniqueLayerName(map, this.args.get("LAYERNAME"), this.args.get("THEMENAME"));
+            String legendLabel = layer.GetLegendLabel();
+            if(this.args.get("THEMENAME").trim().length() > 0)
+                legendLabel = legendLabel + " (" + this.args.get("THEMENAME") + ")";
+            
+            MgResourceIdentifier layerResId = new MgResourceIdentifier("Session:" + this.args.get("SESSION") + "//" + uniqueName + ".LayerDefinition");
+            
+            MgByteSource byteSource = new MgByteSource(layerDefinition.getBytes(), layerDefinition.length());
+            resourceService.SetResource(layerResId, byteSource.GetReader(), null);
+            
+            MgLayer newLayer = new MgLayer(layerResId, resourceService);
+            newLayer.SetName(uniqueName);
+            newLayer.SetLegendLabel(legendLabel);
+            newLayer.SetDisplayInLegend(layer.GetDisplayInLegend());
+            newLayer.SetVisible(true);
+            newLayer.SetSelectable(layer.GetSelectable());
+            layers.Insert(layers.IndexOf(layer), newLayer);
+            
+            map.Save(resourceService);
+
+            return uniqueName;
+        }
+        
+        private String InterpolateColor(double portion, String startColor, String endColor, int percentTransparent)
+        {
+            String result = String.format("%02x", 255*(100-percentTransparent)/100);
+            
+            if(startColor.equals(endColor))
+                return result+startColor;
+            
+            int red = this.CalculateRGB(portion, startColor.substring(0,2), endColor.substring(0,2));
+            result = (Integer.toHexString(red).length() == 1)? result+"0"+Integer.toHexString(red) : result+Integer.toHexString(red);
+            int green = this.CalculateRGB(portion, startColor.substring(2,4), endColor.substring(2,4));
+            result = (Integer.toHexString(green).length() == 1)? result+"0"+Integer.toHexString(green) : result+Integer.toHexString(green);
+            int blue = this.CalculateRGB(portion, startColor.substring(4,6), endColor.substring(4,6));
+            result = (Integer.toHexString(blue).length() == 1)? result+"0"+Integer.toHexString(blue) : result+Integer.toHexString(blue);
+            
+            return result;
+        }
+        
+        private int CalculateRGB(double portion, String startRGB, String endRGB)
+        {
+            double result = Integer.parseInt(startRGB, 16) + portion*(Integer.parseInt(endRGB, 16) - Integer.parseInt(startRGB, 16));
+            return (int) result;
+        }
+        
+        private ArrayList<Integer> GetDistributionsForDataType(int type) throws MgException
+        {
+            ArrayList<Integer> distroTypes = new ArrayList<Integer>();
+            
+            switch(type)
+            {
+                case MgPropertyType.String :
+                    distroTypes.add(0);
+                    break;
+                case MgPropertyType.Byte :
+                case MgPropertyType.Int16 :
+                case MgPropertyType.Int32 :
+                case MgPropertyType.Int64 :
+                    distroTypes.add(0);
+                    distroTypes.add(1);
+                    distroTypes.add(2);
+                    distroTypes.add(3);
+                    distroTypes.add(4);
+                    break;
+                case MgPropertyType.Single :
+                case MgPropertyType.Double :
+                    distroTypes.add(1);
+                    distroTypes.add(2);
+                    distroTypes.add(3);
+                    distroTypes.add(4);
+                    break;
+                case MgPropertyType.Boolean :
+                case MgPropertyType.DateTime :
+                case MgPropertyType.Blob :
+                case MgPropertyType.Clob :
+                case MgPropertyType.Feature :
+                case MgPropertyType.Geometry :
+                case MgPropertyType.Null :
+                    break;
+            }
+            return distroTypes;
+        }
+        
+        private String MakeUniqueLayerName(MgMap map, String layerName, String themeName) throws MgException
+        {
+            String desiredName = "_" + layerName + themeName;
+            String uniqueName = desiredName;
+            int index = 1;
+            
+            while(map.GetLayers().Contains(uniqueName))
+            {
+                uniqueName = desiredName + Integer.toString(index);
+                index++;
+            }
+            return uniqueName;
+        }
+        
+        private String GetFeaturePropertyValue(MgReader dataReader, String name) throws MgException
+        {
+            String value = null;
+            int propertyType = dataReader.GetPropertyType(name);
+            switch(propertyType)
+            {
+                case MgPropertyType.Boolean :
+                    value = String.valueOf(dataReader.GetBoolean(name));
+                    break;
+                case MgPropertyType.Byte :
+                    value = String.valueOf(dataReader.GetByte(name));
+                    break;
+                case MgPropertyType.Single :
+                    value = String.valueOf(dataReader.GetSingle(name));
+                    break;
+                case MgPropertyType.Double :
+                    value = String.valueOf(dataReader.GetDouble(name));
+                    break;
+                case MgPropertyType.Int16 :
+                    value = String.valueOf(dataReader.GetInt16(name));
+                    break;
+                case MgPropertyType.Int32 :
+                    value = String.valueOf(dataReader.GetInt32(name));
+                    break;
+                case MgPropertyType.Int64 :
+                    value = String.valueOf(dataReader.GetInt64(name));
+                    break;
+                case MgPropertyType.String :
+                    value = dataReader.GetString(name);
+                    break;
+                case MgPropertyType.DateTime :
+                case MgPropertyType.Null :
+                case MgPropertyType.Blob :
+                case MgPropertyType.Clob :
+                case MgPropertyType.Feature :
+                case MgPropertyType.Geometry :
+                case MgPropertyType.Raster :
+                    value = "[unsupported data type]";
+                    break;
+            }
+            return value;
+        }
+    }
+
+%>

Added: trunk/MgDev/Doc/samples/javaviewersample/theme/templates/arearuletemplate.xml
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/theme/templates/arearuletemplate.xml	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/theme/templates/arearuletemplate.xml	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,17 @@
+<AreaRule>
+ <LegendLabel>%s</LegendLabel>
+ <Filter>%s</Filter>
+ <AreaSymbolization2D>
+  <Fill>
+   <FillPattern>Solid</FillPattern>
+   <ForegroundColor>%s</ForegroundColor>
+   <BackgroundColor>FF000000</BackgroundColor>
+  </Fill>
+  <Stroke>
+   <LineStyle>Solid</LineStyle>
+   <Thickness>0</Thickness>
+   <Color>%s</Color>
+   <Unit>Inches</Unit>
+  </Stroke>
+ </AreaSymbolization2D>
+</AreaRule>

Added: trunk/MgDev/Doc/samples/javaviewersample/theme/themecontroller.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/theme/themecontroller.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/theme/themecontroller.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,104 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ page import="org.json.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+<%@ include file ="classes/theme.jsp" %>
+<%@ include file ="classes/command.jsp" %>
+
+<%
+    Map<String, String> args = new HashMap<String, String>();
+
+    Enumeration paramNames = request.getParameterNames();
+    while(paramNames.hasMoreElements())
+    {
+        String paramName = (String)paramNames.nextElement();
+        String paramValue = request.getParameter(paramName);
+        args.put(paramName, paramValue);
+    }
+
+    InitializeWebTier();
+
+    Theme theme = new Theme(args);
+    JSONArray jsonArr = new JSONArray();
+    JSONArray jsonPropArr = new JSONArray();
+    JSONArray jsonDistroArr = null;
+    JSONArray jsonScaleArr = new JSONArray();
+    JSONObject jsonObj = new JSONObject();
+    JSONObject jsonPropObj = new JSONObject();
+    String responseType = "";
+    String responseString = "";
+
+    if(args.get("COMMAND") != null)
+    {
+        int cmd = Integer.valueOf(args.get("COMMAND"));
+        switch (cmd)
+        {
+            case Command.GETLAYERINFO:
+                responseType = "text/plain";
+                LayerInfo layerInfo = theme.GetLayerInfo();
+                ArrayList<Property> propArrayList = layerInfo.properties;
+                
+                for(int i=0; i<propArrayList.size(); i++)
+                {
+                    jsonDistroArr = new JSONArray();
+                    ArrayList<Integer> distroArrayList = propArrayList.get(i).distroTypes;
+                    for(int j=0; j<distroArrayList.size(); j++)
+                    {
+                        jsonDistroArr.put(distroArrayList.get(j));
+                    }
+                    jsonPropObj.put("name", propArrayList.get(i).name);
+                    jsonPropObj.put("dataType", propArrayList.get(i).dataType);
+                    jsonPropObj.put("distroTypes", jsonDistroArr.toString());
+                    jsonPropArr.put(i, jsonPropObj.toString());
+                }
+                ArrayList<String> scaleArrayList = layerInfo.scaleRanges;
+                for(int k=0; k<scaleArrayList.size(); k++)
+                {
+                    jsonScaleArr.put(scaleArrayList.get(k));
+                }
+                    
+                jsonObj.put("properties", jsonPropArr.toString());
+                jsonObj.put("scaleRanges", jsonScaleArr.toString());
+                responseString = jsonObj.toString();
+                break;
+            case Command.GETPROPERTYMINMAXCOUNT:
+                responseType = "text/plain";
+                ArrayList<String> arrayList = theme.GetPropertyMinMaxCount();
+                for(int i=0;i<arrayList.size();i++)
+                {
+                    jsonArr.put(arrayList.get(i));
+                }
+                responseString = jsonArr.toString();
+                break;
+            case Command.APPLYTHEME:
+                responseType = "text/plain";
+		responseString = theme.ApplyTheme();
+                break;
+        }
+    }
+    
+    response.setContentType(responseType);
+
+    out.print(responseString);
+    out.flush();
+%>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/javaviewersample/theme/thememain.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/theme/thememain.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/theme/thememain.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,476 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file ="../utilityfunctions.jsp" %>
+<%@ include file ="classes/theme.jsp" %>
+<%@ include file ="classes/command.jsp" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<%
+    String errorMsg = null;
+    String errorDetail = null;
+    Map<String, String> args = new HashMap<String, String>();
+    Theme theme = null;
+    ArrayList<String> layerNames = null;
+    
+    Enumeration paramNames = request.getParameterNames();
+    while(paramNames.hasMoreElements())
+    {
+        String paramName = (String)paramNames.nextElement();
+        String paramValue = request.getParameter(paramName);
+        args.put(paramName, paramValue);
+    }
+    
+    try
+    {
+        InitializeWebTier();
+    
+        theme = new Theme(args);
+        
+        layerNames = theme.GetMapLayerNames();
+    }
+    catch (MgException e)
+    {
+        errorMsg = e.GetMessage();
+        errorDetail = e.GetDetails();
+    }
+%>
+<html>
+<head>
+    <title>Theme Layer</title>
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+    <script language="javascript" src="../../viewerfiles/browserdetect.js"></script>
+    <script language="javascript" src="../json.js"></script>
+
+    <script language="javascript">
+        var READY_STATE_UNINITIALIZED 	= 0;
+        var READY_STATE_LOADING 		= 1;
+        var READY_STATE_LOADED 			= 2;
+        var READY_STATE_INTERACTIVE 	= 3;
+        var READY_STATE_COMPLETE 		= 4;
+
+        var NOT_BUSY_IMAGE = "../images/loader_inactive.gif";
+        var BUSY_IMAGE = "../images/loader_pulse.gif";
+
+        var SET_FILL_FROM_COLOR 	= 1;
+        var SET_FILL_TO_COLOR 		= 2;
+        var SET_LINE_FROM_COLOR 	= 3;
+        var SET_LINE_TO_COLOR		= 4;
+
+        var fillFromColor = "FF0000";
+        var fillToColor = "0000FF";
+        var lineFromColor = "000000";
+        var lineToColor = "000000";
+
+        var session = "<%= args.get("SESSION") %>";
+        var mapName = "<%= args.get("MAPNAME") %>";
+
+        var distNameArray = <%= theme.getNameArray() %>;
+        var distValueArray = <%= theme.getValueArray() %>;
+
+        var themeReqHandler = null;
+        var layerInfo = null;
+
+        var featureCount = 0;
+        var ruleCount = 8;
+
+        function OnLayerChange()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var propertySelect = document.getElementById("propertySelect");
+            var scaleSelect = document.getElementById("scaleSelect");
+
+            reqParams = "COMMAND=<%=Command.GETLAYERINFO%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "themecontroller.jsp", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            reqHandler.send(reqParams);
+            layerInfo = reqHandler.responseText.parseJSON();
+            layerInfo.properties = layerInfo.properties.parseJSON();
+            layerInfo.scaleRanges = layerInfo.scaleRanges.parseJSON();
+            
+            for(var i = 0; i < layerInfo.properties.length; i++)
+            {
+                layerInfo.properties[i] = layerInfo.properties[i].parseJSON();
+                layerInfo.properties[i].distroTypes = layerInfo.properties[i].distroTypes.parseJSON();
+            }
+            
+            propertySelect.options.length = 0;
+            for (var i = 0; i < layerInfo.properties.length; i++)
+            {
+                propertySelect.options[i] = new Option(layerInfo.properties[i].name, i, false, false);
+            }
+            OnPropertyChange();
+            
+            scaleSelect.options.length = 0;
+            for (var i = 0; i < layerInfo.scaleRanges.length; i++)
+            {
+                scaleSelect.options[i] = new Option(layerInfo.scaleRanges[i], i, false, false);
+            }
+        }
+
+        function OnPropertyChange()
+        {
+            var propertySelect = document.getElementById("propertySelect");
+            var distroSelect = document.getElementById("distroSelect");
+
+            PopulateMinMaxCount(propertySelect.value);
+	    
+            distroSelect.options.length = 0;
+            if (propertySelect.selectedIndex >= 0)
+            {
+                for (var i = 0; i < layerInfo.properties[propertySelect.value].distroTypes.length; i++)
+                {
+                    distroSelect.options[i] = new Option(distNameArray[layerInfo.properties[propertySelect.value].distroTypes[i]], distValueArray[layerInfo.properties[propertySelect.value].distroTypes[i]], false, false);
+                }
+            }
+            OnDistroChange();
+
+        }
+
+        function OnDistroChange()
+        {
+            var distroSelect = document.getElementById("distroSelect");
+            var numRules = document.getElementById("numRules");
+	
+            if (distroSelect.value == distValueArray[0])
+            {
+                numRules.disabled = true;
+                numRules.value = featureCount;
+            }
+            else
+            {
+                numRules.disabled = false;
+                numRules.value = ruleCount;
+            }
+        }
+		
+
+        function PopulateMinMaxCount(propertyIndex)
+        {
+            var layerSelect = document.getElementById("layerSelect");
+
+            reqParams = "COMMAND=<%=Command.GETPROPERTYMINMAXCOUNT%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+            reqParams += "&PROPERTYNAME=" + encodeURIComponent(layerInfo.properties[propertyIndex].name);
+
+            if (msie)
+                themeReqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                themeReqHandler = new XMLHttpRequest();
+
+            themeReqHandler.onreadystatechange = OnGetMinMaxCountReadyStateChange;
+            themeReqHandler.open("POST", "themecontroller.jsp", true);
+            themeReqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            document.getElementById("busyImg").src = BUSY_IMAGE;
+
+            DisableControls(['layerSelect', 'propertySelect'], true);
+
+            themeReqHandler.send(reqParams);
+        }
+
+        function OnGetMinMaxCountReadyStateChange()
+        {
+            var ready = themeReqHandler.readyState;
+
+            if (ready == READY_STATE_COMPLETE)
+            {
+                minMaxCount = themeReqHandler.responseText.parseJSON();
+
+                document.getElementById("minValue").value = minMaxCount[0];
+                document.getElementById("maxValue").value = minMaxCount[1];
+                featureCount = minMaxCount[2];
+
+                OnDistroChange();
+
+                DisableControls(['layerSelect', 'propertySelect'], false);
+                document.getElementById("busyImg").src = NOT_BUSY_IMAGE;
+                themeReqHandler = null;
+            }
+        }
+
+        function DisableControls(ids, enable)
+        {
+            for (var i = 0; i < ids.length; i++)
+            {
+                document.getElementById(ids[i]).disabled = enable;
+            }
+        }
+
+        function PickColor(whichColor, allowTransparency, transparent)
+        {
+            var clr;
+            setColor = whichColor;
+
+            if (setColor == SET_FILL_FROM_COLOR)
+                clr = fillFromColor;
+            else if (setColor == SET_FILL_TO_COLOR)
+                clr = fillToColor;
+            else if (setColor == SET_LINE_FROM_COLOR)
+                clr = lineFromColor;
+            else if (setColor == SET_LINE_TO_COLOR)
+                clr = lineToColor;
+            else
+                return;
+
+            height = allowTransparency? 470: 445;
+            w = window.open("../../mapviewerjava/colorpicker.jsp?LOCALE=en&CLR=" + clr + "&ALLOWTRANS=" + (allowTransparency? "1":"0") + "&TRANS=" + (transparent?"1":"0"), "colorPicker", "toolbar=no,status=no,width=355,height=" + height);
+            w.focus();
+        }
+
+        function OnColorPicked(clr, trans)
+        {
+            if (setColor == SET_FILL_FROM_COLOR)
+                fillFromColor = clr;
+            else if (setColor == SET_FILL_TO_COLOR)
+                fillToColor = clr;
+            else if (setColor == SET_LINE_FROM_COLOR)
+                lineFromColor = clr;
+            else if (setColor == SET_LINE_TO_COLOR)
+                lineToColor = clr;
+            else
+                return;
+
+            UpdateColors();
+        }
+
+        function UpdateColors()
+        {
+            var elt;
+
+            elt = document.getElementById("fillFromSwatch").style;
+            elt.backgroundColor = "#" + fillFromColor;
+            elt.color = "#" + fillFromColor;
+
+            elt = document.getElementById("fillToSwatch").style;
+            elt.backgroundColor = "#" + fillToColor;
+            elt.color = "#" + fillToColor;
+
+            elt = document.getElementById("lineFromSwatch").style;
+            elt.backgroundColor = "#" + lineFromColor;
+            elt.color = "#" + lineFromColor;
+
+            elt = document.getElementById("lineToSwatch").style;
+            elt.backgroundColor = "#" + lineToColor;
+            elt.color = "#" + lineToColor;
+        }
+
+        function ApplyTheme()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var propertySelect = document.getElementById("propertySelect");
+
+            reqParams = "COMMAND=<%=Command.APPLYTHEME%>";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+            reqParams += "&THEMENAME=" + encodeURIComponent(document.getElementById("themeName").value);
+            reqParams += "&PROPERTYNAME=" + encodeURIComponent(layerInfo.properties[propertySelect.value].name);
+            reqParams += "&DATATYPE=" + encodeURIComponent(layerInfo.properties[propertySelect.value].dataType);
+            reqParams += "&MINVALUE=" + encodeURIComponent(document.getElementById("minValue").value);
+            reqParams += "&MAXVALUE=" + encodeURIComponent(document.getElementById("maxValue").value);
+            reqParams += "&DISTRO=" + encodeURIComponent(document.getElementById("distroSelect").value);
+            reqParams += "&NUMRULES=" + encodeURIComponent(document.getElementById("numRules").value);
+            reqParams += "&SCALERANGEINDEX=" + encodeURIComponent(document.getElementById("scaleSelect").value);
+            reqParams += "&FILLTRANS=" + encodeURIComponent(document.getElementById("fillTrans").value);
+            reqParams += "&FILLFROM=" + encodeURIComponent(fillFromColor);
+            reqParams += "&FILLTO=" + encodeURIComponent(fillToColor);
+            reqParams += "&LINEFROM=" + encodeURIComponent(lineFromColor);
+            reqParams += "&LINETO=" + encodeURIComponent(lineToColor);
+
+            if (msie)
+                themeReqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                themeReqHandler = new XMLHttpRequest();
+
+            themeReqHandler.onreadystatechange = OnApplyThemeReadyStateChange;
+            themeReqHandler.open("POST", "themecontroller.jsp", true);
+            themeReqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            document.getElementById("busyImg").src = BUSY_IMAGE;
+
+            DisableControls(['layerSelect', 'propertySelect'], true);
+
+            themeReqHandler.send(reqParams);
+        }
+
+        function OnApplyThemeReadyStateChange()
+        {
+            var ready = themeReqHandler.readyState;
+
+            if (ready == READY_STATE_COMPLETE)
+            {
+                DisableControls(['layerSelect', 'propertySelect'], false);
+                document.getElementById("busyImg").src = NOT_BUSY_IMAGE;
+                themeReqHandler = null;
+
+                parent.parent.Refresh();
+            }
+        }
+
+        function OnLoad()
+	{
+		OnLayerChange();
+		UpdateColors();
+	}
+
+    </script>
+
+</head>
+
+<body onLoad="OnLoad()" marginwidth=5 marginheight=5 leftmargin=5 topmargin=5 bottommargin=5 rightmargin=5>
+
+<% if (errorMsg == null) { %>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td colspan="2" class="Title"><img id="busyImg" src="../images/loader_pulse.gif" style="vertical-align:bottom">&nbsp;Theme Layer<hr></td></tr>
+    <tr><td colspan="2" class="SubTitle">Select a Layer</td></tr>
+    <tr><td colspan="2">Layer:</td></tr>
+    <tr><tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="layerSelect" onChange="OnLayerChange()" style="width: 100%">
+            <%
+                String selected = "selected";
+                for(int i=0; i<layerNames.size(); i++) {
+            %>
+                    <option value="<%= layerNames.get(i) %>" <%=selected %> ><%= layerNames.get(i) %></option>
+            <%
+                    selected = "";
+                }
+            %>
+            </select>
+        </td>
+    </tr>
+    <tr><td colspan="2">Theme Name:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="100" class="Ctrl" id="themeName" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" class="SubTitle">Define Conditions</td></tr>
+    <tr><td colspan="2">Property:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="propertySelect" onChange="OnPropertyChange()" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td colspan="2">Min:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="100" class="Ctrl" id="minValue" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2">Max:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="100" class="Ctrl" id="maxValue" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2">Distribution:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="distroSelect" onChange="OnDistroChange()" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td colspan="2"># of Rules:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="10" class="Ctrl" id="numRules" value="8" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" class="SubTitle">Scale Range</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="scaleSelect" style="width: 100%">
+            </select>
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" class="SubTitle">Style Ramp</td></tr>
+    <tr><td>Fill Transparency:</td></tr>
+    <tr>
+        <td  colspan="2" class="RegText">
+            <input class="Ctrl" id="fillTrans" type="text"  maxlength="3" value="0" style="width:90%">&nbsp;%
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td>Fill Color:</td></tr>
+    <tr>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;From:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="fillFromSwatch" style="color: #FF0000; background-color: #FF0000">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_FILL_FROM_COLOR,false,false)">
+        </td>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;To:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="fillToSwatch" style="color: #0000FF; background-color: #0000FF">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_FILL_TO_COLOR,false,false)">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td>Border Color:</td></tr>
+    <tr>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;From:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="lineFromSwatch" style="color: #000000; background-color: #000000">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_LINE_FROM_COLOR,false,false)">
+        </td>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;To:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="lineToSwatch" style="color: #000000; background-color: #000000">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_LINE_TO_COLOR,false,false)">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" ><hr></td></tr>
+    <tr><td colspan="2" align="right"><input class="Ctrl" type="button" value="Apply" style="width: 60px;" onClick="ApplyTheme()"></td></tr>
+</table>
+
+<% } else { %>
+
+<table class="RegText" border="0" cellspacing="0" width="100%%">
+    <tr><td class="Title">Error<hr></td></tr>
+    <tr><td><% System.out.println(errorMsg); %></td></tr>
+    <tr><td><% System.out.println(errorDetail); %></td></tr>
+</table>
+
+<% } %>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/title.html
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/title.html	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/title.html	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>Title Frame Content</title>
+<style type="text/css">
+<!--
+.apptitle {
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+	font-size: 16px;
+	font-style: normal;
+	color: #FFFFFF;
+	vertical-align: baseline;
+	height: 30px;
+	line-height: 30px;
+	margin-left: 6px;
+}
+-->
+</style>
+</head>
+<body bgcolor="#006633">
+<p class="apptitle">Viewer Sample Application</p>
+</body>
+</html>

Added: trunk/MgDev/Doc/samples/javaviewersample/utilityfunctions.jsp
===================================================================
--- trunk/MgDev/Doc/samples/javaviewersample/utilityfunctions.jsp	                        (rev 0)
+++ trunk/MgDev/Doc/samples/javaviewersample/utilityfunctions.jsp	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,83 @@
+<%--
+  -Copyright (C) 2004-2006  Autodesk, Inc.
+  -This library is free software; you can redistribute it and/or
+  -modify it under the terms of version 2.1 of the GNU Lesser
+  -General Public License as published by the Free Software Foundation.
+
+  -This library is distributed in the hope that it will be useful,
+  -but WITHOUT ANY WARRANTY; without even the implied warranty of
+  -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  -Lesser General Public License for more details.
+
+  -You should have received a copy of the GNU Lesser General Public
+  -License along with this library; if not, write to the Free Software
+  -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+--%>
+
+<%@ page import="java.util.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ page import="org.osgeo.mapguide.*" %>
+<%!
+void InitializeWebTier() throws MgException
+{
+    String realpath = getServletContext().getRealPath("/");
+    // Initialize web tier with the site configuration file.  The config
+    // file should be in the same folder as this script.
+    String configPath =  realpath + "webconfig.ini";
+    MapGuideJavaApi.MgInitializeWebTier( configPath );
+}
+
+String GetQueryXmlTemplatePath()
+{
+    String realpath = getServletContext().getRealPath("/");
+    // Initialize web tier with the site configuration file.  The config
+    // file should be in the same folder as this script.
+    String xmlTemplatePath = realpath + "javaviewersample\\query\\templates\\filterlayerdefinition.xml";
+    return xmlTemplatePath;
+}
+
+String GetThemeXmlTemplatePath()
+{
+    String realpath = getServletContext().getRealPath("/");
+    // Initialize web tier with the site configuration file.  The config
+    // file should be in the same folder as this script.
+    String xmlTemplatePath = realpath + "javaviewersample\\theme\\templates\\arearuletemplate.xml";
+    return xmlTemplatePath;
+}
+
+// Searches the map for a layer with the specified name.
+
+MgLayer GetLayerByName(MgMap map, String layerName) throws MgException
+{
+    MgLayer layer = null;
+    for (int i = 0; i < map.GetLayers().GetCount(); i++)
+    {
+        MgLayer nextLayer = (MgLayer) map.GetLayers().GetItem(i);
+        if (nextLayer.GetName().equals(layerName))
+        {
+            layer = nextLayer;
+            break;
+        }
+    }
+    return layer;
+}
+
+void OutputReaderContent(ServletResponse response, MgByteReader byteReader) throws MgException, Exception
+{
+    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+    byte[] byteBuffer = new byte[1024];
+    int numBytes = byteReader.Read(byteBuffer, 1024);
+    while(numBytes > 0)
+    {
+        bos.write(byteBuffer, 0, numBytes);
+        numBytes = byteReader.Read(byteBuffer, 1024);
+    }
+    response.setContentLength(bos.size());
+    response.setContentType(byteReader.GetMimeType());
+    response.getOutputStream().write(bos.toByteArray());
+}
+
+%>

Added: trunk/MgDev/Doc/samples/phpviewersample/JSON.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/JSON.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/JSON.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,806 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Converts to and from JSON format.
+ *
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
+ * format. It is easy for humans to read and write. It is easy for machines
+ * to parse and generate. It is based on a subset of the JavaScript
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+ * This feature can also be found in  Python. JSON is a text format that is
+ * completely language independent but uses conventions that are familiar
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
+ * ideal data-interchange language.
+ *
+ * This package provides a simple encoder and decoder for JSON notation. It
+ * is intended for use with client-side Javascript applications that make
+ * use of HTTPRequest to perform server communication functions - data can
+ * be encoded into JSON notation for use in a client-side javascript, or
+ * decoded from incoming Javascript requests. JSON format is native to
+ * Javascript, and can be directly eval()'ed with no further parsing
+ * overhead
+ *
+ * All strings should be in ASCII or UTF-8 format!
+ *
+ * LICENSE: Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met: Redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following
+ * disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * @category
+ * @package     Services_JSON
+ * @author      Michal Migurski <mike-json at teczno.com>
+ * @author      Matt Knapp <mdknapp[at]gmail[dot]com>
+ * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+ * @copyright   2005 Michal Migurski
+ * @version     CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+ */
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_SLICE',   1);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_STR',  2);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_ARR',  3);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_OBJ',  4);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_CMT', 5);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_LOOSE_TYPE', 16);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
+
+/**
+ * Converts to and from JSON format.
+ *
+ * Brief example of use:
+ *
+ * <code>
+ * // create a new instance of Services_JSON
+ * $json = new Services_JSON();
+ *
+ * // convert a complexe value to JSON notation, and send it to the browser
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
+ * $output = $json->encode($value);
+ *
+ * print($output);
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
+ *
+ * // accept incoming POST data, assumed to be in JSON notation
+ * $input = file_get_contents('php://input', 1000000);
+ * $value = $json->decode($input);
+ * </code>
+ */
+class Services_JSON
+{
+   /**
+    * constructs a new JSON instance
+    *
+    * @param    int     $use    object behavior flags; combine with boolean-OR
+    *
+    *                           possible values:
+    *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
+    *                                   "{...}" syntax creates associative arrays
+    *                                   instead of objects in decode().
+    *                           - SERVICES_JSON_SUPPRESS_ERRORS:  error suppression.
+    *                                   Values which can't be encoded (e.g. resources)
+    *                                   appear as NULL instead of throwing errors.
+    *                                   By default, a deeply-nested resource will
+    *                                   bubble up with an error, so all return values
+    *                                   from encode() should be checked with isError()
+    */
+    function Services_JSON($use = 0)
+    {
+        $this->use = $use;
+    }
+
+   /**
+    * convert a string from one UTF-16 char to one UTF-8 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf16  UTF-16 character
+    * @return   string  UTF-8 character
+    * @access   private
+    */
+    function utf162utf8($utf16)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding')) {
+            return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+        }
+
+        $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+        switch(true) {
+            case ((0x7F & $bytes) == $bytes):
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x7F & $bytes);
+
+            case (0x07FF & $bytes) == $bytes:
+                // return a 2-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xC0 | (($bytes >> 6) & 0x1F))
+                     . chr(0x80 | ($bytes & 0x3F));
+
+            case (0xFFFF & $bytes) == $bytes:
+                // return a 3-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xE0 | (($bytes >> 12) & 0x0F))
+                     . chr(0x80 | (($bytes >> 6) & 0x3F))
+                     . chr(0x80 | ($bytes & 0x3F));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }
+
+   /**
+    * convert a string from one UTF-8 char to one UTF-16 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf8   UTF-8 character
+    * @return   string  UTF-16 character
+    * @access   private
+    */
+    function utf82utf16($utf8)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding')) {
+            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+        }
+
+        switch(strlen($utf8)) {
+            case 1:
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return $utf8;
+
+            case 2:
+                // return a UTF-16 character from a 2-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x07 & (ord($utf8{0}) >> 2))
+                     . chr((0xC0 & (ord($utf8{0}) << 6))
+                         | (0x3F & ord($utf8{1})));
+
+            case 3:
+                // return a UTF-16 character from a 3-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr((0xF0 & (ord($utf8{0}) << 4))
+                         | (0x0F & (ord($utf8{1}) >> 2)))
+                     . chr((0xC0 & (ord($utf8{1}) << 6))
+                         | (0x7F & ord($utf8{2})));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }
+
+   /**
+    * encodes an arbitrary variable into JSON format
+    *
+    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+    *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+    *                           if var is a strng, note that encode() always expects it
+    *                           to be in ASCII or UTF-8 format!
+    *
+    * @return   mixed   JSON string representation of input var or an error if a problem occurs
+    * @access   public
+    */
+    function encode($var)
+    {
+        switch (gettype($var)) {
+            case 'boolean':
+                return $var ? 'true' : 'false';
+
+            case 'NULL':
+                return 'null';
+
+            case 'integer':
+                return (int) $var;
+
+            case 'double':
+            case 'float':
+                return (float) $var;
+
+            case 'string':
+                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+                $ascii = '';
+                $strlen_var = strlen($var);
+
+               /*
+                * Iterate over every character in the string,
+                * escaping with a slash or encoding to UTF-8 where necessary
+                */
+                for ($c = 0; $c < $strlen_var; ++$c) {
+
+                    $ord_var_c = ord($var{$c});
+
+                    switch (true) {
+                        case $ord_var_c == 0x08:
+                            $ascii .= '\b';
+                            break;
+                        case $ord_var_c == 0x09:
+                            $ascii .= '\t';
+                            break;
+                        case $ord_var_c == 0x0A:
+                            $ascii .= '\n';
+                            break;
+                        case $ord_var_c == 0x0C:
+                            $ascii .= '\f';
+                            break;
+                        case $ord_var_c == 0x0D:
+                            $ascii .= '\r';
+                            break;
+
+                        case $ord_var_c == 0x22:
+                        case $ord_var_c == 0x2F:
+                        case $ord_var_c == 0x5C:
+                            // double quote, slash, slosh
+                            $ascii .= '\\'.$var{$c};
+                            break;
+
+                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                            // characters U-00000000 - U-0000007F (same as ASCII)
+                            $ascii .= $var{$c};
+                            break;
+
+                        case (($ord_var_c & 0xE0) == 0xC0):
+                            // characters U-00000080 - U-000007FF, mask 110XXXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                            $c += 1;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xF0) == 0xE0):
+                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}));
+                            $c += 2;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xF8) == 0xF0):
+                            // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}));
+                            $c += 3;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xFC) == 0xF8):
+                            // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}));
+                            $c += 4;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xFE) == 0xFC):
+                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}),
+                                         ord($var{$c + 5}));
+                            $c += 5;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+                    }
+                }
+
+                return '"'.$ascii.'"';
+
+            case 'array':
+               /*
+                * As per JSON spec if any array key is not an integer
+                * we must treat the the whole array as an object. We
+                * also try to catch a sparsely populated associative
+                * array with numeric keys here because some JS engines
+                * will create an array with empty indexes up to
+                * max_index which can cause memory issues and because
+                * the keys, which may be relevant, will be remapped
+                * otherwise.
+                *
+                * As per the ECMA and JSON specification an object may
+                * have any string as a property. Unfortunately due to
+                * a hole in the ECMA specification if the key is a
+                * ECMA reserved word or starts with a digit the
+                * parameter is only accessible using ECMAScript's
+                * bracket notation.
+                */
+
+                // treat as a JSON object
+                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                    $properties = array_map(array($this, 'name_value'),
+                                            array_keys($var),
+                                            array_values($var));
+
+                    foreach($properties as $property) {
+                        if(Services_JSON::isError($property)) {
+                            return $property;
+                        }
+                    }
+
+                    return '{' . join(',', $properties) . '}';
+                }
+
+                // treat it like a regular array
+                $elements = array_map(array($this, 'encode'), $var);
+
+                foreach($elements as $element) {
+                    if(Services_JSON::isError($element)) {
+                        return $element;
+                    }
+                }
+
+                return '[' . join(',', $elements) . ']';
+
+            case 'object':
+                $vars = get_object_vars($var);
+
+                $properties = array_map(array($this, 'name_value'),
+                                        array_keys($vars),
+                                        array_values($vars));
+
+                foreach($properties as $property) {
+                    if(Services_JSON::isError($property)) {
+                        return $property;
+                    }
+                }
+
+                return '{' . join(',', $properties) . '}';
+
+            default:
+                return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
+                    ? 'null'
+                    : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
+        }
+    }
+
+   /**
+    * array-walking function for use in generating JSON-formatted name-value pairs
+    *
+    * @param    string  $name   name of key to use
+    * @param    mixed   $value  reference to an array element to be encoded
+    *
+    * @return   string  JSON-formatted name-value pair, like '"name":value'
+    * @access   private
+    */
+    function name_value($name, $value)
+    {
+        $encoded_value = $this->encode($value);
+
+        if(Services_JSON::isError($encoded_value)) {
+            return $encoded_value;
+        }
+
+        return $this->encode(strval($name)) . ':' . $encoded_value;
+    }
+
+   /**
+    * reduce a string by removing leading and trailing comments and whitespace
+    *
+    * @param    $str    string      string value to strip of comments and whitespace
+    *
+    * @return   string  string value stripped of comments and whitespace
+    * @access   private
+    */
+    function reduce_string($str)
+    {
+        $str = preg_replace(array(
+
+                // eliminate single line comments in '// ...' form
+                '#^\s*//(.+)$#m',
+
+                // eliminate multi-line comments in '/* ... */' form, at start of string
+                '#^\s*/\*(.+)\*/#Us',
+
+                // eliminate multi-line comments in '/* ... */' form, at end of string
+                '#/\*(.+)\*/\s*$#Us'
+
+            ), '', $str);
+
+        // eliminate extraneous space
+        return trim($str);
+    }
+
+   /**
+    * decodes a JSON string into appropriate variable
+    *
+    * @param    string  $str    JSON-formatted string
+    *
+    * @return   mixed   number, boolean, string, array, or object
+    *                   corresponding to given JSON input string.
+    *                   See argument 1 to Services_JSON() above for object-output behavior.
+    *                   Note that decode() always returns strings
+    *                   in ASCII or UTF-8 format!
+    * @access   public
+    */
+    function decode($str)
+    {
+        $str = $this->reduce_string($str);
+
+        switch (strtolower($str)) {
+            case 'true':
+                return true;
+
+            case 'false':
+                return false;
+
+            case 'null':
+                return null;
+
+            default:
+                $m = array();
+
+                if (is_numeric($str)) {
+                    // Lookie-loo, it's a number
+
+                    // This would work on its own, but I'm trying to be
+                    // good about returning integers where appropriate:
+                    // return (float)$str;
+
+                    // Return float or int, as appropriate
+                    return ((float)$str == (integer)$str)
+                        ? (integer)$str
+                        : (float)$str;
+
+                } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
+                    // STRINGS RETURNED IN UTF-8 FORMAT
+                    $delim = substr($str, 0, 1);
+                    $chrs = substr($str, 1, -1);
+                    $utf8 = '';
+                    $strlen_chrs = strlen($chrs);
+
+                    for ($c = 0; $c < $strlen_chrs; ++$c) {
+
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                        $ord_chrs_c = ord($chrs{$c});
+
+                        switch (true) {
+                            case $substr_chrs_c_2 == '\b':
+                                $utf8 .= chr(0x08);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\t':
+                                $utf8 .= chr(0x09);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\n':
+                                $utf8 .= chr(0x0A);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\f':
+                                $utf8 .= chr(0x0C);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\r':
+                                $utf8 .= chr(0x0D);
+                                ++$c;
+                                break;
+
+                            case $substr_chrs_c_2 == '\\"':
+                            case $substr_chrs_c_2 == '\\\'':
+                            case $substr_chrs_c_2 == '\\\\':
+                            case $substr_chrs_c_2 == '\\/':
+                                if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+                                   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+                                    $utf8 .= $chrs{++$c};
+                                }
+                                break;
+
+                            case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+                                // single, escaped unicode character
+                                $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+                                       . chr(hexdec(substr($chrs, ($c + 4), 2)));
+                                $utf8 .= $this->utf162utf8($utf16);
+                                $c += 5;
+                                break;
+
+                            case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+                                $utf8 .= $chrs{$c};
+                                break;
+
+                            case ($ord_chrs_c & 0xE0) == 0xC0:
+                                // characters U-00000080 - U-000007FF, mask 110XXXXX
+                                //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 2);
+                                ++$c;
+                                break;
+
+                            case ($ord_chrs_c & 0xF0) == 0xE0:
+                                // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 3);
+                                $c += 2;
+                                break;
+
+                            case ($ord_chrs_c & 0xF8) == 0xF0:
+                                // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 4);
+                                $c += 3;
+                                break;
+
+                            case ($ord_chrs_c & 0xFC) == 0xF8:
+                                // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 5);
+                                $c += 4;
+                                break;
+
+                            case ($ord_chrs_c & 0xFE) == 0xFC:
+                                // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 6);
+                                $c += 5;
+                                break;
+
+                        }
+
+                    }
+
+                    return $utf8;
+
+                } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+                    // array, or object notation
+
+                    if ($str{0} == '[') {
+                        $stk = array(SERVICES_JSON_IN_ARR);
+                        $arr = array();
+                    } else {
+                        if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = array();
+                        } else {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = new stdClass();
+                        }
+                    }
+
+                    array_push($stk, array('what'  => SERVICES_JSON_SLICE,
+                                           'where' => 0,
+                                           'delim' => false));
+
+                    $chrs = substr($str, 1, -1);
+                    $chrs = $this->reduce_string($chrs);
+
+                    if ($chrs == '') {
+                        if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                            return $arr;
+
+                        } else {
+                            return $obj;
+
+                        }
+                    }
+
+                    //print("\nparsing {$chrs}\n");
+
+                    $strlen_chrs = strlen($chrs);
+
+                    for ($c = 0; $c <= $strlen_chrs; ++$c) {
+
+                        $top = end($stk);
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+
+                        if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+                            // found a comma that is not inside a string, array, etc.,
+                            // OR we've reached the end of the character list
+                            $slice = substr($chrs, $top['where'], ($c - $top['where']));
+                            array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+                            //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                            if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                                // we are in an array, so just push an element onto the stack
+                                array_push($arr, $this->decode($slice));
+
+                            } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                                // we are in an object, so figure
+                                // out the property name and set an
+                                // element in an associative array,
+                                // for now
+                                $parts = array();
+                                
+                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // "name":value pair
+                                    $key = $this->decode($parts[1]);
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // name:value pair, where name is unquoted
+                                    $key = $parts[1];
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                }
+
+                            }
+
+                        } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+                            // found a quote, and we are not inside a string
+                            array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+                            //print("Found start of string at {$c}\n");
+
+                        } elseif (($chrs{$c} == $top['delim']) &&
+                                 ($top['what'] == SERVICES_JSON_IN_STR) &&
+                                 ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
+                            // found a quote, we're in a string, and it's not escaped
+                            // we know that it's not escaped becase there is _not_ an
+                            // odd number of backslashes at the end of the string so far
+                            array_pop($stk);
+                            //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '[') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-bracket, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+                            //print("Found start of array at {$c}\n");
+
+                        } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+                            // found a right-bracket, and we're in an array
+                            array_pop($stk);
+                            //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '{') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-brace, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+                            //print("Found start of object at {$c}\n");
+
+                        } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+                            // found a right-brace, and we're in an object
+                            array_pop($stk);
+                            //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($substr_chrs_c_2 == '/*') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a comment start, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+                            $c++;
+                            //print("Found start of comment at {$c}\n");
+
+                        } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+                            // found a comment end, and we're in one now
+                            array_pop($stk);
+                            $c++;
+
+                            for ($i = $top['where']; $i <= $c; ++$i)
+                                $chrs = substr_replace($chrs, ' ', $i, 1);
+
+                            //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        }
+
+                    }
+
+                    if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                        return $arr;
+
+                    } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                        return $obj;
+
+                    }
+
+                }
+        }
+    }
+
+    /**
+     * @todo Ultimately, this should just call PEAR::isError()
+     */
+    function isError($data, $code = null)
+    {
+        if (class_exists('pear')) {
+            return PEAR::isError($data, $code);
+        } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
+                                 is_subclass_of($data, 'services_json_error'))) {
+            return true;
+        }
+
+        return false;
+    }
+}
+
+if (class_exists('PEAR_Error')) {
+
+    class Services_JSON_Error extends PEAR_Error
+    {
+        function Services_JSON_Error($message = 'unknown error', $code = null,
+                                     $mode = null, $options = null, $userinfo = null)
+        {
+            parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
+        }
+    }
+
+} else {
+
+    /**
+     * @todo Ultimately, this class shall be descended from PEAR_Error
+     */
+    class Services_JSON_Error
+    {
+        function Services_JSON_Error($message = 'unknown error', $code = null,
+                                     $mode = null, $options = null, $userinfo = null)
+        {
+
+        }
+    }
+
+}
+    
+?>

Added: trunk/MgDev/Doc/samples/phpviewersample/ajaxtiledviewersample.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/ajaxtiledviewersample.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/ajaxtiledviewersample.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,52 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+
+<?php
+    include 'utilityfunctions.php';
+
+    // Initialize a PHP session and register a variable to hold the
+    // Server session id, then initialize the Web Extensions,
+    // and connect to the Server, and create a session.
+
+    MgInitializeWebTier($configFilePath);
+
+	$site = new MgSite();
+	$site->Open(new MgUserInformation('Anonymous', ''));
+
+	$sessionId = $site->CreateSession();
+	$webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganPhpTiled.WebLayout";
+?>
+
+<html>
+
+<head>
+    <title>Viewer Sample Application</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+</head>
+
+<frameset rows="50,*" frameborder="NO" border="0" framespacing="0">
+    <frame src="title.html?AppName=AJAX" name="TitleFrame" scrolling="NO" noresize>
+    <frame src="../mapviewerphp/ajaxviewer.php?SESSION=<?php echo $sessionId; ?>&WEBLAYOUT=<?php echo $webLayout; ?>" name="ViewerFrame">
+</frameset>
+
+</html>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/ajaxviewersample.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/ajaxviewersample.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/ajaxviewersample.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,52 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+
+<?php
+    include 'utilityfunctions.php';
+
+    // Initialize a PHP session and register a variable to hold the
+    // Server session id, then initialize the Web Extensions,
+    // and connect to the Server, and create a session.
+
+    MgInitializeWebTier($configFilePath);
+
+	$site = new MgSite();
+	$site->Open(new MgUserInformation('Anonymous', ''));
+
+	$sessionId = $site->CreateSession();
+	$webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganPhp.WebLayout";
+?>
+
+<html>
+
+<head>
+    <title>Viewer Sample Application</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+</head>
+
+<frameset rows="50,*" frameborder="NO" border="0" framespacing="0">
+    <frame src="title.html?AppName=AJAX" name="TitleFrame" scrolling="NO" noresize>
+    <frame src="../mapviewerphp/ajaxviewer.php?SESSION=<?php echo $sessionId; ?>&WEBLAYOUT=<?php echo $webLayout; ?>" name="ViewerFrame">
+</frameset>
+
+</html>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/dwfviewersample.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/dwfviewersample.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/dwfviewersample.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,52 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+
+<?php
+    include 'utilityfunctions.php';
+
+    // Initialize a PHP session and register a variable to hold the
+    // Server session id, then initialize the Web Extensions,
+    // and connect to the Server, and create a session.
+
+    MgInitializeWebTier($configFilePath);
+
+	$site = new MgSite();
+	$site->Open(new MgUserInformation('Anonymous', ''));
+
+	$sessionId = $site->CreateSession();
+	$webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganPhp.WebLayout";
+?>
+
+<html>
+
+<head>
+    <title>Viewer Sample Application</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+</head>
+
+<frameset rows="50,*" frameborder="NO" border="0" framespacing="0">
+    <frame src="title.html?AppName=AJAX" name="TitleFrame" scrolling="NO" noresize>
+    <frame src="../mapviewerphp/dwfviewer.php?SESSION=<?php echo $sessionId; ?>&WEBLAYOUT=<?php echo $webLayout; ?>" name="ViewerFrame">
+</frameset>
+
+</html>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/findaddress/clearaddressresults.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/findaddress/clearaddressresults.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/findaddress/clearaddressresults.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,95 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Viewer Sample Application - Clear Address Results</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <meta http-equiv="content-script-type" content="text/javascript">
+</head>
+
+<?php
+    include '../utilityfunctions.php';
+
+    $mgSessionId = ($_SERVER['REQUEST_METHOD'] == "POST")? $_POST['SESSION']: $_GET['SESSION'];
+
+    try
+    {
+        // Initialize the Web Extensions and connect to the Server using
+        // the Web Extensions session identifier stored in PHP session state.
+
+        MgInitializeWebTier($configFilePath);
+
+        $userInfo = new MgUserInformation($mgSessionId);
+        $siteConnection = new MgSiteConnection();
+        $siteConnection->Open($userInfo);
+
+        $featureService = $siteConnection->CreateService(MgServiceType::FeatureService);
+
+        $addressMarkerDataResId = new MgResourceIdentifier("Session:" . $mgSessionId . "//AddressMarker.FeatureSource");
+
+        $commands = new MgFeatureCommandCollection();
+        $commands->Add(new MgDeleteFeatures('AddressMarker', "ID like '%'"));
+
+        $featureService->UpdateFeatures($addressMarkerDataResId, $commands, false);
+
+        // Create a ReserviceService object and use it to open the Map
+        // object from the sessions repository. Use the Map object to hide
+        // the "ParcelMarker" layer and then save the updated Map back to
+        // the session.
+
+        $resourceService = $siteConnection->CreateService(MgServiceType::ResourceService);
+        $map = new MgMap();
+        $map->Open($resourceService, 'Sheboygan');
+
+        $layer = GetLayerByName($map, 'AddressMarker');
+        $layer->SetVisible(false);
+        $layer->ForceRefresh();
+
+        $map->Save($resourceService);
+    }
+    catch (MgException $e)
+    {
+        echo $e->GetMessage();
+        echo $e->GetDetails();
+    }
+?>
+
+<!-- Finally emit this function and assocate it with the onLoad event  -->
+<!-- for the page so that it gets executed when this page loads in the -->
+<!-- browser. The function calls the Refresh method on the Viewer      -->
+<!-- frame forcing the Viewer to update itself to match the state of   -->
+<!-- the Server-Side Map object.                                       -->
+
+<script language=javascript>
+function OnPageLoad()
+{
+   parent.Refresh();
+   parent.taskFrame.taskPaneFrame.location.href = "findaddressmain.php?SESSION=<?php echo $mgSessionId; ?>";
+}
+</script>
+
+<body onLoad="OnPageLoad()">
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddress.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddress.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddress.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,194 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Viewer Sample Application - Find Address</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+
+    <script language=javascript>
+        function InitDocument()
+        {
+            this.ZoomToResult();
+        }
+    </script>
+</head>
+
+<body onload="InitDocument()">
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Find Address<hr></td></tr>
+    <tr><td class="SubTitle">Search Results</td></tr>
+
+<?php
+    include '../utilityfunctions.php';
+    include 'findaddressfunctions.php';
+
+    // Include the xmlrpc library.
+    require_once('kd_xmlrpc.php');
+
+    $mgSessionId = ($_SERVER['REQUEST_METHOD'] == "POST")? $_POST['SESSION']: $_GET['SESSION'];
+    $success = false;
+    $long = 0; $lat = 0;
+
+    try
+    {
+        // Initialize the Web Extensions and connect to the Server using
+        // the Web Extensions session identifier stored in PHP session state.
+
+        MgInitializeWebTier ($configFilePath);
+
+        $userInfo = new MgUserInformation($mgSessionId);
+        $siteConnection = new MgSiteConnection();
+        $siteConnection->Open($userInfo);
+
+        $address = $_GET['address'] . ', Sheboygan, WI';
+
+        // Make the request to geocoder.us passing the address.
+        list($success, $response) = XMLRPC_request('rpc.geocoder.us', '/service/xmlrpc', 'geocode', array(XMLRPC_prepare($address)));
+
+        // Stuff the response into a new variable:
+        $nested_array = $response;
+
+        // For some reason (presumably a good one), geocoder.us responds with a nested
+        // array. We need to extract the inner array from the outer and stuff it into a
+        // new variable:
+        $geoarray = array_pop($nested_array);
+
+        // The $success variable is intended for error handling, but since geocoder.us
+        // will send an error response to invalid queries (thus flagging $success to 1),
+        // we can't use this to check for errors. Instead, we'll check the values in the
+        // array and deem success or failure based on that.
+
+        if (array_key_exists('lat', $geoarray) && array_key_exists('long', $geoarray))
+        {
+            // The geocode successfully returned a location.
+
+            $lat = $geoarray['lat'];
+            $long = $geoarray['long'];
+
+            // Build an address1 and address2 variables from the result.
+            $address1 = $geoarray['number'] . ' '
+                . (strlen($geoarray['prefix']) > 0 ? $geoarray['prefix'] . ' ' : '')
+                . (strlen($geoarray['street']) > 0 ? $geoarray['street'] . ' ' : '')
+                . (strlen($geoarray['type']) > 0 ? $geoarray['type'] . ' ' : '')
+                . (strlen($geoarray['suffix']) > 0 ? $geoarray['suffix'] . ' ' : '');
+
+            $address2 = $geoarray['city']
+                . ', ' . $geoarray['state']
+                . '  ' . $geoarray['zip'];
+
+            echo '<tr><td><img src="../images/pushpinblue.jpg">';
+            echo '<a href="gotopoint.php?X=' . $long . '&Y=' . $lat . '&Scale=2000" target="scriptFrame"> ' . $address1 . '</a></td></tr>';
+            echo '<tr><td>' . $address2 . '</td></tr>';
+            echo '<tr><td class="Spacer"></td></tr>';
+            echo '<tr><td>Longitude: ' . $long . '</td></tr>';
+            echo '<tr><td>Latitude: ' . $lat . '<hr></td></tr>';
+
+            // Create ResourceService and FeatureService objects and use
+            // the ResourceService object to open the map instance in
+            // session state.
+
+            $resourceService = $siteConnection->CreateService(MgServiceType::ResourceService);
+            $featureService = $siteConnection->CreateService(MgServiceType::FeatureService);
+
+            $map = new MgMap();
+            $map->Open($resourceService, 'Sheboygan');
+
+            // Check the map for the AddressMarker layer. If it does not
+            // exist then create a feature source to store address results
+            // and a layer to display them.
+
+            $addressMarkerDataResId = new MgResourceIdentifier("Session:" . $mgSessionId . "//AddressMarker.FeatureSource");
+            $addressLayer = GetLayerByName($map, 'AddressMarker');
+            if ($addressLayer == null)
+            {
+                CreateAddressMarkerFeatureSource($featureService, $addressMarkerDataResId);
+                $addressLayer = CreateAddressMarkerLayer($resourceService, $addressMarkerDataResId, $mgSessionId);
+
+                $map->GetLayers()->Insert(0, $addressLayer);
+            }
+            else if ($addressLayer->GetVisible())
+            {
+                // If the layer exists and is visible, then display the
+                // previous results.
+
+                EmitAddressResults($featureService, $addressMarkerDataResId, $mgSessionId);
+            }
+
+            // Insert the results of the Geo-Code into the temporary
+            // feature source and ensure the address marker layer
+            // is visible.
+
+            $geometryReaderWriter = new MgAgfReaderWriter();
+            $geometryFactory = new MgGeometryFactory();
+            $addrPoint = $geometryFactory->CreatePoint($geometryFactory->CreateCoordinateXY((double)$long, (double)$lat));
+
+            $properties = new MgPropertyCollection();
+            $properties->Add(new MgStringProperty('Address', $address1));
+            $properties->Add(new MgGeometryProperty('Location', $geometryReaderWriter->Write($addrPoint)));
+
+            $commands = new MgFeatureCommandCollection();
+            $commands->Add(new MgInsertFeatures('AddressMarker', $properties));
+
+            $featureService->UpdateFeatures($addressMarkerDataResId, $commands, false);
+
+            $addressLayer->SetVisible(true);
+            $addressLayer->ForceRefresh();
+
+            $map->Save($resourceService);
+
+            $success = true;
+        }
+        else
+        {
+            echo '<tr><td>Address not found: ' . $address . '<hr></td></tr>';
+            $success = false;
+        }
+    }
+    catch (MgException $e)
+    {
+        echo $e->GetMessage();
+        echo '<br>';
+        echo $e->GetDetails();
+    }
+?>
+
+</table>
+
+Geocoding Provided by: <a href="http://geocoder.us/" target="_blank">geocoder.us</a>.<br>
+Locative Tecnologies offers the free geocoder.us web service for non commercial purposes. If you wish to use this geocoding web service in an production application you must sign up for a commercial license. Click the link above for more information.
+
+</body>
+
+<script language=javascript>
+function ZoomToResult()
+{
+    success = <?php echo $success == true? "true": "false"; ?>;
+    if(success)
+        parent.parent.ZoomToView(<?php echo $long; ?>, <?php echo $lat; ?>, 2000, true);
+}
+</script>
+
+</html>

Added: trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddressfunctions.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddressfunctions.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddressfunctions.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,132 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+function EmitAddressResults($featureService, $addressMarkerDataResId, $mgSessionId)
+{
+    echo '<table class="RegText" border="0" cellspacing="0" width="100%">';
+    echo '<tr><td class="SubTitle">Previous Results</td></tr>';
+
+    $geometryReaderWriter = new MgAgfReaderWriter();
+    $featureReader = $featureService->SelectFeatures($addressMarkerDataResId, 'AddressMarker', null);
+
+    while ($featureReader->ReadNext())
+    {
+        $address = $featureReader->GetString('Address');
+        $byteReader = $featureReader->GetGeometry('Location');
+
+        $geometry = $geometryReaderWriter->Read($byteReader);
+        $x = $geometry->GetCoordinate()->GetX();
+        $y = $geometry->GetCoordinate()->GetY();
+
+        echo '<tr><td>';
+        echo '<img src="../images/pushpinblue.jpg">';
+        echo '<a href="gotopoint.php?X=' . $x . '&Y=' . $y . '&Scale=2000" target="scriptFrame"> ' . $address . '</a></td></tr>';
+    }
+    $featureReader->Close();
+
+    echo '</table>';
+    echo '<form action="clearaddressresults.php" method="get" target="scriptFrame">';
+    echo '<input type="hidden" name="SESSION" value="' . $mgSessionId . '">';
+    echo '<input type="button" class="Ctrl" value="Clear Results" onClick="javascript:submit()">';
+    echo '</form>';
+    echo '<hr>';
+}
+
+// Create a temporary Feature Source to store geocode results.
+
+function CreateAddressMarkerFeatureSource($featureService, $addressMarkerDataResId)
+{
+    $ll84Wkt = 'GEOGCS["WGS84 Lat/Long\'s, Degrees, -180 ==> +180",DATUM["D_WGS_1984",SPHEROID["World_Geodetic_System_of_1984",6378137,298.257222932867]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]';
+
+    $addressClass = new MgClassDefinition();
+    $addressClass->SetName('AddressMarker');
+    $properties = $addressClass->GetProperties();
+
+    $idProperty = new MgDataPropertyDefinition('ID');
+    $idProperty->SetDataType(MgPropertyType::Int32);
+    $idProperty->SetReadOnly(true);
+    $idProperty->SetNullable(false);
+    $idProperty->SetAutoGeneration(true);
+    $properties->Add($idProperty);
+
+    $addressProperty = new MgDataPropertyDefinition('Address');
+    $addressProperty->SetDataType(MgPropertyType::String);
+    $addressProperty->SetLength(512);
+    $properties->Add($addressProperty);
+
+    $locationProperty = new MgGeometricPropertyDefinition('Location');
+    $locationProperty->SetGeometryTypes(MgGeometryType::Point);
+    $locationProperty->SetHasElevation(false);
+    $locationProperty->SetHasMeasure(false);
+    $locationProperty->SetReadOnly(false);
+    $locationProperty->SetSpatialContextAssociation('LL84');
+    $properties->Add($locationProperty);
+
+    $idProperties = $addressClass->GetIdentityProperties();
+    $idProperties->Add($idProperty);
+
+    $addressClass->SetDefaultGeometryPropertyName('Location');
+
+    $addressSchema = new MgFeatureSchema();
+    $addressSchema->SetName('AddressMarkerSchema');
+    $addressSchema->GetClasses()->Add($addressClass);
+
+    $sdfParams = new MgCreateSdfParams('LL84', $ll84Wkt, $addressSchema);
+
+    $featureService->CreateFeatureSource($addressMarkerDataResId, $sdfParams);
+}
+
+// Create a temporary Layer to display geocode results.
+
+function CreateAddressMarkerLayer($resourceService, $addressMarkerDataResId, $sessionId)
+{
+    // Load the AddressMarker layer definition template into
+    // a PHP DOM object, find the "ResourceId" element, and
+    // modify it's content to reference the temporary
+    // feature source.
+
+    $doc = DOMDocument::load(GetXmlPath());
+    $featureSourceNode = $doc->getElementsByTagName('ResourceId')->item(0);
+    $featureSourceNode->nodeValue = $addressMarkerDataResId->ToString();
+
+    // Get the updated layer definition from the DOM object
+    // and save it to the session repository using the
+    // ResourceService object.
+
+    $layerDefinition = $doc->saveXML();
+    $byteSource = new MgByteSource($layerDefinition, strlen($layerDefinition));
+    $byteSource->SetMimeType(MgMimeType::Xml);
+
+    $tempLayerResId = new MgResourceIdentifier("Session:" . $sessionId . "//AddressMarker.LayerDefinition");
+
+    $resourceService->SetResource($tempLayerResId, $byteSource->GetReader(), null);
+
+    // Create an MgLayer object based on the new layer definition
+    // and return it to the caller.
+
+    $addressLayer = new MgLayer($tempLayerResId, $resourceService);
+    $addressLayer->SetName("AddressMarker");
+    $addressLayer->SetLegendLabel("AddressMarker");
+    $addressLayer->SetDisplayInLegend(false);
+    $addressLayer->SetSelectable(false);
+
+    return $addressLayer;
+}
+
+?>

Added: trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddressmain.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddressmain.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/findaddress/findaddressmain.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,128 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Find Address Task</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+
+    <script language="javascript">
+    function Submit()
+    {
+    	var addressForm = document.getElementById("addressForm");
+    	var addressValue = document.getElementById("addressValue");
+    	var addressInput = document.getElementById("addressInput");
+
+    	addressValue.value = addressInput.value;
+    	addressForm.submit();
+    }
+    </script>
+</head>
+
+<body>
+
+<?php
+    include '../utilityfunctions.php';
+    include 'findaddressfunctions.php';
+
+    $mgSessionId = ($_SERVER['REQUEST_METHOD'] == "POST")? $_POST['SESSION']: $_GET['SESSION'];
+    $showPreviousResults = false;
+
+    try
+    {
+        // Initialize the Web Extensions and connect to the Server using
+        // the Web Extensions session identifier stored in PHP session state.
+
+        MgInitializeWebTier($configFilePath);
+
+        $userInfo = new MgUserInformation($mgSessionId);
+        $siteConnection = new MgSiteConnection();
+        $siteConnection->Open($userInfo);
+
+        // Create a ReserviceService object and use it to open the Map
+        // object from the sessions repository. Use the Map object to
+        // determine if the "AddressMarker" layer is visible.
+
+        $resourceService = $siteConnection->CreateService(MgServiceType::ResourceService);
+        $map = new MgMap();
+        $map->Open($resourceService, 'Sheboygan');
+        $addressLayer = GetLayerByName($map, 'AddressMarker');
+
+        if ($addressLayer != null)
+        {
+            $showPreviousResults = $addressLayer->GetVisible();
+        }
+    }
+    catch (MgException $e)
+    {
+        echo $e->GetMessage();
+        echo $e->GetDetails();
+    }
+?>
+
+<form id="addressForm" action="findaddress.php" method="get" target="_self">
+    <input name="SESSION" type="hidden" value="<?php echo $mgSessionId; ?>">
+    <input id="addressValue" name="address" type="hidden" value="">
+</form>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Find Address<hr></td></tr>
+    <tr><td class="SubTitle">Search for an Address</td></tr>
+    <tr><td>Address:</td></tr>
+    <tr>
+        <td class="RegText">
+        <input maxlength="100" class="Ctrl" id="addressInput" style="width: 95%">
+        </td>
+    </tr>
+    <tr><td><strong>Sheboygan, WI</strong></td></tr>
+    <tr>
+        <td>
+        <input class="Ctrl" type="button" onClick="Submit()" value="Find" style="width:60px">
+        </td>
+    </tr>
+
+    <tr><td><hr>Hint try:</td></tr>
+    <tr><td>&nbsp;&nbsp;601 North 5th Street</td></tr>
+    <tr><td>&nbsp;&nbsp;720 Riverfront Drive<hr></td></tr>
+</table>
+
+<?php
+    // If there are previous results, display them as hyperlinks and emit
+    // a second form with a Clear Results button.
+
+    if ($showPreviousResults)
+    {
+        $featureService = $siteConnection->CreateService(MgServiceType::FeatureService);
+        $addressMarkerDataResId = new MgResourceIdentifier("Session:" . $mgSessionId . "//AddressMarker.FeatureSource");
+
+        EmitAddressResults($featureService, $addressMarkerDataResId, $mgSessionId);
+    }
+?>
+
+Geocoding Provided by: <a href="http://geocoder.us/" target="_blank">geocoder.us</a>.<br>
+Locative Tecnologies offers the free geocoder.us web service for non commercial purposes. If you wish to use this geocoding web service in an production application you must sign up for a commercial license. Click the link above for more information.
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/phpviewersample/findaddress/gotopoint.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/findaddress/gotopoint.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/findaddress/gotopoint.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,50 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Viewer Sample Application- Goto Point</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <meta http-equiv="content-script-type" content="text/javascript">
+</head>
+
+<!-- Emit this function and assocate it with the onLoad event for the -->
+<!-- page so that it gets executed when this page loads in the        -->
+<!-- browser. The function calls the ZoomToView method on the         -->
+<!-- Viewer frame forcing the Viewer to navigate to the specified     -->
+<!-- point and scale.                                                 -->
+
+<script language="javascript">
+
+function OnPageLoad()
+{
+    parent.ZoomToView(<?php echo $_GET['X']; ?>, <?php echo $_GET['Y']; ?>, <?php echo $_GET['Scale']; ?>, true);
+}
+
+</script>
+
+<body onLoad="OnPageLoad()">
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/phpviewersample/findaddress/kd_xmlrpc.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/findaddress/kd_xmlrpc.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/findaddress/kd_xmlrpc.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,498 @@
+<?php
+/*
+An XML-RPC implementation by Keith Devens, version 2.5f.
+http://www.keithdevens.com/software/xmlrpc/
+
+Release history available at:
+http://www.keithdevens.com/software/xmlrpc/history/
+
+This code is Open Source, released under terms similar to the Artistic License.
+Read the license at http://www.keithdevens.com/software/license/
+
+Note: this code requires version 4.1.0 or higher of PHP.
+*/
+
+function & XML_serialize(&$data, $level = 0, $prior_key = NULL){
+    #assumes a hash, keys are the variable names
+    $xml_serialized_string = "";
+    while(list($key, $value) = each($data)){
+        $inline = false;
+        $numeric_array = false;
+        $attributes = "";
+        #echo "My current key is '$key', called with prior key '$prior_key'<br>";
+        if(!strstr($key, " attr")){ #if it's not an attribute
+            if(array_key_exists("$key attr", $data)){
+                while(list($attr_name, $attr_value) = each($data["$key attr"])){
+                    #echo "Found attribute $attribute_name with value $attribute_value<br>";
+                    $attr_value = &htmlspecialchars($attr_value, ENT_QUOTES);
+                    $attributes .= " $attr_name=\"$attr_value\"";
+                }
+            }
+
+            if(is_numeric($key)){
+                #echo "My current key ($key) is numeric. My parent key is '$prior_key'<br>";
+                $key = $prior_key;
+            }else{
+                #you can't have numeric keys at two levels in a row, so this is ok
+                #echo "Checking to see if a numeric key exists in data.";
+                if(is_array($value) and array_key_exists(0, $value)){
+                #   echo " It does! Calling myself as a result of a numeric array.<br>";
+                    $numeric_array = true;
+                    $xml_serialized_string .= XML_serialize($value, $level, $key);
+                }
+                #echo "<br>";
+            }
+
+            if(!$numeric_array){
+                $xml_serialized_string .= str_repeat("\t", $level) . "<$key$attributes>";
+
+                if(is_array($value)){
+                    $xml_serialized_string .= "\r\n" . XML_serialize($value, $level+1);
+                }else{
+                    $inline = true;
+                    $xml_serialized_string .= htmlspecialchars($value);
+                }
+
+                $xml_serialized_string .= (!$inline ? str_repeat("\t", $level) : "") . "</$key>\r\n";
+            }
+        }else{
+            #echo "Skipping attribute record for key $key<bR>";
+        }
+    }
+    if($level == 0){
+        $xml_serialized_string = "<?xml version=\"1.0\" ?>\r\n" . $xml_serialized_string;
+        return $xml_serialized_string;
+    }else{
+        return $xml_serialized_string;
+    }
+}
+
+class XML {
+    var $parser; #a reference to the XML parser
+    var $document; #the entire XML structure built up so far
+    var $current; #a pointer to the current item - what is this
+    var $parent; #a pointer to the current parent - the parent will be an array
+    var $parents; #an array of the most recent parent at each level
+
+    var $last_opened_tag;
+
+    function XML($data=null){
+        $this->parser = xml_parser_create();
+
+        xml_parser_set_option ($this->parser, XML_OPTION_CASE_FOLDING, 0);
+        xml_set_object($this->parser, &$this);
+        xml_set_element_handler($this->parser, "open", "close");
+        xml_set_character_data_handler($this->parser, "data");
+#       register_shutdown_function(array(&$this, 'destruct'));
+    }
+
+    function destruct(){
+        xml_parser_free($this->parser);
+    }
+
+    function parse($data){
+        $this->document = array();
+        $this->parent = &$this->document;
+        $this->parents = array();
+        $this->last_opened_tag = NULL;
+        xml_parse($this->parser, $data);
+        return $this->document;
+    }
+
+    function open($parser, $tag, $attributes){
+        #echo "Opening tag $tag<br>\n";
+        $this->data = "";
+        $this->last_opened_tag = $tag; #tag is a string
+        if(array_key_exists($tag, $this->parent)){
+            #echo "There's already an instance of '$tag' at the current level ($level)<br>\n";
+            if(is_array($this->parent[$tag]) and array_key_exists(0, $this->parent[$tag])){ #if the keys are numeric
+                #need to make sure they're numeric (account for attributes)
+                $key = count_numeric_items($this->parent[$tag]);
+                #echo "There are $key instances: the keys are numeric.<br>\n";
+            }else{
+                #echo "There is only one instance. Shifting everything around<br>\n";
+                $temp = &$this->parent[$tag];
+                unset($this->parent[$tag]);
+                $this->parent[$tag][0] = &$temp;
+
+                if(array_key_exists("$tag attr", $this->parent)){
+                    #shift the attributes around too if they exist
+                    $temp = &$this->parent["$tag attr"];
+                    unset($this->parent["$tag attr"]);
+                    $this->parent[$tag]["0 attr"] = &$temp;
+                }
+                $key = 1;
+            }
+            $this->parent = &$this->parent[$tag];
+        }else{
+            $key = $tag;
+        }
+        if($attributes){
+            $this->parent["$key attr"] = $attributes;
+        }
+
+        $this->parent[$key] = array();
+        $this->parent = &$this->parent[$key];
+        array_unshift($this->parents, &$this->parent);
+    }
+
+    function data($parser, $data){
+        #echo "Data is '", htmlspecialchars($data), "'<br>\n";
+        if($this->last_opened_tag != NULL){
+            $this->data .= $data;
+        }
+    }
+
+    function close($parser, $tag){
+        #echo "Close tag $tag<br>\n";
+        if($this->last_opened_tag == $tag){
+            $this->parent = $this->data;
+            $this->last_opened_tag = NULL;
+        }
+        array_shift($this->parents);
+        $this->parent = &$this->parents[0];
+    }
+}
+
+function & XML_unserialize(&$xml){
+    $xml_parser = new XML();
+    $data = &$xml_parser->parse(&$xml);
+    $xml_parser->destruct();
+    return $data;
+}
+
+function & XMLRPC_parse(&$request){
+    if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+        XMLRPC_debug('XMLRPC_parse', "<p>Received the following raw request:</p>" . XMLRPC_show($request, 'print_r', true));
+    }
+    $data = &XML_unserialize(&$request);
+    if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+        XMLRPC_debug('XMLRPC_parse', "<p>Returning the following parsed request:</p>" . XMLRPC_show($data, 'print_r', true));
+    }
+    return $data;
+}
+
+function & XMLRPC_prepare($data, $type = NULL){
+    if(is_array($data)){
+        $num_elements = count($data);
+        if((array_key_exists(0, $data) or !$num_elements) and $type != 'struct'){ #it's an array
+            if(!$num_elements){ #if the array is empty
+                $returnvalue =  array('array' => array('data' => NULL));
+            }else{
+                $returnvalue['array']['data']['value'] = array();
+                $temp = &$returnvalue['array']['data']['value'];
+                $count = count_numeric_items($data);
+                for($n=0; $n<$count; $n++){
+                    $type = NULL;
+                    if(array_key_exists("$n type", $data)){
+                        $type = $data["$n type"];
+                    }
+                    $temp[$n] = XMLRPC_prepare(&$data[$n], $type);
+                }
+            }
+        }else{ #it's a struct
+            if(!$num_elements){ #if the struct is empty
+                $returnvalue = array('struct' => NULL);
+            }else{
+                $returnvalue['struct']['member'] = array();
+                $temp = &$returnvalue['struct']['member'];
+                while(list($key, $value) = each($data)){
+                    if(substr($key, -5) != ' type'){ #if it's not a type specifier
+                        $type = NULL;
+                        if(array_key_exists("$key type", $data)){
+                            $type = $data["$key type"];
+                        }
+                        $temp[] = array('name' => $key, 'value' => XMLRPC_prepare(&$value, $type));
+                    }
+                }
+            }
+        }
+    }else{ #it's a scalar
+        if(!$type){
+            if(is_int($data)){
+                $returnvalue['int'] = $data;
+                return $returnvalue;
+            }elseif(is_float($data)){
+                $returnvalue['double'] = $data;
+                return $returnvalue;
+            }elseif(is_bool($data)){
+                $returnvalue['boolean'] = ($data ? 1 : 0);
+                return $returnvalue;
+            }elseif(preg_match('/^\d{8}T\d{2}:\d{2}:\d{2}$/', $data, $matches)){ #it's a date
+                $returnvalue['dateTime.iso8601'] = $data;
+                return $returnvalue;
+            }elseif(is_string($data)){
+                $returnvalue['string'] = htmlspecialchars($data);
+                return $returnvalue;
+            }
+        }else{
+            $returnvalue[$type] = htmlspecialchars($data);
+        }
+    }
+    return $returnvalue;
+}
+
+function & XMLRPC_adjustValue(&$current_node){
+    if(is_array($current_node)){
+        if(isset($current_node['array'])){
+            if(!is_array($current_node['array']['data'])){
+                #If there are no elements, return an empty array
+                return array();
+            }else{
+                #echo "Getting rid of array -> data -> value<br>\n";
+                $temp = &$current_node['array']['data']['value'];
+                if(is_array($temp) and array_key_exists(0, $temp)){
+                    $count = count($temp);
+                    for($n=0;$n<$count;$n++){
+                        $temp2[$n] = &XMLRPC_adjustValue(&$temp[$n]);
+                    }
+                    $temp = &$temp2;
+                }else{
+                    $temp2 = &XMLRPC_adjustValue(&$temp);
+                    $temp = array(&$temp2);
+                    #I do the temp assignment because it avoids copying,
+                    # since I can put a reference in the array
+                    #PHP's reference model is a bit silly, and I can't just say:
+                    # $temp = array(&XMLRPC_adjustValue(&$temp));
+                }
+            }
+        }elseif(isset($current_node['struct'])){
+            if(!is_array($current_node['struct'])){
+                #If there are no members, return an empty array
+                return array();
+            }else{
+                #echo "Getting rid of struct -> member<br>\n";
+                $temp = &$current_node['struct']['member'];
+                if(is_array($temp) and array_key_exists(0, $temp)){
+                    $count = count($temp);
+                    for($n=0;$n<$count;$n++){
+                        #echo "Passing name {$temp[$n][name]}. Value is: " . show($temp[$n][value], var_dump, true) . "<br>\n";
+                        $temp2[$temp[$n]['name']] = &XMLRPC_adjustValue(&$temp[$n]['value']);
+                        #echo "adjustValue(): After assigning, the value is " . show($temp2[$temp[$n]['name']], var_dump, true) . "<br>\n";
+                    }
+                }else{
+                    #echo "Passing name $temp[name]<br>\n";
+                    $temp2[$temp['name']] = &XMLRPC_adjustValue(&$temp['value']);
+                }
+                $temp = &$temp2;
+            }
+        }else{
+            $types = array('string', 'int', 'i4', 'double', 'dateTime.iso8601', 'base64', 'boolean');
+            $fell_through = true;
+            foreach($types as $type){
+                if(array_key_exists($type, $current_node)){
+                    #echo "Getting rid of '$type'<br>\n";
+                    $temp = &$current_node[$type];
+                    #echo "adjustValue(): The current node is set with a type of $type<br>\n";
+                    $fell_through = false;
+                    break;
+                }
+            }
+            if($fell_through){
+                $type = 'string';
+                #echo "Fell through! Type is $type<br>\n";
+            }
+            switch ($type){
+                case 'int': case 'i4': $temp = (int)$temp;    break;
+                case 'string':         $temp = (string)$temp; break;
+                case 'double':         $temp = (double)$temp; break;
+                case 'boolean':        $temp = (bool)$temp;   break;
+            }
+        }
+    }else{
+        $temp = (string)$current_node;
+    }
+    return $temp;
+}
+
+function XMLRPC_getParams($request){
+    if(!is_array($request['methodCall']['params'])){
+        #If there are no parameters, return an empty array
+        return array();
+    }else{
+        #echo "Getting rid of methodCall -> params -> param<br>\n";
+        $temp = &$request['methodCall']['params']['param'];
+        if(is_array($temp) and array_key_exists(0, $temp)){
+            $count = count($temp);
+            for($n = 0; $n < $count; $n++){
+                #echo "Serializing parameter $n<br>";
+                $temp2[$n] = &XMLRPC_adjustValue(&$temp[$n]['value']);
+            }
+        }else{
+            $temp2[0] = &XMLRPC_adjustValue($temp['value']);
+        }
+        $temp = &$temp2;
+        return $temp;
+    }
+}
+
+function XMLRPC_getMethodName($methodCall){
+    #returns the method name
+    return $methodCall['methodCall']['methodName'];
+}
+
+function XMLRPC_request($site, $location, $methodName, $params = NULL, $user_agent = NULL){
+    $site = explode(':', $site);
+    if(isset($site[1]) and is_numeric($site[1])){
+        $port = $site[1];
+    }else{
+        $port = 80;
+    }
+    $site = $site[0];
+
+    $data["methodCall"]["methodName"] = $methodName;
+    $param_count = count($params);
+    if(!$param_count){
+        $data["methodCall"]["params"] = NULL;
+    }else{
+        for($n = 0; $n<$param_count; $n++){
+            $data["methodCall"]["params"]["param"][$n]["value"] = $params[$n];
+        }
+    }
+    $data = XML_serialize($data);
+
+    if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+        XMLRPC_debug('XMLRPC_request', "<p>Received the following parameter list to send:</p>" . XMLRPC_show($params, 'print_r', true));
+    }
+    $conn = fsockopen ($site, $port); #open the connection
+    if(!$conn){ #if the connection was not opened successfully
+        if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+            XMLRPC_debug('XMLRPC_request', "<p>Connection failed: Couldn't make the connection to $site.</p>");
+        }
+        return array(false, array('faultCode'=>10532, 'faultString'=>"Connection failed: Couldn't make the connection to $site."));
+    }else{
+        $headers =
+            "POST $location HTTP/1.0\r\n" .
+            "Host: $site\r\n" .
+            "Connection: close\r\n" .
+            ($user_agent ? "User-Agent: $user_agent\r\n" : '') .
+            "Content-Type: text/xml\r\n" .
+            "Content-Length: " . strlen($data) . "\r\n\r\n";
+
+        fputs($conn, "$headers");
+        fputs($conn, $data);
+
+        if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+            XMLRPC_debug('XMLRPC_request', "<p>Sent the following request:</p>\n\n" . XMLRPC_show($headers . $data, 'print_r', true));
+        }
+
+        #socket_set_blocking ($conn, false);
+        $response = "";
+        while(!feof($conn)){
+            $response .= fgets($conn, 1024);
+        }
+        fclose($conn);
+
+        #strip headers off of response
+
+        $responsesubstr = substr($response, strpos($response, "\r\n\r\n")+4);
+        $data = XML_unserialize($responsesubstr);
+
+        if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+            XMLRPC_debug('XMLRPC_request', "<p>Received the following response:</p>\n\n" . XMLRPC_show($response, 'print_r', true) . "<p>Which was serialized into the following data:</p>\n\n" . XMLRPC_show($data, 'print_r', true));
+        }
+        if(isset($data['methodResponse']['fault'])){
+            $return =  array(false, XMLRPC_adjustValue(&$data['methodResponse']['fault']['value']));
+            if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+                XMLRPC_debug('XMLRPC_request', "<p>Returning:</p>\n\n" . XMLRPC_show($return, 'var_dump', true));
+            }
+            return $return;
+        }else{
+            $return = array(true, XMLRPC_adjustValue(&$data['methodResponse']['params']['param']['value']));
+            if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+                XMLRPC_debug('XMLRPC_request', "<p>Returning:</p>\n\n" . XMLRPC_show($return, 'var_dump', true));
+            }
+            return $return;
+        }
+    }
+}
+
+function XMLRPC_response($return_value, $server = NULL){
+    $data["methodResponse"]["params"]["param"]["value"] = &$return_value;
+    $return = XML_serialize(&$data);
+
+    if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+        XMLRPC_debug('XMLRPC_response', "<p>Received the following data to return:</p>\n\n" . XMLRPC_show($return_value, 'print_r', true));
+    }
+
+    header("Connection: close");
+    header("Content-Length: " . strlen($return));
+    header("Content-Type: text/xml");
+    header("Date: " . date("r"));
+    if($server){
+        header("Server: $server");
+    }
+
+    if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+        XMLRPC_debug('XMLRPC_response', "<p>Sent the following response:</p>\n\n" . XMLRPC_show($return, 'print_r', true));
+    }
+    echo $return;
+}
+
+function XMLRPC_error($faultCode, $faultString, $server = NULL){
+    $array["methodResponse"]["fault"]["value"]["struct"]["member"] = array();
+    $temp = &$array["methodResponse"]["fault"]["value"]["struct"]["member"];
+    $temp[0]["name"] = "faultCode";
+    $temp[0]["value"]["int"] = $faultCode;
+    $temp[1]["name"] = "faultString";
+    $temp[1]["value"]["string"] = $faultString;
+
+    $return = XML_serialize($array);
+
+    header("Connection: close");
+    header("Content-Length: " . strlen($return));
+    header("Content-Type: text/xml");
+    header("Date: " . date("r"));
+    if($server){
+        header("Server: $server");
+    }
+    if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){
+        XMLRPC_debug('XMLRPC_error', "<p>Sent the following error response:</p>\n\n" . XMLRPC_show($return, 'print_r', true));
+    }
+    echo $return;
+}
+
+function XMLRPC_convert_timestamp_to_iso8601($timestamp){
+    #takes a unix timestamp and converts it to iso8601 required by XMLRPC
+    #an example iso8601 datetime is "20010822T03:14:33"
+    return date("Ymd\TH:i:s", $timestamp);
+}
+
+function XMLRPC_convert_iso8601_to_timestamp($iso8601){
+    return strtotime($iso8601);
+}
+
+function count_numeric_items(&$array){
+    return is_array($array) ? count(array_filter(array_keys($array), 'is_numeric')) : 0;
+}
+
+function XMLRPC_debug($function_name, $debug_message){
+    $GLOBALS['XMLRPC_DEBUG_INFO'][] = array($function_name, $debug_message);
+}
+
+function XMLRPC_debug_print(){
+    if($GLOBALS['XMLRPC_DEBUG_INFO']){
+        echo "<table border=\"1\" width=\"100%\">\n";
+        foreach($GLOBALS['XMLRPC_DEBUG_INFO'] as $debug){
+            echo "<tr><th style=\"vertical-align: top\">$debug[0]</th><td>$debug[1]</td></tr>\n";
+        }
+        echo "</table>\n";
+        unset($GLOBALS['XMLRPC_DEBUG_INFO']);
+    }else{
+        echo "<p>No debugging information available yet.</p>";
+    }
+}
+
+function XMLRPC_show($data, $func = "print_r", $return_str = false){
+    ob_start();
+    $func($data);
+    $output = ob_get_contents();
+    ob_end_clean();
+    if($return_str){
+        return "<pre>" . htmlspecialchars($output) . "</pre>\n";
+    }else{
+        echo "<pre>", htmlspecialchars($output), "</pre>\n";
+    }
+}
+
+?>

Added: trunk/MgDev/Doc/samples/phpviewersample/findaddress/templates/addressmarker.xml
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/findaddress/templates/addressmarker.xml	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/findaddress/templates/addressmarker.xml	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<LayerDefinition version="1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="LayerDefinition-1.0.0.xsd">
+  <VectorLayerDefinition>
+    <ResourceId></ResourceId>
+    <FeatureName>AddressMarker</FeatureName>
+    <FeatureNameType>FeatureClass</FeatureNameType>
+    <Geometry>Location</Geometry>
+    <VectorScaleRange>
+      <MaxScale>10000</MaxScale>
+      <PointTypeStyle>
+        <DisplayAsText>false</DisplayAsText>
+        <AllowOverpost>false</AllowOverpost>
+        <PointRule>
+          <LegendLabel></LegendLabel>
+          <Label>
+            <Unit>Points</Unit>
+            <SizeContext>DeviceUnits</SizeContext>
+            <SizeX>7</SizeX>
+            <SizeY>10</SizeY>
+            <Text>Address</Text>
+            <FontName>Verdana</FontName>
+            <ForegroundColor>FF000000</ForegroundColor>
+            <BackgroundColor>FFFFFFFF</BackgroundColor>
+            <BackgroundStyle>Ghosted</BackgroundStyle>
+            <HorizontalAlignment>&apos;Center&apos;</HorizontalAlignment>
+            <VerticalAlignment>&apos;Baseline&apos;</VerticalAlignment>
+          </Label>
+          <PointSymbolization2D>
+            <W2D>
+              <Unit>Millimeters</Unit>
+              <SizeContext>DeviceUnits</SizeContext>
+              <SizeX>15</SizeX>
+              <SizeY>15</SizeY>
+              <W2DSymbol>
+                <ResourceId>Library://Samples/Sheboygan/Symbols/BasicSymbols.SymbolLibrary</ResourceId>
+                <LibraryItemName>PushPin - Blue</LibraryItemName>
+              </W2DSymbol>
+            </W2D>
+          </PointSymbolization2D>
+        </PointRule>
+      </PointTypeStyle>
+    </VectorScaleRange>
+    <VectorScaleRange>
+      <PointTypeStyle>
+        <DisplayAsText>false</DisplayAsText>
+        <AllowOverpost>false</AllowOverpost>
+        <PointRule>
+          <LegendLabel></LegendLabel>
+          <PointSymbolization2D>
+            <W2D>
+              <Unit>Millimeters</Unit>
+              <SizeContext>DeviceUnits</SizeContext>
+              <SizeX>15</SizeX>
+              <SizeY>15</SizeY>
+              <W2DSymbol>
+                <ResourceId>Library://Samples/Sheboygan/Symbols/BasicSymbols.SymbolLibrary</ResourceId>
+                <LibraryItemName>PushPin - Blue</LibraryItemName>
+              </W2DSymbol>
+            </W2D>
+          </PointSymbolization2D>
+        </PointRule>
+      </PointTypeStyle>
+    </VectorScaleRange>
+  </VectorLayerDefinition>
+</LayerDefinition>

Added: trunk/MgDev/Doc/samples/phpviewersample/images/Thumbs.db
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/phpviewersample/images/Thumbs.db
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/phpviewersample/images/loader_inactive.gif
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/phpviewersample/images/loader_inactive.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/phpviewersample/images/loader_pulse.gif
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/phpviewersample/images/loader_pulse.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/phpviewersample/images/pushpin.jpg
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/phpviewersample/images/pushpin.jpg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/phpviewersample/images/pushpinblue.jpg
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/Doc/samples/phpviewersample/images/pushpinblue.jpg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/Doc/samples/phpviewersample/json.js
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/json.js	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/json.js	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,120 @@
+/*
+    json.js
+    2006-04-28
+
+    This file adds these methods to JavaScript:
+
+        object.toJSONString()
+
+            This method produces a JSON text from an object. The
+            object must not contain any cyclical references.
+
+        array.toJSONString()
+
+            This method produces a JSON text from an array. The
+            array must not contain any cyclical references.
+
+        string.parseJSON()
+
+            This method parses a JSON text to produce an object or
+            array. It will return false if there is an error.
+*/
+(function () {
+    var m = {
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        },
+        s = {
+            array: function (x) {
+                var a = ['['], b, f, i, l = x.length, v;
+                for (i = 0; i < l; i += 1) {
+                    v = x[i];
+                    f = s[typeof v];
+                    if (f) {
+                        v = f(v);
+                        if (typeof v == 'string') {
+                            if (b) {
+                                a[a.length] = ',';
+                            }
+                            a[a.length] = v;
+                            b = true;
+                        }
+                    }
+                }
+                a[a.length] = ']';
+                return a.join('');
+            },
+            'boolean': function (x) {
+                return String(x);
+            },
+            'null': function (x) {
+                return "null";
+            },
+            number: function (x) {
+                return isFinite(x) ? String(x) : 'null';
+            },
+            object: function (x) {
+                if (x) {
+                    if (x instanceof Array) {
+                        return s.array(x);
+                    }
+                    var a = ['{'], b, f, i, v;
+                    for (i in x) {
+                        v = x[i];
+                        f = s[typeof v];
+                        if (f) {
+                            v = f(v);
+                            if (typeof v == 'string') {
+                                if (b) {
+                                    a[a.length] = ',';
+                                }
+                                a.push(s.string(i), ':', v);
+                                b = true;
+                            }
+                        }
+                    }
+                    a[a.length] = '}';
+                    return a.join('');
+                }
+                return 'null';
+            },
+            string: function (x) {
+                if (/["\\\x00-\x1f]/.test(x)) {
+                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+                        var c = m[b];
+                        if (c) {
+                            return c;
+                        }
+                        c = b.charCodeAt();
+                        return '\\u00' +
+                            Math.floor(c / 16).toString(16) +
+                            (c % 16).toString(16);
+                    });
+                }
+                return '"' + x + '"';
+            }
+        };
+
+    Object.prototype.toJSONString = function () {
+        return s.object(this);
+    };
+
+    Array.prototype.toJSONString = function () {
+        return s.array(this);
+    };
+})();
+
+String.prototype.parseJSON = function () {
+    try {
+        return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
+                this.replace(/"(\\.|[^"\\])*"/g, ''))) &&
+            eval('(' + this + ')');
+    } catch (e) {
+        return false;
+    }
+};

Added: trunk/MgDev/Doc/samples/phpviewersample/overview/overviewmain.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/overview/overviewmain.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/overview/overviewmain.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,60 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Resource - Welcome</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+</head>
+
+<body>
+
+<?php
+    $platform = $_SERVER['SERVER_SOFTWARE'];
+?>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Overview<hr></td></tr>
+    <tr><td>
+        Welcome to the Sample Application.
+
+        This sample demonstrates how to construct a
+        Viewer application using the Web Extensions APIs. The application is based on a subset
+        of the Sheboygan data set and shows how to:
+
+        <ul>
+            <li>Connect to a Site and create a session.</li>
+            <li>Query feature data and work with geometry.</li>
+            <li>Change the view of a map from server-side script.</li>
+            <li>Read and manipulate XML based resources.</li>
+            <li>Store temporary resources within a session.</li>
+            <li>Plot a map as an EPlot DWF.</li>
+        </ul>
+    </td></tr>
+    <tr><td>Server Platform: <font color="#AA0000"><?php echo $platform; ?></font></td></tr>
+</table>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/phpviewersample/plot/plot.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/plot/plot.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/plot/plot.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,87 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+// This script plots the current view of the map, optionally
+// using the Scale parameter if Scale > 0.
+
+include '../utilityfunctions.php';
+
+$mgSessionId = ($_SERVER['REQUEST_METHOD'] == "POST")? $_POST['SESSION']: $_GET['SESSION'];
+
+try
+{
+    // Initialize the Web Extensions and connect to the erver using
+    // the Web Extensions session identifier stored in PHP session state.
+
+    MgInitializeWebTier ($configFilePath);
+
+    $userInfo = new MgUserInformation($mgSessionId);
+    $siteConnection = new MgSiteConnection();
+    $siteConnection->Open($userInfo);
+
+    $resourceService = $siteConnection->CreateService(MgServiceType::ResourceService);
+
+    // Create an instance of ResourceService and use that to open the
+    // current map instance stored in session state.
+
+    $resourceService = $siteConnection->CreateService(MgServiceType::ResourceService);
+    $map = new MgMap();
+    $map->Open($resourceService, 'Sheboygan');
+
+    // Now create an instance of MappingService and use it to plot the
+    // current view of the map.
+
+    $dwfVersion = new MgDwfVersion("6.01", "1.2");
+    $plotSpec = new MgPlotSpecification(8.5, 11, MgPageUnitsType::Inches);
+    $plotSpec->SetMargins(0.5, 0.5, 0.5, 0.5);
+
+    $mappingService = $siteConnection->CreateService(MgServiceType::MappingService);
+
+    $layout = null;
+    if (array_key_exists('UseLayout', $_GET) && $_GET['UseLayout'] == 'true')
+    {
+        $layoutRes = new MgResourceIdentifier("Library://Samples/Sheboygan/Layouts/SheboyganMap.PrintLayout");
+        $layout =  new MgLayout($layoutRes, "City of Sheboygan", MgPageUnitsType::Inches);
+    }
+
+    $scale = doubleval($_GET['Scale']);
+    if ($scale <= 0)
+    {
+        $byteReader = $mappingService->GeneratePlot($map, $plotSpec, $layout, $dwfVersion);
+    }
+    else
+    {
+        $mapCenter = $map->GetViewCenter()->GetCoordinate();
+        $byteReader = $mappingService->GeneratePlot($map, $mapCenter, $scale, $plotSpec, $layout, $dwfVersion);
+    }
+
+    // Now output the resulting DWF.
+
+    OutputReaderContent($byteReader);
+}
+catch (MgException $e)
+{
+    $result = $e->GetMessage() . "<br><br>" . $e->GetDetails();
+
+    header('Content-Type: text/html');
+    header('Content-Length: ' . strlen($result));
+    echo $result;
+}
+
+?>

Added: trunk/MgDev/Doc/samples/phpviewersample/plot/plotmain.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/plot/plotmain.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/plot/plotmain.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,164 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+    <title>Plot Task</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+
+    <script language="javascript">
+    function Submit()
+    {
+        var plotForm = document.getElementById("plotForm");
+        var scaleValue = document.getElementById("scaleValue");
+        var useLayoutValue = document.getElementById("useLayoutValue");
+        var useLayoutSelect = document.getElementById("useLayoutSelect");
+        if(useLayoutSelect.checked)
+            useLayoutValue.value = "true";
+        else
+        	useLayoutValue.value = "false";
+
+        scaleValue.value = "0";
+        plotForm.submit();
+    }
+    function SubmitAtScale()
+    {
+        var plotForm = document.getElementById("plotForm");
+        var scaleValue = document.getElementById("scaleValue");
+        var scaleSelect = document.getElementById("scaleSelect");
+        var useLayoutValue = document.getElementById("useLayoutValue");
+        var useLayoutAtScale = document.getElementById("useLayoutAtScale");
+        if(useLayoutAtScale.checked)
+            useLayoutValue.value = "true";
+        else
+        	useLayoutValue.value = "false";
+
+        scaleValue.value = scaleSelect.value;
+        plotForm.submit();
+    }
+    </script>
+</head>
+
+<body>
+
+<?php
+    include '../utilityfunctions.php';
+
+    // Display a couple of forms prompting the user to either
+    // plot the current view of the map, or the current view of
+    // the map at a specified scale. Submitting one of these forms
+    // opens a new window containing an EPlot DWF. The EPlot DWF
+    // is generated by the plot.php script.
+
+    $mgSessionId = ($_SERVER['REQUEST_METHOD'] == "POST")? $_POST['SESSION']: $_GET['SESSION'];
+    $currentScale = 0;
+
+    try
+    {
+        // Initialize the Web Extensions and connect to the Server using
+        // the Web Extensions session identifier stored in PHP session state.
+
+        MgInitializeWebTier($configFilePath);
+
+        $userInfo = new MgUserInformation($mgSessionId);
+        $siteConnection = new MgSiteConnection();
+        $siteConnection->Open($userInfo);
+
+        // Create a ReserviceService object and use it to open the Map
+        // object from the sessions repository. Use the Map object to
+        // determine the current scale of the map for display on this
+        // page.
+
+        $resourceService = $siteConnection->CreateService(MgServiceType::ResourceService);
+        $map = new MgMap();
+        $map->Open($resourceService, 'Sheboygan');
+
+        $viewCenter = $map->GetViewCenter();
+        $viewScale = $map->GetViewScale();
+    }
+    catch (MgException $e)
+    {
+        echo $e->GetMessage();
+        echo $e->GetDetails();
+    }
+?>
+
+<form id="plotForm" action="plot.php" method="get" target="_blank">
+    <input name="SESSION" type="hidden" value="<?php echo $mgSessionId; ?>">
+    <input name="Scale" id="scaleValue" type="hidden" value="0">
+    <input name="UseLayout" id="useLayoutValue" type="hidden" value="false">
+</form>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td class="Title">&nbsp;Plot as DWF<hr></td></tr>
+    <tr><td class="SubTitle">Plot a View of the Map</td></tr>
+    <tr><td>View Center X:  <?php printf('%.3f', $viewCenter->GetCoordinate()->GetX()); ?></td></tr>
+    <tr><td>View Center Y:  <?php printf('%.3f', $viewCenter->GetCoordinate()->GetY()); ?></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td>View Scale:     1:<?php printf('%.0f', $viewScale); ?><hr></td></tr>
+
+    <tr><td class="SubTitle">Plot the Current Map View</td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="button" onClick="Submit()" value="Plot" style="width:60px">
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="checkbox" id="useLayoutSelect">&nbsp;Use Print Layout<hr>
+        </td>
+    </tr>
+
+    <tr><td class="SubTitle">Plot at a Specified Scale</td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr><td class=\"Spacer\"></td></tr>
+    <tr>
+        <td>
+            Scale:
+            <select size="1" class="Ctrl" id="scaleSelect" style="width:80px">
+                <option value="1000">1:1,000</option>
+                <option value="8000">1:8,000</option>
+                <option value="20000">1:20,000</option>
+                <option value="25000">1:25,000</option>
+            </select>
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="button" onClick="SubmitAtScale()" value="Plot" style="width:60px">
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input class="Ctrl" type="checkbox" id="useLayoutAtScale">&nbsp;Use Print Layout
+        </td>
+    </tr>
+</table>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/phpviewersample/query/classes/feature.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/query/classes/feature.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/query/classes/feature.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,40 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+
+class Feature
+{
+	public $displayValue = '';
+	public $centerX = '';
+	public $centerY = '';
+	public $idList = null;
+
+	function __construct($displayValue, $centerPoint, $idList)
+	{
+		$this->displayValue = $displayValue;
+		$this->centerX = $centerPoint->GetCoordinate()->GetX();
+		$this->centerY = $centerPoint->GetCoordinate()->GetY();
+		$this->idList = $idList;
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/query/classes/property.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/query/classes/property.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/query/classes/property.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,36 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+
+class Property
+{
+	public $name = '';
+	public $isString = false;
+
+	function __construct($name, $isString)
+	{
+		$this->name = $name;
+		$this->isString = $isString;
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/query/classes/query.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/query/classes/query.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/query/classes/query.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,551 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+
+require_once('property.php');
+require_once('feature.php');
+require_once '../JSON.php';
+
+class Query
+{
+	private $args = null;
+	private $site = null;
+
+	public $numOperators;
+	public $numExpressions;
+	public $strOperators;
+	public $strExpressions;
+
+	function __construct($args)
+	{
+		$this->args = $args;
+		$this->site = new MgSiteConnection();
+		$this->site->Open(new MgUserInformation($args['SESSION']));
+
+		$this->numOperators = array('Equal to', 'Not equal to', 'Greater than', 'Greater than or equal to', 'Less than', 'Less than or equal to');
+		$this->numExpressions = array(' = %s', ' != %s', ' > %s', ' >= %s', ' < %s', ' <= %s');
+
+		$this->strOperators = array('Begins with', 'Contains', 'Equal to');
+		$this->strExpressions = array(" like '%s%%'", " like '%%%s%%'", " = '%s'");
+	}
+
+    function GetMapLayerNames()
+    {
+        $layerNames = array();
+
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+        $layers = $map->GetLayers();
+
+        for ($i = 0; $i < $layers->GetCount(); $i++)
+        {
+            $layer = $layers->GetItem($i);
+
+            //TODO: Exclude Raster and Drawing Layers???
+
+            if((substr($layer->GetName(), 0, 1) != "_") && (substr(strtoupper($layer->GetFeatureSourceId()), 0, 7) != "SESSION"))
+		    {
+		        $layerNames[$layer->GetName()] = $layer->GetLegendLabel();
+		    }
+        }
+        asort($layerNames);
+
+        return $layerNames;
+    }
+
+    function GetLayerProperties()
+    {
+        $properties = array();
+
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+        $layer = $map->GetLayers()->GetItem($this->args['LAYERNAME']);
+
+		$featureService = $this->site->CreateService(MgServiceType::FeatureService);
+        $resId = new MgResourceIdentifier($layer->GetFeatureSourceId());
+        $schemaClass = explode(':', $layer->GetFeatureClassName());
+
+        $classDef = $featureService->GetClassDefinition($resId, $schemaClass[0], $schemaClass[1]);
+
+        for ($i = 0; $i < $classDef->GetProperties()->GetCount(); $i++)
+        {
+            $propertyDef = $classDef->GetProperties()->GetItem($i);
+
+            if ($propertyDef->GetPropertyType() == MgFeaturePropertyType::DataProperty)
+            {
+				$dataType = $propertyDef->GetDataType();
+				if ($this->IsValidDataType($dataType))
+				{
+	                array_push($properties, new Property($propertyDef->GetName(), $dataType == MgPropertyType::String));
+				}
+            }
+        }
+        return $properties;
+    }
+
+	function ToggleSpatialFilter()
+	{
+		$result = true;
+
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+
+		$layers = $map->GetLayers();
+		if ($layers->Contains('_QuerySpatialFilter'))
+		{
+			$layer = $layers->GetItem('_QuerySpatialFilter');
+			if ($this->args['VISIBLE'] == 'true')
+				$layer->SetVisible(true);
+			else
+				$layer->SetVisible(false);
+
+			$map->Save($resourceService);
+		}
+
+		return $result;
+	}
+
+	function ShowSpatialFilter()
+	{
+		$result = true;
+
+		$sdfResId = new MgResourceIdentifier('Session:' . $this->args['SESSION'] . '//Filter.FeatureSource');
+
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+		$featureService = $this->site->CreateService(MgServiceType::FeatureService);
+
+        $updateCommands = new MgFeatureCommandCollection();
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+
+		$layer = null;
+		$layers = $map->GetLayers();
+		if ($layers->Contains('_QuerySpatialFilter'))
+		{
+			$layer = $layers->GetItem('_QuerySpatialFilter');
+            $updateCommands->Add(new MgDeleteFeatures('Filter', "ID like '%'"));
+		}
+		else
+		{
+			// Create the Feature Source (SDF)
+
+			$sdfSchema = $this->CreateFilterSchema();
+			$sdfParams = new MgCreateSdfParams('MAPCS', $map->GetMapSRS(), $sdfSchema);
+			$featureService->CreateFeatureSource($sdfResId, $sdfParams);
+
+			// Create the Layer
+
+			$layerResId = new MgResourceIdentifier('Session:' . $this->args['SESSION'] . '//Filter.LayerDefinition');
+
+	        $layerDefinition = file_get_contents("templates/filterlayerdefinition.xml");
+    	    $layerDefinition = sprintf($layerDefinition, $sdfResId->ToString());
+
+			$byteSource = new MgByteSource($layerDefinition, strlen($layerDefinition));
+			$resourceService->SetResource($layerResId, $byteSource->GetReader(), null);
+
+			$layer = new MgLayer($layerResId, $resourceService);
+
+			$layer->SetName('_QuerySpatialFilter');
+			$layer->SetLegendLabel('_QuerySpatialFilter');
+			$layer->SetDisplayInLegend(false);
+			$layer->SetSelectable(false);
+
+			$layers->Insert(0, $layer);
+		}
+
+		// Make the layer visible
+
+		$layer->SetVisible(true);
+		$map->Save($resourceService);
+
+		// Add the geometry to the filter feature source
+
+		$polygon = $this->CreatePolygonFromGeomText($this->args['GEOMTEXT']);
+		$agfWriter = new MgAgfReaderWriter();
+		$byteReader = $agfWriter->Write($polygon);
+
+		$propertyValues = new MgPropertyCollection();
+		$propertyValues->Add(new MgGeometryProperty('Geometry', $byteReader));
+
+		$updateCommands->Add(new MgInsertFeatures('Filter', $propertyValues));
+
+		$featureService->UpdateFeatures($sdfResId, $updateCommands, false);
+
+		return $result;
+	}
+
+	function Execute()
+	{
+		$result = array();
+
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+        $layer = $map->GetLayers()->GetItem($this->args['LAYERNAME']);
+
+		$featureService = $this->site->CreateService(MgServiceType::FeatureService);
+        $resId = new MgResourceIdentifier($layer->GetFeatureSourceId());
+		$featureClass = $layer->GetFeatureClassName();
+		$featureGeometry = $layer->GetFeatureGeometryName();
+
+		// Initialize the coordinate system transform
+
+		$schemaAndClass = explode(":", $featureClass);
+		$classDef = $featureService->GetClassDefinition($resId, $schemaAndClass[0], $schemaAndClass[1]);
+		$geomProp = $classDef->GetProperties()->GetItem($featureGeometry);
+		$spatialContext = $geomProp->GetSpatialContextAssociation();
+
+		$csTransform = null;
+		$csInverseTransform = null;
+		$coordSysFactory = new MgCoordinateSystemFactory();
+
+		$scReader = $featureService->GetSpatialContexts($resId, false);
+		while ($scReader->ReadNext() && $csTransform == null)
+		{
+			if ($scReader->GetName() == $spatialContext)
+			{
+				$source = $coordSysFactory->Create($scReader->GetCoordinateSystemWkt());
+				$target = $coordSysFactory->Create($map->GetMapSRS());
+				$csTransform = new MgCoordinateSystemTransform($source, $target);
+				$csInverseTransform = new MgCoordinateSystemTransform($target, $source);
+			}
+		}
+		$scReader->Close();
+
+		// Execute the query
+
+		$queryMax = (int) $this->args['QUERYMAX'];
+		$queryOptions = new MgFeatureQueryOptions();
+
+		if ($this->args['USEPROPERTYFILTER'] == 'true')
+		{
+			$propertyFilter = $this->args['PROPERTYNAME'];
+			if ($this->args['ISSTRING'] == 'true')
+				$propertyFilter .= sprintf($this->strExpressions[$this->args['OPERATOR']], $this->args['VALUE']);
+			else
+				$propertyFilter .= sprintf($this->numExpressions[$this->args['OPERATOR']], $this->args['VALUE']);
+
+			$queryOptions->SetFilter($propertyFilter);
+		}
+
+		if ($this->args['USESPATIALFILTER'] == 'true')
+		{
+			$polygon = $this->CreatePolygonFromGeomText($this->args['GEOMTEXT']);
+			$polygon = $polygon->Transform($csInverseTransform);
+
+			$queryOptions->SetSpatialFilter($featureGeometry, $polygon, MgFeatureSpatialOperations::Intersects);
+		}
+
+		$count = 0;
+		$geometryReaderWriter = new MgAgfReaderWriter();
+		$featureReader = $featureService->SelectFeatures($resId, $layer->GetFeatureClassName(), $queryOptions);
+		while ($featureReader->ReadNext() && ($queryMax <= 0 || $count < $queryMax))
+		{
+			$displayValue = $this->GetFeaturePropertyValue($featureReader, $this->args['OUTPUTPROPERTY']);
+
+			$byteReader = $featureReader->GetGeometry($featureGeometry);
+            $geometry = $geometryReaderWriter->Read($byteReader);
+            $centerPoint = $geometry->GetCentroid();
+			$centerPoint = $centerPoint->Transform($csTransform);
+
+			$idList = $this->GetFeatureIdList($map, $layer, $featureReader);
+
+			array_push($result, new Feature($displayValue, $centerPoint, $idList));
+			$count++;
+		}
+
+		return $result;
+	}
+
+	function GetSelectionXML()
+	{
+	    $json = new Services_JSON();
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+		$featureService = $this->site->CreateService(MgServiceType::FeatureService);
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+		$layer = $map->GetLayers()->GetItem($this->args['LAYERNAME']);
+        $resId = new MgResourceIdentifier($layer->GetFeatureSourceId());
+		$featureClass = $layer->GetFeatureClassName();
+		$schemaAndClass = explode(":", $featureClass);
+		$classDef = $featureService->GetClassDefinition($resId, $schemaAndClass[0], $schemaAndClass[1]);
+
+		$properties = new MgPropertyCollection();
+		$idList = $json->decode($this->args['IDLIST']);
+
+		foreach ($idList as $key => $value)
+		{
+			switch($classDef->GetProperties()->GetItem($key)->GetDataType())
+			{
+				case MgPropertyType::Boolean :
+					$properties->Add(new MgBooleanProperty($key, $value));
+					break;
+
+				case MgPropertyType::Byte :
+					$properties->Add(new MgByteProperty($key, $value));
+					break;
+
+				case MgPropertyType::Single :
+					$properties->Add(new MgSingleProperty($key, $value));
+					break;
+
+				case MgPropertyType::Double :
+					$properties->Add(new MgDoubleProperty($key, $value));
+					break;
+
+				case MgPropertyType::Int16 :
+					$properties->Add(new MgInt16Property($key, $value));
+					break;
+
+				case MgPropertyType::Int32 :
+					$properties->Add(new MgInt32Property($key, $value));
+					break;
+
+				case MgPropertyType::Int64 :
+					$properties->Add(new MgInt64Property($key, $value));
+					break;
+
+				case MgPropertyType::String :
+					$properties->Add(new MgStringProperty($key, $value));
+					break;
+
+				case MgPropertyType::DateTime :
+					$properties->Add(new MgDateTimeProperty($key, $value));
+					break;
+
+				case MgPropertyType::Null :
+				case MgPropertyType::Blob :
+				case MgPropertyType::Clob :
+				case MgPropertyType::Feature :
+				case MgPropertyType::Geometry :
+				case MgPropertyType::Raster :
+					break;
+			}
+		}
+
+		$selection = new MgSelection($map);
+		$selection->AddFeatureIds($layer, $featureClass, $properties);
+
+		return $selection->ToXml();
+	}
+
+	private function GetFeaturePropertyValue($featureReader, $name)
+	{
+		$value = '';
+		$propertyType = $featureReader->GetPropertyType($name);
+		switch($propertyType)
+		{
+			case MgPropertyType::Boolean :
+				$value = $featureReader->GetBoolean($name);
+				break;
+
+			case MgPropertyType::Byte :
+				$value = $featureReader->GetByte($name);
+				break;
+
+			case MgPropertyType::Single :
+				$value = $featureReader->GetSingle($name);
+				break;
+
+			case MgPropertyType::Double :
+				$value = $featureReader->GetDouble($name);
+				break;
+
+			case MgPropertyType::Int16 :
+				$value = $featureReader->GetInt16($name);
+				break;
+
+			case MgPropertyType::Int32 :
+				$value = $featureReader->GetInt32($name);
+				break;
+
+			case MgPropertyType::Int64 :
+				$value = $featureReader->GetInt64($name);
+				break;
+
+			case MgPropertyType::String :
+				$value = $featureReader->GetString($name);
+				break;
+
+			case MgPropertyType::DateTime :
+			case MgPropertyType::Null :
+			case MgPropertyType::Blob :
+			case MgPropertyType::Clob :
+			case MgPropertyType::Feature :
+			case MgPropertyType::Geometry :
+			case MgPropertyType::Raster :
+				$value = '[unsupported data type]';
+				break;
+		}
+		return $value;
+	}
+
+	private function GetFeatureIdList($map, $layer, $featureReader)
+	{
+		$classDef = $featureReader->GetClassDefinition();
+		$idProps = $classDef->GetIdentityProperties();
+		$idList = array();
+
+		for ($i = 0; $i < $idProps->GetCount(); $i++)
+		{
+			$idProp = $idProps->GetItem($i);
+
+			switch($idProp->GetDataType()) {
+				case MgPropertyType::Boolean :
+					$idList[$idProp->GetName()] = $featureReader->GetBoolean($idProp->GetName());
+					break;
+
+				case MgPropertyType::Byte :
+					$idList[$idProp->GetName()] = $featureReader->GetByte($idProp->GetName());
+					break;
+
+				case MgPropertyType::Single :
+					$idList[$idProp->GetName()] = $featureReader->GetSingle($idProp->GetName());
+					break;
+
+				case MgPropertyType::Double :
+					$idList[$idProp->GetName()] = $featureReader->GetDouble($idProp->GetName());
+					break;
+
+				case MgPropertyType::Int16 :
+					$idList[$idProp->GetName()] = $featureReader->GetInt16($idProp->GetName());
+					break;
+
+				case MgPropertyType::Int32 :
+					$idList[$idProp->GetName()] = $featureReader->GetInt32($idProp->GetName());
+					break;
+
+				case MgPropertyType::Int64 :
+					$idList[$idProp->GetName()] = $featureReader->GetInt64($idProp->GetName());
+					break;
+
+				case MgPropertyType::String :
+					$idList[$idProp->GetName()] = $featureReader->GetString($idProp->GetName());
+					break;
+
+				case MgPropertyType::DateTime :
+					$idList[$idProp->GetName()] = $featureReader->GetDateTime($idProp->GetName());
+					break;
+
+				case MgPropertyType::Null :
+				case MgPropertyType::Blob :
+				case MgPropertyType::Clob :
+				case MgPropertyType::Feature :
+				case MgPropertyType::Geometry :
+				case MgPropertyType::Raster :
+					break;
+			}
+		}
+
+		return $idList;
+	}
+
+    private function IsValidDataType($type)
+    {
+        $valid = true;
+
+        switch($type)
+        {
+            case MgPropertyType::Blob:
+				$valid = false;
+				break;
+            case MgPropertyType::Clob:
+				$valid = false;
+				break;
+            case MgPropertyType::Byte:
+				$valid = false;
+				break;
+            case MgPropertyType::Feature:
+				$valid = false;
+				break;
+            case MgPropertyType::Geometry:
+				$valid = false;
+				break;
+            case MgPropertyType::Null:
+				$valid = false;
+				break;
+        }
+        return $valid;
+    }
+
+	private function CreateFilterSchema()
+	{
+		$filterSchema = new MgFeatureSchema();
+		$filterSchema->SetName('FilterSchema');
+
+		$filterClass = new MgClassDefinition();
+		$filterClass->SetName('Filter');
+		$properties = $filterClass->GetProperties();
+
+		$idProperty = new MgDataPropertyDefinition('ID');
+		$idProperty->SetDataType(MgPropertyType::Int32);
+		$idProperty->SetReadOnly(true);
+		$idProperty->SetNullable(false);
+		$idProperty->SetAutoGeneration(true);
+		$properties->Add($idProperty);
+
+		$geometryProperty = new MgGeometricPropertyDefinition('Geometry');
+		$geometryProperty->SetGeometryTypes(MgFeatureGeometricType::Surface);
+		$geometryProperty->SetHasElevation(false);
+		$geometryProperty->SetHasMeasure(false);
+		$geometryProperty->SetReadOnly(false);
+		$geometryProperty->SetSpatialContextAssociation('MAPCS');
+		$properties->Add($geometryProperty);
+
+		$filterClass->GetIdentityProperties()->Add($idProperty);
+		$filterClass->SetDefaultGeometryPropertyName('Geometry');
+
+		$filterSchema->GetClasses()->Add($filterClass);
+
+		return $filterSchema;
+	}
+
+	private function CreatePolygonFromGeomText($geomText)
+	{
+		$geometryFactory = new MgGeometryFactory();
+
+		$vertices = explode(',', $geomText);
+		$count = $vertices[0];
+
+		$coords = new MgCoordinateCollection();
+		for ($i = 0; $i < $count; $i++)
+		{
+			$coord = $geometryFactory->CreateCoordinateXY((double) $vertices[($i * 2) + 1], (double) $vertices[($i * 2) + 2]);
+			$coords->Add($coord);
+		}
+
+		$linearRing = $geometryFactory->CreateLinearRing($coords);
+		$polygon = $geometryFactory->CreatePolygon($linearRing, null);
+
+		return $polygon;
+	}
+}
+?>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/query/querycontroller.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/query/querycontroller.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/query/querycontroller.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,65 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+	require_once '../utilityfunctions.php';
+    require_once '../JSON.php';
+	require_once 'classes/query.php';
+
+	$args = ($_SERVER['REQUEST_METHOD'] == "POST") ? $_POST : $_GET;
+
+    MgInitializeWebTier($configFilePath);
+
+    $query = new Query($args);
+    $json = new Services_JSON();
+	$responseType = '';
+	$response = '';
+
+	if (array_key_exists('COMMAND', $args))
+	{
+		$cmd = $args['COMMAND'];
+		switch ($cmd) {
+			case "GETLAYERPROPERTIES":
+				$reponseType = 'text/plain';
+			    $response = $json->encode($query->GetLayerProperties());
+				break;
+			case "TOGGLESPATIALFILTER":
+				$reponseType = 'text/plain';
+			    $response = $json->encode($query->ToggleSpatialFilter());
+				break;
+			case "SHOWSPATIALFILTER":
+				$reponseType = 'text/plain';
+			    $response = $json->encode($query->ShowSpatialFilter());
+				break;
+			case "EXECUTEQUERY":
+				$reponseType = 'text/plain';
+			    $response = $json->encode($query->Execute());
+				break;
+			case "GETSELECTIONXML":
+				$reponseType = 'text/xml';
+			    $response = $query->GetSelectionXML();
+				break;
+		}
+	}
+
+    header('Content-Type: ' . $responseType);
+    echo $response;
+?>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/query/querymain.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/query/querymain.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/query/querymain.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,479 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+
+	require_once '../utilityfunctions.php';
+    require_once '../JSON.php';
+	require_once 'classes/query.php';
+
+	$args = ($_SERVER['REQUEST_METHOD'] == "POST") ? $_POST : $_GET;
+
+	$errorMsg = null;
+	$errorDetail = null;
+
+	try
+	{
+		MgInitializeWebTier($configFilePath);
+
+		$query = new Query($args);
+
+		$layerNames = $query->GetMapLayerNames();
+	}
+	catch (MgException $mge)
+	{
+		$errorMsg = $mge->GetMessage();
+		$errorDetail = $mge->GetDetails();
+		echo $errorMsg;
+		echo $errorDetail;
+	}
+	catch (Exception $e)
+	{
+		$errorMsg = $e->GetMessage();
+		echo $errorMsg;
+	}
+?>
+<html>
+<head>
+	<title>Query Features</title>
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+	<script language="javascript" src="../../viewerfiles/browserdetect.js"></script>
+	<script language="javascript" src="../json.js"></script>
+
+	<script language="javascript">
+		var READY_STATE_UNINITIALIZED 	= 0;
+		var READY_STATE_LOADING 		= 1;
+		var READY_STATE_LOADED 			= 2;
+		var READY_STATE_INTERACTIVE 	= 3;
+		var READY_STATE_COMPLETE 		= 4;
+
+		var NOT_BUSY_IMAGE = "../images/loader_inactive.gif";
+		var BUSY_IMAGE = "../images/loader_pulse.gif";
+
+        var session = '<?= $args['SESSION'] ?>';
+        var mapName = '<?= $args['MAPNAME'] ?>';
+
+		var strOps = '<?php $json = new Services_JSON(); echo $json->encode($query->strOperators) ?>'.parseJSON();
+		var numOps = '<?php $json = new Services_JSON(); echo $json->encode($query->numOperators) ?>'.parseJSON();
+		var queryReqHandler = null;
+		var spatialFilterGeomText = null;
+		var properties = null;
+		var results;
+
+		function OnLayerChange()
+		{
+            var layerSelect = document.getElementById("layerSelect");
+            var propertySelect = document.getElementById("propertySelect");
+            var outputSelect = document.getElementById("outputSelect");
+
+            reqParams = "COMMAND=GETLAYERPROPERTIES";
+			reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+			reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "querycontroller.php", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+			reqHandler.send(reqParams);
+			properties = reqHandler.responseText.parseJSON();
+
+			propertySelect.options.length = 0;
+			outputSelect.options.length = 0;
+			for (var i = 0; i < properties.length; i++)
+			{
+				propertySelect.options[i] = new Option(properties[i].name, i, false, false);
+				outputSelect.options[i] = new Option(properties[i].name, i, false, false);
+			}
+			OnPropertyChange();
+		}
+
+		function OnPropertyChange()
+		{
+            var propertySelect = document.getElementById("propertySelect");
+            var operatorSelect = document.getElementById("operatorSelect");
+
+			operatorSelect.options.length = 0;
+			if (propertySelect.selectedIndex >= 0)
+			{
+				var ops = null;
+				if (properties[propertySelect.value].isString)
+					ops = strOps;
+				else
+					ops = numOps;
+
+				for (var i = 0; i < ops.length; i++)
+				{
+					operatorSelect.options[i] = new Option(ops[i], i, false, false);
+				}
+			}
+
+		}
+
+		function OnToggleSpatialFilter()
+		{
+			if (spatialFilterGeomText != null)
+			{
+				ToggleSpatialFilter(document.getElementById("spatialFilter").checked);
+			}
+		}
+
+		function OnDigitizeRectangle()
+		{
+			parent.parent.mapFrame.DigitizeRectangle(OnRectangleDigitized);
+		}
+
+		function OnRectangleDigitized(rectangle)
+		{
+			var geomText = "5,"
+				+ rectangle.Point1.X + "," + rectangle.Point1.Y + ","
+				+ rectangle.Point2.X + "," + rectangle.Point1.Y + ","
+				+ rectangle.Point2.X + "," + rectangle.Point2.Y + ","
+				+ rectangle.Point1.X + "," + rectangle.Point2.Y + ","
+				+ rectangle.Point1.X + "," + rectangle.Point1.Y;
+
+			ShowSpatialFilter(geomText);
+		}
+
+		function OnDigitizePolygon()
+		{
+			parent.parent.mapFrame.DigitizePolygon(OnPolyonDigitized);
+		}
+
+		function OnPolyonDigitized(polygon)
+		{
+			var geomText = polygon.Count;
+			for (var i = 0; i < polygon.Count; i++)
+			{
+				geomText += "," + polygon.Point(i).X + "," + polygon.Point(i).Y;
+			}
+
+			ShowSpatialFilter(geomText);
+		}
+
+		function OnClearSpatialFilter()
+		{
+			document.getElementById("spatialFilter").checked = false;
+			OnToggleSpatialFilter();
+
+			spatialFilterGeomText = null;
+		}
+
+		function ShowSpatialFilter(geomText)
+		{
+            reqParams = "COMMAND=SHOWSPATIALFILTER";
+			reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+			reqParams += "&GEOMTEXT=" + encodeURIComponent(geomText);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            if (msie)
+                reqHandler.open("POST", "querycontroller.php", false);
+            else
+                reqHandler.open("POST", "../phpviewersample/query/querycontroller.php", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+            reqHandler.send(reqParams);
+
+			spatialFilterGeomText = geomText;
+			document.getElementById("spatialFilter").checked = true;
+			parent.parent.Refresh();
+		}
+
+		function ToggleSpatialFilter(visible)
+		{
+			reqParams = "COMMAND=TOGGLESPATIALFILTER";
+			reqParams += "&SESSION=" + encodeURIComponent(session);
+			reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+			reqParams += "&VISIBLE=" + encodeURIComponent(visible);
+
+			if (msie)
+				reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+			else
+				reqHandler = new XMLHttpRequest();
+
+			reqHandler.open("POST", "querycontroller.php", false);
+			reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+			reqHandler.send(reqParams);
+
+			parent.parent.Refresh();
+		}
+
+		function ExecuteQuery()
+		{
+		    var layerSelect = document.getElementById("layerSelect");
+
+            reqParams = "COMMAND=EXECUTEQUERY";
+			reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+			reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+
+			if (document.getElementById("propertyFilter").checked)
+			{
+				reqParams += "&USEPROPERTYFILTER=true";
+				property = properties[document.getElementById("propertySelect").value];
+				reqParams += "&PROPERTYNAME=" + encodeURIComponent(property.name);
+				reqParams += "&ISSTRING=" + encodeURIComponent(property.isString);
+				reqParams += "&OPERATOR=" + encodeURIComponent(document.getElementById("operatorSelect").value);
+				reqParams += "&VALUE=" + encodeURIComponent(document.getElementById("valueInput").value);
+			}
+			else
+			{
+				reqParams += "&USEPROPERTYFILTER=false";
+			}
+
+			if (document.getElementById("spatialFilter").checked && spatialFilterGeomText != null)
+			{
+				reqParams += "&USESPATIALFILTER=true";
+				reqParams += "&GEOMTEXT=" + encodeURIComponent(spatialFilterGeomText);
+			}
+			else
+			{
+				reqParams += "&USESPATIALFILTER=false";
+			}
+
+			reqParams += "&OUTPUTPROPERTY=" + encodeURIComponent(properties[document.getElementById("outputSelect").value].name);
+			reqParams += "&QUERYMAX=" + encodeURIComponent(document.getElementById("queryMax").value);
+
+            if (msie)
+                queryReqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                queryReqHandler = new XMLHttpRequest();
+
+			queryReqHandler.onreadystatechange = OnReadyStateChange;
+            queryReqHandler.open("POST", "querycontroller.php", true);
+            queryReqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+			document.getElementById("executeBtn").disabled = true;
+			document.getElementById("busyImg").src = BUSY_IMAGE;
+
+			queryReqHandler.send(reqParams);
+		}
+
+		function SelectFeature()
+		{
+		    var layerSelect = document.getElementById("layerSelect");
+			var resultSelect = document.getElementById("resultSelect");
+
+            reqParams = "COMMAND=GETSELECTIONXML";
+			reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+			reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+			reqParams += "&IDLIST=" + results[resultSelect.value].idList.toJSONString();
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "querycontroller.php", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+			reqHandler.send(reqParams);
+			selectionXml = reqHandler.responseText;
+
+            parent.parent.mapFrame.SetSelectionXML(TrimString(selectionXml));
+        }
+
+        function TrimString(responseString)
+        {
+            responseString = responseString.replace( /^\s+/g, "" );
+            return responseString.replace( /\s+$/g, "" );
+        }
+
+		function ZoomToFeature()
+		{
+			var resultSelect = document.getElementById("resultSelect");
+			var scaleInput = document.getElementById("scaleInput");
+			scale = scaleInput.value;
+			scale = (scale == 0) ? 10000 : scale;
+			scale = scale*1.0;
+
+			feature = results[resultSelect.value];
+			parent.parent.mapFrame.ZoomToView(feature.centerX, feature.centerY, scale, true);
+		}
+
+		function OnReadyStateChange()
+		{
+			var ready = queryReqHandler.readyState;
+
+			if (ready == READY_STATE_COMPLETE)
+			{
+				results = queryReqHandler.responseText.parseJSON();
+
+				var resultSelect = document.getElementById("resultSelect");
+				resultSelect.options.length = 0;
+				for (var i = 0; i < results.length; i++)
+				{
+					resultSelect.options[i] = new Option(results[i].displayValue, i, false, false);
+				}
+				OnResultChange();
+
+				document.getElementById("executeBtn").disabled = false;
+				document.getElementById("busyImg").src = NOT_BUSY_IMAGE;
+				queryReqHandler = null;
+			}
+		}
+
+		function OnResultChange()
+		{
+            var resultSelect = document.getElementById("resultSelect");
+			var scaleInput = document.getElementById("scaleInput");
+			var zoomBtn = document.getElementById("zoomBtn");
+			var selectBtn = document.getElementById("selectBtn");
+
+			if (resultSelect.selectedIndex >= 0)
+			{
+				scaleInput.disabled = false;
+				zoomBtn.disabled = false;
+				selectBtn.disabled = false;
+			}
+			else
+			{
+				scaleInput.disabled = true;
+				zoomBtn.disabled = true;
+				selectBtn.disabled = true;
+			}
+		}
+
+		function OnLoad()
+		{
+			OnLayerChange();
+			OnResultChange();
+		}
+
+		function OnUnload()
+		{
+			ToggleSpatialFilter(false);
+		}
+	</script>
+
+</head>
+
+<body onLoad="OnLoad();" onUnload="OnUnload();" marginwidth=5 marginheight=5 leftmargin=5 topmargin=5 bottommargin=5 rightmargin=5>
+
+<?php if ($errorMsg == null) { ?>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+	<tr><td class="Title"><img id="busyImg" src="../images/loader_inactive.gif" style="vertical-align:bottom">&nbsp;Query Features<hr></td></tr>
+	<tr><td class="SubTitle">Select a Layer</td></tr>
+    <tr><td>Layer:</td></tr>
+	<tr>
+		<td class="RegText">
+			<select size="1" class="Ctrl" id="layerSelect" onChange="OnLayerChange()" style="width: 100%">
+				<?php
+					$selected = 'selected';
+					foreach($layerNames as $layerName => $layerLabel) {
+				?>
+				<option value="<?= $layerName ?>" <?=$selected ?> ><?= $layerLabel ?></option>
+				<?php
+						$selected = '';
+					}
+				?>
+		  	</select>
+		</td>
+	</tr>
+    <tr><td class="Spacer"></td></tr>
+	<tr><td class="SubTitle"><input class="Ctrl" type="checkbox" id="propertyFilter" checked>&nbsp;Property Filter</td></tr>
+    <tr><td>Property:</td></tr>
+	<tr>
+		<td class="RegText">
+			<select size="1" class="Ctrl" id="propertySelect" onChange="OnPropertyChange()" style="width: 100%">
+		  	</select>
+		</td>
+	</tr>
+    <tr><td>Operator:</td></tr>
+	<tr>
+		<td class="RegText">
+			<select size="1" class="Ctrl" id="operatorSelect" style="width: 100%">
+		  	</select>
+		</td>
+	</tr>
+    <tr><td>Value:</td></tr>
+	<tr>
+		<td class="RegText">
+            <input maxlength="100" class="Ctrl" id="valueInput" style="width: 100%">
+		</td>
+	</tr>
+    <tr><td class="Spacer"></td></tr>
+	<tr><td class="SubTitle"><input class="Ctrl" type="checkbox" onChange="OnToggleSpatialFilter()" id="spatialFilter">&nbsp;Spatial Filter</td></tr>
+    <tr><td>Digitize:</td></tr>
+    <tr>
+        <td align="center">
+            <input type="button" name="" value="Rectangle" class="Ctrl" id="rectButton" onClick="OnDigitizeRectangle()" style="width: 30%">
+            <input type="button" name="" value="Polygon" class="Ctrl" id="polyButtton" onClick="OnDigitizePolygon()" style="width: 30%">
+            <input type="button" name="" value="Clear" class="Ctrl" id="clearButton" onClick="OnClearSpatialFilter()" style="width: 30%">
+        </td>
+    </tr>
+    <tr><td class="Spacer"></td></tr>
+	<tr><td class="SubTitle">Output</td></tr>
+    <tr><td>Output property:</td></tr>
+	<tr>
+		<td class="RegText">
+			<select size="1" class="Ctrl" id="outputSelect" style="width: 100%">
+		  	</select>
+		</td>
+	</tr>
+    <tr><td class="Spacer"></td></tr>
+    <tr><td><hr></td></tr>
+	<tr>
+		<td>
+			<input id="executeBtn" class="Ctrl" name="" type="button" onClick="ExecuteQuery()" value="Execute" style="width:60px">
+			&nbsp;&nbsp;Max results:&nbsp;
+			<input name="" id="queryMax" class="Ctrl" type="text" value="100" size="5">
+		</td>
+	</tr>
+    <tr><td class="Spacer"></td></tr>
+	<tr><td class="SubTitle">Results</td></tr>
+	<tr>
+		<td>
+			<select class="Ctrl" id="resultSelect" size="15" onChange="OnResultChange()" style="width: 100%"></select>
+		</td>
+	</tr>
+	<tr>
+		<td>
+			Scale:&nbsp;<input class="Ctrl" id="scaleInput" type="text" size="6" value="10000">
+			<input class="Ctrl" id="zoomBtn" type="button" onClick="ZoomToFeature()" value="Zoom" style="width:60px">
+			<input class="Ctrl" id="selectBtn" type="button" onClick="SelectFeature()" value="Select" style="width:60px">
+		</td>
+	</tr>
+
+</table>
+
+<?php } else { ?>
+
+<table class="RegText" border="0" cellspacing="0" width="100%%">
+	<tr><td class="Title">Error<hr></td></tr>
+	<tr><td><?= $errorMsg ?></td></tr>
+	<tr><td><?= $errorDetail ?></td></tr>
+</table>
+
+<?php } ?>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/phpviewersample/query/templates/filterlayerdefinition.xml
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/query/templates/filterlayerdefinition.xml	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/query/templates/filterlayerdefinition.xml	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<LayerDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="LayerDefinition-1.0.0.xsd" version="1.0.0">
+  <VectorLayerDefinition>
+    <ResourceId>%s</ResourceId>
+    <FeatureName>FilterSchema:Filter</FeatureName>
+    <FeatureNameType>FeatureClass</FeatureNameType>
+    <Geometry>Geometry</Geometry>
+    <VectorScaleRange>
+      <AreaTypeStyle>
+        <AreaRule>
+          <LegendLabel></LegendLabel>
+          <AreaSymbolization2D>
+            <Fill>
+              <FillPattern>Solid</FillPattern>
+              <ForegroundColor>40FF0000</ForegroundColor>
+              <BackgroundColor>FF000000</BackgroundColor>
+            </Fill>
+            <Stroke>
+              <LineStyle>Solid</LineStyle>
+              <Thickness>0</Thickness>
+              <Color>FFFF0000</Color>
+              <Unit>Inches</Unit>
+            </Stroke>
+          </AreaSymbolization2D>
+        </AreaRule>
+      </AreaTypeStyle>
+    </VectorScaleRange>
+  </VectorLayerDefinition>
+</LayerDefinition>

Added: trunk/MgDev/Doc/samples/phpviewersample/styles/gt.css
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/styles/gt.css	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/styles/gt.css	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,43 @@
+td.Title
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-weight: bold;
+	font-size: 13pt;
+}
+td.SubTitle
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-weight: bold;
+	font-size: 8pt;
+	background-color: #DCDCDC;
+	color: black;
+	height: 20px;
+}
+td.Spacer
+{
+    height: 4px;
+}
+.Swatch
+{
+	border: black 1px solid;
+	height: 16px;
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 10pt;
+}
+td.InfoText
+{
+	background-color: #FFFFCC;
+	color: #666666;
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}
+.RegText
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}
+.Ctrl
+{
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 8pt;
+}

Added: trunk/MgDev/Doc/samples/phpviewersample/theme/classes/layerinfo.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/theme/classes/layerinfo.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/theme/classes/layerinfo.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,36 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+
+class LayerInfo
+{
+	public $properties = null;
+	public $scaleRanges = null;
+
+	function __construct($properties, $scaleRanges)
+	{
+		$this->properties = $properties;
+		$this->scaleRanges = $scaleRanges;
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/theme/classes/property.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/theme/classes/property.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/theme/classes/property.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,38 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+
+class Property
+{
+	public $name = '';
+	public $dataType = 0;
+	public $distroTypes = null;
+
+	function __construct($name, $dataType, $distroTypes)
+	{
+		$this->name = $name;
+		$this->dataType = $dataType;
+		$this->distroTypes = $distroTypes;
+	}
+}
+
+?>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/theme/classes/theme.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/theme/classes/theme.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/theme/classes/theme.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,470 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+
+require_once('layerinfo.php');
+require_once('property.php');
+require_once '../JSON.php';
+
+class Theme
+{
+	private $args = null;
+	private $site = null;
+
+	public $distNameArray = array("Individual", "Equal", "Standard Deviation", "Quantile", "Jenks (Natural Breaks)");
+	public $distValueArray = array("INDIV_DIST", "EQUAL_DIST", "STDEV_DIST", "QUANT_DIST", "JENK_DIST");
+
+	function __construct($args)
+	{
+		$this->args = $args;
+		$this->site = new MgSiteConnection();
+		$this->site->Open(new MgUserInformation($args['SESSION']));
+	}
+
+    function GetMapLayerNames()
+    {
+        $layerNames = array();
+
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+		$featureService = $this->site->CreateService(MgServiceType::FeatureService);
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+        $layers = $map->GetLayers();
+
+        for ($i = 0; $i < $layers->GetCount(); $i++)
+        {
+            $layer = $layers->GetItem($i);
+            if((substr($layer->GetName(), 0, 1) != "_") && (substr(strtoupper($layer->GetFeatureSourceId()), 0, 7) != "SESSION"))
+		    {
+        	    $resId = new MgResourceIdentifier($layer->GetFeatureSourceId());
+			    $schemaClass = explode(':', $layer->GetFeatureClassName());
+
+			    $classDef = $featureService->GetClassDefinition($resId, $schemaClass[0], $schemaClass[1]);
+			    $propDef = $classDef->GetProperties()->GetItem($layer->GetFeatureGeometryName());
+
+			    if($propDef->GetPropertyType() == MgFeaturePropertyType::GeometricProperty)
+			    {
+					if ($propDef->GetGeometryTypes() == MgFeatureGeometricType::Surface)
+					{
+						$layerNames[$layer->GetName()] = $layer->GetLegendLabel();
+					}
+				}
+			}
+        }
+        asort($layerNames);
+
+        return $layerNames;
+    }
+
+    function GetLayerInfo()
+    {
+        $properties = array();
+		$scaleRanges = array();
+
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+        $layer = $map->GetLayers()->GetItem($this->args['LAYERNAME']);
+
+		// First get a list of all of the Feature Class properties that can be used for theming.
+
+		$featureService = $this->site->CreateService(MgServiceType::FeatureService);
+        $resId = new MgResourceIdentifier($layer->GetFeatureSourceId());
+        $schemaClass = explode(':', $layer->GetFeatureClassName());
+
+        $classDef = $featureService->GetClassDefinition($resId, $schemaClass[0], $schemaClass[1]);
+
+        for ($i = 0; $i < $classDef->GetProperties()->GetCount(); $i++)
+        {
+            $propertyDef = $classDef->GetProperties()->GetItem($i);
+
+            if ($propertyDef->GetPropertyType() == MgFeaturePropertyType::DataProperty)
+            {
+				$dataType = $propertyDef->GetDataType();
+				$distroTypes = $this->GetDistributionsForDataType($dataType);
+				if (count($distroTypes) > 0)
+				{
+	                array_push($properties, new Property($propertyDef->GetName(), $dataType, $distroTypes));
+				}
+            }
+        }
+
+		// Next get a list of all of the layers scale ranges.
+
+		$layerDefResId = $layer->GetLayerDefinition();
+		$byteReader = $resourceService->GetResourceContent($layerDefResId);
+
+		$doc = DOMDocument::loadXML($byteReader->ToString());
+		$nodeList = $doc->getElementsByTagName('VectorScaleRange');
+
+		foreach ($nodeList as $node)
+		{
+			$range = null;
+
+			$minNodeList = $node->getElementsByTagName('MinScale');
+			if ($minNodeList->length > 0)
+				$range = $minNodeList->item(0)->nodeValue;
+			else
+				$range = '0';
+
+			$maxNodeList = $node->getElementsByTagName('MaxScale');
+			if ($maxNodeList->length > 0)
+				$range .= ' - ' . $maxNodeList->item(0)->nodeValue;
+			else
+				$range .= ' - Infinity';
+
+			array_push($scaleRanges, $range);
+		}
+
+        return new LayerInfo($properties, $scaleRanges);
+    }
+
+	function GetPropertyMinMaxCount()
+	{
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+        $layer = $map->GetLayers()->GetItem($this->args['LAYERNAME']);
+
+		$featureService = $this->site->CreateService(MgServiceType::FeatureService);
+        $resId = new MgResourceIdentifier($layer->GetFeatureSourceId());
+
+// Note: Should be able to do this:
+//
+//		$minValue = 0;
+//		$maxValue = 0;
+//		$count = 0;
+//
+//		$aggregateOptions = new MgFeatureAggregateOptions();
+//		$aggregateOptions->AddComputedProperty('min', 'Min(' . $this->args['PROPERTYNAME'] . ')');
+//		$aggregateOptions->AddComputedProperty('max', 'Max(' . $this->args['PROPERTYNAME'] . ')');
+//		$aggregateOptions->AddComputedProperty('count', 'Count(' . $this->args['PROPERTYNAME'] . ')');
+//
+//		$dataReader = $featureService->SelectAggregate($resId, $layer->GetFeatureClassName(), $aggregateOptions);
+//
+//		if ($dataReader->ReadNext())
+//		{
+//			$minValue = $this->GetFeaturePropertyValue($dataReader, 'min');
+//			$maxValue = $this->GetFeaturePropertyValue($dataReader, 'max');
+//			$count = $this->GetFeaturePropertyValue($dataReader, 'count');
+//		}
+//		$dataReader->Close();
+//
+// However due to a bug, Min/Max do not work on string types, so we have to do this:
+
+		unset($minValue);
+		unset($maxValue);
+		$count = 0;
+
+		$queryOptions = new MgFeatureQueryOptions();
+		$queryOptions->AddFeatureProperty($this->args['PROPERTYNAME']);
+
+		$featureReader = $featureService->SelectFeatures($resId, $layer->GetFeatureClassName(), $queryOptions);
+
+		while($featureReader->ReadNext())
+		{
+			$value = $this->GetFeaturePropertyValue($featureReader, $this->args['PROPERTYNAME']);
+			if ($value != null)
+			{
+				if(!isset($maxValue) && !isset($minValue))
+				{
+					$maxValue = $value;
+					$minValue = $value;
+				}
+				if($value > $maxValue)
+					$maxValue = $value;
+				if($value < $minValue)
+					$minValue = $value;
+			}
+			$count++;
+		}
+		$featureReader->Close();
+
+		if(!isset($maxValue) && !isset($minValue))
+		{
+			$maxValue="";
+			$minValue="";
+		}
+
+		return array($minValue, $maxValue, $count);
+	}
+
+	function ApplyTheme()
+	{
+		$resourceService = $this->site->CreateService(MgServiceType::ResourceService);
+		$featureService = $this->site->CreateService(MgServiceType::FeatureService);
+
+		$map = new MgMap();
+		$map->Open($resourceService, $this->args['MAPNAME']);
+		$layers = $map->GetLayers();
+        $layer = $layers->GetItem($this->args['LAYERNAME']);
+
+        $resId = new MgResourceIdentifier($layer->GetFeatureSourceId());
+		$layerDefResId = $layer->GetLayerDefinition();
+		$byteReader = $resourceService->GetResourceContent($layerDefResId);
+
+		// Load the Layer Definition and Navigate to the specified <VectorScaleRange>
+
+		$doc = DOMDocument::loadXML($byteReader->ToString());
+		$nodeList = $doc->getElementsByTagName('VectorScaleRange');
+
+		$vectorScaleRangecElement = $nodeList->item($this->args['SCALERANGEINDEX']);
+		$areaTypeStyle = $vectorScaleRangecElement->getElementsByTagName('AreaTypeStyle')->item(0);
+
+		// Remove any existing <AreaRule> elements.
+
+		$areaRuleList = $areaTypeStyle->getElementsByTagName('AreaRule');
+		$ruleCount = $areaRuleList->length;
+		for($index = 0; $index < $ruleCount; $index++)
+		{
+			$areaTypeStyle->removeChild($areaRuleList->item(0));
+		}
+
+		// Now create the new <AreaRule> elements.
+
+		$areaRuleTemplate = file_get_contents("templates/arearuletemplate.xml");
+		$aggregateOptions = new MgFeatureAggregateOptions();
+
+		$portion = 0.0;
+		$increment = ($this->args['NUMRULES'] > 1) ? $increment = 1.0 / ($this->args['NUMRULES'] - 1) : 1.0;
+
+		if ($this->args['DISTRO'] == 'INDIV_DIST')
+		{
+			$aggregateOptions->AddFeatureProperty($this->args['PROPERTYNAME']);
+			$aggregateOptions->SelectDistinct(true);
+
+			$dataReader = $featureService->SelectAggregate($resId, $layer->GetFeatureClassName(), $aggregateOptions);
+			while ($dataReader->ReadNext())
+			{
+				$value = $this->GetFeaturePropertyValue($dataReader, $this->args['PROPERTYNAME']);
+
+				$filterText = '&quot;' . $this->args['PROPERTYNAME'] . '&quot; = ';
+				if ($this->args['DATATYPE'] == MgPropertyType::String)
+					$filterText .= "'" . $value . "'";
+				else
+					$filterText .= $value;
+
+	    	    $areaRuleXML = sprintf($areaRuleTemplate,
+					$this->args['PROPERTYNAME'] . ': ' . $value,
+					$filterText,
+					$this->InterpolateColor($portion, $this->args['FILLFROM'], $this->args['FILLTO'], $this->args['FILLTRANS']),
+					$this->InterpolateColor($portion, $this->args['LINEFROM'], $this->args['LINETO'], 0));
+
+				$areaDoc = DOMDocument::loadXML($areaRuleXML);
+				$areaNode = $doc->importNode($areaDoc->documentElement, true);
+				$areaTypeStyle->appendChild($areaNode);
+
+				$portion += $increment;
+			}
+			$dataReader->Close();
+		}
+		else
+		{
+			$values = array();
+
+			$aggregateOptions->AddComputedProperty('THEME_VALUE',
+				$this->args['DISTRO'] . '("' . $this->args['PROPERTYNAME'] . '",' . $this->args['NUMRULES'] . ',' . $this->args['MINVALUE'] . ',' . $this->args['MAXVALUE'] . ')');
+
+			$dataReader = $featureService->SelectAggregate($resId, $layer->GetFeatureClassName(), $aggregateOptions);
+			while ($dataReader->ReadNext())
+			{
+				$value = $this->GetFeaturePropertyValue($dataReader, 'THEME_VALUE');
+				array_push($values, $value);
+			}
+			$dataReader->Close();
+
+			for ($i = 0; $i < count($values) - 1; $i++)
+			{
+				$filterText = '&quot;' . $this->args['PROPERTYNAME'] . '&quot; &gt;= ' . $values[$i] . ' AND &quot;' . $this->args['PROPERTYNAME'];
+				if ($i == count($values) - 1)
+					$filterText .= '&quot; &lt;= ' . $values[$i + 1];
+				else
+					$filterText .= '&quot; &lt; ' . $values[$i + 1];
+
+	    	    $areaRuleXML = sprintf($areaRuleTemplate,
+					$this->args['PROPERTYNAME'] . ': ' . $values[$i] . ' - ' . $values[$i + 1],
+					$filterText,
+					$this->InterpolateColor($portion, $this->args['FILLFROM'], $this->args['FILLTO'], $this->args['FILLTRANS']),
+					$this->InterpolateColor($portion, $this->args['LINEFROM'], $this->args['LINETO'], 0));
+
+				$areaDoc = DOMDocument::loadXML($areaRuleXML);
+				$areaNode = $doc->importNode($areaDoc->documentElement, true);
+				$areaTypeStyle->appendChild($areaNode);
+
+				$portion += $increment;
+			}
+
+		}
+
+		// Now save our new layer definition to the session and add it to the map.
+
+		$layerDefinition = $doc->saveXML();
+		$uniqueName = $this->MakeUniqueLayerName($map, $this->args['LAYERNAME'], $this->args['THEMENAME']);
+		$legendLabel = $layer->GetLegendLabel();
+		if (strlen(trim($this->args['THEMENAME'])) > 0 )
+			$legendLabel .= ' (' . $this->args['THEMENAME'] . ')';
+
+		$layerResId = new MgResourceIdentifier('Session:' . $this->args['SESSION'] . '//' . $uniqueName . '.LayerDefinition');
+
+		$byteSource = new MgByteSource($layerDefinition, strlen($layerDefinition));
+		$resourceService->SetResource($layerResId, $byteSource->GetReader(), null);
+
+		$newLayer = new MgLayer($layerResId, $resourceService);
+		$newLayer->SetName($uniqueName);
+		$newLayer->SetLegendLabel($legendLabel);
+		$newLayer->SetDisplayInLegend($layer->GetDisplayInLegend());
+		$newLayer->SetVisible(true);
+		$newLayer->SetSelectable($layer->GetLegendLabel());
+		$layers->Insert($layers->IndexOf($layer), $newLayer);
+
+		$map->Save($resourceService);
+
+		return $uniqueName;
+	}
+
+
+	private function InterpolateColor($portion, $startColor, $endColor, $percentTransparent)
+	{
+		$result = sprintf("%02x", 255 * (100 - $percentTransparent) / 100);
+
+		if ($startColor == $endColor)
+			return $result . $startColor;
+
+		$red = $this->CalculateRGB($portion, substr($startColor, 0, 2), substr($endColor, 0, 2));
+		$result = (strlen(dechex($red)) == 1) ? $result . "0" . dechex($red) : $result . dechex($red);
+		$green = $this->CalculateRGB($portion, substr($startColor, 2, 2), substr($endColor, 2, 2));
+		$result = (strlen(dechex($green)) == 1) ? $result . "0" . dechex($green) : $result . dechex($green);
+		$blue = $this->CalculateRGB($portion, substr($startColor, 4, 2), substr($endColor, 4, 2));
+		$result = (strlen(dechex($blue)) == 1) ? $result . "0" . dechex($blue) : $result . dechex($blue);
+
+		return $result;
+	}
+
+	private function CalculateRGB($portion, $startRGB, $endRGB)
+	{
+		return (hexdec($startRGB) + ($portion * (hexdec($endRGB) - hexdec($startRGB))));
+	}
+
+	private function GetFeaturePropertyValue($featureReader, $name)
+	{
+		$value = '';
+		$propertyType = $featureReader->GetPropertyType($name);
+		switch($propertyType)
+		{
+			case MgPropertyType::Boolean :
+				$value = $featureReader->GetBoolean($name);
+				break;
+
+			case MgPropertyType::Byte :
+				$value = $featureReader->GetByte($name);
+				break;
+
+			case MgPropertyType::Single :
+				$value = $featureReader->GetSingle($name);
+				break;
+
+			case MgPropertyType::Double :
+				$value = $featureReader->GetDouble($name);
+				break;
+
+			case MgPropertyType::Int16 :
+				$value = $featureReader->GetInt16($name);
+				break;
+
+			case MgPropertyType::Int32 :
+				$value = $featureReader->GetInt32($name);
+				break;
+
+			case MgPropertyType::Int64 :
+				$value = $featureReader->GetInt64($name);
+				break;
+
+			case MgPropertyType::String :
+				$value = $featureReader->GetString($name);
+				break;
+
+			case MgPropertyType::DateTime :
+			case MgPropertyType::Null :
+			case MgPropertyType::Blob :
+			case MgPropertyType::Clob :
+			case MgPropertyType::Feature :
+			case MgPropertyType::Geometry :
+			case MgPropertyType::Raster :
+				$value = '[unsupported data type]';
+				break;
+		}
+		return $value;
+	}
+
+    private function GetDistributionsForDataType($type)
+    {
+        $distros = array();
+
+        switch($type)
+        {
+			case MgPropertyType::String:
+				array_push($distros, 0);
+				break;
+
+			case MgPropertyType::Byte :
+			case MgPropertyType::Int16 :
+			case MgPropertyType::Int32 :
+			case MgPropertyType::Int64 :
+				array_push($distros, 0, 1, 2, 3, 4);
+				break;
+
+			case MgPropertyType::Single :
+			case MgPropertyType::Double :
+				array_push($distros, 1, 2, 3, 4);
+				break;
+
+			case MgPropertyType::Boolean:
+			case MgPropertyType::DateTime:
+            case MgPropertyType::Blob:
+            case MgPropertyType::Clob:
+            case MgPropertyType::Byte:
+            case MgPropertyType::Feature:
+            case MgPropertyType::Geometry:
+            case MgPropertyType::Null:
+				break;
+        }
+        return $distros;
+    }
+
+	private function MakeUniqueLayerName($map, $layerName, $themeName)
+	{
+		$desiredName = "_" . $layerName . $themeName;
+		$uniqueName = $desiredName;
+		$index = 1;
+
+		while ($map->GetLayers()->Contains($uniqueName))
+		{
+			$uniqueName = $desiredName . $index;
+			$index++;
+		}
+		return $uniqueName;
+	}
+}
+?>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/theme/templates/arearuletemplate.xml
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/theme/templates/arearuletemplate.xml	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/theme/templates/arearuletemplate.xml	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,17 @@
+<AreaRule>
+ <LegendLabel>%s</LegendLabel>
+ <Filter>%s</Filter>
+ <AreaSymbolization2D>
+  <Fill>
+   <FillPattern>Solid</FillPattern>
+   <ForegroundColor>%s</ForegroundColor>
+   <BackgroundColor>FF000000</BackgroundColor>
+  </Fill>
+  <Stroke>
+   <LineStyle>Solid</LineStyle>
+   <Thickness>0</Thickness>
+   <Color>%s</Color>
+   <Unit>Inches</Unit>
+  </Stroke>
+ </AreaSymbolization2D>
+</AreaRule>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/theme/themecontroller.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/theme/themecontroller.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/theme/themecontroller.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,59 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+    require_once '../utilityfunctions.php';
+    require_once '../JSON.php';
+    require_once 'classes/theme.php';
+
+    $args = ($_SERVER['REQUEST_METHOD'] == "POST") ? $_POST : $_GET;
+
+    MgInitializeWebTier($configFilePath);
+
+    $theme = new Theme($args);
+    $json = new Services_JSON();
+    $responseType = '';
+    $response = '';
+
+    if (array_key_exists('COMMAND', $args))
+    {
+        $cmd = $args['COMMAND'];
+        switch ($cmd) {
+            case "GETLAYERINFO":
+                $reponseType = 'text/plain';
+                $response = $json->encode($theme->GetLayerInfo());
+                break;
+            case "GETPROPERTYMINMAXCOUNT":
+                $reponseType = 'text/plain';
+                $response = $json->encode($theme->GetPropertyMinMaxCount());
+                break;
+            case "APPLYTHEME":
+                $reponseType = 'text/plain';
+                $response = $json->encode($theme->ApplyTheme());
+//                $reponseType = 'text/xml';
+//                $response = $theme->ApplyTheme();
+                break;
+        }
+    }
+
+    header('Content-Type: ' . $responseType);
+    echo $response;
+?>
\ No newline at end of file

Added: trunk/MgDev/Doc/samples/phpviewersample/theme/thememain.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/theme/thememain.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/theme/thememain.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,458 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+
+<?php
+    require_once '../utilityfunctions.php';
+    require_once '../JSON.php';
+    require_once 'classes/theme.php';
+
+    $args = ($_SERVER['REQUEST_METHOD'] == "POST") ? $_POST : $_GET;
+
+    $errorMsg = null;
+    $errorDetail = null;
+
+    try
+    {
+        MgInitializeWebTier($configFilePath);
+
+        $theme = new Theme($args);
+
+        $layerNames = $theme->GetMapLayerNames();
+    }
+    catch (MgException $mge)
+    {
+        $errorMsg = $mge->GetMessage();
+        $errorDetail = $mge->GetDetails();
+    }
+    catch (Exception $e)
+    {
+        $errorMsg = $e->GetMessage();
+    }
+?>
+<html>
+<head>
+    <title>Theme Layer</title>
+    <link rel="stylesheet" href="../styles/gt.css" type="text/css">
+    <script language="javascript" src="../../viewerfiles/browserdetect.js"></script>
+    <script language="javascript" src="../json.js"></script>
+
+    <script language="javascript">
+        var READY_STATE_UNINITIALIZED     = 0;
+        var READY_STATE_LOADING         = 1;
+        var READY_STATE_LOADED             = 2;
+        var READY_STATE_INTERACTIVE     = 3;
+        var READY_STATE_COMPLETE         = 4;
+
+        var NOT_BUSY_IMAGE = "../images/loader_inactive.gif";
+        var BUSY_IMAGE = "../images/loader_pulse.gif";
+
+        var SET_FILL_FROM_COLOR     = 1;
+        var SET_FILL_TO_COLOR         = 2;
+        var SET_LINE_FROM_COLOR     = 3;
+        var SET_LINE_TO_COLOR        = 4;
+
+        var fillFromColor = "FF0000";
+        var fillToColor = "0000FF";
+        var lineFromColor = "000000";
+        var lineToColor = "000000";
+
+        var session = '<?= $args['SESSION'] ?>';
+        var mapName = '<?= $args['MAPNAME'] ?>';
+
+        var distNameArray = '<?php $json = new Services_JSON(); echo $json->encode($theme->distNameArray) ?>'.parseJSON();
+        var distValueArray = '<?php $json = new Services_JSON(); echo $json->encode($theme->distValueArray) ?>'.parseJSON();
+
+        var themeReqHandler = null;
+        var layerInfo = null;
+
+        var featureCount = 0;
+        var ruleCount = 8;
+
+        function OnLayerChange()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var propertySelect = document.getElementById("propertySelect");
+            var scaleSelect = document.getElementById("scaleSelect");
+
+            reqParams = "COMMAND=GETLAYERINFO";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+
+            if (msie)
+                reqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                reqHandler = new XMLHttpRequest();
+
+            reqHandler.open("POST", "themecontroller.php", false);
+            reqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            reqHandler.send(reqParams);
+            layerInfo = reqHandler.responseText.parseJSON();
+
+            propertySelect.options.length = 0;
+            for (var i = 0; i < layerInfo.properties.length; i++)
+            {
+                propertySelect.options[i] = new Option(layerInfo.properties[i].name, i, false, false);
+            }
+            OnPropertyChange();
+
+            scaleSelect.options.length = 0;
+            for (var i = 0; i < layerInfo.scaleRanges.length; i++)
+            {
+                scaleSelect.options[i] = new Option(layerInfo.scaleRanges[i], i, false, false);
+            }
+        }
+
+        function OnPropertyChange()
+        {
+            var propertySelect = document.getElementById("propertySelect");
+            var distroSelect = document.getElementById("distroSelect");
+
+            PopulateMinMaxCount(propertySelect.value);
+
+            distroSelect.options.length = 0;
+            if (propertySelect.selectedIndex >= 0)
+            {
+                for (var i = 0; i < layerInfo.properties[propertySelect.value].distroTypes.length; i++)
+                {
+                    distroSelect.options[i] = new Option(distNameArray[layerInfo.properties[propertySelect.value].distroTypes[i]], distValueArray[layerInfo.properties[propertySelect.value].distroTypes[i]], false, false);
+                }
+            }
+            OnDistroChange();
+        }
+
+        function OnDistroChange()
+        {
+            var distroSelect = document.getElementById("distroSelect");
+            var numRules = document.getElementById("numRules");
+
+            if (distroSelect.value == distValueArray[0])
+            {
+                numRules.disabled = true;
+                numRules.value = featureCount;
+            }
+            else
+            {
+                numRules.disabled = false;
+                numRules.value = ruleCount;
+            }
+        }
+
+        function PopulateMinMaxCount(propertyIndex)
+        {
+            var layerSelect = document.getElementById("layerSelect");
+
+            reqParams = "COMMAND=GETPROPERTYMINMAXCOUNT";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+            reqParams += "&PROPERTYNAME=" + encodeURIComponent(layerInfo.properties[propertyIndex].name);
+
+            if (msie)
+                themeReqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                themeReqHandler = new XMLHttpRequest();
+
+            themeReqHandler.onreadystatechange = OnGetMinMaxCountReadyStateChange;
+            themeReqHandler.open("POST", "themecontroller.php", true);
+            themeReqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            document.getElementById("busyImg").src = BUSY_IMAGE;
+
+            DisableControls(['layerSelect', 'propertySelect'], true);
+
+            themeReqHandler.send(reqParams);
+        }
+
+        function OnGetMinMaxCountReadyStateChange()
+        {
+            var ready = themeReqHandler.readyState;
+
+            if (ready == READY_STATE_COMPLETE)
+            {
+                minMaxCount = themeReqHandler.responseText.parseJSON();
+
+                document.getElementById("minValue").value = minMaxCount[0];
+                document.getElementById("maxValue").value = minMaxCount[1];
+                featureCount = minMaxCount[2];
+
+                OnDistroChange();
+
+                DisableControls(['layerSelect', 'propertySelect'], false);
+                document.getElementById("busyImg").src = NOT_BUSY_IMAGE;
+                themeReqHandler = null;
+            }
+        }
+
+        function DisableControls(ids, enable)
+        {
+            for (var i = 0; i < ids.length; i++)
+            {
+                document.getElementById(ids[i]).disabled = enable;
+            }
+        }
+
+        function PickColor(whichColor, allowTransparency, transparent)
+        {
+            var clr;
+            setColor = whichColor;
+
+            if (setColor == SET_FILL_FROM_COLOR)
+                clr = fillFromColor;
+            else if (setColor == SET_FILL_TO_COLOR)
+                clr = fillToColor;
+            else if (setColor == SET_LINE_FROM_COLOR)
+                clr = lineFromColor;
+            else if (setColor == SET_LINE_TO_COLOR)
+                clr = lineToColor;
+           else
+                return;
+
+            height = allowTransparency? 470: 445;
+            w = window.open("../../mapviewerphp/colorpicker.php?LOCALE=en&CLR=" + clr + "&ALLOWTRANS=" + (allowTransparency? "1":"0") + "&TRANS=" + (transparent?"1":"0"), "colorPicker", "toolbar=no,status=no,width=355,height=" + height);
+            w.focus();
+        }
+
+        function OnColorPicked(clr, trans)
+        {
+            if (setColor == SET_FILL_FROM_COLOR)
+                fillFromColor = clr;
+            else if (setColor == SET_FILL_TO_COLOR)
+                fillToColor = clr;
+            else if (setColor == SET_LINE_FROM_COLOR)
+                lineFromColor = clr;
+            else if (setColor == SET_LINE_TO_COLOR)
+                lineToColor = clr;
+           else
+                return;
+
+            UpdateColors();
+        }
+
+        function UpdateColors()
+        {
+            var elt;
+
+            elt = document.getElementById("fillFromSwatch").style;
+            elt.backgroundColor = "#" + fillFromColor;
+            elt.color = "#" + fillFromColor;
+
+            elt = document.getElementById("fillToSwatch").style;
+            elt.backgroundColor = "#" + fillToColor;
+            elt.color = "#" + fillToColor;
+
+            elt = document.getElementById("lineFromSwatch").style;
+            elt.backgroundColor = "#" + lineFromColor;
+            elt.color = "#" + lineFromColor;
+
+            elt = document.getElementById("lineToSwatch").style;
+            elt.backgroundColor = "#" + lineToColor;
+            elt.color = "#" + lineToColor;
+        }
+
+        function ApplyTheme()
+        {
+            var layerSelect = document.getElementById("layerSelect");
+            var propertySelect = document.getElementById("propertySelect");
+
+            reqParams = "COMMAND=APPLYTHEME";
+            reqParams += "&SESSION=" + encodeURIComponent(session);
+            reqParams += "&MAPNAME=" + encodeURIComponent(mapName);
+            reqParams += "&LAYERNAME=" + encodeURIComponent(layerSelect.value);
+            reqParams += "&THEMENAME=" + encodeURIComponent(document.getElementById("themeName").value);
+            reqParams += "&PROPERTYNAME=" + encodeURIComponent(layerInfo.properties[propertySelect.value].name);
+            reqParams += "&DATATYPE=" + encodeURIComponent(layerInfo.properties[propertySelect.value].dataType);
+            reqParams += "&MINVALUE=" + encodeURIComponent(document.getElementById("minValue").value);
+            reqParams += "&MAXVALUE=" + encodeURIComponent(document.getElementById("maxValue").value);
+            reqParams += "&DISTRO=" + encodeURIComponent(document.getElementById("distroSelect").value);
+            reqParams += "&NUMRULES=" + encodeURIComponent(document.getElementById("numRules").value);
+            reqParams += "&SCALERANGEINDEX=" + encodeURIComponent(document.getElementById("scaleSelect").value);
+            reqParams += "&FILLTRANS=" + encodeURIComponent(document.getElementById("fillTrans").value);
+            reqParams += "&FILLFROM=" + encodeURIComponent(fillFromColor);
+            reqParams += "&FILLTO=" + encodeURIComponent(fillToColor);
+            reqParams += "&LINEFROM=" + encodeURIComponent(lineFromColor);
+            reqParams += "&LINETO=" + encodeURIComponent(lineToColor);
+
+            if (msie)
+                themeReqHandler = new ActiveXObject("Microsoft.XMLHTTP");
+            else
+                themeReqHandler = new XMLHttpRequest();
+
+            themeReqHandler.onreadystatechange = OnApplyThemeReadyStateChange;
+            themeReqHandler.open("POST", "themecontroller.php", true);
+            themeReqHandler.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+            document.getElementById("busyImg").src = BUSY_IMAGE;
+
+            DisableControls(['layerSelect', 'propertySelect'], true);
+
+            themeReqHandler.send(reqParams);
+        }
+
+        function OnApplyThemeReadyStateChange()
+        {
+            var ready = themeReqHandler.readyState;
+
+            if (ready == READY_STATE_COMPLETE)
+            {
+                DisableControls(['layerSelect', 'propertySelect'], false);
+                document.getElementById("busyImg").src = NOT_BUSY_IMAGE;
+                themeReqHandler = null;
+
+                parent.parent.Refresh();
+            }
+        }
+
+        function OnLoad()
+        {
+            OnLayerChange();
+            UpdateColors();
+        }
+    </script>
+
+</head>
+
+<body onLoad="OnLoad()" marginwidth=5 marginheight=5 leftmargin=5 topmargin=5 bottommargin=5 rightmargin=5>
+
+<?php if ($errorMsg == null) { ?>
+
+<table class="RegText" border="0" cellspacing="0" width="100%">
+    <tr><td colspan="2" class="Title"><img id="busyImg" src="../images/loader_pulse.gif" style="vertical-align:bottom">&nbsp;Theme Layer<hr></td></tr>
+    <tr><td colspan="2" class="SubTitle">Select a Layer</td></tr>
+    <tr><td colspan="2">Layer:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="layerSelect" onChange="OnLayerChange()" style="width: 100%">
+                <?php
+                    $selected = 'selected';
+                    foreach($layerNames as $layerName => $layerLabel) {
+                ?>
+                <option value="<?= $layerName ?>" <?=$selected ?> ><?= $layerLabel ?></option>
+                <?php
+                        $selected = '';
+                    }
+                ?>
+              </select>
+        </td>
+    </tr>
+    <tr><td colspan="2">Theme Name:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="100" class="Ctrl" id="themeName" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" class="SubTitle">Define Conditions</td></tr>
+    <tr><td colspan="2">Property:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="propertySelect" onChange="OnPropertyChange()" style="width: 100%">
+              </select>
+        </td>
+    </tr>
+    <tr><td colspan="2">Min:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="100" class="Ctrl" id="minValue" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2">Max:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="100" class="Ctrl" id="maxValue" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2">Distribution:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="distroSelect" onChange="OnDistroChange()" style="width: 100%">
+              </select>
+        </td>
+    </tr>
+    <tr><td colspan="2"># of Rules:</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <input maxlength="10" class="Ctrl" id="numRules" value="8" style="width: 100%">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" class="SubTitle">Scale Range</td></tr>
+    <tr>
+        <td colspan="2" class="RegText">
+            <select size="1" class="Ctrl" id="scaleSelect" style="width: 100%">
+              </select>
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" class="SubTitle">Style Ramp</td></tr>
+    <tr><td>Fill Transparency:</td></tr>
+    <tr>
+        <td  colspan="2" class="RegText">
+            <input class="Ctrl" id="fillTrans" type="text"  maxlength="3" value="0" style="width:90%">&nbsp;%
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td>Fill Color:</td></tr>
+    <tr>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;From:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="fillFromSwatch" style="color: #FF0000; background-color: #FF0000">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_FILL_FROM_COLOR,false,false)">
+        </td>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;To:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="fillToSwatch" style="color: #0000FF; background-color: #0000FF">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_FILL_TO_COLOR,false,false)">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td>Border Color:</td></tr>
+    <tr>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;From:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="lineFromSwatch" style="color: #000000; background-color: #000000">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_LINE_FROM_COLOR,false,false)">
+        </td>
+        <td valign="top">
+            &nbsp;&nbsp;&nbsp;To:<br>
+            &nbsp;&nbsp;&nbsp;<span class="Swatch" id="lineToSwatch" style="color: #000000; background-color: #000000">&nbsp;transparent&nbsp;</span>&nbsp;&nbsp;
+            <input class="Ctrl" type="button" value="..." style="width: 22px;" onClick="PickColor(SET_LINE_TO_COLOR,false,false)">
+        </td>
+    </tr>
+    <tr><td colspan="2" class="Spacer"></td></tr>
+    <tr><td colspan="2" ><hr></td></tr>
+    <tr><td colspan="2" align="right"><input class="Ctrl" type="button" value="Apply" style="width: 60px;" onClick="ApplyTheme()"></td></tr>
+</table>
+
+<?php } else { ?>
+
+<table class="RegText" border="0" cellspacing="0" width="100%%">
+    <tr><td class="Title">Error<hr></td></tr>
+    <tr><td><?= $errorMsg ?></td></tr>
+    <tr><td><?= $errorDetail ?></td></tr>
+</table>
+
+<?php } ?>
+
+</body>
+
+</html>

Added: trunk/MgDev/Doc/samples/phpviewersample/title.html
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/title.html	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/title.html	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>Title Frame Content</title>
+<style type="text/css">
+<!--
+.apptitle {
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+	font-size: 16px;
+	font-style: normal;
+	color: #FFFFFF;
+	vertical-align: baseline;
+	height: 30px;
+	line-height: 30px;
+	margin-left: 6px;
+}
+-->
+</style>
+</head>
+<body bgcolor="#006633">
+<p class="apptitle">Viewer Sample Application</p>
+</body>
+</html>

Added: trunk/MgDev/Doc/samples/phpviewersample/utilityfunctions.php
===================================================================
--- trunk/MgDev/Doc/samples/phpviewersample/utilityfunctions.php	                        (rev 0)
+++ trunk/MgDev/Doc/samples/phpviewersample/utilityfunctions.php	2011-12-08 17:49:44 UTC (rev 6318)
@@ -0,0 +1,92 @@
+<?php
+
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+?>
+<?php
+
+	$thisFile = __FILE__;
+	$pos = strrpos($thisFile, '\\');
+	if ($pos == false)
+	{
+	   $pos = strrpos($thisFile, '/');
+	}
+
+	$web_Dir = substr($thisFile, 0, $pos+1);
+	$configFilePath = $web_Dir . "../webconfig.ini";
+
+	include $web_Dir . "../mapviewerphp/constants.php";
+
+
+	// Searches the map for a layer with the specified name.
+
+	function GetXmlPath()
+	{
+
+		$thisFile = __FILE__;
+		$pos = strrpos($thisFile, '\\');
+		if ($pos == false)
+		{
+		   $pos = strrpos($thisFile, '/');
+		}
+
+		$web_Dir = substr($thisFile, 0, $pos+1);
+
+		return $web_Dir. "findaddress/templates/addressmarker.xml";
+	}
+
+	$web_Dir = substr($thisFile, 0, $pos+1);
+	function GetLayerByName($map, $layerName)
+	{
+	    $layer = null;
+	    for ($i = 0; $i < $map->GetLayers()->GetCount(); $i++)
+	    {
+	        $nextLayer = $map->GetLayers()->GetItem($i);
+	        if ($nextLayer->GetName() == $layerName)
+	        {
+	            $layer = $nextLayer;
+	            break;
+	        }
+	    }
+	    return $layer;
+	}
+
+	// Read the content from an MgByteReader and send it back as the response.
+
+	function OutputReaderContent($byteReader)
+	{
+		$buffer = '';
+		$contentLen = 0;
+		do
+		{
+			$data = str_pad("\0", 50000, "\0");
+			$len = $byteReader->Read($data, 50000);
+			if ($len > 0)
+			{
+				$contentLen = $contentLen + $len;
+				$buffer = $buffer . substr($data, 0, $len);
+			}
+		} while ($len > 0);
+
+		header('Content-Type: ' . $byteReader->GetMimeType());
+		header('Content-Length: ' . $contentLen);
+		echo $buffer;
+
+		return;
+	}
+?>
\ No newline at end of file



More information about the mapguide-commits mailing list