Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 94 additions & 31 deletions Src/xWorks/ConfiguredLcmGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,22 @@ internal static string GetWsForEntryType(ICmObject entry, LcmCache cache)
return wsString;
}

/// <summary>
/// Get the ConfigurableDictionaryNode for the main entry.
/// </summary>
private static ConfigurableDictionaryNode MainEntryNode(DictionaryConfigurationModel configuration)
{
return configuration.Parts[0];
}

/// <summary>
/// Get the ConfigurableDictionaryNode for the minor entry.
/// </summary>
private static ConfigurableDictionaryNode MinorEntryNode(ICmObject entry, DictionaryConfigurationModel configuration)
{
return configuration.Parts.Skip(1).LastOrDefault(part => IsListItemSelectedForExport(part, entry));
}

/// <summary>
/// Generating the xhtml representation for the given ICmObject using the given configuration node to select which data to write out
/// If it is a Dictionary Main Entry or non-Dictionary entry, uses the first configuration node.
Expand All @@ -259,7 +275,7 @@ public static IFragment GenerateContentForEntry(ICmObject entryObj, DictionaryCo
DictionaryPublicationDecorator publicationDecorator, GeneratorSettings settings, int index = -1)
{
if (IsMainEntry(entryObj, configuration))
return GenerateContentForMainEntry(entryObj, configuration.Parts[0], publicationDecorator, settings, index);
return GenerateContentForMainEntry(entryObj, MainEntryNode(configuration), publicationDecorator, settings, index);

var entry = (ILexEntry)entryObj;
return entry.PublishAsMinorEntry
Expand All @@ -279,7 +295,7 @@ private static IFragment GenerateContentForMinorEntry(ICmObject entry, Dictionar
DictionaryPublicationDecorator publicationDecorator, GeneratorSettings settings, int index)
{
// LT-15232: show minor entries using only the last applicable Minor Entry node (not more than once)
var applicablePart = configuration.Parts.Skip(1).LastOrDefault(part => IsListItemSelectedForExport(part, entry));
var applicablePart = MinorEntryNode(entry, configuration);
return applicablePart == null ? settings.ContentGenerator.CreateFragment() : GenerateContentForEntry(entry, applicablePart, publicationDecorator, settings, index);
}

Expand All @@ -300,6 +316,61 @@ internal static bool IsMainEntry(ICmObject entry, DictionaryConfigurationModel c
return lexEntry.EntryRefsOS.Any(ler => ler.RefType == LexEntryRefTags.krtComplexForm);
}

/// <summary>
/// Checks if a lexical entry is displayed.
/// </summary>
/// <returns>true if displayed.</returns>
private static bool EntryIsDisplayed(ILexEntry lexEntry, List<ConfigurableDictionaryNode> nodeList,
DictionaryPublicationDecorator publicationDecorator, GeneratorSettings settings)
{
// If there is no publication decorator then we are generating a preview. For previews always
// treat a target as displayed.
if (publicationDecorator == null)
{
return true;
}

bool displayed = false;
DictionaryConfigurationModel configModel = nodeList.First().Model;
bool mainEntry = IsMainEntry(lexEntry, configModel);

// First determine if the dictionary configuration is set to display the entry type.
if (mainEntry)
{
displayed = MainEntryNode(configModel).IsEnabled;
}
else
{
var node = MinorEntryNode(lexEntry, configModel);
displayed = node != null && node.IsEnabled;
}

// Second check if we are publishing minor entries.
if (displayed && !mainEntry && !lexEntry.PublishAsMinorEntry)
{
displayed = false;
}

// Third check if the active Publication excludes it.
var currentPubPoss = publicationDecorator.Publication;
if (displayed && currentPubPoss != null &&
currentPubPoss.NameHierarchyString != xWorksStrings.AllEntriesPublication)
{
if (!lexEntry.PublishIn.Contains(currentPubPoss))
{
displayed = false;
}
// Note: A better name for ShowMainEntryIn() would probably be
// ShowAsHeadwordIn(), since it applies to both main and minor entries.
if (!lexEntry.ShowMainEntryIn.Contains(currentPubPoss))
{
displayed = false;
}
}

return displayed;
}

/// <summary>Generates content with the GeneratorSettings.ContentGenerator for an ICmObject for a specific ConfigurableDictionaryNode</summary>
/// <remarks>the configuration node must match the entry type</remarks>
internal static IFragment GenerateContentForEntry(ICmObject entry, ConfigurableDictionaryNode configuration,
Expand Down Expand Up @@ -585,7 +656,7 @@ internal static IFragment GenerateContentForFieldByReflection(object field, List
return settings.ContentGenerator.CreateFragment();
}

var bldr = GenerateContentForValue(field, propertyValue, nodeList, settings);
var bldr = GenerateContentForValue(field, propertyValue, nodeList, publicationDecorator, settings);
if (config.ReferencedOrDirectChildren != null)
{
foreach (var child in config.ReferencedOrDirectChildren)
Expand Down Expand Up @@ -2549,48 +2620,40 @@ private static bool IsCollectionEmpty(object collection)
/// <param name="config"></param>
/// <param name="settings"></param>
private static IFragment GenerateContentForValue(object field, object propertyValue, List<ConfigurableDictionaryNode> nodeList,
GeneratorSettings settings)
DictionaryPublicationDecorator publicationDecorator, GeneratorSettings settings)
{
// If we're working with a headword, either for this entry or another one (Variant or Complex Form, etc.), store that entry's GUID
// so we can generate a link to the main or minor entry for this headword.
var guid = Guid.Empty;
var config = nodeList.Last();
if (config.IsHeadWord)
{
if (field is ILexEntry)
ILexEntry lexEntry = null;
if (field is ILexEntry entry)
{
// For Complex Forms, don't generate the reference if we are not going to publish the entry to Webonary.
if (settings.IsWebExport &&
!((ILexEntry)field).PublishAsMinorEntry &&
((ILexEntry)field).EntryRefsOS.Count > 0)
{
guid = Guid.Empty;
}
else
{
guid = ((ILexEntry)field).Guid;
}
lexEntry = entry;
}
else if (field is ILexEntryRef)
else if (field is ILexEntryRef entryRef)
{
// For Variants, don't generate the reference if we are not going to publish the entry to Webonary.
if (settings.IsWebExport &&
!((ILexEntryRef)field).OwningEntry.PublishAsMinorEntry)
{
guid = Guid.Empty;
}
else
{
guid = ((ILexEntryRef)field).OwningEntry.Guid;
}
lexEntry = entryRef.OwningEntry;
}
else if (field is ISenseOrEntry senseOrEntry)
{
lexEntry = senseOrEntry.Item is ILexEntry ? (ILexEntry)(senseOrEntry.Item) : ((ILexSense)(senseOrEntry.Item)).Entry;
}
else if (field is ILexSense sense)
{
lexEntry = sense.OwnerOfClass(LexEntryTags.kClassId) as ILexEntry;
}
else if (field is ISenseOrEntry)
guid = ((ISenseOrEntry)field).EntryGuid;
else if (field is ILexSense)
guid = ((ILexSense)field).OwnerOfClass(LexEntryTags.kClassId).Guid;
else
Debug.WriteLine(String.Format("Need to find Entry Guid for {0}",
field == null ? DictionaryConfigurationMigrator.BuildPathStringFromNode(config) : field.GetType().Name));

// Check if the Lexical Entry is going to be displayed.
if (lexEntry != null && EntryIsDisplayed(lexEntry, nodeList, publicationDecorator, settings))
{
guid = lexEntry.Guid;
}
}

if (propertyValue is ITsString)
Expand Down
24 changes: 16 additions & 8 deletions Src/xWorks/xWorksTests/ConfiguredXHTMLGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7418,19 +7418,23 @@ public void GenerateContentForEntry_ComplexFormDontGenerateReference()
};
CssGeneratorTests.PopulateFieldsForTesting(mainEntryNode);

mainEntryNode.Model.IsRootBased = true;
subentryRef.HideMinorEntry = 1;
const string withReference = "/div[@class='lexentry']/span[@class='subentries']/span[@class='subentry']/span[@class='headword']/span[@lang='fr']/span[@lang='fr']/a[@href]";
const string withoutReference = "/div[@class='lexentry']/span[@class='subentries']/span[@class='subentry']/span[@class='headword']/span[@lang='fr']/span[@lang='fr']";

// When hiding minor entries this should still generate the reference (if not publishing to Webonary).
// When hiding minor entries and NOT publishing to Webonary this should NOT generate the reference.
var settings = new ConfiguredLcmGenerator.GeneratorSettings(Cache, m_propertyTable, false, false, null, false, false);
var result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, mainEntryNode, null, settings).ToString();
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 2);
var flidVirtual = Cache.ServiceLocator.GetInstance<Virtuals>().LexDbEntries;
var pubEverything = new DictionaryPublicationDecorator(Cache, (ISilDataAccessManaged)Cache.MainCacheAccessor, flidVirtual);
var result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, mainEntryNode, pubEverything, settings).ToString();
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 0);
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withoutReference, 2);

