/*
   Copyright 2013, 2019, 2020 Nationale-Nederlanden, 2020-2021 WeAreFrank!

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
package nl.nn.adapterframework.pipes;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.json.XML;

import lombok.Getter;
import nl.nn.adapterframework.configuration.ConfigurationException;
import nl.nn.adapterframework.core.PipeLineSession;
import nl.nn.adapterframework.core.PipeRunException;
import nl.nn.adapterframework.core.PipeRunResult;
import nl.nn.adapterframework.doc.IbisDoc;
import nl.nn.adapterframework.stream.Message;
import nl.nn.adapterframework.util.TransformerPool;
import nl.nn.adapterframework.util.XmlUtils;

/**
 * Perform an JSON to XML transformation
 *
 * @author Martijn Onstwedder
 * @author Tom van der Heijden
 */

public class JsonPipe extends FixedForwardPipe {
	private @Getter Direction direction = Direction.JSON2XML;
	private @Getter String version = "2";
	private @Getter boolean addXmlRootElement=true;

	private TransformerPool tpXml2Json;
	
	public enum Direction {
		JSON2XML,
		XML2JSON;
	}

	@Override
	public void configure() throws ConfigurationException {
		super.configure();
		Direction dir = getDirection();
		if (dir == null) {
			throw new ConfigurationException("direction must be set");
		}
		if (dir == Direction.XML2JSON && "2".equals(getVersion())) {
			tpXml2Json = TransformerPool.configureStyleSheetTransformer(getLogPrefix(null), this, "/xml/xsl/xml2json.xsl", 0);
		}
	}

	@Override
	public PipeRunResult doPipe(Message message, PipeLineSession session) throws PipeRunException {

		if (message == null) {
			throw new PipeRunException(this, getLogPrefix(session) + "got null input");
		}

		try {
			String stringResult=null;
			String actualVersion = getVersion();
			
			switch (getDirection()) {
			case JSON2XML:
				stringResult = message.asString();
				JSONTokener jsonTokener = new JSONTokener(stringResult);
				if (stringResult.startsWith("{")) {
					JSONObject jsonObject = new JSONObject(jsonTokener);
					stringResult = XML.toString(jsonObject);
				}
				if (stringResult.startsWith("[")) {
					JSONArray jsonArray = new JSONArray(jsonTokener);
					stringResult = XML.toString(jsonArray);
				}

				if(isAddXmlRootElement()) {
					boolean isWellFormed = XmlUtils.isWellFormed(stringResult);
					if (!isWellFormed) {
						stringResult = "<root>" + stringResult + "</root>";
					}
				}
				break;
			case XML2JSON:
				if ("2".equals(actualVersion)) {
					stringResult = tpXml2Json.transform(message,null);
				} else {
					JSONObject jsonObject = XML.toJSONObject(message.asString());
					stringResult = jsonObject.toString();
				}
				break;
			default:
				throw new IllegalStateException("unknown direction ["+getDirection()+"]");
			}
			return new PipeRunResult(getSuccessForward(), stringResult);
		} catch (Exception e) {
			throw new PipeRunException(this, getLogPrefix(session) + " Exception on transforming input", e);
		}
	}

	@IbisDoc({"Direction of the transformation.", "json2xml"})
	public void setDirection(Direction value) {
		direction = value;
	}

	@IbisDoc({"Version of the jsonpipe. Either 1 or 2.", "2"})
	public void setVersion(String version) {
		this.version = version;
	}

	@IbisDoc({"when true, and direction is json2xml, it wraps a root element around the converted message", "true"})
	public void setAddXmlRootElement(boolean addXmlRootElement) {
		this.addXmlRootElement = addXmlRootElement;
	}
}

@@ -57,17 +57,17 @@
 2020-202
-1
+2
  WeAreFr
@@ -1214,45 +1214,241 @@
 %0A * 
-P
+JSON is not aware of the element order. This pipe p
 erform
+s
  a
-n JSON to XML transformation
+ %3Cstrong%3Ebest effort%3C/strong%3E JSON to XML transformation. %0A * If you wish to validate or add structure to the converted (xml) file, please use the %7B@link Json2XmlValidator%7D.
 %0A *%0A
@@ -1512,17 +1512,16 @@
 den%0A */%0A
-%0A
 public c
@@ -1746,18 +1746,17 @@
 l2Json;%0A
-%09
 %0A
+
 %09public 
@@ -1889,16 +1889,17 @@
 gure();%0A
+%0A
 %09%09Direct
@@ -2459,52 +2459,9 @@
 ll;%0A
-%09%09%09String actualVersion = getVersion();%0A%09%09%09
 %0A
+
 %09%09%09s
@@ -3146,21 +3146,20 @@
 als(
-actual
+get
 Version
+()
 )) %7B
@@ -3451,16 +3451,17 @@
 );%0A%09%09%09%7D%0A
+%0A
 %09%09%09retur
@@ -3698,24 +3698,24 @@
 ion.%22, %22
-json2xml
+JSON2XML
 %22%7D)%0A%09pub
@@ -3811,13 +3811,13 @@
 the 
-jsonp
+JsonP
 ipe.
@@ -3924,17 +3924,17 @@
 isDoc(%7B%22
-w
+W
 hen true

Update FrankDoc for JsonPipe (#2717)