This class caches the layout and part inventories and optimizes looking up a particular item.
示例#1
0
        /// <summary>
        /// Executes in two distinct scenarios.
        ///
        /// 1. If disposing is true, the method has been called directly
        /// or indirectly by a user's code via the Dispose method.
        /// Both managed and unmanaged resources can be disposed.
        ///
        /// 2. If disposing is false, the method has been called by the
        /// runtime from inside the finalizer and you should not reference (access)
        /// other managed objects, as they already have been garbage collected.
        /// Only unmanaged resources can be disposed.
        /// </summary>
        /// <param name="disposing"></param>
        /// <remarks>
        /// If any exceptions are thrown, that is fine.
        /// If the method is being done in a finalizer, it will be ignored.
        /// If it is thrown by client code calling Dispose,
        /// it needs to be handled by fixing the bug.
        ///
        /// If subclasses override this method, they should call the base implementation.
        /// </remarks>
        protected virtual void Dispose(bool disposing)
        {
            //Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************");
            // Must not be run more than once.
            if (m_isDisposed)
            {
                return;
            }

            if (disposing)
            {
                // Dispose managed resources here.
                // does not belong to us!
//				if (m_layouts != null)
//					m_layouts.Dispose();
            }

            // Dispose unmanaged resources here, whether disposing is true or false.
            m_sda        = null;
            m_layoutName = null;
            m_mdc        = null;
            m_cache      = null;
            m_layouts    = null;
            m_colSpec    = null;

            m_isDisposed = true;
        }
