/// ------------------------------------------------------------------------------------ /// <summary> /// Test the Prop method. /// </summary> /// <param name="hvo">HVO part of the key</param> /// <param name="tag">tag part of the key</param> /// <param name="expValue">Expected value</param> /// <param name="type">The field type of <paramref name="expValue"/></param> /// <remarks>The C++ implementation only supports 32 and 64bit integers and /// (non-multilingual) strings.</remarks> /// ------------------------------------------------------------------------------------ protected virtual void CheckProp(int hvo, int tag, object expValue, CellarModuleDefns type) { object val = m_ISilDataAccess.get_Prop(hvo, tag); if (type == CellarModuleDefns.kcptTime || type == CellarModuleDefns.kcptInteger || type == CellarModuleDefns.kcptString) { Assert.AreEqual(expValue, val); } else { Assert.AreEqual(null, val); } }
/// <summary> /// Get the field values as a dict, keyed by field ID, for any CmObject. /// </summary> /// <returns>A dictionary with integer field ID mapped to values.</returns> /// <param name="cache">LCM cache the object lives in.</param> /// <param name="obj">Object whose fields we're getting.</param> protected IDictionary <int, object> GetFieldValues(LcmCache cache, ICmObject obj) { IFwMetaDataCacheManaged mdc = cache.ServiceLocator.MetaDataCache; ISilDataAccess data = cache.DomainDataByFlid; int[] fieldIds = mdc.GetFields(obj.ClassID, false, (int)CellarPropertyTypeFilter.All); var fieldValues = new Dictionary <int, object>(); foreach (int flid in fieldIds) { if (mdc.IsCustom(flid)) { continue; // Custom fields get processed differently } string fieldName = mdc.GetFieldNameOrNull(flid); if (String.IsNullOrEmpty(fieldName)) { continue; } object value = data.get_Prop(obj.Hvo, flid); fieldValues[flid] = value; } return(fieldValues); }
public void AutoLoad() { // Get the language project as an FDO object ILangProject lp = m_fdoCache.LangProject; // Use it to get the HVO of the data notebook, but without making an FDO object // and thus loading data. Assert.IsTrue(m_sda.get_IsPropInCache(lp.Hvo, (int)LangProject.LangProjectTags.kflidResearchNotebook, (int)CellarModuleDefns.kcptOwningAtom, 0), "LP notebook loaded by FDO"); int hvoNotebook = m_fdoCache.GetObjProperty(lp.Hvo, (int)LangProject.LangProjectTags.kflidResearchNotebook); // Owning atomic Assert.IsFalse(m_sda.get_IsPropInCache(hvoNotebook, (int)RnResearchNbk.RnResearchNbkTags.kflidEventTypes, (int)CellarModuleDefns.kcptOwningAtom, 0), "Notebook event types not preloaded"); int hvoEventTypes = m_sda.get_ObjectProp(hvoNotebook, (int)RnResearchNbk.RnResearchNbkTags.kflidEventTypes); Assert.IsTrue(m_sda.get_IsPropInCache(hvoNotebook, (int)RnResearchNbk.RnResearchNbkTags.kflidEventTypes, (int)CellarModuleDefns.kcptOwningAtom, 0), "Notebook event types autoloaded"); Assert.IsTrue(hvoEventTypes != 0, "got real event types"); int flidET = m_sda.get_IntProp(hvoEventTypes, (int)CmObjectFields.kflidCmObject_OwnFlid); Assert.AreEqual((int)RnResearchNbk.RnResearchNbkTags.kflidEventTypes, flidET, "owning flid loaded correctly"); int clsidET = m_sda.get_IntProp(hvoEventTypes, (int)CmObjectFields.kflidCmObject_Class); Assert.AreEqual((int)CmPossibilityList.kClassId, clsidET, "class autoloaded"); int ownerET = m_sda.get_ObjectProp(hvoEventTypes, (int)CmObjectFields.kflidCmObject_Owner); Assert.AreEqual(hvoNotebook, ownerET, "owner auto-loaded"); // Todo: test ref atomic. // Owning collection. Assert.IsFalse(m_sda.get_IsPropInCache(hvoNotebook, (int)RnResearchNbk.RnResearchNbkTags.kflidRecords, (int)CellarModuleDefns.kcptOwningCollection, 0), "Nb records not preloaded"); // Forces a load int chvoRecs = m_sda.get_VecSize(hvoNotebook, (int)RnResearchNbk.RnResearchNbkTags.kflidRecords); Assert.IsTrue(m_sda.get_IsPropInCache(hvoNotebook, (int)RnResearchNbk.RnResearchNbkTags.kflidRecords, (int)CellarModuleDefns.kcptOwningCollection, 0), "Nb records autoloaded"); // Be careful what we assert...don't want it too dependent on the exact data. // Should be OK to assume at least a few records. Assert.IsTrue(chvoRecs > 4, "at least 4 recs"); int hvoRec3 = m_sda.get_VecItem(hvoNotebook, (int)RnResearchNbk.RnResearchNbkTags.kflidRecords, 3); int clsIDR3 = m_sda.get_IntProp(hvoRec3, (int)CmObjectFields.kflidCmObject_Class); Assert.IsTrue((int)RnEvent.kClassId == clsIDR3 || (int)RnAnalysis.kClassId == clsIDR3, "class of rec 3 valid"); Assert.IsFalse(m_sda.get_IsPropInCache(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidResearchers, (int)CellarModuleDefns.kcptReferenceCollection, 0), "R3 researchers not preloaded"); int chvoR3Researchers = m_sda.get_VecSize(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidResearchers); Assert.IsTrue(m_sda.get_IsPropInCache(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidResearchers, (int)CellarModuleDefns.kcptReferenceCollection, 0), "R3 researchers autoloaded"); // We can't assume anything about any one record, but we should be able to find // at least one where researchers is non-empty. Along the way we do at least // some testing of VecProp and also make sure we can load a string that is a // BigString bool fGotEmpty = false; bool fGotNonEmpty = false; bool fGotEvent = false; int hvoEvent = 0; // some record will be an event... int hvoText = 0; // that has a non-empty structured text... int hvoPara = 0; // that has a non-empty paragraph with a label. for (int ihvo = 0; ihvo < chvoRecs && ((!fGotEmpty) || (!fGotNonEmpty) || (!fGotEvent) || hvoText == 0); ihvo++) { int hvoRec = m_sda.get_VecItem(hvoNotebook, (int)RnResearchNbk.RnResearchNbkTags.kflidRecords, ihvo); int chvoResearchers = m_sda.get_VecSize(hvoRec, (int)RnGenericRec.RnGenericRecTags.kflidResearchers); if (chvoResearchers > 0) { if (!fGotNonEmpty) { fGotNonEmpty = true; // Try this on the first non-empty list. int hvoResearcher = m_sda.get_VecItem(hvoRec, (int)RnGenericRec.RnGenericRecTags.kflidResearchers, 0); int clsidResearcher = m_sda.get_IntProp(hvoResearcher, (int)CmObjectFields.kflidCmObject_Class); Assert.AreEqual(CmPerson.kClassId, clsidResearcher, "class of researcher"); } } else { fGotEmpty = true; // should now be considered cached anyway. Assert.IsTrue(m_sda.get_IsPropInCache(hvoRec, (int)RnGenericRec.RnGenericRecTags.kflidResearchers, (int)CellarModuleDefns.kcptReferenceCollection, 0), "empty researchers autoloaded"); } int clsIDRec = m_sda.get_IntProp(hvoRec, (int)CmObjectFields.kflidCmObject_Class); if (clsIDRec == (int)RnEvent.kClassId && !fGotEvent) { hvoEvent = hvoRec; hvoText = m_sda.get_ObjectProp(hvoEvent, (int)RnEvent.RnEventTags.kflidDescription); if (hvoText != 0) { int chvo; using (ArrayPtr arrayPtr = MarshalEx.ArrayToNative(1000, typeof(int))) { // if there's a description with more than 1000 paragraphs this will break and // we'll fix it then. m_sda.VecProp(hvoText, (int)StText.StTextTags.kflidParagraphs, 1000, out chvo, arrayPtr); int[] rgHvo = (int[])MarshalEx.NativeToArray(arrayPtr, chvo, typeof(int)); // search for the paragraph that has non-empty label (there are a couple). for (int ihvoPara = 0; ihvoPara < chvo; ++ihvoPara) { hvoPara = rgHvo[ihvoPara]; // BigString ITsString tssPara = m_sda.get_StringProp(hvoPara, (int)StTxtPara.StTxtParaTags.kflidContents); if (tssPara.Length > 0) { string sname = m_sda.get_UnicodeProp(hvoPara, (int)StPara.StParaTags.kflidStyleName); if (sname != null && sname.Length > 0) { fGotEvent = true; } // Todo: it would be nice to test UnicodePropRgch, but we can't test // on the same prop because it's already loaded. Also, the modification // for data loading is shared code. We could make another cache instance // to test from, maybe? Or keep searching till we find another instance? // Could also look for a kcptBigUnicode, but implementation is identical. } } } } } } Assert.IsTrue(fGotEmpty && fGotNonEmpty, "found both empty and non-empty researcher lists"); Assert.IsTrue(hvoEvent != 0, "got at least one event"); // todo: test sequence (somehow verify order). // todo: test ref seq/collection (verify it does NOT set the owner to the referring obj). // Ref atomic Assert.IsFalse(m_sda.get_IsPropInCache(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidConfidence, (int)CellarModuleDefns.kcptReferenceAtom, 0), "R3 confidence not preloaded"); int hvoConfidence = m_sda.get_ObjectProp(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidConfidence); Assert.IsTrue(m_sda.get_IsPropInCache(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidConfidence, (int)CellarModuleDefns.kcptReferenceAtom, 0), "R3 confidence autoloaded"); if (hvoConfidence != 0) { int clsidConfidence = m_sda.get_IntProp(hvoConfidence, (int)CmObjectFields.kflidCmObject_Class); Assert.AreEqual(CmPossibility.kClassId, clsidConfidence, "class of confidence"); } // TsString. Assert.IsFalse(m_sda.get_IsPropInCache(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidTitle, (int)CellarModuleDefns.kcptString, 0), "title of rec 3 not preloaded"); ITsString qtssRec3Title = m_sda.get_StringProp(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidTitle); Assert.IsTrue(m_sda.get_IsPropInCache(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidTitle, (int)CellarModuleDefns.kcptString, 0), "autoloaded title of rec 3"); // Int (e.g., gendate) Assert.IsFalse(m_sda.get_IsPropInCache(hvoEvent, (int)RnEvent.RnEventTags.kflidDateOfEvent, (int)CellarModuleDefns.kcptInteger, 0), "date of event not preloaded"); int nDateEvent = m_sda.get_IntProp(hvoEvent, (int)RnEvent.RnEventTags.kflidDateOfEvent); Assert.IsTrue(m_sda.get_IsPropInCache(hvoEvent, (int)RnEvent.RnEventTags.kflidDateOfEvent, (int)CellarModuleDefns.kcptInteger, 0), "autoloaded date of event"); // Todo: find example of int64 prop and test. // Test loading of binary data (into a TsTextProps). object obj = m_sda.get_UnknownProp(hvoPara, (int)StPara.StParaTags.kflidStyleRules); Assert.IsNotNull(obj as ITsTextProps); // Also loading of raw binary data, using the same prop. using (ArrayPtr rgbData = MarshalEx.ArrayToNative(10000, typeof(byte))) { int cb = -1; m_sda.BinaryPropRgb(hvoPara, (int)StPara.StParaTags.kflidStyleRules, rgbData, 10000, out cb); Assert.IsTrue(cb > 0, "got some bytes using BinaryPropRgb"); // Enhance JohnT: wish I could figure what they ought to be and test... // Get a UserView object (they have no owner, so go direct) SqlConnection con = new SqlConnection(string.Format("Server={0}; Database={1}; User ID = fwdeveloper;" + "Password=careful; Pooling=false;", m_fdoCache.ServerName, m_fdoCache.DatabaseName)); con.Open(); SqlCommand cmd = con.CreateCommand(); cmd.CommandText = "select top 2 id from UserView"; SqlDataReader reader = cmd.ExecuteReader(); reader.Read(); int hvoUv = reader.GetInt32(0); reader.Close(); con.Close(); // Guid prop Guid guidUv = m_sda.get_GuidProp(hvoUv, (int)UserView.UserViewTags.kflidApp); Assert.IsFalse(guidUv == Guid.Empty, "got non-empty guid"); // Time prop long lEventTime = m_sda.get_TimeProp(hvoEvent, (int)RnGenericRec.RnGenericRecTags.kflidDateCreated); Assert.IsFalse(lEventTime == 0, "got meaningful time"); // Enhance JohnT: really verify. // Int prop int viewSubtype = m_sda.get_IntProp(hvoUv, (int)UserView.UserViewTags.kflidSubType); // Enhance JohnT: think of a way to verify... // get_Prop: Time object objMod = m_sda.get_Prop(hvoRec3, (int)RnGenericRec.RnGenericRecTags.kflidDateModified); Assert.IsTrue(objMod is long); // get_Prop: String int hvoRec0 = m_sda.get_VecItem(hvoNotebook, (int)RnResearchNbk.RnResearchNbkTags.kflidRecords, 0); object objTitle = m_sda.get_Prop(hvoRec0, (int)RnGenericRec.RnGenericRecTags.kflidTitle); Assert.IsTrue(objTitle is ITsString, "get_Prop title is string"); // get_Prop: Int object objType = m_sda.get_Prop(hvoUv, (int)UserView.UserViewTags.kflidType); Assert.IsTrue(objType is int, "get_Prop type is integer"); // Confirm some more results by loading through FDO ICmObject objRec3 = CmObject.CreateFromDBObject(m_fdoCache, hvoRec3); Assert.IsTrue(objRec3 is IRnGenericRec, "object of correct type"); IRnGenericRec grRec3 = (IRnGenericRec)objRec3; // I'd prefer to use full ITsString equality test, but not sure how to get // a regular ITsString from FDO obj. Assert.AreEqual(qtssRec3Title.Text, grRec3.Title.Text, "two ways to retrieve R3 title match"); // Can't try this yet because FDO GenDate not yet implemented. The data type might not // be right anyway. // CmObject objEvent = CmObject.CreateFromDBObject(m_fdoCache, hvoEvent); // Assert.IsTrue(objEvent is RnEvent, "type of event"); // RnEvent ev1 = (RnEvent) objEvent; // Assert.AreEqual(ev1.DateOfEvent, nDateEvent, "date of event matches"); } }
/// <summary> /// /// </summary> /// <param name="hvo"></param> /// <param name="tag"></param> /// <returns></returns> public object get_Prop(int hvo, int tag) { return(m_sda.get_Prop(hvo, tag)); }
/// <summary> /// Read an arbitrary property as a variant. The view subsystem does not care what /// kind of value you put in the variant. However, when you use AddProp, the view /// subsystem calls back to Prop to get the variant which is then passed to /// DisplayVariant. DisplayVariant must be prepared to handle whatever Prop puts there. /// If you put an IUnknown or IDispatch value in the variant, the Views code will /// call Release once on that object. Normally you should pass a ${SmartVariant}. /// S_FALSE (and variant VTEMPTY) if no known value for this property, or /// if the implemetation does not know how to represent it as a variant. Current /// implementations can represent 32 and 64 bit integers and (nonmultilingual) strings. /// Some implementations may return S_OK and variant VTEMPTY. ///</summary> /// <param name='hvo'> </param> /// <param name='tag'> </param> /// <returns></returns> public virtual object get_Prop(int hvo, int tag) { return(m_baseSda.get_Prop(hvo, tag)); }