package com.sas.unravl.generators;
import com.fasterxml.jackson.databind.JsonNode;
import com.sas.unravl.UnRAVL;
import com.sas.unravl.UnRAVLException;
import com.sas.unravl.util.Json;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
/**
* This class produces text from a JSON text specification. This may be used for
* a text ResponseBodyGenerator or a TextAssertion.
*
* <pre>
* { "key" : "text-value" }
* { "key" : "@fileOrUrl" }
* { "key" : array-of-text }
* </pre>
*
* <p>
* In the first form, the text is expressed as a single JSON string.
* </p>
* <p>
* In the second form, the text is read from a text file or a URL. The text is
* assumed to be in UTF-8 encoding.
* </p>
* <p>
* In the third form, Text will combine texts in an array. Each element of the
* array may be a text-value or a <code>{@literal @}file-or-url</code> or a
* nested array. The values are separated by a newline. If you want a trailing
* newline, the last value should be the empty string, "".
* </p>
* <p>
* TODO: add an <code>"encoding" : <em>encoding-name</em></code>
* </p>
*
* @author David.Biesack@sas.com
*
*/
public class Text implements CharSequence {
private static final int BUFSIZE = 256;
public static final Charset UTF_8 = Charset.forName("UTF-8");
StringBuilder text = new StringBuilder();
private final UnRAVL script;
public Text(UnRAVL script) {
this.script = script;
}
public Text(UnRAVL script, JsonNode node, String key) throws IOException,
UnRAVLException {
this(script, node.get(key));
}
public Text(UnRAVL script, JsonNode node) throws IOException,
UnRAVLException {
this(script);
build(node);
}
public Text(UnRAVL script, String text) throws IOException, UnRAVLException {
this(script);
build(text);
}
private void build(JsonNode node) throws IOException, UnRAVLException {
if (node == null) {
} else if (node.isTextual()) {
build(node.textValue());
} else if (node.isArray()) {
String delimiter = "";
for (JsonNode each : Json.array(node)) {
text.append(delimiter);
build(each);
delimiter = "\n";
}
}
}
private void build(String textValue) throws IOException {
if (textValue.startsWith(UnRAVL.REDIRECT_PREFIX)) {
String expanded = script.expand(textValue
.substring(UnRAVL.REDIRECT_PREFIX.length()));
buildFromStream(expanded);
} else {
text.append(textValue);
}
}
private void buildFromStream(String fileOrURL) throws IOException {
InputStream is = null;
try {
URL url = new URL(fileOrURL);
is = url.openStream();
} catch (MalformedURLException e) {
File f = new File(fileOrURL);
if (f.exists()) {
is = new FileInputStream(f);
} else {
is = getClass().getResourceAsStream(fileOrURL);
}
}
if (is == null) {
throw new IOException("No such file or URL " + fileOrURL);
}
Reader r = new InputStreamReader(is, UTF_8);
char buffer[] = new char[BUFSIZE];
BufferedReader br = new BufferedReader(r);
for (int n = br.read(buffer, 0, BUFSIZE); n > 0; n = br.read(buffer, 0,
BUFSIZE))
text.append(buffer, 0, n);
br.close();
}
public Reader reader() {
return new StringReader(text());
}
@Override
public char charAt(int index) {
return text.charAt(index);
}
@Override
public int length() {
return text.length();
}
@Override
public CharSequence subSequence(int start, int length) {
return text.subSequence(start, length);
}
public String text() {
return text.toString();
}
@Override
public String toString() {
return text();
}
@Override
public int hashCode() {
return text.hashCode();
}
@Override
public boolean equals(Object other) {
if (other == null)
return false;
else if (other instanceof Text) {
return text.equals(((Text) other).text());
} else
return false;
}
/**
* Utility method to extract a byte array from a string, using UTF-8
* encoding. This method ignores the UnsupportedEncodingException because
* all JRE's are required to support the UTF-8 encoding.
*
* @param s
* a string
* @return the UTF-8 encoding of the string, as a byte array
*/
public static byte[] utf8(String s) {
return s.getBytes(UTF_8);
}
/**
* Utility method to crate a string from a UTF-8 encoded byte array This
* method ignores the UnsupportedEncodingException because all JRE's are
* required to support the UTF-8 encoding.
*
* @param byteArray
* input bytes which must be a UTF-8 encoding
* @return the string
* @throws IllegalArgumentException
* if the bytes could not be converted to a string with UTF-8
*/
public static String utf8ToString(byte[] byteArray) {
return new String(byteArray, UTF_8);
}
/**
* Encode text using URL UTF-8 encoding.
*
* @param text
* input text string
* @return the encoded text
* @throws IllegalStateException
* if the string could not be encoded with UTF-8
*/
public static String urlEncode(String text) {
String encoded;
try {
encoded = URLEncoder.encode(text, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(
"Could not encode string to URL UTF-8 encoding");
}
return encoded;
}
}