示例#2
0
		/// <summary>
		/// Returns an array of string values (keys) for the objects under this layout node.
		/// </summary>
		/// <param name="fdoCache">The fdo cache.</param>
		/// <param name="sda">The sda.</param>
		/// <param name="layout">The layout.</param>
		/// <param name="hvo">The hvo.</param>
		/// <param name="layoutCache">The layout cache.</param>
		/// <param name="caller">where layout is a component of a 'part' element, caller
		/// is the 'part ref' that invoked it.</param>
		/// <param name="stringTbl">The string TBL.</param>
		/// <param name="wsForce">if non-zero, "string" elements are forced to use that writing system for multistrings.</param>
		/// <returns></returns>
		static public string[] StringsFor(FdoCache fdoCache, ISilDataAccess sda, XmlNode layout, int hvo,
			LayoutCache layoutCache, XmlNode caller, StringTable stringTbl, int wsForce)
		{
			// Some nodes are known to be uninteresting.
			if (XmlVc.CanSkipNode(layout))
				return new string[0]; // don't know how to sort, treat as empty key.

			switch (layout.Name)
			{
				case "string":
				{
					int hvoTarget = hvo;
					XmlVc.GetActualTarget(layout, ref hvoTarget, sda);	// modify the hvo if needed
					if (hvo != hvoTarget)
					{
						return AddStringFromOtherObj(layout, hvoTarget, fdoCache, sda);
					}
					int flid = GetFlid(sda, layout, hvo);
					if (wsForce != 0)
					{
						// If we are forcing a writing system, and it's a multistring, get the forced alternative.
						int itype = sda.MetaDataCache.GetFieldType(flid);
						itype = itype & (int)CellarPropertyTypeFilter.VirtualMask;
						switch (itype)
						{
							case (int) CellarPropertyType.MultiUnicode:
							case (int) CellarPropertyType.MultiString:
								if (wsForce < 0)
								{
									int wsActual;
									var tss = WritingSystemServices.GetMagicStringAlt(fdoCache, sda, wsForce, hvo, flid, true, out wsActual);
									return new[] {tss == null ? "" : tss.Text };
								}
								return new[]
										   {sda.get_MultiStringAlt(hvo, flid, wsForce).Text};
						}
					}
					bool fFoundType;
					var strValue = fdoCache.GetText(hvo, flid, layout, out fFoundType);
					if (fFoundType)
						return new[] {strValue};

					throw new Exception("Bad property type (" + strValue + " for hvo " + hvo +
												" found for string property "
							+ flid + " in " + layout.OuterXml);
				}
				case "configureMlString":
				{
					int flid = GetFlid(sda, layout, hvo);
					// The Ws info specified in the part ref node
					HashSet<int> wsIds = WritingSystemServices.GetAllWritingSystems(fdoCache, caller, null, hvo, flid);
					if (wsIds.Count == 1)
					{
						var strValue = sda.get_MultiStringAlt(hvo, flid, wsIds.First()).Text;
						return new[] {strValue};
					}
					return new[] {AddMultipleAlternatives(fdoCache, sda, wsIds, hvo, flid, caller)};
				}
				case "multiling":
					return ProcessMultiLingualChildren(fdoCache, sda, layout, hvo, layoutCache, caller, stringTbl, wsForce);
				case "layout":
					// "layout" can occur when GetNodeToUseForColumn returns a phony 'layout'
					// formed by unifying a layout with child nodes. Assemble its children.
					// (arguably, we should treat that like div if current flow is a pile.
					// but we can't tell that and it rarely makes a difference.)
				case "para":
				case "span":
				{
					return AssembleChildKeys(fdoCache, sda, layout, hvo, layoutCache, caller, stringTbl, wsForce);
				}
				case "column":
					// top-level node for whole column; concatenate children as for "para"
					// if multipara is false, otherwise as for "div"
					if (XmlUtils.GetOptionalBooleanAttributeValue(layout, "multipara", false))
						return ChildKeys(fdoCache, sda, layout, hvo, layoutCache, caller, stringTbl, wsForce);
					else
						return AssembleChildKeys(fdoCache, sda, layout, hvo, layoutCache, caller, stringTbl, wsForce);

				case "part":
				{
					string partref = XmlUtils.GetOptionalAttributeValue(layout, "ref");
					if (partref == null)
						return ChildKeys(fdoCache, sda, layout, hvo, layoutCache, caller, stringTbl, wsForce); // an actual part, made up of its pieces
					XmlNode part = XmlVc.GetNodeForPart(hvo, partref, false, sda, layoutCache);
					// This is the critical place where we introduce a caller. The 'layout' is really a 'part ref' which is the
					// 'caller' for all embedded nodes in the called part.
					return StringsFor(fdoCache, sda, part, hvo, layoutCache, layout, stringTbl, wsForce);
				}
				case "div":
				case "innerpile":
				{
					// Concatenate keys for child nodes (as distinct strings)
					return ChildKeys(fdoCache, sda, layout, hvo, layoutCache, caller, stringTbl, wsForce);
				}
				case "obj":
				{
					// Follow the property, get the object, look up the layout to use,
					// invoke recursively.
					int flid = GetFlid(sda, layout, hvo);
					int hvoTarget = sda.get_ObjectProp(hvo, flid);
					if (hvoTarget == 0)
						break; // return empty key
					string targetLayoutName = XmlUtils.GetOptionalAttributeValue(layout, "layout"); // uses 'default' if missing.
					XmlNode layoutTarget = GetLayoutNodeForChild(sda, hvoTarget, flid, targetLayoutName, layout, layoutCache);
					if (layoutTarget == null)
						break;
					return ChildKeys(fdoCache, sda, layoutTarget, hvoTarget, layoutCache, caller, stringTbl, wsForce);
				}
				case "seq":
				{
					// Follow the property. For each object, look up the layout to use,
					// invoke recursively, concatenate
					int flid = GetFlid(sda, layout, hvo);
					int[] contents;
					int ctarget = sda.get_VecSize(hvo, flid);
					using (ArrayPtr arrayPtr = MarshalEx.ArrayToNative<int>(ctarget))
					{
						int chvo;
						sda.VecProp(hvo, flid, ctarget, out chvo, arrayPtr);
						contents = MarshalEx.NativeToArray<int>(arrayPtr, chvo);
					}

					string[] result = null;
					string targetLayoutName = XmlVc.GetLayoutName(layout, caller); // also allows for finding "param" attr in caller, if not null
					int i = 0;
					foreach (int hvoTarget in contents)
					{
						int prevResultLength = GetArrayLength(result);
						XmlNode layoutTarget = GetLayoutNodeForChild(sda, hvoTarget, flid, targetLayoutName, layout, layoutCache);
						if (layoutTarget == null)
							continue; // should not happen, but best recovery we can make
						result = Concatenate(result, ChildKeys(fdoCache, sda, layoutTarget, hvoTarget, layoutCache, caller, stringTbl, wsForce));
						// add a separator between the new childkey group and the previous childkey group
						if (i > 0 && prevResultLength != GetArrayLength(result) && prevResultLength > 0)
						{
							int ichIns = 0;
							if (result[prevResultLength - 1] != null)
								ichIns = result[prevResultLength - 1].Length;
							AddSeparator(ref result[prevResultLength - 1],  ichIns, layout);
						}
						++i;
					}

					return result;
				}
				case "choice":
				{
					foreach(XmlNode whereNode in layout.ChildNodes)
					{
						if (whereNode.Name != "where")
						{
							if (whereNode.Name == "otherwise")
								return StringsFor(fdoCache, sda, XmlUtils.GetFirstNonCommentChild(whereNode), hvo, layoutCache, caller, stringTbl, wsForce);
							continue; // ignore any other nodes,typically comments
						}
						// OK, it's a where node.
						if (XmlVc.ConditionPasses(whereNode, hvo, fdoCache, sda, caller))
							return StringsFor(fdoCache, sda, XmlUtils.GetFirstNonCommentChild(whereNode), hvo, layoutCache, caller, stringTbl, wsForce);
					}
					break; // if no condition passes and no otherwise, return null.
				}
				case "if":
				{
					if (XmlVc.ConditionPasses(layout, hvo, fdoCache, sda, caller))
						return StringsFor(fdoCache, sda, XmlUtils.GetFirstNonCommentChild(layout), hvo, layoutCache, caller, stringTbl, wsForce);
					break;
				}
				case "ifnot":
				{
					if (!XmlVc.ConditionPasses(layout, hvo, fdoCache, sda, caller))
						return StringsFor(fdoCache, sda, XmlUtils.GetFirstNonCommentChild(layout), hvo, layoutCache, caller, stringTbl, wsForce);
					break;
				}
				case "lit":
				{
					string literal = layout.InnerText;
					if (stringTbl != null)
					{
						string sTranslate = XmlUtils.GetOptionalAttributeValue(layout, "translate", "");
						if (sTranslate.Trim().ToLower() != "do not translate")
							literal = stringTbl.LocalizeLiteralValue(literal);
					}
					return new[] { literal };
				}
				case "int":
				{
					int flid = GetFlid(sda, layout, hvo);
					int val = sda.get_IntProp(hvo, flid);
					return new[] {AlphaCompNumberString(val)};
				}
				case "datetime":
				{
					int flid = GetFlid(sda, layout, hvo);
					CellarPropertyType itype = (CellarPropertyType)sda.MetaDataCache.GetFieldType(flid);
					if (itype == CellarPropertyType.Time)
					{
						DateTime dt = SilTime.GetTimeProperty(sda, hvo, flid);
						return new[] {DateTimeCompString(dt)};
					}
					else
					{
						string stFieldName = XmlUtils.GetManditoryAttributeValue(layout, "field");
						throw new Exception("Bad field type (" + stFieldName + " for hvo " + hvo + " found for " +
							layout.Name + "  property "	+ flid + " in " + layout.OuterXml);
					}
				}
				case "picture":
					// Treat a picture as a non-empty string for purposes of deciding whether something is empty.
					// This string seems as good as anything for other purposes.
					return new[] {"a picture"};
				default: // unknown or comment node, adds nothing
					Debug.Assert(false, "unrecognized XML node.");
					break;
			}
			return new string[0]; // don't know how to sort, treat as empty key.
		}
