aheinecke@4872: try: aheinecke@4872: from osgeo import ogr aheinecke@4872: except ImportErrror: aheinecke@4872: import ogr aheinecke@4872: import osr ingo@3655: import shpimporter aheinecke@4877: import utils aheinecke@4935: import re ingo@2853: ingo@2853: class Importer: ingo@2853: aheinecke@4872: def __init__(self, config, dbconn): ingo@3654: self.config = config aheinecke@4872: self.dbconn = dbconn ingo@3654: self.river_id = config.river_id ingo@2861: self.dest_srs = osr.SpatialReference() ingo@3654: self.dest_srs.ImportFromEPSG(config.target_srs) aheinecke@4884: self.handled_fields = [] aheinecke@4885: self.tracking_import = False aheinecke@4935: self.srcLayer = None ingo@2853: ingo@2853: def getKind(self, path): ingo@2853: raise NotImplementedError("Importer.getKind is abstract!") ingo@2853: ingo@2853: def getPath(self, base): ingo@2853: raise NotImplementedError("Importer.getPath is abstract!") ingo@2853: ingo@2853: def getTablename(self): ingo@2853: raise NotImplementedError("Importer.getTablename is abstract!") ingo@2853: ingo@3654: def getName(self): ingo@3654: raise NotImplementedError("Importer.getTablename is abstract!") ingo@3654: ingo@2853: def IsFieldSet(self, feat, name): aheinecke@4935: if not name: aheinecke@4935: return False aheinecke@4878: if feat.GetFieldIndex(name) == -1: aheinecke@4878: return False # Avoids an Error in IsFieldSet aheinecke@4878: return feat.IsFieldSet(feat.GetFieldIndex(name)) ingo@2853: aheinecke@4935: def searchField(self, regex): aheinecke@4935: """ aheinecke@4935: Searches for a field in the current src layer that matches aheinecke@4935: the expression regex. aheinecke@4935: Throws an exception if more then one field matches aheinecke@4935: @param feat: The feature to search for attributes aheinecke@4935: @param regex: The regex to look for aheinecke@4935: aheinecke@4935: @returns: The field name as a string aheinecke@4935: """ aheinecke@4935: aheinecke@4935: if not hasattr(self.srcLayer, "fieldnames"): aheinecke@4935: self.srcLayer.fieldnames = [] aheinecke@4935: for i in range(0, self.srcLayer.GetLayerDefn().GetFieldCount()): aheinecke@4935: self.srcLayer.fieldnames.append( aheinecke@4935: self.srcLayer.GetLayerDefn().GetFieldDefn(i).GetNameRef()) aheinecke@4935: aheinecke@4935: result = None aheinecke@4935: for name in self.srcLayer.fieldnames: aheinecke@4935: match = re.match(regex, name, re.IGNORECASE) aheinecke@4935: if match: aheinecke@4935: if result: aheinecke@4935: raise Exception("More then one field matches: %s" % regex) aheinecke@4935: else: aheinecke@4935: result = match.group(0) aheinecke@4935: return result aheinecke@4935: ingo@2853: def IsDoubleFieldSet(self, feat, name): ingo@2853: try: ingo@2853: isset = feat.GetFieldAsDouble(name) ingo@2853: return isset is not None ingo@2853: except: ingo@2853: return False ingo@2853: ingo@2853: def isShapeRelevant(self, name, path): ingo@2853: return True ingo@2853: ingo@2853: def walkOverShapes(self, shape): ingo@2853: (name, path) = shape ingo@2853: if not self.isShapeRelevant(name, path): ingo@3655: shpimporter.INFO("Skip shapefile '%s'" % path) ingo@2853: return ingo@2853: ingo@2853: shp = ogr.Open(shape[1]) ingo@2853: if shp is None: ingo@3655: shpimporter.ERROR("Shapefile '%s' could not be opened!" % path) ingo@2853: return ingo@2853: ingo@3655: shpimporter.INFO("Processing shapefile '%s'" % path) ingo@2853: srcLayer = shp.GetLayerByName(name) ingo@2853: ingo@2853: if srcLayer is None: ingo@3655: shpimporter.ERROR("Layer '%s' was not found!" % name) ingo@2853: return ingo@2853: ingo@2853: return self.shape2Database(srcLayer, name, path) ingo@2853: ingo@2861: def transform(self, feat): ingo@2861: geometry = feat.GetGeometryRef() ingo@2861: src_srs = geometry.GetSpatialReference() ingo@2861: ingo@2861: if src_srs is None: ingo@3679: shpimporter.ERROR("No source SRS given! No transformation possible!") ingo@2861: return feat ingo@2861: ingo@2861: transformer = osr.CoordinateTransformation(src_srs, self.dest_srs) ingo@2861: geometry.Transform(transformer) ingo@2861: ingo@2861: return feat ingo@2861: aheinecke@4884: def handled(self, field): aheinecke@4884: """ aheinecke@4884: Register a field or a map of as handled during the import. aheinecke@4884: aheinecke@4884: There is a warning printed after the import for each unhandled field! aheinecke@4884: """ aheinecke@4884: if not field in self.handled_fields: aheinecke@4884: self.handled_fields.append(field) aheinecke@4884: aheinecke@4884: def copyFields(self, src, target, mapping): aheinecke@4884: """ aheinecke@4884: Checks the mapping dictonary for key value pairs to aheinecke@4884: copy from the source to the destination feature. aheinecke@4935: The keys can be reguar expressions that are matched aheinecke@4935: agains the source fieldnames aheinecke@4884: aheinecke@4884: The Key is the attribute of the source feature to be copied aheinecke@4884: into the target attribute named by the dict's value. aheinecke@4884: """ aheinecke@4885: self.tracking_import = True aheinecke@4884: for key, value in mapping.items(): aheinecke@4935: realname = self.searchField(key) aheinecke@4935: if realname == None: aheinecke@4884: continue aheinecke@4935: if not realname in self.handled_fields: aheinecke@4935: self.handled_fields.append(realname) aheinecke@4884: # 0 OFTInteger, Simple 32bit integer aheinecke@4884: # 1 OFTIntegerList, List of 32bit integers aheinecke@4884: # 2 OFTReal, Double Precision floating point aheinecke@4884: # 3 OFTRealList, List of doubles aheinecke@4884: # 4 OFTString, String of ASCII chars aheinecke@4884: # 5 OFTStringList, Array of strings aheinecke@4884: # 6 OFTWideString, deprecated aheinecke@4884: # 7 OFTWideStringList, deprecated aheinecke@4884: # 8 OFTBinary, Raw Binary data aheinecke@4884: # 9 OFTDate, Date aheinecke@4884: # 10 OFTTime, Time aheinecke@4884: # 11 OFTDateTime, Date and Time aheinecke@4935: if src.IsFieldSet(src.GetFieldIndex(realname)): aheinecke@4935: if src.GetFieldType(realname) == 2: aheinecke@4935: target.SetField(value, src.GetFieldAsDouble(realname)) aheinecke@4884: else: aheinecke@4935: target.SetField(value, utils.getUTF8(src.GetField(realname))) aheinecke@4884: ingo@2853: def shape2Database(self, srcLayer, name, path): aheinecke@4872: destLayer = self.dbconn.GetLayerByName(self.getTablename()) ingo@2853: ingo@2853: if srcLayer is None: ingo@3655: shpimporter.ERROR("Shapefile is None!") ingo@2853: return -1 ingo@2853: ingo@2853: if destLayer is None: ingo@3655: shpimporter.ERROR("No destination layer given!") ingo@2853: return -1 ingo@2853: ingo@2853: count = srcLayer.GetFeatureCount() ingo@3655: shpimporter.DEBUG("Try to add %i features to database." % count) ingo@2853: ingo@2853: srcLayer.ResetReading() aheinecke@4935: self.srcLayer = srcLayer ingo@2853: ingo@2853: geomType = -1 ingo@2853: success = 0 ingo@2853: unsupported = 0 ingo@2861: creationFailed = 0 ingo@2853: featureDef = destLayer.GetLayerDefn() ingo@2853: ingo@2853: for feat in srcLayer: ingo@2853: geom = feat.GetGeometryRef() ingo@2861: ingo@2861: if geom is None: aheinecke@4878: shpimporter.DEBUG("Unkown Geometry reference for feature") ingo@2861: continue ingo@2861: ingo@2853: geomType = geom.GetGeometryType() ingo@2853: ingo@2853: if self.isGeometryValid(geomType): ingo@2853: newFeat = self.createNewFeature(featureDef, ingo@2853: feat, aheinecke@4951: name=utils.getUTF8(name), ingo@2853: path=path) ingo@2853: ingo@2853: if newFeat is not None: aheinecke@4877: newFeat.SetField("path", utils.getUTF8Path(path)) ingo@2861: newFeat = self.transform(newFeat) ingo@2853: res = destLayer.CreateFeature(newFeat) ingo@2853: if res is None or res > 0: aheinecke@4872: shpimporter.ERROR("Unable to insert feature. Error: %r" % res) ingo@2853: else: ingo@2853: success = success + 1 ingo@2861: else: ingo@2861: creationFailed = creationFailed + 1 ingo@2853: else: ingo@2853: unsupported = unsupported + 1 ingo@2853: ingo@3655: shpimporter.INFO("Inserted %i features" % success) ingo@3655: shpimporter.INFO("Failed to create %i features" % creationFailed) ingo@3655: shpimporter.INFO("Found %i unsupported features" % unsupported) ingo@2853: aheinecke@4886: if self.tracking_import: aheinecke@4886: unhandled = [] aheinecke@4886: for i in range(0, srcLayer.GetLayerDefn().GetFieldCount()): aheinecke@4886: act_field = srcLayer.GetLayerDefn().GetFieldDefn(i).GetNameRef() aheinecke@4886: if not act_field in self.handled_fields: aheinecke@4886: unhandled.append(act_field) aheinecke@4884: aheinecke@4886: if len(unhandled): aheinecke@4886: shpimporter.INFO("Did not import values from fields: %s " % \ aheinecke@4886: " ".join(unhandled)) aheinecke@4884: ingo@2853: try: ingo@3655: if self.config.dry_run > 0: ingo@3655: return geomType ingo@2853: destLayer.CommitTransaction() ingo@2853: except e: ingo@3655: shpimporter.ERROR("Exception while committing transaction.") ingo@2853: ingo@2853: return geomType