/// <summary> /// Reads a user-perceived feature ID using the specified naming tags. /// </summary> /// <param name="nativeField">The tag to use for a native ID.</param> /// <param name="foreignField">The tag to use for a foreign ID.</param> /// <returns>The user-perceived ID that was read (may be null)</returns> internal FeatureId ReadFeatureId(DataField nativeField, DataField foreignField) { if (IsNextField(nativeField)) { uint nativeKey = m_Reader.ReadUInt32(nativeField.ToString()); NativeId nid = MapModel.FindNativeId(nativeKey); if (nid == null) { return(MapModel.AddNativeId(nativeKey)); } else { return(nid); } } if (IsNextField(foreignField)) { string key = m_Reader.ReadString(foreignField.ToString()); ForeignId fid = MapModel.FindForeignId(key); if (fid == null) { return(MapModel.AddForeignId(key)); } else { return(fid); } } return(null); }
/// <summary> /// Tries to produce a numeric key. /// </summary> /// <param name="id">The raw ID to use (without any check digit).</param> /// <returns>The numeric key value (0 if a numeric key cannot be generated).</returns> internal uint GetNumericKey(uint id) { // If a check digit is required, and the raw ID exceeds 200 // million, it means that the numeric key wouldn't fit in // a 32-bit value. if (HasCheckDigit && id > 200000000) { return(0); } // If the key format is not completely numeric, we can't do it. if (!IsNumericKey()) { return(0); } // If a check digit is not required, the supplied raw ID is // the numeric key we want to store. if (!HasCheckDigit) { return(id); } // Work out the check digit and append it to the raw ID. uint checkdig = NativeId.GetCheckDigit(id); return(id * 10 + checkdig); }
/// <summary> /// Reads back an array of ID mappings, associating the user-perceived IDs with the /// corresponding spatial features. /// </summary> /// <param name="field">A tag associated with the array</param> internal void ReadIdMappings(DataField field) { if (!IsNextField(field)) { return; } IdMapping[] mapping = ReadPersistentArray <IdMapping>(field); for (int i = 0; i < mapping.Length; i++) { IdMapping m = mapping[i]; NativeId nid = MapModel.FindNativeId(m.RawId); if (nid == null) { nid = MapModel.AddNativeId(m.RawId); } Feature f = MapModel.Find <Feature>(m.InternalId); // Ignore null ref if we are dealing with the very last mapping of a connection path // (covers CEdit bug that produced spurious point at the end of the path). if (f == null) { //if (m_CurrentEdit is PathOperation && i == (mapping.Length - 1)) // break; throw new ApplicationException("Cannot locate feature for ID mapping: " + m); } f.SetId(nid); } }
/// <summary> /// Ensures this feature is clean after some sort of edit. If this feature has been marked /// for deletion (either deletion through a <see cref="DeletionOperation"/>, or because /// the creating edit is being rolled back), this ensures that any associated ID object /// no longer refers to this feature. /// <para/> /// Any override should first do it's stuff, then call this implementation. /// </summary> internal virtual void Clean() { // Return if this feature hasn't been marked for deletion if (!IsUndoing) { return; } // If this feature is active, but it doesn't appear to be indexed, // do it now. This is a bit of a kludge, meant to cover the fact // that lines are erroneously dropping out of the index after making // updates. //if (this.IsInactive == false && this.IsIndexed == false) // this.MapModel.EditingIndex.AddFeature(this); // Return if there is no feature ID. if (m_Id == null) { return; } // Cut the reference that the ID makes to this feature (the ID // may continue to point to other features). m_Id.CutReference(this); // Remove the the ID from its enclosing ID packet NativeId nid = (m_Id as NativeId); if (nid != null) { nid.IdGroup.ReleaseId(nid); } }
/// <summary> /// Restores (un-deletes) this feature. /// </summary> /// <returns>True if feature restored. False if the feature wasn't marked as inactive.</returns> internal virtual bool Restore() { // Return if this feature doesn't currently have the "inactive" state if (!IsInactive) { return(false); } // If this feature referred to an ID, restore it. if (m_Id != null) { // Ensure that the ID is cross-referenced to this feature. m_Id.AddReference(this); // That's pretty well it. When a feature is de-activated, only the back // pointer from the ID is nulled out. The feature retained it's pointer to the ID, // and the ID itself was left in place as part of the IdPacket to which it belongs. // For native IDs, the packet needs to be told to decrement the number of free // IDs. // TODO: This may be irrelevant (need to also review the logic when something is // de-activated). if (m_Id is NativeId) { IdManager idMan = MapModel.IdManager; if (idMan != null) { // Find the ID group that applies to the feature's // entity type (this will be null if the entity type was // not originally listed in the IdEntity table, or the // group is considered to be obsolete). IdGroup g = idMan.GetGroup(this.EntityType); // If we got a group (and the ID if not foreign) try to find // the ID packet that refers to the feature's ID. if (g != null) { NativeId nid = (m_Id as NativeId); IdPacket p = g.FindPacket(nid); p.RestoreId(m_Id); } } } } // Add back into the map index. MapModel.EditingIndex.AddFeature(this); // Remember that the feature is now active IsInactive = false; return(true); }
/// <summary> /// Release an allocated ID for a feature that is being removed due to an undo. /// This nulls out the reference to the ID from its enclosing ID packet. /// </summary> /// <param name="id">The ID that should be returned to the pool of available IDs.</param> internal void ReleaseId(NativeId id) { IdPacket p = FindPacket(id); if (p == null) { throw new ApplicationException("Cannot locate packet for ID: " + id.FormattedKey); } p.DeleteId(id); }
/// <summary> /// Records an ID if it belongs to this ID packet /// </summary> /// <param name="nid">The ID that may belong to this packet</param> /// <returns>True if the supplied ID has been recorded as part of /// this packet</returns> internal bool SetId(NativeId nid) { int index = GetIndex(nid.RawId); if (index < 0) { return(false); } m_Ids[index] = nid; return(true); }
/// <summary> /// Exhaustive search for the ID packet that refers to a specific ID. This method /// should only be called in situations where something has gone astray. /// </summary> /// <param name="fid">The ID to search for</param> /// <returns>The packet that contains the specified object (null if not found)</returns> internal IdPacket FindPacket(NativeId nid) { foreach (IdGroup g in m_IdGroups) { IdPacket p = g.FindPacket(nid); if (p != null) { return(p); } } return(null); }
/// <summary> /// Formats an ID number the way this ID group likes to see it. /// </summary> /// <param name="id">The raw ID to format (may not actually lie within the /// limits of this packet).</param> /// <returns>The formatted result.</returns> internal string FormatId(uint id) { // Apply the format assuming no check digit. string key = String.Format(KeyFormat, id); // If there really is a check digit, work it out and append it. if (HasCheckDigit) { uint cd = NativeId.GetCheckDigit(id); key += cd.ToString(); } return(key); }
/// <summary> /// Obtains any ID mappings for the features that are associated with an instance of <see cref="NativeId"/> /// </summary> /// <param name="features">The features of interest</param> /// <returns>The ID mappings for those features that have a native ID (never null, but could be an empty array).</returns> IdMapping[] GetIdMappings(Feature[] features) { List <IdMapping> result = new List <IdMapping>(features.Length); foreach (Feature f in features) { NativeId id = (f.FeatureId as NativeId); if (id != null) { result.Add(new IdMapping(f.InternalId, id.RawId)); } } return(result.ToArray()); }
/// <summary> /// Deletes an ID that this packet points to. This nulls out the reference to the ID, /// and should be called ONLY if the feature ID is being eliminated as a result of undo. /// </summary> /// <param name="fid">The feature ID to remove. At call, it should be inactive (not /// referring to anything).</param> /// <returns>True if ID reference has been nulled out.</returns> internal bool DeleteId(NativeId fid) { // Confirm the ID is inactive. if (!fid.IsInactive) { throw new Exception("IdPacket.DeleteId - ID is still in use"); } // Get the array index of the ID. int index = GetIndex(fid); if (index < 0) { return(false); } m_Ids[index] = null; return(true); }
/// <summary> /// Exhaustive search for the ID packet that refers to a specific ID. This method /// should only be called in situations where something has gone astray. /// </summary> /// <param name="fid">The ID to search for</param> /// <returns>The packet that contains the specified object (null if not found)</returns> internal IdPacket FindPacket(NativeId nid) { foreach (IdGroup g in m_IdGroups) { IdPacket p = g.FindPacket(nid); if (p!=null) return p; } return null; }
/// <summary> /// Exhaustive search for the ID packet that refers to a specific ID. /// </summary> /// <param name="fid">The ID to search for</param> /// <returns>The packet that contains the specified object (null if not found)</returns> internal IdPacket FindPacket(NativeId fid) { uint rawId = fid.RawId; return(m_Packets.Find(p => p.Contains(rawId))); }
/// <summary> /// Records an ID if it belongs to this ID packet /// </summary> /// <param name="nid">The ID that may belong to this packet</param> /// <returns>True if the supplied ID has been recorded as part of /// this packet</returns> internal bool SetId(NativeId nid) { int index = GetIndex(nid.RawId); if (index < 0) return false; m_Ids[index] = nid; return true; }
/// <summary> /// Deletes an ID that this packet points to. This nulls out the reference to the ID, /// and should be called ONLY if the feature ID is being eliminated as a result of undo. /// </summary> /// <param name="fid">The feature ID to remove. At call, it should be inactive (not /// referring to anything).</param> /// <returns>True if ID reference has been nulled out.</returns> internal bool DeleteId(NativeId fid) { // Confirm the ID is inactive. if (!fid.IsInactive) throw new Exception("IdPacket.DeleteId - ID is still in use"); // Get the array index of the ID. int index = GetIndex(fid); if (index < 0) return false; m_Ids[index] = null; return true; }
/// <summary> /// Release an allocated ID for a feature that is being removed due to an undo. /// This nulls out the reference to the ID from its enclosing ID packet. /// </summary> /// <param name="id">The ID that should be returned to the pool of available IDs.</param> internal void ReleaseId(NativeId id) { IdPacket p = FindPacket(id); if (p == null) throw new ApplicationException("Cannot locate packet for ID: " + id.FormattedKey); p.DeleteId(id); }
/// <summary> /// Creates a new feature ID that doesn't reference anything (and does not add it to the map model). /// </summary> /// <param name="id">The ID to create.</param> /// <returns>The created feature ID.</returns> internal FeatureId CreateId(uint id) { // Confirm that the specified ID falls within this range. if (id < (uint)Min || id > (uint)Max) { throw new Exception("IdPacket.CreateId - New ID is not in range!"); } // Confirm that the specified ID was previously reserved (if not, // see if it has already been created). int reserveIndex = FindReservedId(id); if (reserveIndex < 0) { string msg = String.Format("ID {0} d was not properly reserved.", id); throw new ApplicationException(msg); } // Confirm that the packet does not already refer to an active ID. int index = (int)id - Min; bool reuse = false; NativeId fid = m_Ids[index]; if (fid != null) { if (fid.IsInactive) { reuse = true; } else { throw new Exception("IdPacket.CreateId - ID slot has already been used."); } } // If we're not re-using an old ID, create one. if (!reuse) { string keystr; // The key string // Try to get a numeric key. uint keyval = m_Group.GetNumericKey(id); if (keyval != 0) { // If we got one, we still need to represent it as a string (for // the FeatureId constructor). However, we need to let the // constructor know that it's ok to convert it back to numeric! keystr = keyval.ToString(); } else { // Format the ID using the key format (+ possible check digit) keystr = m_Group.FormatId(id); } // Create the new ID fid = new NativeId(m_Group, id); m_Ids[index] = fid; } // Clear the reserve status m_ReservedIds.RemoveAt(reserveIndex); return(fid); }
/// <summary> /// Creates a new feature ID that doesn't reference anything (and does not add it to the map model). /// </summary> /// <param name="id">The ID to create.</param> /// <returns>The created feature ID.</returns> internal FeatureId CreateId(uint id) { // Confirm that the specified ID falls within this range. if (id<(uint)Min || id>(uint)Max) throw new Exception("IdPacket.CreateId - New ID is not in range!"); // Confirm that the specified ID was previously reserved (if not, // see if it has already been created). int reserveIndex = FindReservedId(id); if (reserveIndex < 0) { string msg = String.Format("ID {0} d was not properly reserved.", id); throw new ApplicationException(msg); } // Confirm that the packet does not already refer to an active ID. int index = (int)id - Min; bool reuse = false; NativeId fid = m_Ids[index]; if (fid!=null) { if (fid.IsInactive) reuse = true; else throw new Exception("IdPacket.CreateId - ID slot has already been used."); } // If we're not re-using an old ID, create one. if (!reuse) { string keystr; // The key string // Try to get a numeric key. uint keyval = m_Group.GetNumericKey(id); if (keyval!=0) { // If we got one, we still need to represent it as a string (for // the FeatureId constructor). However, we need to let the // constructor know that it's ok to convert it back to numeric! keystr = keyval.ToString(); } else { // Format the ID using the key format (+ possible check digit) keystr = m_Group.FormatId(id); } // Create the new ID fid = new NativeId(m_Group, id); m_Ids[index] = fid; } // Clear the reserve status m_ReservedIds.RemoveAt(reserveIndex); return fid; }
/// <summary> /// Exhaustive search for the ID packet that refers to a specific ID. /// </summary> /// <param name="fid">The ID to search for</param> /// <returns>The packet that contains the specified object (null if not found)</returns> internal IdPacket FindPacket(NativeId fid) { uint rawId = fid.RawId; return m_Packets.Find(p => p.Contains(rawId)); }