示例#3
0
		static private string[] AssembleChildKeys(FdoCache fdoCache, ISilDataAccess sda, XmlNode layout, int hvo,
			LayoutCache layoutCache, XmlNode caller, StringTable stringTbl, int wsForce)
		{
			return Assemble(ChildKeys(fdoCache, sda, layout, hvo, layoutCache, caller, stringTbl, wsForce));
		}
示例#4
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Returns an array of string values (keys) for the objects under the layout child nodes.
		/// </summary>
		/// ------------------------------------------------------------------------------------
		static internal string[] ChildKeys(FdoCache fdoCache, ISilDataAccess sda, XmlNode layout, int hvo,
			LayoutCache layoutCache, XmlNode caller, StringTable stringTbl, int wsForce)
		{
			string[] result = null;
			foreach (XmlNode child in layout.ChildNodes)
			{
				if (child is XmlComment)
					continue;
				result = Concatenate(result, StringsFor(fdoCache, sda, child, hvo, layoutCache, caller, stringTbl, wsForce));
			}
			return result;
		}
示例#5
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// The node argument is an "obj" or "seq" element, and caller (if not null) is a part
		/// element that invoked the node and may override its "layout" attribute.
		/// Apply the same logic used by XmlVc to determine the node that will be used
		/// to display the destination object hvoDst
		/// </summary>
		/// <param name="hvoDst">The hvo DST.</param>
		/// <param name="caller">The caller.</param>
		/// <param name="node">The node.</param>
		/// <param name="layouts">The layouts.</param>
		/// <param name="sda">The sda.</param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		static XmlNode GetNodeForRelatedObject(int hvoDst, XmlNode caller, XmlNode node,
			LayoutCache layouts, ISilDataAccess sda)
		{
			if (XmlUtils.GetOptionalAttributeValue(node, "frag") != null)
				return null; // old approach not handled.
			// (frag="true" is also used to prevent splitting entry when sorting on gloss or
			// allomorph in Find Entries dialog display.  Part of fixing LT-10293.)
			string layoutName = XmlVc.GetLayoutName(node, caller);
			XmlNode layoutNode = XmlVc.GetNodeForPart(hvoDst, layoutName, true, sda, layouts);
			return XmlVc.GetDisplayNodeForChild(layoutNode, node, layouts);
		}
