def getDataSource():
    """ Return IDataSource

    TODO: must return actual DataSource
    """
    conn = GS.getData('PGCONN')  # http://initd.org/psycopg/docs/usage.html#thread-safety
#    assert isinstance(conn, postgis.PGConnection)
    if not conn or not isinstance(conn, postgis.PGConnection):
        ini = mfslib.getIniData(APP)
        dsn = ini.get('common', 'PG.DSN')
        conn = postgis.PGConnection(dsn, APP)
        GS.setData('PGCONN', conn)

    return postgis.DataSource(conn.conn)
def mainPage():
    """ List of all MFS servlets, for demo purposes only
    """
    lst = []
    for x in ('mainPage', 'helpPage', 'favicon', 'clientaccesspolicy', 'servicesList', 'layersList'):
        # static pages
        lst.append((url_for(x), ''))

    ini = mfslib.getIniData(APP)
    lyrs = mfslib.getLyrsList(ini)
    for lyrid in lyrs:
        tabname = ini.get(lyrid, 'layer.table')
        fldname = ini.get(lyrid, 'layer.geomfield')
        oidname = ini.get(lyrid, 'layer.oidfield')

        # metadata extraction
        lst.append((url_for('dbTableInfo',
                            table=tabname, geomfield=fldname, oidfield=oidname),
                    'Layer %s DB table info' % lyrid))

        # stored metadata
        lst.append((url_for('layerController', layerid=lyrid), 'Layer %s metadata' % lyrid))

        # layer data query by box
        lst.append((url_for('layerOperations', layerid=lyrid, operation='query',
            geometry='{"xmin":3907314.1268439,"ymin":6927697.68990079,"xmax":3996369.71947852,"ymax":7001516.67745022,"spatialReference":{"wkid":102100}}',
            outSR='102100',
            spatialRel='esriSpatialRelIntersects',
            geometryType='esriGeometryEnvelope',
#             returnGeometry='true',
#             inSR='102100',
#             outFields='*',
#             f='pjson'
        ), 'Layer %s data query by box' % lyrid))

        # layer data query by polygon
        lst.append((url_for('layerOperations', layerid=lyrid, operation='query',
            geometryType='esriGeometryPolygon',
            spatialRel='esriSpatialRelIntersects',
            outSR='102100',
            geometry='{"spatialReference":{"wkid":102100},"rings":[[[-3580921.90110393,-273950.309374072],[-3580921.90110393,15615167.6343221],[20037508.3427892,15615167.6343221],[20037508.3427892,-273950.309374072],[-3580921.90110393,-273950.309374072]],[[-20037508.3427892,-273950.309374072],[-20037508.3427892,15615167.6343221],[-18609053.1581958,15615167.6343221],[-18609053.1581958,-273950.309374072],[-20037508.3427892,-273950.309374072]]]}',
#             returnGeometry='true',
#             inSR='102100',
#             outFields='*',
#             f='pjson'
        ), 'Layer %s data query by polygon' % lyrid))

    return render_template('servlets.html', lst=lst)
def getLayerConfig(lyrid):
    """ Return layermeta.LayerInfo readed from ini file and layer metadata file
    Args:
        lyrid: string, ini section name
    """
    ini = mfslib.getIniData(APP)
    tabname = ini.get(lyrid, 'layer.table')
    geomfield = ini.get(lyrid, 'layer.geomfield')
    oidfield = ini.get(lyrid, 'layer.oidfield')
    res = layermeta.LayerInfo(tabname, geomfield, oidfield)

    stordir = APP.config['DATA_FILES_ROOTDIR']
    text = layermeta.layerMeta(lyrid, stordir)
    res.setAGInfo(text)

    return res
def getLayerConfig(lyrid):
    """ Return layermeta.LayerInfo readed from ini file and layer metadata file
    Args:
        lyrid: string, ini section name
    """
    ini = mfslib.getIniData(APP)
    tabname = ini.get(lyrid, 'layer.table')
    geomfield = ini.get(lyrid, 'layer.geomfield')
    oidfield = ini.get(lyrid, 'layer.oidfield')
    res = layermeta.LayerInfo(tabname, geomfield, oidfield)

    stordir = APP.config['DATA_FILES_ROOTDIR']
    text = layermeta.layerMeta(lyrid, stordir)
    res.setAGInfo(text)

    return res
