Skip to content

Commit 32870e4

Browse files
author
jdeolive
committed
tweaked type mapping stuff, registered more mappers for geotools/geoscript type conversions
1 parent 7e01d85 commit 32870e4

18 files changed

+151
-49
lines changed

geoscript/core.py

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,90 @@ def rename(self):
1313
def register(t):
1414
ProxyRenamer(t).rename()
1515

16-
_tmap = {}
17-
_tmap[int] = java.lang.Integer
18-
_tmap[java.lang.Integer] = int
19-
_tmap[java.lang.Short] = int
20-
_tmap[java.lang.Float] = int
21-
22-
_tmap[long] = java.lang.Long
23-
_tmap[java.lang.Long] = long
24-
25-
_tmap[str] = java.lang.String
26-
_tmap[unicode] = java.lang.String
27-
_tmap[java.lang.String] = str
28-
29-
_tmap[float] = java.lang.Double
30-
_tmap[java.lang.Double] = float
31-
_tmap[java.lang.Float] = float
32-
33-
"""
34-
Maps a jython type to its associated java type.
35-
"""
16+
class TypeMapper(object):
17+
"""
18+
Maps a jython/geoscript type to java/geotools type, and back.
19+
"""
20+
21+
def __init__(self, fromType, toType, conv=None):
22+
self.fromType = fromType
23+
self.toType = toType
24+
self.conv = conv
25+
26+
def map(self, obj):
27+
if isinstance(obj,type):
28+
return self.toType
29+
30+
if self.conv:
31+
return self.conv(obj)
32+
33+
# default is to try and just invoke the constructor
34+
return self.toType(obj)
35+
36+
# forward type map
37+
_fmap = {}
38+
39+
# reverse type map
40+
_rmap = {}
41+
42+
def registerTypeMapping(fromType, toType, conv=None):
43+
"""
44+
Registers a forward mapping (called by :func:`map`) from a java/geotools
45+
type to a jython/geoscript type.
46+
"""
47+
_fmap[fromType] = TypeMapper(fromType, toType, conv)
48+
49+
def registerTypeUnmapping(fromType, toType, conv=None):
50+
"""
51+
Registers a reverse mapping (called by :func:`unmap`) from a jython/geoscript
52+
type to a java/geotools type.
53+
"""
54+
_rmap[fromType] = TypeMapper(fromType, toType, conv)
55+
56+
# register some core type mappers
57+
registerTypeMapping(java.lang.Integer, int)
58+
registerTypeMapping(java.lang.Short, int)
59+
registerTypeMapping(java.lang.Byte, int)
60+
registerTypeUnmapping(int, java.lang.Integer)
61+
62+
registerTypeMapping(java.lang.Long, long)
63+
registerTypeUnmapping(long, java.lang.Long)
64+
65+
registerTypeMapping(java.lang.String, str)
66+
registerTypeUnmapping(str, java.lang.String)
67+
registerTypeUnmapping(unicode, java.lang.String)
68+
69+
registerTypeMapping(java.lang.Double, float)
70+
registerTypeMapping(java.lang.Float, float)
71+
registerTypeUnmapping(float, java.lang.Double)
72+
3673
def map(o):
74+
"""
75+
Maps a java/geotools type to its associated jython/geoscript type.
76+
"""
77+
return _doMap(o, _fmap)
78+
79+
def unmap(o):
80+
"""
81+
Reverse maps a jython/geoscript type to its associated java/geotools type.
82+
"""
83+
return _doMap(o, _rmap)
84+
85+
def _doMap(o, maps):
3786
if isinstance(o,type):
3887
t = o
3988
else:
4089
t = type(o)
4190

42-
if _tmap.has_key(t):
43-
mapped = _tmap[t]
44-
if isinstance(o,type):
45-
return mapped
46-
else:
47-
return mapped(o)
91+
if maps.has_key(t):
92+
return maps[t].map(o)
93+
94+
# could not find direct match, look for subclasses
95+
matches = [x for x in maps.keys() if issubclass(t,x)]
96+
if len(matches) == 1:
97+
# single match, go with it
98+
return maps[matches[0]].map(o)
4899

49100
return o
50101

102+

geoscript/feature/feature.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import string
22
from org.geotools.feature.simple import SimpleFeatureBuilder
3+
from org.opengis.feature import Feature as _Feature
34
from geoscript import core, geom
45

