<commit_before>package com.mongodb.rhino;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.bson.BSONObject;
import org.bson.types.ObjectId;
import org.bson.types.Symbol;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

import com.mongodb.BasicDBObject;

/**
 * Direct conversion between native Rhino objects and BSON.
 * <p>
 * This class can be used directly in Rhino.
 * 
 * @author <NAME>
 */
public class BSON
{
	//
	// Static operations
	//

	/**
	 * Convert from native Rhino to BSON.
	 * 
	 * @param object
	 *        A Rhino native object
	 * @return A BSON object
	 */
	public static BSONObject to( ScriptableObject object )
	{
		BasicDBObject bson = new BasicDBObject();

		Object[] ids = object.getAllIds();
		for( Object id : ids )
		{
			String key = id.toString();
			Object value = forBson( ScriptableObject.getProperty( object, key ), key );
			bson.put( key, value );
		}

		return bson;
	}

	/**
	 * Convert from BSON to native Rhino.
	 * 
	 * @param bson
	 *        A BSON object
	 * @return A Rhino native object
	 */
	public static NativeObject from( BSONObject bson )
	{
		if( bson == null )
			return null;

		NativeObject object = new NativeObject();

		for( String key : bson.keySet() )
		{
			Object value = forRhino( bson.get( key ) );
			ScriptableObject.putProperty( object, key, value );
		}

		return object;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Private

	/**
	 * If necessary, convert from native Rhino to a type supported by BSON.
	 * 
	 * @param object
	 *        An object
	 * @param key
	 *        The key used for the object (optional)
	 * @return An object ready to be put inside a BSON object
	 */
	private static Object forBson( Object object, String key )
	{
		if( object instanceof NativeJavaObject )
		{
			// This happens either because the developer purposely creates a
			// Java object, or because it was returned from a Java call and
			// wrapped by Rhino.

			return ( (NativeJavaObject) object ).unwrap();
		}
		else if( object instanceof NativeArray )
		{
			// Convert Rhino array to list

			NativeArray array = (NativeArray) object;
			int length = (int) array.getLength();
			List<Object> list = new ArrayList<Object>( length );

			for( int i = 0; i < length; i++ )
				list.add( forBson( ScriptableObject.getProperty( array, i ), null ) );

			return list;
		}
		else if( object instanceof ScriptableObject )
		{
			ScriptableObject scriptable = (ScriptableObject) object;
			if( scriptable.getClassName().equals( "Date" ) )
			{
				// The NativeDate class is private in Rhino, but we can access
				// it like a regular object.

				Object time = ScriptableObject.callMethod( scriptable, "getTime", null );
				if( time instanceof Number )
					return new Date( ( (Number) time ).longValue() );
			}

			// Convert

			return to( scriptable );
		}
		else if( "_id".equals( key ) )
		{
			return new ObjectId( object.toString() );<commit_msg>Add support for JavaScript "undefined" type (issue #2)<commit_after>package com.mongodb.rhino;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.bson.BSONObject;
import org.bson.types.ObjectId;
import org.bson.types.Symbol;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Undefined;

import com.mongodb.BasicDBObject;

/**
 * Direct conversion between native Rhino objects and BSON.
 * <p>
 * This class can be used directly in Rhino.
 * 
 * @author <NAME>
 */
public class BSON
{
	//
	// Static operations
	//

	/**
	 * Convert from native Rhino to BSON.
	 * 
	 * @param object
	 *        A Rhino native object
	 * @return A BSON object
	 */
	public static BSONObject to( ScriptableObject object )
	{
		BasicDBObject bson = new BasicDBObject();

		Object[] ids = object.getAllIds();
		for( Object id : ids )
		{
			String key = id.toString();
			Object value = forBson( ScriptableObject.getProperty( object, key ), key );
			bson.put( key, value );
		}

		return bson;
	}

	/**
	 * Convert from BSON to native Rhino.
	 * 
	 * @param bson
	 *        A BSON object
	 * @return A Rhino native object
	 */
	public static NativeObject from( BSONObject bson )
	{
		if( bson == null )
			return null;

		NativeObject object = new NativeObject();

		for( String key : bson.keySet() )
		{
			Object value = forRhino( bson.get( key ) );
			ScriptableObject.putProperty( object, key, value );
		}

		return object;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Private

	/**
	 * If necessary, convert from native Rhino to a type supported by BSON.
	 * 
	 * @param object
	 *        An object
	 * @param key
	 *        The key used for the object (optional)
	 * @return An object ready to be put inside a BSON object
	 */
	private static Object forBson( Object object, String key )
	{
		if( object instanceof NativeJavaObject )
		{
			// This happens either because the developer purposely creates a
			// Java object, or because it was returned from a Java call and
			// wrapped by Rhino.

			return ( (NativeJavaObject) object ).unwrap();
		}
		else if( object instanceof NativeArray )
		{
			// Convert Rhino array to list

			NativeArray array = (NativeArray) object;
			int length = (int) array.getLength();
			List<Object> list = new ArrayList<Object>( length );

			for( int i = 0; i < length; i++ )
				list.add( forBson( ScriptableObject.getProperty( array, i ), null ) );

			return list;
		}
		else if( object instanceof ScriptableObject )
		{
			ScriptableObject scriptable = (ScriptableObject) object;
			if( scriptable.getClassName().equals( "Date" ) )
			{
				// The NativeDate class is private in Rhino, but we can access
				// it like a regular object.

				Object time = ScriptableObject.callMethod( scriptable, "getTime", null );
				if( time instanceof Number )
					return new Date( ( (Number) time ).longValue() );
			}

			// Convert

			return to( scriptable );
		}
		else if( object instanceof Undefined )
		{
			return null;
		}
		else if( "_id".equals( key ) )
		{
			return new ObjectId( object.toString() );
{'fraction_non_alphanumeric': 0.1266736873777644, 'fraction_numerical': 0.00045133142771174966, 'mean_word_length': 2.838337182448037, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, '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': '2400721', 'n_tokens_mistral': 2233, 'n_tokens_neox': 1949, 'n_words': 654}