//SUT
// When hiding minor entries and publishing to Webonary this should NOT generate the reference.
settings = new ConfiguredLcmGenerator.GeneratorSettings(Cache, m_propertyTable, false, false, null, false, true);
result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, mainEntryNode, null, settings).ToString();
result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, mainEntryNode, pubEverything, settings).ToString();
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 0);
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withoutReference, 2);
}
Expand Down Expand Up @@ -7687,19 +7691,23 @@ public void GenerateContentForEntry_VariantDontGenerateReference()
};
CssGeneratorTests.PopulateFieldsForTesting(model);

mainEntryNode.Model.IsRootBased = true;
variantEntryRef.HideMinorEntry = 1;
const string withReference = "/div[@class='lexentry']/span[@class='variantformentrybackrefs']/span[@class='variantformentrybackref']/span[@class='headword']/span[@lang='fr']/span[@lang='fr']/a[@href]";
const string withoutReference = "/div[@class='lexentry']/span[@class='variantformentrybackrefs']/span[@class='variantformentrybackref']/span[@class='headword']/span[@lang='fr']/span[@lang='fr']";

// When hiding minor entries this should still generate the reference (if not publishing to Webonary).
// When hiding minor entries and NOT publishing to Webonary this should NOT generate the reference.
var settings = new ConfiguredLcmGenerator.GeneratorSettings(Cache, m_propertyTable, false, false, null, false, false);
var result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, model, null, settings).ToString();
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 2);
var flidVirtual = Cache.ServiceLocator.GetInstance<Virtuals>().LexDbEntries;
var pubEverything = new DictionaryPublicationDecorator(Cache, (ISilDataAccessManaged)Cache.MainCacheAccessor, flidVirtual);
var result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, model, pubEverything, settings).ToString();
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 0);
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withoutReference, 2);

