comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:1aca3d413885
1 /*
2 * Postarc
3 *
4 * Author:
5 * Christian Lins <christian.lins@intevation.de>
6 *
7 * Copyright:
8 * Copyright (C) 2012 Intevation GmbH <http://www.intevation.de/>
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 using System;
25 using System.Collections.Generic;
26 using System.Linq;
27 using System.Text;
28 using ESRI.ArcGIS.Geodatabase;
29 using ESRI.ArcGIS.Geometry;
30 using ESRI.ArcGIS.esriSystem;
31 using Npgsql;
32 using NpgsqlTypes;
33 using System.Runtime.InteropServices;
34 using System.Diagnostics;
35 using Postarc.Geodatabase;
36
37 namespace Postarc.Feature
38 {
39 [Guid("77FB1E58-69A9-4bac-AFB6-76F0F85D3B75"), ClassInterface(ClassInterfaceType.None)]
40 public class FeatureClass :
41 IDataset, IDatasetEdit, IDatasetEditInfo,
42 IFeatureClass,
43 IGeoDataset,
44 //IModelInfo,
45 ISchemaLock,
46 ISubtypes,
47 ITable /* inherits IClass */, ITableCapabilities,
48 ITopology,
49 IValidation, IValidation2
50 {
51 private string browseName = "BrowseName";
52 private string clsid = "{77FB1E58-69A9-4bac-AFB6-76F0F85D3B75}";
53 private IFields fields = new FieldsClass();
54 private string shapeFieldName = "shape";
55 private esriGeometryType shapeType = esriGeometryType.esriGeometryPoint;
56
57 protected PostGISConnection connection;
58 protected ISpatialReference spatialReference = FeatureLayer.CreateGeographicSpatialReference();
59 protected string tableName;
60 protected Workspace workspace = new Workspace();
61
62 internal PostGISConnection PostGISConnection
63 {
64 get
65 {
66 return this.connection;
67 }
68 }
69
70 /// <summary>
71 /// Name of the PostGIS table behind this FeatureClass.
72 /// </summary>
73 internal string TableName
74 {
75 get
76 {
77 return this.tableName;
78 }
79 }
80
81 public FeatureClass(esriGeometryType shapeType)
82 {
83 this.shapeType = shapeType;
84
85 IFieldEdit field = new FieldClass();
86 field.Name_2 = "OID";
87 field.Type_2 = esriFieldType.esriFieldTypeOID;
88 AddField(field);
89
90 field = new FieldClass();
91 field.Name_2 = ShapeFieldName;
92 field.Type_2 = esriFieldType.esriFieldTypeGeometry;
93 AddField(field as IField);
94
95 field = new FieldClass();
96 field.Name_2 = "test";
97 field.Type_2 = esriFieldType.esriFieldTypeInteger;
98 // AddField(field as IField);
99 }
100
101 public FeatureClass(PostGISConnection conn, string tableName)
102 {
103 this.connection = conn;
104 this.tableName = tableName;
105
106 LoadFieldDefinitionFromTable();
107 }
108
109 /// <summary>
110 ///
111 /// </summary>
112 /// <returns></returns>
113 protected internal int NextOID()
114 {
115 NpgsqlConnection conn = this.connection.Open();
116 NpgsqlCommand cmd = new NpgsqlCommand(
117 "SELECT Max(" + FeatureCursor.POSTARC_OID_COLUMN + ") FROM " + tableName, conn);
118 int maxOID = Convert.ToInt32(cmd.ExecuteScalar());
119 conn.Close();
120 return maxOID + 1;
121 }
122
123 protected internal void LoadFieldDefinitionFromTable()
124 {
125 NpgsqlConnection conn = this.connection.Open();
126
127 NpgsqlCommand cmd = new NpgsqlCommand("SELECT * FROM " + tableName + " LIMIT 1", conn);
128 NpgsqlDataReader cur = cmd.ExecuteReader();
129 for (int n = 0; n < cur.FieldCount; n++)
130 {
131 NpgsqlDbType type = cur.GetFieldNpgsqlDbType(n);
132 string name = cur.GetName(n);
133 if (name.Equals(FeatureCursor.POSTARC_OID_COLUMN, StringComparison.OrdinalIgnoreCase))
134 {
135 name = FeatureCursor.ARCGIS_OID_COLUMN;
136 AddField(name, type, true);
137 }
138 else if (name.Equals(FeatureCursor.POSTARC_SHAPE_COLUMN, StringComparison.OrdinalIgnoreCase))
139 {
140 type = NpgsqlDbType.Point;
141 AddField(name, type);
142 }
143 else
144 {
145 AddField(name, type);
146 }
147 }
148 conn.Close();
149 }
150
151 protected void AddField(string name, NpgsqlDbType type, bool isOID = false)
152 {
153 esriFieldType esriType = esriFieldType.esriFieldTypeBlob;
154 switch (type)
155 {
156 case NpgsqlDbType.Bigint:
157 case NpgsqlDbType.Integer:
158 if (isOID)
159 {
160 esriType = esriFieldType.esriFieldTypeOID;
161 AddField(name, esriType, false);
162 }
163 else
164 {
165 esriType = esriFieldType.esriFieldTypeInteger;
166 AddField(name, esriType);
167 }
168 break;
169 case NpgsqlDbType.Point:
170 esriType = esriFieldType.esriFieldTypeGeometry;
171 this.shapeType = esriGeometryType.esriGeometryPoint;
172 this.shapeFieldName = name;
173 AddField(name, esriType, true, true);
174 break;
175 case NpgsqlDbType.Varchar:
176 esriType = esriFieldType.esriFieldTypeString;
177 AddField(name, esriType, true, false, 255);
178 break;
179 }
180 }
181
182 protected void AddField(
183 string name,
184 esriFieldType type,
185 bool editable = true,
186 bool isGeometry = false,
187 int length = 4)
188 {
189 IFieldEdit field = new FieldClass();
190 field.Name_2 = name;
191 field.Type_2 = type;
192 field.AliasName_2 = name;
193 field.Editable_2 = editable;
194 if (isGeometry)
195 {
196 field.GeometryDef_2 = new Point() as IGeometryDef;
197 Debug.Assert(field.GeometryDef != null);
198 }
199 field.Length_2 = length;
200 AddField(field as IField);
201 }
202
203 public void AddField(IField field)
204 {
205 IFieldsEdit fields = this.fields as IFieldsEdit;
206 fields.AddField(field);
207 }
208
209 public void AddIndex(IIndex Index)
210 {
211
212 }
213
214 public string AliasName
215 {
216 get
217 {
218 return "AliasName";
219 }
220 }
221
222 public IField AreaField
223 {
224 get
225 {
226 return null; // null is correct when ShapeType is point
227 }
228 }
229
230 public UID CLSID
231 {
232 get
233 {
234 UID uid = new UID();
235 uid.Value = clsid;
236 return uid;
237 }
238 }
239
240 /// <summary>
241 /// Calls CreateFeatureBuffer()
242 /// </summary>
243 /// <returns></returns>
244 public IFeature CreateFeature()
245 {
246 Debug.WriteLine("PostGISFeatureClass::CreateFeature()");
247 return CreateFeatureBuffer() as IFeature;
248 }
249
250 /// <summary>
251 /// Creates a new Postarc.Feature.Feature instance as IFeatureBuffer.
252 /// </summary>
253 /// <returns></returns>
254 public IFeatureBuffer CreateFeatureBuffer()
255 {
256 Debug.WriteLine("PostGISFeatureClass::CreateFeatureBuffer()");
257 int oidIdx = fields.FindField(FeatureCursor.ARCGIS_OID_COLUMN);
258 object[] row = new object[fields.FieldCount];
259 row[oidIdx] = NextOID();
260 return new Feature(this, fields, oidIdx, row);
261 }
262
263 public void DeleteField(IField Field)
264 {
265
266 }
267
268 public void DeleteIndex(IIndex Index)
269 {
270
271 }
272
273 public ESRI.ArcGIS.esriSystem.UID EXTCLSID
274 {
275 get
276 {
277 return null;
278 }
279 }
280
281 public object Extension
282 {
283 get
284 {
285 return new DummyClassExtension() as IClassExtension;
286 }
287 }
288
289 public IPropertySet ExtensionProperties
290 {
291 get
292 {
293 Debug.WriteLine("PostGISFeatureClass::ExtensionProperties");
294 return new PropertySetClass();
295 }
296 }
297
298 public int FeatureClassID
299 {
300 get
301 {
302 return GetHashCode(); // TODO: Return unique ID for this feature class
303 }
304 }
305
306 public int FeatureCount(IQueryFilter QueryFilter)
307 {
308 NpgsqlConnection conn = this.connection.Open();
309 NpgsqlCommand cmd = new NpgsqlCommand("SELECT Count(*) FROM " + tableName, conn);
310 int cnt = Convert.ToInt32(cmd.ExecuteScalar());
311 conn.Close();
312 return cnt;
313 }
314
315 public IFeatureDataset FeatureDataset
316 {
317 get
318 {
319 return new Postarc.Geodatabase.FeatureDataset(this);
320 }
321 }
322
323 public esriFeatureType FeatureType
324 {
325 get
326 {
327 return esriFeatureType.esriFTSimple;
328 }
329 }
330
331 public IFields Fields
332 {
333 get
334 {
335 return fields;
336 }
337 }
338
339 public int FindField(string Name)
340 {
341 return this.fields.FindField(Name);
342 }
343
344 public IFeature GetFeature(int oid)
345 {
346 QueryFilterClass filter = new QueryFilterClass();
347 filter.WhereClause = "OID in (" + oid + ")";
348 IFeatureCursor cur = Search(filter, false);
349 return cur.NextFeature();
350 }
351
352 public IFeatureCursor GetFeatures(object fids, bool recycling)
353 {
354 QueryFilterClass filter = new QueryFilterClass();
355 StringBuilder buf = new StringBuilder();
356 buf.Append(FeatureCursor.POSTARC_OID_COLUMN);
357 buf.Append(" in (");
358 int[] oids = (int[])fids;
359 for (int n = 0; n < oids.Length; n++)
360 {
361 buf.Append(oids[n]);
362 if (n != oids.Length - 1)
363 buf.Append(",");
364 }
365 buf.Append(")");
366 filter.WhereClause = buf.ToString();
367
368 return new FeatureCursor(this, this.connection, filter);
369 }
370
371 public bool HasOID
372 {
373 get
374 {
375 return true;
376 }
377 }
378
379 public IIndexes Indexes
380 {
381 get
382 {
383 return null;
384 }
385 }
386
387 public IFeatureCursor Insert(bool useBuffering)
388 {
389 return null;
390 }
391
392 ICursor ITable.Insert(bool useBuffering)
393 {
394 return null;
395 }
396
397 public IField LengthField
398 {
399 get
400 {
401 return null;
402 }
403 }
404
405 public string OIDFieldName
406 {
407 get
408 {
409 return "OID";
410 }
411 }
412
413 public int ObjectClassID
414 {
415 get
416 {
417 return -1;
418 }
419 }
420
421 public IFeatureCursor Search(IQueryFilter filter, bool recycling)
422 {
423 return new FeatureCursor(this, this.connection, filter);
424 }
425
426 ICursor ITable.Search(IQueryFilter filter, bool recycling)
427 {
428 return Search(filter, recycling) as ICursor;
429 }
430
431 public ISelectionSet Select(
432 IQueryFilter queryFilter,
433 esriSelectionType selType,
434 esriSelectionOption selOption,
435 IWorkspace selectionContainer)
436 {
437 Postarc.Geodatabase.SelectionSet sel = new Postarc.Geodatabase.SelectionSet(this);
438 IFeatureCursor cur = Search(queryFilter, false);
439 IFeature feature;
440 while ((feature = cur.NextFeature()) != null)
441 {
442 sel.Add(feature.OID);
443 }
444 //return sel as ISelectionSet;
445 return null;
446 }
447
448 public string ShapeFieldName
449 {
450 get
451 {
452 return this.shapeFieldName;
453 }
454 }
455
456 internal int ShapeFieldIndex
457 {
458 get
459 {
460 return Fields.FindField(shapeFieldName);
461 }
462 }
463
464 public esriGeometryType ShapeType
465 {
466 get
467 {
468 return this.shapeType;
469 }
470 }
471
472 public IFeatureCursor Update(IQueryFilter filter, bool recycling)
473 {
474 return null;
475 }
476
477 ICursor ITable.Update(IQueryFilter filter, bool recycling)
478 {
479 return null;
480 }
481
482 public IEnumRelationshipClass get_RelationshipClasses(esriRelRole role)
483 {
484 Debug.WriteLine("FeatureClass::get_RelationshipClasses(): FIXME");
485 return null; // TODO: ?
486 }
487
488 public string BrowseName
489 {
490 get
491 {
492 return this.browseName;
493 }
494 set
495 {
496 this.browseName = value;
497 }
498 }
499
500 public bool CanCopy()
501 {
502 return false;
503 }
504
505 public bool CanDelete()
506 {
507 return false;
508 }
509
510 public bool CanRename()
511 {
512 return false;
513 }
514
515 public string Category
516 {
517 get
518 {
519 return "PostGIS";
520 }
521 }
522
523 public IDataset Copy(string copyName, IWorkspace copyWorkspace)
524 {
525 return null;
526 }
527
528 public void Delete()
529 {
530
531 }
532
533 public IName FullName
534 {
535 get
536 {
537 return new FeatureClassName();
538 }
539 }
540
541 public string Name
542 {
543 get
544 {
545 return "PostGIS FeatureClass";
546 }
547 }
548
549 public IPropertySet PropertySet
550 {
551 get
552 {
553 return null;
554 }
555 }
556
557 public void Rename(string name)
558 {
559 }
560
561 public IEnumDataset Subsets
562 {
563 get
564 {
565 return null;
566 }
567 }
568
569 public esriDatasetType Type
570 {
571 get
572 {
573 return esriDatasetType.esriDTFeatureClass;
574 }
575 }
576
577 /// <summary>
578 /// Returns the associated Postarc.Feature.Workspace instance of this
579 /// FeatureClass.
580 /// </summary>
581 public IWorkspace Workspace
582 {
583 get
584 {
585 return this.workspace as IWorkspace;
586 }
587 }
588
589 /// <summary>
590 /// From IDatasetEdit
591 /// </summary>
592 /// <returns></returns>
593 public bool IsBeingEdited()
594 {
595 return this.workspace.IsBeingEdited();
596 }
597
598 public void AlterAliasName(string Name)
599 {
600
601 }
602
603 public void AlterClassExtensionCLSID(UID ClassExtensionCLSID, IPropertySet classExtensionProperties)
604 {
605
606 }
607
608 public void AlterDefaultValue(string FieldName, object Value)
609 {
610
611 }
612
613 public void AlterDomain(string FieldName, IDomain Domain)
614 {
615
616 }
617
618 public void AlterFieldAliasName(string FieldName, string AliasName)
619 {
620
621 }
622
623 public void AlterFieldModelName(string FieldName, string ModelName)
624 {
625
626 }
627
628 public void AlterInstanceCLSID(UID InstanceCLSID)
629 {
630
631 }
632
633 public void AlterModelName(string Name)
634 {
635
636 }
637
638 public int RegisterAsObjectClass(string suggestedOIDFieldName, string configKeyword)
639 {
640 return 0; // FIXME
641 }
642
643
644 public void AlterClassExtensionProperties(IPropertySet classExtensionProperties)
645 {
646
647 }
648
649 public void AddGlobalID(string FieldName)
650 {
651
652 }
653
654 public void DeleteGlobalID()
655 {
656
657 }
658
659 /* public int AllowableComponents
660 {
661 get
662 {
663 return 0; // FIXME
664 }
665 }
666
667 public void Analyze(int tableComponents)
668 {
669
670 }*/
671
672 public bool CanEdit
673 {
674 get
675 {
676 // TODO: Check for write access to PostGIS table
677 return true;
678 }
679 }
680
681
682 public bool CanRedo
683 {
684 get
685 {
686 return false;
687 }
688 }
689
690 public bool CanUndo
691 {
692 get
693 {
694 return false;
695 }
696 }
697
698 /// <summary>
699 /// IFeatureClassLoad.LoadOnlyMode: Indicates if the featureclass is in load only mode.
700 /// </summary>
701 /*public bool LoadOnlyMode
702 {
703 get
704 {
705 return true; //FIXME
706 }
707 set
708 {
709
710 }
711 }*/
712
713 /*
714 public void UpdateExtent()
715 {
716
717 }*/
718
719 /*
720 public void RemoveFeature(IFeature Feature)
721 {
722
723 }
724
725 public void RemoveFeatures(ISet features)
726 {
727
728 }
729
730 public void WriteFeature(IFeature Feature)
731 {
732
733 }
734
735 public void WriteFeatures(ISet features)
736 {
737
738 }*/
739
740 public IEnvelope Extent
741 {
742 get
743 {
744 IPoint point = new PointClass();
745 point.PutCoords(0, 0);
746 ITopologicalOperator topOp = point as ITopologicalOperator;
747 IGeometry buf = topOp.Buffer(100);
748 return buf.Envelope;
749 }
750 }
751
752 public ISpatialReference SpatialReference
753 {
754 get
755 {
756 return spatialReference;
757 }
758 }
759
760
761 /*public IGeodataXform GeodataXform
762 {
763 get
764 {
765 return null; //FIXME
766 }
767 }
768
769 public IEnvelope NativeExtent
770 {
771 get
772 {
773 return null; //FIXME
774 }
775 }
776
777 public ISpatialReference NativeSpatialReference
778 {
779 get
780 {
781 return null; // FIXME
782 }
783 }*/
784
785 public string ModelName
786 {
787 get
788 {
789 return "ModelName"; //FIXME
790 }
791 set
792 {
793
794 }
795 }
796
797
798 public IGeometricNetwork GeometricNetwork
799 {
800 get
801 {
802 return null; // FIXME
803 }
804 }
805
806 public esriNetworkClassAncillaryRole NetworkAncillaryRole
807 {
808 get
809 {
810 return esriNetworkClassAncillaryRole.esriNCARNone; //FIXME
811 }
812 }
813
814 public int get_FieldToWeightMapping(int FieldIndex)
815 {
816 return 0;//FIXME
817 }
818
819 public bool CanBypassStoreMethod()
820 {
821 return false;
822 }
823
824 public bool CanBypassEditSession()
825 {
826 return false;
827 }
828
829 public void ChangeSchemaLock(esriSchemaLock schemaLock)
830 {
831
832 }
833
834 public void GetCurrentSchemaLocks(out IEnumSchemaLockInfo schemaLockInfo)
835 {
836 schemaLockInfo = null; // FIXME
837 }
838
839 public void AddSubtype(int SubtypeCode, string SubtypeName)
840 {
841
842 }
843
844 public int DefaultSubtypeCode
845 {
846 get
847 {
848 return 0; //FIXME
849 }
850 set
851 {
852
853 }
854 }
855
856 public void DeleteSubtype(int SubtypeCode)
857 {
858
859 }
860
861 public bool HasSubtype
862 {
863 get
864 {
865 return false;
866 }
867 }
868
869 public int SubtypeFieldIndex
870 {
871 get
872 {
873 Debug.WriteLine("FeatureClass::SubtypeFieldIndex::get");
874 return 0; //FIXME
875 }
876 }
877
878 public string SubtypeFieldName
879 {
880 get
881 {
882 return "";
883 }
884 set
885 {
886
887 }
888 }
889
890 public IEnumSubtype Subtypes
891 {
892 get
893 {
894 Debug.WriteLine("FeatureClass::Subtypes(): FIXME");
895 return null; //FIXME
896 }
897 }
898
899 public object get_DefaultValue(int subtypeCode, string fieldName)
900 {
901 return null; // FIXME
902 }
903
904 public IDomain get_Domain(int subtypeCode, string fieldName)
905 {
906 Debug.WriteLine("FeatureClass::get_Domain(): FIXME " + fieldName);
907 return null; //FIXME
908 }
909
910 public string get_SubtypeName(int subtypeCode)
911 {
912 return ""; //FIXME
913 }
914
915 public void set_DefaultValue(int ubtypeCode, string fieldName, object value)
916 {
917
918 }
919
920 public void set_Domain(int ubtypeCode, string fieldName, IDomain domain)
921 {
922
923 }
924
925 public IRow CreateRow()
926 {
927 Debug.WriteLine("PostGISFeatureClass::CreateRow()");
928 return CreateRowBuffer() as IRow;
929 }
930
931 public IRowBuffer CreateRowBuffer()
932 {
933 Debug.WriteLine("PostGISFeatureClass::CreateRowBuffer()");
934 return CreateFeature() as IRowBuffer;
935 }
936
937 public void DeleteSearchedRows(IQueryFilter queryFilter)
938 {
939
940 }
941
942 public IRow GetRow(int oid)
943 {
944 Debug.WriteLine("PostGISFeatureClass::GetRow");
945 ICursor cur = GetRows(new int[] { oid }, false);
946 return cur.NextRow();
947 }
948
949 public ICursor GetRows(object oids_obj, bool recycling)
950 {
951 Debug.WriteLine("PostGISFeatureClass::GetRows");
952 return (ICursor)GetFeatures(oids_obj, recycling);
953 }
954
955 public int RowCount(IQueryFilter queryFilter)
956 {
957 return FeatureCount(queryFilter);
958 }
959
960 public void UpdateSearchedRows(IQueryFilter queryFilter, IRowBuffer buffer)
961 {
962
963 }
964
965 /// <summary>
966 /// From ITableCapabilities
967 /// </summary>
968 public bool CanSelect
969 {
970 get
971 {
972 return true;
973 }
974 }
975
976 public void AddClass(IClass classToAdd, double Weight, int XYRank, int ZRank, bool EventNotificationOnValidate)
977 {
978
979 }
980
981 public ITopologyGraph Cache
982 {
983 get
984 {
985 return null; //FIXME
986 }
987 }
988
989 public double ClusterTolerance
990 {
991 get
992 {
993 return 0.0001; // FIXME
994 }
995 }
996
997 public int MaximumGeneratedErrorCount
998 {
999 get
1000 {
1001 return 0; // FIXME
1002 }
1003 }
1004
1005 public void RemoveClass(IClass classToRemove)
1006 {
1007
1008 }
1009
1010 public esriTopologyState State
1011 {
1012 get
1013 {
1014 return esriTopologyState.esriTSUnanalyzed; // FIXME
1015 }
1016 }
1017
1018 public int TopologyID
1019 {
1020 get
1021 {
1022 return 0; //FIXME
1023 }
1024 }
1025
1026 public IEnvelope ValidateTopology(IEnvelope areaToValidate)
1027 {
1028 return null; //FIXME
1029 }
1030
1031 public IPolygon get_DirtyArea(IPolygon location)
1032 {
1033 return null; //FIXME
1034 }
1035
1036 public void AddRule(IRule Rule)
1037 {
1038
1039 }
1040
1041 public void DeleteRule(IRule Rule)
1042 {
1043
1044 }
1045
1046 public IEnumRule Rules
1047 {
1048 get
1049 {
1050 return null; // FIXME
1051 }
1052 }
1053
1054 public ISelectionSet Validate(IQueryFilter Selection, IWorkspace Workspace)
1055 {
1056 return null;
1057 }
1058
1059 public ISelectionSet ValidateSelection(ISelectionSet Selection, IWorkspace Workspace)
1060 {
1061 return null; // FIXME
1062 }
1063
1064 public ISet ValidateSet(ISet Selection)
1065 {
1066 return null;
1067 }
1068
1069 public IEnumRule get_RulesByField(string FieldName)
1070 {
1071 return null;
1072 }
1073
1074 public IEnumRule get_RulesBySubtypeCode(int SubtypeCode)
1075 {
1076 return null;
1077 }
1078
1079 public void AlterRule(IRule Rule)
1080 {
1081
1082 }
1083 }
1084 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)