private void WriteAssociationProperty(AssociationPropertyDefinition assoc) { if (assoc.AssociatedClass != null) { Console.WriteLine("\tAssociated Class: {0}", assoc.AssociatedClass.Name); } if (assoc.IdentityProperties != null) { Console.WriteLine("\tIdentity Properties:"); foreach (DataPropertyDefinition data in assoc.IdentityProperties) { Console.WriteLine("\t\t- {0}", data.Name); } } Console.WriteLine("\tDelete Rule: {0}", assoc.DeleteRule); Console.WriteLine("\tRead-Only: {0}\n\tLock Cascade: {1}", assoc.IsReadOnly, assoc.LockCascade); Console.WriteLine("\tMultiplicity: {0}", assoc.Multiplicity); Console.WriteLine("\tProperty Type: {0}", assoc.PropertyType); if (assoc.ReverseIdentityProperties != null) { Console.WriteLine("\tReverse Identity Properties:"); foreach (DataPropertyDefinition data in assoc.ReverseIdentityProperties) { Console.WriteLine("\t\t- {0}", data.Name); } } Console.WriteLine("\tReverse Multiplicity: {0}\n\tReverse Name: {1}", assoc.ReverseMultiplicity, assoc.ReverseName); }
public void ClassChanged() { if (_view.SelectedClass != null) { var cls = _walker.GetClassDefinition(_view.SelectedSchema, _view.SelectedClass.ClassName); this.SelectedClass = cls; List <string> p = new List <string>(); foreach (PropertyDefinition pd in cls.Properties) { if (pd.PropertyType == PropertyType.PropertyType_DataProperty || pd.PropertyType == PropertyType.PropertyType_GeometricProperty) { p.Add(pd.Name); } else if (pd.PropertyType == PropertyType.PropertyType_ObjectProperty) { String szPrefix = pd.Name; ObjectPropertyDefinition pdo = (ObjectPropertyDefinition)pd; // TODO: make this an iterative loop // only processing one sub-set for now foreach (PropertyDefinition pdSub in pdo.Class.Properties) { if (pdSub.PropertyType == PropertyType.PropertyType_DataProperty || pd.PropertyType == PropertyType.PropertyType_GeometricProperty) { p.Add(szPrefix + "." + pdSub.Name); } // TODO: process objects and associations } } else if (pd.PropertyType == PropertyType.PropertyType_AssociationProperty) { String szPrefix = pd.Name; AssociationPropertyDefinition pda = (AssociationPropertyDefinition)pd; // TODO: make this an iterative loop // only processing one sub-set for now foreach (PropertyDefinition pdSub in pda.AssociatedClass.Properties) { if (pdSub.PropertyType == PropertyType.PropertyType_DataProperty || pd.PropertyType == PropertyType.PropertyType_GeometricProperty) { p.Add(szPrefix + "." + pdSub.Name); } // TODO: process objects and associations } } } _view.PropertyList = p; _view.FireMapPreviewStateChanged(cls.ClassType == ClassType.ClassType_FeatureClass); } }
/// <summary> /// Adds the association property. /// </summary> /// <param name="assocDef">The association def.</param> /// <param name="szClassHierarchy">The class name hierarchy.</param> public void AddAssociationProperty(AssociationPropertyDefinition assocDef, String szClassHierarchy) { String szObjectName = ""; if (!String.IsNullOrEmpty(szClassHierarchy)) { szObjectName = szClassHierarchy + "."; } szObjectName += assocDef.Name; // TODO: maybe need to do some work on "objectDef.IdentityProperty" to aid interface foreach (PropertyDefinition pd in assocDef.AssociatedClass.Properties) { switch (pd.PropertyType) { case PropertyType.PropertyType_DataProperty: AddDataProperty((DataPropertyDefinition)pd, szObjectName); break; case PropertyType.PropertyType_GeometricProperty: AddGeometricProperty((GeometricPropertyDefinition)pd, szObjectName); break; // allows for cascading hierarchy - crazy man! case PropertyType.PropertyType_ObjectProperty: AddObjectProperty((ObjectPropertyDefinition)pd, szObjectName); break; // allows for cascading hierarchy - crazy man! // TODO: do NOT allow for cascading associations until reciprocol nature is // better understood - else get into a loop between parent and child // Possibly just need to check this (pd) does not point back to the previous!? // See similar comment here in "void FdoRdbmsFilterProcessor::FollowRelation(...)" // \FDO\branches\3.5\Providers\GenericRdbms\Src\Fdo\Filter\FdoRdbmsFilterProcessor.cpp //case PropertyType.PropertyType_AssociationProperty: // AddAssociationProperty((AssociationPropertyDefinition)pd, szObjectName); //break; } } }
private static ICollection <string> GetReferencedClasses(ClassDefinition clsDef) { HashSet <string> clsNames = new HashSet <string>(); foreach (PropertyDefinition propDef in clsDef.Properties) { if (propDef.PropertyType == PropertyType.PropertyType_AssociationProperty) { AssociationPropertyDefinition ap = (AssociationPropertyDefinition)propDef; clsNames.Add(ap.AssociatedClass.QualifiedName); } else if (propDef.PropertyType == PropertyType.PropertyType_ObjectProperty) { ObjectPropertyDefinition op = (ObjectPropertyDefinition)propDef; clsNames.Add(op.Class.QualifiedName); } } return(clsNames); }
/// <summary> /// Adds the association property. /// </summary> /// <param name="assocDef">The association def.</param> /// <param name="szClassHierarchy">The class name hierarchy.</param> public void AddAssociationProperty(AssociationPropertyDefinition assocDef, String szClassHierarchy) { String szObjectName = ""; if (!String.IsNullOrEmpty(szClassHierarchy)) szObjectName = szClassHierarchy + "."; szObjectName += assocDef.Name; // TODO: maybe need to do some work on "objectDef.IdentityProperty" to aid interface foreach (PropertyDefinition pd in assocDef.AssociatedClass.Properties) { switch (pd.PropertyType) { case PropertyType.PropertyType_DataProperty: AddDataProperty((DataPropertyDefinition)pd, szObjectName); break; case PropertyType.PropertyType_GeometricProperty: AddGeometricProperty((GeometricPropertyDefinition)pd, szObjectName); break; // allows for cascading hierarchy - crazy man! case PropertyType.PropertyType_ObjectProperty: AddObjectProperty((ObjectPropertyDefinition)pd, szObjectName); break; // allows for cascading hierarchy - crazy man! // TODO: do NOT allow for cascading associations until reciprocol nature is // better understood - else get into a loop between parent and child // Possibly just need to check this (pd) does not point back to the previous!? // See similar comment here in "void FdoRdbmsFilterProcessor::FollowRelation(...)" // \FDO\branches\3.5\Providers\GenericRdbms\Src\Fdo\Filter\FdoRdbmsFilterProcessor.cpp //case PropertyType.PropertyType_AssociationProperty: // AddAssociationProperty((AssociationPropertyDefinition)pd, szObjectName); //break; } } }
/// <summary> /// Adds the association property. /// </summary> /// <param name="assocDef">The association def.</param> public void AddAssociationProperty(AssociationPropertyDefinition assocDef) { // TODO: validate this statement and action MessageBox.Show("Association Properties cannot be added at INSERT time\n\nInsert a record into the associated class with the same ID"); // AddAssociationProperty(assocDef, null); }
internal void AddProperty(PropertyType type) { TreeNode node = _view.schemaTree.SelectedNode; if (node.Level == LEVEL_CLASS) { if (type == PropertyType.PropertyType_AssociationProperty || type == PropertyType.PropertyType_ObjectProperty) { var sn = node.Parent; if (sn.Nodes.Count == 1) //The selected class is the only one { MessageService.ShowError("No other class definitions exist in the current schema"); return; } } string schema = node.Parent.Name; string clsName = node.Name; string prefix = "Property"; switch (type) { case PropertyType.PropertyType_AssociationProperty: prefix = "AssociationProperty"; break; case PropertyType.PropertyType_DataProperty: prefix = "DataProperty"; break; case PropertyType.PropertyType_GeometricProperty: prefix = "GeometricProperty"; break; case PropertyType.PropertyType_ObjectProperty: prefix = "ObjectProperty"; break; case PropertyType.PropertyType_RasterProperty: prefix = "RasterProperty"; break; } string name = _context.GenerateName(prefix); while (_context.PropertyNameExists(schema, clsName, name)) { name = _context.GenerateName(prefix); } PropertyDefinition pd = null; switch (type) { case PropertyType.PropertyType_AssociationProperty: pd = new AssociationPropertyDefinition(name, ""); break; case PropertyType.PropertyType_DataProperty: var dp = new DataPropertyDefinition(name, ""); if (dp.DataType == DataType.DataType_String) { dp.Length = 255; } pd = dp; break; case PropertyType.PropertyType_GeometricProperty: pd = new GeometricPropertyDefinition(name, ""); break; case PropertyType.PropertyType_ObjectProperty: pd = new ObjectPropertyDefinition(name, ""); break; case PropertyType.PropertyType_RasterProperty: break; } if (pd != null) { _context.AddProperty(schema, clsName, pd); } } }
/// <summary> /// Utility method to clone a feature schema /// </summary> /// <param name="fs"></param> /// <param name="ignoreDeleted"></param> /// <returns></returns> public static FeatureSchema CloneSchema(FeatureSchema fs, bool ignoreDeleted) { if (fs == null) { throw new ArgumentNullException("fs"); } /* * This method is BIG. So it needs some explanation. * * Because Association and Object Properties reference other classes, the classes * containing such properties are processed *last*. Everything else is assumed to * be cloned (without problems) and cached in a temp dictionary for processing these * classes w/ Association/Object properties. * * When processing these remaining classes, we iteratively attempt to clone each class. * Each successfully cloned class will be added to the temp dictionary. Eventually all * references will be satisfied, that's when we can finally return the cloned schema. */ Dictionary <string, ClassDefinition> cloned = new Dictionary <string, ClassDefinition>(); List <ClassDefinition> classesWithReferences = new List <ClassDefinition>(); FeatureSchema fsc = new FeatureSchema(fs.Name, fs.Description); CopyElementAttributes(fs.Attributes, fsc.Attributes); if (ignoreDeleted) { foreach (ClassDefinition cls in fs.Classes) { if (cls.ElementState != SchemaElementState.SchemaElementState_Deleted) { ICollection <string> refs = GetReferencedClasses(cls); if (refs.Count == 0) { var klass = CloneClass(cls, ignoreDeleted); fsc.Classes.Add(klass); cloned.Add(klass.QualifiedName, klass); } else { //Check for self-references classesWithReferences.Add(cls); } } } } else { foreach (ClassDefinition cls in fs.Classes) { ICollection <string> refs = GetReferencedClasses(cls); if (refs.Count == 0) { var klass = CloneClass(cls, ignoreDeleted); fsc.Classes.Add(klass); cloned.Add(klass.QualifiedName, klass); } else { //Check for self-references classesWithReferences.Add(cls); } } } //TODO: Does the FDO spec allow self-referenced Association/Object //properties? If not, it would simplify this code greatly. //Repeat until all references satisfied while (classesWithReferences.Count > 0) { List <ClassDefinition> successfullyCloned = new List <ClassDefinition>(); foreach (ClassDefinition cls in classesWithReferences) { bool bSuccess = false; ClassDefinition klass = null; switch (cls.ClassType) { case ClassType.ClassType_Class: klass = new Class(cls.Name, cls.Description); break; case ClassType.ClassType_FeatureClass: klass = new FeatureClass(cls.Name, cls.Description); break; } Dictionary <AssociationPropertyDefinition, AssociationPropertyDefinition> processAp = new Dictionary <AssociationPropertyDefinition, AssociationPropertyDefinition>(); Dictionary <ObjectPropertyDefinition, ObjectPropertyDefinition> processOp = new Dictionary <ObjectPropertyDefinition, ObjectPropertyDefinition>(); var props = cls.Properties; for (int i = 0; i < props.Count; i++) { var prop = props[i]; if (prop.PropertyType == PropertyType.PropertyType_AssociationProperty) { var ap = (AssociationPropertyDefinition)prop; var apClone = new AssociationPropertyDefinition(ap.Name, ap.Description); ClassDefinition associatedClass = null; associatedClass = cloned[ap.AssociatedClass.QualifiedName]; if (associatedClass == null) { //could be a self-reference if (klass.Name.Equals(ap.AssociatedClass.Name)) { associatedClass = klass; } } if (associatedClass != null) { apClone.AssociatedClass = associatedClass; apClone.DeleteRule = ap.DeleteRule; //Process identity properties. Shelve for later processing if //any property can't be found var idProps = ap.IdentityProperties; bool foundAll = true; foreach (DataPropertyDefinition dp in idProps) { if (!props.Contains(dp)) { foundAll = false; } } if (foundAll) { foreach (DataPropertyDefinition dp in idProps) { apClone.IdentityProperties.Add((DataPropertyDefinition)props[dp.Name]); } } else { processAp.Add(apClone, ap); } apClone.LockCascade = ap.LockCascade; apClone.Multiplicity = ap.Multiplicity; //Process reverse identity properties. Shelve for later processing if //any property can't be found var ridProps = ap.ReverseIdentityProperties; foundAll = true; foreach (DataPropertyDefinition dp in ridProps) { if (!props.Contains(dp)) { foundAll = false; } } if (foundAll) { foreach (DataPropertyDefinition dp in ridProps) { apClone.ReverseIdentityProperties.Add((DataPropertyDefinition)apClone.AssociatedClass.Properties[dp.Name]); } } else { processAp.Add(apClone, ap); } apClone.ReverseMultiplicity = ap.ReverseMultiplicity; apClone.ReverseName = ap.ReverseName; klass.Properties.Add(apClone); } else { break; } } else if (prop.PropertyType == PropertyType.PropertyType_ObjectProperty) { var op = (ObjectPropertyDefinition)prop; var opClone = new ObjectPropertyDefinition(op.Name, op.Description); if (cloned.ContainsKey(op.Class.QualifiedName)) { ClassDefinition associatedClass = cloned[op.Class.QualifiedName]; opClone.Class = associatedClass; //Process identity property. Shelve for later processing if none found if (props.Contains(op.IdentityProperty.Name)) { opClone.IdentityProperty = (DataPropertyDefinition)op.Class.Properties[op.IdentityProperty.Name]; } else { processOp.Add(opClone, op); } opClone.ObjectType = op.ObjectType; opClone.OrderType = op.OrderType; klass.Properties.Add(opClone); } else { break; } } else { bool identity = false; bool geometry = false; var dp = prop as DataPropertyDefinition; var gp = prop as GeometricPropertyDefinition; identity = (dp != null && cls.IdentityProperties.Contains(dp)); geometry = (gp != null && cls.ClassType == ClassType.ClassType_FeatureClass && ((FeatureClass)cls).GeometryProperty == gp); //Clone property and add to cloned class var cp = CloneProperty(prop); klass.Properties.Add(cp); if (identity) { Debug.Assert(cp.PropertyType == PropertyType.PropertyType_DataProperty); klass.IdentityProperties.Add((DataPropertyDefinition)cp); } if (geometry) { Debug.Assert(cp.PropertyType == PropertyType.PropertyType_GeometricProperty); Debug.Assert(klass.ClassType == ClassType.ClassType_FeatureClass); ((FeatureClass)klass).GeometryProperty = (GeometricPropertyDefinition)cp; } } } if (processAp.Count > 0) { foreach (AssociationPropertyDefinition apClone in processAp.Keys) { var ap = processAp[apClone]; //Retry identity properties apClone.IdentityProperties.Clear(); var idProps = ap.IdentityProperties; foreach (DataPropertyDefinition dp in idProps) { apClone.IdentityProperties.Add((DataPropertyDefinition)props[dp.Name]); } //Retry reverse identity properties apClone.ReverseIdentityProperties.Clear(); var ridProps = ap.ReverseIdentityProperties; foreach (DataPropertyDefinition dp in ridProps) { apClone.ReverseIdentityProperties.Add((DataPropertyDefinition)apClone.AssociatedClass.Properties[dp.Name]); } } } if (processOp.Count > 0) { foreach (ObjectPropertyDefinition opClone in processOp.Keys) { var op = processOp[opClone]; //Retry identity property opClone.IdentityProperty = (DataPropertyDefinition)op.Class.Properties[op.IdentityProperty.Name]; } } //All properties accounted for if (klass.Properties.Count == cls.Properties.Count && klass.IdentityProperties.Count == cls.IdentityProperties.Count) { bSuccess = true; } if (bSuccess) { fsc.Classes.Add(klass); successfullyCloned.Add(cls); } } //Purge successfully cloned entries foreach (ClassDefinition cls in successfullyCloned) { int ridx = classesWithReferences.IndexOf(cls); if (ridx >= 0) { classesWithReferences.RemoveAt(ridx); } } } return(fsc); }
internal void AddProperty(PropertyType type) { TreeNode node = _view.schemaTree.SelectedNode; if (node.Level == LEVEL_CLASS) { if (type == PropertyType.PropertyType_AssociationProperty || type == PropertyType.PropertyType_ObjectProperty) { var sn = node.Parent; if (sn.Nodes.Count == 1) //The selected class is the only one { MessageService.ShowError("No other class definitions exist in the current schema"); return; } } string schema = node.Parent.Name; string clsName = node.Name; string prefix = "Property"; switch (type) { case PropertyType.PropertyType_AssociationProperty: prefix = "AssociationProperty"; break; case PropertyType.PropertyType_DataProperty: prefix = "DataProperty"; break; case PropertyType.PropertyType_GeometricProperty: prefix = "GeometricProperty"; break; case PropertyType.PropertyType_ObjectProperty: prefix = "ObjectProperty"; break; case PropertyType.PropertyType_RasterProperty: prefix = "RasterProperty"; break; } string name = _context.GenerateName(prefix); while (_context.PropertyNameExists(schema, clsName, name)) { name = _context.GenerateName(prefix); } PropertyDefinition pd = null; switch (type) { case PropertyType.PropertyType_AssociationProperty: pd = new AssociationPropertyDefinition(name, ""); break; case PropertyType.PropertyType_DataProperty: var dp = new DataPropertyDefinition(name, ""); if (dp.DataType == DataType.DataType_String) dp.Length = 255; pd = dp; break; case PropertyType.PropertyType_GeometricProperty: pd = new GeometricPropertyDefinition(name, ""); break; case PropertyType.PropertyType_ObjectProperty: pd = new ObjectPropertyDefinition(name, ""); break; case PropertyType.PropertyType_RasterProperty: break; } if (pd != null) _context.AddProperty(schema, clsName, pd); } }
void DoWork(object sender, DoWorkEventArgs e) { IFdoReader reader = null; using (FdoFeatureService service = _connection.CreateFeatureService()) { try { if (e.Argument is FeatureAggregateOptions) { reader = service.SelectAggregates((FeatureAggregateOptions)e.Argument); } else if (e.Argument is StandardQuery) { var stdArg = (e.Argument as StandardQuery); reader = service.SelectFeatures(stdArg.query, stdArg.Limit, stdArg.UseExtendedSelect); } else if (e.Argument is string) { reader = service.ExecuteSQLQuery(e.Argument.ToString()); } //Init the data grid view FdoFeatureTable table = new FdoFeatureTable(); table.RequestSpatialContext += delegate(object o, string name) { SpatialContextInfo c = service.GetSpatialContext(name); if (c != null) { table.AddSpatialContext(c); } }; ClassDefinition clsDef = null; bool hasJoins = false; if (e.Argument is StandardQuery) { var qry = ((StandardQuery)e.Argument).query; clsDef = service.GetClassByName(qry.ClassName); //TODO: Should really qualify this, but our input parameters do not specify a schema hasJoins = qry.JoinCriteria.Count > 0; } table.InitTable(reader, clsDef, hasJoins); // need to store object class defn outside loop ClassDefinition classDefObject = null; ClassDefinition classDefAssoc = null; while (reader.ReadNext() && !_queryWorker.CancellationPending) { //Pass processed feature to data grid view FdoFeature feat = table.NewRow(); for (int i = 0; i < reader.FieldCount; i++) { string name = reader.GetName(i); if (!reader.IsNull(name)) { FdoPropertyType pt = reader.GetFdoPropertyType(name); switch (pt) { case FdoPropertyType.Association: // TODO: how to handle for non-StandardQuery if (e.Argument is StandardQuery) { // because the original code used an iterator over the reader.FieldCount // it is a bit of a hack to get another definition of the class and check // we are at the right property with a name comparison // TODO: code review to see if this can be implemented better FdoFeatureReader readerFeature = (FdoFeatureReader)reader; ClassDefinition classDef = readerFeature.GetClassDefinition(); foreach (PropertyDefinition propertyDef in classDef.Properties) { // only looking for the right association if ((PropertyType.PropertyType_AssociationProperty == propertyDef.PropertyType) && (propertyDef.Name.Equals(name))) { AssociationPropertyDefinition assocProp = (AssociationPropertyDefinition)propertyDef; ClassDefinition classAssoc = assocProp.AssociatedClass; // get a reader from the association - nice! IFeatureReader readerAssoc = readerFeature.GetFeatureObject(name); if ((null != readerAssoc) && (readerAssoc.ReadNext())) { // TODO: this should be an iterative function // the simple reassignment on each instance fails // (classDefObject.Properties is always zero after first record) // so have set classDefObject higher-up and re-use/ // - problem will occur if more than one association // ClassDefinition classDefObject = readerObject.GetClassDefinition(); if (null == classDefAssoc) { classDefAssoc = readerAssoc.GetClassDefinition(); } foreach (PropertyDefinition propertyDefAssoc in classDefAssoc.Properties) { String nameAssoc = propertyDefAssoc.Name; // TODO: only "data" type handled at present if (PropertyType.PropertyType_DataProperty == propertyDefAssoc.PropertyType) { DataPropertyDefinition datapropertyDefAssoc = (DataPropertyDefinition)propertyDefAssoc; String szFullName = name + "." + nameAssoc; DataType ptAssoc = datapropertyDefAssoc.DataType; // TODO: handle all types switch (ptAssoc) { case DataType.DataType_String: feat[szFullName] = readerAssoc.GetString(nameAssoc); break; case DataType.DataType_Int16: feat[szFullName] = readerAssoc.GetInt16(nameAssoc); break; case DataType.DataType_Int32: feat[szFullName] = readerAssoc.GetInt32(nameAssoc); break; case DataType.DataType_Int64: feat[szFullName] = readerAssoc.GetInt64(nameAssoc); break; } } } readerAssoc.Close(); } } } } break; case FdoPropertyType.BLOB: feat[name] = reader.GetLOB(name).Data; break; case FdoPropertyType.Boolean: feat[name] = reader.GetBoolean(name); break; case FdoPropertyType.Byte: feat[name] = reader.GetByte(name); break; case FdoPropertyType.CLOB: feat[name] = reader.GetLOB(name).Data; break; case FdoPropertyType.DateTime: { try { feat[name] = reader.GetDateTime(name); } catch //Unrepresentable dates { feat[name] = DBNull.Value; } } break; case FdoPropertyType.Decimal: //We should probably remove this as FDO coerces decimals to doubles (otherwise why is there not a GetDecimal() method in FdoIReader?) { double val = reader.GetDouble(name); if (Double.IsNaN(val)) { feat[name] = DBNull.Value; } else { feat[name] = Convert.ToDecimal(val); } } break; case FdoPropertyType.Double: feat[name] = reader.GetDouble(name); break; case FdoPropertyType.Geometry: { try { byte[] fgf = reader.GetGeometry(name); OSGeo.FDO.Geometry.IGeometry geom = service.GeometryFactory.CreateGeometryFromFgf(fgf); var fg = new FdoGeometry(geom); //OGR geometry trap using (var env = fg.Envelope) { } feat[name] = fg; } catch { feat[name] = DBNull.Value; } } break; case FdoPropertyType.Int16: feat[name] = reader.GetInt16(name); break; case FdoPropertyType.Int32: feat[name] = reader.GetInt32(name); break; case FdoPropertyType.Int64: feat[name] = reader.GetInt64(name); break; case FdoPropertyType.Object: // TODO: how to handle for non-StandardQuery if (e.Argument is StandardQuery) { // because the original code used an iterator over the reader.FieldCount // it is a bit of a hack to get another definition of the class and check // we are at the right property with a name comparison // TODO: code review to see if this can be implemented better FdoFeatureReader readerFeature = (FdoFeatureReader)reader; ClassDefinition classDef = readerFeature.GetClassDefinition(); foreach (PropertyDefinition propertyDef in classDef.Properties) { // only looking for the right object if ((PropertyType.PropertyType_ObjectProperty == propertyDef.PropertyType) && (propertyDef.Name.Equals(name))) { ObjectPropertyDefinition assocProp = (ObjectPropertyDefinition)propertyDef; ClassDefinition classAssoc = assocProp.Class; // get a reader from the object - nice! IFeatureReader readerObject = readerFeature.GetFeatureObject(name); if ((null != readerObject) && (readerObject.ReadNext())) { // TODO: this should be an iterative function // the simple reassignment on each instance fails // (classDefObject.Properties is always zero after first record) // so have set classDefObject higher-up and re-use/ // - problem will occur if more than one association // ClassDefinition classDefObject = readerObject.GetClassDefinition(); if (null == classDefObject) { classDefObject = readerObject.GetClassDefinition(); } foreach (PropertyDefinition propertyDefObject in classDefObject.Properties) { String nameObject = propertyDefObject.Name; // TODO: only "data" type handled at present if (PropertyType.PropertyType_DataProperty == propertyDefObject.PropertyType) { DataPropertyDefinition datapropertyDefObject = (DataPropertyDefinition)propertyDefObject; String szFullName = name + "." + nameObject; DataType ptAssoc = datapropertyDefObject.DataType; // TODO: handle all types switch (ptAssoc) { case DataType.DataType_String: feat[szFullName] = readerObject.GetString(nameObject); break; case DataType.DataType_Int16: feat[szFullName] = readerObject.GetInt16(nameObject); break; case DataType.DataType_Int32: feat[szFullName] = readerObject.GetInt32(nameObject); break; case DataType.DataType_Int64: feat[szFullName] = readerObject.GetInt64(nameObject); break; } } } readerObject.Close(); readerObject = null; } } } } break; //case FdoPropertyType.Raster: case FdoPropertyType.Single: feat[name] = reader.GetSingle(name); break; case FdoPropertyType.String: feat[name] = reader.GetString(name); break; } } else { feat[name] = DBNull.Value; } } table.AddRow(feat); if (table.Rows.Count % 50 == 0) { System.Threading.Thread.Sleep(50); } } if (_queryWorker.CancellationPending) { e.Cancel = true; _cancelResult = table; } else { e.Result = table; } } finally { if (reader != null) { reader.Close(); } } } }
void CreatePropertyNodes(ClassDefinition classDef, TreeNode classNode) { //Pre-sort SortedList <string, PropertyDefinition> sorted = new SortedList <string, PropertyDefinition>(); foreach (PropertyDefinition propDef in classDef.Properties) { sorted.Add(propDef.Name, propDef); } foreach (PropertyDefinition propDef in sorted.Values) { TreeNode propertyNode = new TreeNode(); propertyNode.Name = propertyNode.Text = propDef.Name; switch (propDef.PropertyType) { case PropertyType.PropertyType_DataProperty: { DataPropertyDefinition dataDef = propDef as DataPropertyDefinition; propertyNode.ImageKey = propertyNode.SelectedImageKey = IMG_DATA_PROPERTY; if (classDef.IdentityProperties.Contains(dataDef)) { propertyNode.ImageKey = propertyNode.SelectedImageKey = IMG_ID_PROPERTY; } propertyNode.ToolTipText = string.Format("Data Type: {0}\nLength: {1}\nAuto-Generated: {2}\nRead-Only: {3}\nNullable: {4}", dataDef.DataType, dataDef.Length, dataDef.IsAutoGenerated, dataDef.ReadOnly, dataDef.Nullable); } break; case PropertyType.PropertyType_GeometricProperty: { GeometricPropertyDefinition geomDef = propDef as GeometricPropertyDefinition; propertyNode.ImageKey = propertyNode.SelectedImageKey = IMG_GEOM_PROPERTY; propertyNode.ToolTipText = string.Format("Has Elevation: {0}\nHas Measure: {1}\nRead-Only: {2}\nGeometry Types: {3}\nSpatial Context: {4}", geomDef.HasElevation, geomDef.HasMeasure, geomDef.ReadOnly, GeomTypesAsString(geomDef.GeometryTypes), geomDef.SpatialContextAssociation); } break; case PropertyType.PropertyType_RasterProperty: { RasterPropertyDefinition rastDef = propDef as RasterPropertyDefinition; propertyNode.ImageKey = propertyNode.SelectedImageKey = IMG_RASTER_PROPERTY; propertyNode.ToolTipText = "Raster Property"; } break; case PropertyType.PropertyType_ObjectProperty: { ObjectPropertyDefinition objDef = propDef as ObjectPropertyDefinition; propertyNode.ImageKey = propertyNode.SelectedImageKey = IMG_OBJECT_PROPERTY; propertyNode.ToolTipText = "Object Property"; } break; case PropertyType.PropertyType_AssociationProperty: { AssociationPropertyDefinition assocDef = propDef as AssociationPropertyDefinition; propertyNode.ImageKey = propertyNode.SelectedImageKey = IMG_ASSOC_PROPERTY; propertyNode.ToolTipText = "Association Property"; } break; } classNode.Nodes.Add(propertyNode); } }
public AssociationPropertyDefinitionDecorator(AssociationPropertyDefinition p) : base(p) { _a = p; }
private int PurgeAffectedAssocationProperties(AssociationPropertyDefinition[] properties) { int removed = 0; for (int i = 0; i < properties.Length; i++) { var ap = properties[i]; System.Diagnostics.Debug.Assert(ap.Parent != null); var cls = (ClassDefinition)ap.Parent; cls.Properties.Remove(ap); RemoveNode(cls.Name, ap.Name); //Sync UI removed++; } return removed; }
public void Init() { _view.InitializeGrid(); _view.UseTransactionEnabled = (_conn.Capability.GetBooleanCapability(CapabilityType.FdoCapabilityType_SupportsTransactions)); using (FdoFeatureService service = _conn.CreateFeatureService()) { ClassDefinition cd = service.GetClassByName(_className); if (cd != null) { _view.ClassName = cd.Name; foreach (PropertyDefinition pd in cd.Properties) { switch (pd.PropertyType) { case PropertyType.PropertyType_DataProperty: _view.AddDataProperty((DataPropertyDefinition)pd, _feature[pd.Name]); break; case PropertyType.PropertyType_GeometricProperty: if (null != (_feature[pd.Name] as FdoGeometry)) // else throws exeption with the ".Text" null reference { _view.AddGeometricProperty((GeometricPropertyDefinition)pd, (_feature[pd.Name] as FdoGeometry).Text); } break; case PropertyType.PropertyType_AssociationProperty: AssociationPropertyDefinition pdAssoc = (AssociationPropertyDefinition)pd; ClassDefinition cdAssoc = service.GetClassByName(pdAssoc.AssociatedClass.Name); foreach (PropertyDefinition pdThis in cdAssoc.Properties) { String szPropertyName = pd.Name + "." + pdThis.Name; // TODO: iterate associations and objects switch (pdThis.PropertyType) { case PropertyType.PropertyType_DataProperty: // TODO: fix this issue of reverse association // at the moment can get geom from parent to child - but throws error from child to parent try { _view.AddDataProperty((DataPropertyDefinition)pdThis, _feature[szPropertyName], pd.Name); } catch (Exception exThis) { // System.Windows.Forms.MessageBox.Show("Cannot Edit Association Property\n\n" + exThis.Message); } break; case PropertyType.PropertyType_GeometricProperty: // TODO: fix this issue of reverse association // at the moment can get geom from parent to child - but throws error from child to parent try { if (null != (_feature[szPropertyName] as FdoGeometry)) // else throws exeption with the ".Text" null reference { _view.AddGeometricProperty((GeometricPropertyDefinition)pdThis, (_feature[szPropertyName] as FdoGeometry).Text, pd.Name); } } catch (Exception exThis) { System.Windows.Forms.MessageBox.Show("Cannot Edit Association Geometry\n\n" + exThis.Message); } break; } } break; case PropertyType.PropertyType_ObjectProperty: ObjectPropertyDefinition pdObject = (ObjectPropertyDefinition)pd; ClassDefinition cdObject = service.GetClassByName(pdObject.Class.Name); foreach (PropertyDefinition pdThis in cdObject.Properties) { String szPropertyName = pd.Name + "." + pdThis.Name; // TODO: iterate associations and objects switch (pdThis.PropertyType) { case PropertyType.PropertyType_DataProperty: _view.AddDataProperty((DataPropertyDefinition)pdThis, _feature[szPropertyName], pd.Name); break; case PropertyType.PropertyType_GeometricProperty: if (null != (_feature[szPropertyName] as FdoGeometry)) // else throws exeption with the ".Text" null reference { _view.AddGeometricProperty((GeometricPropertyDefinition)pdThis, (_feature[szPropertyName] as FdoGeometry).Text, pd.Name); } break; } } break; } } } } }
private void WriteAssociationProperty(AssociationPropertyDefinition assoc) { if(assoc.AssociatedClass != null) Console.WriteLine("\tAssociated Class: {0}", assoc.AssociatedClass.Name); if (assoc.IdentityProperties != null) { Console.WriteLine("\tIdentity Properties:"); foreach (DataPropertyDefinition data in assoc.IdentityProperties) { Console.WriteLine("\t\t- {0}", data.Name); } } Console.WriteLine("\tDelete Rule: {0}", assoc.DeleteRule); Console.WriteLine("\tRead-Only: {0}\n\tLock Cascade: {1}", assoc.IsReadOnly, assoc.LockCascade); Console.WriteLine("\tMultiplicity: {0}", assoc.Multiplicity); Console.WriteLine("\tProperty Type: {0}", assoc.PropertyType); if (assoc.ReverseIdentityProperties != null) { Console.WriteLine("\tReverse Identity Properties:"); foreach (DataPropertyDefinition data in assoc.ReverseIdentityProperties) { Console.WriteLine("\t\t- {0}", data.Name); } } Console.WriteLine("\tReverse Multiplicity: {0}\n\tReverse Name: {1}", assoc.ReverseMultiplicity, assoc.ReverseName); }
/// <summary> /// Utility method to clone a feature schema /// </summary> /// <param name="fs"></param> /// <param name="ignoreDeleted"></param> /// <returns></returns> public static FeatureSchema CloneSchema(FeatureSchema fs, bool ignoreDeleted) { if (fs == null) throw new ArgumentNullException("fs"); /* * This method is BIG. So it needs some explanation. * * Because Association and Object Properties reference other classes, the classes * containing such properties are processed *last*. Everything else is assumed to * be cloned (without problems) and cached in a temp dictionary for processing these * classes w/ Association/Object properties. * * When processing these remaining classes, we iteratively attempt to clone each class. * Each successfully cloned class will be added to the temp dictionary. Eventually all * references will be satisfied, that's when we can finally return the cloned schema. */ Dictionary<string, ClassDefinition> cloned = new Dictionary<string,ClassDefinition>(); List<ClassDefinition> classesWithReferences = new List<ClassDefinition>(); FeatureSchema fsc = new FeatureSchema(fs.Name, fs.Description); CopyElementAttributes(fs.Attributes, fsc.Attributes); if (ignoreDeleted) { foreach (ClassDefinition cls in fs.Classes) { if (cls.ElementState != SchemaElementState.SchemaElementState_Deleted) { ICollection<string> refs = GetReferencedClasses(cls); if (refs.Count == 0) { var klass = CloneClass(cls, ignoreDeleted); fsc.Classes.Add(klass); cloned.Add(klass.QualifiedName, klass); } else { //Check for self-references classesWithReferences.Add(cls); } } } } else { foreach (ClassDefinition cls in fs.Classes) { ICollection<string> refs = GetReferencedClasses(cls); if (refs.Count == 0) { var klass = CloneClass(cls, ignoreDeleted); fsc.Classes.Add(klass); cloned.Add(klass.QualifiedName, klass); } else { //Check for self-references classesWithReferences.Add(cls); } } } //TODO: Does the FDO spec allow self-referenced Association/Object //properties? If not, it would simplify this code greatly. //Repeat until all references satisfied while (classesWithReferences.Count > 0) { List<ClassDefinition> successfullyCloned = new List<ClassDefinition>(); foreach (ClassDefinition cls in classesWithReferences) { bool bSuccess = false; ClassDefinition klass = null; switch (cls.ClassType) { case ClassType.ClassType_Class: klass = new Class(cls.Name, cls.Description); break; case ClassType.ClassType_FeatureClass: klass = new FeatureClass(cls.Name, cls.Description); break; } Dictionary<AssociationPropertyDefinition, AssociationPropertyDefinition> processAp = new Dictionary<AssociationPropertyDefinition, AssociationPropertyDefinition>(); Dictionary<ObjectPropertyDefinition, ObjectPropertyDefinition> processOp = new Dictionary<ObjectPropertyDefinition, ObjectPropertyDefinition>(); var props = cls.Properties; for (int i = 0; i < props.Count; i++) { var prop = props[i]; if (prop.PropertyType == PropertyType.PropertyType_AssociationProperty) { var ap = (AssociationPropertyDefinition)prop; var apClone = new AssociationPropertyDefinition(ap.Name, ap.Description); ClassDefinition associatedClass = null; associatedClass = cloned[ap.AssociatedClass.QualifiedName]; if (associatedClass == null) { //could be a self-reference if (klass.Name.Equals(ap.AssociatedClass.Name)) associatedClass = klass; } if (associatedClass != null) { apClone.AssociatedClass = associatedClass; apClone.DeleteRule = ap.DeleteRule; //Process identity properties. Shelve for later processing if //any property can't be found var idProps = ap.IdentityProperties; bool foundAll = true; foreach (DataPropertyDefinition dp in idProps) { if (!props.Contains(dp)) foundAll = false; } if (foundAll) { foreach (DataPropertyDefinition dp in idProps) { apClone.IdentityProperties.Add((DataPropertyDefinition)props[dp.Name]); } } else { processAp.Add(apClone, ap); } apClone.LockCascade = ap.LockCascade; apClone.Multiplicity = ap.Multiplicity; //Process reverse identity properties. Shelve for later processing if //any property can't be found var ridProps = ap.ReverseIdentityProperties; foundAll = true; foreach (DataPropertyDefinition dp in ridProps) { if (!props.Contains(dp)) foundAll = false; } if (foundAll) { foreach (DataPropertyDefinition dp in ridProps) { apClone.ReverseIdentityProperties.Add((DataPropertyDefinition)apClone.AssociatedClass.Properties[dp.Name]); } } else { processAp.Add(apClone, ap); } apClone.ReverseMultiplicity = ap.ReverseMultiplicity; apClone.ReverseName = ap.ReverseName; klass.Properties.Add(apClone); } else { break; } } else if (prop.PropertyType == PropertyType.PropertyType_ObjectProperty) { var op = (ObjectPropertyDefinition)prop; var opClone = new ObjectPropertyDefinition(op.Name, op.Description); if (cloned.ContainsKey(op.Class.QualifiedName)) { ClassDefinition associatedClass = cloned[op.Class.QualifiedName]; opClone.Class = associatedClass; //Process identity property. Shelve for later processing if none found if (props.Contains(op.IdentityProperty.Name)) { opClone.IdentityProperty = (DataPropertyDefinition)op.Class.Properties[op.IdentityProperty.Name]; } else { processOp.Add(opClone, op); } opClone.ObjectType = op.ObjectType; opClone.OrderType = op.OrderType; klass.Properties.Add(opClone); } else { break; } } else { bool identity = false; bool geometry = false; var dp = prop as DataPropertyDefinition; var gp = prop as GeometricPropertyDefinition; identity = (dp != null && cls.IdentityProperties.Contains(dp)); geometry = (gp != null && cls.ClassType == ClassType.ClassType_FeatureClass && ((FeatureClass)cls).GeometryProperty == gp); //Clone property and add to cloned class var cp = CloneProperty(prop); klass.Properties.Add(cp); if (identity) { Debug.Assert(cp.PropertyType == PropertyType.PropertyType_DataProperty); klass.IdentityProperties.Add((DataPropertyDefinition)cp); } if (geometry) { Debug.Assert(cp.PropertyType == PropertyType.PropertyType_GeometricProperty); Debug.Assert(klass.ClassType == ClassType.ClassType_FeatureClass); ((FeatureClass)klass).GeometryProperty = (GeometricPropertyDefinition)cp; } } } if (processAp.Count > 0) { foreach (AssociationPropertyDefinition apClone in processAp.Keys) { var ap = processAp[apClone]; //Retry identity properties apClone.IdentityProperties.Clear(); var idProps = ap.IdentityProperties; foreach (DataPropertyDefinition dp in idProps) { apClone.IdentityProperties.Add((DataPropertyDefinition)props[dp.Name]); } //Retry reverse identity properties apClone.ReverseIdentityProperties.Clear(); var ridProps = ap.ReverseIdentityProperties; foreach (DataPropertyDefinition dp in ridProps) { apClone.ReverseIdentityProperties.Add((DataPropertyDefinition)apClone.AssociatedClass.Properties[dp.Name]); } } } if (processOp.Count > 0) { foreach (ObjectPropertyDefinition opClone in processOp.Keys) { var op = processOp[opClone]; //Retry identity property opClone.IdentityProperty = (DataPropertyDefinition)op.Class.Properties[op.IdentityProperty.Name]; } } //All properties accounted for if (klass.Properties.Count == cls.Properties.Count && klass.IdentityProperties.Count == cls.IdentityProperties.Count) { bSuccess = true; } if (bSuccess) { fsc.Classes.Add(klass); successfullyCloned.Add(cls); } } //Purge successfully cloned entries foreach (ClassDefinition cls in successfullyCloned) { int ridx = classesWithReferences.IndexOf(cls); if (ridx >= 0) classesWithReferences.RemoveAt(ridx); } } return fsc; }
/// <summary> /// Initializes the table from a reader /// </summary> /// <param name="reader">The reader.</param> /// <param name="origClass">The original class definition</param> /// <param name="ignorePk">If true, will not convert the identity properties of the class definition to primary keys</param> public void InitTable(IFdoReader reader, ClassDefinition origClass, bool ignorePk) { this.Columns.Clear(); this.TableName = reader.GetClassName(); string[] geometries = reader.GeometryProperties; _geometryColumn = reader.DefaultGeometryProperty; List <DataColumn> pk = new List <DataColumn>(); for (int i = 0; i < reader.FieldCount; i++) { string name = reader.GetName(i); FdoPropertyType ptype = reader.GetFdoPropertyType(name); if (ptype == FdoPropertyType.Raster) { //Raster's can't conceivably be previewed in tabular form, so omit it } else if (ptype == FdoPropertyType.Object) { // because the original code used an iterator over the reader.FieldCount // it is a bit of a hack to get another definition of the class and check // we are at the right property with a name comparison // TODO: code review to see if this can be implemented better FdoFeatureReader readerFeature = (FdoFeatureReader)reader; ClassDefinition classDef = readerFeature.GetClassDefinition(); foreach (PropertyDefinition propertyDef in classDef.Properties) { // only looking for the right association if ((PropertyType.PropertyType_ObjectProperty == propertyDef.PropertyType) && (propertyDef.Name.Equals(name))) { ObjectPropertyDefinition objectProp = (ObjectPropertyDefinition)propertyDef; ClassDefinition classDefObject = objectProp.Class; // TODO: this should be an iterative function? foreach (PropertyDefinition propertyDefObject in classDefObject.Properties) { String nameObject = propertyDefObject.Name; // TODO: find a better way to convert types Type type = "".GetType(); // TODO: handle data and iterative associations and objects if (PropertyType.PropertyType_DataProperty == propertyDefObject.PropertyType) { DataPropertyDefinition datapropertyDefObject = (DataPropertyDefinition)propertyDefObject; DataType ptAssoc = datapropertyDefObject.DataType; switch (ptAssoc) { case DataType.DataType_String: type = "".GetType(); break; } DataColumn dc = this.Columns.Add(name + "." + nameObject, type); } else if (PropertyType.PropertyType_GeometricProperty == propertyDefObject.PropertyType) { type = typeof(FdoGeometry); DataColumn dc = this.Columns.Add(name + "." + nameObject, type); } } } } } else if (ptype == FdoPropertyType.Association) { // because the original code used an iterator over the reader.FieldCount // it is a bit of a hack to get another definition of the class and check // we are at the right property with a name comparison // TODO: code review to see if this can be implemented better FdoFeatureReader readerFeature = (FdoFeatureReader)reader; ClassDefinition classDef = readerFeature.GetClassDefinition(); foreach (PropertyDefinition propertyDef in classDef.Properties) { // only looking for the right association if ((PropertyType.PropertyType_AssociationProperty == propertyDef.PropertyType) && (propertyDef.Name.Equals(name))) { AssociationPropertyDefinition assocProp = (AssociationPropertyDefinition)propertyDef; ClassDefinition classDefAssoc = assocProp.AssociatedClass; // TODO: this should be an iterative function? foreach (PropertyDefinition propertyDefAssoc in classDefAssoc.Properties) { String nameAssoc = propertyDefAssoc.Name; // TODO: find a better way to convert types Type type = typeof(String); // TODO: handle data and iterative associations and objects if (PropertyType.PropertyType_DataProperty == propertyDefAssoc.PropertyType) { DataPropertyDefinition datapropertyDefAssoc = (DataPropertyDefinition)propertyDefAssoc; DataType ptAssoc = datapropertyDefAssoc.DataType; switch (ptAssoc) { case DataType.DataType_String: type = typeof(String); break; } DataColumn dc = this.Columns.Add(name + "." + nameAssoc, type); } else if (PropertyType.PropertyType_GeometricProperty == propertyDefAssoc.PropertyType) { type = typeof(FdoGeometry); DataColumn dc = this.Columns.Add(name + "." + nameAssoc, type); } } } } } else { Type type = reader.GetFieldType(i); if (Array.IndexOf <string>(geometries, name) >= 0) { type = typeof(FdoGeometry); string assoc = reader.GetSpatialContextAssociation(name); if (!string.IsNullOrEmpty(assoc)) { this.RequestSpatialContext(this, assoc); } } DataColumn dc = this.Columns.Add(name, type); if (origClass != null) { //HACK: If this query is the result of the join, the returned Class Definition may have some //fubar constraints applied to it. So use the original Class Definition var idProps = origClass.IdentityProperties; if (ptype != FdoPropertyType.Geometry && idProps.Contains(name)) { pk.Add(dc); } } else { if (ptype != FdoPropertyType.Geometry && reader.IsIdentity(name)) { pk.Add(dc); } } } } if (pk.Count > 0 && !ignorePk) { this.PrimaryKey = pk.ToArray(); } }