# -*- coding:latin1 -*-
# Copyright (C) 2004 by Intevation GmbH
# Authors:
# Jan Schüngel <jschuengel@intevation.de>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with Thuban for details.

"""
This module extends Thuban with the possibility to handle
UMN MapServer mapfiles.
"""

__version__ = "$Revision: 1.11 $"
# $Source: /thubanrepository/thuban/Extensions/umn_mapserver/mf_import.py,v $
# $Id: mf_import.py,v 1.11 2004/08/09 11:41:35 jschuengel Exp $



# ###################################
#
# import necessary modules
#
# ###################################

import os, re

from mapscript import mapObj

from wxPython.wx import wxFileDialog, \
                        wxOPEN, wxOVERWRITE_PROMPT, wxID_OK

from wxPython.lib.dialogs import wxMultipleChoiceDialog

# use _() already now for all strings that may later be translated
from Thuban import _

# Thuban has named commands which can be registered in the central
# instance registry.
from Thuban.UI.command import registry, Command

# The instance of the main menu of the Thuban application
from Thuban.UI import mainwindow

# The layer an projection from Thuban
from Thuban.Model.layer import Layer, RasterLayer
from Thuban.Model.proj import Projection

# needed to add the new menu
from Thuban.UI.mainwindow import main_menu, wxID_CANCEL

from Thuban.Model.classification import ClassGroupSingleton, \
                                        ClassGroupRange, \
                                        ClassGroupProperties, \
                                        ClassGroupDefault

from Thuban.Model.range import Range

# The Thuban color objects
from Thuban.Model.color import Transparent 

# import Map Object for the Mapfile
from mapfile import MF_Map

# ###################################
#
# Mainpart of the Extension
#
# ###################################
from Thuban.Model.layer import BaseLayer
class AnnotationLayer(BaseLayer):
    """
    Class to show AnnontationLayer in Thuban.
    This Class is temporary and has only the task 
    to indicate the layer in the layerlist.
    """
    def __init__(self, title, data, visible = False, projection = None):
        
        BaseLayer.__init__(self, title, 
                                 visible = visible,
                                 projection = projection)
        self.store = None
        self.SetShapeStore(data)
    
    def SetShapeStore(self, store):
        self.store = store
    
    def ShapeStore(self):
        return self.store
    
    def ShapeType(self):
        """Return the type of the shapes in the layer.
        """
        return "annotation"
    
    def BoundingBox(self):
        """Return the layer's bounding box in the intrinsic coordinate system.

        If the layer has no shapes, return None.
        """
        return self.store.BoundingBox()

    def LatLongBoundingBox(self):
        """Return the layer's bounding box in lat/long coordinates.

        Return None, if the layer doesn't contain any shapes.
        """
        bbox = self.BoundingBox()
        if bbox is not None and self.projection is not None:
            bbox = self.projection.InverseBBox(bbox)
        return bbox


def set_projection_to_tb(tb_con, mapobj):
    """
    Helpfunction to set the projection in thuban.
    
    Parameters:
        tb_con -- The thuban conext (mapobj or layerobj)
        mapobj -- The mapobject (from mapscript)
    """
    if (mapobj.get_projection().get_params() != None):
        projparams = mapobj.get_projection().get_params()
        # check if it is an latlong projection, becaues one
        # more parameter is needed in that case
        addtometer = False
        for param in projparams:
            projkey = param.split("=")
            if projkey[0] == "proj":
                if projkey[1] == "latlong":
                    addtometer = True
            if projkey[0] == "to_meter":
                addtometer = False
        if addtometer == True:
            projparams.append("to_meter=0.017453")
        tb_con.SetProjection(Projection(projparams))
    if mapobj.get_projection().get_epsgcode() != None:
        projepsg = mapobj.get_projection().get_epsgproj()
        tb_con.SetProjection(projepsg)  

