Skip to content

Commit 98b3cab

Browse files
committed
Added a new lambda to split long fragments into compilable strings
1 parent a33a77f commit 98b3cab

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package io.swagger.codegen.mustache;
2+
3+
import java.io.IOException;
4+
import java.io.Writer;
5+
6+
import com.samskivert.mustache.Mustache;
7+
import com.samskivert.mustache.Template.Fragment;
8+
9+
/**
10+
* Splits long fragments into smaller strings and uses a StringBuilder to merge
11+
* them back.
12+
*
13+
* Register:
14+
*
15+
* <pre>
16+
* additionalProperties.put("lambdaSplitString", new SplitStringLambda());
17+
* </pre>
18+
*
19+
* Use:
20+
*
21+
* <pre>
22+
* {{#lambdaSplitString}}{{summary}}{{/lambdaSplitString}}
23+
* </pre>
24+
*/
25+
public class SplitStringLambda implements Mustache.Lambda {
26+
private static final int DEFAULT_MAX_LENGTH = 65535;
27+
28+
private static final String SPLIT_INIT = "new StringBuilder(%d)";
29+
30+
private static final String SPLIT_PART = ".append(\"%s\")";
31+
32+
private static final String SPLIT_SUFFIX = ".toString()";
33+
34+
private final int maxLength;
35+
36+
public SplitStringLambda() {
37+
this(DEFAULT_MAX_LENGTH);
38+
}
39+
40+
public SplitStringLambda(int maxLength) {
41+
this.maxLength = maxLength;
42+
}
43+
44+
@Override
45+
public void execute(Fragment fragment, Writer writer) throws IOException {
46+
String input = fragment.execute();
47+
int inputLength = input.length();
48+
49+
StringBuilder builder = new StringBuilder();
50+
if (inputLength > maxLength) {
51+
52+
// Initialize a StringBuilder
53+
builder.append(String.format(SPLIT_INIT, inputLength));
54+
55+
int currentPosition = 0;
56+
int currentStringLength = 0;
57+
char currentLastChar = '\\';
58+
59+
// Split input into parts of at most maxLength and not ending with an escape character
60+
// Append each part to the StringBuilder
61+
while (currentPosition + maxLength < input.length()) {
62+
currentStringLength = maxLength;
63+
currentLastChar = input.charAt(currentPosition + currentStringLength - 1);
64+
if (currentLastChar == '\\') {
65+
--currentStringLength;
66+
}
67+
68+
builder.append(String.format(SPLIT_PART, input.substring(currentPosition, currentPosition + currentStringLength)));
69+
currentPosition += currentStringLength;
70+
}
71+
72+
// Append last part if necessary
73+
if (currentPosition < input.length()) {
74+
builder.append(String.format(SPLIT_PART, input.substring(currentPosition)));
75+
}
76+
77+
// Close the builder and merge everything back to a string
78+
builder.append(SPLIT_SUFFIX);
79+
} else {
80+
builder.append(String.format("\"%s\"", input));
81+
}
82+
83+
writer.write(builder.toString());
84+
}
85+
86+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package io.swagger.codegen.mustache;
2+
3+
import static org.mockito.Mockito.when;
4+
import static org.testng.Assert.assertEquals;
5+
6+
import java.io.IOException;
7+
import java.io.StringWriter;
8+
import java.util.HashMap;
9+
import java.util.Map;
10+
11+
import org.mockito.Mock;
12+
import org.mockito.Mockito;
13+
import org.mockito.MockitoAnnotations;
14+
import org.testng.annotations.AfterMethod;
15+
import org.testng.annotations.BeforeMethod;
16+
import org.testng.annotations.Test;
17+
18+
import com.samskivert.mustache.Template.Fragment;
19+
20+
public class SplitStringLambdaTest {
21+
private static final String INPUT_STRING = "1112223334";
22+
23+
private static final Map<Integer, String> EXPECTED_OUTPUTS;
24+
static {
25+
EXPECTED_OUTPUTS = new HashMap<>();
26+
EXPECTED_OUTPUTS.put(2,
27+
String.format(
28+
"new StringBuilder(%d).append(\"11\").append(\"12\").append(\"22\").append(\"33\").append(\"34\").toString()",
29+
INPUT_STRING.length()));
30+
EXPECTED_OUTPUTS.put(3,
31+
String.format(
32+
"new StringBuilder(%d).append(\"111\").append(\"222\").append(\"333\").append(\"4\").toString()",
33+
INPUT_STRING.length()));
34+
}
35+
36+
private static final String INPUT_QUOTED_STRING = "1\\\"11\\\"2223\\\"334";
37+
private static final String INPUT_QUOTED_OUTPUT = String.format(
38+
"new StringBuilder(%d).append(\"1\\\"\").append(\"11\").append(\"\\\"2\").append(\"223\").append(\"\\\"3\").append(\"34\").toString()",
39+
INPUT_QUOTED_STRING.length());
40+
41+
@Mock
42+
private Fragment fragment;
43+
44+
@BeforeMethod
45+
public void init() {
46+
MockitoAnnotations.initMocks(this);
47+
}
48+
49+
@AfterMethod
50+
public void reset() {
51+
Mockito.reset(fragment);
52+
}
53+
54+
private void testString(String input, int maxLength, String expected) throws IOException {
55+
when(fragment.execute()).thenReturn(input);
56+
57+
StringWriter output = new StringWriter();
58+
new SplitStringLambda(maxLength).execute(fragment, output);
59+
assertEquals(output.toString(), expected);
60+
}
61+
62+
@Test
63+
public void testSplitGroupsOf2() throws IOException {
64+
int maxLength = 2;
65+
testString(INPUT_STRING, maxLength, EXPECTED_OUTPUTS.get(maxLength));
66+
}
67+
68+
@Test
69+
public void testSplitGroupsOf3() throws IOException {
70+
int maxLength = 3;
71+
testString(INPUT_STRING, maxLength, EXPECTED_OUTPUTS.get(maxLength));
72+
}
73+
74+
@Test
75+
public void testSplitQuotedString() throws IOException {
76+
int maxLength = 3;
77+
testString(INPUT_QUOTED_STRING, maxLength, INPUT_QUOTED_OUTPUT);
78+
}
79+
80+
@Test
81+
public void testShortString() throws IOException {
82+
testString(INPUT_STRING, INPUT_STRING.length(), String.format("\"%s\"", INPUT_STRING));
83+
}
84+
85+
}

0 commit comments

Comments
 (0)