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) { } } }
/// <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); } }