def layersList():
    """ Layers index page processor.
    Returns JSON text with FeatureServer description, include layers list.

    Spec: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Feature_Service/02r3000000z2000000/
    """
    ini = mfslib.getIniData(APP)
    lyrs = mfslib.getLyrsList(ini)
    layers = []
    for lid in lyrs:
        name = ini.get(lid, 'layer.name')
        layers.append({'id': int(lid), 'name': name})

    stordir = APP.config['DATA_FILES_ROOTDIR']
    text = layermeta.layerMeta(0, stordir, fname='mfs.index.js')
    resp = simplejson.loads(text)

    resp['layers'] = layers
    return makeResponce(resp)
def layersList():
    """ Layers index page processor.
    Returns JSON text with FeatureServer description, include layers list.

    Spec: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Feature_Service/02r3000000z2000000/
    """
    ini = mfslib.getIniData(APP)
    lyrs = mfslib.getLyrsList(ini)
    layers = []
    for lid in lyrs:
        name = ini.get(lid, 'layer.name')
        layers.append({'id': int(lid), 'name': name})

    stordir = APP.config['DATA_FILES_ROOTDIR']
    text = layermeta.layerMeta(0, stordir, fname='mfs.index.js')
    resp = simplejson.loads(text)

    resp['layers'] = layers
    return makeResponce(resp)
def layerOperations(layerid=0, operation=''):
    """ Esri API, process all operations for layer by Layer ID and operation name
    http://resources.arcgis.com/en/help/rest/apiref/fslayer.html
    http://resources.arcgis.com/en/help/rest/apiref/fsquery.html#response

    Known request example
    .../FeatureServer/0/query?returnGeometry=true
        &geometryType=esriGeometryEnvelope
        &geometry={"xmin":-7182265.21424325,"ymin":-1567516.84684806,"xmax":17864620.2142433,"ymax":14321601.0968481,"spatialReference":{"wkid":102100}}
        &inSR=102100
        &spatialRel=esriSpatialRelIntersects
        &outSR=102100
        &outFields=*
        &f=pjson

    f=pjson by default
    """
    res = {}
    ini = mfslib.getIniData(APP)
    lyrs = mfslib.getLyrsList(ini)

    if not (str(layerid) in lyrs and operation == 'query'):
        res = esri.errorObject(
            details=
            u"Unsupported query parameters: layerid not in %s or operation != 'query'"
            % lyrs)
        return makeResponce(res)

    lyrconf = getLayerConfig(str(layerid))
    if not lyrconf.isValid():
        res = esri.errorObject(details=u"Layer config not found.")
        return makeResponce(res)

    ds = getDataSource()

    op = esri.getLyrOperation(operation, request.values)

    try:
        res = layerdata.layerData(lyrconf, ds, op)
    except Exception, e:
        traceback.print_exc(file=sys.stderr)
        res = esri.errorObject(details=u"Data processing error: %s" % e)
def layerOperations(layerid=0, operation=''):
    """ Esri API, process all operations for layer by Layer ID and operation name
    http://resources.arcgis.com/en/help/rest/apiref/fslayer.html
    http://resources.arcgis.com/en/help/rest/apiref/fsquery.html#response

    Known request example
    .../FeatureServer/0/query?returnGeometry=true
        &geometryType=esriGeometryEnvelope
        &geometry={"xmin":-7182265.21424325,"ymin":-1567516.84684806,"xmax":17864620.2142433,"ymax":14321601.0968481,"spatialReference":{"wkid":102100}}
        &inSR=102100
        &spatialRel=esriSpatialRelIntersects
        &outSR=102100
        &outFields=*
        &f=pjson

    f=pjson by default
    """
    res = {}
    ini = mfslib.getIniData(APP)
    lyrs = mfslib.getLyrsList(ini)

    if not (str(layerid) in lyrs and operation == 'query'):
        res = esri.errorObject(
            details=u"Unsupported query parameters: layerid not in %s or operation != 'query'" % lyrs)
        return makeResponce(res)

    lyrconf = getLayerConfig(str(layerid))
    if not lyrconf.isValid():
        res = esri.errorObject(details=u"Layer config not found.")
        return makeResponce(res)

    ds = getDataSource()

    op = esri.getLyrOperation(operation, request.values)

    try:
        res = layerdata.layerData(lyrconf, ds, op)
    except Exception, e:
        traceback.print_exc(file=sys.stderr)
        res = esri.errorObject(details=u"Data processing error: %s" % e)
