Mercurial > dive4elements > river
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 |