def create_rangeexpression(mapexprstr):
    """
    create a expressionstring in thuban style from an given
    mapfile expressionstring 
    
    mapexprstr = the expressionstring from the mapfile
    """
    attribut_expr = "\[\w+\]"
    attribut = re.compile(attribut_expr)
    operator_expr = ">=|<=|<|>|="
    operator = re.compile(operator_expr)
    #only and now supported
    link_expr = "AND" 
    link = re.compile(link_expr)
    oneexpr = "\s*\[\w+\]\s*>*<*=*\s*\w+"
    theexpr = re.compile(oneexpr)
    
    # init the string variables to build the string later
    thestring = ""
    strbegin = None
    strmin = None
    strmax = None
    strend = None

    link_result = link.findall(mapexprstr)
    attr = attribut.findall(mapexprstr)
    if len(link_result) == 0 and len(attr) == 1:
        strattr = attr[0][1:-1]
        expression = theexpr.findall(mapexprstr)
        if expression:
            operator_result = operator.search(mapexprstr)
            if operator_result.group(0) == ">=":
                strbegin =  "["
                strmin = operator_result.string[operator_result.start()+2:].replace(" ","")
                strmax = "oo"
                strend = "]"
            elif operator_result.group(0) == "<=":
                strbegin =  "["
                strmin = "-oo"
                strmax = operator_result.string[operator_result.start()+2:].replace(" ","")
                strend = "]"
            elif operator_result.group(0) == ">":
                strbegin = "]"
                strmin = operator_result.string[operator_result.start()+1:].replace(" ","")
                strmax = "oo"
                strend = "]"
            elif operator_result.group(0) == "<":
                strbegin = "["
                strmin = "-oo"
                strmax = operator_result.string[operator_result.start()+1:].replace(" ","")
                strend = "["
            elif operator_result.group(0) == "=":
                # create a singleton, not implemented yet
                errorstring = "singleton creation not implemented yet"
            else:
                errorstring = "no operator found"
        else:
            errorstring = "no expression found"
    elif len(link_result) == 1:
        if attr[0] == attr[1]:
            strattr = attr[0][1:-1]
            first_expr,second_expr = mapexprstr.split("AND")
            oneexpr_result = theexpr.findall(mapexprstr)
            operator1_result = operator.search(first_expr)
            operator2_result = operator.search(second_expr)
            errorstring = "operators are wrong"
            if operator1_result.group(0)[0] == "<" and \
               operator2_result.group(0)[0] == ">":
                optemt = operator1_result
                operator1_result = operator2_result
                operator2_result = optemt
            if operator1_result.group(0) == ">=":
                strbegin =  "["
                strmin = operator1_result.string[operator1_result.start()+2:].replace(" ","")
            elif operator1_result.group(0) == ">":
                strbegin = "]"
                strmin = operator1_result.string[operator1_result.start()+1:].replace(" ","")
            if operator2_result.group(0) == "<=":
                strend =  "]"
                strmax = operator2_result.string[operator2_result.start()+2:].replace(" ","")
            elif operator2_result.group(0) == "<" and operator1_result != ">" :
                strend = "["
                strmax = operator2_result.string[operator2_result.start()+1:].replace(" ","")
            if strmax < strmin:
                errorstring = "values are wrong"
                strbegin = None
        else:
           errorstring = "Attributes not equal"
    elif len(link_result) == 0:
        errorstring = "Link expression not supported"
    else:
        errorstring = "More then two expressions"

    #create the expression thestring
    if strbegin and strmin and strmax and strend:
        thestring = strbegin +strmin+";"+strmax + strend
        return (strattr, thestring)
    else:
        return (None,errorstring)

def add_annotationlayer(context, tb_map, mapobj, maplayer):
    """
    add a polygonlayer to thuban
    
    tb_map = context.mainwindow.canvas.Map()
    
    mapobj = the Mapobject created from the mapfile
    
    maplayer = layer obj to add to thuban
    """
    filepath = mapobj.get_mappath()
    layertitle = maplayer.get_name()
    if maplayer.get_data():
        if os.path.isabs(maplayer.get_data()):
            filename = maplayer.get_data() +".shp"
        else:
            filename = os.path.join(filepath, mapobj.get_shapepath(), \
                                           maplayer.get_data())
            filename = filename + ".shp"
        # Normalize the pathname by collapses 
        # redundant separators and up-level references
        filename = os.path.normpath(filename)
    else:
        context.mainwindow.RunMessageBox(_('Error Loading Layer'),
            _("no shp file definied, maybe used a feature obj '%s'.") % layertitle)
    # try to open the layer
    try:
        store = context.application.Session().OpenShapefile(filename)
    except IOError:
        # the layer couldn't be opened
        context.mainwindow.RunMessageBox(_('Open Shapepath'),
                                         _("Can't open the file '%s'.") % filename)
    else:
        # added an annotation layer as empty layer to thuban
        # because thuban don't supports annotation.
        layertitle = maplayer.get_name()
        annotationlayer = AnnotationLayer(layertitle,store)
        # associate a copy of the maplayer object to the layer in thuban.
        annotationlayer.extension_umn_layerobj = maplayer
        tb_map.AddLayer(annotationlayer)
    

