/*
* Copyright 2010.
*/
package ro.isdc.wro.extensions.processor.support.jsonhpack;
import java.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ro.isdc.wro.WroRuntimeException;
import ro.isdc.wro.extensions.script.RhinoScriptBuilder;
import ro.isdc.wro.util.StopWatch;
import ro.isdc.wro.util.WroUtil;
/**
* The underlying implementation use the json.hpack project: {@link https://github.com/WebReflection/json.hpack}.
*
* @author Alex Objelean
* @since 1.3.8
*/
public class JsonHPack {
private static final Logger LOG = LoggerFactory.getLogger(JsonHPack.class);
private static final String DEFAULT_JS = "json.hpack.min.js";
/**
* Initialize script builder for evaluation.
*/
private RhinoScriptBuilder initScriptBuilder() {
try {
return RhinoScriptBuilder.newClientSideAwareChain().addJSON().evaluateChain(
getScriptAsStream(), DEFAULT_JS);
} catch (final Exception e) {
LOG.error("Processing error:" + e.getMessage(), e);
throw new WroRuntimeException("Processing error", e);
}
}
/**
* @return stream of the script.
*/
protected InputStream getScriptAsStream() {
return JsonHPack.class.getResourceAsStream(DEFAULT_JS);
}
public String unpack(final String rawData) {
final StopWatch stopWatch = new StopWatch();
stopWatch.start("initContext");
final RhinoScriptBuilder builder = initScriptBuilder();
stopWatch.stop();
stopWatch.start("json.hunpack");
final boolean isEnclosedInDoubleArray = isEnclosedInDoubleArray(rawData);
String data = rawData;
if (!isEnclosedInDoubleArray) {
data = "[" + data + "]";
}
try {
final String execute = "JSON.stringify(JSON.hunpack(eval(" + WroUtil.toJSMultiLineString(data) + ")));";
final Object result = builder.evaluate(execute, "unpack");
String resultAsString = String.valueOf(result);
if (!isEnclosedInDoubleArray) {
//remove [] characters in which the json is enclosed
resultAsString = removeEnclosedArray(resultAsString);
}
return resultAsString;
} finally {
stopWatch.stop();
LOG.debug(stopWatch.prettyPrint());
}
}
/**
* @param data css content to process.
* @return processed css content.
*/
public String pack(final String rawData) {
final StopWatch stopWatch = new StopWatch();
stopWatch.start("initContext");
final RhinoScriptBuilder builder = initScriptBuilder();
stopWatch.stop();
stopWatch.start("json.hpack");
final boolean isEnclosedInArray = isEnclosedInArray(rawData);
String data = rawData;
if (!isEnclosedInArray) {
data = "[" + data + "]";
}
try {
final String execute = "JSON.stringify(JSON.hpack(eval(" + WroUtil.toJSMultiLineString(data) + "), 4));";
final Object result = builder.evaluate(execute, "pack");
String resultAsString = String.valueOf(result);
if (!isEnclosedInArray) {
//remove [] characters in which the json is enclosed
resultAsString = removeEnclosedArray(resultAsString);
}
return resultAsString;
} finally {
stopWatch.stop();
LOG.debug(stopWatch.prettyPrint());
}
}
/**
* Remove first and last occurrence of '[' and ']' characters.
*/
private String removeEnclosedArray(final String resultAsString) {
return resultAsString.replaceFirst("(?ims)\\[", "").replaceFirst("(?ims)\\](?!.*\\])", "");
}
/**
* Check if the string is enclosed with [] (array).
* @param rawData string to test.
*/
private boolean isEnclosedInArray(final String rawData) {
return rawData.matches("(?ims)^\\s*\\[.*\\]");
}
/**
* Check if the string is enclosed with [[]] (double array).
* @param rawData string to test.
*/
private boolean isEnclosedInDoubleArray(final String rawData) {
return rawData.matches("(?ims)^\\s*\\[\\[.*\\]\\]");
}
}