view RestDbJsonStore.py @ 51:17dcf148beb3

more JSON store
author casties
date Thu, 09 Sep 2010 10:01:16 +0200
parents 29c822d15bc1
children 435d6664ed90
line wrap: on
line source

'''
Created on 2.9.2010

@author: casties
'''

from OFS.Folder import Folder
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
import logging
import re
import psycopg2
import json
import time

from zope.interface import implements
from zope.publisher.interfaces import IPublishTraverse
from ZPublisher.BaseRequest import DefaultPublishTraverse
import Shared.DC.ZRDB.DA
from Products.ZSQLMethods.SQL import SQLConnectionIDs

from RestDbInterface import *


class RestDbJsonStore(RestDbInterface):
    """Object for RESTful access to JSON objects
    path schema: /db/{schema}/{table}/{tag}/{type}/{item}
    """
    implements(IPublishTraverse)
    
    meta_type="RESTjson"
    manage_options=Folder.manage_options+(
        {'label':'Config','action':'manage_editRestDbJsonStoreForm'},
        )

    # management templates
    manage_editRestDbJsonStoreForm=PageTemplateFile('zpt/editRestDbJsonStore',globals())

    # JSON_* templates are scripts
    def JSON_index(self,data):
        """JSON index function"""
        self.REQUEST.RESPONSE.setHeader("Content-Type", "application/json")
        json.dump(data, self.REQUEST.RESPONSE)        

    
    def __init__(self, id, title, connection_id=None):
        """init"""
        self.id = id
        self.title = title
        # database connection id
        self.connection_id = connection_id

    def getJsonString(self,object):
        """returns a JSON formatted string from object"""
        return json.dumps(object)


    def publishTraverse(self,request,name):
        """change the traversal"""
        # get stored path
        path = request.get('restdb_path', [])
        logging.debug("publishtraverse: name=%s restdb_path=%s"%(name,path))
        
        if name in ("index_html", "PUT"):
            # end of traversal
            if request.get("method") == "POST" and request.get("action",None) == "PUT":
                # fake PUT by POST with action=PUT
                name = "PUT"
                
            return getattr(self, name)
            #TODO: should we check more?
        else:
            # traverse
            if len(path) == 0:
                # first segment
                if name == 'db':
                    # virtual path -- continue traversing
                    path = [name]
                    request['restdb_path'] = path
                else:
                    # try real path
                    tr = DefaultPublishTraverse(self, request)
                    ob = tr.publishTraverse(request, name)
                    return ob
            else:
                path.append(name)

        # continue traversing
        return self
 
    def index_html(self,REQUEST,RESPONSE):
        """index method"""
        # ReST path was stored in request
        path = REQUEST.get('restdb_path',[])
        
        # type and format are real parameter
        resultFormat = REQUEST.get('format','HTML').upper()
        queryType = REQUEST.get('type',None)
        
        logging.debug("index_html path=%s resultFormat=%s queryType=%s"%(path,resultFormat,queryType))

        if queryType is not None:
            # non-empty queryType -- look for template
            pt = getattr(self.template, "%s_%s"%(resultFormat,queryType), None)
            if pt is not None:
                return pt(format=resultFormat,type=queryType,path=path)
            
        if len(path) == 3:
            # list of tags
            return self.showListOfTags(resultFormat=resultFormat,schema=path[1],table=path[2])
        elif len(path) == 4:
            # list of types
            return self.showListOfTypes(resultFormat=resultFormat,schema=path[1],table=path[2],tag=path[3])
        elif len(path) == 5:
            # list of types
            return self.showListOfItems(resultFormat=resultFormat,schema=path[1],table=path[2],tag=path[3],type=path[4])
        elif len(path) == 6:
            # show item
            return self.showItem(resultFormat=resultFormat,schema=path[1],table=path[2],tag=path[3],type=path[4],item=path[5])
        
        # don't know what to do
        return str(REQUEST)

    def PUT(self, REQUEST, RESPONSE):
        """
        Implement WebDAV/HTTP PUT/FTP put method for this object.
        """
        path = REQUEST.get('restdb_path',[])
        logging.debug("RestDbInterface PUT (path=%s)"%repr(path))
        #logging.debug("req=%s"%REQUEST)
        #self.dav__init(REQUEST, RESPONSE)
        #self.dav__simpleifhandler(REQUEST, RESPONSE)
        # ReST path was stored in request
        if len(path) == 3:
            schema = path[1]
            tablename = path[2]
            file = REQUEST.get("create_table_file",None)
            if file is None:
                RESPONSE.setStatus(400)
                return

            fields = None
            fieldsStr = REQUEST.get("create_table_fields",None)
            logging.debug("put with schema=%s table=%s file=%s fields=%s"%(schema,tablename,file,repr(fieldsStr)))
            if fieldsStr is not None:
                # unpack fields
                fields = [{"name":n, "type": t} for (n,t) in [f.split(":") for f in fieldsStr.split(",")]]
                
            ret = self.createTableFromXML(schema, tablename, file, fields)
            # return the result as JSON
            format = REQUEST.get("format","JSON")
            if format == "JSON":
                RESPONSE.setHeader("Content-Type", "application/json")
                json.dump(ret, RESPONSE)
                
            elif format == "JSONHTML":
                RESPONSE.setHeader("Content-Type", "text/html")
                RESPONSE.write("<html>\n<body>\n<pre>")
                json.dump(ret, RESPONSE)
                RESPONSE.write("</pre>\n</body>\n</html>")
            
        else:
            # 400 Bad Request
            RESPONSE.setStatus(400)
            return
    
    def showListOfTags(self,resultFormat,schema,table):
        """returns the list of existing tags"""
        tags = self.getListOfTags(schema, table)
        if resultFormat == 'JSON':
            self.REQUEST.RESPONSE.setHeader("Content-Type", "application/json")
            json.dump(tags, self.REQUEST.RESPONSE)        
        else:
            json.dump(tags, self.REQUEST.RESPONSE)        
        
    def getListOfTags(self,schema,table):
        """returns the list of existing tags"""
        logging.debug("getlistoftags schema=%s table=%s"%(schema,table))
        sql = 'select distinct json_tag from "%s"."%s"'%(schema,table)
        res = self.executeSQL(sql)
        if len(res['rows']) > 0:
            tags = [r[0] for r in res['rows']]
            return tags
        
        return []
    
    def showListOfTypes(self,resultFormat,schema,table,tag):
        """returns the list of existing types"""
        types = self.getListOfTypes(schema, table,tag)
        if resultFormat == 'JSON':
            self.REQUEST.RESPONSE.setHeader("Content-Type", "application/json")
            json.dump(types, self.REQUEST.RESPONSE)        
        else:
            json.dump(types, self.REQUEST.RESPONSE)        
        
    def getListOfTypes(self,schema,table,tag):
        """returns the list of existing tags"""
        logging.debug("getlistoftypes schema=%s table=%s tag=%s"%(schema,table,tag))
        sql = 'select distinct json_type from "%s"."%s" where json_tag = %%s'%(schema,table)
        res = self.executeSQL(sql,(tag,))
        if len(res['rows']) > 0:
            tags = [r[0] for r in res['rows']]
            return tags
        
        return []
    
    def showListOfItems(self,resultFormat,schema,table,tag,type):
        """returns the list of existing items"""
        items = self.getListOfItems(schema, table, tag, type)
        if resultFormat == 'JSON':
            self.REQUEST.RESPONSE.setHeader("Content-Type", "application/json")
            json.dump(items, self.REQUEST.RESPONSE)        
        else:
            json.dump(items, self.REQUEST.RESPONSE)        
        
    def getListOfItems(self,schema,table,tag,type):
        """returns the list of existing tags"""
        logging.debug("getlistofitems schema=%s table=%s tag=%s type=%s"%(schema,table,tag,type))
        sql = 'select distinct json_item from "%s"."%s" where json_tag = %%s and json_type = %%s'%(schema,table)
        res = self.executeSQL(sql,(tag,type))
        if len(res['rows']) > 0:
            items = [r[0] for r in res['rows']]
            return items
        
        return []
    
    def showItem(self,resultFormat,schema,table,tag,type,item):
        """returns the item"""
        item = self.getItem(schema, table, tag, type, item)
        if resultFormat == 'JSON':
            self.REQUEST.RESPONSE.setHeader("Content-Type", "application/json")
            json.dump(item, self.REQUEST.RESPONSE)        
        else:
            json.dump(item, self.REQUEST.RESPONSE)        
        
    def getItem(self,schema,table,tag,type,item):
        """returns the list of existing tags"""
        logging.debug("getitem schema=%s table=%s tag=%s type=%s item=%s"%(schema,table,tag,type,item))
        sql = 'select json_value from "%s"."%s" where json_tag = %%s and json_type = %%s and json_item = %%s'%(schema,table)
        res = self.executeSQL(sql,(tag,type,item))
        if len(res['rows']) > 0:
            # just one item
            item = res['rows'][0][0]
            return item
        
        return {}
    
manage_addRestDbJsonStoreForm=PageTemplateFile('zpt/addRestDbJsonStore',globals())

def manage_addRestDbJsonStore(self, id, title='', label='', description='',
                     createPublic=0,
                     createUserF=0,
                     REQUEST=None):
        """Add a new object with id *id*."""
    
        ob=RestDbJsonStore(str(id),title)
        self._setObject(id, ob)
        
        #checkPermission=getSecurityManager().checkPermission
        REQUEST.RESPONSE.redirect('manage_main')