Example #1
0
        /// <summary>Gets the direct subclasses of the given class (not including itself).</summary>
        /// <param name='clid'>Class indentifier to work with.</param>
        /// <param name='countMaximumToReturn'>Count of the maximum number of subclass IDs to return (Size of the array.)
        /// When set to zero, countDirectSubclasses will contain the full count, so a second call can use the right sized array.</param>
        /// <param name='countDirectSubclasses'>Count of how many subclass IDs are the output array.</param>
        /// <param name='subclasses'>Array of subclass IDs.</param>
        public void GetDirectSubclasses(System.UInt32 clid,
                                        int countMaximumToReturn, out int countDirectSubclasses,
                                        [MarshalAs(UnmanagedType.CustomMarshaler,
                                                   MarshalTypeRef = typeof(ArrayPtrMarshaler),
                                                   SizeParamIndex = 1)] ArrayPtr /*ULONG[]*/ subclasses)
        {
            countDirectSubclasses = 0;             // Start with 0 for output parameter.
            uint[] uIds = new uint[countMaximumToReturn];
            if (!m_metaClassRecords.ContainsKey(clid))
            {
                throw new ArgumentException("Class not found.");
            }
            MetaClassRec mcr = m_metaClassRecords[clid];

            countDirectSubclasses = mcr.m_directSubclasses.Count;
            if (countMaximumToReturn == 0)
            {
                return;                 // Client only wanted the count.
            }
            if (countMaximumToReturn < countDirectSubclasses)
            {
                throw new ArgumentException("Output array is too small.", "countMaximumToReturn");
            }
            int iSubclassClid = 0;

            for (int i = 0; i < mcr.m_directSubclasses.Count; ++i)
            {
                uIds[iSubclassClid++] = mcr.m_directSubclasses[i];
            }
            MarshalEx.ArrayToNative(subclasses, countMaximumToReturn, uIds);
        }
Example #2
0
        /// <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);
        }
Example #3
0
        /// <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);
        }
Example #4
0
        /// <summary>Gets the name of the base class for a given class.</summary>
        /// <param name='clid'>Class identification number.</param>
        /// <returns>Output name of the base class.</returns>
        public string GetBaseClsName(System.UInt32 clid)
        {
            if (clid == 0)
            {
                throw new ArgumentException("CmObject has no base class.");
            }
            MetaClassRec mcr = m_metaClassRecords[clid];

            mcr = m_metaClassRecords[mcr.m_baseClsid] as MetaClassRec;
            return(mcr.m_className);
        }
Example #5
0
        private void GetAllSubclassesForClid(uint clid, List <uint> allSubclassClids)
        {
            MetaClassRec mcr = m_metaClassRecords[clid];

            for (int i = 0; i < mcr.m_directSubclasses.Count; ++i)
            {
                uint subClassClid = mcr.m_directSubclasses[i];
                allSubclassClids.Add(subClassClid);
                GetAllSubclassesForClid(subClassClid, allSubclassClids);
            }
        }
Example #6
0
        /// <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);
        }
Example #7
0
        /// <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;
            }
        }
Example #8
0
 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;
 }
Example #9
0
        /// <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;
            }
        }
Example #10
0
        /// <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);
        }
Example #11
0
		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;
		}
Example #12
0
		/// <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;
			}
		}
Example #13
0
		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);
		}
Example #14
0
		/// <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);
		}
Example #15
0
        /// <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);
        }