/// <summary> /// Given a field id and a class id, /// this returns true if it is legal to store this class of object /// (or any of its superclasses) in the field. /// </summary> /// <param name='flid'>Field identification number.</param> /// <param name='clid'>Class identification number.</param> /// <returns>A System.Boolean</returns> public bool get_IsValidClass(System.UInt32 flid, System.UInt32 clid) { if (!m_metaFieldRecords.ContainsKey(flid)) { throw new ArgumentException("Invalid field identifier", "flid"); } MetaFieldRec mfr = m_metaFieldRecords[flid]; //if (mfr.m_dstClsid <= 0) // return false; if (mfr.m_dstClsid == clid) { return(IsObjectFieldType(mfr.m_fieldType)); } // Check superclasses. MetaClassRec mcr; do { mcr = m_metaClassRecords[clid]; clid = mcr.m_baseClsid; if (mfr.m_dstClsid == clid) { return(IsObjectFieldType(mfr.m_fieldType)); } } while (clid != 0); return(false); }
/// <summary>Gets the "Id" of the destination class that corresponds to this field.</summary> /// <param name='flid'>Field identification number.</param> /// <returns>Output "Id" of the class that contains the field.</returns> public uint GetDstClsId(System.UInt32 flid) { // Zero is not acceptable. CheckFlid(flid); MetaFieldRec mfr = m_metaFieldRecords[flid]; return(mfr.m_dstClsid); }
/// <summary> /// Gets a list of the fields for the specified class. /// Fields of superclasses are also returned, if the relevant flag is true. /// </summary> /// <param name='clid'>Class identification number.</param> /// <param name='includeSuperclasses'>'True' to also get superclass fields.</param> /// <param name='fieldTypes'> /// Gets all fields whose types match the specified argument, /// which should be a combination of the fcpt values defined in CmTypes.h, e.g., /// to get all owning properties pass kfcptOwningCollection | kfcptOwningAtom | kfcptOwningSequence. /// </param> /// <param name='countFlidMax'> /// Size of the 'flids' array. /// (Use 0 to get the size to use in a second call to actually get them.)</param> /// <param name='flids'>Array of flids.</param> /// <returns> /// Count of flids that are returned, /// or that could be returned, if 'countFlidMax' is 0.</returns> /// <exception cref="ArgumentException"> /// Thrown if the output array is too small. /// </exception> public int GetFields(System.UInt32 clid, bool includeSuperclasses, int fieldTypes, int countFlidMax, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ArrayPtrMarshaler), SizeParamIndex = 3)] ArrayPtr /*ULONG[]*/ flids) { int countFlids = 0; int iflid = 0; uint currentClid = clid; uint[] uIds = new uint[countFlidMax]; // This loop executes once if fIncludeSuperclasses is false, otherwise over clid // and all superclasses. for (; ;) { MetaClassRec mcr = m_metaClassRecords[currentClid]; for (int i = 0; i < mcr.m_fields.Count; ++i) { uint flid = mcr.m_fields[i]; MetaFieldRec mfr = m_metaFieldRecords[flid]; if (fieldTypes != (int)CellarModuleDefns.kgrfcptAll) { // Look up field type and see if it matches int flidType = mfr.m_fieldType; int fcpt = 1 << flidType; if ((fieldTypes & fcpt) == 0) { continue; // don't return this one } } countFlids++; if (countFlidMax > 0) { if (countFlids > countFlidMax) { throw new ArgumentException("Output array is too small.", "countFlidMax"); } uIds[iflid++] = flid; } } if (!includeSuperclasses) { break; } if (currentClid == 0) // just processed CmObject { break; } currentClid = mcr.m_baseClsid; } if (iflid > 0) { MarshalEx.ArrayToNative(flids, countFlidMax, uIds); } return(countFlids); }
/// <summary>Gets the "Id" value of the class that contains this field.</summary> /// <param name='flid'>Field identification number.</param> /// <returns>Output "Id" of the class that contains the field.</returns> public uint GetOwnClsId(System.UInt32 flid) { // 0 technically says that CmObject implements item. // Zero is not acceptable. CheckFlid(flid); MetaFieldRec mfr = m_metaFieldRecords[flid]; return(mfr.m_ownClsid); }
/// <summary> /// Gets the name of the destination class that corresponds to this field. /// This is the name of the class that is either owned or referred to by another class. /// </summary> /// <param name='flid'>Field identification number.</param> /// <returns>Name of the destination class.</returns> public string GetDstClsName(System.UInt32 flid) { // Zero is not acceptable. CheckFlid(flid); MetaFieldRec mfr = m_metaFieldRecords[flid]; MetaClassRec mcr = m_metaClassRecords[mfr.m_dstClsid]; return(mcr.m_className); }
/// <summary>Gets the name of the class that contains this field.</summary> /// <param name='flid'>Field identification number.</param> /// <returns>Name of the class that contains the field.</returns> public string GetOwnClsName(System.UInt32 flid) { // Zero is not acceptable. CheckFlid(flid); uint ulFlid = flid; if (!m_metaFieldRecords.ContainsKey(ulFlid)) { throw new ArgumentException("Invalid field identifier", "flid"); } MetaFieldRec mfr = m_metaFieldRecords[ulFlid]; MetaClassRec mcr = m_metaClassRecords[mfr.m_ownClsid]; return(mcr.m_className); }
/// <summary>Check if the given flid is virtual or regular.</summary> /// <param name='flid'>Field identifier to check.</param> /// <returns>'True' if 'flid' is a virtual field, otherwise 'false'. </returns> public bool get_IsVirtual(int flid) { MetaFieldRec mfr = m_metaFieldRecords[flid]; return(mfr.m_fType == FieldType.virt); }
/// <summary>Add a virtual property (field) to a class.</summary> /// <param name='className'>Name of the class that gets the new virtual property</param> /// <param name='fieldName'>Name of the new virtual Field.</param> /// <param name='virtualFlid'>Field identifier for the enw virtual field</param> /// <param name='iFieldType'> /// This type value indicates if the field is a primitive data type /// or a MultiStr/MultiTxt value or describes the relationship /// between two classes (i.e. owning/reference and atomic/collection/sequence). /// These numeric values are defined in CoreImpl\CellarPropertyType.cs. /// It must NOT have the virtual bit OR'd in. /// </param> public void AddVirtualProp(string className, string fieldName, int virtualFlid, int iFieldType) { CellarPropertyType fieldType = (CellarPropertyType)iFieldType; // Do various tests to make sure: // 1. The given className exists, // 2. The given fieldName does NOT exist for the given class, // 3. The given virtualFlid does NOT exist, and finally // 4. The fieldType is a legal value. // Will throw, if the classname doesn't exist, // dealing with #1, above. if (!m_nameToClid.ContainsKey(className)) throw new ArgumentException("Class not found."); var clid = m_nameToClid[className]; // Check condition #2, above. // JohnT changed the last argument to 'false'. MDC should allow override virtual handlers. var flid = GetFieldId2(clid, fieldName, false); if (flid > 0) throw new ArgumentException("Field name already exists.", "fieldName"); // Check condition #3, above. MetaFieldRec mfr; if (m_metaFieldRecords.ContainsKey(virtualFlid)) throw new ArgumentException("Field number already in use.", "virtualFlid"); // Test condition #4, above. // May throw if fieldType isn't valid. switch (fieldType) { default: throw new ArgumentException("Invalid field type.", "fieldType"); case CellarPropertyType.Boolean: case CellarPropertyType.Integer: case CellarPropertyType.Numeric: case CellarPropertyType.Float: case CellarPropertyType.Time: case CellarPropertyType.Guid: case CellarPropertyType.Image: case CellarPropertyType.GenDate: case CellarPropertyType.Binary: case CellarPropertyType.String: case CellarPropertyType.MultiString: case CellarPropertyType.Unicode: case CellarPropertyType.MultiUnicode: case CellarPropertyType.OwningAtomic: case CellarPropertyType.ReferenceAtomic: case CellarPropertyType.OwningCollection: case CellarPropertyType.ReferenceCollection: case CellarPropertyType.OwningSequence: case CellarPropertyType.ReferenceSequence: mfr = new MetaFieldRec { m_fieldType = fieldType, m_fieldName = fieldName, m_ownClsid = clid, m_fType = FieldType.virt }; MetaClassRec mcr = m_metaClassRecords[clid]; InstallField(mcr, clid, mfr.m_fieldName, virtualFlid, mfr); break; } }
private void InstallField(MetaClassRec mcr, int clid, string fieldName, int flid, MetaFieldRec mfr) { mcr.m_fields.Add(flid); m_metaFieldRecords[flid] = mfr; m_nameToFlid[MakeFlidKey(clid, fieldName)] = flid; }
/// <summary> /// Initialize the meta-data fields required to be on the base class (which must be the base for /// all other classes. /// </summary> /// <param name="doc">The XML document containing the model</param> private void InitBaseClassMetaFields(XmlDocument doc) { int clid = 0; int flid; MetaClassRec mcr; MetaFieldRec mfr; if (!m_metaClassRecords.ContainsKey(clid)) { XmlNode baseClassNode = doc.DocumentElement.SelectSingleNode("class[@num='0']"); // Add CmObject properties. string baseClassName = (baseClassNode == null) ? "BaseClass" : XmlUtils.GetManditoryAttributeValue(baseClassNode, "id"); mcr = new MetaClassRec(baseClassName, true, baseClassName); flid = (int)CmObjectFields.kflidCmObject_Guid; mfr = new MetaFieldRec { m_fieldType = CellarPropertyType.Guid, m_fieldName = "Guid$", m_ownClsid = clid }; InstallField(mcr, clid, "Guid$", flid, mfr); flid = (int)CmObjectFields.kflidCmObject_Class; mfr = new MetaFieldRec { m_fieldType = CellarPropertyType.Integer, m_fieldName = "Class$", m_ownClsid = clid }; InstallField(mcr, clid, "Class$", flid, mfr); flid = (int)CmObjectFields.kflidCmObject_Owner; mfr = new MetaFieldRec { m_fieldType = CellarPropertyType.ReferenceAtomic, m_fieldName = "Owner$", m_ownClsid = clid }; InstallField(mcr, clid, "Owner$", flid, mfr); flid = (int)CmObjectFields.kflidCmObject_OwnFlid; mfr = new MetaFieldRec { m_fieldType = CellarPropertyType.Integer, m_fieldName = "OwnFlid$", m_ownClsid = clid }; InstallField(mcr, clid, "OwnFlid$", flid, mfr); flid = (int)CmObjectFields.kflidCmObject_OwnOrd; mfr = new MetaFieldRec { m_fieldType = CellarPropertyType.Integer, m_fieldName = "OwnOrd$", m_ownClsid = clid }; InstallField(mcr, clid, "OwnOrd$", flid, mfr); m_metaClassRecords[clid] = mcr; m_nameToClid[baseClassName] = clid; } }
public void InitXml(string pathname, bool clearPrevCache) { if (pathname == null) throw new ArgumentNullException("pathname"); if (m_pathnames.Contains(pathname)) throw new ArgumentException(String.Format("File '{0}' has already been processed.", pathname)); var doc = new XmlDocument(); using (TextReader xmlStream = FileUtils.OpenFileForRead(pathname, Encoding.UTF8)) { doc.Load(xmlStream); var classes = doc.SelectNodes("EntireModel"); if (classes.Count == 0) throw new ArgumentException("No classes found."); if (clearPrevCache) { m_metaFieldRecords.Clear(); m_metaClassRecords.Clear(); m_nameToClid.Clear(); m_nameToFlid.Clear(); } InitBaseClassMetaFields(doc); int clid; int flid; MetaClassRec mcr; MetaFieldRec mfr; // Spin through each module now. foreach (XmlNode newClassNode in doc.DocumentElement) { clid = XmlUtils.GetMandatoryIntegerAttributeValue(newClassNode, "num"); if (clid > 0) // Basic initialization has already happened for the base class. { var newClassName = XmlUtils.GetManditoryAttributeValue(newClassNode, "id"); // Check to see if the class already exists. if (m_nameToClid.ContainsKey(newClassName)) throw new ArgumentException("Duplicate Cellar Class named; " + newClassName); mcr = new MetaClassRec(XmlUtils.GetOptionalAttributeValue(newClassNode, "base", newClassName), XmlUtils.GetBooleanAttributeValue(newClassNode, "abstract"), newClassName); m_metaClassRecords[clid] = mcr; m_nameToClid[newClassName] = clid; } else mcr = m_metaClassRecords[clid]; // Spin through the properties now. var flidBase = clid * 1000; foreach (XmlNode fieldNode in newClassNode.SelectNodes("props/*")) { flid = flidBase + XmlUtils.GetMandatoryIntegerAttributeValue(fieldNode, "num"); mfr = new MetaFieldRec { m_fieldName = XmlUtils.GetManditoryAttributeValue(fieldNode, "id"), m_ownClsid = clid, m_sig = XmlUtils.GetManditoryAttributeValue(fieldNode, "sig") }; if (m_nameToClid.ContainsKey(mfr.m_sig)) { mfr.m_dstClsid = m_nameToClid[mfr.m_sig]; mfr.m_sig = null; } // /basic | props/owning | props/rel switch (fieldNode.Name) { default: break; case "basic": switch (mfr.m_sig) { case "TextPropBinary": mfr.m_fieldType = CellarPropertyType.Binary; break; case "Boolean": mfr.m_fieldType = CellarPropertyType.Boolean; break; case "Integer": mfr.m_fieldType = CellarPropertyType.Integer; break; case "Time": mfr.m_fieldType = CellarPropertyType.Time; break; case "String": mfr.m_fieldType = CellarPropertyType.String; break; case "MultiString": mfr.m_fieldType = CellarPropertyType.MultiString; break; case "Unicode": mfr.m_fieldType = CellarPropertyType.Unicode; break; case "MultiUnicode": mfr.m_fieldType = CellarPropertyType.MultiUnicode; break; case "Guid": mfr.m_fieldType = CellarPropertyType.Guid; break; case "Image": mfr.m_fieldType = CellarPropertyType.Image; break; case "GenDate": mfr.m_fieldType = CellarPropertyType.GenDate; break; case "Binary": mfr.m_fieldType = CellarPropertyType.Binary; break; case "Numeric": mfr.m_fieldType = CellarPropertyType.Numeric; break; case "Float": mfr.m_fieldType = CellarPropertyType.Float; break; } mfr.m_sig = null; break; case "owning": switch (XmlUtils.GetManditoryAttributeValue(fieldNode, "card")) { case "atomic": mfr.m_fieldType = CellarPropertyType.OwningAtomic; break; case "col": mfr.m_fieldType = CellarPropertyType.OwningCollection; break; case "seq": mfr.m_fieldType = CellarPropertyType.OwningSequence; break; } break; case "rel": switch (XmlUtils.GetManditoryAttributeValue(fieldNode, "card")) { case "atomic": mfr.m_fieldType = CellarPropertyType.ReferenceAtomic; break; case "col": mfr.m_fieldType = CellarPropertyType.ReferenceCollection; break; case "seq": mfr.m_fieldType = CellarPropertyType.ReferenceSequence; break; } break; } // Add mfr. InstallField(mcr, clid, mfr.m_fieldName, flid, mfr); } } // Some mfr objects may not have been able to set their m_dstClsid member, // if the referenced class had not been loaded yet. // So, try to connect them now. // If the client is using multiple files, they may not be set until the last file is loaded. foreach (var kvp in m_metaFieldRecords) { mfr = kvp.Value; if (mfr.m_sig == null || !m_nameToClid.ContainsKey(mfr.m_sig)) continue; mfr.m_dstClsid = m_nameToClid[mfr.m_sig]; mfr.m_sig = null; } // Get direct subclass ids. // Also set the superclass id. foreach (var kvp in m_metaClassRecords) { mcr = kvp.Value; var clidChild = kvp.Key; var clidBase = m_nameToClid[mcr.m_superclassName]; mcr.m_baseClsid = clidBase; if (clidChild == clidBase) continue; // CmObject. if (!m_metaClassRecords.ContainsKey(clidBase)) continue; var recBase = m_metaClassRecords[clidBase]; recBase.m_directSubclasses.Add(clidChild); } } // Keep the good pathname in case we need to reload. m_pathnames.Add(pathname); }
/// <summary> /// Gets the type of the field. /// </summary> /// <param name='flid'>Field identification number.</param> /// <returns>Output field type</returns> /// <remarks> /// This type value indicates if the field is a primitive data type /// or a MultiStr/MultiBigStr/MultiTxt/MultiBigTxt value or describes the relationship /// between two classes (i.e. owning/reference and atomic/collection/sequence). /// These numeric values are defined in the 'FWROOT\src\cellar\lib\CmTypes.h' file. /// </remarks> public int GetFieldType(System.UInt32 flid) { MetaFieldRec mfr = m_metaFieldRecords[flid]; return(mfr.m_fieldType); }
/// <summary>Gets the listRoot of the field.</summary> /// <param name='flid'>Field identification number.</param> /// <returns>Output field ListRoot. (May be 0, if not found.)</returns> public int GetFieldListRoot(System.UInt32 flid) { MetaFieldRec mfr = m_metaFieldRecords[flid]; return(mfr.m_fieldListRoot); }
/// <summary>Gets the Xml UI of a field.</summary> /// <param name='flid'>Field identification number.</param> /// <returns>Output name of the field. (May be null, if not found.)</returns> public string GetFieldXml(System.UInt32 flid) { MetaFieldRec mfr = m_metaFieldRecords[flid]; return(mfr.m_fieldXml); }
/// <summary>Initialize MetaDataCache using an XML file.</summary> /// <param name='pathname'>pathname</param> /// <param name='clearPrevCache'>clearPrevCache</param> /// <remarks> /// Any number of files can be loaded using this method, but calls after the first time should use false for clearPrevCache. /// See Ling.cm or xmi2cellar3.xml for supported XML data formats. /// Note: This may also be used to load persisted custom fields. /// </remarks> public void InitXml(string pathname, bool clearPrevCache) { if (pathname == null) { throw new ArgumentNullException("pathname"); } if (m_pathnames.Contains(pathname)) { throw new ArgumentException(String.Format("File '{0}' has already been processed.", pathname)); } var doc = new XmlDocument(); using (TextReader xmlStream = FileUtils.OpenFileForRead(pathname, Encoding.UTF8)) { doc.Load(xmlStream); var classes = doc.SelectNodes("EntireModel"); if (classes.Count == 0) { throw new ArgumentException("No classes found."); } if (clearPrevCache) { m_metaFieldRecords.Clear(); m_metaClassRecords.Clear(); m_nameToClid.Clear(); m_nameToFlid.Clear(); } InitBaseClassMetaFields(doc); int clid; int flid; MetaClassRec mcr; MetaFieldRec mfr; // Spin through each module now. foreach (XmlNode newClassNode in doc.DocumentElement) { clid = XmlUtils.GetMandatoryIntegerAttributeValue(newClassNode, "num"); if (clid > 0) // Basic initialization has already happened for the base class. { var newClassName = XmlUtils.GetManditoryAttributeValue(newClassNode, "id"); // Check to see if the class already exists. if (m_nameToClid.ContainsKey(newClassName)) { throw new ArgumentException("Duplicate Cellar Class named; " + newClassName); } mcr = new MetaClassRec(XmlUtils.GetOptionalAttributeValue(newClassNode, "base", newClassName), XmlUtils.GetBooleanAttributeValue(newClassNode, "abstract"), newClassName); m_metaClassRecords[clid] = mcr; m_nameToClid[newClassName] = clid; } else { mcr = m_metaClassRecords[clid]; } // Spin through the properties now. var flidBase = clid * 1000; foreach (XmlNode fieldNode in newClassNode.SelectNodes("props/*")) { flid = flidBase + XmlUtils.GetMandatoryIntegerAttributeValue(fieldNode, "num"); mfr = new MetaFieldRec { m_fieldName = XmlUtils.GetManditoryAttributeValue(fieldNode, "id"), m_ownClsid = clid, m_sig = XmlUtils.GetManditoryAttributeValue(fieldNode, "sig") }; if (m_nameToClid.ContainsKey(mfr.m_sig)) { mfr.m_dstClsid = m_nameToClid[mfr.m_sig]; mfr.m_sig = null; } // /basic | props/owning | props/rel switch (fieldNode.Name) { default: break; case "basic": switch (mfr.m_sig) { case "TextPropBinary": mfr.m_fieldType = CellarPropertyType.Binary; break; case "Boolean": mfr.m_fieldType = CellarPropertyType.Boolean; break; case "Integer": mfr.m_fieldType = CellarPropertyType.Integer; break; case "Time": mfr.m_fieldType = CellarPropertyType.Time; break; case "String": mfr.m_fieldType = CellarPropertyType.String; break; case "MultiString": mfr.m_fieldType = CellarPropertyType.MultiString; break; case "Unicode": mfr.m_fieldType = CellarPropertyType.Unicode; break; case "MultiUnicode": mfr.m_fieldType = CellarPropertyType.MultiUnicode; break; case "Guid": mfr.m_fieldType = CellarPropertyType.Guid; break; case "Image": mfr.m_fieldType = CellarPropertyType.Image; break; case "GenDate": mfr.m_fieldType = CellarPropertyType.GenDate; break; case "Binary": mfr.m_fieldType = CellarPropertyType.Binary; break; case "Numeric": mfr.m_fieldType = CellarPropertyType.Numeric; break; case "Float": mfr.m_fieldType = CellarPropertyType.Float; break; } mfr.m_sig = null; break; case "owning": switch (XmlUtils.GetManditoryAttributeValue(fieldNode, "card")) { case "atomic": mfr.m_fieldType = CellarPropertyType.OwningAtomic; break; case "col": mfr.m_fieldType = CellarPropertyType.OwningCollection; break; case "seq": mfr.m_fieldType = CellarPropertyType.OwningSequence; break; } break; case "rel": switch (XmlUtils.GetManditoryAttributeValue(fieldNode, "card")) { case "atomic": mfr.m_fieldType = CellarPropertyType.ReferenceAtomic; break; case "col": mfr.m_fieldType = CellarPropertyType.ReferenceCollection; break; case "seq": mfr.m_fieldType = CellarPropertyType.ReferenceSequence; break; } break; } // Add mfr. InstallField(mcr, clid, mfr.m_fieldName, flid, mfr); } } // Some mfr objects may not have been able to set their m_dstClsid member, // if the referenced class had not been loaded yet. // So, try to connect them now. // If the client is using multiple files, they may not be set until the last file is loaded. foreach (var kvp in m_metaFieldRecords) { mfr = kvp.Value; if (mfr.m_sig == null || !m_nameToClid.ContainsKey(mfr.m_sig)) { continue; } mfr.m_dstClsid = m_nameToClid[mfr.m_sig]; mfr.m_sig = null; } // Get direct subclass ids. // Also set the superclass id. foreach (var kvp in m_metaClassRecords) { mcr = kvp.Value; var clidChild = kvp.Key; var clidBase = m_nameToClid[mcr.m_superclassName]; mcr.m_baseClsid = clidBase; if (clidChild == clidBase) { continue; // CmObject. } if (!m_metaClassRecords.ContainsKey(clidBase)) { continue; } var recBase = m_metaClassRecords[clidBase]; recBase.m_directSubclasses.Add(clidChild); } } // Keep the good pathname in case we need to reload. m_pathnames.Add(pathname); }
/// <summary>Initialize MetaDataCache using an XML file.</summary> /// <param name='pathname'>pathname</param> /// <param name='clearPrevCache'>clearPrevCache</param> /// <remarks> /// Any number of files can be loaded using this method, but calls after the first time should use false for clearPrevCache. /// See Ling.cm or xmi2cellar3.xml for supported XML data formats. /// Note: This may also be used to load persisted custom fields. /// </remarks> public void InitXml(string pathname, bool clearPrevCache) { if (pathname == null) throw new ArgumentNullException("pathname"); if (m_pathnames.Contains(pathname)) throw new ArgumentException(String.Format("File '{0}' has already been processed.", pathname)); XmlDocument doc = new XmlDocument(); doc.Load(pathname); XmlNodeList cellarModules = doc.SelectNodes("CellarModule"); if (cellarModules.Count == 0) cellarModules = doc.SelectNodes("EntireModel/CellarModule"); if (cellarModules.Count == 0) throw new ArgumentException("No CellarModules to work with."); if (clearPrevCache) { m_metaFieldRecords.Clear(); m_metaClassRecords.Clear(); m_nameToClid.Clear(); m_nameToFlid.Clear(); } uint clid = 0; uint flid; MetaClassRec mcr; MetaFieldRec mfr; if (!m_metaClassRecords.ContainsKey(clid)) { // Add CmObject properties. mcr = new MetaClassRec("CmObject", true, "CmObject"); flid = (uint)CmObjectFields.kflidCmObject_Guid; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptGuid; mfr.m_fieldName = "Guid$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "Guid$", flid, mfr); flid = (uint)CmObjectFields.kflidCmObject_Class; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptInteger; mfr.m_fieldName = "Class$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "Class$", flid, mfr); flid = (uint)CmObjectFields.kflidCmObject_Owner; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptReferenceAtom; mfr.m_fieldName = "Owner$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "Owner$", flid, mfr); flid = (uint)CmObjectFields.kflidCmObject_OwnFlid; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptInteger; mfr.m_fieldName = "OwnFlid$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "OwnFlid$", flid, mfr); flid = (uint)CmObjectFields.kflidCmObject_OwnOrd; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptInteger; mfr.m_fieldName = "OwnOrd$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "OwnOrd$", flid, mfr); m_metaClassRecords[clid] = mcr; m_nameToClid["CmObject"] = clid; } // Spin through each module now. foreach (XmlNode newModule in cellarModules) { uint clidBase = (uint)XmlUtils.GetMandatoryIntegerAttributeValue(newModule, "num") * 1000; // Spin through each class which is not CmObject. // Get each class whose 'num' attribute is greater than 0. foreach (XmlNode newClassNode in newModule.SelectNodes("class[@num!=0]")) { string newClassName = XmlUtils.GetManditoryAttributeValue(newClassNode, "id"); // Check to see if the class already exists. if (m_nameToClid.ContainsKey(newClassName)) throw new ArgumentException("Duplicate Cellar Class named; " + newClassName); clid = clidBase + (uint)XmlUtils.GetMandatoryIntegerAttributeValue(newClassNode, "num"); mcr = new MetaClassRec(XmlUtils.GetManditoryAttributeValue(newClassNode, "base"), XmlUtils.GetBooleanAttributeValue(newClassNode, "abstract"), newClassName); m_metaClassRecords[clid] = mcr; m_nameToClid[newClassName] = clid; // Spin through the properties now. uint flidBase = clid * 1000; foreach (XmlNode fieldNode in newClassNode.SelectNodes("props/*")) { flid = flidBase + (uint)XmlUtils.GetMandatoryIntegerAttributeValue(fieldNode, "num"); mfr = new MetaFieldRec(); mfr.m_fieldName = XmlUtils.GetManditoryAttributeValue(fieldNode, "id"); mfr.m_ownClsid = clid; mfr.m_fieldLabel = XmlUtils.GetOptionalAttributeValue(fieldNode, "userlabel", null); mfr.m_fieldHelp = XmlUtils.GetOptionalAttributeValue(fieldNode, "fieldhelp", null); mfr.m_fieldXml = XmlUtils.GetOptionalAttributeValue(fieldNode, "fieldxml", null); mfr.m_fieldListRoot = XmlUtils.GetOptionalIntegerValue(fieldNode, "listroot", 0); mfr.m_fieldWs = XmlUtils.GetOptionalIntegerValue(fieldNode, "wsselector", 0); mfr.m_sig = XmlUtils.GetManditoryAttributeValue(fieldNode, "sig"); if (m_nameToClid.ContainsKey(mfr.m_sig)) { mfr.m_dstClsid = m_nameToClid[mfr.m_sig]; mfr.m_sig = null; } // /basic | props/owning | props/rel switch (fieldNode.Name) { default: break; case "basic": bool isBig = XmlUtils.GetOptionalBooleanAttributeValue(fieldNode, "big", false); switch (mfr.m_sig) { case "Boolean": mfr.m_fieldType = (int)CellarModuleDefns.kcptBoolean; break; case "Integer": mfr.m_fieldType = (int)CellarModuleDefns.kcptInteger; break; case "Time": mfr.m_fieldType = (int)CellarModuleDefns.kcptTime; break; case "String": mfr.m_fieldType = (isBig) ? (int)CellarModuleDefns.kcptBigString : (int)CellarModuleDefns.kcptString; break; case "MultiString": mfr.m_fieldType = (isBig) ? (int)CellarModuleDefns.kcptMultiBigString : (int)CellarModuleDefns.kcptMultiString; break; case "Unicode": mfr.m_fieldType = (isBig) ? (int)CellarModuleDefns.kcptBigUnicode : (int)CellarModuleDefns.kcptUnicode; break; case "MultiUnicode": mfr.m_fieldType = (isBig) ? (int)CellarModuleDefns.kcptMultiBigUnicode : (int)CellarModuleDefns.kcptMultiUnicode; break; case "Guid": mfr.m_fieldType = (int)CellarModuleDefns.kcptGuid; break; case "Image": mfr.m_fieldType = (int)CellarModuleDefns.kcptImage; break; case "GenDate": mfr.m_fieldType = (int)CellarModuleDefns.kcptGenDate; break; case "Binary": mfr.m_fieldType = (int)CellarModuleDefns.kcptBinary; break; case "Numeric": mfr.m_fieldType = (int)CellarModuleDefns.kcptNumeric; break; case "Float": mfr.m_fieldType = (int)CellarModuleDefns.kcptFloat; break; } mfr.m_sig = null; break; case "owning": switch (XmlUtils.GetManditoryAttributeValue(fieldNode, "card")) { case "atomic": mfr.m_fieldType = (int)CellarModuleDefns.kcptOwningAtom; break; case "col": mfr.m_fieldType = (int)CellarModuleDefns.kcptOwningCollection; break; case "seq": mfr.m_fieldType = (int)CellarModuleDefns.kcptOwningSequence; break; } break; case "rel": switch (XmlUtils.GetManditoryAttributeValue(fieldNode, "card")) { case "atomic": mfr.m_fieldType = (int)CellarModuleDefns.kcptReferenceAtom; break; case "col": mfr.m_fieldType = (int)CellarModuleDefns.kcptReferenceCollection; break; case "seq": mfr.m_fieldType = (int)CellarModuleDefns.kcptReferenceSequence; break; } break; } // Add mfr. InstallField(mcr, clid, mfr.m_fieldName, flid, mfr); } } } // Some mfr objects may not have been able to set their m_dstClsid member, // if the referenced class had not been loaded yet. // So, try to connect them now. // If the client is using multiple files, they may not be set until the last file is loaded. foreach (KeyValuePair<uint, MetaFieldRec> kvp in m_metaFieldRecords) { mfr = kvp.Value; if (mfr.m_sig != null && m_nameToClid.ContainsKey(mfr.m_sig)) { mfr.m_dstClsid = m_nameToClid[mfr.m_sig]; mfr.m_sig = null; } } // Get direct subclass ids. // Also set the superclass id. foreach (KeyValuePair<uint, MetaClassRec> kvp in m_metaClassRecords) { mcr = kvp.Value; uint clidChild = kvp.Key; uint clidBase = m_nameToClid[mcr.m_superclassName]; mcr.m_baseClsid = clidBase; if (clidChild == clidBase) continue; // CmObject. if (m_metaClassRecords.ContainsKey(clidBase)) { MetaClassRec recBase = m_metaClassRecords[clidBase] as MetaClassRec; recBase.m_directSubclasses.Add(clidChild); } } // Keep the good pathname in case we need to reload. m_pathnames.Add(pathname); }
/// <summary>Add a virtual property (field) to a class.</summary> /// <param name='className'>Name of the class that gets the new virtual property</param> /// <param name='fieldName'>Name of the new virtual Field.</param> /// <param name='virtualFlid'>Field identifier for the enw virtual field</param> /// <param name='iFieldType'> /// This type value indicates if the field is a primitive data type /// or a MultiStr/MultiTxt value or describes the relationship /// between two classes (i.e. owning/reference and atomic/collection/sequence). /// These numeric values are defined in CoreImpl\CellarPropertyType.cs. /// It must NOT have the virtual bit OR'd in. /// </param> public void AddVirtualProp(string className, string fieldName, int virtualFlid, int iFieldType) { CellarPropertyType fieldType = (CellarPropertyType)iFieldType; // Do various tests to make sure: // 1. The given className exists, // 2. The given fieldName does NOT exist for the given class, // 3. The given virtualFlid does NOT exist, and finally // 4. The fieldType is a legal value. // Will throw, if the classname doesn't exist, // dealing with #1, above. if (!m_nameToClid.ContainsKey(className)) { throw new ArgumentException("Class not found."); } var clid = m_nameToClid[className]; // Check condition #2, above. // JohnT changed the last argument to 'false'. MDC should allow override virtual handlers. var flid = GetFieldId2(clid, fieldName, false); if (flid > 0) { throw new ArgumentException("Field name already exists.", "fieldName"); } // Check condition #3, above. MetaFieldRec mfr; if (m_metaFieldRecords.ContainsKey(virtualFlid)) { throw new ArgumentException("Field number already in use.", "virtualFlid"); } // Test condition #4, above. // May throw if fieldType isn't valid. switch (fieldType) { default: throw new ArgumentException("Invalid field type.", "fieldType"); case CellarPropertyType.Boolean: case CellarPropertyType.Integer: case CellarPropertyType.Numeric: case CellarPropertyType.Float: case CellarPropertyType.Time: case CellarPropertyType.Guid: case CellarPropertyType.Image: case CellarPropertyType.GenDate: case CellarPropertyType.Binary: case CellarPropertyType.String: case CellarPropertyType.MultiString: case CellarPropertyType.Unicode: case CellarPropertyType.MultiUnicode: case CellarPropertyType.OwningAtomic: case CellarPropertyType.ReferenceAtomic: case CellarPropertyType.OwningCollection: case CellarPropertyType.ReferenceCollection: case CellarPropertyType.OwningSequence: case CellarPropertyType.ReferenceSequence: mfr = new MetaFieldRec { m_fieldType = fieldType, m_fieldName = fieldName, m_ownClsid = clid, m_fType = FieldType.virt }; MetaClassRec mcr = m_metaClassRecords[clid]; InstallField(mcr, clid, mfr.m_fieldName, virtualFlid, mfr); break; } }
/// <summary>Initialize MetaDataCache using an XML file.</summary> /// <param name='pathname'>pathname</param> /// <param name='clearPrevCache'>clearPrevCache</param> /// <remarks> /// Any number of files can be loaded using this method, but calls after the first time should use false for clearPrevCache. /// See Ling.cm or xmi2cellar3.xml for supported XML data formats. /// Note: This may also be used to load persisted custom fields. /// </remarks> public void InitXml(string pathname, bool clearPrevCache) { if (pathname == null) { throw new ArgumentNullException("pathname"); } if (m_pathnames.Contains(pathname)) { throw new ArgumentException(String.Format("File '{0}' has already been processed.", pathname)); } XmlDocument doc = new XmlDocument(); doc.Load(pathname); XmlNodeList cellarModules = doc.SelectNodes("CellarModule"); if (cellarModules.Count == 0) { cellarModules = doc.SelectNodes("EntireModel/CellarModule"); } if (cellarModules.Count == 0) { throw new ArgumentException("No CellarModules to work with."); } if (clearPrevCache) { m_metaFieldRecords.Clear(); m_metaClassRecords.Clear(); m_nameToClid.Clear(); m_nameToFlid.Clear(); } uint clid = 0; uint flid; MetaClassRec mcr; MetaFieldRec mfr; if (!m_metaClassRecords.ContainsKey(clid)) { // Add CmObject properties. mcr = new MetaClassRec("CmObject", true, "CmObject"); flid = (uint)CmObjectFields.kflidCmObject_Guid; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptGuid; mfr.m_fieldName = "Guid$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "Guid$", flid, mfr); flid = (uint)CmObjectFields.kflidCmObject_Class; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptInteger; mfr.m_fieldName = "Class$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "Class$", flid, mfr); flid = (uint)CmObjectFields.kflidCmObject_Owner; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptReferenceAtom; mfr.m_fieldName = "Owner$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "Owner$", flid, mfr); flid = (uint)CmObjectFields.kflidCmObject_OwnFlid; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptInteger; mfr.m_fieldName = "OwnFlid$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "OwnFlid$", flid, mfr); flid = (uint)CmObjectFields.kflidCmObject_OwnOrd; mfr = new MetaFieldRec(); mfr.m_fieldType = (int)CellarModuleDefns.kcptInteger; mfr.m_fieldName = "OwnOrd$"; mfr.m_ownClsid = clid; InstallField(mcr, clid, "OwnOrd$", flid, mfr); m_metaClassRecords[clid] = mcr; m_nameToClid["CmObject"] = clid; } // Spin through each module now. foreach (XmlNode newModule in cellarModules) { uint clidBase = (uint)XmlUtils.GetMandatoryIntegerAttributeValue(newModule, "num") * 1000; // Spin through each class which is not CmObject. // Get each class whose 'num' attribute is greater than 0. foreach (XmlNode newClassNode in newModule.SelectNodes("class[@num!=0]")) { string newClassName = XmlUtils.GetManditoryAttributeValue(newClassNode, "id"); // Check to see if the class already exists. if (m_nameToClid.ContainsKey(newClassName)) { throw new ArgumentException("Duplicate Cellar Class named; " + newClassName); } clid = clidBase + (uint)XmlUtils.GetMandatoryIntegerAttributeValue(newClassNode, "num"); mcr = new MetaClassRec(XmlUtils.GetManditoryAttributeValue(newClassNode, "base"), XmlUtils.GetBooleanAttributeValue(newClassNode, "abstract"), newClassName); m_metaClassRecords[clid] = mcr; m_nameToClid[newClassName] = clid; // Spin through the properties now. uint flidBase = clid * 1000; foreach (XmlNode fieldNode in newClassNode.SelectNodes("props/*")) { flid = flidBase + (uint)XmlUtils.GetMandatoryIntegerAttributeValue(fieldNode, "num"); mfr = new MetaFieldRec(); mfr.m_fieldName = XmlUtils.GetManditoryAttributeValue(fieldNode, "id"); mfr.m_ownClsid = clid; mfr.m_fieldLabel = XmlUtils.GetOptionalAttributeValue(fieldNode, "userlabel", null); mfr.m_fieldHelp = XmlUtils.GetOptionalAttributeValue(fieldNode, "fieldhelp", null); mfr.m_fieldXml = XmlUtils.GetOptionalAttributeValue(fieldNode, "fieldxml", null); mfr.m_fieldListRoot = XmlUtils.GetOptionalIntegerValue(fieldNode, "listroot", 0); mfr.m_fieldWs = XmlUtils.GetOptionalIntegerValue(fieldNode, "wsselector", 0); mfr.m_sig = XmlUtils.GetManditoryAttributeValue(fieldNode, "sig"); if (m_nameToClid.ContainsKey(mfr.m_sig)) { mfr.m_dstClsid = m_nameToClid[mfr.m_sig]; mfr.m_sig = null; } // /basic | props/owning | props/rel switch (fieldNode.Name) { default: break; case "basic": bool isBig = XmlUtils.GetOptionalBooleanAttributeValue(fieldNode, "big", false); switch (mfr.m_sig) { case "Boolean": mfr.m_fieldType = (int)CellarModuleDefns.kcptBoolean; break; case "Integer": mfr.m_fieldType = (int)CellarModuleDefns.kcptInteger; break; case "Time": mfr.m_fieldType = (int)CellarModuleDefns.kcptTime; break; case "String": mfr.m_fieldType = (isBig) ? (int)CellarModuleDefns.kcptBigString : (int)CellarModuleDefns.kcptString; break; case "MultiString": mfr.m_fieldType = (isBig) ? (int)CellarModuleDefns.kcptMultiBigString : (int)CellarModuleDefns.kcptMultiString; break; case "Unicode": mfr.m_fieldType = (isBig) ? (int)CellarModuleDefns.kcptBigUnicode : (int)CellarModuleDefns.kcptUnicode; break; case "MultiUnicode": mfr.m_fieldType = (isBig) ? (int)CellarModuleDefns.kcptMultiBigUnicode : (int)CellarModuleDefns.kcptMultiUnicode; break; case "Guid": mfr.m_fieldType = (int)CellarModuleDefns.kcptGuid; break; case "Image": mfr.m_fieldType = (int)CellarModuleDefns.kcptImage; break; case "GenDate": mfr.m_fieldType = (int)CellarModuleDefns.kcptGenDate; break; case "Binary": mfr.m_fieldType = (int)CellarModuleDefns.kcptBinary; break; case "Numeric": mfr.m_fieldType = (int)CellarModuleDefns.kcptNumeric; break; case "Float": mfr.m_fieldType = (int)CellarModuleDefns.kcptFloat; break; } mfr.m_sig = null; break; case "owning": switch (XmlUtils.GetManditoryAttributeValue(fieldNode, "card")) { case "atomic": mfr.m_fieldType = (int)CellarModuleDefns.kcptOwningAtom; break; case "col": mfr.m_fieldType = (int)CellarModuleDefns.kcptOwningCollection; break; case "seq": mfr.m_fieldType = (int)CellarModuleDefns.kcptOwningSequence; break; } break; case "rel": switch (XmlUtils.GetManditoryAttributeValue(fieldNode, "card")) { case "atomic": mfr.m_fieldType = (int)CellarModuleDefns.kcptReferenceAtom; break; case "col": mfr.m_fieldType = (int)CellarModuleDefns.kcptReferenceCollection; break; case "seq": mfr.m_fieldType = (int)CellarModuleDefns.kcptReferenceSequence; break; } break; } // Add mfr. InstallField(mcr, clid, mfr.m_fieldName, flid, mfr); } } } // Some mfr objects may not have been able to set their m_dstClsid member, // if the referenced class had not been loaded yet. // So, try to connect them now. // If the client is using multiple files, they may not be set until the last file is loaded. foreach (KeyValuePair <uint, MetaFieldRec> kvp in m_metaFieldRecords) { mfr = kvp.Value; if (mfr.m_sig != null && m_nameToClid.ContainsKey(mfr.m_sig)) { mfr.m_dstClsid = m_nameToClid[mfr.m_sig]; mfr.m_sig = null; } } // Get direct subclass ids. // Also set the superclass id. foreach (KeyValuePair <uint, MetaClassRec> kvp in m_metaClassRecords) { mcr = kvp.Value; uint clidChild = kvp.Key; uint clidBase = m_nameToClid[mcr.m_superclassName]; mcr.m_baseClsid = clidBase; if (clidChild == clidBase) { continue; // CmObject. } if (m_metaClassRecords.ContainsKey(clidBase)) { MetaClassRec recBase = m_metaClassRecords[clidBase] as MetaClassRec; recBase.m_directSubclasses.Add(clidChild); } } // Keep the good pathname in case we need to reload. m_pathnames.Add(pathname); }