示例#6
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Main (recursive) part of CollectBrowseItems. Given that hvo is to be displayed using node,
		/// figure what objects to put in the list.
		/// </summary>
		/// <param name="hvo">The hvo.</param>
		/// <param name="node">The node.</param>
		/// <param name="collector">The collector.</param>
		/// <param name="mdc">The MDC.</param>
		/// <param name="sda">The sda.</param>
		/// <param name="layouts">The layouts.</param>
		/// <param name="caller">The caller.</param>
		/// <param name="hvos">The hvos.</param>
		/// <param name="flids">The flids.</param>
		/// ------------------------------------------------------------------------------------
		static void CollectBrowseItems(int hvo, XmlNode node, ArrayList collector,
			IFwMetaDataCache mdc, ISilDataAccess sda, LayoutCache layouts, XmlNode caller, int[] hvos, int[] flids)
		{
			switch(node.Name)
			{
			case "obj":
			{
				int clsid = sda.get_IntProp(hvo, CmObjectTags.kflidClass);
				int flid = mdc.GetFieldId2(clsid, XmlUtils.GetManditoryAttributeValue(node, "field"), true);
				int hvoDst = sda.get_ObjectProp(hvo, flid);
				if (hvoDst == 0)
				{
					// We want a row, even though it's blank for this column.
					collector.Add(new ManyOnePathSortItem(hvo, hvos, flids));
					return;
				}
				// At this point we have to mimic the process that XmlVc uses to come up with the
				// node that will be used to process the destination item.
				XmlNode dstNode = GetNodeForRelatedObject(hvoDst, caller, node, layouts, sda);
				if (dstNode == null)
				{
					// maybe an old-style "frag" element? Anyway, we can't do anything smart,
					// so just insert the original object.
					collector.Add(new ManyOnePathSortItem(hvo, hvos, flids));
					return;
				}
				CollectBrowseItems(hvoDst, dstNode, collector, mdc, sda, layouts, null, AppendInt(hvos, hvo), AppendInt(flids, flid));
			}
				break;
			case "seq":
			{
				// very like "obj" except for the loop. How could we capture this?
				int clsid = sda.get_IntProp(hvo, CmObjectTags.kflidClass);
				int flid = mdc.GetFieldId2(clsid, XmlUtils.GetManditoryAttributeValue(node, "field"), true);
				int chvo = sda.get_VecSize(hvo, flid);
				if (chvo == 0)
				{
					// We want a row, even though it's blank for this column.
					collector.Add(new ManyOnePathSortItem(hvo, hvos, flids));
					return;
				}
				for (int ihvo = 0; ihvo < chvo; ihvo++)
				{
					int hvoDst = sda.get_VecItem(hvo, flid, ihvo);
					// At this point we have to mimic the process that XmlVc uses to come up with the
					// node that will be used to process the destination item.
					XmlNode dstNode = GetNodeForRelatedObject(hvoDst, caller, node, layouts, sda);
					if (dstNode == null)
					{
						if (ihvo == 0)
						{
							// maybe an old-style "frag" element? Anyway, we can't do anything smart,
							// so just insert the original object.
							collector.Add(new ManyOnePathSortItem(hvo, hvos, flids));
							return;
						}
						// if this happens and it's not the first object, we have a funny mixture of modes.
						// As a fall-back, skip this object.
						continue;
					}
					CollectBrowseItems(hvoDst, dstNode, collector, mdc, sda, layouts, null, AppendInt(hvos, hvo), AppendInt(flids, flid));
				}
			}
				break;
			case "span":
			case "para":
			case "div":
			case "concpara":
			case "innerpile":
			case "column":
				// Review JohnT: In XmlVc, "part" is the one thing that calls ProcessChildren with non-null caller.
				// this should make some difference here, but I can't figure what yet, or come up with a test that fails.
			case "part":
			case "layout":
				// These are grouping nodes. In general this terminates things. However, if there is only
				// one thing embedded apart from comments and properties, we can proceed.
				XmlNode mainChild = FindMainChild(node);
				if (mainChild == null)
				{
					// no single non-trivial child, keep our current object
					collector.Add(new ManyOnePathSortItem(hvo, hvos, flids));
					return;
				}
				// Recurse with same object, but process the 'main child'.
				CollectBrowseItems(hvo, mainChild, collector, mdc, sda, layouts, caller, hvos, flids);
				break;

			default:
				collector.Add(new ManyOnePathSortItem(hvo, hvos, flids));
				break;
			}
		}
示例#7
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Given one of the original list items, and the spec of the column we want to sort by,
		/// add to collector whatever ManyOnePathSortItems are appropriate.
		/// </summary>
		/// <param name="hvo">The hvo.</param>
		/// <param name="colSpec">The col spec.</param>
		/// <param name="collector">The collector.</param>
		/// <param name="mdc">The MDC.</param>
		/// <param name="sda">The sda.</param>
		/// <param name="layouts">The layouts.</param>
		/// ------------------------------------------------------------------------------------
		public static void CollectBrowseItems(int hvo, XmlNode colSpec, ArrayList collector,
			IFwMetaDataCache mdc, ISilDataAccess sda, LayoutCache layouts)
		{
			XmlNode topNode = XmlBrowseViewBaseVc.GetColumnNode(colSpec, hvo, sda, layouts);

			// Todo: handle various cases here, mostly drill-down to <seq> or <obj>
			CollectBrowseItems(hvo, topNode, collector, mdc, sda, layouts, null, null, null);
		}