def layerController(layerid=0):
    """ Esri API, process requests to layer by Layer ID
    http://resources.arcgis.com/en/help/rest/apiref/fslayer.html

    Known requests example
    .../FeatureServer/0?f=pjson

    f=json by default
    """
    # layer metadata .../FeatureServer/0?f=pjson
    ini = mfslib.getIniData(APP)
    lyrs = mfslib.getLyrsList(ini)

    if not (str(layerid) in lyrs):
        resp = esri.errorObject(
            details=u"Invalid query parameters: layerid %s not in %s" % (layerid, lyrs))
        return makeResponce(resp)

    stordir = APP.config['DATA_FILES_ROOTDIR']
    text = layermeta.layerMeta(layerid, stordir)
    resp = make_response(text)
    resp.headers['Content-Type'] = 'text/plain;charset=utf-8'
    return resp
def layerController(layerid=0):
    """ Esri API, process requests to layer by Layer ID
    http://resources.arcgis.com/en/help/rest/apiref/fslayer.html

    Known requests example
    .../FeatureServer/0?f=pjson

    f=json by default
    """
    # layer metadata .../FeatureServer/0?f=pjson
    ini = mfslib.getIniData(APP)
    lyrs = mfslib.getLyrsList(ini)

    if not (str(layerid) in lyrs):
        resp = esri.errorObject(
            details=u"Invalid query parameters: layerid %s not in %s" %
            (layerid, lyrs))
        return makeResponce(resp)

    stordir = APP.config['DATA_FILES_ROOTDIR']
    text = layermeta.layerMeta(layerid, stordir)
    resp = make_response(text)
    resp.headers['Content-Type'] = 'text/plain;charset=utf-8'
    return resp
def mainPage():
    """ List of all MFS servlets, for demo purposes only
    """
    lst = []
    for x in ('mainPage', 'helpPage', 'favicon', 'clientaccesspolicy',
              'servicesList', 'layersList'):
        # static pages
        lst.append((url_for(x), ''))

    ini = mfslib.getIniData(APP)
    lyrs = mfslib.getLyrsList(ini)
    for lyrid in lyrs:
        tabname = ini.get(lyrid, 'layer.table')
        fldname = ini.get(lyrid, 'layer.geomfield')
        oidname = ini.get(lyrid, 'layer.oidfield')

        # metadata extraction
        lst.append(
            (url_for('dbTableInfo',
                     table=tabname,
                     geomfield=fldname,
                     oidfield=oidname), 'Layer %s DB table info' % lyrid))

        # stored metadata
        lst.append((url_for('layerController',
                            layerid=lyrid), 'Layer %s metadata' % lyrid))

        # layer data query by box
        lst.append((
            url_for(
                'layerOperations',
                layerid=lyrid,
                operation='query',
                geometry=
                '{"xmin":3907314.1268439,"ymin":6927697.68990079,"xmax":3996369.71947852,"ymax":7001516.67745022,"spatialReference":{"wkid":102100}}',
                outSR='102100',
                spatialRel='esriSpatialRelIntersects',
                geometryType='esriGeometryEnvelope',
                #             returnGeometry='true',
                #             inSR='102100',
                #             outFields='*',
                #             f='pjson'
            ),
            'Layer %s data query by box' % lyrid))

        # layer data query by polygon
        lst.append((
            url_for(
                'layerOperations',
                layerid=lyrid,
                operation='query',
                geometryType='esriGeometryPolygon',
                spatialRel='esriSpatialRelIntersects',
                outSR='102100',
                geometry=
                '{"spatialReference":{"wkid":102100},"rings":[[[-3580921.90110393,-273950.309374072],[-3580921.90110393,15615167.6343221],[20037508.3427892,15615167.6343221],[20037508.3427892,-273950.309374072],[-3580921.90110393,-273950.309374072]],[[-20037508.3427892,-273950.309374072],[-20037508.3427892,15615167.6343221],[-18609053.1581958,15615167.6343221],[-18609053.1581958,-273950.309374072],[-20037508.3427892,-273950.309374072]]]}',
                #             returnGeometry='true',
                #             inSR='102100',
                #             outFields='*',
                #             f='pjson'
            ),
            'Layer %s data query by polygon' % lyrid))

    return render_template('servlets.html', lst=lst)