def add_rasterlayer(context, tb_map, mapobj, maplayer):
    """
    add a rasterlayer to thuban
    
    tb_map = context.mainwindow.canvas.Map()
    
    mapobj = the Mapobject created from the mapfile
    
    maplayer = layer obj to add to thuban
    """
    imgpath = maplayer.get_data()
    shapepath = mapobj.get_shapepath()
    filepath = mapobj.get_mappath()
    layertitle = maplayer.get_name()
    # if there is no imagepath defined, the Raster Layer could not load
    if imgpath == None:
        context.mainwindow.RunMessageBox(_('Error Loading Raster Layer'),
                                         _("Can't open the rasterlayer '%s'.") % layertitle)
    else:
        if os.path.isabs(imgpath):
            filename = imgpath
        else:
            filename = os.path.join(filepath, shapepath,imgpath) 
        # Normalize the pathname by collapses 
        # redundant separators and up-level references
        filename = os.path.normpath(filename)
        rasterlayer = RasterLayer(layertitle, filename)
        # set the visible status
        rasterlayer.SetVisible(maplayer.get_status())
        #add the projection if exists
        set_projection_to_tb(rasterlayer, maplayer)
        
        # associate a copy of the maplayer object to the layer in thuban.
        rasterlayer.extension_umn_layerobj = maplayer
        tb_map.AddLayer(rasterlayer)