示例#8
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// We want to display the object bvi.KeyObject, or one of its pathobjects, in a
		/// column specified by colSpec.
		/// Determine the hvo and XmlNode that we should use as the root for the cell.
		/// By default, we display the first object in the path, using the base node
		/// derived from the colSpec.
		/// However, if the colSpec begins with a path compatible with bvi.PathFlid(0),
		/// we can use bvi.PathObject(1) and the appropriate derived node.
		/// If all flids match we can use bvi.KeyObject itself.
		/// If collectOuterStructParts is non-null, it accumulates containing parts
		/// that are structural, like para, span, div.
		/// </summary>
		/// <param name="bvi">The bvi.</param>
		/// <param name="colSpec">The col spec.</param>
		/// <param name="mdc">The MDC.</param>
		/// <param name="sda">The sda.</param>
		/// <param name="layouts">The layouts.</param>
		/// <param name="hvo">The hvo.</param>
		/// <param name="collectOuterStructParts">The collect outer struct parts.</param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		public static XmlNode GetNodeToUseForColumn(IManyOnePathSortItem bvi, XmlNode colSpec,
			IFwMetaDataCache mdc, ISilDataAccess sda, LayoutCache layouts, out int hvo, List<XmlNode> collectOuterStructParts)
		{
			return GetDisplayCommandForColumn(bvi, colSpec, mdc, sda, layouts, out hvo, collectOuterStructParts).Node;
		}
示例#9
0
		/// <summary>
		/// This returns a NodeDisplayCommand containing thd node for GetNodeToUseForColumn. However, it distinguishes whether to
		/// display the children of this node or the node itself by returning the appropriate kind of NodeDisplayCommand.
		/// </summary>
		/// <param name="bvi"></param>
		/// <param name="colSpec"></param>
		/// <param name="mdc"></param>
		/// <param name="sda"></param>
		/// <param name="layouts"></param>
		/// <param name="hvo"></param>
		/// <param name="collectOuterStructParts"></param>
		/// <returns></returns>
		public static NodeDisplayCommand GetDisplayCommandForColumn(IManyOnePathSortItem bvi, XmlNode colSpec,
			IFwMetaDataCache mdc, ISilDataAccess sda, LayoutCache layouts, out int hvo, List<XmlNode> collectOuterStructParts)
		{
			XmlNode topNode = XmlBrowseViewBaseVc.GetColumnNode(colSpec, bvi.PathObject(0), sda, layouts);
			return GetDisplayCommandForColumn1(bvi, topNode, mdc, sda, layouts, 0, out hvo, collectOuterStructParts);
		}
示例#10
0
		public override void FixtureSetup()
		{
			base.FixtureSetup();

			SetupTestModel(Resources.TextCacheModel_xml);

			m_sda = new RealDataCache();
			m_sda.MetaDataCache = MetaDataCache.CreateMetaDataCache("TestModel.xml");
			//m_cache.ParaContentsFlid = kflidParaContents;
			//m_cache.ParaPropertiesFlid = kflidParaProperties;
			//m_cache.TextParagraphsFlid = kflidTextParas;

			Debug.Assert(m_wsManager == null);
			m_wsManager = Cache.ServiceLocator.GetInstance<IWritingSystemManager>();
			m_sda.WritingSystemFactory = m_wsManager;

			m_wsAnal = Cache.DefaultAnalWs;

			m_wsVern = Cache.DefaultVernWs;

			//IWritingSystem deWs;
			//m_wsManager.GetOrSet("de", out deWs);
			//m_wsDeu = deWs.Handle;

			//m_wsManager.UserWs = m_wsEng;
			//m_wsUser = m_wsManager.UserWs;

			m_tsf = TsStrFactoryClass.Create();

			m_hvoLexDb = m_sda.MakeNewObject(kclsidLexDb, 0, -1, -1);

			kflidLexDb_Entries = m_sda.MetaDataCache.GetFieldId("LexDb", "Entries", false);
			kflidEntry_Form = m_sda.MetaDataCache.GetFieldId("Entry", "Form", false);
			kflidEntry_Summary = m_sda.MetaDataCache.GetFieldId("Entry", "Summary", false);

			m_hvoKick = m_sda.MakeNewObject(kclsidEntry, m_hvoLexDb, kflidLexDb_Entries, 0);
			m_sda.SetMultiStringAlt(m_hvoKick, kflidEntry_Form, m_wsVern, m_tsf.MakeString("kick", m_wsVern));
			m_sda.SetString(m_hvoKick, kflidEntry_Summary, m_tsf.MakeString("strike with foot", m_wsAnal));

			var keyAttrs = new Dictionary<string, string[]>();
			keyAttrs["layout"] = new[] { "class", "type", "name", "choiceGuid" };
			keyAttrs["group"] = new[] { "label" };
			keyAttrs["part"] = new[] { "ref" };
			var layoutInventory = new Inventory("*.fwlayout", "/LayoutInventory/*", keyAttrs, "test", "nowhere");
			layoutInventory.LoadElements(Resources.Layouts_xml, 1);

			keyAttrs = new Dictionary<string, string[]>();
			keyAttrs["part"] = new[] { "id" };

			var partInventory = new Inventory("*Parts.xml", "/PartInventory/bin/*", keyAttrs, "test", "nowhere");
			partInventory.LoadElements(Resources.Parts_xml, 1);

			m_layouts = new LayoutCache(m_sda.MetaDataCache, layoutInventory, partInventory);
		}
