Skip to content

Commit

Permalink
Added a new lambda to split long fragments into compilable strings
Browse files Browse the repository at this point in the history
  • Loading branch information
smasset committed Apr 17, 2019
1 parent a33a77f commit 98b3cab
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package io.swagger.codegen.mustache;

import java.io.IOException;
import java.io.Writer;

import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template.Fragment;

/**
* Splits long fragments into smaller strings and uses a StringBuilder to merge
* them back.
*
* Register:
*
* <pre>
* additionalProperties.put("lambdaSplitString", new SplitStringLambda());
* </pre>
*
* Use:
*
* <pre>
* {{#lambdaSplitString}}{{summary}}{{/lambdaSplitString}}
* </pre>
*/
public class SplitStringLambda implements Mustache.Lambda {
private static final int DEFAULT_MAX_LENGTH = 65535;

private static final String SPLIT_INIT = "new StringBuilder(%d)";

private static final String SPLIT_PART = ".append(\"%s\")";

private static final String SPLIT_SUFFIX = ".toString()";

private final int maxLength;

public SplitStringLambda() {
this(DEFAULT_MAX_LENGTH);
}

public SplitStringLambda(int maxLength) {
this.maxLength = maxLength;
}

@Override
public void execute(Fragment fragment, Writer writer) throws IOException {
String input = fragment.execute();
int inputLength = input.length();

StringBuilder builder = new StringBuilder();
if (inputLength > maxLength) {

// Initialize a StringBuilder
builder.append(String.format(SPLIT_INIT, inputLength));

int currentPosition = 0;
int currentStringLength = 0;
char currentLastChar = '\\';

// Split input into parts of at most maxLength and not ending with an escape character
// Append each part to the StringBuilder
while (currentPosition + maxLength < input.length()) {
currentStringLength = maxLength;
currentLastChar = input.charAt(currentPosition + currentStringLength - 1);
if (currentLastChar == '\\') {
--currentStringLength;
}

builder.append(String.format(SPLIT_PART, input.substring(currentPosition, currentPosition + currentStringLength)));
currentPosition += currentStringLength;
}

// Append last part if necessary
if (currentPosition < input.length()) {
builder.append(String.format(SPLIT_PART, input.substring(currentPosition)));
}

// Close the builder and merge everything back to a string
builder.append(SPLIT_SUFFIX);
} else {
builder.append(String.format("\"%s\"", input));
}

writer.write(builder.toString());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package io.swagger.codegen.mustache;

import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;

import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import com.samskivert.mustache.Template.Fragment;

public class SplitStringLambdaTest {
private static final String INPUT_STRING = "1112223334";

private static final Map<Integer, String> EXPECTED_OUTPUTS;
static {
EXPECTED_OUTPUTS = new HashMap<>();
EXPECTED_OUTPUTS.put(2,
String.format(
"new StringBuilder(%d).append(\"11\").append(\"12\").append(\"22\").append(\"33\").append(\"34\").toString()",
INPUT_STRING.length()));
EXPECTED_OUTPUTS.put(3,
String.format(
"new StringBuilder(%d).append(\"111\").append(\"222\").append(\"333\").append(\"4\").toString()",
INPUT_STRING.length()));
}

private static final String INPUT_QUOTED_STRING = "1\\\"11\\\"2223\\\"334";
private static final String INPUT_QUOTED_OUTPUT = String.format(
"new StringBuilder(%d).append(\"1\\\"\").append(\"11\").append(\"\\\"2\").append(\"223\").append(\"\\\"3\").append(\"34\").toString()",
INPUT_QUOTED_STRING.length());

@Mock
private Fragment fragment;

@BeforeMethod
public void init() {
MockitoAnnotations.initMocks(this);
}

@AfterMethod
public void reset() {
Mockito.reset(fragment);
}

private void testString(String input, int maxLength, String expected) throws IOException {
when(fragment.execute()).thenReturn(input);

StringWriter output = new StringWriter();
new SplitStringLambda(maxLength).execute(fragment, output);
assertEquals(output.toString(), expected);
}

@Test
public void testSplitGroupsOf2() throws IOException {
int maxLength = 2;
testString(INPUT_STRING, maxLength, EXPECTED_OUTPUTS.get(maxLength));
}

@Test
public void testSplitGroupsOf3() throws IOException {
int maxLength = 3;
testString(INPUT_STRING, maxLength, EXPECTED_OUTPUTS.get(maxLength));
}

@Test
public void testSplitQuotedString() throws IOException {
int maxLength = 3;
testString(INPUT_QUOTED_STRING, maxLength, INPUT_QUOTED_OUTPUT);
}

@Test
public void testShortString() throws IOException {
testString(INPUT_STRING, INPUT_STRING.length(), String.format("\"%s\"", INPUT_STRING));
}

}

0 comments on commit 98b3cab

Please sign in to comment.