mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
GP-155 - Help - fixed intermittent build failure due to different nodes
with shared 'text' attribute values
This commit is contained in:
parent
798c3abf42
commit
68ef3a22c5
4 changed files with 252 additions and 145 deletions
|
@ -68,7 +68,6 @@
|
||||||
text="Program Annotations Affecting the Decompiler"
|
text="Program Annotations Affecting the Decompiler"
|
||||||
target="help/topics/DecompilePlugin/DecompilerAnnotations.html">
|
target="help/topics/DecompilePlugin/DecompilerAnnotations.html">
|
||||||
<tocdef id="AnnoteFunctionBody" sortgroup="a" text="Machine Instructions" target="help/topics/DecompilePlugin/DecompilerAnnotations.html#AnnoteFunctionBody"/>
|
<tocdef id="AnnoteFunctionBody" sortgroup="a" text="Machine Instructions" target="help/topics/DecompilePlugin/DecompilerAnnotations.html#AnnoteFunctionBody"/>
|
||||||
<!-- Space added to text="Comments" attribute below to distinguish it from the CommentsPlugin section of the same name -->
|
|
||||||
<tocdef id="AnnoteComments" sortgroup="b" text="Comments" target="help/topics/DecompilePlugin/DecompilerAnnotations.html#AnnoteComments"/>
|
<tocdef id="AnnoteComments" sortgroup="b" text="Comments" target="help/topics/DecompilePlugin/DecompilerAnnotations.html#AnnoteComments"/>
|
||||||
<tocdef id="AnnoteVariables" sortgroup="c" text="Variable Annotations" target="help/topics/DecompilePlugin/DecompilerAnnotations.html#AnnoteVariables"/>
|
<tocdef id="AnnoteVariables" sortgroup="c" text="Variable Annotations" target="help/topics/DecompilePlugin/DecompilerAnnotations.html#AnnoteVariables"/>
|
||||||
<tocdef id="AnnotePrototype" sortgroup="d" text="Function Prototypes" target="help/topics/DecompilePlugin/DecompilerAnnotations.html#AnnotePrototype"/>
|
<tocdef id="AnnotePrototype" sortgroup="d" text="Function Prototypes" target="help/topics/DecompilePlugin/DecompilerAnnotations.html#AnnotePrototype"/>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,14 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package help;
|
package help;
|
||||||
|
|
||||||
import help.validator.LinkDatabase;
|
|
||||||
import help.validator.model.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import help.validator.LinkDatabase;
|
||||||
|
import help.validator.model.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that will take in a group of help directories and create a tree of
|
* A class that will take in a group of help directories and create a tree of
|
||||||
* help Table of Contents (TOC) items. Ideally, this tree can be used to create a single
|
* help Table of Contents (TOC) items. Ideally, this tree can be used to create a single
|
||||||
|
@ -33,7 +32,6 @@ import java.util.*;
|
||||||
* We call this class an <b>overlay</b> tree to drive home the idea that each
|
* We call this class an <b>overlay</b> tree to drive home the idea that each
|
||||||
* help directory's TOC data is put into the tree, with any duplicate paths overlayed
|
* help directory's TOC data is put into the tree, with any duplicate paths overlayed
|
||||||
* on top of those from other help directories.
|
* on top of those from other help directories.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class OverlayHelpTree {
|
public class OverlayHelpTree {
|
||||||
|
|
||||||
|
@ -44,10 +42,13 @@ public class OverlayHelpTree {
|
||||||
|
|
||||||
public OverlayHelpTree(TOCItemProvider tocItemProvider, LinkDatabase linkDatabase) {
|
public OverlayHelpTree(TOCItemProvider tocItemProvider, LinkDatabase linkDatabase) {
|
||||||
this.linkDatabase = linkDatabase;
|
this.linkDatabase = linkDatabase;
|
||||||
for (TOCItemExternal external : tocItemProvider.getTOCItemExternalsByDisplayMapping().values()) {
|
for (TOCItemExternal external : tocItemProvider.getTOCItemExternalsByDisplayMapping()
|
||||||
|
.values()) {
|
||||||
addExternalTOCItem(external);
|
addExternalTOCItem(external);
|
||||||
}
|
}
|
||||||
for (TOCItemDefinition definition : tocItemProvider.getTOCItemDefinitionsByIDMapping().values()) {
|
|
||||||
|
for (TOCItemDefinition definition : tocItemProvider.getTOCItemDefinitionsByIDMapping()
|
||||||
|
.values()) {
|
||||||
addSourceTOCItem(definition);
|
addSourceTOCItem(definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,12 +168,6 @@ public class OverlayHelpTree {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO delete this debug
|
|
||||||
// Set<Entry<String, Set<TOCItem>>> entrySet = parentToChildrenMap.entrySet();
|
|
||||||
// for (Entry<String, Set<TOCItem>> entry : entrySet) {
|
|
||||||
// System.out.println(entry.getKey() + " -> " + entry.getValue());
|
|
||||||
// }
|
|
||||||
|
|
||||||
OverlayNode newRootNode = new OverlayNode(null, rootItem);
|
OverlayNode newRootNode = new OverlayNode(null, rootItem);
|
||||||
buildChildren(newRootNode);
|
buildChildren(newRootNode);
|
||||||
|
|
||||||
|
@ -255,6 +250,7 @@ public class OverlayHelpTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO LOOKIE
|
||||||
private static final Comparator<OverlayNode> CHILD_SORT_COMPARATOR =
|
private static final Comparator<OverlayNode> CHILD_SORT_COMPARATOR =
|
||||||
new Comparator<OverlayNode>() {
|
new Comparator<OverlayNode>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -283,7 +279,16 @@ public class OverlayHelpTree {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return text1.compareTo(text2);
|
int result = text1.compareTo(text2);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point we have 2 nodes that have the same text attribute as children of
|
||||||
|
// a <TOCDEF> tag. This is OK, as we use text only for sorting, but not for the
|
||||||
|
// display text. Use the ID as a tie-breaker for sorting, which should provide
|
||||||
|
// sorting consistency.
|
||||||
|
return o1.getIDAttribute().compareTo(o2.getIDAttribute()); // ID should not be null
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package help.validator.model;
|
package help.validator.model;
|
||||||
|
|
||||||
import help.validator.LinkDatabase;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import help.validator.LinkDatabase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Table of Contents entry, which is represented in the help output as an xml tag.
|
* A Table of Contents entry, which is represented in the help output as an xml tag.
|
||||||
*/
|
*/
|
||||||
|
@ -63,7 +63,8 @@ public abstract class TOCItem {
|
||||||
String sortPreference, int lineNumber) {
|
String sortPreference, int lineNumber) {
|
||||||
this.parentItem = parentItem;
|
this.parentItem = parentItem;
|
||||||
this.sourceFile = sourceFile;
|
this.sourceFile = sourceFile;
|
||||||
this.IDAttribute = ID;
|
this.IDAttribute = Objects.requireNonNull(ID,
|
||||||
|
"TOC Tag missing 'id' attribute: " + sourceFile + ":" + lineNumber);
|
||||||
this.textAttribute = text;
|
this.textAttribute = text;
|
||||||
|
|
||||||
this.targetAttribute = target;
|
this.targetAttribute = target;
|
||||||
|
@ -157,82 +158,108 @@ public abstract class TOCItem {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj)
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
if (obj == null)
|
}
|
||||||
|
if (obj == null) {
|
||||||
return false;
|
return false;
|
||||||
if (getClass() != obj.getClass())
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
TOCItem other = (TOCItem) obj;
|
TOCItem other = (TOCItem) obj;
|
||||||
if (IDAttribute == null) {
|
if (IDAttribute == null) {
|
||||||
if (other.IDAttribute != null)
|
if (other.IDAttribute != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!IDAttribute.equals(other.IDAttribute))
|
}
|
||||||
|
else if (!IDAttribute.equals(other.IDAttribute)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (sortPreference == null) {
|
if (sortPreference == null) {
|
||||||
if (other.sortPreference != null)
|
if (other.sortPreference != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!sortPreference.equals(other.sortPreference))
|
}
|
||||||
|
else if (!sortPreference.equals(other.sortPreference)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (sourceFile == null) {
|
if (sourceFile == null) {
|
||||||
if (other.sourceFile != null)
|
if (other.sourceFile != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!sourceFile.equals(other.sourceFile))
|
}
|
||||||
|
else if (!sourceFile.equals(other.sourceFile)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (targetAttribute == null) {
|
if (targetAttribute == null) {
|
||||||
if (other.targetAttribute != null)
|
if (other.targetAttribute != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!targetAttribute.equals(other.targetAttribute))
|
}
|
||||||
|
else if (!targetAttribute.equals(other.targetAttribute)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (textAttribute == null) {
|
if (textAttribute == null) {
|
||||||
if (other.textAttribute != null)
|
if (other.textAttribute != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!textAttribute.equals(other.textAttribute))
|
}
|
||||||
|
else if (!textAttribute.equals(other.textAttribute)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the two items are the same, except that they come from a different source file.
|
* True if the two items are the same, except that they come from a different source file.
|
||||||
|
* @param other the other item
|
||||||
|
* @return true if equivalent
|
||||||
*/
|
*/
|
||||||
public boolean isEquivalent(TOCItem other) {
|
public boolean isEquivalent(TOCItem other) {
|
||||||
if (this == other)
|
if (this == other) {
|
||||||
return true;
|
return true;
|
||||||
if (other == null)
|
}
|
||||||
|
if (other == null) {
|
||||||
return false;
|
return false;
|
||||||
if (getClass() != other.getClass())
|
}
|
||||||
|
if (getClass() != other.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (IDAttribute == null) {
|
if (IDAttribute == null) {
|
||||||
if (other.IDAttribute != null)
|
if (other.IDAttribute != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!IDAttribute.equals(other.IDAttribute))
|
}
|
||||||
|
else if (!IDAttribute.equals(other.IDAttribute)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (sortPreference == null) {
|
if (sortPreference == null) {
|
||||||
if (other.sortPreference != null)
|
if (other.sortPreference != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!sortPreference.equals(other.sortPreference))
|
}
|
||||||
|
else if (!sortPreference.equals(other.sortPreference)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (targetAttribute == null) {
|
if (targetAttribute == null) {
|
||||||
if (other.targetAttribute != null)
|
if (other.targetAttribute != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!targetAttribute.equals(other.targetAttribute))
|
}
|
||||||
|
else if (!targetAttribute.equals(other.targetAttribute)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (textAttribute == null) {
|
if (textAttribute == null) {
|
||||||
if (other.textAttribute != null)
|
if (other.textAttribute != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!textAttribute.equals(other.textAttribute))
|
}
|
||||||
|
else if (!textAttribute.equals(other.textAttribute)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +280,8 @@ public abstract class TOCItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateTOCItemTag(LinkDatabase linkDatabase, boolean isInlineTag, int indentLevel) {
|
public String generateTOCItemTag(LinkDatabase linkDatabase, boolean isInlineTag,
|
||||||
|
int indentLevel) {
|
||||||
StringBuilder buildy = new StringBuilder();
|
StringBuilder buildy = new StringBuilder();
|
||||||
buildy.append(INDENTS[indentLevel]);
|
buildy.append(INDENTS[indentLevel]);
|
||||||
buildy.append('<').append(TOC_TAG_NAME).append(' ');
|
buildy.append('<').append(TOC_TAG_NAME).append(' ');
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package help;
|
package help;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
@ -68,12 +68,12 @@ public class OverlayHelpTreeTest {
|
||||||
|
|
||||||
Path tocSourceFile = Paths.get("/fake/path_2/TOC_Source.xml");
|
Path tocSourceFile = Paths.get("/fake/path_2/TOC_Source.xml");
|
||||||
String root_ID = root.getIDAttribute();
|
String root_ID = root.getIDAttribute();
|
||||||
TOCItemReference root_ref = referenceItem(root_ID, tocSourceFile);
|
TOCItemReference root_ref = tocref(root_ID, tocSourceFile);
|
||||||
|
|
||||||
String child_1_ID = child_1.getIDAttribute();
|
String child_1_ID = child_1.getIDAttribute();
|
||||||
TOCItemReference child_1_ref = referenceItem(root_ref, child_1_ID, tocSourceFile);
|
TOCItemReference child_1_ref = tocref(root_ref, child_1_ID, tocSourceFile);
|
||||||
|
|
||||||
TOCItemDefinition child_2 = definitionItem(child_1_ref, "child_2", tocSourceFile);
|
TOCItemDefinition child_2 = tocdef(child_1_ref, "child_2", tocSourceFile);
|
||||||
|
|
||||||
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
||||||
tocProvider.addExternal(root);
|
tocProvider.addExternal(root);
|
||||||
|
@ -88,6 +88,57 @@ public class OverlayHelpTreeTest {
|
||||||
assertOrder(spy, 3, child_2);
|
assertOrder(spy, 3, child_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSourceTOCFileThatDependsAnotherTOCSourceFile() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
The first source file defines attributes that the second file references.
|
||||||
|
|
||||||
|
Example makeup we will create:
|
||||||
|
|
||||||
|
TOC_Source.xml
|
||||||
|
|
||||||
|
<tocdef id="root" target="fake">
|
||||||
|
<tocdef id="child_1" target="fake" />
|
||||||
|
</tocdef>
|
||||||
|
|
||||||
|
|
||||||
|
Another TOC_Source.xml
|
||||||
|
|
||||||
|
<tocref id="root">
|
||||||
|
<tocref="child_1">
|
||||||
|
<tocdef id="child_2" target="fake" />
|
||||||
|
</tocref>
|
||||||
|
</tocref>
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Path toc_1 = Paths.get("/fake/path_1/TOC_Source.xml");
|
||||||
|
TOCItemDefinition root = tocdef("root", toc_1);
|
||||||
|
TOCItemDefinition child_1 = tocdef(root, "child_1", toc_1);
|
||||||
|
|
||||||
|
Path toc_2 = Paths.get("/fake/path_2/TOC_Source.xml");
|
||||||
|
String root_ID = root.getIDAttribute();
|
||||||
|
String child_1_ID = child_1.getIDAttribute();
|
||||||
|
|
||||||
|
TOCItemReference root_ref = tocref(root_ID, toc_2);
|
||||||
|
TOCItemReference child_1_ref = tocref(root_ref, child_1_ID, toc_2);
|
||||||
|
TOCItemDefinition child_2 = tocdef(child_1_ref, "child_2", toc_2);
|
||||||
|
|
||||||
|
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
||||||
|
tocProvider.addDefinition(root);
|
||||||
|
tocProvider.addDefinition(child_1);
|
||||||
|
tocProvider.addDefinition(child_2);// in the second TOC file
|
||||||
|
|
||||||
|
TOCSpyWriter spy = printOverlayTree(tocProvider, toc_2);
|
||||||
|
|
||||||
|
assertNodeCount(spy, 3);
|
||||||
|
assertOrder(spy, 1, root);
|
||||||
|
assertOrder(spy, 2, child_1);
|
||||||
|
assertOrder(spy, 3, child_2);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSourceTOCFileThatDependsUponPreBuiltHelp_MultiplePreBuiltInputs() {
|
public void testSourceTOCFileThatDependsUponPreBuiltHelp_MultiplePreBuiltInputs() {
|
||||||
//
|
//
|
||||||
|
@ -131,18 +182,17 @@ public class OverlayHelpTreeTest {
|
||||||
TOCItemExternal prebuilt_a_child = externalItem(child_1_a, "prebuilt_a_child");
|
TOCItemExternal prebuilt_a_child = externalItem(child_1_a, "prebuilt_a_child");
|
||||||
|
|
||||||
// note: same ID values, since they represent the same nodes, but from different TOC files
|
// note: same ID values, since they represent the same nodes, but from different TOC files
|
||||||
TOCItemExternal root_b = externalItemAlt(null, "root");
|
TOCItemExternal root_b = externalItem(null, "root");
|
||||||
TOCItemExternal child_1_b = externalItemAlt(root_b, "child_1");
|
TOCItemExternal child_1_b = externalItem(root_b, "child_1");
|
||||||
TOCItemExternal prebuilt_b_child = externalItemAlt(child_1_b, "prebuilt_b_child");
|
TOCItemExternal prebuilt_b_child = externalItem(child_1_b, "prebuilt_b_child");
|
||||||
|
|
||||||
Path tocSourceFile = Paths.get("/fake/path_2/TOC_Source.xml");
|
Path tocSourceFile = Paths.get("/fake/path_2/TOC_Source.xml");
|
||||||
String root_ID = root_a.getIDAttribute();
|
String root_ID = root_a.getIDAttribute();
|
||||||
TOCItemReference root_ref = referenceItem(root_ID, tocSourceFile);
|
TOCItemReference root_ref = tocref(root_ID, tocSourceFile);
|
||||||
|
|
||||||
String child_1_ID = child_1_a.getIDAttribute();
|
String child_1_ID = child_1_a.getIDAttribute();
|
||||||
TOCItemReference child_1_ref = referenceItem(root_ref, child_1_ID, tocSourceFile);
|
TOCItemReference child_1_ref = tocref(root_ref, child_1_ID, tocSourceFile);
|
||||||
|
TOCItemDefinition child_2 = tocdef(child_1_ref, "child_2", tocSourceFile);
|
||||||
TOCItemDefinition child_2 = definitionItem(child_1_ref, "child_2", tocSourceFile);
|
|
||||||
|
|
||||||
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
||||||
tocProvider.addExternal(root_a);
|
tocProvider.addExternal(root_a);
|
||||||
|
@ -166,54 +216,79 @@ public class OverlayHelpTreeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSourceTOCFileThatDependsAnotherTOCSourceFile() {
|
public void testSourceTOCFileThatHasNodeWithSameTextAttributeAsOneOfItsExternalModluleDependencies() {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
The first source file defines attributes that the second file references.
|
The first source file defines attributes that the second file references. Both files
|
||||||
|
will have multiple nodes that coincidentally share 'text' attribute values.
|
||||||
|
|
||||||
|
Note: the 'id' attributes have to be unique; the 'text' attributes do not have to be unique
|
||||||
|
|
||||||
Example makeup we will create:
|
Example makeup we will create:
|
||||||
|
|
||||||
TOC_Source.xml
|
PreBuild_TOC.xml
|
||||||
|
|
||||||
<tocdef id="root" target="fake">
|
<tocitem id="root" target="fake">
|
||||||
<tocdef id="child_1" target="fake" />
|
<tocitem id="child_1_1" text="Child 1" target="fake" />
|
||||||
</tocdef>
|
</tocitem>
|
||||||
|
|
||||||
|
Another PreBuild_TOC.xml
|
||||||
|
|
||||||
|
<tocitem id="root" target="fake">
|
||||||
|
<tocitem id="child_2_1" text=Child 1" target="fake" />
|
||||||
|
<tocitem id="child_2_2" text=Child 2" target="fake" />
|
||||||
|
</tocitem>
|
||||||
|
|
||||||
|
|
||||||
Another TOC_Source.xml
|
Another TOC_Source.xml
|
||||||
|
|
||||||
<tocref id="root">
|
<tocref id="root">
|
||||||
<tocref="child_1">
|
<tocref="child_1_1">
|
||||||
<tocdef id="child_2" target="fake" />
|
<tocdef id="child_2_1a" text="Child 1a" target="fake" />
|
||||||
</tocref>
|
</tocref>
|
||||||
|
<tocdef id="child_3_2" text="Child 2" target="fake" />
|
||||||
</tocref>
|
</tocref>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path toc_1 = Paths.get("/fake/path_1/TOC_Source.xml");
|
TOCItemExternal root_a = externalItem("root");
|
||||||
TOCItemDefinition root = definitionItem("root", toc_1);
|
TOCItemExternal child_1_1 = externalItem(root_a, "child_1_1", "Child 1");
|
||||||
TOCItemDefinition child_1 = definitionItem(root, "child_1", toc_1);
|
|
||||||
|
|
||||||
Path toc_2 = Paths.get("/fake/path_2/TOC_Source.xml");
|
// note: same ID values, since they represent the same nodes, but from different TOC files
|
||||||
String root_ID = root.getIDAttribute();
|
TOCItemExternal root_b = externalItem(null, "root");
|
||||||
String child_1_ID = child_1.getIDAttribute();
|
TOCItemExternal child_2_1 = externalItem(root_b, "child_2_1", "Child 1");
|
||||||
|
TOCItemExternal child_2_2 = externalItem(root_b, "child_2_2", "Child 2");
|
||||||
|
|
||||||
TOCItemReference root_ref = referenceItem(root_ID, toc_2);
|
Path toc = Paths.get("/fake/path_2/TOC_Source.xml");
|
||||||
TOCItemReference child_1_ref = referenceItem(root_ref, child_1_ID, toc_2);
|
String root_ID = root_a.getIDAttribute();
|
||||||
TOCItemDefinition child_2 = definitionItem(child_1_ref, "child_2", toc_2);
|
String child_1_ID = child_1_1.getIDAttribute();
|
||||||
|
|
||||||
|
TOCItemReference root_ref = tocref(root_ID, toc);
|
||||||
|
TOCItemReference child_1_ref = tocref(root_ref, child_1_ID, toc);
|
||||||
|
TOCItemDefinition child_2_1a = tocdef(child_1_ref, "child_2_1a", "Child 1a", toc);
|
||||||
|
TOCItemDefinition child_3_2 = tocdef(root_ref, "child_3_2", "Child 2", toc);
|
||||||
|
|
||||||
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
||||||
tocProvider.addDefinition(root);
|
tocProvider.addExternal(root_a);
|
||||||
tocProvider.addDefinition(child_1);
|
tocProvider.addExternal(child_1_1);
|
||||||
tocProvider.addDefinition(child_2);// in the second TOC file
|
tocProvider.addExternal(root_b);
|
||||||
|
tocProvider.addExternal(child_2_1);
|
||||||
|
tocProvider.addExternal(child_2_2);
|
||||||
|
tocProvider.addDefinition(child_2_1a); // in the first external TOC file
|
||||||
|
tocProvider.addDefinition(child_3_2);
|
||||||
|
|
||||||
TOCSpyWriter spy = printOverlayTree(tocProvider, toc_2);
|
TOCSpyWriter spy = printOverlayTree(tocProvider, toc);
|
||||||
|
|
||||||
assertNodeCount(spy, 3);
|
assertNodeCount(spy, 4);
|
||||||
assertOrder(spy, 1, root);
|
assertOrder(spy, 1, root_a);
|
||||||
assertOrder(spy, 2, child_1);
|
assertOrder(spy, 2, child_1_1);
|
||||||
assertOrder(spy, 3, child_2);
|
assertOrder(spy, 3, child_2_1a);
|
||||||
|
assertOrder(spy, 4, child_3_2);
|
||||||
|
|
||||||
|
// note: prebuilt_a_child and prebuilt_b_child don't get output, since they do not have
|
||||||
|
// the same TOC file ID as the help file being processed (in other words, they don't
|
||||||
|
// live in the TOC_Source.xml being processes, so they are not part of the output).
|
||||||
}
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
@ -242,22 +317,26 @@ public class OverlayHelpTreeTest {
|
||||||
return spy;
|
return spy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TOCItemDefinition definitionItem(String ID, Path tocSourceFile) {
|
private TOCItemDefinition tocdef(String ID, Path tocSourceFile) {
|
||||||
return definitionItem(null, ID, tocSourceFile);
|
return tocdef(null, ID, tocSourceFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TOCItemDefinition definitionItem(TOCItem parent, String ID, Path tocSourceFile) {
|
private TOCItemDefinition tocdef(TOCItem parent, String ID, Path tocSourceFile) {
|
||||||
|
return tocdef(parent, ID, ID, tocSourceFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TOCItemDefinition tocdef(TOCItem parent, String ID, String text, Path tocSourceFile) {
|
||||||
String target = "fake";
|
String target = "fake";
|
||||||
String sort = "";
|
String sort = "";
|
||||||
int line = 1;
|
int line = 1;
|
||||||
return new TOCItemDefinition(parent, tocSourceFile, ID, ID, target, sort, line);
|
return new TOCItemDefinition(parent, tocSourceFile, ID, text, target, sort, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TOCItemReference referenceItem(String referenceID, Path tocSourceFile) {
|
private TOCItemReference tocref(String referenceID, Path tocSourceFile) {
|
||||||
return referenceItem(null, referenceID, tocSourceFile);
|
return tocref(null, referenceID, tocSourceFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TOCItemReference referenceItem(TOCItem parent, String referenceID, Path tocSourceFile) {
|
private TOCItemReference tocref(TOCItem parent, String referenceID, Path tocSourceFile) {
|
||||||
return new TOCItemReference(parent, tocSourceFile, referenceID, 1);
|
return new TOCItemReference(parent, tocSourceFile, referenceID, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,24 +345,20 @@ public class OverlayHelpTreeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private TOCItemExternal externalItem(TOCItem parent, String ID) {
|
private TOCItemExternal externalItem(TOCItem parent, String ID) {
|
||||||
Path tocFile = Paths.get("/fake/path_1/PreBuild_TOC.xml");
|
return externalItem(parent, ID, ID);
|
||||||
String target = "fake";
|
|
||||||
String sort = "";
|
|
||||||
int line = 1;
|
|
||||||
return new TOCItemExternal(parent, tocFile, ID, ID, target, sort, line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TOCItemExternal externalItemAlt(TOCItem parent, String ID) {
|
private TOCItemExternal externalItem(TOCItem parent, String ID, String text) {
|
||||||
Path tocFile = Paths.get("/fake/path_1/PreBuild_TOC.xml");
|
Path tocFile = Paths.get("/fake/path_1/PreBuild_TOC.xml");
|
||||||
String target = "fake";
|
String target = "fake";
|
||||||
String sort = "";
|
String sort = "";
|
||||||
int line = 1;
|
int line = 1;
|
||||||
return new TOCItemExternal(parent, tocFile, ID, ID, target, sort, line);
|
return new TOCItemExternal(parent, tocFile, ID, text, target, sort, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertOrder(TOCSpyWriter spy, int ordinal, TOCItem item) {
|
private void assertOrder(TOCSpyWriter spy, int ordinal, TOCItem item) {
|
||||||
String ID = spy.getItem(ordinal - 1 /* make an index */);
|
String ID = spy.getItem(ordinal - 1 /* make an index */);
|
||||||
assertEquals("Did not find TOC item at expected index: " + ordinal, item.getIDAttribute(),
|
assertEquals("Did not find TOC item at expected ordinal: " + ordinal, item.getIDAttribute(),
|
||||||
ID);
|
ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +399,7 @@ public class OverlayHelpTreeTest {
|
||||||
|
|
||||||
private void storeDisplayAttribute(String s) {
|
private void storeDisplayAttribute(String s) {
|
||||||
// create a pattern to pull out the display string
|
// create a pattern to pull out the display string
|
||||||
Pattern p = Pattern.compile(".*display=\"(.*)\" toc_id.*");
|
Pattern p = Pattern.compile(".*toc_id=\"(.*)\".*");
|
||||||
Matcher matcher = p.matcher(s.trim());
|
Matcher matcher = p.matcher(s.trim());
|
||||||
|
|
||||||
if (!matcher.matches()) {
|
if (!matcher.matches()) {
|
||||||
|
@ -347,8 +422,8 @@ public class OverlayHelpTreeTest {
|
||||||
Map<String, TOCItemDefinition> definitions = new HashMap<>();
|
Map<String, TOCItemDefinition> definitions = new HashMap<>();
|
||||||
|
|
||||||
void addExternal(TOCItemExternal item) {
|
void addExternal(TOCItemExternal item) {
|
||||||
String displayText = item.getIDAttribute();
|
String ID = item.getIDAttribute();
|
||||||
externals.put(displayText, item);
|
externals.put(ID, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDefinition(TOCItemDefinition item) {
|
void addDefinition(TOCItemDefinition item) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue