wiki:MapGuideRfc129

Version 5 (modified by jng, 11 years ago) ( diff )

--

MapGuide RFC 129 - SWIG/IMake enhancements and enhanced Java wrapper API

This page contains a change request (RFC) for the MapGuide Open Source project. More MapGuide RFCs can be found on the RFCs page.

Status

RFC Template Version(1.0)
Submission Date29 Nov 2012
Last Modified14 Jan 2013
AuthorJackie Ng
RFC Statusadopted
Implementation Statusimplemented
Proposed Milestone2.5
Assigned PSC guide(s)(when determined)
Voting History(vote date)
+1Jackie,Zac,Haris,Trevor
+0
-0
-1
no voteBob,Paul,Tom,Bruce

Overview

This RFC proposes to add enhancments to SWIG/IMake to support an enhanced Java wrapper API as well as supporting the preservation/conversion of doxygen API documentation fragments for Java and .net

Motivation

The problems with the current Java wrapper API are well documented:

  • Java method names are in UpperCamelCase (verbatim copy from MapGuide's C++ classes) instead of lowerCamelCase
  • MgException is a checked exception. All java methods have the "throws MgException" clause forcing the user to either implement a (possibly un-necessary try/catch block) or to add their own "throws MgException" clause in their calling method
  • MapGuide collection classes (eg. MgStringCollection) not implementing the java.util.Collection interface
  • Lack of integrated javadoc comments in java proxy source files due to doxygen comments being lost in the SWIG build/translation process

Proposed Solution

To address these issues, modifications will be made to our internal copy of SWIG and IMake to enable the creation of an "enhanced" Java wrapper API

Add a JavaApiEx project to the WebTier solution

This is a copy of the JavaApi directory with a set of SWIG macros/customizations/typemaps to facilitiate the implemenation of java.util.Collection and java.util.Iterable for proxy classes that require such interfaces

Classes which are currently slated for java.util.Collection support include:

The following collection classes will not implement the java.util.Collection interface due to disparity in interface and implementation

Classes which are currently slated for java.util.Iterable support include:

The following classes will have special implementations of equals() and hashCode() needed for item containment logic to properly work in the java.util.Collection API

Classes that implement java.util.Collection or java.lang.Iterable can be iterated with java's enhanced for loop:

MgClassDefinitionCollection classes = ...
for (MgClassDefinition clsDef : classes) {
    ...
}

To distinguish this wrapper from the original, this project will output MapGuideJavaApiEx.dll as the JNI glue library and MapGuideApiEx.jar as the Java wrapper API jar.

The pre-defined AppThrowable java exception class will now extend from java.lang.RuntimeException, making all subclasses (MgException and co) unchecked exceptions

Modify swig to support 2 new java-specific command-line options (-mgjavacasing and -mgjavanothrow)

With the -mgjavacasing option given, all method names will be re-written with the first letter lower-cased by SWIG

With the -mgjavanothrow option given, the "throws MgException" clause is omitted from all Java method declarations

The JavaApi project will invoke SWIG as before. The JavaApiEx project will invoke SWIG with these 2 new options

Use the SWIG modifier directives as a means of transplanting documentation / deprecation

Using the %typemap(javaclassmodifiers) and %javamethodmodifiers directives (for .net, this is %typemap(csclassmodifiers) and %csmethodmodifiers), we can attach documentation blocks and any attributes to our Java/C# proxy class methods

For example a deprecated API like the blank MgMap constructor can be decorated like so

//Java  
%javamethodmodifiers MgMap::MgMap() %{/**  
* This constructor is deprecated. Use MgMap(MgSiteConnection) instead  
*/   
@Deprecated public%}
  
//C#  
%csmethodmodifiers MgMap::MgMap() %{///<summary>  
/// This constructor is deprecated. Use MgMap(MgSiteConnection) instead  
// </summary>  
[Obsolete(\"This API is deprecated\")] public%}  

Which will cause SWIG to generate the following proxy class method declarations

//Java   
public class MgMap   
{   
    /**  
     * This constructor is deprecated. Use MgMap(MgSiteConnection) instead  
     */  
    @Deprecated public MgMap() {   
    ...   
    }    
}   

//C#   
public class MgMap   
{   
    ///<summary>
    /// This constructor is deprecated. Use MgMap(MgSiteConnection) instead  
    ///</summary>
    [Obsolete("This API is deprecated")] public MgMap() {   
        ...   
    }    
}   

In addition to documentation, this also gives us the ability to transfer C++ API deprecation intent to the target languages as well, allowing for csc and javac to trigger compiler warnings regarding use of deprecated APIs.

As long as the deprecated C++ API(s) are marked up with the doxygen \deprecated directive, they will properly transfer across as @Deprecated in Java and ObsoleteAttribute in .net

Modify IMake to collect doxygen fragments of input headers and output the translated version in the target language

It is obviously impractical to manually write out these SWIG modifier directives by hand. So we'll modify IMake to do this for us.

IMake already does some sort of documentation collection when it writes out the constants source files for PHP/Java/.net. Unfortunately this is a verbatim doxygen dump which renders these blocks un-usable when used for auto-completion within an IDE

So IMake will be modified as follows:

  • Retain the documentation collection logic when the input file is not Constants.xml
  • Add methods to convert the collected doxygen documentation to the target language's documentation format (JavaDoc for Java, XML documentation for .net)
  • Write these converted fragments out as the aforementioned SWIG modifier directives for the target language.

These IMake changes only apply for Java and .net. See implications

Update the *ApiGen.xml files

All these files require a new DocTarget element, which specifies the output file that IMake will write these SWIG modifier directives to.

This file is %include'd into the MapGuideApi.i (the split one for .net) that IMake generates for SWIG, allowing for the documentation to be transferred over to the proxy classes of the target language

Modify the .net and Java API build process

The nmake files for the .net API will be modified so that the csc.exe call includes the /doc parameter. Allowing for Visual Studio intellisense files to be created for each OSGeo.MapGuide assembly

The JavaApi and JavaApiEx pre-build events will be modified to include an extra step to build a -source jar file, allowing for similar integrated auto-complete API documentation in the major Java IDEs

All of the above changes have been implemented in this sandbox. Upon adoption of this RFC, the changes in this sandbox will be merged back into the trunk code stream.

Implications

The existing API wrappers (including the existing Java one) are not affected by these changes.

In fact for some languages (Java/.net), they will be getting the extra benefit of integrated API documentation and compiler warnings on use of deprecated APIs

This RFC has zero effect (positive or negative) on the PHP wrapper. This is due to SWIG not generating any source PHP files for PHP proxy classes, so there is no actual target to drop in the converted doxygen fragments. Also there is no official way to document PHP code, so trying to bring these same integrated API documentation benefits over to PHP is currently a fruitless endeavour.

The DoxyTransform build tool which is currently employed to convert doxygen API documentation to Visual Studio intellisense xml files will be removed as this RFC renders that tool obsolete, and this RFC supports API documentation transfer to both .net and Java instead of just .net

For the "enhanced" Java wrapper, the conversion of method names to lowerCamelCase has exposed some API naming conflicts:

  • The converted MgException.getStackTrace() conflicts with java.lang.Throwable.getStackTrace()
  • The converted MgPropertyDefinition.delete() conflicts with the SWIG-generated delete() method for finalization
  • The converted MgClassDefinition.delete() conflicts with the SWIG-generated delete() method for finalization
  • The converted MgFeatureSchema.delete() conflicts with the SWIG-generated delete() method for finalization
  • The converted add() method of any MapGuide collection class conflicts with the add() method as specified in the java.util.Collection interface (MapGuide's add() returns void, java.util.Collection's add() returns boolean)

Since this "enhanced" Java wrapper will be a new wrapper API, there is no compatibility history to deal with unlike the other wrappers so as a result it is much safer and easier to rename the conflicting methods in this enhanced wrapper than to rename the conflicting APIs in the C++ classes (as was the case for MapGuideRfc89)

The conflicting methods will be renamed in the wrapper as so:

The Java variant of the AJAX viewer will still use the existing Java wrapper. There are no plans in this RFC to convert the Java AJAX viewer to use the enhanced Java wrapper. It is envisioned that this enhanced Java wrapper will be made available in the 2.5 timeframe as a "developer preview" option. Whether this will replace the existing Java wrapper will be the scope for a future RFC.

Test Plan

Add a java test application to exercise the classes in the enhanced java wrapper that implement java.util.Collection and java.lang.Iterable

Test/verify functionality of existing viewers in both Windows/Linux to confirm the SWIG/IMake changes have no adverse effects on the existing wrapper APIs

Funding / Resources

Community

Note: See TracWiki for help on using the wiki.