示例#1
0
        /// <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);
            }
        }
示例#2
0
        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;
                    }
                }
            }
        }