Saturday, 18 May 2013

MapGuide tidibts: The resource dependency chain

You probably know in MapGuide that there is a whole different bunch of type of resources available at your disposal, when authoring up your data, maps and applications.

You probably also know that if you move, rename or delete a resource you may be affecting and/or breaking other resources that depend on it.

How about the big picture? Well here's one I've prepared earlier.

As you can see, with the exception of the Load Procedure, Application Definition and Web Layout, every other resource type has a dependency on another resource type.

Consider what you may be potentially breaking when you move, rename or delete a given resource.

Wednesday, 15 May 2013

The lab experiment is evolving

And no, I am not trying to build a new MapGuide viewer. :)

This new feature just makes such as task dead simple


Saturday, 11 May 2013

MapGuide tidbits: Maximizing .net code reuse

Code reuse is always a good thing. If you use the .net MapGuide API, you may want to consider some options that can enhance re-usability of your code.

For those who don't know, the MapGuide API is an extension of a common subset known as the Geospatial Platform API. AutoCAD Map3D extends this subset to integrate with AutoCAD Map3D, MapGuide extends this common subset to support web applications and mg-desktop extends this subset to give you a portable MapGuide environment for your desktop applications.



As you can see from the diagram there are key abstract classes in the Geospatial Platform API that are derived by the various implementations (bolded for emphasis). It just so happens that these classes are the key classes for working with maps and layers and the rest of the API through service classes.

By writing your .net code to work against the abstract classes in the Geospatial Platform API, you get to maximize its reuse against the various extensions of this common subset. For example, have your code:
  • Work against MgMapBase instead of MgMap, MgdMap or AcMapMap
  • Work against MgLayerBase instead of MgLayer, MgdLayer or AcMapLayer
  • Work against MgResourceService instead of AcMapResourceService or MgdResourceService
You hopefully get the idea. Where possible, work against the abstract class instead of the concrete implementation.

Writing code this way makes the code more amenable to easy manual dependency injection, with your MapGuide, mg-desktop or AutoCAD Map3D specific code doing the actual injecting, but the dependency injectee not having to care because it works against the abstract class and not the concrete implementations, thus allowing this injectee code to be re-used anywhere that can provide a concrete implementation of the class.

Of course, each extension of the common subset has their own implementation quirks. AutoCAD Map3D has some, mg-desktop has some too. But if such quirks do not affect you, then this coding strategy is something to consider if you want to re-use such code beyond MapGuide web applications.

Another lab experiment


Saturday, 4 May 2013

One request to rule them all

Seriously, image Data URIs are the absolute bomb!





Thursday, 2 May 2013

MapGuide tidbits: MgByteReader and friends

This one's a bit of a post for newbies, so you can skip it if you already know this stuff :)

If you look at the various bits of the MapGuide API, you'll probably see lots of references to MgByteReader lying around. An API will either return one or require one as part of its method parameters.

What is a MgByteReader? A MgByteReader is basically a MapGuide analogue to your Stream class in .net/Java and serves the same purpose: an unified I/O abstraction for things that can be fed into the MapGuide API and things that are returned from the MapGuide API. Things like.

  • Images (of rendered maps/selections)
  • Resource Data files (to download/upload)
  • XML files (to/from the repository)
  • DWF files (for DWF ePlots)
So if you're given an MgByteReader from a particular API, what can I do with it? Similarly, if an API requires passing in a MgByteReader, how can I make one?

Here's a diagram I made up that should explain everything to you.




Since MgByteReader is basically a stream, you might be wondering if the .net/Java/PHP wrappers to the MapGuide API provides any adapters to allow MgByteReader objects to be consumed as Stream objects, so you don't have to do any manual conversion. For PHP and Java, you're out of luck. You'll have to dump the MgByteReader into a supported form as per the above diagram, and then work from there.

For .net however, I've already solved this problem for you :) If you're using the Maestro API (that wraps both the official MapGuide API and the mapagent interface), for APIs that return MgByteReader objects Maestro provides wrapper APIs that return System.IO.Stream objects instead. Similarly for APIs that take MgByteReader parameters, Maestro's wrapper API takes System.IO.Stream objects.

If you're not using Maestro, there's a MgReadOnlyStream class I wrote for mg-desktop that can easily be reused for your own .net applications if you require a System.IO.Stream adapter. MgReadOnlyStream provides mg-desktop an easy way to convert the output of a rendering service API into something that requires a System.IO.Stream (eg. a System.Drawing.Image). That's pretty much the gist of how our mg-desktop viewer works, taking MgByteReader objects from the rendering service, wrapping it into a MgReadOnlyStream and feeding that to a System.Drawing.Image, to then be painted onto a WinForms control surface.

Hope this helps.

Sunday, 28 April 2013

MapGuide tidbits: OpenLayers in relation to Fusion

I'd had been holding off on this particular post for quite some time because what is written below wasn't exactly true or applicable until MapGuide RFC 132 was implemented. Now that the RFC is completed, the time to publish this post is more suitable.

As some of you know, Fusion is built on top of the powerful OpenLayers library.

But what you may not know (and probably want to know) are the specifics.

What version of OpenLayers?

Believe it or not, I myself do not know what version of OpenLayers is currently bundled with the Fusion that comes with MapGuide Open Source 2.5 (or older releases). Our bundled copy in Fusion has the release version number scrubbed out by SVN making it hard to determine the actual version number.

I strongly believe it is OpenLayers 2.10 due to the lack of touch event support.

For the next release of MapGuide Open Source (2.6) the answer will be crystal clear: Fusion will be using OpenLayers 2.12. What OpenLayers 2.12 brings to the table for Fusion will be the topic of another post.

What OpenLayers build profile?

As some of you may know, OpenLayers is not a monolithic library. It can be customized with various build profiles to include/exclude certain parts of the OpenLayers library. What that means in practice is that some parts of the OpenLayers API may not be available to be used in Fusion because we use our own custom build profile for OpenLayers. Our custom build profile is defined in fusion.cfg, there you can see what parts of the OpenLayers API we've included and what parts we've excluded.

Now sadly, the way OpenLayers is set up within the fusion source tree (before RFC 132) is that we are keeping in a "built" version of OpenLayers.js and have customizations done on that one file. This makes customizing your own OpenLayers build for use with Fusion much more harder as our current audit trail of Fusion-specific customizations is very hard to track. This means that customizing your own OpenLayers for Fusion may not be as simple as:
  1. Download the OpenLayers zip/tarball
  2. Build it with your desired build profile
  3. Overwrite Fusion's OpenLayers.js with your built copy.
For the Fusion that will come MapGuide Open Source 2.6, this will be much more clearer. We'll be reserving a section of the Fusion repo, for Fusion-specific customizations to individual js files in OpenLayers such that customizing your own OpenLayers becomes:
  1. Download the OpenLayers 2.12 zip/tarball
  2. Overlay the directory (where you unzip/untared) with our Fusion-specific modified files
  3. Build OpenLayers with your desired build profile
  4. Overwrite Fusion's OpenLayers.js with your built copy
  5. Re-build and re-minify Fusion with your custom OpenLayers.
This way, the OpenLayers build you customize will retain our Fusion-specific changes where necessary, and allows you to tap into parts of OpenLayers that we may have excluded from our custom build.