Table of Contents
Abstract
This document describes the design of mapbuilder-lib, a module within the Community Map Builder framework.
This document is referred to as mapbuilder-lib Software Design Description, associated with release $Name: mapbuilder-lib-1_0-rc1 $.
The source document is stored in Docbook XML format and is stored
in the Community Mapbuilder CVS repository in
mapbuilder/design/mapbuilder-lib.xml.
mapbuilder-lib provides components that can be used to build geographic client applications within a web browser. It uses Open GIS Standards (OGC) to communication with external Map Servers.
It uses Javascript and XSL which can be rendered by Internet Explorer 6+, Mozilla 1.3+ and Netscape 6+.
mapbuilder-lib uses an object oriented design which makes it easy to extend.
This document describes the design of mapbuilder-lib, a module within the Community Map Builder framework. See the layout guide for instructions on customizing the configuration elements.
The structure of this document is loosely based on the SDD template provided by MIL-STD 498.
jsdocs of javascript objects. (Similar to javadocs).
Web Map Service specification.
Web Map Context specification.
Web Feature Service specification.
The goals of the libraries are to provide the following:
Mapbuilder Clients should be easy for users to run. Users should not have to download and install new software. Instead all Mapbuilder clients should run inside the commonly used web browsers. In particular, Internet Explorer 6+ and Mozilla browsers based on Mozilla 1.3+.
Mapbuilder should keep deployment requirements to a minimum in order to maximise the user base. Hence:
Where possible, clients should not require server side scripts.
If server side scripts are required, the server environments currently supported include: Perl, PHP, JSP. Contributions for equivalent functionality in other server environments is encouraged. Please see server dependencies
(TBD link a section for server requirements).
Mapbuilder widgets are to be incorporated into HTML web pages. Incorporating widgets should be kept simple so that someone with basic HTML and Javascript knowledge can build a Mapbuilder Web Page.
All client functionality needs to be downloaded, so it is important to keep it to a minimum. Files that are downloaded should also be static which means that browsers will cache them locally. (CGI scripts generally do not provide images that are cached).
Mapbuilder stores state data internally in XML files. Converting XML to HTML is done using XSL. XSL has the advantage that it can be used both in the client and server.
A modular design has many benefits.
A client need only include the module it requires, hence reducing the size of the client.
A modular design is easier to understand, maintain and extend.
Extra functionality can be easily added and removed.
It is easier to break development up between multiple developers.
Mapbuilder software is open source. Open source was chosen because:
Part of our target audience are community groups who often cannot justify buying software.
Developers are more likely to extend open source software.
It's fun developing open source software.
Any libraries that Mapbuilder uses or extends should not introduce an incompatible or closed license.
Hopefully potential developers will extend this project in preference to creating their own. Things that should help attract developers include:
Keep the design simple, modular and easy to understand.
Provide design and user documentation.
Provide discussion forums.
Provide stable releases which are easy to install and evaluate.
Provide demos that potential users and developers can try.
Mapbuilder uses the Model View Controller (MVC) design pattern for rendering widgets. Unlike many Content Management Systems, mapbuilder stores it's all it's model data in the web browser, which speeds up user interactions because communication with the server is reduced.
The MVC pattern forces one to think of an application in terms of three modules:
This maintains the state and data that the application
represents. When changes occur in the model, it sends update
events to all of its views. Context is
the Model in the Mapbuilder application and stores Layers,
Bounding Box etc.
The user interface which displays information about the
model to the user. Views displaying dynamic data need to
register for StateChange events from the Model.
Legend, MapPane, etc
are all Mapbuilder Views that get update events when
Context changes.
The user interface presented to the user to manipulate
the application (ie keyboard and mouse input).
ZoomTool, PanTool,
SelectFeature are all Mapbuilder
Controllers which update Context.
Some components can act as both a View and Controller. For
example, a LocatorMap may allow users to draw a
select box to change the BoundingBox. Also, when the BoundingBox in
Context changes, the LocatorMap will draw a new Box over it's
basemap.
There is a lot of literature describing the MVC Design Pattern. Here is one.
The components are explained in more detail in Section 4.4, “Components”.
The benefits of using the MVC design pattern include:
Views and Tools can be added or removed without effecting the rest of the application. Tools do not have any dependencies on Views and visa-versa which makes Tools and Views simpler.
Views can display the same data in different ways. For example, a Locater Map and Main Map both display the BoundingBox in different ways.
Once the interfaces have been defined, components can be developed in parallel.
Javascript doesn't provide inheritance, however there are a number of sub-optimal hacks available and we have used a couple of them in mapbuilder. Most are similar to this example where Legend extends WidgetBase.
var base = new WidgetBase(this, widgetNode, model);
...
// If this object is being created because a child is extending this object,
// then child.properties = this.properties
for (sProperty in this) {
widget[sProperty] = this[sProperty];
}
It is important to note that our implementation of inheritance requires each function call to be passed it's object instance (usually called objRef). Eg:
/**
* Remove widget from display.
* @param objRef Pointer to this object.
*/
this.clearWidget = function(objRef) {
..
}The Main Web Page uses include and initialise mapbuilder-lib and to layout the page.
Example 1. Including and initialising mapbuilder-lib
<html>
<head>
<title>Mapbuilder Demo</title>
<link rel="stylesheet" href="../lib/skin/default/html.css" type="text/css">
<script>
// URL of Mapbuilder configuration file.
var mbConfigUrl='config/CompleteConfig.xml';
</script>
<script type="text/javascript" src="../lib/Mapbuilder.js"></script>
</head>
<body onload="mbDoLoad()">
<Insert more html here/>
</body>
</html>mapbuilder-lib widgets are inserted using HTML tags with unique identifies. When mapbuilder-lib renders widgets, HTML is inserted into the widget tags.
Example 2. HTML with widget tags
<table>
<tr>
<td id="mainMapPaneId"/>
</tr>
<tr>
<td>
<div id="buttonBarId"/>
</td>
</tr>
</table>For further details on how to use mapbuilder-lib, refer to the Users Guide.
Layout of widgets should be done using CSS instead of tables. Most Content Management Systems (CMS) use CSS for layout. The CSS can be maintained as a "skin" and a different skin can be selected easilly by users.
A minor change needs to be made to the paint() methods so that painting to an undefined HTML id will work.
The Web Map Context stores geographic state, like Map Layers, Bounding Box, etc. The format is defined by the OGC's Web Map Context (WMC) specification.
At least one context.xml file is required for each Mapbuilder application and is referenced from the config.xml file.
The Config file is an XML document which describes which mapbuilder-lib components should be included in an application. The schema for the config file is stored at mapbuilder/lib/schema/config.xsd and can be viewed more easilly using the Mapbuilder Components Register.
The mapbuilder-lib configuration XML document is based on RDF principles. Future plans include defining a mapbuilder config document schema by extending the RDF schema.
The config doc follows Object-Property-Value rule of GML3 and RDF. As a rule of thumb, this means that parent and child elements alternate between UpperCamelCase and lowerCamelCase, Upper is for objects and lower is for properties. An object can only contain another object through a property value.
Example 3. Example use of Object-Property-Value
<ContextCollection id="collectionGroup">
<defaultModelUrl>context/demoCollection.ccml</defaultModelUrl>
<widgets>
<CollectionList id="collectionListId">
<scriptFile>widget/collectionList/CollectionList.js</scriptFile>
<stylesheet>widget/collectionList/Collection2List.xsl</stylesheet>
<targetWidgetGroup>mainMapGroup</targetWidgetGroup>
</CollectionList>
</widgets>
</ContextCollection>
A more complete description of the object-property-value rule can be found in section 2.1 of the document: Developing and Managing GML Application Schemas.
Model components store mapbuilder state and notify widgets when state changes. State is often read from and stored in XML files.
TBD: Explain how state is stored in Listener objects.
Widgets are responsible for rendering map components into the MainPage whenever state changes. Usually, the widget uses XSL to convert an XML document to an HTML snippet. The HTML snippet is inserted into the widget's HTML tag in the MainPage.
Tool Components process mouse and key actions on behalf of a widget and update Model Components with new state information.
The Listener object provides setParam() and getParam() methods, and notifies Listeners when the parameter changes. Objects requiring this functionality extend the Listener object.
The Listener object was introduced to overcome Javascript's poor support for events.
Example 4. Simple use of Listener
SomeModel contains a parameter someParam and SomeWidget needs to repaint itself whenever someParam changes.
- SomeModel extends Listener()
function SomeModel() { // Inherit the Listener functions and parameters var listener = new Listener(); for (sProperty in listener) { this[sProperty] = listener[sProperty]; } ...- SomeWidget registers to receive update events when someParam changes
/** Function called when someParam changes */ this.someFunction=function(objRef){ alert("someParam has changed"); } someModel.addListener("someParam",this.someFunction,this);- SomeTool updates someParam and triggers a call to SomeWidget.someFunction
SomeModel.setParam("someParam", "newValue");
The Mapbuilder object is responsible for loading and initialising required script files. The scripts required is determined from the Config file. The Mapbuilder object loads the scripts in order of dependency, periodically checking the load status. When all scripts have loaded, the javascript objects are initialised which triggers the rendering of widgets.
Javascript doesn't naturally provide inheritance. Instead there are a number of hack solutions that a programmer can choose from. In mapbuilder-lib, the following method is used:
Javascript object constructors must have the same name as the node of it's corresponding object in the configuration document. For example, a <Context> object from the config doc will be instantiated by the javascript call:
var model = new Context();
The Javascript code for each model, widget and tool object type should be created in the lib/model, lib/widget and lib/tool directories respectively. By default, the file containing javascript object code will have the same filename as the object type name, so for example, the javascript Context code will be loaded from the file lib/model/Context.js. This default filename of the javascript object code can be over-ridden by setting a <scriptfile> property on the object in the configuration document.
In addition, the stylehseet filename for widgets will also use the object type name with an extension of .xsl by default. For example, the <Legend> XSL file to style the Legend object is lib/widget/Legend.xsl by default. This default filename can be over-ridden by setting a <stylesheet> property on the widget object.
When extending the mapbuilder code base, it's usually easiest to copy code from other models, widgets and tools.
Depending on what functionality you want to add, you will begin at one of the steps listed below. For example you could be just adding a tool to a widget (step 4 only) or you could be adding a whole new model type, along with a new ModelGroup in the config file and associated widgets and tools (steps 1 through 4).
Add a new model type:
If you are representing a new XML document type not already supported by mapbuilder, first code the javascript Model object. All model objects should inherit from ModelBase. Javascript source files are added to the lib/models directory. Add a new object to the <models> property of the config document which points to the javascript source file. The model constructor must be named the same as the <modelType> properties of a ModelGroup object.
Add a new model:
Only do this if the actual instance of the model you are working with is not already represented as a Model in config. Assign the Model an "id" attribute so that it can be referenced using that id as the property name of mbConfig (e.g. mbConfig['modelId']). Add defaultModelUrl properties to the Model which is the URL of the document that will be loaded by default.
Add widgets to a model:
For each view of the model to be displayed on the web page, add a widget object to the <widgets> property. All widget objects must inherit from the WidgetBase class. A widget constructor must have the same name as the widget object node name in the config document. Source code for widgets is added as a subdirectory of lib/widgets containing all files required to paint the widget. Add the <scriptfile> and <stylesheet> properties to the object in config to point to these source files. The widget will be painted to the HTML element with the same id as the "id" attribute of the widget. Customize the widget object as required.
Add tools to widgets
For each controller used to control the model objects, add a tool object to the widget <tools> property. A tool constructor must have the same name as the tool object node name in the config document. Source code for tools are added to the lib/tools directory (TBD: subject to change). Add the <scriptfile> property to the object in config to point to these source files. A tool contained by one model group can be used as a controller of another model group by adding a <targetModelGroup> property which has the value of a ModelGroup id. Customize the tool object as required.
Table A.1. Glossary
| Term | Expanded Acronym | Description |
|---|---|---|
| AOI | Area Of Interest | |
| CSS | Coordinate System Specification | |
| CTS | Coordinate Transform Service | As specified by the OGC. |
| IDE | Integrated Development Environment | |
| IRC | Internet Relay Chat | A way to communicate in real time with lots of other people around the world in a virtual meeting. |
| GCS | Grid Coverage Specification | As specified by the OGC. |
| GIS | Geographic Information Systems | |
| GML | Geographic Markup Language | XML format for describing geographic features. |
| LGPL | GNU General Public License | Open Source License. |
| MIL-STD 498 | Military Standard 498 | Set of processes for software development. |
| OGC | Open GIS Consortium | Geographic Standards Body |
| RDF | Resource Description Framework | Framework to describe any Internet resource such as a Web site and its content. |
| SDD | Software Design Description | A design document as defined by MIL-STD 498. |
| SRS | Spacial Reference System | Spacial Reference System (as defined by the OGC). An alpha-numeric ID which specifies what coordinate system you are using. Eg: SRS="EPSG:4326". |
| SVG | Scalable Vector Graphics | |
| SLD | Styled Layer Descriptor | XML document which describes how to draw specific features. Eg, A road line may be drawn in red, 3 pixels wide. |
| UML | Unified Modeling Language | A set of diagrams used to describe software pictorially. |
| WCS | Web Coverage Server | |
| WFS | Web Feature Server | Return vector data about features. |
| WMS | Web Map Server | Return raster map images and point queries. |
| XSL | Extensible Stylesheet Language | A language for expressing stylesheets. |
| XSLT | XSL Transform | A language for transforming XML documents into other XML documents. |
| XML | Extensible Markup Language |
Table B.1. Legend for UML class diagrams
| Package | |
| Dependencies between packages. This expresses that classes within a package use classes from the package it depends on. | |
| Interfaces. An Interface is restricted to only contain operations but no attributes. Also, operations are abstract and have no implementation. | |
| Classes. Classes hold operations and attributes and have relations to other classes via association or inheritance relations. | |
| Inheritance relations. Between interfaces or between classes. | |
| Implementation relations. Only between interfaces and classes. | |
| Association relations. Associations are relations between classes. They often include navigation arrows, and multiplicity (eg 1..*). |