Skip to content

Commit f6dd67f

Browse files
author
Eugene Bochilo
committed
Implement non-page(s) target-counter(s)
DEVSIX-4693
1 parent 471d130 commit f6dd67f

File tree

4 files changed

+125
-12
lines changed

4 files changed

+125
-12
lines changed

styled-xml-parser/src/main/java/com/itextpdf/styledxmlparser/LogMessageConstant.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ public final class LogMessageConstant {
7979
public static final String QUOTE_IS_NOT_CLOSED_IN_CSS_EXPRESSION = "The quote is not closed in css expression: {0}";
8080
/** The Constant INVALID_CSS_PROPERTY_DECLARATION. */
8181
public static final String INVALID_CSS_PROPERTY_DECLARATION = "Invalid css property declaration: {0}";
82+
/**
83+
* The Constant INCORRECT_CHARACTER_SEQUENCE.
84+
*/
85+
public static final String INCORRECT_CHARACTER_SEQUENCE = "Incorrect character sequence.";
8286
public static final String INCORRECT_RESOLUTION_UNIT_VALUE = "Resolution value unit should be either dpi, dppx or dpcm!";
8387
/** The Constant RULE_IS_NOT_SUPPORTED. */
8488
public static final String RULE_IS_NOT_SUPPORTED = "The rule @{0} is unsupported. All selectors in this rule will be ignored.";

styled-xml-parser/src/main/java/com/itextpdf/styledxmlparser/css/util/CssUtils.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,26 +86,39 @@ private CssUtils() {
8686
* @return the {@link List} of split result
8787
*/
8888
public static List<String> splitStringWithComma(final String value) {
89+
return splitString(value, ',', new EscapeGroup('(', ')'));
90+
}
91+
92+
/**
93+
* Splits the provided {@link String} by split character with respect of escape characters.
94+
*
95+
* @param value value to split
96+
* @param splitChar character to split the String
97+
* @param escapeCharacters escape characters
98+
* @return the {@link List} of split result
99+
*/
100+
public static List<String> splitString(String value, char splitChar, EscapeGroup... escapeCharacters) {
89101
if (value == null) {
90102
return new ArrayList<>();
91103
}
92104
final List<String> resultList = new ArrayList<>();
93-
int lastComma = 0;
94-
int notClosedBrackets = 0;
105+
int lastSplitChar = 0;
95106
for (int i = 0; i < value.length(); ++i) {
96-
if (value.charAt(i) == ',' && notClosedBrackets == 0) {
97-
resultList.add(value.substring(lastComma, i));
98-
lastComma = i + 1;
99-
}
100-
if (value.charAt(i) == '(') {
101-
++notClosedBrackets;
107+
final char currentChar = value.charAt(i);
108+
boolean isEscaped = false;
109+
for (final EscapeGroup character : escapeCharacters) {
110+
if (currentChar == splitChar) {
111+
isEscaped = isEscaped || character.isEscaped();
112+
} else {
113+
character.processCharacter(currentChar);
114+
}
102115
}
103-
if (value.charAt(i) == ')') {
104-
--notClosedBrackets;
105-
notClosedBrackets = Math.max(notClosedBrackets, 0);
116+
if (currentChar == splitChar && !isEscaped) {
117+
resultList.add(value.substring(lastSplitChar, i));
118+
lastSplitChar = i + 1;
106119
}
107120
}
108-
final String lastToken = value.substring(lastComma);
121+
final String lastToken = value.substring(lastSplitChar);
109122
if (!lastToken.isEmpty()) {
110123
resultList.add(lastToken);
111124
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.itextpdf.styledxmlparser.css.util;
2+
3+
import com.itextpdf.io.util.MessageFormatUtil;
4+
import com.itextpdf.styledxmlparser.LogMessageConstant;
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
8+
/**
9+
* Class to store escape characters and their processing logic.
10+
* This class is used in {@link CssUtils#splitString(String, char, EscapeGroup...)} method.
11+
*/
12+
public class EscapeGroup {
13+
private static final Logger LOGGER = LoggerFactory.getLogger(EscapeGroup.class);
14+
15+
private final char openCharacter;
16+
private final char closeCharacter;
17+
18+
private int counter = 0;
19+
20+
/**
21+
* Creates instance of {@link EscapeGroup}.
22+
*
23+
* @param openCharacter opening escape character
24+
* @param closeCharacter closing escape character
25+
*/
26+
public EscapeGroup(char openCharacter, char closeCharacter) {
27+
this.openCharacter = openCharacter;
28+
this.closeCharacter = closeCharacter;
29+
}
30+
31+
/**
32+
* Creates instance of {@link EscapeGroup} when opening and closing characters are the same.
33+
*
34+
* @param escapeChar opening and closing escape character
35+
*/
36+
public EscapeGroup(char escapeChar) {
37+
this.openCharacter = escapeChar;
38+
this.closeCharacter = escapeChar;
39+
}
40+
41+
/**
42+
* Is currently processed character in {@link CssUtils#splitString(String, char, EscapeGroup...)} escaped.
43+
*
44+
* @return true if escaped, false otherwise
45+
*/
46+
boolean isEscaped() {
47+
return counter != 0;
48+
}
49+
50+
/**
51+
* Processes given character.
52+
*
53+
* @param nextCharacter next character to process
54+
*/
55+
void processCharacter(char nextCharacter) {
56+
if (openCharacter == closeCharacter) {
57+
if (nextCharacter == openCharacter) {
58+
if (isEscaped()) {
59+
++counter;
60+
} else {
61+
--counter;
62+
}
63+
}
64+
} else {
65+
if (nextCharacter == openCharacter) {
66+
++counter;
67+
} else if (nextCharacter == closeCharacter) {
68+
--counter;
69+
if (counter < 0) {
70+
LOGGER.warn(MessageFormatUtil.format(LogMessageConstant.INCORRECT_CHARACTER_SEQUENCE));
71+
counter = 0;
72+
}
73+
}
74+
}
75+
}
76+
}

styled-xml-parser/src/test/java/com/itextpdf/styledxmlparser/css/util/CssUtilsTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ public void elementNodeAttributeIsNotStylesheet() {
387387
}
388388

389389
@Test
390+
@LogMessages(messages = @LogMessage(messageTemplate = LogMessageConstant.INCORRECT_CHARACTER_SEQUENCE))
390391
public void splitStringWithCommaTest() {
391392
Assert.assertEquals(new ArrayList<String>(), CssUtils.splitStringWithComma(null));
392393
Assert.assertEquals(Arrays.asList("value1", "value2", "value3"),
@@ -405,6 +406,25 @@ public void splitStringWithCommaTest() {
405406
CssUtils.splitStringWithComma("v.al*ue1\",( v2,v3),\"(v4,v5;);,value3"));
406407
}
407408

409+
@Test
410+
public void splitStringTest() {
411+
Assert.assertEquals(new ArrayList<String>(), CssUtils.splitString(null, ','));
412+
Assert.assertEquals(Arrays.asList("value1", "(value,with,comma)", "value3"),
413+
CssUtils.splitString("value1,(value,with,comma),value3", ',', new EscapeGroup('(', ')')));
414+
Assert.assertEquals(Arrays.asList("value1 ", " (val(ue,with,comma),value3"),
415+
CssUtils.splitString("value1 , (val(ue,with,comma),value3", ',', new EscapeGroup('(', ')')));
416+
Assert.assertEquals(Arrays.asList("some text", " (some", " text in", " brackets)", " \"some, text, in quotes,\""),
417+
CssUtils.splitString("some text, (some, text in, brackets), \"some, text, in quotes,\"", ',',
418+
new EscapeGroup('\"')));
419+
Assert.assertEquals(Arrays.asList("some text", " (some. text in. brackets)", " \"some. text. in quotes.\""),
420+
CssUtils.splitString("some text. (some. text in. brackets). \"some. text. in quotes.\"", '.',
421+
new EscapeGroup('\"'), new EscapeGroup('(', ')')));
422+
Assert.assertEquals(Arrays.asList("value1", "(value", "with" ,"comma)", "value3"),
423+
CssUtils.splitString("value1,(value,with,comma),value3", ','));
424+
Assert.assertEquals(Arrays.asList("value1", "value", "with" ,"comma", "value3"),
425+
CssUtils.splitString("value1,value,with,comma,value3", ',', new EscapeGroup(',')));
426+
}
427+
408428
@Test
409429
public void parseBlendModeTest() {
410430
Assert.assertEquals(BlendMode.NORMAL, CssUtils.parseBlendMode(null));

0 commit comments

Comments
 (0)