示例#11
0
		static private XmlNode GetLayoutNodeForChild(ISilDataAccess sda, int hvoTarget, int flid, string targetLayoutName,
			XmlNode layout, LayoutCache layoutCache)
		{
			XmlNode layoutTarget = XmlVc.GetNodeForPart(hvoTarget, targetLayoutName, true, sda, layoutCache);
			if (layoutTarget == null)
				layoutTarget = layout; // no layout looked up, use whatever children caller has
			else if (layout.ChildNodes.Count != 0)
			{
				// got both a looked-up layout and child nodes overriding.
				if (layoutTarget.Name == "layout")
				{
					// thing we looked up is a layout, we will unify.
					layoutTarget = layoutCache.LayoutInventory.GetUnified(layoutTarget, layout);
				}
				else
				{
					// thing we looked up is a part, for now (see XmlVc.Display) we just replace
					// with supplied parts
					layoutTarget = layout;
				}
			}
			return layoutTarget;
		}
示例#12
0
		public void Setup()
		{
			// Create the following:
			// - part and layout inventories
			// - metadata cache
			// - DataAccess cache
			// - collection of columns to display.

			// We want a MetaDataCache that knows about
			// - LexEntry.Senses, Msas, CitationForm, Bibliography, Etymology
			// - LexSense.SemanticDomains, SenseType, Status, gloss
			// - CmPossibility Name, abbr
			// - MoMorphSynAnalysis
			// - MoStemMsa
			// - MoDerivationalMsa
			m_mdc = FwMetaDataCacheClass.Create();
			string m_sTestPath = Path.Combine(DirectoryFinder.FwSourceDirectory,
				@"Common\Controls\XmlViews\XmlViewsTests\SampleCm.xml");
			m_mdc.InitXml(m_sTestPath, true);

			// We want ISilDataAccess with:
			// - LexEntry (1) with no senses and one MSA (2)
			// - LexEntry (4) with one sense (5) and no MSA
			// - LexEntry (6) with three senses (7, 8, 9) and two MSAs (10, 11)
			// - sense(5) with no semantic domains
			// - senses with one SD (7->30, 8->31)
			// - sense with three SDs, one the same as the first (9->30, 31, 32)
			// - MoStemMsa (2, 11)
			// - MoDerivationalMsa (10)
			m_cda = VwCacheDaClass.Create();
			m_sda = m_cda as ISilDataAccess;
			m_wsf = LgWritingSystemFactoryClass.Create();
			m_sda.WritingSystemFactory = m_wsf;
			SimpleDataParser parser = new SimpleDataParser(m_mdc, m_cda);

			parser.Parse(Path.Combine(DirectoryFinder.FwSourceDirectory,
				@"Common\Controls\XmlViews\XmlViewsTests\SampleData.xml"));
			int wsEn = m_wsf.GetWsFromStr("en");
			// These are mainly to check out the parser.
			Assert.AreEqual(3, m_sda.get_ObjectProp(2, 23011), "part of speech of an MoStemMsa");
			Assert.AreEqual(2, m_sda.get_VecItem(1, 2009, 0), "owned msa");
			Assert.AreEqual("noun", m_sda.get_MultiStringAlt(3, 7003, wsEn).Text, "got ms property");
			Assert.AreEqual(9, m_sda.get_VecItem(6, 2010, 2), "3rd sense");
			Assert.AreEqual(31, m_sda.get_VecItem(9, 21016, 1), "2nd semantic domain");

			// Columns includes
			// - CitationForm (string inside span)
			// - Bibliography (string not in span)
			// - Sense glosses (string in para in seq, nested in column element)
			// - Semantic domains (pair of strings in para in seq in seq, using layout refs)
			// - MSAs (simplified, but polymorphic with one having <choice> and one <obj> to CmPossibility
			XmlDocument docColumns = new XmlDocument();
			docColumns.Load(Path.Combine(DirectoryFinder.FwSourceDirectory,
				@"Common\Controls\XmlViews\XmlViewsTests\TestColumns.xml"));
			m_columnList = docColumns.DocumentElement.ChildNodes;

			// Parts just has what those columns need.
			string partDirectory = Path.Combine(DirectoryFinder.FwSourceDirectory,
				@"Common\Controls\XmlViews\XmlViewsTests");
			Dictionary<string, string[]> keyAttrs = new Dictionary<string, string[]>();
			keyAttrs["layout"] = new string[] {"class", "type", "name" };
			keyAttrs["group"] = new string[] {"label"};
			keyAttrs["part"] = new string[] {"ref"};


			// Currently there are no specialized layout files that match.
			m_layoutInventory = new Inventory(new string[] {partDirectory},
				"*Layouts.xml", "/LayoutInventory/*", keyAttrs);

			keyAttrs = new Dictionary<string, string[]>();
			keyAttrs["part"] = new string[] {"id"};

			m_partInventory = new Inventory(new string[] {partDirectory},
				"TestParts.xml", "/PartInventory/bin/*", keyAttrs);
			if (m_layouts != null)
				m_layouts.Dispose();
			m_layouts = new LayoutCache(m_mdc, m_layoutInventory, m_partInventory);
		}
