Mercurial > postarc > postarc
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) + { + + } + } +}