def add_polygonlayer(context, tb_map, mapobj, maplayer):
    """
    add a polygonlayer to thuban
    
    tb_map = context.mainwindow.canvas.Map()
    
    mapobj = the Mapobject created from the mapfile
    
    maplayer = layer obj to add to thuban
    """
    filepath = mapobj.get_mappath()
    layertitle = maplayer.get_name()
    if maplayer.get_data():
        if os.path.isabs(maplayer.get_data()):
            filename = maplayer.get_data() +".shp"
        else:
            filename = os.path.join(filepath, mapobj.get_shapepath(), \
                                           maplayer.get_data())
            filename = filename + ".shp"
        # Normalize the pathname by collapses 
        # redundant separators and up-level references
        filename = os.path.normpath(filename)
    else:
        context.mainwindow.RunMessageBox(_('Error Loading Layer'),
            _("no shp file definied, maybe used a feature obj '%s'.") % layertitle)
    # try to open the layer
    try:
        store = context.application.Session().OpenShapefile(filename)
    except IOError:
        # the layer couldn't be opened
        context.mainwindow.RunMessageBox(_('Open Shapepath'),
                                         _("Can't open the file '%s'.") % filename)
    else:
        # create a new layer which will be added to thuban later
        layer = Layer(layertitle, store)
        # all classes of the maplayer
        map_clazzes = maplayer.get_classes()
        # number of layers loaded vom maplayer
        map_numclazzes = len(map_clazzes)
        # defaultclazzset is necessary to know if a default class is set
        # in thuban. if is not and there are more them one class in the
        # mapfile the colors of the default layer in thuban musst 
        # set to Transparence
        defaultclazzset = None

        # create a class in thuban for every class in the maplayer
        for map_clazznr in range(0, map_numclazzes, 1):
            # define the color
            map_clazz = map_clazzes[map_clazznr]
            layer_style = map_clazz.get_styles()[0]
            clazz_name = map_clazz.get_name()
            clazz = layer.GetClassification()
            prop = ClassGroupProperties()
            # set the layerprojection if given
            # TODO check this, becaus it is not working correctly
            # set_projection_to_tb(layer, maplayer)

            # if outline color is defined use it else set transparent
            if layer_style.get_outlinecolor():
               tb_color = layer_style.get_outlinecolor().get_thubancolor()
               prop.SetLineColor(tb_color)
            else:
                prop.SetLineColor(Transparent)
            # if color is defined use it as fillcolor
            # but if the layer type is line use the color as linecolor
            if layer_style.get_color():
                tb_color = layer_style.get_color().get_thubancolor()
                if maplayer.get_type() == 'line':
                    prop.SetLineColor(tb_color)
                else:
                    prop.SetFill(tb_color)
            else:
                prop.SetFill(Transparent)

            #set size for the line
            if ((maplayer.get_type() == 'polygon') or   
                 (maplayer.get_type() == 'line')):
                if layer_style.get_size():
                    prop.SetLineWidth(layer_style.get_size())
                    
            # generate special expression classes to show in thuban
            # not all possibilities from the MapServer are supported now
            # supporteed:
            #    String comparisons
            # not supported:
            #    Regular expressions
            #    Logical expressions
            expressionstring = map_clazz.get_expressionstring()
            if (((map_numclazzes == 1) & (not expressionstring)) or
               ((map_numclazzes > 1) & (expressionstring == None)) or
               (expressionstring == '/./')):
                if clazz_name == None:
                    clazz_name = ""
                new_group = ClassGroupDefault(props = prop, label = clazz_name)
                new_group.SetVisible(map_clazz.get_status())
                clazz.SetDefaultGroup(new_group)
                defaultclazzset = True
                # break, because alle classes behind the one which definies the
                # default will be ignored by mapserver. See sample
                # TODO: if possible set it as invisible class in thuban, but
                #       show the parts of that class as default.
                #       not possible at the moment ?
                break
                
            # this is the String comparison.
            # the expressionstring is enclosed by the ' or " indications
            elif ((expressionstring[0] == "'") or
                 (expressionstring[0] == '"')):
                expressionclassitem = maplayer.get_classitem().upper()
                layer.SetClassificationColumn(expressionclassitem)
                try:
                    theexpression = int(expressionstring[1:-1])
                except:
                    theexpression = expressionstring[1:-1]
                if clazz_name == None:
                    clazz_name = str("")
                new_group = ClassGroupSingleton(value = theexpression,
                                                props = prop,
                                                label = clazz_name)
                new_group.SetVisible(map_clazz.get_status())
                clazz.AppendGroup(new_group)
            elif (expressionstring[0] == "("): 
                expressionclassitem, thubanexpr \
                              = create_rangeexpression(expressionstring[1:-1])
                if expressionclassitem == None:
                    if clazz_name == None:
                        clazz_showtxt = "Nr. " + str(map_clazznr+1)
                    else:
                        clazz_showtxt = clazz_name
                    context.mainwindow.RunMessageBox(_('Error Loading Expression'), \
                            _("%s \n" + \
                               "Can't load the Expression from layer \n" + \
                               "Layer: %s ; Class: %s\n" + \
                               "Expression: %s")\
                            %(thubanexpr, layer.title, clazz_showtxt, expressionstring[1:-1]) )
                else:
                    layer.SetClassificationColumn(expressionclassitem)
                    if clazz_name == None:
                        clazz_name = str("")
                    expressionrange = Range(thubanexpr)
                    new_group = ClassGroupRange(expressionrange,
                                                props = prop,
                                                label = clazz_name)
                    new_group.SetVisible(map_clazz.get_status())
                    clazz.AppendGroup(new_group)

            else:
                new_group = ClassGroupSingleton(props = prop,label = clazz_name)
                new_group.SetVisible(map_clazz.get_status())
                clazz.AppendGroup(new_group)
        
        # if there is no default layer set,
        # the color and linecolor will set as Transparent.
        if (not defaultclazzset):
            proptp = ClassGroupProperties()
            proptp.SetLineColor(Transparent)
            new_group = ClassGroupDefault(props = proptp)
            clazz.SetDefaultGroup(new_group)
            defaultclazzset = None
        
        # set the visible status
        layer.SetVisible(maplayer.get_status())
        #add the projection if exists
        set_projection_to_tb(layer, maplayer)
        
        # associate a copy of the maplayer object to the layer in thuban.
        layer.extension_umn_layerobj =maplayer
        #add the layer into thuban
        tb_map.AddLayer(layer)


def select_layer2import(context, mapobj):
    """
    shows a dialog to select the layers to import.
    
    mapobj = the Mapobject created from the mapfile
    """
    # Show number of Layer found in file
    numlayers = len(mapobj.get_layers())
    if numlayers == 0:
        context.mainwindow.RunMessageBox(_('Loading Layer'),
                                     _("No Layer found."))
    else:
        context.mainwindow.RunMessageBox(_('Loading Layer'),
                                         _("%s Layer loaded from file.") % numlayers)
    # Show a dialog to select layers to load into thuban only    
    lst = []
    selectedlayer = []
    numlayers = len(mapobj.get_layers())
    for layernr in range(0, numlayers,1):
        lst.append(mapobj.get_layers()[layernr].get_name() +
                  " (" + mapobj.get_layers()[layernr].get_type() +")" )
            
    dlgsize = (300,130+len(lst)*20)
    if dlgsize[1] >= 300:
        dlgsize = (300,300)
    dlg = wxMultipleChoiceDialog(context.mainwindow,
                                 "Select the layers from the\n" +
                                 "list to load into thuban.\n" +
                                 "annotation not supported !",
                                 "Select Layer.", lst, size = dlgsize)
    if (dlg.ShowModal() == wxID_OK):
        selectedlayer = dlg.GetValue()
    return selectedlayer

