'Import L1 Admin Boundaries into the Locations table from GADMv1
- designed to be called from import_admin_areas()
- assumes a fresh database with just Countries imported
@param ogr - The OGR Python module
@param level - "L1" or "L2"
@param countries - List of ISO2 countrycodes to download data for
defaults to all countries'

def import_gadm1(self, ogr, level='L1', countries=[]):

    if (level == 'L1'):
        layer = {'url': 'http://gadm.org/data/gadm_v1_lev1_shp.zip', 'zipfile': 'gadm_v1_lev1_shp.zip', 'shapefile': 'gadm1_lev1', 'namefield': 'NAME_1', 'sourceCodeField': 'ID_1', 'edenCodeField': 'GADM1', 'parent': 'L0', 'parentSourceCodeField': 'ISO', 'parentEdenCodeField': 'ISO3'}
    elif (level == 'L2'):
        layer = {'url': 'http://biogeo.ucdavis.edu/data/gadm/gadm_v1_lev2_shp.zip', 'zipfile': 'gadm_v1_lev2_shp.zip', 'shapefile': 'gadm_v1_lev2', 'namefield': 'NAME_2', 'sourceCodeField': 'ID_2', 'edenCodeField': 'GADM2', 'parent': 'L1', 'parentSourceCodeField': 'ID_1', 'parentEdenCodeField': 'GADM1'}
    else:
        current.log.warning(('Level    %s    not    supported!' % level))
        return
    import csv
    import shutil
    import zipfile
    db = current.db
    s3db = current.s3db
    cache = s3db.cache
    table = s3db.gis_location
    ttable = s3db.gis_location_tag
    csv.field_size_limit(((2 ** 20) * 100))
    ENCODING = 'cp1251'
    def latin_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
        for row in csv.reader(unicode_csv_data):
            (yield [unicode(cell, ENCODING) for cell in row])
    def latin_dict_reader(data, dialect=csv.excel, **kwargs):
        reader = latin_csv_reader(data, dialect=dialect, **kwargs)
        headers = reader.next()
        for r in reader:
            (yield dict(zip(headers, r)))
    cwd = os.getcwd()
    TEMP = os.path.join(cwd, 'temp')
    if (not os.path.exists(TEMP)):
        import tempfile
        TEMP = tempfile.gettempdir()
    tempPath = os.path.join(TEMP, 'GADMv1')
    if (not os.path.exists(tempPath)):
        try:
            os.mkdir(tempPath)
        except OSError:
            current.log.error(('Unable    to    create    temp    folder    %s!' % tempPath))
            return
    os.chdir(tempPath)
    try:
        shutil.rmtree('CSV')
    except OSError:
        pass
    layerName = layer['shapefile']
    fileName = layer['zipfile']
    if (not os.path.isfile(fileName)):
        from gluon.tools import fetch
        url = layer['url']
        current.log.debug(('Downloading    %s' % url))
        try:
            file = fetch(url)
        except urllib2.URLError as exception:
            current.log.error(exception)
            os.chdir(cwd)
            return
        fp = StringIO(file)
    else:
        current.log.debug(('Using    existing    file    %s' % fileName))
        fp = open(fileName)
    current.log.debug(('Unzipping    %s' % layerName))
    myfile = zipfile.ZipFile(fp)
    for ext in ('dbf', 'prj', 'sbn', 'sbx', 'shp', 'shx'):
        fileName = ('%s.%s' % (layerName, ext))
        file = myfile.read(fileName)
        f = open(fileName, 'w')
        f.write(file)
        f.close()
    myfile.close()
    current.log.debug(('Converting    %s.shp    to    CSV' % layerName))
    bSkipFailures = False
    nGroupTransactions = 200
    nFIDToFetch = ogr.NullFID
    inputFileName = ('%s.shp' % layerName)
    inputDS = ogr.Open(inputFileName, False)
    outputFileName = 'CSV'
    outputDriver = ogr.GetDriverByName('CSV')
    outputDS = outputDriver.CreateDataSource(outputFileName, options=[])
    inputLayer = inputDS.GetLayer(0)
    inputFDefn = inputLayer.GetLayerDefn()
    outputLayer = outputDS.CreateLayer(layerName)
    inputFieldCount = inputFDefn.GetFieldCount()
    panMap = [(-1) for i in range(inputFieldCount)]
    outputFDefn = outputLayer.GetLayerDefn()
    nDstFieldCount = 0
    if (outputFDefn is not None):
        nDstFieldCount = outputFDefn.GetFieldCount()
    for iField in range(inputFieldCount):
        inputFieldDefn = inputFDefn.GetFieldDefn(iField)
        oFieldDefn = ogr.FieldDefn(inputFieldDefn.GetNameRef(), inputFieldDefn.GetType())
        oFieldDefn.SetWidth(inputFieldDefn.GetWidth())
        oFieldDefn.SetPrecision(inputFieldDefn.GetPrecision())
        iDstField = (-1)
        if (outputFDefn is not None):
            iDstField = outputFDefn.GetFieldIndex(oFieldDefn.GetNameRef())
        if (iDstField >= 0):
            panMap[iField] = iDstField
        elif (outputLayer.CreateField(oFieldDefn) == 0):
            if (outputFDefn is None):
                outputFDefn = outputLayer.GetLayerDefn()
            panMap[iField] = nDstFieldCount
            nDstFieldCount = (nDstFieldCount + 1)
    nFeaturesInTransaction = 0
    inputLayer.ResetReading()
    if (nGroupTransactions > 0):
        outputLayer.StartTransaction()
    while True:
        poDstFeature = None
        if (nFIDToFetch != ogr.NullFID):
            if (nFeaturesInTransaction == 0):
                poFeature = inputLayer.GetFeature(nFIDToFetch)
            else:
                poFeature = None
        else:
            poFeature = inputLayer.GetNextFeature()
        if (poFeature is None):
            break
        nParts = 0
        nIters = 1
        for iPart in range(nIters):
            nFeaturesInTransaction = (nFeaturesInTransaction + 1)
            if (nFeaturesInTransaction == nGroupTransactions):
                outputLayer.CommitTransaction()
                outputLayer.StartTransaction()
                nFeaturesInTransaction = 0
            poDstFeature = ogr.Feature(outputLayer.GetLayerDefn())
            if (poDstFeature.SetFromWithMap(poFeature, 1, panMap) != 0):
                if (nGroupTransactions > 0):
                    outputLayer.CommitTransaction()
                current.log.error(('Unable    to    translate    feature    %d    from    layer    %s' % (poFeature.GetFID(), inputFDefn.GetName())))
                os.chdir(cwd)
                return
            poDstGeometry = poDstFeature.GetGeometryRef()
            if (poDstGeometry is not None):
                if (nParts > 0):
                    poPart = poDstGeometry.GetGeometryRef(iPart).Clone()
                    poDstFeature.SetGeometryDirectly(poPart)
                    poDstGeometry = poPart
            if ((outputLayer.CreateFeature(poDstFeature) != 0) and (not bSkipFailures)):
                if (nGroupTransactions > 0):
                    outputLayer.RollbackTransaction()
                os.chdir(cwd)
                return
    if (nGroupTransactions > 0):
        outputLayer.CommitTransaction()
    outputDS.Destroy()
    inputDS.Destroy()
    fileName = ('%s.csv' % layerName)
    filePath = os.path.join('CSV', fileName)
    os.rename(filePath, fileName)
    os.removedirs('CSV')
    current.log.debug(('Opening    %s.shp' % layerName))
    ds = ogr.Open(('%s.shp' % layerName))
    if (ds is None):
        current.log.debug('Open    failed.\n')
        os.chdir(cwd)
        return
    lyr = ds.GetLayerByName(layerName)
    lyr.ResetReading()
    current.log.debug(('Opening    %s.csv' % layerName))
    rows = latin_dict_reader(open(('%s.csv' % layerName)))
    nameField = layer['namefield']
    sourceCodeField = layer['sourceCodeField']
    edenCodeField = layer['edenCodeField']
    parentSourceCodeField = layer['parentSourceCodeField']
    parentLevel = layer['parent']
    parentEdenCodeField = layer['parentEdenCodeField']
    parentCodeQuery = (ttable.tag == parentEdenCodeField)
    count = 0
    for row in rows:
        feat = lyr[count]
        parentCode = feat.GetField(parentSourceCodeField)
        query = (((table.level == parentLevel) & parentCodeQuery) & (ttable.value == parentCode))
        parent = db(query).select(table.id, ttable.value, limitby=(0, 1), cache=cache).first()
        if (not parent):
            current.log.warning(('Skipping    -    cannot    find    parent    with    key:    %s,    value:    %s' % (parentEdenCodeField, parentCode)))
            count += 1
            continue
        if countries:
            if (level == 'L1'):
                if (parent['gis_location_tag'].value not in countries):
                    count += 1
                    continue
            else:
                country = self.get_parent_country(parent.id, key_type='code')
                if (country not in countries):
                    count += 1
                    continue
        name = row.pop(nameField)
        name.encode('utf8')
        code = feat.GetField(sourceCodeField)
        geom = feat.GetGeometryRef()
        if (geom is not None):
            if (geom.GetGeometryType() == ogr.wkbPoint):
                lat = geom.GetX()
                lon = geom.GetY()
                id = table.insert(name=name, level=level, gis_feature_type=1, lat=lat, lon=lon, parent=parent.id)
                ttable.insert(location_id=id, tag=edenCodeField, value=code)
            else:
                wkt = geom.ExportToWkt()
                if wkt.startswith('LINESTRING'):
                    gis_feature_type = 2
                elif wkt.startswith('POLYGON'):
                    gis_feature_type = 3
                elif wkt.startswith('MULTIPOINT'):
                    gis_feature_type = 4
                elif wkt.startswith('MULTILINESTRING'):
                    gis_feature_type = 5
                elif wkt.startswith('MULTIPOLYGON'):
                    gis_feature_type = 6
                elif wkt.startswith('GEOMETRYCOLLECTION'):
                    gis_feature_type = 7
                id = table.insert(name=name, level=level, gis_feature_type=gis_feature_type, wkt=wkt, parent=parent.id)
                ttable.insert(location_id=id, tag=edenCodeField, value=code)
        else:
            current.log.debug('No    geometry\n')
        count += 1
    ds.Destroy()
    db.commit()
    current.log.debug('Updating    Location    Tree...')
    try:
        self.update_location_tree()
    except MemoryError:
        current.log.critical('Memory    error    when    trying    to    update_location_tree()!')
    db.commit()
    os.chdir(cwd)
    return