//SUT
// When hiding minor entries and publishing to Webonary this should NOT generate the reference.
settings = new ConfiguredLcmGenerator.GeneratorSettings(Cache, m_propertyTable, false, false, null, false, true);
result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, model, null, settings).ToString();
result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, model, pubEverything, settings).ToString();
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 0);
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withoutReference, 2);
}
Expand Down
24 changes: 22 additions & 2 deletions Src/xWorks/xWorksTests/LcmJsonGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,17 @@ public void GenerateJsonForEntry_FilterByPublication()
Children = new List<ConfigurableDictionaryNode> { mainHeadwordNode, mainPronunciationsNode, sensesNode, pictureNode, subentryNode, variantNode },
FieldDescription = "LexEntry"
};
CssGeneratorTests.PopulateFieldsForTesting(mainEntryNode);
var minorEntryNode = new ConfigurableDictionaryNode
{
FieldDescription = "LexEntry",
CSSClassNameOverride = "minorentry",
DictionaryNodeOptions = ConfiguredXHTMLGeneratorTests.GetFullyEnabledListOptions(DictionaryNodeListOptions.ListIds.Variant, Cache)
};
var model = new DictionaryConfigurationModel
{
Parts = new List<ConfigurableDictionaryNode> { mainEntryNode, minorEntryNode }
};
CssGeneratorTests.PopulateFieldsForTesting(model);

//SUT
var output = ConfiguredLcmGenerator.GenerateContentForEntry(entryEntry, mainEntryNode, pubMain, DefaultSettings, 0).ToString();
Expand Down Expand Up @@ -577,7 +587,17 @@ public void GenerateJsonForEntry_TypeAfterForm()
Children = new List<ConfigurableDictionaryNode> { mainHeadwordNode, variantNodeTypeAfter },
FieldDescription = "LexEntry"
};
CssGeneratorTests.PopulateFieldsForTesting(mainEntryNodeTypeAfter);
var minorEntryNode = new ConfigurableDictionaryNode
{
FieldDescription = "LexEntry",
CSSClassNameOverride = "minorentry",
DictionaryNodeOptions = ConfiguredXHTMLGeneratorTests.GetFullyEnabledListOptions(DictionaryNodeListOptions.ListIds.Variant, Cache)
};
var model = new DictionaryConfigurationModel
{
Parts = new List<ConfigurableDictionaryNode> { mainEntryNodeTypeAfter, minorEntryNode }
};
CssGeneratorTests.PopulateFieldsForTesting(model);

//SUT
var outputTypeAfter = ConfiguredLcmGenerator.GenerateContentForEntry(entryEntry, mainEntryNodeTypeAfter, pubMain, DefaultSettings, 0).ToString();
Expand Down
Loading