<commit_before>/*
 * Copyright (C) 2011-2015 by <NAME> <<EMAIL>>
 * Copyright (C) 2013 by <NAME>
 * Copyright (C) 2015 by <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library 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
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

package jolie.js;

import java.io.IOException;
import java.io.Reader;
import java.util.Map;
import jolie.runtime.Value;
import jolie.runtime.ValueVector;
import jolie.runtime.typing.Type;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;

public class JsUtils
{
	/**
	 * Jolie values consist of a root value with optional attribute/child
	 * values. JSON defines primitive values, arrays and objects. JSON objects
	 * may contain attributes, but no root value. For this reason Jolie
	 * introduces a "ROOT_SIGN" named attribute on each mapped Jolie value with
	 * a root value set.
	 */
	private static final String ROOT_SIGN = "$";

	/**
	 * Jolie values do not support multi-dimensional arrays as JSON, hence
	 * val[i][j] in Jolie becomes val._[i]._[j] with two nested single-
	 * dimensional arrays "JSONARRAY_KEY".
	 */
	public static final String JSONARRAY_KEY = "_";

    // Jolie value -> JSON string
	private static void appendKeyColon( StringBuilder builder, String key )
	{
		builder.append( '"' ).append( key ).append( "\":" );
	}

	private static String nativeValueToJsonString( Value value ) throws IOException
	{
		if ( !value.isDefined() ) {
			return "null";
		} else if ( value.isInt() || value.isLong() || value.isBool() || value.isDouble() ) {
			return value.strValue();
		} else {
			return '"' + JSONValue.escape( value.strValue() ) + '"';
		}
	}

	private static void valueVectorToJsonString( ValueVector vector, StringBuilder builder, boolean isArray, Type type )
		throws IOException
	{
		if ( isArray || (type != null && type.cardinality().max() > 1 && vector.size() > 1) ) {
			builder.append( '[' );
			for( int i = 0; i < vector.size(); i++ ) {
				valueToJsonString( vector.get( i ), false, type, builder );
				if ( i < vector.size() - 1 ) {
					builder.append( ',' );
				}
			}
			builder.append( ']' );
		} else {
			valueToJsonString( vector.first(), false, type, builder );
		}
	}

	public static void valueToJsonString( Value value, boolean extendedRoot, Type type, StringBuilder builder ) throws IOException
	{
		if ( value.hasChildren( JSONARRAY_KEY ) ) {
			valueVectorToJsonString( value.children().get( JSONARRAY_KEY ), builder, true, null );
			return;
		}
		int size = value.children().size();
		if ( size == 0 ) {
			if ( extendedRoot ) {
				builder.append( '{' );
				if ( value.isDefined() ) {
					appendKeyColon( builder, ROOT_SIGN );
					builder.append( nativeValueToJsonString( value ) );
				}
				builder.append( '}' );
			} else {
				builder.append( nativeValueToJsonString( value ) );
			}
		} else {
			builder.append( '{' );
			if ( value.isDefined() ) {
				appendKeyColon( builder, ROOT_SIGN );
				builder.append( nativeValueToJsonString( value ) );
				builder.append( ',' );
			}
			int i = 0;
			for( Map.Entry<String, ValueVector> child : value.children().entrySet() ) {
				final Type subType = type.findSubType( child.getKey() );
				appendKeyColon( builder, child.getKey() );<commit_msg>Check for type null pointers in jolie-js.<commit_after>/*
 * Copyright (C) 2011-2015 by <NAME> <<EMAIL>>
 * Copyright (C) 2013 by <NAME>
 * Copyright (C) 2015 by <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library 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
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

package jolie.js;

import java.io.IOException;
import java.io.Reader;
import java.util.Map;
import jolie.runtime.Value;
import jolie.runtime.ValueVector;
import jolie.runtime.typing.Type;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;

public class JsUtils
{
	/**
	 * Jolie values consist of a root value with optional attribute/child
	 * values. JSON defines primitive values, arrays and objects. JSON objects
	 * may contain attributes, but no root value. For this reason Jolie
	 * introduces a "ROOT_SIGN" named attribute on each mapped Jolie value with
	 * a root value set.
	 */
	private static final String ROOT_SIGN = "$";

	/**
	 * Jolie values do not support multi-dimensional arrays as JSON, hence
	 * val[i][j] in Jolie becomes val._[i]._[j] with two nested single-
	 * dimensional arrays "JSONARRAY_KEY".
	 */
	public static final String JSONARRAY_KEY = "_";

    // Jolie value -> JSON string
	private static void appendKeyColon( StringBuilder builder, String key )
	{
		builder.append( '"' ).append( key ).append( "\":" );
	}

	private static String nativeValueToJsonString( Value value ) throws IOException
	{
		if ( !value.isDefined() ) {
			return "null";
		} else if ( value.isInt() || value.isLong() || value.isBool() || value.isDouble() ) {
			return value.strValue();
		} else {
			return '"' + JSONValue.escape( value.strValue() ) + '"';
		}
	}

	private static void valueVectorToJsonString( ValueVector vector, StringBuilder builder, boolean isArray, Type type )
		throws IOException
	{
		if ( isArray || (type != null && type.cardinality().max() > 1 && vector.size() > 1) ) {
			builder.append( '[' );
			for( int i = 0; i < vector.size(); i++ ) {
				valueToJsonString( vector.get( i ), false, type, builder );
				if ( i < vector.size() - 1 ) {
					builder.append( ',' );
				}
			}
			builder.append( ']' );
		} else {
			valueToJsonString( vector.first(), false, type, builder );
		}
	}

	public static void valueToJsonString( Value value, boolean extendedRoot, Type type, StringBuilder builder ) throws IOException
	{
		if ( value.hasChildren( JSONARRAY_KEY ) ) {
			valueVectorToJsonString( value.children().get( JSONARRAY_KEY ), builder, true, null );
			return;
		}
		int size = value.children().size();
		if ( size == 0 ) {
			if ( extendedRoot ) {
				builder.append( '{' );
				if ( value.isDefined() ) {
					appendKeyColon( builder, ROOT_SIGN );
					builder.append( nativeValueToJsonString( value ) );
				}
				builder.append( '}' );
			} else {
				builder.append( nativeValueToJsonString( value ) );
			}
		} else {
			builder.append( '{' );
			if ( value.isDefined() ) {
				appendKeyColon( builder, ROOT_SIGN );
				builder.append( nativeValueToJsonString( value ) );
				builder.append( ',' );
			}
			int i = 0;
			for( Map.Entry<String, ValueVector> child : value.children().entrySet() ) {
				final Type subType = ( type != null ? type.findSubType( child.getKey() ) : null );
				appendKeyColon( builder, child.getKey() );
{'fraction_non_alphanumeric': 0.12168644281747033, 'fraction_numerical': 0.008836152486745772, 'mean_word_length': 3.556066705002875, 'pattern_counts': {'":': 2, '<': 19, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '657115', 'n_tokens_mistral': 2638, 'n_tokens_neox': 2346, 'n_words': 803}