diff Postarc/Postarc/Feature/FeatureClass.cs @ 0:1aca3d413885 tip

Initial import of Postarc
author Christian Lins <christian.lins@intevation.de>
date Fri, 05 Oct 2012 23:55:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Postarc/Postarc/Feature/FeatureClass.cs	Fri Oct 05 23:55:06 2012 +0200
@@ -0,0 +1,1084 @@
+/*
+ * Postarc
+ *
+ * Author:
+ * Christian Lins <christian.lins@intevation.de>
+ *
+ * Copyright:
+ * Copyright (C) 2012 Intevation GmbH <http://www.intevation.de/>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ESRI.ArcGIS.Geodatabase;
+using ESRI.ArcGIS.Geometry;
+using ESRI.ArcGIS.esriSystem;
+using Npgsql;
+using NpgsqlTypes;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using Postarc.Geodatabase;
+
+namespace Postarc.Feature
+{
+    [Guid("77FB1E58-69A9-4bac-AFB6-76F0F85D3B75"), ClassInterface(ClassInterfaceType.None)]
+    public class FeatureClass :
+        IDataset, IDatasetEdit, IDatasetEditInfo,
+        IFeatureClass, 
+        IGeoDataset,
+        //IModelInfo,
+        ISchemaLock,
+        ISubtypes,
+        ITable /* inherits IClass */, ITableCapabilities,
+        ITopology,
+        IValidation, IValidation2
+    {
+        private string browseName = "BrowseName";
+        private string clsid = "{77FB1E58-69A9-4bac-AFB6-76F0F85D3B75}";
+        private IFields fields = new FieldsClass();
+        private string shapeFieldName = "shape";
+        private esriGeometryType shapeType = esriGeometryType.esriGeometryPoint;
+
+        protected PostGISConnection connection;
+        protected ISpatialReference spatialReference = FeatureLayer.CreateGeographicSpatialReference();
+        protected string tableName;
+        protected Workspace workspace = new Workspace();
+
+        internal PostGISConnection PostGISConnection
+        {
+            get
+            {
+                return this.connection;
+            }
+        }
+
+        /// <summary>
+        /// Name of the PostGIS table behind this FeatureClass.
+        /// </summary>
+        internal string TableName
+        {
+            get
+            {
+                return this.tableName;
+            }
+        }
+
+        public FeatureClass(esriGeometryType shapeType)
+        {
+            this.shapeType = shapeType;
+
+            IFieldEdit field = new FieldClass();
+            field.Name_2 = "OID";
+            field.Type_2 = esriFieldType.esriFieldTypeOID;
+            AddField(field);
+
+            field = new FieldClass();
+            field.Name_2 = ShapeFieldName;
+            field.Type_2 = esriFieldType.esriFieldTypeGeometry;
+            AddField(field as IField);
+
+            field = new FieldClass();
+            field.Name_2 = "test";
+            field.Type_2 = esriFieldType.esriFieldTypeInteger;
+            //    AddField(field as IField);
+        }
+
+        public FeatureClass(PostGISConnection conn, string tableName)
+        {
+            this.connection = conn;
+            this.tableName = tableName;
+
+            LoadFieldDefinitionFromTable();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        protected internal int NextOID()
+        {
+            NpgsqlConnection conn = this.connection.Open();
+            NpgsqlCommand cmd = new NpgsqlCommand(
+                "SELECT Max(" + FeatureCursor.POSTARC_OID_COLUMN + ") FROM " + tableName, conn);
+            int maxOID = Convert.ToInt32(cmd.ExecuteScalar());
+            conn.Close();
+            return maxOID + 1;
+        }
+
+        protected internal void LoadFieldDefinitionFromTable()
+        {
+            NpgsqlConnection conn = this.connection.Open();
+
+            NpgsqlCommand cmd = new NpgsqlCommand("SELECT * FROM " + tableName + " LIMIT 1", conn);
+            NpgsqlDataReader cur = cmd.ExecuteReader();
+            for (int n = 0; n < cur.FieldCount; n++)
+            {
+                NpgsqlDbType type = cur.GetFieldNpgsqlDbType(n);
+                string name = cur.GetName(n);
+                if (name.Equals(FeatureCursor.POSTARC_OID_COLUMN, StringComparison.OrdinalIgnoreCase))
+                {
+                    name = FeatureCursor.ARCGIS_OID_COLUMN;
+                    AddField(name, type, true);
+                }
+                else if (name.Equals(FeatureCursor.POSTARC_SHAPE_COLUMN, StringComparison.OrdinalIgnoreCase))
+                {
+                    type = NpgsqlDbType.Point;
+                    AddField(name, type);
+                }
+                else
+                {
+                    AddField(name, type);
+                }
+            }
+            conn.Close();
+        }
+
+        protected void AddField(string name, NpgsqlDbType type, bool isOID = false)
+        {
+            esriFieldType esriType = esriFieldType.esriFieldTypeBlob;
+            switch (type)
+            {
+                case NpgsqlDbType.Bigint:
+                case NpgsqlDbType.Integer:
+                    if (isOID)
+                    {
+                        esriType = esriFieldType.esriFieldTypeOID;
+                        AddField(name, esriType, false);
+                    }
+                    else
+                    {
+                        esriType = esriFieldType.esriFieldTypeInteger;
+                        AddField(name, esriType);
+                    }
+                    break;
+                case NpgsqlDbType.Point:
+                    esriType = esriFieldType.esriFieldTypeGeometry;
+                    this.shapeType = esriGeometryType.esriGeometryPoint;
+                    this.shapeFieldName = name;
+                    AddField(name, esriType, true, true);
+                    break;
+                case NpgsqlDbType.Varchar:
+                    esriType = esriFieldType.esriFieldTypeString;
+                    AddField(name, esriType, true, false, 255);
+                    break;
+            }
+        }
+
+        protected void AddField(
+            string name,
+            esriFieldType type,
+            bool editable = true,
+            bool isGeometry = false,
+            int length = 4)
+        {
+            IFieldEdit field = new FieldClass();
+            field.Name_2 = name;
+            field.Type_2 = type;
+            field.AliasName_2 = name;
+            field.Editable_2 = editable;
+            if (isGeometry)
+            {
+                field.GeometryDef_2 = new Point() as IGeometryDef;
+                Debug.Assert(field.GeometryDef != null);
+            }
+            field.Length_2 = length;
+            AddField(field as IField);
+        }
+
+        public void AddField(IField field)
+        {
+            IFieldsEdit fields = this.fields as IFieldsEdit;
+            fields.AddField(field);
+        }
+
+        public void AddIndex(IIndex Index)
+        {
+
+        }
+
+        public string AliasName
+        {
+            get
+            {
+                return "AliasName";
+            }
+        }
+
+        public IField AreaField
+        {
+            get
+            {
+                return null; // null is correct when ShapeType is point
+            }
+        }
+
+        public UID CLSID
+        {
+            get
+            {
+                UID uid = new UID();
+                uid.Value = clsid;
+                return uid;
+            }
+        }
+
+        /// <summary>
+        /// Calls CreateFeatureBuffer()
+        /// </summary>
+        /// <returns></returns>
+        public IFeature CreateFeature()
+        {
+            Debug.WriteLine("PostGISFeatureClass::CreateFeature()");
+            return CreateFeatureBuffer() as IFeature;
+        }
+
+        /// <summary>
+        /// Creates a new Postarc.Feature.Feature instance as IFeatureBuffer.
+        /// </summary>
+        /// <returns></returns>
+        public IFeatureBuffer CreateFeatureBuffer()
+        {
+            Debug.WriteLine("PostGISFeatureClass::CreateFeatureBuffer()");
+            int oidIdx = fields.FindField(FeatureCursor.ARCGIS_OID_COLUMN);
+            object[] row = new object[fields.FieldCount];
+            row[oidIdx] = NextOID();
+            return new Feature(this, fields, oidIdx, row);
+        }
+
+        public void DeleteField(IField Field)
+        {
+
+        }
+
+        public void DeleteIndex(IIndex Index)
+        {
+
+        }
+
+        public ESRI.ArcGIS.esriSystem.UID EXTCLSID
+        {
+            get
+            {
+                return null;
+            }
+        }
+
+        public object Extension
+        {
+            get
+            {
+                return new DummyClassExtension() as IClassExtension;
+            }
+        }
+
+        public IPropertySet ExtensionProperties
+        {
+            get
+            {
+                Debug.WriteLine("PostGISFeatureClass::ExtensionProperties");
+                return new PropertySetClass();
+            }
+        }
+
+        public int FeatureClassID
+        {
+            get
+            {
+                return GetHashCode(); // TODO: Return unique ID for this feature class
+            }
+        }
+
+        public int FeatureCount(IQueryFilter QueryFilter)
+        {
+            NpgsqlConnection conn = this.connection.Open();
+            NpgsqlCommand cmd = new NpgsqlCommand("SELECT Count(*) FROM " + tableName, conn);
+            int cnt = Convert.ToInt32(cmd.ExecuteScalar());
+            conn.Close();
+            return cnt;
+        }
+
+        public IFeatureDataset FeatureDataset
+        {
+            get
+            {
+                return new Postarc.Geodatabase.FeatureDataset(this);
+            }
+        }
+
+        public esriFeatureType FeatureType
+        {
+            get
+            {
+                return esriFeatureType.esriFTSimple;
+            }
+        }
+
+        public IFields Fields
+        {
+            get
+            {
+                return fields;
+            }
+        }
+
+        public int FindField(string Name)
+        {
+            return this.fields.FindField(Name);
+        }
+
+        public IFeature GetFeature(int oid)
+        {
+            QueryFilterClass filter = new QueryFilterClass();
+            filter.WhereClause = "OID in (" + oid + ")";
+            IFeatureCursor cur = Search(filter, false);
+            return cur.NextFeature();
+        }
+
+        public IFeatureCursor GetFeatures(object fids, bool recycling)
+        {
+            QueryFilterClass filter = new QueryFilterClass();
+            StringBuilder buf = new StringBuilder();
+            buf.Append(FeatureCursor.POSTARC_OID_COLUMN);
+            buf.Append(" in (");
+            int[] oids = (int[])fids;
+            for (int n = 0; n < oids.Length; n++)
+            {
+                buf.Append(oids[n]);
+                if (n != oids.Length - 1)
+                    buf.Append(",");
+            }
+            buf.Append(")");
+            filter.WhereClause = buf.ToString();
+
+            return new FeatureCursor(this, this.connection, filter);
+        }
+
+        public bool HasOID
+        {
+            get
+            {
+                return true;
+            }
+        }
+
+        public IIndexes Indexes
+        {
+            get
+            {
+                return null;
+            }
+        }
+
+        public IFeatureCursor Insert(bool useBuffering)
+        {
+            return null;
+        }
+
+        ICursor ITable.Insert(bool useBuffering)
+        {
+            return null;
+        }
+
+        public IField LengthField
+        {
+            get
+            {
+                return null;
+            }
+        }
+
+        public string OIDFieldName
+        {
+            get
+            {
+                return "OID";
+            }
+        }
+
+        public int ObjectClassID
+        {
+            get
+            {
+                return -1;
+            }
+        }
+
+        public IFeatureCursor Search(IQueryFilter filter, bool recycling)
+        {
+            return new FeatureCursor(this, this.connection, filter);
+        }
+
+        ICursor ITable.Search(IQueryFilter filter, bool recycling)
+        {
+            return Search(filter, recycling) as ICursor;
+        }
+
+        public ISelectionSet Select(
+            IQueryFilter queryFilter, 
+            esriSelectionType selType, 
+            esriSelectionOption selOption, 
+            IWorkspace selectionContainer)
+        {
+            Postarc.Geodatabase.SelectionSet sel = new Postarc.Geodatabase.SelectionSet(this);
+            IFeatureCursor cur = Search(queryFilter, false);
+            IFeature feature;
+            while ((feature = cur.NextFeature()) != null)
+            {
+                sel.Add(feature.OID);
+            }
+            //return sel as ISelectionSet;
+            return null;
+        }
+
+        public string ShapeFieldName
+        {
+            get
+            {
+                return this.shapeFieldName;
+            }
+        }
+
+        internal int ShapeFieldIndex
+        {
+            get
+            {
+                return Fields.FindField(shapeFieldName);
+            }
+        }
+
+        public esriGeometryType ShapeType
+        {
+            get
+            {
+                return this.shapeType;
+            }
+        }
+
+        public IFeatureCursor Update(IQueryFilter filter, bool recycling)
+        {
+            return null;
+        }
+
+        ICursor ITable.Update(IQueryFilter filter, bool recycling)
+        {
+            return null;
+        }
+
+        public IEnumRelationshipClass get_RelationshipClasses(esriRelRole role)
+        {
+            Debug.WriteLine("FeatureClass::get_RelationshipClasses(): FIXME");
+            return null; // TODO: ?
+        }
+
+        public string BrowseName
+        {
+            get
+            {
+                return this.browseName;
+            }
+            set
+            {
+                this.browseName = value;
+            }
+        }
+
+        public bool CanCopy()
+        {
+            return false;
+        }
+
+        public bool CanDelete()
+        {
+            return false;
+        }
+
+        public bool CanRename()
+        {
+            return false;
+        }
+
+        public string Category
+        {
+            get
+            {
+                return "PostGIS";
+            }
+        }
+
+        public IDataset Copy(string copyName, IWorkspace copyWorkspace)
+        {
+            return null;
+        }
+
+        public void Delete()
+        {
+
+        }
+
+        public IName FullName
+        {
+            get
+            {
+                return new FeatureClassName();
+            }
+        }
+
+        public string Name
+        {
+            get
+            {
+                return "PostGIS FeatureClass";
+            }
+        }
+
+        public IPropertySet PropertySet
+        {
+            get
+            {
+                return null;
+            }
+        }
+
+        public void Rename(string name)
+        {
+        }
+
+        public IEnumDataset Subsets
+        {
+            get
+            {
+                return null;
+            }
+        }
+
+        public esriDatasetType Type
+        {
+            get
+            {
+                return esriDatasetType.esriDTFeatureClass;
+            }
+        }
+
+        /// <summary>
+        /// Returns the associated Postarc.Feature.Workspace instance of this
+        /// FeatureClass.
+        /// </summary>
+        public IWorkspace Workspace
+        {
+            get
+            {
+                return this.workspace as IWorkspace;
+            }
+        }
+
+        /// <summary>
+        /// From IDatasetEdit
+        /// </summary>
+        /// <returns></returns>
+        public bool IsBeingEdited()
+        {
+            return this.workspace.IsBeingEdited();
+        }
+
+        public void AlterAliasName(string Name)
+        {
+
+        }
+
+        public void AlterClassExtensionCLSID(UID ClassExtensionCLSID, IPropertySet classExtensionProperties)
+        {
+
+        }
+
+        public void AlterDefaultValue(string FieldName, object Value)
+        {
+
+        }
+
+        public void AlterDomain(string FieldName, IDomain Domain)
+        {
+
+        }
+
+        public void AlterFieldAliasName(string FieldName, string AliasName)
+        {
+
+        }
+
+        public void AlterFieldModelName(string FieldName, string ModelName)
+        {
+
+        }
+
+        public void AlterInstanceCLSID(UID InstanceCLSID)
+        {
+
+        }
+
+        public void AlterModelName(string Name)
+        {
+
+        }
+
+        public int RegisterAsObjectClass(string suggestedOIDFieldName, string configKeyword)
+        {
+            return 0; // FIXME
+        }
+
+
+        public void AlterClassExtensionProperties(IPropertySet classExtensionProperties)
+        {
+
+        }
+
+        public void AddGlobalID(string FieldName)
+        {
+
+        }
+
+        public void DeleteGlobalID()
+        {
+
+        }
+
+        /*        public int AllowableComponents
+                {
+                    get
+                    {
+                        return 0; // FIXME
+                    }
+                }
+
+                public void Analyze(int tableComponents)
+                {
+
+                }*/
+
+        public bool CanEdit
+        {
+            get
+            {
+                // TODO: Check for write access to PostGIS table
+                return true;
+            }
+        }
+
+
+        public bool CanRedo
+        {
+            get
+            {
+                return false;
+            }
+        }
+
+        public bool CanUndo
+        {
+            get
+            {
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// IFeatureClassLoad.LoadOnlyMode: Indicates if the featureclass is in load only mode. 
+        /// </summary>
+        /*public bool LoadOnlyMode
+        {
+            get
+            {
+                return true; //FIXME
+            }
+            set
+            {
+
+            }
+        }*/
+
+        /*
+        public void UpdateExtent()
+        {
+
+        }*/
+
+        /*
+        public void RemoveFeature(IFeature Feature)
+        {
+
+        }
+
+        public void RemoveFeatures(ISet features)
+        {
+
+        }
+
+        public void WriteFeature(IFeature Feature)
+        {
+
+        }
+
+        public void WriteFeatures(ISet features)
+        {
+
+        }*/
+
+        public IEnvelope Extent
+        {
+            get
+            {
+                IPoint point = new PointClass();
+                point.PutCoords(0, 0);
+                ITopologicalOperator topOp = point as ITopologicalOperator;
+                IGeometry buf = topOp.Buffer(100);
+                return buf.Envelope;
+            }
+        }
+
+        public ISpatialReference SpatialReference
+        {
+            get
+            {
+                return spatialReference;
+            }
+        }
+
+
+        /*public IGeodataXform GeodataXform
+        {
+            get
+            {
+                return null; //FIXME
+            }
+        }
+
+        public IEnvelope NativeExtent
+        {
+            get
+            {
+                return null;  //FIXME
+            }
+        }
+
+        public ISpatialReference NativeSpatialReference
+        {
+            get
+            {
+                return null; // FIXME
+            }
+        }*/
+
+        public string ModelName
+        {
+            get
+            {
+                return "ModelName"; //FIXME
+            }
+            set
+            {
+
+            }
+        }
+
+
+        public IGeometricNetwork GeometricNetwork
+        {
+            get
+            {
+                return null; // FIXME
+            }
+        }
+
+        public esriNetworkClassAncillaryRole NetworkAncillaryRole
+        {
+            get
+            {
+                return esriNetworkClassAncillaryRole.esriNCARNone;  //FIXME
+            }
+        }
+
+        public int get_FieldToWeightMapping(int FieldIndex)
+        {
+            return 0;//FIXME
+        }
+
+        public bool CanBypassStoreMethod()
+        {
+            return false;
+        }
+
+        public bool CanBypassEditSession()
+        {
+            return false;
+        }
+
+        public void ChangeSchemaLock(esriSchemaLock schemaLock)
+        {
+
+        }
+
+        public void GetCurrentSchemaLocks(out IEnumSchemaLockInfo schemaLockInfo)
+        {
+            schemaLockInfo = null; // FIXME
+        }
+
+        public void AddSubtype(int SubtypeCode, string SubtypeName)
+        {
+
+        }
+
+        public int DefaultSubtypeCode
+        {
+            get
+            {
+                return 0; //FIXME
+            }
+            set
+            {
+
+            }
+        }
+
+        public void DeleteSubtype(int SubtypeCode)
+        {
+
+        }
+
+        public bool HasSubtype
+        {
+            get
+            {
+                return false;
+            }
+        }
+
+        public int SubtypeFieldIndex
+        {
+            get
+            {
+                Debug.WriteLine("FeatureClass::SubtypeFieldIndex::get");
+                return 0;  //FIXME
+            }
+        }
+
+        public string SubtypeFieldName
+        {
+            get
+            {
+                return "";
+            }
+            set
+            {
+
+            }
+        }
+
+        public IEnumSubtype Subtypes
+        {
+            get
+            {
+                Debug.WriteLine("FeatureClass::Subtypes(): FIXME");
+                return null; //FIXME
+            }
+        }
+
+        public object get_DefaultValue(int subtypeCode, string fieldName)
+        {
+            return null; // FIXME
+        }
+
+        public IDomain get_Domain(int subtypeCode, string fieldName)
+        {
+            Debug.WriteLine("FeatureClass::get_Domain(): FIXME " + fieldName);
+            return null;  //FIXME
+        }
+
+        public string get_SubtypeName(int subtypeCode)
+        {
+            return ""; //FIXME
+        }
+
+        public void set_DefaultValue(int ubtypeCode, string fieldName, object value)
+        {
+
+        }
+
+        public void set_Domain(int ubtypeCode, string fieldName, IDomain domain)
+        {
+
+        }
+
+        public IRow CreateRow()
+        {
+            Debug.WriteLine("PostGISFeatureClass::CreateRow()");
+            return CreateRowBuffer() as IRow;
+        }
+
+        public IRowBuffer CreateRowBuffer()
+        {
+            Debug.WriteLine("PostGISFeatureClass::CreateRowBuffer()");
+            return CreateFeature() as IRowBuffer;
+        }
+
+        public void DeleteSearchedRows(IQueryFilter queryFilter)
+        {
+
+        }
+
+        public IRow GetRow(int oid)
+        {
+            Debug.WriteLine("PostGISFeatureClass::GetRow");
+            ICursor cur = GetRows(new int[] { oid }, false);
+            return cur.NextRow();
+        }
+
+        public ICursor GetRows(object oids_obj, bool recycling)
+        {
+            Debug.WriteLine("PostGISFeatureClass::GetRows");
+            return (ICursor)GetFeatures(oids_obj, recycling);
+        }
+
+        public int RowCount(IQueryFilter queryFilter)
+        {
+            return FeatureCount(queryFilter);
+        }
+
+        public void UpdateSearchedRows(IQueryFilter queryFilter, IRowBuffer buffer)
+        {
+
+        }
+
+        /// <summary>
+        /// From ITableCapabilities
+        /// </summary>
+        public bool CanSelect
+        {
+            get
+            {
+                return true;
+            }
+        }
+
+        public void AddClass(IClass classToAdd, double Weight, int XYRank, int ZRank, bool EventNotificationOnValidate)
+        {
+
+        }
+
+        public ITopologyGraph Cache
+        {
+            get
+            {
+                return null; //FIXME
+            }
+        }
+
+        public double ClusterTolerance
+        {
+            get
+            {
+                return 0.0001; // FIXME
+            }
+        }
+
+        public int MaximumGeneratedErrorCount
+        {
+            get
+            {
+                return 0; // FIXME
+            }
+        }
+
+        public void RemoveClass(IClass classToRemove)
+        {
+
+        }
+
+        public esriTopologyState State
+        {
+            get
+            {
+                return esriTopologyState.esriTSUnanalyzed; // FIXME
+            }
+        }
+
+        public int TopologyID
+        {
+            get
+            {
+                return 0;  //FIXME
+            }
+        }
+
+        public IEnvelope ValidateTopology(IEnvelope areaToValidate)
+        {
+            return null; //FIXME
+        }
+
+        public IPolygon get_DirtyArea(IPolygon location)
+        {
+            return null; //FIXME
+        }
+
+        public void AddRule(IRule Rule)
+        {
+
+        }
+
+        public void DeleteRule(IRule Rule)
+        {
+
+        }
+
+        public IEnumRule Rules
+        {
+            get
+            {
+                return null; // FIXME
+            }
+        }
+
+        public ISelectionSet Validate(IQueryFilter Selection, IWorkspace Workspace)
+        {
+            return null;
+        }
+
+        public ISelectionSet ValidateSelection(ISelectionSet Selection, IWorkspace Workspace)
+        {
+            return null; // FIXME
+        }
+
+        public ISet ValidateSet(ISet Selection)
+        {
+            return null;
+        }
+
+        public IEnumRule get_RulesByField(string FieldName)
+        {
+            return null;
+        }
+
+        public IEnumRule get_RulesBySubtypeCode(int SubtypeCode)
+        {
+            return null;
+        }
+
+        public void AlterRule(IRule Rule)
+        {
+
+        }
+    }
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)