From 261b801347fe01bb3520ba1dad713fc9f3039486 Mon Sep 17 00:00:00 2001
From: Jorrit Schaap <schaap@astron.nl>
Date: Wed, 17 Aug 2016 07:53:28 +0000
Subject: [PATCH] Task #9607: added queries to get predecessor and successor
 ids for a given mom2id

---
 SAS/MoM/MoMQueryService/momqueryrpc.py     |  30 ++++++
 SAS/MoM/MoMQueryService/momqueryservice.py | 112 +++++++++++++++++----
 2 files changed, 122 insertions(+), 20 deletions(-)

diff --git a/SAS/MoM/MoMQueryService/momqueryrpc.py b/SAS/MoM/MoMQueryService/momqueryrpc.py
index b9a9548f8d6..c611638755b 100644
--- a/SAS/MoM/MoMQueryService/momqueryrpc.py
+++ b/SAS/MoM/MoMQueryService/momqueryrpc.py
@@ -38,6 +38,18 @@ class MoMQueryRPC(RPCWrapper):
         logger.info("Received %s projects" % (len(projects)))
         return projects
 
+    def getPredecessorIds(self, ids):
+        logger.debug("getSuccessorIds(%s)", ids)
+        result = self.rpc('GetPredecessorIds', mom_ids=ids)
+        logger.info("GetPredecessorIds(%s): %s", ids, result)
+        return result
+
+    def getSuccessorIds(self, ids):
+        logger.debug("getSuccessorIds(%s)", ids)
+        result = self.rpc('GetSuccessorIds', mom_ids=ids)
+        logger.info("getSuccessorIds(%s): %s", ids, result)
+        return result
+
 
 def main():
     # Check the invocation arguments
@@ -49,6 +61,8 @@ def main():
     parser.add_option('-V', '--verbose', dest='verbose', action='store_true', help='verbose logging')
     parser.add_option('-P', '--projects', dest='projects', action='store_true', help='get list of all projects')
     parser.add_option('-p', '--project_details', dest='project_details', type='int', help='get project details for mom object with given id')
+    parser.add_option('--predecessors', dest='id_for_predecessors', type='int', help='get the predecessor id\'s for the given mom2id')
+    parser.add_option('--successors', dest='id_for_successors', type='int', help='get the successors id\'s for the given mom2id')
     (options, args) = parser.parse_args()
 
     if len(sys.argv) == 1:
@@ -71,5 +85,21 @@ def main():
             else:
                 print 'No results'
 
+        if options.id_for_predecessors:
+            predecessor_ids = rpc.getPredecessorIds(options.id_for_predecessors)
+            if predecessor_ids:
+                for k, v in predecessor_ids.items():
+                    print '  %s: %s' % (k, v)
+            else:
+                print 'No results'
+
+        if options.id_for_successors:
+            successor_ids = rpc.getSuccessorIds(options.id_for_successors)
+            if successor_ids:
+                for k, v in successor_ids.items():
+                    print '  %s: %s' % (k, v)
+            else:
+                print 'No results'
+
 if __name__ == '__main__':
     main()
diff --git a/SAS/MoM/MoMQueryService/momqueryservice.py b/SAS/MoM/MoMQueryService/momqueryservice.py
index af8fdb6b26e..d285fca3846 100755
--- a/SAS/MoM/MoMQueryService/momqueryservice.py
+++ b/SAS/MoM/MoMQueryService/momqueryservice.py
@@ -55,6 +55,20 @@ def _isListOfInts(items):
 
     return True
 
+def _toIdsString(mom_ids):
+    if isinstance(mom_ids, int):
+        ids = [mom_ids]
+    elif _isListOfInts(mom_ids):
+        ids = mom_ids
+    else:
+        ids = _idsFromString(mom_ids)
+
+    if not ids:
+        raise ValueError("Could not find proper ids in: " + mom_ids)
+
+    ids_str = ','.join([str(id) for id in ids])
+    return ids_str
+
 class MoMDatabaseWrapper:
     '''handler class for details query in mom db'''
     def __init__(self, dbcreds):
@@ -99,18 +113,9 @@ class MoMDatabaseWrapper:
         if not mom_ids:
             return {}
 
-        if _isListOfInts(mom_ids):
-            ids = mom_ids
-        else:
-            ids = _idsFromString(mom_ids)
-
-        if not ids:
-            raise ValueError("Could not find proper ids in: " + mom_ids)
-
-        ids_str = ','.join([str(id) for id in ids])
+        ids_str = _toIdsString(mom_ids)
 
-        logger.info("Query for mom id%s: %s" %
-                    ('\'s' if len(ids) > 1 else '', ids_str))
+        logger.info("getProjectDetails for mom ids: %s" % ids_str)
 
         # TODO: make a view for this query in momdb!
         query = '''SELECT project.mom2id as project_mom2id, project.id as project_mom2objectid, project.name as project_name, project.description as project_description,
@@ -160,6 +165,70 @@ class MoMDatabaseWrapper:
 
         return result
 
+    def getPredecessorIds(self, mom_ids):
+        if not mom_ids:
+            return {}
+
+        ids_str = _toIdsString(mom_ids)
+
+        logger.info("getPredecessorIds for mom ids: %s" % ids_str)
+
+        query = '''SELECT mom2id, predecessor
+        FROM mom2object
+        where mom2id in (%s)
+        order by mom2id;
+        ''' % (ids_str,)
+        rows = self._executeQuery(query)
+
+        result = {}
+        for row in rows:
+            mom2id = row['mom2id']
+            pred_string = row['predecessor']
+            pred_id_list = [y[1:] for y in [x.strip() for x in pred_string.split(',')] if y[0] == 'M']
+            pred_id_list = [int(x) for x in pred_id_list if x.isdigit()]
+            result[str(mom2id)] = pred_id_list
+
+        for mom2id in ids_str.split(','):
+            if not mom2id in result:
+                result[mom2id] = []
+
+        logger.info('predecessors: %s', result)
+
+        return result
+
+    def getSuccessorIds(self, mom_ids):
+        if not mom_ids:
+            return {}
+
+        ids_str = _toIdsString(mom_ids)
+
+        logger.info("getSuccessorIds for mom ids: %s" % ids_str)
+
+        condition = ' OR '.join(['predecessor LIKE \'%%M%s%%\'' % x for x in ids_str.split(',')])
+
+        # TODO: make a view for this query in momdb!
+        query = '''SELECT mom2id, predecessor
+        FROM mom2object
+        where %s
+        order by mom2id;
+        ''' % (condition,)
+        rows = self._executeQuery(query)
+
+        result = {}
+        for mom2id in ids_str.split(','):
+            result[mom2id] = []
+
+        for row in rows:
+            suc_mom2id = row['mom2id']
+            pred_string = row['predecessor']
+            pred_id_list = [y[1:] for y in [x.strip() for x in pred_string.split(',')] if y[0] == 'M']
+            for mom2id in ids_str.split(','):
+                if mom2id in pred_id_list:
+                    result[str(mom2id)].append(suc_mom2id)
+
+        logger.info('successors: %s', result)
+
+        return result
 
 class ProjectDetailsQueryHandler(MessageHandlerInterface):
     '''handler class for details query in mom db
@@ -171,24 +240,27 @@ class ProjectDetailsQueryHandler(MessageHandlerInterface):
 
         self.service2MethodMap = {
             'GetProjects': self.getProjects,
-            'GetProjectDetails': self.getProjectDetails
+            'GetProjectDetails': self.getProjectDetails,
+            'GetPredecessorIds': self.getPredecessorIds,
+            'GetSuccessorIds': self.getSuccessorIds
             }
 
     def prepare_loop(self):
         self.momdb = MoMDatabaseWrapper(self.dbcreds)
 
     def getProjectDetails(self, mom_ids):
-        if not mom_ids:
-            return {}
-        
-        ids = _idsFromString(mom_ids)
-        if not _isListOfInts(ids):
-            raise ValueError("%s is not a proper list of ints" % str(mom_ids))
-        return self.momdb.getProjectDetails(ids)
+        return self.momdb.getProjectDetails(mom_ids)
 
     def getProjects(self):
         return self.momdb.getProjects()
 
+    def getPredecessorIds(self, mom_ids):
+        return self.momdb.getPredecessorIds(mom_ids)
+
+    def getSuccessorIds(self, mom_ids):
+        return self.momdb.getSuccessorIds(mom_ids)
+
+
 def createService(busname=DEFAULT_MOMQUERY_BUSNAME,
                   servicename=DEFAULT_MOMQUERY_SERVICENAME,
                   dbcreds=None,
@@ -207,7 +279,7 @@ def createService(busname=DEFAULT_MOMQUERY_BUSNAME,
     return Service(servicename,
                    handler,
                    busname=busname,
-                   numthreads=2,
+                   numthreads=1,
                    use_service_methods=True,
                    verbose=False,
                    broker=broker,
-- 
GitLab