示例#13
0
		public void Teardown()
		{
			if (m_wsf != null && Marshal.IsComObject(m_wsf))
			{
				m_wsf.Shutdown();
				Marshal.ReleaseComObject(m_wsf);
			}
			m_wsf = null;

			if (Marshal.IsComObject(m_cda))
			{
				Marshal.ReleaseComObject(m_cda);
			}
			m_cda = null;

			if (Marshal.IsComObject(m_mdc))
			{
				Marshal.ReleaseComObject(m_mdc);
			}
			m_mdc = null;

			if (Marshal.IsComObject(m_sda))
			{
				Marshal.ReleaseComObject(m_sda);
			}
			m_sda = null;

			m_layoutInventory = null;
			m_columnList = null;
			m_layouts = null;
			m_partInventory = null;
		}
示例#14
0
		/// <summary>
		/// Given the "column" element that describes a column of a browse view,
		/// come up with the XmlNode whose children will be the actual parts (or part refs)
		/// to use to display the contents.
		/// </summary>
		/// <param name="column"></param>
		/// <param name="hvo"></param>
		/// <param name="sda"></param>
		/// <param name="layouts"></param>
		/// <returns></returns>
		public static XmlNode GetColumnNode(XmlNode column, int hvo, ISilDataAccess sda, LayoutCache layouts)
		{
			XmlNode nodeToProcess = column;
			string layoutName = XmlUtils.GetOptionalAttributeValue(column, "layout");
			if (layoutName != null)
			{
				// new approach: display the object using the specified layout.
				XmlNode nodeInner = GetNodeForPart(hvo, layoutName, true, sda,
					layouts);
				if (nodeInner != null)
					nodeToProcess = nodeInner;
			}
			return nodeToProcess;
		}
示例#15
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Process a fragment's children against multiple writing systems.
		/// </summary>
		/// ------------------------------------------------------------------------------------
		static private string[] ProcessMultiLingualChildren(FdoCache fdoCache, ISilDataAccess sda, XmlNode frag, int hvo,
			LayoutCache layoutCache, XmlNode caller, StringTable stringTbl, int wsForce)
		{
			string sWs = XmlUtils.GetOptionalAttributeValue(frag, "ws");
			if (sWs == null)
				return null;

			Debug.Assert(s_qwsCurrent == null);
			Debug.Assert(s_cwsMulti == 0);
			string[] result = null;
			try
			{
				HashSet<int> wsIds = WritingSystemServices.GetAllWritingSystems(fdoCache, frag, s_qwsCurrent, 0, 0);
				s_cwsMulti = wsIds.Count;
				if (s_cwsMulti > 1)
					s_sMultiSep = XmlUtils.GetOptionalAttributeValue(frag, "sep");
				s_fMultiFirst = true;
				foreach (int WSId in wsIds)
				{
					s_qwsCurrent = fdoCache.ServiceLocator.WritingSystemManager.Get(WSId);
					result = Concatenate(result, ChildKeys(fdoCache, sda, frag, hvo, layoutCache, caller, stringTbl, wsForce));
				}
			}
			finally
			{
				// Make sure these are reset, no matter what.
				s_qwsCurrent = null;
				s_cwsMulti = 0;
				s_sMultiSep = null;
				s_fMultiFirst = false;
			}
			return result;
		}
