PyonParser.java
/*
* #%L
* This file is part of jFold.
* %%
* Copyright (C) 2012 - 2019 Mike Thomas <mikepthomas@outlook.com>
* %%
* jFold is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* %
* jFold is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* %
* You should have received a copy of the GNU General Public License
* along with jFold. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package info.mikethomas.jfold.util;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.XSlf4j;
/**
* <p>PyonParser class.</p>
*
* @author Michael Thomas (mikepthomas@outlook.com)
* @version 7.5.1
*/
@XSlf4j
@UtilityClass
public final class PyonParser {
/** Constant <code>PYON_1</code>. */
public static final String PYON_1 = "\nPyON 1 ";
/** Constant <code>PYON_HEADER</code>. */
public static final String PYON_HEADER = PYON_1 + "(.*)\n";
/** Constant <code>PYON_TRAILER</code>. */
public static final String PYON_TRAILER = "\n---";
/** Constant <code>ERROR</code>. */
public static final String ERROR = "error";
/** Constant <code>PYON_ERROR</code>. */
public static final String PYON_ERROR = PYON_HEADER.replace("(.*)", ERROR);
/** Constant <code>NONE</code>. */
public static final String NONE = "\"(.*)\": None";
/** Constant <code>NULL</code>. */
public static final String NULL = "\"$1\": null";
/** Constant <code>JSON_TRUE</code>. */
public static final String JSON_TRUE = "\"$1\": true";
/** Constant <code>PYON_TRUE</code>. */
public static final String PYON_TRUE = "\"(.*)\": True";
/** Constant <code>STRING_TRUE</code>. */
public static final String STRING_TRUE = "\"(.*)\": \"true\"";
/** Constant <code>JSON_FALSE</code>. */
public static final String JSON_FALSE = "\"$1\": false";
/** Constant <code>PYON_FALSE</code>. */
public static final String PYON_FALSE = "\"(.*)\": False";
/** Constant <code>STRING_FALSE</code>. */
public static final String STRING_FALSE = "\"(.*)\": \"false\"";
/**
* <p>Convert a PyON String to JSON.</p>
*
* @param pyon a {@link java.lang.String} object.
* @return a {@link java.lang.String} object.
*/
public String convert(final String pyon) {
log.entry(pyon);
// Check for valid PyON String
if (!pyon.startsWith(PYON_1)) {
log.warn("PyonParser cannot convert String: {}", pyon);
return pyon;
}
// Get PyON Body
var json = pyon
.replaceAll(PYON_HEADER, "")
.replaceAll(PYON_TRAILER, "");
// Check for PyON Error Message
if (pyon.contains(PYON_ERROR)) {
json = json.replaceAll("\"", "");
}
// Add '\n' to make format of PyON to JSON replacements nicer
json = json
.replaceAll("\\[", "[\n") // New Line after Start Array
.replaceAll("\\]", "\n]") // New Line after End Array
.replaceAll("\\{", "{\n") // New Line after Start Object
.replaceAll("\\}", "\n}") // New Line after End Object
.replaceAll(", ", ",\n");
// None is used instead of null
json = json.replaceAll(NONE, NULL);
// Boolean values start with an upper case letter as in Python.
json = json
.replaceAll(PYON_TRUE, JSON_TRUE)
.replaceAll(STRING_TRUE, JSON_TRUE)
.replaceAll(PYON_FALSE, JSON_FALSE)
.replaceAll(STRING_FALSE, JSON_FALSE);
// Format JSON
var mapper = JacksonUtil.getObjectMapper();
var writer = mapper.writerWithDefaultPrettyPrinter();
try {
var jsonNode = mapper.readValue(json, JsonNode.class);
json = writer.writeValueAsString(jsonNode);
} catch (IOException ex) {
log.error("Unable to format json string", ex);
}
return log.exit(json);
}
}