comparison backend/contrib/shpimporter/importer.py @ 5838:5aa05a7a34b7

Rename modules to more fitting names.
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 15:23:37 +0200
parents flys-backend/contrib/shpimporter/importer.py@db5def5456ce
children
comparison
equal deleted inserted replaced
5837:d9901a08d0a6 5838:5aa05a7a34b7
1 try:
2 from osgeo import ogr, osr
3 except ImportError:
4 import ogr, osr
5 import utils
6 import re
7 import logging
8
9 logger = logging.getLogger("importer")
10
11 class Importer:
12
13 def __init__(self, river_id, dbconn, dry_run):
14 self.river_id = river_id
15 self.dbconn = dbconn
16 self.dry_run = dry_run
17 self.dest_srs = osr.SpatialReference()
18 self.dest_srs.ImportFromEPSG(31467)
19 self.handled_fields = []
20 self.tracking_import = False
21 self.srcLayer = None
22
23 def getKind(self, path):
24 raise NotImplementedError("Importer.getKind is abstract!")
25
26 def getPath(self, base):
27 raise NotImplementedError("Importer.getPath is abstract!")
28
29 def getTablename(self):
30 raise NotImplementedError("Importer.getTablename is abstract!")
31
32 def getName(self):
33 raise NotImplementedError("Importer.getName is abstract!")
34
35 def isGeometryValid(self, geomType):
36 raise NotImplementedError("Importer.isGeometryValid is abstract!")
37
38 def createNewFeature(self, featureDef, feat, **args):
39 raise NotImplementedError("Importer.createNewFeature is abstract!")
40
41 def IsFieldSet(self, feat, name):
42 if not name:
43 return False
44 if feat.GetFieldIndex(name) == -1:
45 return False # Avoids an Error in IsFieldSet
46 return feat.IsFieldSet(feat.GetFieldIndex(name))
47
48 def searchValue(self, feat, regex):
49 """
50 Searches for a value that matches regex in all attribute
51 fields of a feature.
52
53 @returns the name of the field where a match was found or None
54 """
55 for val in feat.items():
56 if not isinstance(feat.items()[val], basestring):
57 continue
58 match = re.match(regex, feat.items()[val], re.IGNORECASE)
59 if match:
60 return val
61
62 def searchField(self, regex):
63 """
64 Searches for a field in the current src layer that matches
65 the expression regex.
66 Throws an exception if more than one field matches
67 @param feat: The feature to search for attributes
68 @param regex: The regex to look for
69
70 @returns: The field name as a string
71 """
72
73 if not hasattr(self.srcLayer, "fieldnames"):
74 self.srcLayer.fieldnames = []
75 for i in range(0, self.srcLayer.GetLayerDefn().GetFieldCount()):
76 self.srcLayer.fieldnames.append(
77 self.srcLayer.GetLayerDefn().GetFieldDefn(i).GetNameRef())
78
79 result = None
80 for name in self.srcLayer.fieldnames:
81 match = re.match(regex, name, re.IGNORECASE)
82 if match:
83 if result:
84 raise Exception("More than one field matches: %s" % regex)
85 else:
86 result = match.group(0)
87 return result
88
89 def IsDoubleFieldSet(self, feat, name):
90 if not self.IsFieldSet(feat, name):
91 return False
92 try:
93 isset = feat.GetFieldAsDouble(name)
94 return isset is not None
95 except:
96 return False
97
98 def isShapeRelevant(self, name, path):
99 return True
100
101 def walkOverShapes(self, shape):
102 (name, path) = shape
103
104 shp = ogr.Open(shape[1])
105 if shp is None:
106 logger.error("Shapefile '%s' could not be opened!" % path)
107 return
108
109 if not self.isShapeRelevant(name, path):
110 logger.info("Skip shapefile: '%s' of Type: %s" % (path,
111 utils.getWkbString(shp.GetLayerByName(name).GetGeomType())))
112 return
113
114
115 logger.info("Processing shapefile '%s'" % path)
116 srcLayer = shp.GetLayerByName(name)
117
118 if srcLayer is None:
119 logger.error("Layer '%s' was not found!" % name)
120 return
121
122 return self.shape2Database(srcLayer, name, path)
123
124 def transform(self, feat):
125 geometry = feat.GetGeometryRef()
126 src_srs = geometry.GetSpatialReference()
127
128 if src_srs is None:
129 logger.error("No source SRS given! No transformation possible!")
130 return feat
131
132 transformer = osr.CoordinateTransformation(src_srs, self.dest_srs)
133 if geometry.Transform(transformer):
134 return None
135
136 return feat
137
138 def handled(self, field):
139 """
140 Register a field or a map of as handled during the import.
141
142 There is a warning printed after the import for each unhandled field!
143 """
144 if not field in self.handled_fields:
145 self.handled_fields.append(field)
146
147 def copyFields(self, src, target, mapping):
148 """
149 Checks the mapping dictonary for key value pairs to
150 copy from the source to the destination feature.
151 The keys can be reguar expressions that are matched
152 agains the source fieldnames
153
154 The Key is the attribute of the source feature to be copied
155 into the target attribute named by the dict's value.
156 """
157 self.tracking_import = True
158 for key, value in mapping.items():
159 realname = self.searchField(key)
160 if realname == None:
161 continue
162 if not realname in self.handled_fields:
163 self.handled_fields.append(realname)
164 # 0 OFTInteger, Simple 32bit integer
165 # 1 OFTIntegerList, List of 32bit integers
166 # 2 OFTReal, Double Precision floating point
167 # 3 OFTRealList, List of doubles
168 # 4 OFTString, String of ASCII chars
169 # 5 OFTStringList, Array of strings
170 # 6 OFTWideString, deprecated
171 # 7 OFTWideStringList, deprecated
172 # 8 OFTBinary, Raw Binary data
173 # 9 OFTDate, Date
174 # 10 OFTTime, Time
175 # 11 OFTDateTime, Date and Time
176 if src.IsFieldSet(src.GetFieldIndex(realname)):
177 if src.GetFieldType(realname) == 2:
178 target.SetField(value, src.GetFieldAsDouble(realname))
179 else:
180 target.SetField(value, utils.getUTF8(src.GetField(realname)))
181
182 def shape2Database(self, srcLayer, name, path):
183 destLayer = self.dbconn.GetLayerByName(self.getTablename())
184
185 if srcLayer is None:
186 logger.error("Shapefile is None!")
187 return -1
188
189 if destLayer is None:
190 logger.error("No destination layer given!")
191 return -1
192
193 count = srcLayer.GetFeatureCount()
194 logger.debug("Try to add %i features to database." % count)
195
196 srcLayer.ResetReading()
197 self.srcLayer = srcLayer
198
199 geomType = -1
200 success = 0
201 unsupported = {}
202 creationFailed = 0
203 featureDef = destLayer.GetLayerDefn()
204
205 for feat in srcLayer:
206 geom = feat.GetGeometryRef()
207
208 if geom is None:
209 logger.debug("Unkown Geometry reference for feature")
210 continue
211
212 geomType = geom.GetGeometryType()
213
214 if self.isGeometryValid(geomType):
215 newFeat = self.createNewFeature(featureDef,
216 feat,
217 name=utils.getUTF8(name),
218 path=path)
219
220 if newFeat is not None:
221 newFeat.SetField("path", utils.getUTF8Path(path))
222 newFeat = self.transform(newFeat)
223 if newFeat:
224 res = destLayer.CreateFeature(newFeat)
225 if res is None or res > 0:
226 logger.error("Unable to insert feature. Error: %r" % res)
227 else:
228 success = success + 1
229 else:
230 logger.error("Could not transform feature: %s " % feat.GetFID())
231 creationFailed += 1
232 else:
233 creationFailed = creationFailed + 1
234 else:
235 unsupported[utils.getWkbString(geomType)] = \
236 unsupported.get(utils.getWkbString(geomType), 0) + 1
237
238 logger.info("Inserted %i features" % success)
239 logger.info("Failed to create %i features" % creationFailed)
240 for key, value in unsupported.items():
241 logger.info("Found %i unsupported features of type: %s" % (value, key))
242
243 if self.tracking_import:
244 unhandled = []
245 for i in range(0, srcLayer.GetLayerDefn().GetFieldCount()):
246 act_field = srcLayer.GetLayerDefn().GetFieldDefn(i).GetNameRef()
247 if not act_field in self.handled_fields:
248 unhandled.append(act_field)
249
250 if len(unhandled):
251 logger.info("Did not import values from fields: %s " % \
252 " ".join(unhandled))
253
254 try:
255 if self.dry_run:
256 return geomType
257 destLayer.CommitTransaction()
258 except:
259 logger.error("Exception while committing transaction.")
260
261 return geomType

http://dive4elements.wald.intevation.org