Introduce FileShapeStore

Jan-Oliver Wagner jan at intevation.de
Tue Apr 26 15:42:16 CEST 2005


On Mon, Apr 25, 2005 at 06:03:00PM +0200, Bernhard Herzog wrote:
> Jan-Oliver Wagner <jan at intevation.de> writes:
> > On Fri, Apr 22, 2005 at 09:06:21PM +0200, Bernhard Herzog wrote:
> >> Jan-Oliver Wagner <jan at intevation.de> writes:
> >> > @@ -186,6 +251,10 @@ class ShapefileStore:
> >> >          """
> >> >          return ()
> >> >  
> >> > +    def Table(self):
> >> > +        """Return the table containing the attribute data."""
> >> > +        return self._table
> >> > +
> >> 
> >> I think we should avoid moving the methods around unnecessarily, if
> >> possible.  The same applies to BoundingBox.
> >
> > do you mean my renaming table to _table and bbox to _bbox?
> 
> The patch removes the Table method in one place and adds it in another.
> That distracts from the fact that the instance variable is renamed.

ah, OK. That was due to itertive adaption of the patch.
And here comes trial number 3.

This one OK for checkin?

Best

	Jan
-- 
Jan-Oliver Wagner               http://intevation.de/~jan/

Intevation GmbH                      http://intevation.de/
FreeGIS                                http://freegis.org/
-------------- next part --------------
Index: data.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/Model/data.py,v
retrieving revision 1.15
diff -u -3 -p -r1.15 data.py
--- data.py	24 Nov 2003 19:23:08 -0000	1.15
+++ data.py	26 Apr 2005 13:38:37 -0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2003 by Intevation GmbH
+# Copyright (C) 2003, 2005 by Intevation GmbH
 # Authors:
 # Bernhard Herzog <bh at intevation.de>
 #
@@ -112,29 +112,104 @@ class ShapeTable(transientdb.AutoTransie
         """Return a tuple containing the shapestore"""
         return (self.store(),)
 
+# XXX: (this statement should be kept in mind when re-engeneering)
+#
+# From a desing POV it was wrong to distinguish between table and
+# shapestore.  In hindsight the only reason for doing so was that the
+# shapelib has different objects for the shapefile(s) and the dbf file,
+# which of course matches the way the data is organized into different
+# files.  So the distinction between shapestore and table is an artifact
+# of the shapefile format.  When we added the postgis support we should
+# have adopted the table interface for the entire shape store, making the
+# geometry data an additional column for those shape stores that don't
+# store the geometries in columns in the first place.
+
+class FileShapeStore:
+
+    """The base class to derive any file-based ShapeStore from.
+
+    This class contains all information that is needed by a
+    loader routine to actually load the shapestore.
+    This essentially means that the class contains all required information
+    to save the shapestore specification (i.e. in a .thuban file).
+    """
+
+    def __init__(self, filename, sublayer_name = None):
+        """Initialize the base class with main parameters.
+
+        filename  -- the source filename.
+                     This filename will be converted to an absolute filename.
+                     The filename will be interpreted relative to the .thuban file anyway,
+                     but when saving a session we need to compare absolute paths
+                     and it's usually safer to always work with absolute paths.
+        sublayer_name -- a string representing a layer within the file shape store.
+                     Some file formats support to contain several layers, or
+                     at least the ogr library says so.
+                     For those filetypes who don't, the sublayer_name can be ignored
+                     and by default it is None.
+        """
+        self._filename = os.path.abspath(filename)
+        self._sublayer_name = sublayer_name
+
+    def FileName(self):
+        """Return the filename used to open the shapestore.
+
+        The filename can only be set via __init__ method.
+        """
+        return self._filename
+
+    def FileType(self):
+        """Return the filetype.
+
+        The filetype has to be set in all derived classes.
+        It must be string.
+        Known and used types are: "shapefile"
+        """
+        raise NotImplementedError
 
-class ShapefileStore:
+    def SublayerName(self):
+        """Return the sublayer_name.
+
+        This could be None if the shapestore type only supports a single
+        layer.
+        """
+        return self._sublayer_name
+
+    # Design/Implementation note:
+    # It is not a good idea to have a implementation for a
+    # "setBoundingBox" or BoundingBox # in this base class.
+    # In future this data might change during
+    # a Thuban session and thus can not be kept statically here.
+    # It is expected that for many derived classes the bbox must
+    # be retrieved each time anew.
+
+    def BoundingBox(self):
+        """Return the bounding box of the shapes in the shape store.
+
+        The coordinate system used is whatever was used in the shape store.
+        If the shape store is empty, return None.
+        """
+        raise NotImplementedError
+
+class ShapefileStore(FileShapeStore):
 
     """Combine a shapefile and the corresponding DBF file into one object"""
 
     def __init__(self, session, filename):
-        # Make the filename absolute. The filename will be
-        # interpreted relative to that anyway, but when saving a
-        # session we need to compare absolute paths and it's usually
-        # safer to always work with absolute paths.
-        self.filename = os.path.abspath(filename)
+        FileShapeStore.__init__(self, filename)
 
         self.dbftable = table.DBFTable(filename)
-        self.table = ShapeTable(self, session.TransientDB(), self.dbftable)
+        self._table = ShapeTable(self, session.TransientDB(), self.dbftable)
+        self._bbox = None
         self._open_shapefile()
 
     def _open_shapefile(self):
-        self.shapefile = shapelib.ShapeFile(self.filename)
+        self.shapefile = shapelib.ShapeFile(self.FileName())
         self.numshapes, shapetype, mins, maxs = self.shapefile.info()
         if self.numshapes:
-            self.bbox = mins[:2] + maxs[:2]
+            self._bbox = mins[:2] + maxs[:2]
         else:
-            self.bbox = None
+            self._bbox = None
         self.shapetype = shapelib_shapetypes[shapetype]
 
         # estimate a good depth for the quad tree. Each depth multiplies
@@ -149,19 +224,20 @@ class ShapefileStore:
                                          maxdepth)
 
     def Table(self):
-        """Return the table containing the attribute data"""
-        return self.table
+        """Return the table containing the attribute data."""
+        return self._table
 
     def Shapefile(self):
         """Return the shapefile object"""
         return self.shapefile
 
-    def FileName(self):
-        """Return the filename used to open the shapefile"""
-        return self.filename
-
     def FileType(self):
-        """Return the filetype. This is always the string 'shapefile'"""
+        """Return the filetype.
+
+        The filetype has to be set in all derived classes.
+        It must be string.
+        Known and used types are: "shapefile"
+        """
         return "shapefile"
 
     def ShapeType(self):
@@ -194,12 +270,12 @@ class ShapefileStore:
         return None
 
     def BoundingBox(self):
-        """Return the bounding box of the shapes in the shapestore.
+        """Return the bounding box of the shapes in the shape store.
 
-        The coordinate system used is whatever was used in the shapefile.
-        If the shapefile is empty, return None.
+        The coordinate system used is whatever was used in the shape store.
+        If the shape store is empty, return None.
         """