def import_layer_from_mapfile(context):
    """
    Import only the layers which are selectes from a mapfile
    """
    # open a dialog to select the mapfile to import
    dlg = wxFileDialog(context.mainwindow,
                       _("Select MapFile file"), ".", "",
                       _("UMN MapServer Mapfiles (*.map)|*.map|") +
                       _("All Files (*.*)|*.*"),
                       wxOPEN|wxOVERWRITE_PROMPT)
    if dlg.ShowModal() == wxID_OK:
        filename = dlg.GetPath()
        dlg.Destroy()
    else:
        return

    # Parse mapfile
    mapobj = parse_mapfile(filename)
       
    # Show number of Layer found in file
    numlayers = len(mapobj.get_layers())
    if numlayers == 0:
        context.mainwindow.RunMessageBox(_('Loading Layer'),
                                     _("No Layer found."))
    else:
        context.mainwindow.RunMessageBox(_('Loading Layer'),
                                         _("%s Layer loaded from file.") % numlayers)
    # Show a dialog to select layers to load into thuban only
    # if the mapfile contains any layer
    if numlayers != 0:
        selectedlayer = select_layer2import(context,mapobj)
    else:
        selectedlayer = []

def import_layer_from_mapfile(context):
    """
    import layers from a mapfile
    """
    # open a dialog to select the mapfile to import from
    dlg = wxFileDialog(context.mainwindow,
                       _("Select MapFile file"), ".", "",
                       _("UMN MapServer Mapfiles (*.map)|*.map|") +
                       _("All Files (*.*)|*.*"),
                       wxOPEN|wxOVERWRITE_PROMPT)
    if dlg.ShowModal() == wxID_OK:
        filename = dlg.GetPath()
        dlg.Destroy()
    else:
        return
        
    # Parse mapfile
    mapobj = parse_mapfile(filename)
    oldmapobj = context.mainwindow.canvas.Map().extension_umn_mapobj

    # shows a dialog to select layers to import
    selectedlayer = select_layer2import(context,mapobj)

    # counter to show the numer of layer loaded into Tuban
    layer_count = 0
    # import settings to thuban only if one layer is selected
    if len(selectedlayer) != 0:
        # thuban map context
        tb_map = context.mainwindow.canvas.Map()
        # Check for each Layer if it is possible to show in Thuban
        for layernr in selectedlayer:
            maplayer = mapobj.get_layers()[layernr]
            
            #check if rasterlayer type
            if maplayer.get_type() == 'raster':
                add_rasterlayer(context, tb_map, mapobj, maplayer)
                layer_count += 1
    
            #check if polygonlayer type
            if ((maplayer.get_type() == 'polygon') or   
                 (maplayer.get_type() == 'line') or
                 (maplayer.get_type() == 'circle') or
                 (maplayer.get_type() == 'point')):
                add_polygonlayer(context, tb_map, mapobj, maplayer)
                layer_count += 1
            
            if (maplayer.get_type() == 'annotation'):
                add_annotationlayer(context, tb_map, mapobj, maplayer)

        # show a message how many layer were loaded into thuban
        # if the number of layers is not null
        if layer_count != 0:
            context.mainwindow.RunMessageBox(_('Layer loaded'),
                                             _("%s Layer loaded into Thuban") % layer_count)

