Introduce FileShapeStore

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


On Tue, Apr 26, 2005 at 03:49:26PM +0200, Bernhard Herzog wrote:
> Jan-Oliver Wagner <jan at intevation.de> writes:
> 
> > +class ShapefileStore(FileShapeStore):
> >  
> [...]
> >      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"
> > +        """
> 
> Why did you copy the doc-string from the base class where it describes
> the abstract purpose of the method to a specific implementation?  Now
> the doc-string of the specific implementation doesn't say anything about
> that particular implementation anymore.  The original doc-string would
> have been just fine, IMO.

that was not intentionally.
Here is round number 4.

	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:54:12 -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
+
+    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:
+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,17 +224,13 @@ 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 "shapefile"
@@ -194,12 +265,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 +295,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:54:12 -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)