private static void StoreChildNodeInfo(XmlNode xn, string className, XmlDocConfigureDlg.LayoutTreeNode ltn, ILayoutConverter converter) { string sField = XmlUtils.GetMandatoryAttributeValue(xn, "field"); XmlNode xnCaller = converter.LayoutLevels.PartRef; if (xnCaller == null) { xnCaller = ltn.Configuration; } bool hideConfig = xnCaller == null ? false : XmlUtils.GetOptionalBooleanAttributeValue(xnCaller, "hideConfig", false); // Insert any special configuration appropriate for this property...unless the caller is hidden, in which case, // we don't want to configure it at all. if (!ltn.IsTopLevel && !hideConfig) { if (sField == "Senses" && (ltn.ClassName == "LexEntry" || ltn.ClassName == "LexSense")) { ltn.ShowSenseConfig = true; } else if (sField == "ReferringSenses" && ltn.ClassName == "ReversalIndexEntry") { ltn.ShowSenseConfig = true; } if (sField == "MorphoSyntaxAnalysis" && ltn.ClassName == "LexSense") { ltn.ShowGramInfoConfig = true; } if (sField == "VisibleComplexFormBackRefs" || sField == "ComplexFormsNotSubentries") { //The existence of the attribute is important for this setting, not its value! var sShowAsIndentedPara = XmlUtils.GetAttributeValue(ltn.Configuration, "showasindentedpara"); ltn.ShowComplexFormParaConfig = !String.IsNullOrEmpty(sShowAsIndentedPara); } } bool fRecurse = XmlUtils.GetOptionalBooleanAttributeValue(ltn.Configuration, "recurseConfig", true); if (!fRecurse) { // We don't want to recurse forever just because senses have subsenses, which // can have subsenses, which can ... // Or because entries have subentries (in root type layouts)... ltn.UseParentConfig = true; return; } var sLayout = XmlVc.GetLayoutName(xn, xnCaller); var clidDst = 0; string sClass = null; string sTargetClasses = null; try { // Failure should be fairly unusual, but, for example, part MoForm-Jt-FormEnvPub attempts to display // the property PhoneEnv inside an if that checks that the MoForm is one of the subclasses that has // the PhoneEnv property. MoForm itself does not. if (!((IFwMetaDataCacheManaged)converter.Cache.DomainDataByFlid.MetaDataCache).FieldExists(className, sField, true)) { return; } var flid = converter.Cache.DomainDataByFlid.MetaDataCache.GetFieldId(className, sField, true); var type = (CellarPropertyType)converter.Cache.DomainDataByFlid.MetaDataCache.GetFieldType(flid); Debug.Assert(type >= CellarPropertyType.MinObj); if (type >= CellarPropertyType.MinObj) { var mdc = converter.Cache.MetaDataCacheAccessor; sTargetClasses = XmlUtils.GetOptionalAttributeValue(xn, "targetclasses"); clidDst = mdc.GetDstClsId(flid); if (clidDst == 0) { sClass = XmlUtils.GetOptionalAttributeValue(xn, "targetclass"); } else { sClass = mdc.GetClassName(clidDst); } if (clidDst == StParaTags.kClassId) { string sClassT = XmlUtils.GetOptionalAttributeValue(xn, "targetclass"); if (!String.IsNullOrEmpty(sClassT)) { sClass = sClassT; } } } } catch { return; } if (clidDst == MoFormTags.kClassId && !sLayout.StartsWith("publi")) { return; // ignore the layouts used by the LexEntry-Jt-Headword part. } if (String.IsNullOrEmpty(sLayout) || String.IsNullOrEmpty(sClass)) { return; } if (sTargetClasses == null) { sTargetClasses = sClass; } string[] rgsClasses = sTargetClasses.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); XmlNode subLayout = null; if (rgsClasses.Length > 0) { subLayout = converter.GetLayoutElement(rgsClasses[0], sLayout); } if (subLayout != null) { int iStart = ltn.Nodes.Count; int cNodes = subLayout.ChildNodes.Count; AddChildNodes(subLayout, ltn, iStart, converter); bool fRepeatedConfig = XmlUtils.GetOptionalBooleanAttributeValue(xn, "repeatedConfig", false); if (fRepeatedConfig) { return; // repeats an earlier part element (probably as a result of <if>s) } for (int i = 1; i < rgsClasses.Length; i++) { XmlNode mergedLayout = converter.GetLayoutElement(rgsClasses[i], sLayout); if (mergedLayout != null && mergedLayout.ChildNodes.Count == cNodes) { AddChildNodes(mergedLayout, ltn, iStart, converter); } } } else { // The "layout" in a part node can actually refer directly to another part, so check // for that possibility. var subPart = converter.GetPartElement(rgsClasses[0], sLayout) ?? converter.GetPartElement(className, sLayout); if (subPart == null && !sLayout.EndsWith("-en")) { // Complain if we can't find either a layout or a part, and the name isn't tagged // for a writing system. (We check only for English, being lazy.) var msg = String.Format("Missing jtview layout for class=\"{0}\" name=\"{1}\"", rgsClasses[0], sLayout); converter.LogConversionError(msg); } } }
internal static void AddChildNodes(XmlNode layout, XmlDocConfigureDlg.LayoutTreeNode ltnParent, int iStart, ILayoutConverter converter) { bool fMerging = iStart < ltnParent.Nodes.Count; string className = XmlUtils.GetMandatoryAttributeValue(layout, "class"); List <XmlNode> nodes = PartGenerator.GetGeneratedChildren(layout, converter.Cache, new[] { "ref", "label" }); foreach (XmlNode node in nodes) { XmlNode subLayout; if (node.Name == "sublayout") { Debug.Assert(!fMerging); string subLayoutName = XmlUtils.GetOptionalAttributeValue(node, "name", null); if (subLayoutName == null) { subLayout = node; // a sublayout lacking a name contains the part refs directly. } else { subLayout = converter.GetLayoutElement(className, subLayoutName); } if (subLayout != null) { AddChildNodes(subLayout, ltnParent, ltnParent.Nodes.Count, converter); } } else if (node.Name == "part") { // Check whether this node has already been added to this parent. Don't add // it if it's already there! XmlDocConfigureDlg.LayoutTreeNode ltnOld = FindMatchingNode(ltnParent, node); if (ltnOld != null) { continue; } string sRef = XmlUtils.GetMandatoryAttributeValue(node, "ref"); XmlNode part = converter.GetPartElement(className, sRef); if (part == null && sRef != "$child") { continue; } bool fHide = XmlUtils.GetOptionalBooleanAttributeValue(node, "hideConfig", false); XmlDocConfigureDlg.LayoutTreeNode ltn; var cOrig = 0; if (!fHide) { ltn = new XmlDocConfigureDlg.LayoutTreeNode(node, converter, className) { OriginalIndex = ltnParent.Nodes.Count, ParentLayout = layout, HiddenNode = converter.LayoutLevels.HiddenPartRef, HiddenNodeLayout = converter.LayoutLevels.HiddenLayout }; if (!String.IsNullOrEmpty(ltn.LexRelType)) { converter.BuildRelationTypeList(ltn); } if (!String.IsNullOrEmpty(ltn.EntryType)) { converter.BuildEntryTypeList(ltn, ltnParent.LayoutName); } //if (fMerging) //((LayoutTreeNode)ltnParent.Nodes[iNode]).MergedNodes.Add(ltn); //else ltnParent.Nodes.Add(ltn); } else { Debug.Assert(!fMerging); ltn = ltnParent; cOrig = ltn.Nodes.Count; if (className == "StTxtPara") { ltnParent.HiddenChildLayout = layout; ltnParent.HiddenChild = node; } } try { converter.LayoutLevels.Push(node, layout); var fOldAdding = ltn.AddingSubnodes; ltn.AddingSubnodes = true; if (part != null) { ProcessChildNodes(part.ChildNodes, className, ltn, converter); } ltn.OriginalNumberOfSubnodes = ltn.Nodes.Count; ltn.AddingSubnodes = fOldAdding; if (fHide) { var cNew = ltn.Nodes.Count - cOrig; if (cNew > 1) { var msg = String.Format("{0} nodes for a hidden PartRef ({1})!", cNew, node.OuterXml); converter.LogConversionError(msg); } } } finally { converter.LayoutLevels.Pop(); } } } }