56
class Feature(object):
@@ -76,7 +77,7 @@ def getid(self):
7677
"""
7778

7879
def getgeom(self):
79-
return self._feature.defaultGeometry
80+
return core.map(self._feature.defaultGeometry)
8081

8182
def setgeom(self, g):
8283
self._feature.defaultGeometry = g
@@ -181,3 +182,6 @@ def __repr__(self):
181182

182183
def __eq__(self, other):
183184
return other and self._feature == other._feature
185+
186+
core.registerTypeMapping(_Feature, Feature, lambda x: Feature(f=x))
187+
core.registerTypeUnmapping(Feature, _Feature, lambda x: x._feature)

geoscript/feature/schema.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import string
2-
from org.opengis.feature.type import GeometryDescriptor
2+
from org.opengis.feature.type import FeatureType, GeometryDescriptor
33
from org.geotools.feature import NameImpl
44
from org.geotools.feature.simple import SimpleFeatureTypeBuilder
55
from geoscript import core, geom, proj
@@ -46,9 +46,9 @@ def __init__(self, name=None, fields=[], ft=None,
4646
if prj:
4747
tb.crs(prj._crs)
4848

49-
# we call map() here to avoid setting the type binding to a Python
49+
# we call unmap() here to avoid setting the type binding to a Python
5050
# (eg: PyInteger) type, but rather a native java type (Integer)
51-
tb.add(name, core.map(typ))
51+
tb.add(name, core.unmap(typ))
5252

5353
self._type = tb.buildFeatureType()
5454

@@ -186,3 +186,6 @@ def __repr__(self):
186186

187187
def __eq__(self, other):
188188
return other and self._type == other._type
189+
190+
core.registerTypeMapping(FeatureType, Schema, lambda x: Schema(ft=x))
191+
core.registerTypeUnmapping(Schema, FeatureType, lambda x: x._type)

geoscript/filter.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from org.geotools.filter.text.ecql import ECQL
1010
from org.geotools.xml import Parser, Encoder
1111
from org.geotools.factory import CommonFactoryFinder
12+
from geoscript import core
1213

1314
_factory = CommonFactoryFinder.getFilterFactory(None)
1415

@@ -151,3 +152,6 @@ def _ogc(version):
151152
raise Exception('fromXML() not available, filter libs not on classpath')
152153

153154
return (OGC11.getInstance(),OGCConfiguration11()) if version == 1.1 else (OGC10.getInstance(), OGCConfiguration10())
155+
156+
core.registerTypeMapping(_Filter, Filter)
157+
core.registerTypeMapping(Filter, _Filter, lambda x: x._filter)

geoscript/geom/bounds.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from org.geotools.geometry.jts import ReferencedEnvelope
22
from geoscript.util import deprecated
3-
from geoscript import proj
3+
from geoscript import core, proj
44

55
class Bounds(ReferencedEnvelope):
66
"""
@@ -154,3 +154,5 @@ def __repr__(self):
154154

155155
return '%s)' % s
156156

157+
core.registerTypeMapping(ReferencedEnvelope, Bounds, lambda x: Bounds(env=x))
158+

geoscript/geom/linearring.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from com.vividsolutions.jts.geom import Coordinate
22
from com.vividsolutions.jts.geom import LinearRing as _LinearRing
33
from linestring import LineString
4+
from geoscript import core
45
import geom
56

67
class LinearRing(_LinearRing):
@@ -19,3 +20,4 @@ def __init__(self, *coords):
1920
_LinearRing.__init__(self, l.coordinateSequence, geom._factory)
2021

2122
geom._enhance(LinearRing)
23+
core.registerTypeMapping(_LinearRing, LinearRing)

geoscript/geom/linestring.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from com.vividsolutions.jts.geom import Coordinate
22
from com.vividsolutions.jts.geom import LineString as _LineString
3+
from geoscript import core
34
import geom
45

56
class LineString(_LineString):
@@ -27,3 +28,4 @@ def __init__(self, *coords):
2728
_LineString.__init__(self, ls.coordinateSequence, geom._factory)
2829

2930
geom._enhance(LineString)
31+
core.registerTypeMapping(_LineString, LineString)

geoscript/geom/multilinestring.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from com.vividsolutions.jts.geom import MultiLineString as _MultiLineString
22
from linestring import LineString
3+
from geoscript import core
34
import geom
45

56
class MultiLineString(_MultiLineString):
@@ -29,3 +30,4 @@ def __init__(self, *linestrings):
2930
_MultiLineString.__init__(self, linestrings, geom._factory)
3031

3132
geom._enhance(MultiLineString)
33+
core.registerTypeMapping(_MultiLineString, MultiLineString)

geoscript/geom/multipoint.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from com.vividsolutions.jts.geom import MultiPoint as _MultiPoint
2+
from geoscript import core
23
from point import Point
34
import geom
45

@@ -29,3 +30,4 @@ def __init__(self, *points):
2930
_MultiPoint.__init__(self, points, geom._factory)
3031

3132
geom._enhance(MultiPoint)
33+
core.registerTypeMapping(_MultiPoint, MultiPoint)

geoscript/geom/multipolygon.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from com.vividsolutions.jts.geom import MultiPolygon as _MultiPolygon
2+
from geoscript import core
23
from polygon import Polygon
34
import geom
45

@@ -29,3 +30,4 @@ def __init__(self, *polygons):
2930
_MultiPolygon.__init__(self, polygons, geom._factory)
3031

3132
geom._enhance(MultiPolygon)
33+
core.registerTypeMapping(_MultiPolygon, MultiPolygon)

geoscript/geom/point.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from com.vividsolutions.jts.geom import Coordinate
22
from com.vividsolutions.jts.geom import Point as _Point
3+
from geoscript import core
34
import geom
45

56
class Point(_Point):
@@ -25,3 +26,4 @@ def __init__(self, *coord):
2526
_Point.__init__(self, p.coordinateSequence, geom._factory)
2627

2728
geom._enhance(Point)
29+
core.registerTypeMapping(_Point, Point)

geoscript/geom/polygon.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from com.vividsolutions.jts.geom import Polygon as _Polygon
2+
from geoscript import core
23
from linearring import LinearRing
34
import geom
45

@@ -29,3 +30,4 @@ def __init__(self, *rings):
2930
_Polygon.__init__(self, lr[0], lr[1:], geom._factory)
3031

3132
geom._enhance(Polygon)
33+
core.registerTypeMapping(_Polygon, Polygon)

geoscript/layer/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from cursor import Cursor
12
from layer import Layer
23
from shapefile import Shapefile
34
from io.gml import writeGML, readGML

geoscript/layer/cursor.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from org.geotools.feature import FeatureCollection
2+
from geoscript import core
13
from geoscript.feature import Feature
24
from geoscript.filter import Filter
35

@@ -6,20 +8,23 @@ class Cursor(object):
68
A cursor or iterator over :class:`Feature <geoscript.feature.feature.Feature>` objects.
79
"""
810

9-
def __init__(self, fcol, layer):
11+
def __init__(self, fcol, layer=None):
1012
self._fcol = fcol
11-
self._reader = fcol.features()
13+
self._reader = None
1214
self.layer = layer
1315

1416
def next(self):
17+
if not self._reader:
18+
self._reader = self._fcol.features()
19+
1520
"""
1621
Returns the next feature. Raises `StopIteration` if no more features are available.
1722
"""
1823
if not self._reader.hasNext():
1924
self._reader.close()
2025
raise StopIteration
2126

22-
return Feature(schema=self.layer.schema, f=self._reader.next())
27+
return Feature(schema=self.layer.schema if self.layer else None, f=self._reader.next())
2328

2429
def read(self, n):
2530
"""
@@ -40,7 +45,11 @@ def close(self):
4045
"""
4146
Closes the cursor. This function should *always* be called by client code after the cursor is no longer needed or has been exhausted.
4247
"""
43-
self._reader.close()
48+
if self._reader:
49+
self._reader.close()
4450

4551
def __iter__(self):
4652
return self
53+
54+
core.registerTypeMapping(FeatureCollection, Cursor)
55+
core.registerTypeUnmapping(Cursor, FeatureCollection, lambda x: x._fcol)

geoscript/layer/layer.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
from java import io
66
from java import net
77
from cursor import Cursor
8-
from geoscript import geom, proj, feature
8+
from geoscript import core, geom, proj, feature
99
from geoscript.filter import Filter
1010
from geoscript.util.data import readFeatures
11-
from org.geotools.data import DefaultQuery, Query, Transaction
11+
from org.geotools.data import FeatureSource, DefaultQuery, Query, Transaction
1212
from org.geotools.factory import CommonFactoryFinder
13-
from org.geotools.feature import FeatureCollections
13+
from org.geotools.feature import FeatureCollection, FeatureCollections
1414
from org.opengis.filter.sort import SortOrder
1515

1616
_filterFactory = CommonFactoryFinder.getFilterFactory(None)
@@ -344,8 +344,8 @@ def reproject(self, prj, name=None, chunk=1000):
344344
>>> l2.proj.id
345345
'EPSG:26912'
346346
347-
>>> [f.geom for f in l2.features()]
348-
[POINT (500000 5060716.31816507)]
347+
>>> [f.geom.round() for f in l2.features()]
348+
[POINT (500000 5060716)]
349349
"""
350350

351351
prj = proj.Projection(prj)
@@ -544,3 +544,6 @@ def toJSON(self,out=sys.stdout):
544544
def _newname():
545545
Layer._id += 1
546546
return 'layer_%d' % Layer._id
547+
548+
core.registerTypeMapping(FeatureSource, Layer, lambda x: Layer(fs=x))
549+
core.registerTypeUnmapping(Layer, FeatureSource, lambda x: x._source)

0 commit comments

Comments
 (0)