/// <summary> /// Returns value of custom fields for this CmObject. /// </summary> /// <returns>Either null or a BsonDocument with the following structure /// <br /> /// { <br /> /// "customFields": { fieldName: fieldValue, fieldName2: fieldValue2, etc. } <br /> /// "customFieldGuids": { fieldName: "Guid-as-string", fieldName2: "Guid2-as-string", etc. } <br /> /// } <br /> /// -OR- <br /> /// { <br /> /// "customFields": { fieldName: fieldValue, fieldName2: fieldValue2, etc. } <br /> /// "customFieldGuids": { fieldName: ["guid1", "guid2", "guid3"], fieldName2: "Guid2-as-string", etc. } <br /> /// } <br /> /// The format of the fieldName keys will be "customField_FOO_field_name_with_underscores", /// where FOO is one of "entry", "senses", or "examples". <br /> /// Some fields have no need for a GUID (e.g., a custom number field), so not all fieldNames will appear in customFieldGuids. /// Only custom fields with actual data will be returned: empty lists and strings will be suppressed, and integer /// fields whose value is 0 will be suppressed. (They will get the default int value, 0, when read from Mongo, so this /// allows us to save space in the Mongo DB). If a custom field's value is suppressed, it will not appear in the output, /// and will not have a corresponding value in customFieldGuids. /// If ALL custom fields are suppressed because of having null, default or empty values, then this function will return /// null instead of returning a useless-but-not-actually-empty BsonDocument. /// </returns> /// <param name="cmObj">Cm object.</param> /// <param name="objectType">Either "entry", "senses", or "examples"</param> /// <param name="listConverters">Dictionary of ConvertLcmToMongoOptionList instances, keyed by list code</param> public BsonDocument GetCustomFieldsForThisCmObject(ICmObject cmObj, string objectType, IDictionary <string, ConvertLcmToMongoOptionList> listConverters) { if (cmObj == null) { return(null); } List <int> customFieldIds = new List <int>( LcmMetaData.GetFields(cmObj.ClassID, false, (int)CellarPropertyTypeFilter.All) .Where(flid => cache.GetIsCustomField(flid))); var customFieldData = new BsonDocument(); var customFieldGuids = new BsonDocument(); foreach (int flid in customFieldIds) { string label = LcmMetaData.GetFieldNameOrNull(flid); if (label == null) { return(null); } string lfCustomFieldName = ConvertUtilities.NormalizedFieldName(label, objectType); BsonDocument bsonForThisField = GetCustomFieldData(cmObj.Hvo, flid, objectType, listConverters); if (bsonForThisField != null) { customFieldData.Add(lfCustomFieldName, bsonForThisField["value"]); BsonValue guid; if (bsonForThisField.TryGetValue("guid", out guid)) { if (guid is BsonArray) { customFieldGuids.Add(lfCustomFieldName, guid, ((BsonArray)guid).Count > 0); } else { customFieldGuids.Add(lfCustomFieldName, guid); } } } } BsonDocument result = new BsonDocument(); result.Add("customFields", customFieldData); result.Add("customFieldGuids", customFieldGuids); return(result); }
public void SetCustomFieldsForThisCmObject(ICmObject cmObj, string objectType, BsonDocument customFieldValues, BsonDocument customFieldGuids) { if (customFieldValues == null) { return; } IEnumerable <int> customFieldIds = lcmMetaData.GetFields(cmObj.ClassID, false, (int)CellarPropertyTypeFilter.All) .Where(flid => cache.GetIsCustomField(flid)); var remainingFieldNames = new HashSet <string>(customFieldValues.Select(elem => elem.Name)); foreach (int flid in customFieldIds) { string fieldName = lcmMetaData.GetFieldNameOrNull(flid); if (fieldName == null) { return; } fieldName = ConvertUtilities.NormalizedFieldName(fieldName, objectType); BsonValue fieldValue = customFieldValues.GetValue(fieldName, BsonNull.Value); BsonValue fieldGuidOrGuids = (customFieldGuids == null) ? BsonNull.Value : customFieldGuids.GetValue(fieldName, BsonNull.Value); // Persist Guid.Empty as null to save space if (fieldGuidOrGuids.BsonType == BsonType.String && fieldGuidOrGuids.AsString == "00000000-0000-0000-0000-000000000000") { fieldGuidOrGuids = BsonNull.Value; } remainingFieldNames.Remove(fieldName); if (fieldValue != BsonNull.Value) { SetCustomFieldData(cmObj.Hvo, flid, fieldValue, fieldGuidOrGuids); } } foreach (string fieldName in remainingFieldNames) { // TODO: These are NEW CUSTOM FIELDS! Will need to create them in LCM, then do: // BsonValue fieldValue = customFieldValues.GetValue(fieldName, BsonNull.Value); // BsonValue fieldGuidOrGuids = customFieldGuids.GetValue(fieldName, BsonNull.Value); // SetCustomFieldData(cmObj.Hvo, flid, fieldValue, fieldGuidOrGuids); // Above lines commented out until we can create new custom fields correctly. 2015-11 RM logger.Warning("Custom field {0} from LF skipped, because we're not yet creating new custom fields in LCM", fieldName); } }
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; } } } }