christian@0: /* christian@0: * Postarc christian@0: * christian@0: * Author: christian@0: * Christian Lins christian@0: * christian@0: * Copyright: christian@0: * Copyright (C) 2012 Intevation GmbH christian@0: * christian@0: * This program is free software: you can redistribute it and/or modify christian@0: * it under the terms of the GNU Lesser General Public License as published by christian@0: * the Free Software Foundation, either version 3 of the License, or christian@0: * (at your option) any later version. christian@0: * christian@0: * This program is distributed in the hope that it will be useful, christian@0: * but WITHOUT ANY WARRANTY; without even the implied warranty of christian@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the christian@0: * GNU General Public License for more details. christian@0: * christian@0: * You should have received a copy of the GNU Lesser General Public License christian@0: * along with this program. If not, see . christian@0: */ christian@0: christian@0: using System; christian@0: using System.Collections.Generic; christian@0: using System.Linq; christian@0: using System.Text; christian@0: using ESRI.ArcGIS.Geodatabase; christian@0: using Npgsql; christian@0: using ESRI.ArcGIS.Geometry; christian@0: using System.Diagnostics; christian@0: christian@0: namespace Postarc.Feature christian@0: { christian@0: public class Feature : IFeature, IFeatureBuffer, IRow, IRowBuffer christian@0: { christian@0: protected FeatureClass featureClass; christian@0: protected IFields fields; christian@0: protected object[] row; christian@0: protected IWKTGeometry shape = new Point(); christian@0: christian@0: private int oidIdx = -1; christian@0: christian@0: /// christian@0: /// Constructs a Feature from an existing row in a database table. christian@0: /// christian@0: /// christian@0: /// christian@0: /// christian@0: /// christian@0: public Feature(FeatureClass featureClass, IFields fields, int oidIdx, christian@0: NpgsqlDataReader reader) : this(featureClass, fields, oidIdx) christian@0: { christian@0: this.row = new object[fields.FieldCount]; christian@0: reader.GetValues(this.row); christian@0: LoadShapeFromRow(); christian@0: } christian@0: christian@0: protected Feature(FeatureClass featureClass, IFields fields, int oidIdx) christian@0: { christian@0: this.featureClass = featureClass; christian@0: this.fields = fields; christian@0: this.oidIdx = oidIdx; christian@0: } christian@0: christian@0: protected int ShapeFieldIndex christian@0: { christian@0: get christian@0: { christian@0: return this.fields.FindField(featureClass.ShapeFieldName); christian@0: } christian@0: } christian@0: christian@0: /// christian@0: /// Creates a new feature which is not yet written to a backend. christian@0: /// christian@0: /// christian@0: /// christian@0: /// christian@0: /// christian@0: public Feature(FeatureClass featureClass, IFields fields, int oidIdx, christian@0: object[] row) : this(featureClass, fields, oidIdx) christian@0: { christian@0: this.row = row; christian@0: LoadShapeFromRow(); christian@0: } christian@0: christian@0: protected void LoadShapeFromRow() christian@0: { christian@0: this.shape = new Point(); christian@0: int shpIdx = ShapeFieldIndex; christian@0: if (shpIdx >= 0 && row[ShapeFieldIndex] != null) christian@0: { christian@0: this.shape.SetWKT(row[ShapeFieldIndex] as string); christian@0: } christian@0: } christian@0: christian@0: public IObjectClass Class christian@0: { christian@0: get { throw new NotImplementedException(); } christian@0: } christian@0: christian@0: public void Delete() christian@0: { christian@0: // TODO: Not implemented christian@0: } christian@0: christian@0: public IEnvelope Extent christian@0: { christian@0: get christian@0: { christian@0: return this.Shape.Envelope; christian@0: } christian@0: } christian@0: christian@0: public esriFeatureType FeatureType christian@0: { christian@0: get christian@0: { christian@0: return this.featureClass.FeatureType; christian@0: } christian@0: } christian@0: christian@0: public IFields Fields christian@0: { christian@0: get christian@0: { christian@0: return this.fields; christian@0: } christian@0: } christian@0: christian@0: public bool HasOID christian@0: { christian@0: get christian@0: { christian@0: return oidIdx >= 0; christian@0: } christian@0: } christian@0: christian@0: public int OID christian@0: { christian@0: get christian@0: { christian@0: if (oidIdx >= 0) christian@0: { christian@0: int oid = Convert.ToInt32(this.row[oidIdx]); christian@0: return oid; christian@0: } christian@0: else christian@0: { christian@0: return -1; christian@0: } christian@0: } christian@0: } christian@0: christian@0: public IGeometry Shape christian@0: { christian@0: get christian@0: { christian@0: return this.shape as IGeometry; christian@0: } christian@0: set christian@0: { christian@0: this.shape = value as IWKTGeometry; christian@0: } christian@0: } christian@0: christian@0: public IGeometry ShapeCopy christian@0: { christian@0: get { throw new NotImplementedException(); } christian@0: } christian@0: christian@0: /// christian@0: /// Writes the row to the backend. From IRow interface. christian@0: /// christian@0: public void Store() christian@0: { christian@0: StringBuilder sql = new StringBuilder(); christian@0: NpgsqlConnection conn = featureClass.PostGISConnection.Open(); christian@0: NpgsqlCommand cmd; christian@0: christian@0: if (OID > 0) christian@0: { // Update existing row christian@0: sql.Append("UPDATE "); christian@0: sql.Append(featureClass.TableName); christian@0: sql.Append(" SET "); christian@0: for (int n = 0; n < this.row.Length; n++) christian@0: { christian@0: if (n != this.oidIdx) christian@0: { christian@0: sql.Append(Fields.get_Field(n).Name); christian@0: sql.Append(" = '"); christian@0: if (n == featureClass.ShapeFieldIndex) christian@0: sql.Append(shape.GetWKT()); christian@0: else christian@0: sql.Append(this.row[n]); christian@0: sql.Append("',"); christian@0: } christian@0: } christian@0: sql.Replace(',',' ', sql.Length - 1, 1); christian@0: sql.Append(" WHERE "); christian@0: sql.Append(FeatureCursor.POSTARC_OID_COLUMN); christian@0: sql.Append(" = "); christian@0: sql.Append(OID); christian@0: } christian@0: else christian@0: { // Create new row christian@0: sql.Append("INSERT INTO "); christian@0: sql.Append(featureClass.TableName); christian@0: sql.Append(" ("); christian@0: for (int n = 0; n < this.row.Length; n++) christian@0: { christian@0: if (n == this.oidIdx) christian@0: sql.Append(FeatureCursor.POSTARC_OID_COLUMN); christian@0: else christian@0: sql.Append(Fields.get_Field(n).Name); christian@0: christian@0: if (n != Fields.FieldCount - 1) christian@0: sql.Append(","); christian@0: } christian@0: sql.Append(" ) SELECT "); christian@0: for (int n = 0; n < this.row.Length; n++) christian@0: { christian@0: if (n == this.oidIdx) christian@0: { christian@0: sql.Append("Max("); christian@0: sql.Append(FeatureCursor.POSTARC_OID_COLUMN); christian@0: sql.Append(") + 1"); christian@0: } christian@0: else christian@0: { christian@0: sql.Append("'"); christian@0: if (n == featureClass.ShapeFieldIndex) christian@0: { christian@0: sql.Append(shape.GetWKT()); christian@0: } christian@0: else christian@0: { christian@0: sql.Append(this.row[n]); christian@0: } christian@0: sql.Append("'"); christian@0: } christian@0: if (n != Fields.FieldCount - 1) christian@0: sql.Append(","); christian@0: } christian@0: sql.Append(" FROM "); christian@0: sql.Append(featureClass.TableName); christian@0: } christian@0: christian@0: cmd = new NpgsqlCommand(sql.ToString(), conn); christian@0: int updatedRows = cmd.ExecuteNonQuery(); christian@0: conn.Close(); christian@0: Debug.WriteLine("Feature::Store: " + updatedRows + " rows affected"); christian@0: } christian@0: christian@0: public ITable Table christian@0: { christian@0: get christian@0: { christian@0: return this.featureClass; christian@0: } christian@0: } christian@0: christian@0: public object get_Value(int index) christian@0: { christian@0: Debug.WriteLine("Feature::get_Value(" + index + "): " christian@0: + (row[index] != null ? row[index].GetType() + " " + row[index].ToString() : "")); christian@0: christian@0: if (index == featureClass.ShapeFieldIndex) christian@0: { christian@0: return this.Shape; christian@0: } christian@0: else christian@0: { christian@0: return this.row[index]; christian@0: } christian@0: } christian@0: christian@0: public void set_Value(int index, object value) christian@0: { christian@0: Debug.WriteLine("Feature::set_Value(" + index + ", " + value + ")"); christian@0: this.row[index] = value; christian@0: } christian@0: } christian@0: }