Skip to content

Commit c10daca

Browse files
authored
isEqualNode implementation
1 parent c33b499 commit c10daca

File tree

14 files changed

+173
-24
lines changed

14 files changed

+173
-24
lines changed

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ jobs:
1515
distribution: 'corretto'
1616
- name: Publish package
1717
env:
18-
JRELEASER_NEXUS2_USERNAME: ${{ secrets.TOKEN_JRELEASER_NEXUS2_USERNAME }}
19-
JRELEASER_NEXUS2_TOKEN: ${{ secrets.TOKEN_JRELEASER_NEXUS2_TOKEN }}
18+
JRELEASER_NEXUS2_USERNAME: ${{ secrets.TOKEN_JRELEASER_SONATYPE_USERNAME }}
19+
JRELEASER_NEXUS2_TOKEN: ${{ secrets.TOKEN_JRELEASER_SONATYPE_TOKEN }}
2020
JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }}
2121
JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }}
2222
JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.JRELEASER_GPG_PUBLIC_KEY }}

pom.xml

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,17 @@
7272
<dependency>
7373
<groupId>org.jsoup</groupId>
7474
<artifactId>jsoup</artifactId>
75-
<version>1.18.3</version>
75+
<version>1.19.1</version>
7676
<scope>test</scope>
7777
</dependency>
78+
<!--
79+
<dependency>
80+
<groupId>tools.profiler</groupId>
81+
<artifactId>async-profiler</artifactId>
82+
<version>3.0</version>
83+
<scope>test</scope>
84+
</dependency>
85+
-->
7886
</dependencies>
7987

8088
<build>
@@ -203,15 +211,13 @@
203211
</signing>
204212
<deploy>
205213
<maven>
206-
<nexus2>
207-
<maven-central>
214+
<mavenCentral>
215+
<sonatype>
208216
<active>ALWAYS</active>
209-
<url>https://oss.sonatype.org/service/local</url>;
210-
<closeRepository>true</closeRepository>
211-
<releaseRepository>true</releaseRepository>
217+
<url>https://central.sonatype.com/api/v1/publisher</url>
212218
<stagingRepositories>target/staging-deploy</stagingRepositories>
213-
</maven-central>
214-
</nexus2>
219+
</sonatype>
220+
</mavenCentral>
215221
</maven>
216222
</deploy>
217223
</jreleaser>

src/main/java/ch/digitalfondue/jfiveparse/AttributeNode.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,7 @@ public boolean equals(Object obj) {
103103
getValue().equals(other.getValue()) && //
104104
Objects.equals(prefix, other.prefix) && //
105105
Objects.equals(namespace, other.namespace);
106-
} else {
107-
return false;
108106
}
107+
return false;
109108
}
110109
}

src/main/java/ch/digitalfondue/jfiveparse/Attributes.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@ public boolean equals(Object obj) {
4343
return true;
4444
}
4545

46-
if (!(obj instanceof Attributes)) {
47-
return false;
46+
if (obj instanceof Attributes) {
47+
return Objects.equals(attributes, ((Attributes) obj).attributes);
4848
}
49-
50-
return Objects.equals(attributes, ((Attributes) obj).attributes);
49+
return false;
5150
}
5251

5352
public Attributes copy() {
@@ -64,7 +63,7 @@ public AttributeNode get(String key) {
6463
}
6564

6665
Set<String> keySet() {
67-
return attributes == null ? Collections.emptySet() : attributes.keySet();
66+
return attributes == null ? Set.of() : attributes.keySet();
6867
}
6968

7069
private void ensureMap() {

src/main/java/ch/digitalfondue/jfiveparse/Comment.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package ch.digitalfondue.jfiveparse;
1717

18+
import java.util.Objects;
19+
1820
/**
1921
* Represent a comment.
2022
*/
@@ -61,4 +63,15 @@ public String getNodeName() {
6163
public Node cloneNode(boolean deep) {
6264
return new Comment(getData());
6365
}
66+
67+
@Override
68+
public boolean isEqualNode(Node other) {
69+
if (this == other) {
70+
return true;
71+
}
72+
if (other instanceof Comment) {
73+
return Objects.equals(getData(), ((Comment) other).getData());
74+
}
75+
return false;
76+
}
6477
}

src/main/java/ch/digitalfondue/jfiveparse/Document.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,28 @@ public Node cloneNode(boolean deep) {
117117
}
118118
return cloned;
119119
}
120+
121+
@Override
122+
public boolean isEqualNode(Node other) {
123+
if (this == other) {
124+
return true;
125+
}
126+
if (other instanceof Document) {
127+
Document otherDocument = (Document) other;
128+
if (!Node.nodesEquals(doctype, otherDocument.doctype)) {
129+
return false;
130+
}
131+
int count = getChildCount();
132+
if (count != otherDocument.getChildCount()) {
133+
return false;
134+
}
135+
for (var i = 0; i < count; i++) {
136+
if (!Node.nodesEquals(childNodes.get(i), otherDocument.childNodes.get(i))) {
137+
return false;
138+
}
139+
}
140+
return true;
141+
}
142+
return false;
143+
}
120144
}