-        return self.bbox
+        return self._bbox
 
     def ShapesInRegion(self, bbox):
         """Return an iterable over the shapes that overlap the bounding box.
@@ -224,7 +300,6 @@ class ShapefileStore:
     def Shape(self, index):
         """Return the shape with index index"""
         return ShapefileShape(self.shapefile, index)
-
 
 
 class DerivedShapeStore:
Index: save.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/Model/save.py,v
retrieving revision 1.43
diff -u -3 -p -r1.43 save.py
--- save.py	28 Jan 2005 15:54:00 -0000	1.43
+++ save.py	26 Apr 2005 13:38:37 -0000
@@ -26,7 +26,7 @@ from Thuban.Model.classification import 
     ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap
 from Thuban.Model.transientdb import AutoTransientTable, TransientJoinedTable
 from Thuban.Model.table import DBFTable, FIELDTYPE_STRING
-from Thuban.Model.data import DerivedShapeStore, ShapefileStore, \
+from Thuban.Model.data import DerivedShapeStore, FileShapeStore, \
                               SHAPETYPE_POINT
 
 from Thuban.Model.xmlwriter import XMLWriter
@@ -201,12 +201,12 @@ class SessionSaver(XMLWriter):
                 continue
 
             idvalue = self.define_id(container)
-            if isinstance(container, ShapefileStore):
+            if isinstance(container, FileShapeStore):
                 self.define_id(container.Table(), idvalue)
                 filename = self.prepare_filename(container.FileName())
                 self.write_element("fileshapesource",
                                    {"id": idvalue, "filename": filename,
-                                    "filetype": "shapefile"})
+                                    "filetype": container.FileType()})
             elif isinstance(container, DerivedShapeStore):
                 shapesource, table = container.Dependencies()
                 self.write_element("derivedshapesource",


More information about the Thuban-devel mailing list

This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)