internal void AddField(int flid, string fieldName, CellarPropertyType cpt, int destClsid) { var clsid = flid / 1000; var mfi = new MockFieldInfo { m_flid = flid, m_name = fieldName, m_cpt = cpt, m_destClsid = destClsid, m_fCustom = false, m_fieldHelp = null, m_fieldWs = WritingSystemServices.kwsAnal, m_fieldListRoot = Guid.Empty }; m_fieldsById.Add(flid, mfi); List <MockFieldInfo> list; if (!m_fieldsByClassId.TryGetValue(clsid, out list)) { list = new List <MockFieldInfo>(); m_fieldsByClassId.Add(clsid, list); } list.Add(mfi); }
public void AddVirtualPropTest() { const int flid = 2000000001; const CellarPropertyType type = CellarPropertyType.Image; const string className = "ClassB"; const string fieldName = "NewImageVP"; m_metaDataCache.AddVirtualProp(className, fieldName, flid, (int)type); // Check its flid. var newFlid = m_metaDataCache.GetFieldId(className, fieldName, false); Assert.AreEqual(flid, newFlid, "Wrong field Id."); // Check its data type. Assert.AreEqual(type, (CellarPropertyType)m_metaDataCache.GetFieldType(flid), "Wrong field type."); // Check to see it is virtual. var isVirtual = m_metaDataCache.get_IsVirtual(flid); Assert.IsTrue(isVirtual, "Wrong field virtual setting."); // Check the clid it was supposed to be placed in. var clid = m_metaDataCache.GetClassId(className); Assert.AreEqual(clid, m_metaDataCache.GetOwnClsId(flid), "Wrong clid for new virtual field."); Assert.AreEqual(fieldName, m_metaDataCache.GetFieldName(flid), "Wrong field name for new virtual field."); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Export a collection/sequence list reference field. /// </summary> /// ------------------------------------------------------------------------------------ private void ExportReferenceList(TextWriter writer, List <ICmPossibility> collection, string fieldName, string targetType, CellarPropertyType cpt) { if (collection == null || collection.Count == 0) { return; } if (cpt == CellarPropertyType.ReferenceCollection) { writer.WriteLine("<Field name=\"{0}\" type=\"{1}\" card=\"collection\">", fieldName, targetType); } else { writer.WriteLine("<Field name=\"{0}\" type=\"{1}\" card=\"sequence\">", fieldName, targetType); } int ws; foreach (var item in collection) { ITsString tss = item.Name.GetAlternativeOrBestTss(m_cache.DefaultAnalWs, out ws); writer.WriteLine("<Item ws=\"{0}\">{1}</Item>", m_cache.WritingSystemFactory.GetStrFromWs(ws), XmlUtils.MakeSafeXml(tss.Text)); } writer.WriteLine("</Field>"); }
/// <summary> /// Constructor. /// </summary> /// <param name="flidType">Type of property.</param> /// <param name="flid">Field ID</param> /// <param name="signature">return value signature</param> public ModelPropertyAttribute(CellarPropertyType flidType, int flid, string signature) { if (string.IsNullOrEmpty(signature)) throw new ArgumentNullException("signature"); m_flidType = flidType; m_flid = flid; m_signature = signature; }
/// <summary> /// Constructor. /// </summary> /// <param name="flidType">Type of property.</param> /// <param name="flid">Field ID</param> /// <param name="signature">return value signature</param> public ModelPropertyAttribute(CellarPropertyType flidType, int flid, string signature) { if (string.IsNullOrEmpty(signature)) { throw new ArgumentNullException("signature"); } m_flidType = flidType; m_flid = flid; m_signature = signature; }
public MetaFieldRec() { m_fieldType = 0; m_ownClsid = 0; m_dstClsid = 0; m_fieldWs = 0; m_fieldName = null; m_fieldLabel = null; m_fieldHelp = null; m_fieldXml = null; }
bool m_fGotFocus = false; // True if we have focus. public TypeAheadSupportVc(int tag, LcmCache cache) { m_tag = tag; IFwMetaDataCache mdc = cache.DomainDataByFlid.MetaDataCache; m_clid = mdc.GetOwnClsId(m_tag); m_className = mdc.GetClassName(m_clid); m_fieldName = mdc.GetFieldName(m_tag); m_type = (CellarPropertyType)(mdc.GetFieldType(m_tag) & (int)CellarPropertyTypeFilter.VirtualMask); m_sda = cache.DomainDataByFlid; Cache = cache; }
/// <summary> /// Constructs a custom field using the given arguments and adds it into the Cache. /// </summary> public CustomFieldForTest(LcmCache cache, string customFieldLabel, string customFieldName, int classId, int destClass, int ws, CellarPropertyType fieldType, Guid listGuid) { m_customField = new FieldDescription(cache) { Userlabel = customFieldLabel, Name = customFieldName, HelpString = String.Empty, Class = classId, ListRootId = listGuid, Type = fieldType, DstCls = destClass, WsSelector = ws }; m_customField.UpdateCustomField(); }
private bool IsSupportedFieldType(CellarPropertyType fieldType) { switch (fieldType) { case CellarPropertyType.OwningAtomic: case CellarPropertyType.ReferenceAtomic: case CellarPropertyType.Boolean: //case CellarPropertyType.Float: // Not yet supported (as of 23 march 2013) case CellarPropertyType.GenDate: case CellarPropertyType.Guid: case CellarPropertyType.Integer: //case CellarPropertyType.Numeric: // Not yet supported (as of 23 march 2013) case CellarPropertyType.Time: return(true); } return(false); }
internal void Initialize(FdoCache cache, XCore.IHelpTopicProvider helpTopicProvider, IApp app, IVwStylesheet stylesheet, NotebookImportWiz.RnSfMarker rsfm, CellarPropertyType cpt) { m_cache = cache; m_helpTopicProvider = helpTopicProvider; m_btnAddWritingSystem.Initialize(m_cache, helpTopicProvider, app, stylesheet); NotebookImportWiz.InitializeWritingSystemCombo(rsfm.m_tlo.m_wsId, cache, m_cbWritingSystem); bool fNotAtomic = (cpt != CellarPropertyType.ReferenceAtomic); m_tbDefaultValue.Text = rsfm.m_tlo.m_sEmptyDefault; m_chkDelimMultiEnable.Checked = rsfm.m_tlo.m_fHaveMulti && fNotAtomic; m_chkDelimMultiEnable.Enabled = fNotAtomic; m_tbDelimMulti.Text = rsfm.m_tlo.m_sDelimMulti; m_tbDelimMulti.Enabled = rsfm.m_tlo.m_fHaveMulti && fNotAtomic; m_chkDelimSubEnable.Checked = rsfm.m_tlo.m_fHaveSub; m_tbDelimSub.Text = rsfm.m_tlo.m_sDelimSub; m_tbDelimSub.Enabled = rsfm.m_tlo.m_fHaveSub; m_chkBetweenEnable.Checked = rsfm.m_tlo.m_fHaveBetween; m_tbBetweenBefore.Text = rsfm.m_tlo.m_sMarkStart; m_tbBetweenAfter.Text = rsfm.m_tlo.m_sMarkEnd; m_tbBetweenBefore.Enabled = rsfm.m_tlo.m_fHaveBetween; m_tbBetweenAfter.Enabled = rsfm.m_tlo.m_fHaveBetween; m_chkOnlyBeforeEnable.Checked = rsfm.m_tlo.m_fHaveBefore; m_tbOnlyBefore.Text = rsfm.m_tlo.m_sBefore; m_tbOnlyBefore.Enabled = rsfm.m_tlo.m_fHaveBefore; m_chkDiscardNewStuff.Checked = rsfm.m_tlo.m_fIgnoreNewStuff; m_rbMatchName.Checked = rsfm.m_tlo.m_pnt == PossNameType.kpntName; m_rbMatchAbbr.Checked = rsfm.m_tlo.m_pnt != PossNameType.kpntName; Debug.Assert(rsfm.m_tlo.m_rgsMatch.Count == rsfm.m_tlo.m_rgsReplace.Count); m_lvSubstitutions.Items.Clear(); for (int i = 0; i < rsfm.m_tlo.m_rgsMatch.Count; ++i) { var lvi = new ListViewItem(new[] { rsfm.m_tlo.m_rgsMatch[i], rsfm.m_tlo.m_rgsReplace[i] }); m_lvSubstitutions.Items.Add(lvi); } }
private static bool IsObjectFieldType(CellarPropertyType type) { var isObjectFT = false; switch (type) { case CellarPropertyType.OwningAtomic: case CellarPropertyType.OwningCollection: case CellarPropertyType.OwningSequence: case CellarPropertyType.ReferenceAtomic: case CellarPropertyType.ReferenceCollection: case CellarPropertyType.ReferenceSequence: isObjectFT = true; break; } return isObjectFT; }
private static bool IsObjectFieldType(CellarPropertyType type) { var isObjectFT = false; switch (type) { case CellarPropertyType.OwningAtomic: case CellarPropertyType.OwningCollection: case CellarPropertyType.OwningSequence: case CellarPropertyType.ReferenceAtomic: case CellarPropertyType.ReferenceCollection: case CellarPropertyType.ReferenceSequence: isObjectFT = true; break; } return(isObjectFT); }
public int AddCustomField(string className, string fieldName, CellarPropertyType fieldType, int destinationClass, string fieldHelp, int fieldWs, Guid fieldListRoot) { int clid; if (m_classesByName.TryGetValue(className, out clid)) { List <MockFieldInfo> list; var flid = (clid * 1000) + 500; if (m_fieldsByClassId.TryGetValue(clid, out list)) { var flidMax = flid - 1; foreach (MockFieldInfo mfi in list) { if (mfi.m_fCustom && mfi.m_flid > flid) { flidMax = mfi.m_flid; } } flid = flidMax + 1; } else { list = new List <MockFieldInfo>(); m_fieldsByClassId.Add(clid, list); } var mfiNew = new MockFieldInfo { m_flid = flid, m_name = fieldName, m_cpt = fieldType, m_destClsid = destinationClass, m_fCustom = true, m_fieldHelp = fieldHelp, m_fieldWs = fieldWs, m_fieldListRoot = fieldListRoot }; list.Add(mfiNew); m_fieldsById.Add(flid, mfiNew); return(flid); } return(0); }
private static string GetDefaultValueForPropertyType(CellarPropertyType propertyType) { switch (propertyType) { case CellarPropertyType.Boolean: return("False"); case CellarPropertyType.GenDate: var genDate = new GenDate(); return(string.Format("{0}{1:0000}{2:00}{3:00}{4}", genDate.IsAD ? "" : "-", genDate.Year, genDate.Month, genDate.Day, (int)genDate.Precision)); case CellarPropertyType.Guid: return(Guid.Empty.ToString()); case CellarPropertyType.Float: throw new NotSupportedException("The 'Float' data type is not supported in the FW data model yet (as of 23 March 2013)."); case CellarPropertyType.Integer: return("0"); case CellarPropertyType.Time: var datetime = new DateTime(); datetime = datetime.ToUniversalTime(); // Store it as UTC. return(String.Format("{0}-{1}-{2} {3}:{4}:{5}.{6}", datetime.Year, datetime.Month, datetime.Day, datetime.Hour, datetime.Minute, datetime.Second, datetime.Millisecond)); case CellarPropertyType.Numeric: throw new NotSupportedException("The 'Numeric' data type is not supported in the FW data model yet (as of 23 March 2013)."); default: throw new InvalidOperationException("The given 'propertyType' is not a basic data type."); } }
public override void MakeRoot() { CheckDisposed(); base.MakeRoot(); if (m_fdoCache == null || DesignMode) { return; } // A crude way of making sure the property we want is loaded into the cache. m_obj = m_fdoCache.ServiceLocator.GetInstance <ICmObjectRepository>().GetObject(m_hvoObj); CellarPropertyType type = (CellarPropertyType)m_fdoCache.DomainDataByFlid.MetaDataCache.GetFieldType(m_flid); if (type == CellarPropertyType.Unicode) { m_vc = new UnicodeStringSliceVc(m_flid, m_ws, m_fdoCache); } else if (type == CellarPropertyType.String) { // Even if we were given a writing system, we must not use it if not a multistring, // otherwise the VC crashes when it tries to read the property as multilingual. m_vc = new StringSliceVc(m_flid, m_fdoCache, m_mediator); (m_vc as StringSliceVc).ShowWsLabel = m_fShowWsLabel; } else { m_vc = new StringSliceVc(m_flid, m_ws, m_fdoCache, m_mediator); (m_vc as StringSliceVc).ShowWsLabel = m_fShowWsLabel; } // Review JohnT: why doesn't the base class do this?? m_rootb = VwRootBoxClass.Create(); m_rootb.SetSite(this); // And maybe this too, at least by default? m_rootb.DataAccess = m_fdoCache.DomainDataByFlid; // arg3 is a meaningless initial fragment, since this VC only displays one thing. // arg4 could be used to supply a stylesheet. m_rootb.SetRootObject(m_hvoObj, m_vc, 1, m_styleSheet); }
internal void AddField(int flid, string fieldName, CellarPropertyType cpt, int destClsid) { var clsid = flid / 1000; var mfi = new MockFieldInfo { m_flid = flid, m_name = fieldName, m_cpt = cpt, m_destClsid = destClsid, m_fCustom = false, m_isVirtual = false, m_fieldHelp = null, m_fieldWs = WritingSystemServices.kwsAnal, m_fieldListRoot = Guid.Empty }; m_fieldsById.Add(flid, mfi); List<MockFieldInfo> list; if (!m_fieldsByClassId.TryGetValue(clsid, out list)) { list = new List<MockFieldInfo>(); m_fieldsByClassId.Add(clsid, list); } list.Add(mfi); }
// extracted from the CellarPropertyType enum protected static string GetFlidTypeAsString(CellarPropertyType flidType) { string retval; switch (flidType) { default: throw new ArgumentException("Property element name not recognized."); case CellarPropertyType.Boolean: retval = "Boolean"; break; case CellarPropertyType.Integer: retval = "Integer"; break; case CellarPropertyType.Time: retval = "Time"; break; case CellarPropertyType.String: retval = "String"; break; case CellarPropertyType.MultiString: retval = "MultiString"; break; case CellarPropertyType.Unicode: retval = "Unicode"; break; case CellarPropertyType.MultiUnicode: retval = "MultiUnicode"; break; case CellarPropertyType.Guid: retval = "Guid"; break; case CellarPropertyType.Image: retval = "Image"; break; case CellarPropertyType.GenDate: retval = "GenDate"; break; case CellarPropertyType.Binary: retval = "Binary"; break; case CellarPropertyType.Numeric: retval = "Numeric"; break; case CellarPropertyType.Float: retval = "Float"; break; case CellarPropertyType.OwningAtomic: retval = "OA"; break; case CellarPropertyType.OwningCollection: retval = "OC"; break; case CellarPropertyType.OwningSequence: retval = "OS"; break; case CellarPropertyType.ReferenceAtomic: retval = "RA"; break; case CellarPropertyType.ReferenceCollection: retval = "RC"; break; case CellarPropertyType.ReferenceSequence: retval = "RS"; break; } return(retval); }
public virtual int AddCustomField(string className, string fieldName, CellarPropertyType fieldType, int destinationClass) { return m_metaDataCache.AddCustomField(className, fieldName, fieldType, destinationClass); }
/// <summary> /// This overload allows the label to be specified separately. /// </summary> public int AddCustomField(string className, string fieldName, string label, CellarPropertyType fieldType, int destinationClass, string fieldHelp, int fieldWs, Guid fieldListRoot) { var flid = AddCustomField(className, fieldName, fieldType, destinationClass); m_metaFieldRecords[flid].m_fieldHelp = fieldHelp; m_metaFieldRecords[flid].m_fieldWs = fieldWs; m_metaFieldRecords[flid].m_fieldLabel = label; // user label same as field name now. m_metaFieldRecords[flid].m_fieldListRoot = fieldListRoot; return flid; }
private void AddToLongCache(int obj, int tag, long val, CellarPropertyType flidType) { CheckBasics(obj); // Make sure the hvo has the given tag. CheckHvoTagMatch(obj, tag); // Make sure a long is legal for the given tag. CellarPropertyType tagType = (CellarPropertyType)MetaDataCache.GetFieldType(tag); if (tagType != flidType) throw new ArgumentException(String.Format("Can only put long integers in the tag/flid '{0}'.", tag)); m_longCache[new HvoFlidKey(obj, tag)] = val; }
/// <summary> /// Set custom field data for one field (specified by owner HVO and field ID). /// </summary> /// <returns><c>true</c>, if custom field data was set, <c>false</c> otherwise (e.g., if value hadn't changed, /// or value was null, or field type was one not implemented in LCM, such as CellarPropertyType.Float).</returns> /// <param name="hvo">HVO of object whose field we're setting.</param> /// <param name="flid">Field ID of custom field to set.</param> /// <param name="value">Field's new value (as returned by GetCustomFieldData).</param> /// <param name="guidOrGuids">GUID or guids associated with new value (as returned by GetCustomFieldData). /// May be null or BsonNull.Value if no GUIDs associated with this value.</param> public bool SetCustomFieldData(int hvo, int flid, BsonValue value, BsonValue guidOrGuids) { if ((value == null) || (value == BsonNull.Value) || ((value.BsonType == BsonType.Array) && (value.AsBsonArray.Count == 0))) { return(false); } List <Guid> fieldGuids = new List <Guid>(); if (guidOrGuids == null || guidOrGuids == BsonNull.Value) { // Leave fieldGuids as an empty list } else { if (guidOrGuids is BsonArray) { fieldGuids.AddRange(guidOrGuids.AsBsonArray.Select(bsonValue => ParseGuidOrDefault(bsonValue.AsString))); } else { fieldGuids.Add(ParseGuidOrDefault(guidOrGuids.AsString)); } } ISilDataAccessManaged data = (ISilDataAccessManaged)cache.DomainDataByFlid; CellarPropertyType fieldType = (CellarPropertyType)lcmMetaData.GetFieldType(flid); string fieldName = lcmMetaData.GetFieldNameOrNull(flid); // logger.Debug("Custom field named {0} has type {1}", fieldName, fieldType.ToString()); if (fieldName == null) { return(false); } // Valid field types in LCM are GenDate, Integer, String, OwningAtomic, ReferenceAtomic, and ReferenceCollection, so that's all we implement. switch (fieldType) { case CellarPropertyType.GenDate: { var valueAsMultiText = BsonSerializer.Deserialize <LfMultiText>(value.AsBsonDocument); string valueAsString = valueAsMultiText.BestString(new string[] { MagicStrings.LanguageCodeForGenDateFields }); if (string.IsNullOrEmpty(valueAsString)) { return(false); } GenDate valueAsGenDate; if (GenDate.TryParse(valueAsString, out valueAsGenDate)) { GenDate oldValue = data.get_GenDateProp(hvo, flid); if (oldValue == valueAsGenDate) { return(false); } else { data.SetGenDate(hvo, flid, valueAsGenDate); return(true); } } return(false); } case CellarPropertyType.Integer: { var valueAsMultiText = BsonSerializer.Deserialize <LfMultiText>(value.AsBsonDocument); string valueAsString = valueAsMultiText.BestString(new string[] { MagicStrings.LanguageCodeForIntFields }); if (string.IsNullOrEmpty(valueAsString)) { return(false); } int valueAsInt; if (int.TryParse(valueAsString, out valueAsInt)) { int oldValue = data.get_IntProp(hvo, flid); if (oldValue == valueAsInt) { return(false); } else { data.SetInt(hvo, flid, valueAsInt); return(true); } } return(false); } case CellarPropertyType.OwningAtomic: { // Custom field is a MultiparagraphText, which is an IStText object in LCM IStTextRepository textRepo = servLoc.GetInstance <IStTextRepository>(); Guid fieldGuid = fieldGuids.FirstOrDefault(); IStText text; if (!textRepo.TryGetObject(fieldGuid, out text)) { int currentFieldContentsHvo = data.get_ObjectProp(hvo, flid); if (currentFieldContentsHvo != LcmCache.kNullHvo) { text = (IStText)cache.GetAtomicPropObject(currentFieldContentsHvo); } else { // NOTE: I don't like the "magic" -2 number below, but LCM doesn't seem to have an enum for this. 2015-11 RM int newStTextHvo = data.MakeNewObject(cache.GetDestinationClass(flid), hvo, flid, -2); text = (IStText)cache.GetAtomicPropObject(newStTextHvo); } } // Shortcut: if text contents haven't changed, we don't want to change anything at all BsonValue currentLcmTextContents = ConvertUtilities.GetCustomStTextValues(text, flid, servLoc.WritingSystemManager, lcmMetaData, cache.DefaultUserWs); if ((currentLcmTextContents == BsonNull.Value || currentLcmTextContents == null) && (value == BsonNull.Value || value == null)) { return(false); } if (currentLcmTextContents != null && currentLcmTextContents.Equals(value)) { // No changes needed. return(false); } // BsonDocument passed in contains "paragraphs". ParseCustomStTextValuesFromBson wants only a "value" element // inside the doc, so we'll need to construct a new doc for the StTextValues. BsonDocument doc = value.AsBsonDocument; LfMultiParagraph multiPara = BsonSerializer.Deserialize <LfMultiParagraph>(doc); // Now we have another way to check for "old value and new value were the same": if the LCM multiparagraph was empty, // GetCustomStTextValues will have returned null -- so if this multiPara has no paragraphs, that's also an unchanged situation if ((multiPara.Paragraphs == null || multiPara.Paragraphs.Count <= 0) && (currentLcmTextContents == BsonNull.Value || currentLcmTextContents == null)) { return(false); } int wsId; if (multiPara.InputSystem == null) { wsId = lcmMetaData.GetFieldWs(flid); } else { wsId = servLoc.WritingSystemFactory.GetWsFromStr(multiPara.InputSystem); } ConvertUtilities.SetCustomStTextValues(text, multiPara.Paragraphs, wsId); return(true); } case CellarPropertyType.ReferenceAtomic: if (fieldGuids.FirstOrDefault() != Guid.Empty) { int referencedHvo = data.get_ObjFromGuid(fieldGuids.FirstOrDefault()); int oldHvo = data.get_ObjectProp(hvo, flid); if (referencedHvo == oldHvo) { return(false); } else { data.SetObjProp(hvo, flid, referencedHvo); // TODO: What if the value of the referenced object has changed in LanguageForge? (E.g., change that possibility's text from "foo" to "bar") // Need to implement that scenario. return(true); } } else { // It's a reference to an ICmPossibility instance: create a new entry in appropriate PossibilityList LfStringField valueAsLfStringField = BsonSerializer.Deserialize <LfStringField>(value.AsBsonDocument); string nameHierarchy = valueAsLfStringField.Value; if (nameHierarchy == null) { return(false); } int fieldWs = lcmMetaData.GetFieldWs(flid); // Oddly, this can return 0 for some custom fields. TODO: Find out why: that seems like it would be an error. if (fieldWs == 0) { fieldWs = cache.DefaultUserWs; // TODO: Investigate, because this should probably be wsEn instead so that we can create correct keys. } if (fieldWs < 0) { // FindOrCreatePossibility has a bug where it doesn't handle "magic" writing systems (e.g., -1 for default analysis, etc) and // throws an exception instead. So we need to get a real ws here. fieldWs = WritingSystemServices.ActualWs(cache, fieldWs, hvo, flid); } ICmPossibilityList parentList = GetParentListForField(flid); ICmPossibility newPoss = parentList.FindOrCreatePossibility(nameHierarchy, fieldWs); int oldHvo = data.get_ObjectProp(hvo, flid); if (newPoss.Hvo == oldHvo) { return(false); } else { data.SetObjProp(hvo, flid, newPoss.Hvo); return(true); } } case CellarPropertyType.ReferenceCollection: case CellarPropertyType.ReferenceSequence: { if (value == null || value == BsonNull.Value) { // Can't write null to a collection or sequence in LCM; it's forbidden. So data.SetObjProp(hvo, flid, LcmCache.kNullHvo) will not work. // Instead, we delete all items from the existing collection or sequence, and thus store an empty coll/seq in LCM. int oldSize = data.get_VecSize(hvo, flid); if (oldSize == 0) { // It was already empty, so leave it unchanged so we don't cause unnecessary changes in the .fwdata XML (and unnecessary Mercurial commits). return(false); } else { data.Replace(hvo, flid, 0, oldSize, null, 0); // This is how you set an empty array return(true); } } int fieldWs = lcmMetaData.GetFieldWs(flid); // TODO: Investigate why this is sometimes coming back as 0 instead of as a real writing system ID if (fieldWs == 0) { fieldWs = cache.DefaultUserWs; } ICmPossibilityList parentList = GetParentListForField(flid); LfStringArrayField valueAsStringArray = BsonSerializer.Deserialize <LfStringArrayField>(value.AsBsonDocument); // Step 1: Get ICmPossibility instances from the string keys that LF gave us // First go through all the GUIDs we have and match them up to the keys. If they match up, // then remove the keys from the list. Any remaining keys get looked up with FindOrCreatePossibility(), so now we // have a complete set of GUIDs (or ICmPossibility objects, which works out to the same thing). // TODO: This is all kind of ugly, and WAY too long for one screen. I could put it in its own function, // but there's really no real gain from that, as it simply moves the logic even further away from where // it needs to be. There's not really a *good* way to achieve simplicity with this code design, unfortunately. // The only thing that would be close to simple would be to call some functions from the LcmToMongo option list // converters, and that's pulling in code from the "wrong" direction, which has its own ugliness. Ugh. HashSet <string> keysFromLF = new HashSet <string>(valueAsStringArray.Values); var fieldObjs = new List <ICmPossibility>(); foreach (Guid guid in fieldGuids) { ICmPossibility poss; string key = ""; if (guid != default(Guid)) { poss = servLoc.GetInstance <ICmPossibilityRepository>().GetObject(guid); if (poss == null) { // TODO: Decide what to do with possibilities deleted from LCM key = ""; } else { if (poss.Abbreviation == null) { key = ""; } else { ITsString keyTss = poss.Abbreviation.get_String(wsEn); key = keyTss == null ? "" : keyTss.Text ?? ""; } fieldObjs.Add(poss); } } keysFromLF.Remove(key); // Ignoring return value (HashSet.Remove returns false if the key wasn't present), because false could mean one of two things: // 1. The CmPossibility had its English abbreviation changed in LCM, but LF doesn't know this yet. // If this is the case, the LF key won't match, but the GUID will still match. So we might end up creating // duplicate entries below with the FindOrCreatePossibility. TODO: Need to verify that LCM->LF possibility lists // get updated correctly if renames happen! (... Or use the OptionList converters, that's what they were for.) // 2. The CmPossibility was just created in LF and isn't in LCM yet. In which case we should have been using the // OptionList converters, which would hopefully have handled creating the ICmPossibility instane in LCM. // Either way, we can't really use that fact later, since we can't be certain if the possibility was renamed or created. } // Any remaining keysFromLF strings did not have corresponding GUIDs in Mongo. // This is most likely because they were added by LF, which doesn't write to the customFieldGuids field. // So we assume they exist in FW, and just look them up. foreach (string key in keysFromLF) { ICmPossibility poss = parentList.FindOrCreatePossibility(key, wsEn); // TODO: If this is a new possibility, then we need to populate it with ALL the corresponding data from LF, // which we don't necessarily have at this point. Need to make that a separate step in the Send/Receive: converting option lists first. fieldObjs.Add(poss); } // logger.Debug("Custom field {0} for CmObject {1}: BSON list was [{2}] and customFieldGuids was [{3}]. This was translated to keysFromLF = [{4}] and fieldObjs = [{5}]", // fieldName, // hvo, // String.Join(", ", valueAsStringArray.Values), // String.Join(", ", fieldGuids.Select(g => g.ToString())), // String.Join(", ", keysFromLF.AsEnumerable()), // String.Join(", ", fieldObjs.Select(poss => poss.AbbrAndName)) // ); // Step 2: Remove any objects from the "old" list that weren't in the "new" list // We have to look them up by HVO because that's the only public API available in LCM // Following logic inspired by XmlImportData.CopyCustomFieldData in FieldWorks source int[] oldHvosArray = data.VecProp(hvo, flid); int[] newHvosArray = fieldObjs.Select(poss => poss.Hvo).ToArray(); // Shortcut check if (oldHvosArray.SequenceEqual(newHvosArray)) { // Nothing to do, so return now so that we don't cause unnecessary changes and commits in Mercurial return(false); } HashSet <int> newHvos = new HashSet <int>(newHvosArray); HashSet <int> combinedHvos = new HashSet <int>(); // Loop backwards so deleting items won't mess up indices of subsequent deletions for (int idx = oldHvosArray.Length - 1; idx >= 0; idx--) { int oldHvo = oldHvosArray[idx]; if (newHvos.Contains(oldHvo)) { combinedHvos.Add(oldHvo); } else { data.Replace(hvo, flid, idx, idx + 1, null, 0); // Important to pass *both* null *and* 0 here to remove items } } // Step 3: Add any objects from the "new" list that weren't in the "old" list foreach (int newHvo in newHvosArray) { if (combinedHvos.Contains(newHvo)) { continue; } // This item was added in the new list data.Replace(hvo, flid, combinedHvos.Count, combinedHvos.Count, new int[] { newHvo }, 1); combinedHvos.Add(newHvo); } return(true); } case CellarPropertyType.String: { var valueAsMultiText = BsonSerializer.Deserialize <LfMultiText>(value.AsBsonDocument); int wsIdForField = lcmMetaData.GetFieldWs(flid); string wsStrForField = servLoc.WritingSystemFactory.GetStrFromWs(wsIdForField); KeyValuePair <string, string> kv = valueAsMultiText.BestStringAndWs(new string[] { wsStrForField }); string foundWs = kv.Key ?? string.Empty; string foundData = kv.Value ?? string.Empty; int foundWsId = servLoc.WritingSystemFactory.GetWsFromStr(foundWs); if (foundWsId == 0) { return(false); // Skip any unidentified writing systems } ITsString oldValue = data.get_StringProp(hvo, flid); ITsString newValue = ConvertMongoToLcmTsStrings.SpanStrToTsString(foundData, foundWsId, servLoc.WritingSystemFactory); if (oldValue != null && TsStringUtils.GetDiffsInTsStrings(oldValue, newValue) == null) // GetDiffsInTsStrings() returns null when there are no changes { return(false); } else { data.SetString(hvo, flid, newValue); return(true); } } default: return(false); // TODO: Maybe issue a proper warning (or error) log message for "field type not recognized"? } }
private void VerifyCustomListToPossList(int flid, CellarPropertyType type, string possListName) { var custFieldType = (CellarPropertyType)m_mdc.GetFieldType(flid); var custFieldListGuid = m_mdc.GetFieldListRoot(flid); Assert.AreEqual(type, custFieldType); Guid lstGuid = Guid.Empty; m_customListNamesAndGuids.TryGetValue(possListName, out lstGuid); Assert.AreEqual(custFieldListGuid, lstGuid); }
/// <summary> /// Create a custom field using the given values. /// </summary> public void CreateCustomField(string className, string fieldName, CellarPropertyType cpt, int destClid, string helpString, int wsSelector, Guid listRoot) { m_mdc.AddCustomField(className, fieldName, cpt, destClid, helpString, wsSelector, listRoot); }
/// <summary> /// Constructor for non-object properties. /// </summary> public VirtualPropertyAttribute(CellarPropertyType flidType) : this(flidType, "") { }
public int AddCustomField(string className, string fieldName, CellarPropertyType fieldType, int destinationClass) { CheckClid(className); var clid = m_nameToClid[className]; if (string.IsNullOrEmpty(fieldName)) throw new ArgumentNullException("fieldName"); int flid; // Don't allow custom field with same name as non-custom field if (m_nameToFlid.TryGetValue(MakeFlidKey(clid, fieldName), out flid) && !IsCustom(flid)) throw new FDOInvalidFieldException("Field already exists: " + fieldName, fieldName); // FWR-2804 - in case a custom field already exists that originally had this name, // make sure we use a unique name this time. var uniqueName = AssureUniqueFieldName(clid, fieldName); // Get custom flid for clid. if (m_clidToNextCustomFlid.TryGetValue(clid, out flid)) { // Bump it up by 1. flid += 1; m_clidToNextCustomFlid[clid] = flid; } else { // Start with 500. flid = (clid*1000) + 500; m_clidToNextCustomFlid.Add(clid, flid); } string fieldSig = null; MetaClassRec mcrSig; if (m_metaClassRecords.TryGetValue(destinationClass, out mcrSig)) fieldSig = mcrSig.m_className; AddField(className, flid, uniqueName, null, null, null, fieldSig, fieldType, FieldSource.kCustom, Guid.Empty, 0); var mfr = m_metaFieldRecords[flid]; mfr.m_fieldLabel = fieldName; // user label is original proposed name. m_customFields.Add(mfr); ConnectMetaFieldRec(mfr); return flid; }
private void VerifyCustomFieldPresent(string customFieldLabel, int classWithCustomField, int expectedType, CellarPropertyType ownerType = CellarPropertyType.Nil) { var mdc = Cache.MetaDataCacheAccessor as IFwMetaDataCacheManaged; var flid = mdc.GetFieldId2(classWithCustomField, customFieldLabel, false); Assert.IsTrue(mdc.IsCustom(flid)); Assert.AreEqual(mdc.GetDstClsId(flid), expectedType, "The {0} custom field was not the correct type.", customFieldLabel); }
/// <summary> /// Constructor for object properties. Signature is the name (unqualified) of the class, e.g., "LexEntry". /// </summary> public VirtualPropertyAttribute(CellarPropertyType flidType, string signature) { m_flidType = flidType; m_virtualFlid = GetNextFlid(); m_signature = signature; }
private static XAttribute CreateValAttribute(CellarPropertyType propertyType) { return new XAttribute("val", GetDefaultValueForPropertyType(propertyType)); }
/// <summary> /// Constructor for non-object properties. /// </summary> public VirtualPropertyAttribute(CellarPropertyType flidType) :this(flidType, "") { }
public VectorReferenceUi(FdoCache cache, ICmObject rootObj, int referenceFlid, int targetHvo) : base(cache, rootObj, referenceFlid, targetHvo) { m_iType = (CellarPropertyType)cache.DomainDataByFlid.MetaDataCache.GetFieldType(m_flid); Debug.Assert(m_iType == CellarPropertyType.ReferenceSequence || m_iType == CellarPropertyType.ReferenceCollection); }
public void WriteCustomFieldConfigForOneFieldSourceType( int classId, string fieldSourceType, // Can be either "entry", "senses", or "examples" Dictionary <string, LfConfigFieldBase> lfCustomFieldConfig, Dictionary <string, string> lfCustomFieldTypes ) { IEnumerable <int> customFieldIds = LcmMetaData.GetFields(classId, false, (int)CellarPropertyTypeFilter.All) .Where(flid => cache.GetIsCustomField(flid)); foreach (int flid in customFieldIds) { string label = LcmMetaData.GetFieldNameOrNull(flid); if (label == null) { continue; } string lfCustomFieldName = ConvertUtilities.NormalizedFieldName(label, fieldSourceType); CellarPropertyType LcmFieldType = (CellarPropertyType)LcmMetaData.GetFieldType(flid); lfCustomFieldTypes[lfCustomFieldName] = LcmFieldType.ToString(); string lfCustomFieldType; if (CellarPropertyTypeToLfCustomFieldType.TryGetValue(LcmFieldType, out lfCustomFieldType)) { // Get custom field configuration info LfConfigFieldBase fieldConfig = null; if (lfCustomFieldType.EndsWith("ListRef")) { // List references, whether single or multi, need a list code string listCode = GetParentListCode(flid); fieldConfig = GetLfCustomFieldOptionListConfig(label, lfCustomFieldType, listCode); } else if (lfCustomFieldType == CellarPropertyTypeToLfCustomFieldType[CellarPropertyType.OwningAtomic]) { // Multiparagraphs don't need writing systems fieldConfig = GetLfCustomFieldMultiParagraphConfig(label, lfCustomFieldType); } else { // Single line or MultiText fields need writing systems int fieldWs = LcmMetaData.GetFieldWs(flid); // That's a "magic" ws, which we need to expand into a (list of) real writing system(s). #if FW8_COMPAT var wsesForThisField = new List <IWritingSystem>(); #else var wsesForThisField = new List <CoreWritingSystemDefinition>(); #endif // GetWritingSystemList() in FW 8.3 is buggy and doesn't properly handle the kwsAnal and kwsVern cases, so we handle them here instead. switch (fieldWs) { case WritingSystemServices.kwsAnal: wsesForThisField.Add(servLoc.LanguageProject.DefaultAnalysisWritingSystem); break; case WritingSystemServices.kwsVern: wsesForThisField.Add(servLoc.LanguageProject.DefaultVernacularWritingSystem); break; default: wsesForThisField = WritingSystemServices.GetWritingSystemList(cache, fieldWs, forceIncludeEnglish: false); break; } #if FW8_COMPAT IEnumerable <string> inputSystems = wsesForThisField.Select(LcmWs => LcmWs.Id); #else IEnumerable <string> inputSystems = wsesForThisField.Select(LcmWs => LcmWs.LanguageTag); #endif // GetWritingSystemList returns all analysis WSes even when asked for just one, so if this // is a single-line custom field, trim the WSes down to just the first one if (lfCustomFieldType.StartsWith("Single")) { inputSystems = inputSystems.Take(1); } fieldConfig = GetLfCustomFieldMultiTextConfig(label, lfCustomFieldType, inputSystems.ToList()); } if (fieldConfig != null) { lfCustomFieldConfig[lfCustomFieldName] = fieldConfig; } } } }
public bool OkToMove(int hvoDstOwner, int flidDst, int ihvoDstStart, ObjectDragInfo odi) { CheckDisposed(); FDO.FdoCache cache = Slice.ContainingDataTree.Cache; ICmObjectRepository repo = cache.ServiceLocator.GetInstance <ICmObjectRepository>(); if (flidDst == odi.FlidSrc) { // Verify that it is not a no-operation. if (hvoDstOwner == odi.HvoSrcOwner) { // Same property of same object. If it's a collection, disable. CellarPropertyType fieldType = (CellarPropertyType)cache.DomainDataByFlid.MetaDataCache.GetFieldType((int)flidDst); // We can't drag it to the position it's already at; that's no change. We also can't drag it // to the position one greater: that amounts to trying to place it after itself, which (after // removing it from before itself) amounts to a no-operation. if (fieldType == CellarPropertyType.OwningSequence && ihvoDstStart != odi.IhvoSrcStart && ihvoDstStart != odi.IhvoSrcStart + 1) { // It's a sequence and the target and source positions are different, so we can do it. return(true); } } else { // Different objects; need to verify no circular ownership involved. for (int ihvo = odi.IhvoSrcStart; ihvo <= odi.IhvoSrcEnd; ihvo++) { int hvo = cache.DomainDataByFlid.get_VecItem(odi.HvoSrcOwner, odi.FlidSrc, ihvo); // See if hvoDstOwner is owned by hvo ICmObject obj2 = repo.GetObject(hvoDstOwner); // loop from hvo2 to root owner of hvo2. If hvo2 or any of its owners is hvo, // we have a problem. while (obj2 != null) { if (hvo == obj2.Hvo) { return(false); // circular ownership, can't drop. } obj2 = obj2.Owner; } } return(true); } } else { // Different property, check signature. IFwMetaDataCache mdc = cache.DomainDataByFlid.MetaDataCache; int luclid = mdc.GetDstClsId((int)flidDst); for (int ihvo = odi.IhvoSrcStart; ihvo <= odi.IhvoSrcEnd; ihvo++) { int hvo = cache.DomainDataByFlid.get_VecItem(odi.HvoSrcOwner, odi.FlidSrc, ihvo); int cls = repo.GetObject(hvo).ClassID; while (cls != 0 && cls != luclid) { cls = mdc.GetBaseClsId(cls); } if (cls == 0) { return(false); // wrong signature, can't drop. } } // All sigs OK, allow drop. return(true); } // If none of those cases is OK, can't do it. return(false); }
private void ExportCustomFields(TextWriter writer, IRnGenericRec record) { ISilDataAccessManaged sda = m_cache.DomainDataByFlid as ISilDataAccessManaged; Debug.Assert(sda != null); foreach (int flid in m_customFlids) { string fieldName = m_mdc.GetFieldName(flid); bool fHandled = false; ITsString tss; string s; CellarPropertyType cpt = (CellarPropertyType)m_mdc.GetFieldType(flid); switch (cpt) { case CellarPropertyType.Boolean: break; case CellarPropertyType.Integer: break; case CellarPropertyType.Numeric: break; case CellarPropertyType.Float: break; case CellarPropertyType.Time: break; case CellarPropertyType.Guid: break; case CellarPropertyType.Image: case CellarPropertyType.Binary: break; case CellarPropertyType.GenDate: break; case CellarPropertyType.String: tss = sda.get_StringProp(record.Hvo, flid); if (tss != null && tss.Text != null) { ExportString(writer, tss, fieldName); } fHandled = true; break; case CellarPropertyType.MultiString: case CellarPropertyType.MultiUnicode: ITsMultiString tms = sda.get_MultiStringProp(record.Hvo, flid); int cch = 0; for (int i = 0; i < tms.StringCount; ++i) { int ws; tss = tms.GetStringFromIndex(i, out ws); cch += tss.Length; if (cch > 0) { break; } } if (cch > 0) { writer.WriteLine("<Field name=\"{0}\" type=\"MultiString\">", fieldName); for (int i = 0; i < tms.StringCount; ++i) { int ws; tss = tms.GetStringFromIndex(i, out ws); if (tss != null && tss.Length > 0) { if (cpt == CellarPropertyType.MultiString) { writer.WriteLine(TsStringUtils.GetXmlRep(tss, m_cache.WritingSystemFactory, ws, true)); } else { writer.WriteLine("<AUni ws=\"{0}\">{1}</AUni>", m_cache.WritingSystemFactory.GetStrFromWs(ws), XmlUtils.MakeSafeXml(tss.Text)); } } } writer.WriteLine("</Field>"); } fHandled = true; break; case CellarPropertyType.Unicode: break; case CellarPropertyType.ReferenceAtomic: case CellarPropertyType.ReferenceCollection: case CellarPropertyType.ReferenceSequence: { int destClid = m_mdc.GetDstClsId(flid); List <int> rghvoDest = new List <int>(); if (cpt == CellarPropertyType.ReferenceAtomic) { int hvo = sda.get_ObjectProp(record.Hvo, flid); if (hvo != 0) { if (destClid == CmPossibilityTags.kClassId) { ICmPossibility poss = PossibilityRepository.GetObject(hvo); ExportAtomicReference(writer, poss, fieldName, "CmPossibility"); fHandled = true; } else { rghvoDest.Add(hvo); } } else { fHandled = true; } } else { int[] hvos = sda.VecProp(record.Hvo, flid); if (hvos.Length > 0) { if (destClid == CmPossibilityTags.kClassId) { List <ICmPossibility> collection = new List <ICmPossibility>(); foreach (int hvo in hvos) { collection.Add(PossibilityRepository.GetObject(hvo)); } ExportReferenceList(writer, collection, fieldName, "CmPossibility", cpt); fHandled = true; } else { rghvoDest.AddRange(hvos); } } else { fHandled = true; } } if (rghvoDest.Count > 0) { } } break; case CellarPropertyType.OwningAtomic: case CellarPropertyType.OwningCollection: case CellarPropertyType.OwningSequence: { int destClid = m_mdc.GetDstClsId(flid); List <int> rghvoDest = new List <int>(); if (cpt == CellarPropertyType.OwningAtomic) { int hvo = sda.get_ObjectProp(record.Hvo, flid); if (hvo != 0) { if (destClid == StTextTags.kClassId) { IStText text = StTextRepository.GetObject(hvo); ExportStText(writer, text, fieldName); fHandled = true; } else { rghvoDest.Add(hvo); } } else { fHandled = true; } } else { } } break; } if (!fHandled) { } } }
private void ReadPossibilityMarker(XmlNode xnMarker, RnSfMarker sfm, CellarPropertyType cpt) { foreach (XmlNode xn in xnMarker.ChildNodes) { switch (xn.Name) { case "Match": string sMatch = XmlUtils.GetManditoryAttributeValue(xn, "value"); switch (sMatch) { case "abbr": sfm.m_tlo.m_pnt = PossNameType.kpntAbbreviation; break; case "name": sfm.m_tlo.m_pnt = PossNameType.kpntName; break; default: sfm.m_tlo.m_pnt = PossNameType.kpntAbbreviation; break; } break; case "Multiple": if (cpt == CellarPropertyType.ReferenceCollection || cpt == CellarPropertyType.ReferenceSequence || cpt == CellarPropertyType.OwningCollection || cpt == CellarPropertyType.OwningSequence) { sfm.m_tlo.m_fHaveMulti = true; sfm.m_tlo.m_sDelimMulti = XmlUtils.GetManditoryAttributeValue(xn, "sep"); } break; case "Subchoice": sfm.m_tlo.m_fHaveSub = true; sfm.m_tlo.m_sDelimSub = XmlUtils.GetManditoryAttributeValue(xn, "sep"); break; case "Default": sfm.m_tlo.m_sEmptyDefault = XmlUtils.GetManditoryAttributeValue(xn, "value"); sfm.m_tlo.m_default = null; break; case "DelimitChoice": sfm.m_tlo.m_fHaveBetween = true; sfm.m_tlo.m_sMarkStart = XmlUtils.GetManditoryAttributeValue(xn, "start"); sfm.m_tlo.m_sMarkEnd = XmlUtils.GetManditoryAttributeValue(xn, "end"); break; case "StopChoices": sfm.m_tlo.m_fHaveBefore = true; sfm.m_tlo.m_sBefore = XmlUtils.GetManditoryAttributeValue(xn, "value"); break; case "IgnoreNewChoices": sfm.m_tlo.m_fIgnoreNewStuff = XmlUtils.GetBooleanAttributeValue(xn, "value"); break; case "MatchReplaceChoice": sfm.m_tlo.m_rgsMatch.Add(XmlUtils.GetManditoryAttributeValue(xn, "match")); sfm.m_tlo.m_rgsReplace.Add(XmlUtils.GetOptionalAttributeValue(xn, "replace", String.Empty)); break; case "ItemWrtSys": sfm.m_tlo.m_wsId = XmlUtils.GetManditoryAttributeValue(xn, "ws"); break; } } }
private void SetSubControl() { m_groupOptions.Controls.Clear(); if (m_rsfm.m_flid == 0) { m_groupOptions.Text = LexTextControls.ksDiscardedField; m_groupOptions.Controls.Add(m_discardOpt); m_discardOpt.Location = m_locSubCtrl; return; } CellarPropertyType cpt = (CellarPropertyType)m_mdc.GetFieldType(m_rsfm.m_flid); int clidDst = -1; switch (cpt) { case CellarPropertyType.ReferenceAtomic: case CellarPropertyType.ReferenceCollection: case CellarPropertyType.ReferenceSequence: clidDst = m_mdc.GetDstClsId(m_rsfm.m_flid); switch (clidDst) { case RnGenericRecTags.kClassId: m_groupOptions.Text = LexTextControls.ksRnLinkFieldOptions; m_groupOptions.Controls.Add(m_linkOpt); m_linkOpt.Location = m_locSubCtrl; break; case CrossReferenceTags.kClassId: case ReminderTags.kClassId: throw new NotImplementedException(LexTextControls.ksUnimplementedField); default: int clidBase = clidDst; while (clidBase != 0 && clidBase != CmPossibilityTags.kClassId) { clidBase = m_mdc.GetBaseClsId(clidBase); } if (clidBase == CmPossibilityTags.kClassId) { m_groupOptions.Text = LexTextControls.ksListRefImportOptions; m_groupOptions.Controls.Add(m_listOpt); m_listOpt.Location = m_locSubCtrl; m_listOpt.Initialize(m_cache, m_helpTopicProvider, m_app, m_stylesheet, m_rsfm, cpt); break; } throw new ArgumentException(LexTextControls.ksInvalidField); } break; case CellarPropertyType.OwningAtomic: case CellarPropertyType.OwningCollection: case CellarPropertyType.OwningSequence: clidDst = m_mdc.GetDstClsId(m_rsfm.m_flid); switch (clidDst) { case StTextTags.kClassId: Debug.Assert(cpt == CellarPropertyType.OwningAtomic); m_groupOptions.Text = LexTextControls.ksTextImportOptions; m_groupOptions.Controls.Add(m_textOpt); m_textOpt.Location = m_locSubCtrl; m_textOpt.Initialize(m_cache, m_helpTopicProvider, m_app, m_stylesheet, m_rsfm); break; case RnRoledParticTags.kClassId: m_groupOptions.Text = LexTextControls.ksListRefImportOptions; m_groupOptions.Controls.Add(m_listOpt); m_listOpt.Location = m_locSubCtrl; m_listOpt.Initialize(m_cache, m_helpTopicProvider, m_app, m_stylesheet, m_rsfm, cpt); break; case RnGenericRecTags.kClassId: throw new NotImplementedException(LexTextControls.ksUnimplementedField); default: throw new ArgumentException(LexTextControls.ksInvalidField); } break; case CellarPropertyType.MultiString: case CellarPropertyType.MultiUnicode: m_groupOptions.Text = LexTextControls.ksMultiStringImportOptions; m_groupOptions.Controls.Add(m_stringOpt); m_stringOpt.Location = m_locSubCtrl; m_stringOpt.Initialize(m_cache, m_helpTopicProvider, m_app, m_stylesheet, m_rsfm); break; case CellarPropertyType.String: m_groupOptions.Text = LexTextControls.ksStringImportOptions; m_groupOptions.Controls.Add(m_stringOpt); m_stringOpt.Location = m_locSubCtrl; m_stringOpt.Initialize(m_cache, m_helpTopicProvider, m_app, m_stylesheet, m_rsfm); break; case CellarPropertyType.GenDate: m_groupOptions.Text = LexTextControls.ksGenDateImportOptions; m_groupOptions.Controls.Add(m_dateOpt); m_dateOpt.Location = m_locSubCtrl; m_dateOpt.Initialize(m_cache, m_helpTopicProvider, m_rsfm, true); break; case CellarPropertyType.Time: m_groupOptions.Text = LexTextControls.ksDateTimeImportOptions; m_groupOptions.Controls.Add(m_dateOpt); m_dateOpt.Location = m_locSubCtrl; m_dateOpt.Initialize(m_cache, m_helpTopicProvider, m_rsfm, false); break; case CellarPropertyType.Unicode: case CellarPropertyType.Binary: case CellarPropertyType.Image: case CellarPropertyType.Boolean: case CellarPropertyType.Float: case CellarPropertyType.Guid: case CellarPropertyType.Integer: case CellarPropertyType.Numeric: throw new ArgumentException(LexTextControls.ksInvalidField); } }
int MakeRealObject(ITsString tssTyped) { // Figure whether owning atomic or owning collection or owning sequence. Throw if none. // Unless we're making an unowned IText for a Notebook Record. ISilDataAccess sdaReal = m_fdoCache.DomainDataByFlid; IFwMetaDataCache mdc = sdaReal.MetaDataCache; CellarPropertyType typeOwning = (CellarPropertyType)(mdc.GetFieldType(m_flidEmptyProp) & (int)CellarPropertyTypeFilter.VirtualMask); // Make a new object of the specified class in the specified property. int ord = 0; switch (typeOwning) { default: if (m_flidEmptyProp != RnGenericRecTags.kflidText) { throw new Exception("ghost string property must be owning object property"); } break; case CellarPropertyType.OwningAtomic: ord = -2; break; case CellarPropertyType.OwningCollection: ord = -1; break; case CellarPropertyType.OwningSequence: // ord = 0 set above (inserting the first and only object at position 0). break; } string sClassRaw = mdc.GetClassName(m_clidDst); string sClass = m_mediator.StringTbl.GetString(sClassRaw, "ClassNames"); string sUndo = String.Format(DetailControlsStrings.ksUndoCreate0, sClass); string sRedo = String.Format(DetailControlsStrings.ksRedoCreate0, sClass); int hvoNewObj = 0; int hvoStringObj = 0; UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(sUndo, sRedo, m_fdoCache.ServiceLocator.GetInstance <IActionHandler>(), () => { // Special case: if we just created a Text in RnGenericRecord, and we want to show the contents // of an StTxtPara, make the intermediate objects if (m_flidEmptyProp == RnGenericRecTags.kflidText) { var servLoc = Cache.ServiceLocator; var text = servLoc.GetInstance <ITextFactory>().Create(); var stText = servLoc.GetInstance <IStTextFactory>().Create(); text.ContentsOA = stText; var para = servLoc.GetInstance <IStTxtParaFactory>().Create(); stText.ParagraphsOS.Add(para); hvoNewObj = text.Hvo; hvoStringObj = para.Hvo; // Set the RnGenericRec's Text property to reference the new text sdaReal.SetObjProp(m_hvoObj, m_flidEmptyProp, hvoNewObj); } else { hvoNewObj = hvoStringObj = sdaReal.MakeNewObject(m_clidDst, m_hvoObj, m_flidEmptyProp, ord); } // Set its property m_flidStringProp to tssTyped. If it is multilingual, choose based on ghostWs. var typeString = (CellarPropertyType)(mdc.GetFieldType(m_flidStringProp) & (int)CellarPropertyTypeFilter.VirtualMask); switch (typeString) { default: throw new Exception("ghost property must store strings!"); case CellarPropertyType.MultiString: case CellarPropertyType.MultiUnicode: sdaReal.SetMultiStringAlt(hvoStringObj, m_flidStringProp, m_wsToCreate, tssTyped); break; case CellarPropertyType.String: sdaReal.SetString(hvoStringObj, m_flidStringProp, tssTyped); break; } string ghostInitMethod = XmlUtils.GetOptionalAttributeValue(m_nodeObjProp, "ghostInitMethod"); if (ghostInitMethod != null) { var obj = m_fdoCache.ServiceLocator.GetInstance <ICmObjectRepository>().GetObject(hvoNewObj); Type objType = obj.GetType(); System.Reflection.MethodInfo mi = objType.GetMethod(ghostInitMethod); mi.Invoke(obj, null); } }); return(hvoNewObj); }
public virtual int AddCustomField(string className, string fieldName, CellarPropertyType fieldType, int destinationClass) { return(m_metaDataCache.AddCustomField(className, fieldName, fieldType, destinationClass)); }
/// <summary> /// Returns true for Binary, Boolean, GenDate, Integer and Time /// </summary> /// <param name="type"></param> /// <returns></returns> public bool IsValueType(CellarPropertyType type) { return m_metaDataCache.IsValueType(type); }
private XmlNode GetFxtNodeAndFxtItemLabel(string sClassName, int flid, string sFieldName, CellarPropertyType fieldType, out string sResultOwningElementName, out bool fIsRefVector, out string sFxtItemLabel) { const string ksObjVector = "objVector"; string sObjFieldType = "OS"; if (fieldType == CellarPropertyType.OwningCollection) sObjFieldType = "OC"; string[] asAttributeValues = new string[1]; asAttributeValues[0] = sFieldName + sObjFieldType; FXTElementSearchProperties searchProps = new FXTElementSearchProperties(ksObjVector, "objProperty", asAttributeValues); List<FXTElementSearchProperties> searchPropsList = new List<FXTElementSearchProperties>(2); searchPropsList.Add(searchProps); string[] asAttributeValues2 = new string[1]; asAttributeValues2[0] = sFieldName; FXTElementSearchProperties searchProps2 = new FXTElementSearchProperties(ksRefVector, ksField, asAttributeValues2); searchPropsList.Add(searchProps2); string sAttrValueFound; FXTElementSearchProperties searchPropsFound; XmlNode fxtFieldNode = GetFxtFieldNode(sClassName, searchPropsList, out sResultOwningElementName, out searchPropsFound, out sAttrValueFound); if (fxtFieldNode == null) { sResultOwningElementName = ""; fIsRefVector = false; sFxtItemLabel = ""; return null; // Not all fields are addressed in the FXT description } if (searchPropsFound.ElementName == ksObjVector) { fIsRefVector = false; // want the signature of the field int destClassId = m_cache.GetDestinationClass((int) flid); if (m_cache.DomainDataByFlid.MetaDataCache.GetAbstract(destClassId)) { int iCount = 0; StringBuilder sbSubClasses = new StringBuilder(); GetNamesOfSubClasses(destClassId, sbSubClasses, iCount); sFxtItemLabel = sbSubClasses.ToString(); } else sFxtItemLabel = m_cache.DomainDataByFlid.MetaDataCache.GetClassName(destClassId); } else { fIsRefVector = true; XmlNode fxtItemLabelAttr = fxtFieldNode.SelectSingleNode("@itemLabel"); sFxtItemLabel = fxtItemLabelAttr.InnerText; } return fxtFieldNode; }
public int AddCustomField(string className, string fieldName, CellarPropertyType fieldType, int destinationClass, string fieldHelp, int fieldWs, Guid fieldListRoot) { return m_metaDataCache.AddCustomField(className, fieldName, fieldType, destinationClass, fieldHelp, fieldWs, fieldListRoot); }
private bool IsSupportedFieldType(CellarPropertyType fieldType) { switch (fieldType) { case CellarPropertyType.OwningAtomic: case CellarPropertyType.ReferenceAtomic: case CellarPropertyType.Boolean: //case CellarPropertyType.Float: // Not yet supported (as of 23 march 2013) case CellarPropertyType.GenDate: case CellarPropertyType.Guid: case CellarPropertyType.Integer: //case CellarPropertyType.Numeric: // Not yet supported (as of 23 march 2013) case CellarPropertyType.Time: return true; } return false; }
/// <summary> /// Add a user-defined custom field. /// </summary> /// <param name="className">Class that gets the new custom field.</param> /// <param name="fieldName">Field name for the custom field.</param> /// <param name="fieldType">Data type for the custom field.</param> /// <param name="destinationClass">Class Id for object type custom properties</param> /// <returns>The Id for the new custom field.</returns> /// <exception cref="KeyNotFoundException"> /// Thrown if 'fieldType' is an object type (owning/reference and atomic/collection/sequence) property, /// but 'destinationClass' does not match a class in the model. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown if 'className' or 'fieldName' are null or empty. /// </exception> /// <exception cref="KeyNotFoundException"> /// Thrown if class is not defined. /// </exception> /// <remarks> /// If 'fieldType' is a basic property type, then 'destinationClass' is ignored. /// /// If 'fieldType' is an object type (owning/reference and atomic/collection/sequence) property, /// then 'destinationClass' must match a class in the model. /// </remarks> public int AddCustomField(string className, string fieldName, CellarPropertyType fieldType, int destinationClass) { return AddCustomField(className, fieldName, fieldType, destinationClass, null, 0, Guid.Empty); }
// extracted from the CellarPropertyType enum protected static string GetFlidTypeAsString(CellarPropertyType flidType) { string retval; switch (flidType) { default: throw new ArgumentException("Property element name not recognized."); case CellarPropertyType.Boolean: retval = "Boolean"; break; case CellarPropertyType.Integer: retval = "Integer"; break; case CellarPropertyType.Time: retval = "Time"; break; case CellarPropertyType.String: retval = "String"; break; case CellarPropertyType.MultiString: retval = "MultiString"; break; case CellarPropertyType.Unicode: retval = "Unicode"; break; case CellarPropertyType.MultiUnicode: retval = "MultiUnicode"; break; case CellarPropertyType.Guid: retval = "Guid"; break; case CellarPropertyType.Image: retval = "Image"; break; case CellarPropertyType.GenDate: retval = "GenDate"; break; case CellarPropertyType.Binary: retval = "Binary"; break; case CellarPropertyType.Numeric: retval = "Numeric"; break; case CellarPropertyType.Float: retval = "Float"; break; case CellarPropertyType.OwningAtomic: retval = "OA"; break; case CellarPropertyType.OwningCollection: retval = "OC"; break; case CellarPropertyType.OwningSequence: retval = "OS"; break; case CellarPropertyType.ReferenceAtomic: retval = "RA"; break; case CellarPropertyType.ReferenceCollection: retval = "RC"; break; case CellarPropertyType.ReferenceSequence: retval = "RS"; break; } return retval; }
public int AddCustomField(string className, string fieldName, CellarPropertyType fieldType, int destinationClass, string fieldHelp, int fieldWs, Guid fieldListRoot) { int clid; if (m_classesByName.TryGetValue(className, out clid)) { List<MockFieldInfo> list; var flid = (clid * 1000) + 500; if (m_fieldsByClassId.TryGetValue(clid, out list)) { var flidMax = flid - 1; foreach (MockFieldInfo mfi in list) { if (mfi.m_fCustom && mfi.m_flid >= flid) flidMax = mfi.m_flid; } flid = flidMax + 1; } else { list = new List<MockFieldInfo>(); m_fieldsByClassId.Add(clid, list); } var mfiNew = new MockFieldInfo { m_flid = flid, m_name = fieldName, m_cpt = fieldType, m_destClsid = destinationClass, m_fCustom = true, m_fieldHelp = fieldHelp, m_fieldWs = fieldWs, m_fieldListRoot = fieldListRoot }; list.Add(mfiNew); m_fieldsById.Add(flid, mfiNew); return flid; } return 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; } }
/// <summary> /// Returns true for Boolean, GenDate, Guid, Integer, Float, Numeric, and Time /// </summary> /// <param name="type"></param> /// <remarks> /// Float and Numeric are not used in the model, as of 23 March 2013. /// </remarks> /// <returns></returns> public bool IsValueType(CellarPropertyType type) { return PropertyTypesForValueTypeData.Contains(type); }
/// <summary> /// Gets the data for one custom field, and any relevant GUIDs. /// </summary> /// <param name="hvo">Hvo of object we're getting the field for.</param> /// <param name="flid">Flid for this field.</param> /// <param name="fieldSourceType">Either "entry", "senses" or "examples". Could also be "allomorphs", eventually.</param> /// <param name="bsonForThisField">Output of a BsonDocument with the following structure: <br /> /// { fieldName: { "value": BsonValue, "guid": "some-guid-as-a-string" } } <br /> /// -OR- <br /> /// { fieldName: { "value": BsonValue, "guid": ["guid1", "guid2", "guid3"] } } <br /> /// The format of the fieldName key will be "customField_FOO_field_name_with_underscores", /// where FOO is one of "entry", "senses", or "examples". <br /> /// The type of the "guid" value (array or string) will determine whether there is a single GUID, /// or a list of GUIDs that happens to contain only one entry. /// If there is no "guid" key, that field has no need for a GUID. (E.g., a number). /// </param> /// <param name="listConverters">Dictionary of ConvertLcmToMongoOptionList instances, keyed by list code</param> private BsonDocument GetCustomFieldData(int hvo, int flid, string fieldSourceType, IDictionary <string, ConvertLcmToMongoOptionList> listConverters) { BsonValue fieldValue = null; BsonValue fieldGuid = null; // Might be a single value, might be a list (as a BsonArray) ISilDataAccessManaged data = (ISilDataAccessManaged)cache.DomainDataByFlid; CellarPropertyType LcmFieldType = (CellarPropertyType)LcmMetaData.GetFieldType(flid); var dataGuids = new List <Guid>(); // Valid field types in Lcm are GenDate, Integer, String, OwningAtomic, ReferenceAtomic, and ReferenceCollection, so that's all we implement. switch (LcmFieldType) { case CellarPropertyType.GenDate: GenDate genDate = data.get_GenDateProp(hvo, flid); string genDateStr = genDate.ToLongString(); // LF wants single-string fields in the format { "ws": { "value": "contents" } } fieldValue = String.IsNullOrEmpty(genDateStr) ? null : LfMultiText.FromSingleStringMapping( MagicStrings.LanguageCodeForGenDateFields, genDateStr).AsBsonDocument(); break; // When parsing, will use GenDate.TryParse(str, out genDate) case CellarPropertyType.Integer: fieldValue = new BsonInt32(data.get_IntProp(hvo, flid)); if (fieldValue.AsInt32 == default(Int32)) { fieldValue = null; // Suppress int fields with 0 in them, to save Mongo DB space } else { // LF wants single-string fields in the format { "ws": { "value": "contents" } } fieldValue = LfMultiText.FromSingleStringMapping( MagicStrings.LanguageCodeForIntFields, fieldValue.AsInt32.ToString()).AsBsonDocument(); } break; case CellarPropertyType.OwningAtomic: case CellarPropertyType.ReferenceAtomic: int ownedHvo = data.get_ObjectProp(hvo, flid); fieldValue = GetCustomReferencedObject(ownedHvo, flid, listConverters, ref dataGuids); if (fieldValue != null && LcmFieldType == CellarPropertyType.ReferenceAtomic) { // Single CmPossiblity reference - LF expects format like { "value": "key of possibility" } fieldValue = new BsonDocument("value", fieldValue); } fieldGuid = new BsonString(dataGuids.FirstOrDefault().ToString()); break; case CellarPropertyType.MultiUnicode: ITsMultiString tss = data.get_MultiStringProp(hvo, flid); if (tss != null && tss.StringCount > 0) { fieldValue = LfMultiText.FromMultiITsString(tss, servLoc.WritingSystemManager).AsBsonDocument(); } break; case CellarPropertyType.OwningCollection: case CellarPropertyType.OwningSequence: case CellarPropertyType.ReferenceCollection: case CellarPropertyType.ReferenceSequence: int[] listHvos = data.VecProp(hvo, flid); var innerValues = new BsonArray(listHvos.Select(listHvo => GetCustomReferencedObject(listHvo, flid, listConverters, ref dataGuids)).Where(x => x != null)); if (innerValues.Count == 0) { fieldValue = null; } else { fieldValue = new BsonDocument("values", innerValues); fieldGuid = new BsonArray(dataGuids.Select(guid => guid.ToString())); } break; case CellarPropertyType.String: ITsString iTsValue = data.get_StringProp(hvo, flid); if (iTsValue == null || String.IsNullOrEmpty(iTsValue.Text)) { fieldValue = null; } else { fieldValue = LfMultiText.FromSingleITsString(iTsValue, servLoc.WritingSystemManager).AsBsonDocument(); } break; default: fieldValue = null; if (logger != null) { logger.Warning("Lcm CellarPropertyType.{0} not recognized for LF custom field", LcmFieldType.ToString()); } break; } if (fieldValue == null) { return(null); } else { var result = new BsonDocument(); result.Add("value", fieldValue ?? BsonNull.Value); // BsonValues aren't allowed to have C# nulls; they have their own null representation if (fieldGuid is BsonArray) { result.Add("guid", fieldGuid, ((BsonArray)fieldGuid).Count > 0); } else { result.Add("guid", fieldGuid, fieldGuid != null); } return(result); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Check the IsPropInCache method. /// </summary> /// <param name="hvo">HVO part of the key</param> /// <param name="tag">tag part of the key</param> /// <param name="expValues">Expected values</param> /// ------------------------------------------------------------------------------------ private void CheckIsPropInCache(int hvo, int tag, object[] expValues) { for (CellarPropertyType cpt = CellarPropertyType.Nil; cpt <= CellarPropertyType.ReferenceSequence; cpt++) { bool flag = false; switch (cpt) { case CellarPropertyType.Nil: try { Assert.IsFalse(m_ISilDataAccess.get_IsPropInCache(hvo, tag, (int)cpt, 0)); } catch (ArgumentException) { } continue; case CellarPropertyType.Boolean: case CellarPropertyType.Integer: case CellarPropertyType.Numeric: flag = ((int)expValues[5] != 0); break; case CellarPropertyType.Float: // Never cached so far // TODO: We expect this to fail the test for VwCacheDa because the existing // implementation fails to set the return value to false. Need to fix this // at line 520 of VwCacheDa.cpp. break; case CellarPropertyType.Time: flag = (expValues[4] is long || (int)expValues[4] != 0); break; case CellarPropertyType.Guid: flag = ((Guid)expValues[3] != Guid.Empty); break; case CellarPropertyType.Image: case CellarPropertyType.GenDate: // Never cached so far // TODO: We expect this to fail the test for VwCacheDa because the existing // implementation fails to set the return value to false. Need to fix this // at line 535 of VwCacheDa.cpp. break; case CellarPropertyType.Binary: flag = (expValues[2] is byte[]); break; case CellarPropertyType.MultiString: case CellarPropertyType.MultiUnicode: flag = (expValues[6] != null); break; case CellarPropertyType.String: flag = (expValues[7] != null); break; case CellarPropertyType.Unicode: flag = (expValues[8] != null); break; case CellarPropertyType.OwningAtomic: case CellarPropertyType.ReferenceAtomic: flag = ((int)expValues[0] != 0); break; case CellarPropertyType.OwningCollection: case CellarPropertyType.ReferenceCollection: case CellarPropertyType.OwningSequence: case CellarPropertyType.ReferenceSequence: flag = (expValues[1] is int[]); break; default: continue; } Assert.AreEqual(flag, m_ISilDataAccess.get_IsPropInCache(hvo, tag, (int)cpt, 12345), string.Format("IsPropInCache for property type '{0}' failed;", cpt)); } }
bool m_fGotFocus = false; // True if we have focus. public TypeAheadSupportVc(int tag, FdoCache cache) { m_tag = tag; IFwMetaDataCache mdc = cache.DomainDataByFlid.MetaDataCache; m_clid = mdc.GetOwnClsId(m_tag); m_className = mdc.GetClassName(m_clid); m_fieldName = mdc.GetFieldName(m_tag); m_type = (CellarPropertyType)(mdc.GetFieldType(m_tag) & (int)CellarPropertyTypeFilter.VirtualMask); m_sda = cache.DomainDataByFlid; Cache = cache; }
/// -------------------------------------------------------------------------------- /// <summary> /// Add a field to the MetaDataCache. /// </summary> /// <param name="className">Name of the class.</param> /// <param name="flid">The flid.</param> /// <param name="fieldName">Name of the field.</param> /// <param name="fieldLabel">The field label.</param> /// <param name="fieldHelp">The field help.</param> /// <param name="fieldXml">The field XML.</param> /// <param name="fieldSignature">The field signature.</param> /// <param name="type">The type.</param> /// <param name="fsSource">The fs source.</param> /// <param name="fieldListRoot">The field list root.</param> /// <param name="fieldWs">The field ws.</param> /// -------------------------------------------------------------------------------- private void AddField(string className, int flid, string fieldName, string fieldLabel, string fieldHelp, string fieldXml, string fieldSignature, CellarPropertyType type, FieldSource fsSource, Guid fieldListRoot, int fieldWs) { // Will throw if class is not in one or the other Dictionaries. var clid = m_nameToClid[className]; var mcr = m_metaClassRecords[clid]; var mfr = new MetaFieldRec { m_flid = flid, m_fieldLabel = fieldLabel, m_fieldHelp = fieldHelp, m_fieldXml = fieldXml, m_fieldListRoot = fieldListRoot, m_fieldWs = fieldWs, m_sig = null, m_fieldSource = fsSource }; switch (type) { default: break; case CellarPropertyType.OwningAtomic: // Fall through case CellarPropertyType.OwningCollection: // Fall through case CellarPropertyType.OwningSequence: // Fall through case CellarPropertyType.ReferenceAtomic: // Fall through case CellarPropertyType.ReferenceCollection: // Fall through case CellarPropertyType.ReferenceSequence: mfr.m_sig = fieldSignature; // It may not be present yet when the whole MDC is being initialized via 'Init', // or the Constructor, as the case may be. // Only mess with setting this after intitialization of the main model. // Once all those model classes are in, a client can take his lumps // if this throws an exception. if (m_initialized) { if (string.IsNullOrEmpty(fieldSignature)) throw new KeyNotFoundException("'bstrFieldSignature' is a null or empty key."); // Note that m_fieldSource must be set before calling this. SetDestClass(mfr, m_nameToClid[fieldSignature]); } break; } mfr.m_fieldType = type; mfr.m_fieldName = fieldName; mfr.m_ownClsid = clid; mcr.AddField(mfr); m_metaFieldRecords[flid] = mfr; m_nameToFlid[MakeFlidKey(clid, fieldName)] = flid; }
/// <summary> /// Store a value for either a simple formatted string or a multilingual string. /// </summary> private void SetStringValue(IRnGenericRec rec, RnSfMarker rsf, Sfm2Xml.SfmField field, CellarPropertyType cpt) { // REVIEW: SHOULD WE WORRY ABOUT EMBEDDED CHAR MAPPINGS THAT CHANGE THE WRITING SYSTEM // WHEN IT COMES TO ENCODING CONVERSION??? ReconvertEncodedDataIfNeeded(field, rsf.m_sto.m_wsId); ITsString tss = MakeTsString(field.Data, rsf.m_sto.m_ws.Handle); switch (rsf.m_flid) { case RnGenericRecTags.kflidTitle: rec.Title = tss; break; default: // must be a custom field. Debug.Assert(rsf.m_flid >= (RnGenericRecTags.kClassId * 1000) + 500); switch (cpt) { case CellarPropertyType.MultiString: case CellarPropertyType.MultiUnicode: m_cache.DomainDataByFlid.SetMultiStringAlt(rec.Hvo, rsf.m_flid, rsf.m_sto.m_ws.Handle, tss); break; case CellarPropertyType.String: m_cache.DomainDataByFlid.SetString(rec.Hvo, rsf.m_flid, tss); break; } break; } }
private static string GetDefaultValueForPropertyType(CellarPropertyType propertyType) { switch (propertyType) { case CellarPropertyType.Boolean: return "False"; case CellarPropertyType.GenDate: var genDate = new GenDate(); return string.Format("{0}{1:0000}{2:00}{3:00}{4}", genDate.IsAD ? "" : "-", genDate.Year, genDate.Month, genDate.Day, (int)genDate.Precision); case CellarPropertyType.Guid: return Guid.Empty.ToString(); case CellarPropertyType.Float: throw new NotSupportedException("The 'Float' data type is not supported in the FW data model yet (as of 23 March 2013)."); case CellarPropertyType.Integer: return "0"; case CellarPropertyType.Time: var datetime = new DateTime(); datetime = datetime.ToUniversalTime(); // Store it as UTC. return String.Format("{0}-{1}-{2} {3}:{4}:{5}.{6}", datetime.Year, datetime.Month, datetime.Day, datetime.Hour, datetime.Minute, datetime.Second, datetime.Millisecond); case CellarPropertyType.Numeric: throw new NotSupportedException("The 'Numeric' data type is not supported in the FW data model yet (as of 23 March 2013)."); default: throw new InvalidOperationException("The given 'propertyType' is not a basic data type."); } }
/// <summary> /// Returns true for Binary, Boolean, GenDate, Integer and Time /// </summary> /// <param name="type"></param> /// <returns></returns> public bool IsValueType(CellarPropertyType type) { return(m_metaDataCache.IsValueType(type)); }
/// <summary> /// Should return true for value types; but not implemented /// </summary> /// <param name="type"></param> /// <returns></returns> public bool IsValueType(CellarPropertyType type) { throw new NotSupportedException(); }
public int AddCustomField(string className, string fieldName, CellarPropertyType fieldType, int destinationClass, string fieldHelp, int fieldWs, Guid fieldListRoot) { return(m_metaDataCache.AddCustomField(className, fieldName, fieldType, destinationClass, fieldHelp, fieldWs, fieldListRoot)); }
private void UpdateOwningVector(string sClassName, int flid, string sFieldName, int hvoItem, CellarPropertyType fieldType, XmlDocument fxtResult) { // hvoItem is the owner and something inside the owning sequence field has changed // so we want to find the owner object in the result file and then look for the field items within it. // Note: some use refVector when put real items elsewhere // Note: others use objVector for when the items are stored right here // Parents (i.e. the owner) // some have <element name=""> ; // others have just an (output) element; // some have just the <class> XmlNode resultNode; // figure out the name of the element that corresponds to the field bool fIsRefVector; string sFxtItemLabel; string sResultOwningElementName; XmlNode fxtFieldNode = GetFxtNodeAndFxtItemLabel(sClassName, flid, sFieldName, fieldType, out sResultOwningElementName, out fIsRefVector, out sFxtItemLabel); if (fxtFieldNode == null) return; // Not all fields are addressed in the FXT description file string sXPath = "//" + sResultOwningElementName + "[ancestor-or-self::*[@Id='" + hvoItem + "']]"; resultNode = fxtResult.SelectSingleNode(sXPath); // is the owner if (resultNode == null) { XmlNode objResultNode = FindOrInsertAllElementObject(hvoItem, fxtResult); if (objResultNode != null) { resultNode = objResultNode.SelectSingleNode("descendant-or-self::" + sResultOwningElementName); } else { // the item does not have an Id; it's just the parent element resultNode = fxtResult.SelectSingleNode("//" + sResultOwningElementName); if (resultNode == null) // The object has not been added to the result yet, most likely it is being initialized, so wait for owner to add it return; } } // get set of field items in the database List<int> hvosDatabase = GetHvosInDatabase(hvoItem, flid); // get set of field items in the FXT result file List<int> hvosResult = GetHvosInFxtResult(resultNode, sFxtItemLabel, fxtFieldNode); HandleOwningVectorDeletions(fxtResult, resultNode, hvosResult, hvosDatabase, flid); HandleVectorAdditions(fxtResult, resultNode, sFxtItemLabel, hvosResult, hvosDatabase, sResultOwningElementName, fIsRefVector); UpdateVectorOrds(resultNode, hvosDatabase); }