def import_mapfile(context):
    """
    Import the mapfile from a file given by the user. After that parse
    the mapfile with the mapscript parser to create all necessary objects.

    Loaded polygon layer like polygon, line or point into thuban.
    Raster layer are supported also.

    context - the thuban context
    """
    # create a new session befor a mapfile is imported
    if context.mainwindow.save_modified_session() != wxID_CANCEL:
        context.application.SetSession(mainwindow.create_empty_session())
        
        # context.mainwindow.NewSession()
        # open a dialog to select the mapfile to import
        dlg = wxFileDialog(context.mainwindow,
                           _("Select MapFile file"), ".", "",
                           _("UMN MapServer Mapfiles (*.map)|*.map|") +
                           _("All Files (*.*)|*.*"),
                           wxOPEN|wxOVERWRITE_PROMPT)
        if dlg.ShowModal() == wxID_OK:
            filename = dlg.GetPath()
            dlg.Destroy()
        else:
            return
        
        # Parse mapfile
        mapobj = parse_mapfile(filename)
    
        # shows a dialog to select layers to import
        selectedlayer = select_layer2import(context,mapobj)
        
        # counter to show the numer of layer loaded into Tuban
        layer_count = 0
        # import settings to thuban only if one layer is selected
        if len(selectedlayer) != 0:
            # thuban map context
            tb_map = context.mainwindow.canvas.Map()
            # set the titel and projection
            tb_map.SetTitle(mapobj.get_name())
            set_projection_to_tb(tb_map,mapobj)

            selectedlayer = list(selectedlayer)
            # remove not selected layer from the mapfile
            incount = 0
            delcount = 0
            newselect = []
            for iii in range(0, len(mapobj.get_layers()), 1):
                if iii in selectedlayer:
                    newselect.append(selectedlayer[incount]-delcount)
                    incount += 1
                else:
                    mapobj.remove_layer(iii-delcount)
                    delcount += 1
            selectedlayer = newselect
           
            # Check for each Layer if it is possible to show in Thuban
            for layernr in selectedlayer:

                maplayer = mapobj.get_layers()[layernr]
                
                #check if rasterlayer type
                if maplayer.get_type() == 'raster':
                    add_rasterlayer(context, tb_map, mapobj, maplayer)
                    layer_count += 1
        
                #check if polygonlayer type
                if ((maplayer.get_type() == 'polygon') or   
                     (maplayer.get_type() == 'line') or
                     (maplayer.get_type() == 'circle') or
                     (maplayer.get_type() == 'point')):
                    add_polygonlayer(context, tb_map, mapobj, maplayer)
                    layer_count += 1
                
                if (maplayer.get_type() == 'annotation'):
                    add_annotationlayer(context, tb_map, mapobj, maplayer)
                    layer_count += 1
    
            # add the map object to thuban, to use it later
            tb_map.extension_umn_mapobj = mapobj
    
            # show a message how many layer were loaded into thuban
            # if the number of layers is not null
            if layer_count != 0:
                # get the extent from the map and set it in thuban
                extentrect = mapobj.get_extent().get_rect()
                # fit the new map extent to the window
                context.mainwindow.canvas.FitRectToWindow(extentrect)
                context.mainwindow.RunMessageBox(_('Layer loaded'),
                                                 _("%s Layer loaded into Thuban") % layer_count)

def parse_mapfile(filename):
    """
    Parse the mapfile.

    Currently this is done using the mapscript module.
    NOTE: It is also possible to use here an own parser
    which could at aleast gain independency from the mapscript
    module.

    filename - the filename of the .map file
    """
    theMap = mapObj(filename)

    return MF_Map(theMap)

# check if an mapobj exists, to control the menuitem is available or not
def _has_umn_mapobj(context):
    return False
    """Return true if a umn_mapobj exists"""
    return hasattr(context.mainwindow.canvas.Map(), "extension_umn_mapobj")

#create a new mapfile
def create_new_mapfile(context):
    theMap = MF_Map(mapObj(""))
    context.mainwindow.canvas.Map().extension_umn_mapobj = theMap

# ###################################
#
# Hook in MapServer Extension into Thuban
#
# ###################################

# find the extensions menu (create it anew if not found)
experimental_menu = main_menu.FindOrInsertMenu("experimental", _("Experimenta&l"))
# find the extension menu and add a new submenu if found
mapserver_menu = experimental_menu.FindOrInsertMenu("mapserver", _("&MapServer"))

# register the new command
registry.Add(Command("create_new_mapfile", _("Create new mapfile"), \
                     create_new_mapfile, \
		           helptext = _("Create a new empty mapscript MapObj")))
# finally add the new entry to the extensions menu
mapserver_menu.InsertItem("create_new_mapfile")

# register the new command
registry.Add(Command("import_mapfile", _("Import mapfile"), import_mapfile,
                     helptext = _("Import a mapfile")))
# finally add the new entry to the extensions menu
mapserver_menu.InsertItem("import_mapfile",  after = "create_new_mapfile" )

# register the new command
registry.Add(Command("import_layer_from_mapfile", _("Import layer from mapfile"), 
                     import_layer_from_mapfile,
                     helptext = _("Import a layer from a mapfile"),
                     sensitive = _has_umn_mapobj))
# finally add the new entry to the extensions menu
mapserver_menu.InsertItem("import_layer_from_mapfile", 
                          after = "import_mapfile" )


