diff --git a/NAV Source Control Test Host/Program.cs b/NAV Source Control Test Host/Program.cs
index d89e7c6..5a895db 100644
--- a/NAV Source Control Test Host/Program.cs
+++ b/NAV Source Control Test Host/Program.cs
@@ -44,7 +44,7 @@ namespace NavScm.TestHost
log.DebugFormat("Row {6}/{7}: Type {0}, ID {1}, Name {2}, Modified {3} {4}, Version {5}",
o.Type, o.ID, o.Name, o.Date.ToShortDateString(), o.Time.ToShortTimeString(), o.Version_List, i++, count);
- foundObjects.Add(String.Format("{0}.{1}", o.Type, o.ID), o);
+ foundObjects.Add(o.CacheKey, o);
}
log.InfoFormat("Collection has {0} entries, writing to cache.xml", foundObjects.Count);
diff --git a/NAVSCM Library/NavInterface/NavObject.cs b/NAVSCM Library/NavInterface/NavObject.cs
index 2e04e4a..f2a0493 100644
--- a/NAVSCM Library/NavInterface/NavObject.cs
+++ b/NAVSCM Library/NavInterface/NavObject.cs
@@ -7,8 +7,141 @@ using System.Threading.Tasks;
namespace NavScm.NavInterface
{
- partial class NavObject
+ ///
+ /// Adds a mapping between the NAV SQL Type field an enum to make its handling easier.
+ ///
+ public enum NavObjectType
{
-
+ TableData = 0,
+ Table = 1,
+ Report = 3,
+ Codeunit = 5,
+ XmlPort = 6,
+ MenuSuite = 7,
+ Page = 8,
+ Query = 9
+ }
+
+ ///
+ ///
+ /// This class wraps the actual NAV Object table data retrieved from the target database.
+ /// It adds additional helper functions to manage the cache accociated with it.
+ ///
+ ///
+ /// Note, that equality is defined by the DB primary key, which in turn includes
+ /// Type and ID. See CacheKey
+ /// for details. This sequence is also used for ordering of the object in case of
+ /// a sorted output.
+ ///
+ ///
+ /// Note, that object entries with a Company Name set are rejected at this point. They
+ /// result (probably) from a multi-tenancy/extension setup, which we do not support at
+ /// this time. As well, objects with unknown object types are rejected.
+ ///
+ ///
+ ///
+ ///
+ partial class NavObject : IEquatable, IComparable, IComparable
+ {
+ ///
+ /// Validate restrictions on supported objects as outlined in the class description.
+ ///
+ partial void OnLoaded()
+ {
+ if (Company_Name.Length > 0)
+ throw new InvalidOperationException($"The object {CacheKey} holds a variant with the company name {Company_Name}, which is unsupported");
+ if (Type < 0 || Type == 2 || Type == 4 || Type > 9)
+ throw new InvalidOperationException($"The object type of {CacheKey} is unsupported");
+ }
+
+ ///
+ /// Casts the SQL type to the corresponding Enum.
+ ///
+ public NavObjectType NavType
+ {
+ get { return (NavObjectType)Type; }
+ }
+
+ ///
+ ///
+ /// Constructs an object cache key to uniquely identify the object out of its type and ID.
+ /// Uses the string representation to make debugging easier. The equality operator maps to
+ /// this key as well.
+ ///
+ ///
+ /// Note, that the company Name is ignored here, as we do not support this scenario at this
+ /// time and throw an error just in case.
+ ///
+ ///
+ public string CacheKey
+ {
+ get {
+ return $"{Type}.{ID}";
+ }
+ }
+
+ ///
+ /// Converts the Date and Time fields to a combined Date/Time value.
+ ///
+ public DateTime Modified
+ {
+ get
+ {
+ return Date.Add(Time.TimeOfDay);
+ }
+ }
+
+ ///
+ /// Constructs a hash key based on Type and ID.
+ ///
+ /// Take 4 Bits of object Type and 28 bits of the actual object ID and shuffle them around
+ /// to create the hash key.
+ public override int GetHashCode()
+ {
+ return
+ // lower 8 bits of ID first
+ (ID << 24)
+ // second byte of ID goes next
+ & ((ID << 8) ^ 0x00ff0000)
+ // third byte of ID goes next
+ & ((ID >> 8) ^ 0x0000ff00)
+ // lower 4 bits of fourth ID byte go next
+ & ((ID >> 20) ^ 0x000000f0)
+ // finally add the first four bits of the Type
+ & (Type ^ 0x0000000f)
+ ;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is NavObject)) return false;
+ return Equals((NavObject) obj);
+ }
+
+ public bool Equals(NavObject other)
+ {
+ return Type == other.Type
+ && ID == other.ID;
+ }
+
+ public int CompareTo(NavObject other)
+ {
+ if (Type < other.Type)
+ return -1;
+ if (Type > other.Type)
+ return +1;
+ if (ID < other.ID)
+ return -1;
+ if (ID > other.ID)
+ return +1;
+ return 0;
+ }
+
+ public int CompareTo(object obj)
+ {
+ if (!(obj is NavObject))
+ throw new InvalidOperationException("obj is not an NavObject");
+ return this.CompareTo((NavObject)obj);
+ }
}
}