public void TryItOut() { var filter = new WordsUsedOnlyElsewhereFilter(); filter.Init(Cache, null); var sda = new FakeDecorator((ISilDataAccessManaged)Cache.DomainDataByFlid); filter.DataAccess = sda; UndoableUnitOfWorkHelper.Do("undo", "redo", m_actionHandler, () => { var wfTry = MakeWordform("try"); ISegment seg1; var text1 = MakeText("try it out", out seg1); seg1.AnalysesRS.Add(wfTry); Assert.That(wfTry.FullConcordanceCount, Is.EqualTo(1)); ManyOnePathSortItem itemTry = new ManyOnePathSortItem(wfTry); // Here the global count is non-zero but the corpus count is zero. Assert.That(filter.Accept(itemTry), Is.False, "should not accept an item which occurs elsewhere but not in corpus"); sda.HvoToOccurrenceCount[wfTry.Hvo] = 1; Assert.That(filter.Accept(itemTry), Is.True, "should accept an item in an included text"); sda.HvoToOccurrenceCount[wfTry.Hvo] = 5; Assert.That(filter.Accept(itemTry), Is.True, "should accept an item in an included text, even if there are other occurrences"); var wfNowhere = MakeWordform("nowhere"); ManyOnePathSortItem itemNowhere = new ManyOnePathSortItem(wfNowhere); Assert.That(filter.Accept(itemNowhere), Is.True, "should accept an item that occurs nowhere at all."); }); }
public void GenerateAtomicItems() { ArrayList list = new ArrayList(); XmlNode column = m_columnList[1]; // Etymology XmlViewsUtils.CollectBrowseItems(1, column, list, m_mdc, m_sda, m_layouts); Assert.AreEqual(1, list.Count, "got one item for etymology obj 1"); ManyOnePathSortItem bv = list[0] as ManyOnePathSortItem; Assert.AreEqual(60, bv.KeyObject); Assert.AreEqual(1, bv.PathLength); Assert.AreEqual(1, bv.PathObject(0)); Assert.AreEqual(2011, bv.PathFlid(0)); list.Clear(); XmlViewsUtils.CollectBrowseItems(4, column, list, m_mdc, m_sda, m_layouts); Assert.AreEqual(1, list.Count, "got one item for etymology obj 4"); list.Clear(); XmlViewsUtils.CollectBrowseItems(6, column, list, m_mdc, m_sda, m_layouts); Assert.AreEqual(1, list.Count, "got one item for etymology obj 6"); bv = list[0] as ManyOnePathSortItem; Assert.AreEqual(61, bv.KeyObject); Assert.AreEqual(1, bv.PathLength); Assert.AreEqual(6, bv.PathObject(0)); Assert.AreEqual(2011, bv.PathFlid(0)); }
public void GenerateSeqItems() { ArrayList list = new ArrayList(); XmlNode column = m_columnList[3]; // Glosses XmlViewsUtils.CollectBrowseItems(1, column, list, m_mdc, m_sda, m_layouts); Assert.AreEqual(1, list.Count, "got one items for glosses obj 1"); list.Clear(); XmlViewsUtils.CollectBrowseItems(4, column, list, m_mdc, m_sda, m_layouts); Assert.AreEqual(1, list.Count, "got one item for glosses obj 4"); ManyOnePathSortItem bv = list[0] as ManyOnePathSortItem; Assert.AreEqual(5, bv.KeyObject); Assert.AreEqual(1, bv.PathLength); Assert.AreEqual(4, bv.PathObject(0)); Assert.AreEqual(2010, bv.PathFlid(0)); list.Clear(); XmlViewsUtils.CollectBrowseItems(6, column, list, m_mdc, m_sda, m_layouts); Assert.AreEqual(3, list.Count, "got three items for glosses obj 6"); int[] keys = new int[] { 7, 8, 9 }; for (int i = 0; i < keys.Length; i++) { bv = list[i] as ManyOnePathSortItem; Assert.AreEqual(keys[i], bv.KeyObject); Assert.AreEqual(1, bv.PathLength); Assert.AreEqual(6, bv.PathObject(0)); Assert.AreEqual(2010, bv.PathFlid(0)); } }
private Set <int> GetDescendents(int hvoCommonAncestor, int relativesFlid) { string listPropertyName = Cache.MetaDataCacheAccessor.GetFieldName(relativesFlid); string parentObjName = Cache.ServiceLocator.GetInstance <ICmObjectRepository>().GetObject(hvoCommonAncestor).ClassName; string xpathToPart = "./part[@id='" + parentObjName + "-Jt-" + listPropertyName + "']"; XmlNode pathSpec = m_parentToChildrenSpecs.SelectSingleNode(xpathToPart); Debug.Assert(pathSpec != null, String.Format("You are experiencing a rare and difficult-to-reproduce error (LT- 11443 and linked issues). If you can add any information to the issue or fix it please do. If JohnT is available please call him over. Expected to find part ({0}) in ParentClassPathsToChildren", xpathToPart)); if (pathSpec == null) { return(new Set <int>()); // This just means we don't find a related object. Better than crashing, but not what we intend. } // get the part spec that gives us the path from obsolete current (parent) list item object // to the new one. var vc = new XmlBrowseViewBaseVc(m_cache, null); var parentItem = new ManyOnePathSortItem(hvoCommonAncestor, null, null); var collector = new XmlBrowseViewBaseVc.ItemsCollectorEnv(null, m_cache, hvoCommonAncestor); vc.DisplayCell(parentItem, pathSpec, hvoCommonAncestor, collector); if (collector.HvosCollectedInCell != null && collector.HvosCollectedInCell.Count > 0) { return(collector.HvosCollectedInCell); } return(new Set <int>()); }
private Set <int> GetDescendents(int hvoCommonAncestor, int relativesFlid) { string listPropertyName = Cache.MetaDataCacheAccessor.GetFieldName((uint)relativesFlid); string parentObjName = Cache.MetaDataCacheAccessor.GetClassName((uint)m_cache.GetClassOfObject(hvoCommonAncestor)); string xpathToPart = "./part[@id='" + parentObjName + "-Jt-" + listPropertyName + "']"; XmlNode pathSpec = m_parentToChildrenSpecs.SelectSingleNode(xpathToPart); if (pathSpec == null) { throw new ArgumentException("Expected to find part ({0}) in ParentClassPathsToChildren", xpathToPart); } // get the part spec that gives us the path from obsolete current (parent) list item object // to the new one. using (XmlBrowseViewBaseVc vc = new XmlBrowseViewBaseVc(m_cache, null)) { ManyOnePathSortItem parentItem = new ManyOnePathSortItem(hvoCommonAncestor, null, null); XmlBrowseViewBaseVc.ItemsCollectorEnv collector = new XmlBrowseViewBaseVc.ItemsCollectorEnv(null, m_cache, hvoCommonAncestor); vc.DisplayCell(parentItem, pathSpec, hvoCommonAncestor, collector); if (collector.HvosCollectedInCell != null && collector.HvosCollectedInCell.Count > 0) { return(collector.HvosCollectedInCell); } } return(new Set <int>()); }
private string GetChildObjKey(XmlNode layout, int hvo, ManyOnePathSortItem item, int pathIndex, bool sortedFromEnd) { ICmObject childObj = CmObject.CreateFromDBObject(m_cache, hvo); string layoutName = XmlUtils.GetManditoryAttributeValue(layout, "layout"); XmlNode part = XmlVc.GetNodeForPart(hvo, layoutName, true, m_sda, m_layouts); string key = GetKey(part, childObj, item, pathIndex, sortedFromEnd); if (key != null) { return(key); } return(CallSortMethod(childObj, sortedFromEnd)); }
public void DisplayAtomicPathObject() { ArrayList list = new ArrayList(); XmlNode column = m_columnList[1]; XmlViewsUtils.CollectBrowseItems(1, column, list, m_mdc, m_sda, m_layouts); ManyOnePathSortItem bvi = list[0] as ManyOnePathSortItem; // Try on first column. Nothing in the path matches, but we still dig inside // the span. int useHvo; List <XmlNode> collectStructNodes = new List <XmlNode>(); XmlNode useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[0], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(1, useHvo); CheckDebugId(useNode, "LexemeCf"); Assert.AreEqual(1, collectStructNodes.Count); CheckDebugId(collectStructNodes[0], "LexemeSpan"); // Try on matching column. collectStructNodes.Clear(); useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[1], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(bvi.KeyObject, useHvo); CheckDebugId(useNode, "EtymologyComment"); Assert.AreEqual(1, collectStructNodes.Count); XmlNode structNode1 = collectStructNodes[0]; CheckDebugId(structNode1, "EtymologySpan"); // Try on a column involving a lookup. This affects the node output. collectStructNodes.Clear(); useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[2], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(1, useHvo); CheckDebugId(useNode, "EntryMsaSeq"); Assert.AreEqual(1, collectStructNodes.Count); structNode1 = collectStructNodes[0]; CheckDebugId(structNode1, "EntryMsasDiv"); // On a different view of the Etymology, we should still get the Etymology object. collectStructNodes.Clear(); useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[6], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(bvi.KeyObject, useHvo); CheckDebugId(useNode, "EtymologyComment2"); // But this column has no structural nodes. Assert.AreEqual(0, collectStructNodes.Count); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Keys the specified item. /// </summary> /// <param name="item">The item.</param> /// <param name="fForSorting">if set to <c>true</c> [f for sorting].</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public ITsString Key(ManyOnePathSortItem item, bool fForSorting) { CheckDisposed(); if (m_cache == null) { throw new ApplicationException("There's no way the browse VC (m_vc) can get a string in its current state."); } int hvo = item.RootObject.Hvo; TsStringCollectorEnv collector; if (fForSorting) { collector = new SortCollectorEnv(null, m_cache.MainCacheAccessor, hvo); } else { collector = new TsStringCollectorEnv(null, m_cache.MainCacheAccessor, hvo); } // This will check to see if the VC is either null or disposed. The disposed check is neccesary because // there are several instances where we can have a reference to an instance that was disposed, which will // cause problems later on. // Enhance CurtisH/EricP: If this VC gets used in other places, rather than adding more checks like this one, // it may be better to refactor XWorksViewBase to cause it to reload the sorter and filter from persistence // every time the tool is changed if (m_vc == null || m_vc.IsDisposed) { m_vc = new XmlBrowseViewBaseVc(m_cache, m_stringTbl); } else { if (m_vc.Cache == null) { m_vc.Cache = m_cache; } if (m_vc.Cache == null) { throw new ApplicationException("There's no way the browse VC (m_vc) can get a string in its current state."); } if (m_vc.StringTbl == null) { m_vc.StringTbl = m_stringTbl; } } m_vc.DisplayCell(item, m_colSpec, hvo, collector); return(collector.Result); }
/// <summary> /// Get the items to be compared against the filter. /// </summary> /// <param name="item"></param> /// <returns></returns> protected override int[] GetItems(ManyOnePathSortItem item) { ISilDataAccess sda = m_cache.MainCacheAccessor; List <int> results = new List <int>(); if (item.PathLength > 0 && item.PathFlid(0) == kflidMsas) { // sorted by MSA, match just the one MSA. // I don't think this path can occur with the current XML spec where this is used. int hvoMsa; if (item.PathLength > 1) { hvoMsa = item.PathObject(1); } else { hvoMsa = item.KeyObject; } GetItemsForMsaType(sda, ref results, hvoMsa); } else if (item.PathLength >= 1 && item.PathFlid(0) == kflidEntrySenses) { // sorted in a way that shows one sense per row, test that sense's MSA. int hvoSense; if (item.PathLength > 1) { hvoSense = item.PathObject(1); } else { hvoSense = item.KeyObject; } int hvoMsa = sda.get_ObjectProp(hvoSense, (int)LexSense.LexSenseTags.kflidMorphoSyntaxAnalysis); GetItemsForMsaType(sda, ref results, hvoMsa); } else { int hvoEntry = item.RootObject.Hvo; int cmsa = sda.get_VecSize(hvoEntry, kflidMsas); for (int imsa = 0; imsa < cmsa; imsa++) { int hvoMsa = sda.get_VecItem(hvoEntry, kflidMsas, imsa); GetItemsForMsaType(sda, ref results, hvoMsa); } } return(results.ToArray()); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Figure the node and hvo that correspond to the particular sort item, /// and generate its key. This figures out the XML needed for the particular /// key object, and interprets it to make a key. /// </summary> /// <param name="item">The item.</param> /// <param name="sortedFromEnd"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public string[] Strings(ManyOnePathSortItem item, bool sortedFromEnd) { CheckDisposed(); string result = Key(item, true).Text; if (result == null) { return(new string[0]); } else { if (sortedFromEnd) { result = StringUtils.ReverseString(result); } return(new string[] { result }); } }
public void DisplayPathlessObject() { ArrayList list = new ArrayList(); XmlNode column = m_columnList[0]; XmlViewsUtils.CollectBrowseItems(1, column, list, m_mdc, m_sda, m_layouts); ManyOnePathSortItem bvi = list[0] as ManyOnePathSortItem; // Try on original column. We get original object since there's no path, // but we still dig inside the span int useHvo; List <XmlNode> collectStructNodes = new List <XmlNode>(); XmlNode useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[0], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(1, useHvo); CheckDebugId(useNode, "LexemeCf"); Assert.AreEqual(1, collectStructNodes.Count); CheckDebugId(collectStructNodes[0], "LexemeSpan"); // Try on another column. Again we get original object, and dig inside span collectStructNodes.Clear(); useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[1], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(1, useHvo); CheckDebugId(useNode, "EtymologyObj"); Assert.AreEqual(1, collectStructNodes.Count); XmlNode structNode1 = collectStructNodes[0]; CheckDebugId(structNode1, "EtymologySpan"); // Try on a column involving a lookup. This affects the node output. collectStructNodes.Clear(); useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[2], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(1, useHvo); CheckDebugId(useNode, "EntryMsaSeq"); Assert.AreEqual(1, collectStructNodes.Count); structNode1 = collectStructNodes[0]; CheckDebugId(structNode1, "EntryMsasDiv"); }
public void GeneratePathlessItems() { ArrayList list = new ArrayList(); XmlNode column = m_columnList[0]; XmlViewsUtils.CollectBrowseItems(1, column, list, m_mdc, m_sda, m_layouts); Assert.AreEqual(1, list.Count, "got one item for lexeme obj 1"); ManyOnePathSortItem bv = list[0] as ManyOnePathSortItem; Assert.AreEqual(1, bv.KeyObject); Assert.AreEqual(0, bv.PathLength); list.Clear(); XmlViewsUtils.CollectBrowseItems(4, column, list, m_mdc, m_sda, m_layouts); Assert.AreEqual(1, list.Count, "got one item for lexeme obj 4"); list.Clear(); XmlViewsUtils.CollectBrowseItems(6, column, list, m_mdc, m_sda, m_layouts); Assert.AreEqual(1, list.Count, "got one item for lexeme obj 6"); bv = list[0] as ManyOnePathSortItem; Assert.AreEqual(6, bv.KeyObject); Assert.AreEqual(0, bv.PathLength); }
const int maxDigits = 10; // Int32.MaxValue.ToString().Length;, but that is not 'const'! /// ------------------------------------------------------------------------------------ /// <summary> /// Get a key from the item for sorting. Add enough leading zeros so string comparison works. /// Note: negative number case not tested, for lack of a current example where it is possible. /// </summary> /// <param name="item">The item.</param> /// <param name="sortedFromEnd">if set to <c>true</c> [sorted from end].</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public override string[] SortStrings(ManyOnePathSortItem item, bool sortedFromEnd) { CheckDisposed(); string[] baseResult = base.SortStrings(item, sortedFromEnd); if (sortedFromEnd) { return(baseResult); // what on earth would it mean?? } if (baseResult.Length != 1) { return(baseResult); } string sVal = baseResult[0]; if (sVal.Length == 0) { return new string[] { new String('0', maxDigits) } } ; string prefix = sVal.Substring(0, 1); if (prefix == "-") { sVal = sVal.Substring(1); // strip off the minus } else { prefix = ""; // not negated, no prefix needed. } if (sVal.Length == maxDigits) { return new string[] { prefix + sVal } } ; else { return new string[] { prefix + new String('0', maxDigits - sVal.Length) + sVal } }; }
/// <summary> /// Get a key from the item. /// </summary> /// <param name="item">The item.</param> /// <param name="sortedFromEnd">if set to <c>true</c> [sorted from end].</param> /// <returns></returns> public override string[] SortStrings(ManyOnePathSortItem item, bool sortedFromEnd) { CheckDisposed(); if (item.KeyCmObject == null) { return(new string[0]); } // traverse the part tree from the root, the root object and the root layout node should // be compatible XmlNode layout = XmlVc.GetNodeForPart(item.RootObject.Hvo, m_layoutName, true, m_sda, m_layouts); string key = GetKey(layout, item.RootObject, item, 0, sortedFromEnd); if (key == null) { // the root object sort method is not tried in GetKey key = CallSortMethod(item.RootObject, sortedFromEnd); if (key == null) { // try calling the sort method on the key object key = CallSortMethod(item.KeyCmObject, sortedFromEnd); if (key == null) { // Try the default fallback if we can't find the method. key = item.KeyCmObject.SortKey ?? ""; if (sortedFromEnd) { key = StringUtils.ReverseString(key); } key = key + " " + item.KeyCmObject.SortKey2Alpha; } } } return(new string[] { key }); }
public void DisplayDoubleSeqPathObject() { ArrayList list = new ArrayList(); XmlNode column = m_columnList[5]; XmlViewsUtils.CollectBrowseItems(6, column, list, m_mdc, m_sda, m_layouts); ManyOnePathSortItem bvi = list[0] as ManyOnePathSortItem; // Try on first column. Nothing in the path matches, but we still dig inside // the span. int useHvo; List <XmlNode> collectStructNodes = new List <XmlNode>(); XmlNode useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[0], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(6, useHvo); CheckDebugId(useNode, "LexemeCf"); Assert.AreEqual(1, collectStructNodes.Count); CheckDebugId(collectStructNodes[0], "LexemeSpan"); // Try on etymology column. Has an <obj>, but doens't match collectStructNodes.Clear(); useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[1], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(6, useHvo); CheckDebugId(useNode, "EtymologyObj"); Assert.AreEqual(1, collectStructNodes.Count); XmlNode structNode1 = collectStructNodes[0]; CheckDebugId(structNode1, "EtymologySpan"); // Try on a column involving a lookup. This affects the node output. collectStructNodes.Clear(); useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[2], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(6, useHvo); CheckDebugId(useNode, "EntryMsaSeq"); Assert.AreEqual(1, collectStructNodes.Count); structNode1 = collectStructNodes[0]; CheckDebugId(structNode1, "EntryMsasDiv"); // On the matching column, we should get the leaf object collectStructNodes.Clear(); useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[5], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(bvi.KeyObject, useHvo); CheckDebugId(useNode, "PACN_Para"); Assert.AreEqual(1, collectStructNodes.Count); structNode1 = collectStructNodes[0]; CheckDebugId(structNode1, "DosDiv"); // On the gloss column, we get the sense. collectStructNodes.Clear(); useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[3], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(7, useHvo); // the first sense CheckDebugId(useNode, "SenseGloss"); Assert.AreEqual(1, collectStructNodes.Count); structNode1 = collectStructNodes[0]; CheckDebugId(structNode1, "SenseGlossPara"); // Make sure that for later Bvis, we get later senses collectStructNodes.Clear(); bvi = list[3] as ManyOnePathSortItem; useNode = XmlViewsUtils.GetNodeToUseForColumn(bvi, m_columnList[3], m_mdc, m_sda, m_layouts, out useHvo, collectStructNodes); Assert.AreEqual(9, useHvo); // the third sense, in which context we display the 4th SD }
/// ------------------------------------------------------------------------------------ /// <summary> /// Keys the specified item. /// </summary> /// <param name="item">The item.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public ITsString Key(ManyOnePathSortItem item) { CheckDisposed(); return(Key(item, false)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// For most of these we want to return the same thing. /// </summary> /// <param name="item">The item.</param> /// <param name="sortedFromEnd">if set to <c>true</c> [sorted from end].</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public virtual string[] SortStrings(ManyOnePathSortItem item, bool sortedFromEnd) { CheckDisposed(); return(Strings(item, sortedFromEnd)); }
/// <summary> /// Gets the sort key by traversing the part tree, calling the sort method at the leaves. /// </summary> /// <param name="layout">The layout.</param> /// <param name="cmo">The object.</param> /// <param name="item">The item.</param> /// <param name="pathIndex">Index of the path.</param> /// <param name="sortedFromEnd">if set to <c>true</c> [sorted from end].</param> /// <returns></returns> private string GetKey(XmlNode layout, ICmObject cmo, ManyOnePathSortItem item, int pathIndex, bool sortedFromEnd) { if (layout == null) { return(null); } switch (layout.Name) { case "obj": { int flid = GetFlid(layout, cmo.Hvo); if (pathIndex != -1 && (pathIndex == item.PathLength || flid != item.PathFlid(pathIndex))) { // we are now off of the path pathIndex = -1; } int objHvo = m_cache.GetObjProperty(cmo.Hvo, flid); if (objHvo != 0) { if (pathIndex != -1 && (pathIndex < item.PathLength - 1 && objHvo == item.PathObject(pathIndex + 1)) || (pathIndex == item.PathLength - 1 && objHvo == item.KeyObject)) { return(GetChildObjKey(layout, objHvo, item, pathIndex + 1, sortedFromEnd)); } // we are off of the path return(GetChildObjKey(layout, objHvo, item, -1, sortedFromEnd)); } } break; case "seq": { int flid = GetFlid(layout, cmo.Hvo); if (pathIndex != -1 && (pathIndex == item.PathLength || flid != item.PathFlid(pathIndex))) { // we are now off of the path pathIndex = -1; } int size = m_cache.GetVectorSize(cmo.Hvo, flid); StringBuilder sb = null; for (int i = 0; i < size; i++) { int objHvo = m_cache.GetVectorItem(cmo.Hvo, flid, i); if (pathIndex != -1 && (pathIndex < item.PathLength - 1 && objHvo == item.PathObject(pathIndex + 1)) || (pathIndex == item.PathLength - 1 && objHvo == item.KeyObject)) { return(GetChildObjKey(layout, objHvo, item, pathIndex + 1, sortedFromEnd)); } // if we are off of the path, we concatenate all vector keys to create an // aggregate key string childObjKey = GetChildObjKey(layout, objHvo, item, -1, sortedFromEnd); if (childObjKey != null) { if (sb == null) { sb = new StringBuilder(); } sb.Append(childObjKey); } } if (sb != null) { return(sb.ToString()); } } break; case "layout": case "part": { string partref = XmlUtils.GetOptionalAttributeValue(layout, "ref"); if (partref != null) { XmlNode part = XmlVc.GetNodeForPart(cmo.Hvo, partref, true, m_sda, m_layouts); return(GetKey(part, cmo, item, pathIndex, sortedFromEnd)); } foreach (XmlNode child in layout.ChildNodes) { if (child is XmlComment) { continue; } string key = GetKey(child, cmo, item, pathIndex, sortedFromEnd); if (key != null) { return(key); } } } break; } return(null); }
public int Compare(object x1, object y1) { ManyOnePathSortItem x = x1 as ManyOnePathSortItem; ManyOnePathSortItem y = y1 as ManyOnePathSortItem; int hvoX = x.KeyObject; // CmBaseAnnotations int hvoY = y.KeyObject; int hvoParaX = m_cache.GetObjProperty(hvoX, (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginObject); int hvoParaY = m_cache.GetObjProperty(hvoY, (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginObject); if (hvoParaX == hvoParaY) { // Compare begin offsets and return int offsetX = m_cache.GetIntProperty(hvoX, (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginOffset); int offsetY = m_cache.GetIntProperty(hvoY, (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginOffset); return(offsetX - offsetY); } // Enhance: do something about picture captions?? // While owning objects are the same type, get the owner of each, if they are the same, // compare their position in owner. Special case to put heading before body. // If owners are not the same type, do some trick that will make FLEx texts come before Scripture. int hvoObjX = hvoParaX; int hvoObjY = hvoParaY; do { int hvoOwnerX = m_cache.GetOwnerOfObject(hvoObjX); int hvoOwnerY = m_cache.GetOwnerOfObject(hvoObjY); if (hvoOwnerX == 0) { if (hvoOwnerY == 0) { return(hvoY - hvoX); // totally arbitrary but at least consistent } return(-1); // also arbitrary } if (hvoOwnerY == 0) { return(1); // arbitrary, object with shorter chain comes first. } if (hvoOwnerX == hvoOwnerY) { int flidX = m_cache.GetOwningFlidOfObject(hvoObjX); int flidY = m_cache.GetOwningFlidOfObject(hvoObjY); if (flidX != flidY) { return(flidX - flidY); // typically body and heading. } int indexX = m_cache.GetObjIndex(hvoOwnerX, flidX, hvoObjX); int indexY = m_cache.GetObjIndex(hvoOwnerY, flidY, hvoObjY); return(indexX - indexY); } int clsX = m_cache.GetClassOfObject(hvoOwnerX); int clsY = m_cache.GetClassOfObject(hvoOwnerY); if (clsX != clsY) { // Typically one is in Scripture, the other in a Text. // Arbitrarily order things by the kind of parent they're in. // Enhance JohnT: this will need improvement if we go to hierarchical // structures like nested sections or a folder organization of texts. // We could loop all the way up, and then back down till we find a pair // of owners that are different. // (We reverse the usual X - Y in order to put Texts before Scripture // in this list as in the Texts list in FLEx.) return(clsY - clsX); } hvoObjX = hvoOwnerX; hvoObjY = hvoOwnerY; } while (true); // We'll eventually reach the top of the ownership hierarchy. }