src/main/java/ch/digitalfondue/jfiveparse/DocumentType.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package ch.digitalfondue.jfiveparse;
1717

18+
import java.util.Objects;
19+
1820
/**
1921
* Represent a document type.
2022
*/
@@ -59,4 +61,18 @@ public String getNodeName() {
5961
public Node cloneNode(boolean deep) {
6062
return new DocumentType(getName(), getPublicId(), getSystemId());
6163
}
64+
65+
@Override
66+
public boolean isEqualNode(Node other) {
67+
if (this == other) {
68+
return true;
69+
}
70+
if (other instanceof DocumentType) {
71+
DocumentType otherDocType = (DocumentType) other;
72+
return Objects.equals(name, otherDocType.name) &&
73+
Objects.equals(publicId, otherDocType.publicId) &&
74+
Objects.equals(systemId, otherDocType.systemId);
75+
}
76+
return false;
77+
}
6278
}

src/main/java/ch/digitalfondue/jfiveparse/Element.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ private void ensureAttributesPresence() {
8787
*/
8888
@Override
8989
public List<Node> getChildNodes() {
90-
return childNodes == null ? Collections.emptyList() : Collections.unmodifiableList(childNodes);
90+
return childNodes == null ? List.of() : Collections.unmodifiableList(childNodes);
9191
}
9292

9393
@Override
@@ -343,6 +343,33 @@ public Node cloneNode(boolean deep) {
343343
return clone;
344344
}
345345

346+
@Override
347+
public boolean isEqualNode(Node other) {
348+
if (this == other) {
349+
return true;
350+
}
351+
if (other instanceof Element) {
352+
Element otherElement = (Element) other;
353+
var count = getChildCount();
354+
var equalityCheck = Objects.equals(getNodeName(), otherElement.getNodeName()) &&
355+
Objects.equals(getNamespaceURI(), otherElement.getNamespaceURI()) &&
356+
Objects.equals(count, otherElement.getChildCount()) &&
357+
Objects.equals(getAttributes(), otherElement.getAttributes());
358+
359+
if (!equalityCheck) {
360+
return false;
361+
}
362+
363+
for (var i = 0; i < count; i++) {
364+
if (!Node.nodesEquals(childNodes.get(i), otherElement.childNodes.get(i))) {
365+
return false;
366+
}
367+
}
368+
return true;
369+
}
370+
return false;
371+
}
372+
346373
/**
347374
* Get the html content of the child of this node.
348375
*/

src/main/java/ch/digitalfondue/jfiveparse/Node.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*/
2323
public abstract class Node {
2424

25-
private static final List<Node> EMPTY_LIST = Collections.emptyList();
25+
private static final List<Node> EMPTY_LIST = List.of();
2626

2727
Node parentNode;
2828

@@ -547,6 +547,30 @@ public boolean isSameNode(Node other) {
547547
*/
548548
public abstract Node cloneNode(boolean deep);
549549

550+
/**
551+
* Check if the node is equal to the parameter.
552+
*
553+
* See <a href="https://dom.spec.whatwg.org/#concept-node-equals">...</a>
554+
*
555+
* @param other
556+
* @return
557+
*/
558+
public abstract boolean isEqualNode(Node other);
559+
560+
/**
561+
* Null safe static isEqualNode helper
562+
*
563+
* @param a
564+
* @param b
565+
* @return
566+
*/
567+
static boolean nodesEquals(Node a, Node b) {
568+
if (a != null && b != null) {
569+
return a.isEqualNode(b);
570+
} else {
571+
return a == null && b == null;
572+
}
573+
}
550574

551575
private void replaceTextNodeWith(Node text, StringBuilder concatenatedText) {
552576
if(concatenatedText.length() == 0) {

src/main/java/ch/digitalfondue/jfiveparse/Text.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package ch.digitalfondue.jfiveparse;
1717

18+
import java.util.Objects;
19+
1820
/**
1921
* Represent a text node.
2022
*/
@@ -65,4 +67,15 @@ public String getNodeName() {
6567
public Node cloneNode(boolean deep) {
6668
return new Text(getData());
6769
}
70+
71+
@Override
72+
public boolean isEqualNode(Node other) {
73+
if (this == other) {
74+
return true;
75+
}
76+
if (other instanceof Text) {
77+
return Objects.equals(getData(), ((Text) other).getData());
78+
}
79+
return false;
80+
}
6881
}

src/test/java/ch/digitalfondue/jfiveparse/CheckRead.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package ch.digitalfondue.jfiveparse;
22

3+
//import one.profiler.AsyncProfiler;
4+
35
import java.io.IOException;
46
import java.nio.charset.StandardCharsets;
57
import java.nio.file.Files;
@@ -10,12 +12,17 @@ public class CheckRead {
1012
// test class for gathering profiling stats & co...
1113
public static void main(String[] args) throws IOException {
1214
var content = Files.readString(Path.of("src/test/resources/wikipedia.html"), StandardCharsets.UTF_8);
13-
15+
//AsyncProfiler profiler = AsyncProfiler.getInstance();
16+
//profiler.execute("start,event=cpu,file=test.html");
17+
var start = System.currentTimeMillis();
1418
for (int i = 0; i < 100_000; i++) {
1519
Document doc = JFiveParse.parse(content);
1620

1721
Element e = doc.getElementById("mp-dyk-h2");
1822
String c = e.getOuterHTML();
1923
}
24+
var end = System.currentTimeMillis();
25+
//profiler.execute("stop");
26+
System.out.println("total :" + ((end - start) / 1000.0) + "s");
2027
}
2128
}

src/test/java/ch/digitalfondue/jfiveparse/NodeTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,4 +280,26 @@ void sameNode() {
280280
assertTrue(b.isSameNode(b));
281281
}
282282

283+
284+
private static boolean areFragmentEquals(String a, String b) {
285+
return JFiveParse.parseFragment(a).get(0).isEqualNode(JFiveParse.parseFragment(b).get(0));
286+
}
287+
288+
@Test
289+
void isEqualNodeCheck() {
290+
assertTrue(areFragmentEquals("<p>a</p>", "<p>a</p>"));
291+
assertTrue(areFragmentEquals("<p id=test>a</p>", "<p id='test'>a</p>"));
292+
assertTrue(areFragmentEquals("<p id=test>a<!-- comment --></p>", "<p id='test'>a<!-- comment --></p>"));
293+
assertTrue(areFragmentEquals("<p><span><span><span>b</span></span></span></p>", "<p><span><span><span>b</span></span></span></p>"));
294+
295+
assertFalse(areFragmentEquals("<p>a</p>", "<li>a</li>"));
296+
assertFalse(areFragmentEquals("<p>a</p>", "<p>b</p>"));
297+
assertFalse(areFragmentEquals("<p id=testa>a</p>", "<p id='testb'>a</p>"));
298+
assertFalse(areFragmentEquals("<p id=test>a<!-- comment --></p>", "<p id='test'>a<!-- commentb --></p>"));
299+
assertFalse(areFragmentEquals("<p><span><span><span>b</span></span></span></p>", "<p><span><span><span>c</span></span></span></p>"));
300+
301+
302+
assertTrue(JFiveParse.parse("<html><body>hello</body></html>").isEqualNode(JFiveParse.parse("<html><body>hello</body></html>")));
303+
assertFalse(JFiveParse.parse("<!DOCTYPE html><html><body>hello</body></html>").isEqualNode(JFiveParse.parse("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html><body>hello</body></html>")));
304+
}
283305
}

src/test/java/ch/digitalfondue/jfiveparse/Resizable.java renamed to src/test/java/ch/digitalfondue/jfiveparse/ResizableTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import static org.junit.jupiter.api.Assertions.assertEquals;
66

77

8-
class Resizable {
8+
class ResizableTest {
99

1010
@Test
1111
void checkTest() {

src/test/java/ch/digitalfondue/jfiveparse/TestParsePerf.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import java.io.IOException;
88

99
import static org.junit.jupiter.api.Assertions.assertEquals;
10-
import java.nio.charset.StandardCharsets;
1110
import java.nio.file.Files;
1211
import java.nio.file.Paths;
1312

@@ -19,11 +18,12 @@ public class TestParsePerf {
1918

2019
@BeforeEach
2120
void load() throws IOException {
22-
file = new String(Files.readAllBytes(Paths.get("src/test/resources/test.html")), StandardCharsets.UTF_8);
21+
file = Files.readString(Paths.get("src/test/resources/test.html"));
2322
}
2423

2524
int round = 20_000_000;
2625

26+
@Disabled
2727
@Test
2828
void check() {
2929
assertEquals(91, parser.parse(file).getAllNodesMatching(Selector.select().element("div").toMatcher()).size());
@@ -35,7 +35,6 @@ void check() {
3535
@Disabled
3636
@Test
3737
public void parse() {
38-
3938
long start = System.nanoTime();
4039
for (int i = 0; i < round; i++) {
4140
parser.parse(file);

0 commit comments

Comments
 (0)