#!/usr/bin/env python # -*- coding: utf-8 -*- import sys, urllib, copy, re from astropy.io.votable import parse_single_table from numpy.core.records import record class Iterator: def __init__(self, filepath, mapper): self.filepath = filepath self.master_mapper = mapper self.master_data = mapper.get_data() self.listed_columns = None self.collection_names = [] self.foreign_mappers = self.master_mapper.foreign_mappers self.foreign_data = {} for k,v in self.foreign_mappers.items(): self.foreign_data[k] = v.get_data() self.ptr = 0 self.size = len(self.master_data) def hasNext(self): if self.ptr == 0 and self.size == 0: return True if self.ptr >= self.size: return False else: return True def set_listed_columns(self,listed_columns): self.listed_columns = [] if listed_columns and len(listed_columns) > 0: for lck in listed_columns: for key, value in self.master_mapper.value_map.items(): if (value.table_id == self.master_mapper.master_table_id or value.table_id == "globals") and key == lck: self.listed_columns.append(lck) else: multiplicity = value.multiplicity if multiplicity != None and not any(c["name"] == multiplicity for c in self.collection_names): self.collection_names.appends({"name": multiplicity, "target_table": value.table_id}) else: array_data_open = False array_data = [] old_multiplicity = None for key, value in self.master_mapper.value_map.items(): multiplicity = value.multiplicity ''' Values without field descriptor or without index are considered as static values. They cannot be listed as column values ''' if value.field_descriptor == None or value.field_descriptor.index == None: continue if key.startswith("#") == False : if multiplicity == None: if array_data_open == True: array_data_open = False self.listed_columns.append(array_data) old_multiplicity = None self.listed_columns.append(key) else: if array_data_open == False: array_data_open = True array_data = [] old_multiplicity = multiplicity ''' We can have a set of vector columns but referering to different objects (T1, V1, t2,V2...) ''' elif multiplicity != old_multiplicity: self.listed_columns.append(array_data) array_data = [] old_multiplicity = multiplicity array_data.append(key) else: #if multiplicity != None and multiplicity not in self.collection_names: if multiplicity != None and not any(c["name"] == multiplicity for c in self.collection_names): self.collection_names.append({"name": multiplicity, "target_table": value.table_id}) if array_data_open == True: self.listed_columns.append(array_data) def get_listed_columns(self): retour = {} joined_columns = [] retour["primary"] = copy.copy(self.listed_columns) for tref, foreign_mapper in self.foreign_mappers.items(): if self.master_mapper.primary_key != None : for key, value in foreign_mapper.value_map.items(): if value.table_id == foreign_mapper.master_table_id: if key.startswith("#") == False: joined_columns.append(key) for coll in (c for c in self.collection_names if c["target_table"] == tref): retour[coll["name"]] = joined_columns return retour def is_in_listed_colums(self, key): for lc in self.listed_columns: if isinstance(lc, list) : return (key in lc) else: if key == lc: return True return False def get_static_values(self): if self.size != 0: self.master_mapper.read_row(self.master_data[self.ptr]) if self.listed_columns == None: self.set_listed_columns(None) retour = {} for key, value in self.master_mapper.value_map.items(): if key.startswith("#") == False and key not in self.listed_columns: if (value.table_id == self.master_mapper.master_table_id or value.table_id == "globals") : retour[key] = self.master_mapper.get_field_value_from_key(key) for foreign_mapper in self.foreign_mappers.values(): for key, value in foreign_mapper.value_map.items(): if key.startswith("#") == False and self.is_in_listed_colums(key) == False: if (value.table_id == foreign_mapper.master_table_id or value.table_id == "globals") : retour[key] = foreign_mapper.get_field_value_from_key(key) self.rewind() return retour def extract_joined_data(self, foreign_mapper, foreign_data, joined_data_map_entry, array_mode): if self.master_mapper.primary_key != None : pkv = self.master_mapper.get_field_value_from_descriptor(self.master_mapper.primary_key) for e in self.foreign_data.keys(): #table_data = self.foreign_data[e] for i in range(len(foreign_data)): data_raw = foreign_data[i] foreign_mapper.read_row(data_raw) fkv = foreign_mapper.get_field_value_from_descriptor(self.master_mapper.foreign_key) if pkv == fkv : if array_mode == True: record = [] else: record = {} for key, value in foreign_mapper.value_map.items(): if value.table_id == foreign_mapper.master_table_id: if key.startswith("#") == False: if array_mode == True: record.append(foreign_mapper.get_field_value_from_key(key)) else: record[key] = foreign_mapper.get_field_value_from_key(key) joined_data_map_entry.append(record) def extract_implicit_joined_data(self, key, foreign_mapper, foreign_data, joined_data_map_entry, array_mode): for i in range(len(foreign_data)): foreign_mapper.read_row(foreign_data[i]) if array_mode == True: record = [] else: record = {} for akey in key: if array_mode == True: record.append(foreign_mapper.get_field_value_from_key(akey)) else: record[akey] = foreign_mapper.get_field_value_from_key(akey) joined_data_map_entry.append(record) def get_foreignmapper_id_hosting_key(self, key): for foreign_table_key in self.foreign_mappers.keys(): if key in self.foreign_mappers[foreign_table_key].value_map.keys(): return foreign_table_key return None def get_row_data(self, primary_data, joined_data, array_mode=False): for key in self.listed_columns: if isinstance(key, list) : value = None foreign_data = None foreign_mapper = None joined_data_map = None table_joined_mode = False for akey in key: value = self.master_mapper.value_map[akey] table = value.table_id """ Look for the table containing the key """ table =self.get_foreignmapper_id_hosting_key(akey) if table == None: primary_data[akey] = self.master_mapper.get_field_value_from_key(akey) else: #if table in self.foreign_mappers.keys(): foreign_mapper = self.foreign_mappers[table] foreign_data = self.foreign_data[table] if array_mode == True: joined_data_map = joined_data else: self.get_dataobject_dict(foreign_mapper, foreign_data, array_mode, joined_data, value.multiplicity) #joined_data[value.multiplicity] = foreign_data joined_data_map = joined_data[value.multiplicity] if self.master_mapper.primary_key != None and self.master_mapper.foreign_key.table_id == table: table_joined_mode = True break #else: # primary_data[akey] = self.master_mapper.get_field_value_from_key(akey) if joined_data_map != None: if table_joined_mode == False: self.extract_implicit_joined_data(key, foreign_mapper, foreign_data, joined_data_map, array_mode) else: self.extract_joined_data(foreign_mapper, foreign_data, joined_data_map, array_mode) else : table =self.get_foreignmapper_id_hosting_key(key) #if table == self.master_mapper.master_table_id: if table == None: if array_mode == True: primary_data.append(self.master_mapper.get_field_value_from_key(key)) else: primary_data[key] = self.master_mapper.get_field_value_from_key(key) else : foreign_mapper = self.foreign_mappers[table] foreign_data = self.foreign_data[table] value = foreign_mapper.value_map[key] table = value.table_id if value.multiplicity== None: foreign_mapper.read_row(foreign_data[self.ptr]) if array_mode == True: primary_data.append(foreign_mapper.get_field_value_from_key(key)) else: primary_data[key] = foreign_mapper.get_field_value_from_key(key) else: self.get_dataobject_list(foreign_mapper, foreign_data, array_mode, joined_data) """ for i in range(len(foreign_data)): foreign_mapper.read_row(foreign_data[i]) if array_mode == True: record = [] else: record = {} for fkey, value in foreign_mapper.value_map.items(): if fkey.startswith("#") == False: if array_mode == True: record.append(foreign_mapper.get_field_value_from_key(fkey)) else: record[fkey] = foreign_mapper.get_field_value_from_key(fkey) joined_data.append(record) """ def get_dataobject_list(self, mapper , data, array_mode, joined_data): for i in range(len(data)): mapper.read_row(data[i]) if array_mode == True: record = [] else: record = {} for fkey, value in mapper.value_map.items(): if fkey.startswith("#") == False: if array_mode == True: record.append(mapper.get_field_value_from_key(fkey)) else: record[fkey] = mapper.get_field_value_from_key(fkey) joined_data.append(record) def get_dataobject_dict(self, mapper , data, array_mode, joined_data, jdkey): joined_data[jdkey] = [] for i in range(len(data)): mapper.read_row(data[i]) if array_mode == True: record = [] else: record = {} for fkey, value in mapper.value_map.items(): if fkey.startswith("#") == False: if array_mode == True: record.append(mapper.get_field_value_from_key(fkey)) else: record[fkey] = mapper.get_field_value_from_key(fkey) joined_data[jdkey].append(record) def next_object(self): ''' Reads the current row, format it as a Dictionary and return it :return: Return a Dictionnary representation of the current data row :rtype: map is like { {literal parameters}, collection1_name:[{literal values }, ....] ''' if self.size > 0 : self.master_mapper.read_row(self.master_data[self.ptr]) retour = {} joined_data = {} for cn in self.collection_names: joined_data[cn["name"]] = [] if self.listed_columns == None: self.set_listed_columns(None) self.get_row_data(retour, joined_data) if self.collection_names != None: for k in self.collection_names: if k["name"] != "*" : retour[k["name"]] = joined_data[k["name"]] self.ptr += 1 return retour def next_values(self): ''' Reads the current row, format it as a list and return it The columns can be retrieved with the get_listed_columns() output :return: Return a Dictionary representation of the current data row :rtype: map is like [literal parameter values, [collection1 values], ....] ''' self.master_mapper.read_row(self.master_data[self.ptr]) retour = [] joined_data = [] if self.listed_columns == None: self.set_listed_columns(None) self.get_row_data(retour, joined_data, True) if self.collection_names != None: retour.append(joined_data) self.ptr += 1 return retour def rewind(self): self.ptr = 0