aboutsummaryrefslogtreecommitdiffstats
path: root/webmap-import
diff options
context:
space:
mode:
Diffstat (limited to 'webmap-import')
-rwxr-xr-xwebmap-import99
1 files changed, 92 insertions, 7 deletions
diff --git a/webmap-import b/webmap-import
index e9ae302..e978f34 100755
--- a/webmap-import
+++ b/webmap-import
@@ -730,8 +730,9 @@ def setOutputFieldMap(defn, sources):
fieldMap[fldName] = i
for source in sources:
- src = source['source']['path']
- fieldMap2 = source['import'].get('field-map', None)
+ source_import = source['import']
+
+ fieldMap2 = source_import.get('field-map', None)
if fieldMap2 is None:
fieldMap2 = fieldMap
else:
@@ -744,10 +745,22 @@ def setOutputFieldMap(defn, sources):
if i is None:
raise Exception(f'Ouput layer has no field named "{ofld}"')
fieldMap2[ifld] = i
-
- source['import']['field-map'] = fieldMap2
-
- return fieldMap
+ source_import['field-map'] = fieldMap2
+
+ # validate field value mapping
+ valueMap = source_import.get('value-map', None)
+ if valueMap is not None:
+ for fldName, rules in valueMap.items():
+ if rules is None:
+ continue
+ if not isinstance(rules, list):
+ rules = [rules]
+ for idx, rule in enumerate(rules):
+ if rule is None or not isinstance(rule, dict):
+ raise Exception(f'Field "{fldName}" has invalid rule #{idx}: {rule}')
+ if 'from' not in rule or 'to' not in rule or len(rule) != 2:
+ raise Exception(f'Field "{fldName}" has invalid rule #{idx}: {rule}')
+ rules[idx] = ( rule['from'], rule['to'] )
# Escape the given identifier, cf.
# swig/python/gdal-utils/osgeo_utils/samples/validate_gpkg.py:_esc_id()
@@ -856,6 +869,31 @@ def importSource(lyr, path=None, unar=None, args={}, cachedir=None, extent=None)
return importSource2(lyr, ds_srcpath, args=args,
basedir=Path(tmpdir), extent=extent)
+# Validate field value mapping
+def setFieldMapValue(fld, idx, val):
+ if val is None:
+ if not fld.IsNullable():
+ logging.warning('Field "%s" is not NULLable but remaps NULL', fld.GetName())
+ return None
+
+ fldType = fld.GetType()
+ if fldType == ogr.OFTInteger or fldType == ogr.OFTInteger64:
+ if isinstance(val, int):
+ return val
+ elif fldType == ogr.OFTString:
+ if isinstance(val, str):
+ return val
+ elif fldType == ogr.OFTBinary:
+ if isinstance(val, bytes):
+ return val
+ elif fldType == ogr.OFTReal:
+ if isinstance(val, int):
+ return float(val)
+ elif isinstance(val, float):
+ return val
+
+ raise Exception(f'Field "{fld.GetName()}" mapping #{idx} has incompatible type for {ogr.GetFieldTypeName(fldType)}')
+
# Import a source layer (already extracted)
# This is more or less like ogr2ogr/GDALVectorTranslate() but we roll
# out our own (slower) version because GDALVectorTranslate() insists in
@@ -927,7 +965,6 @@ def importSource2(lyr_dst, path, args={}, basedir=None, extent=None):
# call SetIgnored() on unwanted source fields
logging.debug('Set Ignored=True on output field "%s"', fldName)
fld.SetIgnored(True)
- defn = None
count0 = -1
if lyr.TestCapability(ogr.OLCFastFeatureCount):
@@ -965,6 +1002,32 @@ def importSource2(lyr_dst, path, args={}, basedir=None, extent=None):
else:
logging.info('Source layer "%s" has %d features', layername, count0)
+ # build a list of pairs (field index, mapping_dict)
+ valueMapLiteral = []
+ for fldName, rules in args.get('value-map', {}).items():
+ i = defn.GetFieldIndex(fldName)
+ if i < 0:
+ raise Exception(f'Source layer "{layername}" has no field named "{fldName}"')
+ if fieldMap[i] < 0:
+ logging.warning('Ignored source field "%s" has value map', fldName)
+ continue
+
+ h = {}
+ fld = defn.GetFieldDefn(i)
+ for idx, (rFrom, rTo) in enumerate(rules):
+ # use fld for both from and to (the types must match,
+ # casting is not allowed in the mapping)
+ rFrom = setFieldMapValue(fld, idx, rFrom)
+ rTo = setFieldMapValue(fld, idx, rTo)
+ h[rFrom] = rTo
+
+ if len(h) > 0:
+ valueMapLiteral.append((i, h))
+
+ bValueMapLiteral = len(valueMapLiteral) > 0
+
+ defn = None
+
defn_dst = lyr_dst.GetLayerDefn()
eGType_dst = defn_dst.GetGeomType()
eGType_dst_HasZ = ogr.GT_HasZ(eGType_dst)
@@ -975,6 +1038,28 @@ def importSource2(lyr_dst, path, args={}, basedir=None, extent=None):
mismatch = {}
feature = lyr.GetNextFeature()
while feature is not None:
+ if bValueMapLiteral:
+ for i, h in valueMapLiteral:
+ if not feature.IsFieldSet(i):
+ continue
+ elif feature.IsFieldNull(i):
+ if None in h:
+ v = h[None]
+ if v is not None:
+ # replace NULL with non-NULL value
+ feature.SetField(i, v)
+ continue
+
+ v = feature.GetField(i)
+ if v in h:
+ v2 = h[v]
+ if v2 is None:
+ # replace non-NULL value with NULL
+ feature.SetFieldNull(i)
+ else:
+ # replace non-NULL value with non-NULL value
+ feature.SetField(i, v2)
+
feature2 = ogr.Feature(defn_dst)
feature2.SetFromWithMap(feature, False, fieldMap)