示例#16
0
		/// <summary>
		/// Recursive implementation method for GetDisplayCommandForColumn.
		/// </summary>
		/// <param name="bvi"></param>
		/// <param name="node"></param>
		/// <param name="mdc"></param>
		/// <param name="sda"></param>
		/// <param name="layouts"></param>
		/// <param name="depth"></param>
		/// <param name="hvo"></param>
		/// <param name="collectOuterStructParts"></param>
		/// <returns></returns>
		static NodeDisplayCommand GetDisplayCommandForColumn1(IManyOnePathSortItem bvi, XmlNode node,
			IFwMetaDataCache mdc, ISilDataAccess sda, LayoutCache layouts, int depth,
			out int hvo, List<XmlNode> collectOuterStructParts)
		{
			hvo = bvi.PathObject(depth); // default
			switch(node.Name)
			{
			case "obj":
			case "seq":
			{
				// These two cases are the same here, because if the field matches, the object
				// that determines the next step comes from the bvi, not from one or many items
				// in the property.

				if (bvi.PathLength == depth)
				{
					// No more path, we display the final object using the node we've deduced is
					// appropriate for it.
					// (We could put this test outside the switch. But then we don't dig into
					// layout, para, span, etc elements at the end of the chain. It's more
					// consistent if we always dig as deep as we can.
					hvo = bvi.KeyObject;
					return new NodeDisplayCommand(node);
				}

				int clsid = sda.get_IntProp(bvi.PathObject(depth), CmObjectTags.kflidClass);
				int flid = mdc.GetFieldId2(clsid, XmlUtils.GetManditoryAttributeValue(node, "field"), true);
				if (flid != bvi.PathFlid(depth))
					return new NodeDisplayCommand(node); // different field, can't dig deeper.
				int hvoDst = bvi.PathObject(depth + 1);
				// If the path object has been deleted, fall back to displaying whatever the property currently holds.
				if (sda.get_IntProp(hvoDst, CmObjectTags.kflidClass) == 0)
					return new NodeDisplayCommand(node); // different field, can't dig deeper.
				// At this point we have to mimic the process that XmlVc uses to come up with the
				// node that will be used to process the destination item.
				XmlNode dstNode = GetNodeForRelatedObject(hvoDst, null, node, layouts, sda);
				return GetDisplayCommandForColumn1(bvi, dstNode, mdc, sda, layouts, depth + 1, out hvo, collectOuterStructParts);
			}
			case "para":
			case "span":
			case "div":
			case "concpara":
			case "innerpile":
			{
				XmlNode mainChild = FindMainChild(node);
				if (mainChild == null)
					return new NodeDisplayCommand(node); // can't usefully go further.
				if (collectOuterStructParts != null)
					collectOuterStructParts.Add(node);
				return GetDisplayCommandForColumn1(bvi, mainChild, mdc, sda, layouts, depth, out hvo, collectOuterStructParts);
			}
				// Review JohnT: In XmlVc, "part" is the one thing that calls ProcessChildren with non-null caller.
				// this should make some difference here, but I can't figure what yet, or come up with a test that fails.
				// We may need a "caller" argument to pass this down so it can be used in GetNodeForRelatedObject.
			case "part":
			{
				string layoutName = XmlUtils.GetOptionalAttributeValue(node, "ref");
				if (layoutName != null)
				{
					// It's actually a part ref, in a layout, not a part looked up by one!
					// Get the node it refers to, and make a command to process its children.
					XmlNode part = XmlVc.GetNodeForPart(hvo, layoutName, false, sda, layouts);
					if (part != null)
						return new NodeChildrenDisplayCommand(part); // display this object using the children of the part referenced.
					else
						return new NodeDisplayCommand(node); // no matching part, do default.
				}

				// These are almost the same, but are never added to collectOuterStructParts.
				// Also, expecially in the case of 'layout', they may result from unification, and be meaningless
				// except for their children; in any case, the children are all we want to process.
				// This is the main reason we return a command, not just a node: this case has to return the subclass.
				XmlNode mainChild = FindMainChild(node);
				if (mainChild == null)
					return new NodeChildrenDisplayCommand(node); // can't usefully go further.
				return GetDisplayCommandForColumn1(bvi, mainChild, mdc, sda, layouts, depth, out hvo, collectOuterStructParts);
			}
			case "column":
			case "layout":
			{

				// These are almost the same as para, span, etc, but are never added to collectOuterStructParts.
				// Also, expecially in the case of 'layout', they may result from unification, and be meaningless
				// except for their children; in any case, the children are all we want to process.
				// This is the main reason we return a command, not just a node: this case has to return the subclass.
				XmlNode mainChild = FindMainChild(node);
				if (mainChild == null)
					return new NodeChildrenDisplayCommand(node); // can't usefully go further.
				return GetDisplayCommandForColumn1(bvi, mainChild, mdc, sda, layouts, depth, out hvo, collectOuterStructParts);
			}
			default:
				// If we can't find anything clever to do, we display the object at the
				// current level using the current node.
				return new NodeDisplayCommand(node);
			}
		}
示例#17
0
		/// <summary>
		/// Executes in two distinct scenarios.
		///
		/// 1. If disposing is true, the method has been called directly
		/// or indirectly by a user's code via the Dispose method.
		/// Both managed and unmanaged resources can be disposed.
		///
		/// 2. If disposing is false, the method has been called by the
		/// runtime from inside the finalizer and you should not reference (access)
		/// other managed objects, as they already have been garbage collected.
		/// Only unmanaged resources can be disposed.
		/// </summary>
		/// <param name="disposing"></param>
		/// <remarks>
		/// If any exceptions are thrown, that is fine.
		/// If the method is being done in a finalizer, it will be ignored.
		/// If it is thrown by client code calling Dispose,
		/// it needs to be handled by fixing the bug.
		///
		/// If subclasses override this method, they should call the base implementation.
		/// </remarks>
		protected virtual void Dispose(bool disposing)
		{
			//Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************");
			// Must not be run more than once.
			if (m_isDisposed)
				return;

			if (disposing)
			{
				// Dispose managed resources here.
				// does not belong to us!
//				if (m_layouts != null)
//					m_layouts.Dispose();
			}

			// Dispose unmanaged resources here, whether disposing is true or false.
			m_sda = null;
			m_layoutName = null;
			m_mdc = null;
			m_cache = null;
			m_layouts = null;
			m_colSpec = null;

			m_isDisposed = true;
		}
示例#18
0
		public void Teardown()
		{
			if (Marshal.IsComObject(m_cda))
			{
				Marshal.ReleaseComObject(m_cda);
			}
			m_cda = null;

			if (Marshal.IsComObject(m_mdc))
			{
				Marshal.ReleaseComObject(m_mdc);
			}
			m_mdc = null;

			if (Marshal.IsComObject(m_sda))
			{
				Marshal.ReleaseComObject(m_sda);
			}
			m_sda = null;

			m_layoutInventory = null;
			m_columnList = null;
			m_layouts = null;
			m_partInventory = null;
			m_wsManager = null;
		}