<commit_before>/*
 * Copyright 2004-2005 the original author or authors.
 * 
 * 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 org.codehaus.groovy.grails.web.servlet.mvc;

import groovy.lang.Closure;
import groovy.lang.GroovyObject;
import groovy.lang.ProxyMetaClass;
import groovy.util.Proxy;

import java.beans.IntrospectionException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//import org.apache.commons.lang.WordUtils;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsControllerClass;
import org.codehaus.groovy.grails.metaclass.GenericDynamicProperty;
import org.codehaus.groovy.grails.metaclass.PropertyAccessProxyMetaClass;
import org.codehaus.groovy.grails.web.metaclass.ChainDynamicMethod;
import org.codehaus.groovy.grails.web.metaclass.ControllerDynamicMethodsInterceptor;
import org.codehaus.groovy.grails.web.metaclass.GetParamsDynamicProperty;
import org.codehaus.groovy.grails.web.servlet.GrailsHttpServletRequest;
import org.codehaus.groovy.grails.web.servlet.GrailsHttpServletResponse;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.ControllerExecutionException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.IncompatibleParameterCountException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.NoClosurePropertyForURIException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.NoViewNameDefinedException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.UnknownControllerException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.UnsupportedReturnValueException;
import org.springframework.context.ApplicationContext;
import org.springframework.web.servlet.ModelAndView;

public class SimpleGrailsControllerHelper implements GrailsControllerHelper {

	private GrailsApplication application;
	private ApplicationContext applicationContext;
	private Map chainModel = Collections.EMPTY_MAP;

	public SimpleGrailsControllerHelper(GrailsApplication application, ApplicationContext context) {
		super();
		this.application = application;
		this.applicationContext = context;
	}

	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#getControllerClassByName(java.lang.String)
	 */
	public GrailsControllerClass getControllerClassByName(String name) {
		return this.application.getController(name);
	}
	
	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#getControllerClassByURI(java.lang.String)
	 */
	public GrailsControllerClass getControllerClassByURI(String uri) {
		return this.application.getControllerByURI(uri);
	}
	
	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#getControllerInstance(org.codehaus.groovy.grails.commons.GrailsControllerClass)
	 */
	public GroovyObject getControllerInstance(GrailsControllerClass controllerClass) {
		return (GroovyObject)this.applicationContext.getBean(controllerClass.getFullName());
	}
	
	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#handleURI(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	public ModelAndView handleURI(String uri, HttpServletRequest request, HttpServletResponse response) {
		return handleURI(uri,request,response,Collections.EMPTY_MAP);
	}
	
	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#handleActionResponse(org.codehaus.groovy.grails.commons.GrailsControllerClass, java.lang.Object, java.lang.String, java.lang.String)
	 */
	public ModelAndView handleActionResponse( GrailsControllerClass controllerClass,Object returnValue,String closurePropertyName, String viewName) {
		boolean viewNameBlank = (viewName == null || viewName.length() == 0);
		
		if (returnValue == null) {
			if (viewNameBlank) {
				return null;
			} else {
				return new ModelAndView(viewName);
			}
		} else if (returnValue instanceof Map) {
			// remove any Proxy wrappers and set the adaptee as the value
			removeProxiesFromModelObjects((Map)returnValue);
			if (viewNameBlank) {
				throw new NoViewNameDefinedException("Map instance returned by and no view name specified for closure on property [" + closurePropertyName + "] in controller [" + controllerClass.getFullName() + "]!");
			} else {
				Map returnMap = (Map)returnValue;
				if(!this.chainModel.isEmpty()) {
					this.chainModel.putAll( returnMap );
					return new ModelAndView(viewName, this.chainModel);
				}
				else {
					return new ModelAndView(viewName, returnMap);
				}
			}
		} else if (returnValue instanceof ModelAndView) {
			ModelAndView modelAndView = (ModelAndView)returnValue;
			
			// remove any Proxy wrappers and set the adaptee as the value
			Map modelMap = modelAndView.getModel();
			removeProxiesFromModelObjects(modelMap);
			if(!this.chainModel.isEmpty()) {
				this.chainModel.putAll(modelMap);
				modelAndView.addAllObjects(this.chainModel);
			}
			
			if (modelAndView.getView() == null && modelAndView.getViewName() == null) {
				if (viewNameBlank) {
					throw new NoViewNameDefinedException("ModelAndView instance returned by and no view name defined by nor for closure on property [" + closurePropertyName + "] in controller [" + controllerClass.getFullName() + "]!");
				} else {
					modelAndView.setViewName(viewName);
				}
			}
			return modelAndView;
		}
		
		throw new UnsupportedReturnValueException("Return value [" + returnValue + "] is not supported for closure property [" + closurePropertyName + "] in controller [" + controllerClass.getFullName() + "]!");
	}

	/**
	 * If in Proxy's are used in the Groovy context, unproxy (is that a word?) them by setting
	 * the adaptee as the value in the map so that they can be used in non-groovy view technologies
	 *   
	 * @param model The model as a map
	 */
	private void removeProxiesFromModelObjects(Map model) {
		
		for (Iterator keyIter = model.keySet().iterator(); keyIter.hasNext();) {
			Object current = keyIter.next();
			Object modelObject = model.get(current);
			if(modelObject instanceof Proxy) {
				model.put( current, ((Proxy)modelObject).getAdaptee() );
			}			
		}
	}

	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#handleURI(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.util.Map)
	 */
	public ModelAndView handleURI(String uri, HttpServletRequest request, HttpServletResponse response, Map params) {
		if(uri == null)
			throw new IllegalArgumentException("Controller URI [" + uri + "] cannot be null!");
		
		// step 1: process the uri
		if (uri.indexOf("?") > -1) {
			uri = uri.substring(0, uri.indexOf("?"));
		}		
		if(!uri.startsWith("/"))
			uri = '/' + uri;
		if(uri.endsWith("/"))
			uri = uri.substring(0,uri.length() - 2);
		
		// Step 2: lookup the controller in the application.
		GrailsControllerClass controllerClass = getControllerClassByURI(uri);
		if (controllerClass == null) {
			throw new UnknownControllerException("No controller found for URI [" + uri + "]!");
		}
		//String controllerName = WordUtils.uncapitalize(controllerClass.getName());
		
		// Step 3: load controller from application context.
		GroovyObject controller = getControllerInstance(controllerClass);
		
		// Step 4: get closure property name for URI.
		String closurePropertyName = controllerClass.getClosurePropertyName(uri);
		if (closurePropertyName == null) {
			throw new NoClosurePropertyForURIException("Could not find closure property for URI [" + uri + "] for controller [" + controllerClass.getFullName() + "]!");
		}
		
		// Step 5: get the view name for this URI.
		String viewName = controllerClass.getViewByURI(uri);
		
		
		// Step 6: get closure from closure property
		Closure closure = (Closure)controller.getProperty(closurePropertyName);
		
		// Step 7: process the action
		Object returnValue = handleAction( controller,closure,request,response,params );

		
		// Step 8: determine return value type and handle accordingly
		return handleActionResponse(controllerClass,returnValue,closurePropertyName,viewName);
	}

	public void setChainModel(Map model) {
		this.chainModel  = model;
	}

	public Object handleAction(GroovyObject controller,Closure action, HttpServletRequest request, HttpServletResponse response) {
		return handleAction(controller,action,request,response,Collections.EMPTY_MAP);
	}

	public Object handleAction(GroovyObject controller,Closure action, HttpServletRequest request, HttpServletResponse response, Map params) {
		// Step 3a: Configure a proxy interceptor for controller dynamic methods for this request
		try {
			ControllerDynamicMethodsInterceptor interceptor;
			if(!controller.getMetaClass().getClass().equals( PropertyAccessProxyMetaClass.class )) {
				ProxyMetaClass pmc = PropertyAccessProxyMetaClass.getInstance(controller.getClass());
				interceptor = new ControllerDynamicMethodsInterceptor(controller.getClass(),this,request,response);

				pmc.setInterceptor( interceptor );
				controller.setMetaClass(pmc);				
			}
			else {
				ProxyMetaClass pmc = (ProxyMetaClass)controller.getMetaClass(); 
				interceptor = (ControllerDynamicMethodsInterceptor)pmc.getInterceptor(); 
			}
			// if there are additional params add them to the params dynamic property
			if(params != null && !params.isEmpty()) {
				GetParamsDynamicProperty paramsProp = (GetParamsDynamicProperty)interceptor.getDynamicProperty( GetParamsDynamicProperty.PROPERTY_NAME );
				paramsProp.addParams( params );
			}			
			// check the chain model is not empty and add it
			if(!this.chainModel.isEmpty()) {
				// get the "chainModel" property
				GenericDynamicProperty chainProperty = (GenericDynamicProperty)interceptor.getDynamicProperty(ChainDynamicMethod.PROPERTY_CHAIN_MODEL);
				// if it doesn't exist create it
				if(chainProperty == null) {			
					interceptor.addDynamicProperty( new GenericDynamicProperty( ChainDynamicMethod.PROPERTY_CHAIN_MODEL,Map.class,this.chainModel,false ) );
				}
				else {
					// otherwise add to it
					Map chainPropertyModel = (Map)chainProperty.getValue();
					chainPropertyModel.putAll( this.chainModel );
					this.chainModel = chainPropertyModel;
				}
			}

		}
		catch(IntrospectionException ie) {
			throw new ControllerExecutionException("Error creating dynamic controller methods for controller ["+controller.getClass()+"]: " + ie.getMessage(), ie);
		}
		
		// Step 7: determine argument count and execute.
		Object returnValue = null;
		if (action.getParameterTypes().length == 1) {
			// closure may have zero or one parameter, we cannot be sure.
			returnValue = action.call(new GrailsHttpServletRequest(request));
		} else if (action.getParameterTypes().length == 2) {
			returnValue = action.call(new Object[] { new  GrailsHttpServletRequest(request), new GrailsHttpServletResponse(response) });
		} else {
			throw new IncompatibleParameterCountException("Closure on property [" + action + "] in [" + controller.getClass() + "] has an incompatible parameter count [" + action.getParameterTypes().length + "]! Supported values are 0 and 2.");			
		}
		return returnValue;
	}
	
}
<commit_msg>moved logic for configurion the meta class interceptor into the interceptor itself<commit_after>/*
 * Copyright 2004-2005 the original author or authors.
 * 
 * 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 org.codehaus.groovy.grails.web.servlet.mvc;

import groovy.lang.Closure;
import groovy.lang.GroovyObject;
import groovy.lang.ProxyMetaClass;
import groovy.util.Proxy;

import java.beans.IntrospectionException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//import org.apache.commons.lang.WordUtils;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsControllerClass;
import org.codehaus.groovy.grails.commons.metaclass.GenericDynamicProperty;
import org.codehaus.groovy.grails.commons.metaclass.PropertyAccessProxyMetaClass;
import org.codehaus.groovy.grails.web.metaclass.ChainDynamicMethod;
import org.codehaus.groovy.grails.web.metaclass.ControllerDynamicMethodsInterceptor;
import org.codehaus.groovy.grails.web.metaclass.GetParamsDynamicProperty;
import org.codehaus.groovy.grails.web.servlet.GrailsHttpServletRequest;
import org.codehaus.groovy.grails.web.servlet.GrailsHttpServletResponse;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.ControllerExecutionException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.IncompatibleParameterCountException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.NoClosurePropertyForURIException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.NoViewNameDefinedException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.UnknownControllerException;
import org.codehaus.groovy.grails.web.servlet.mvc.exceptions.UnsupportedReturnValueException;
import org.springframework.context.ApplicationContext;
import org.springframework.web.servlet.ModelAndView;

public class SimpleGrailsControllerHelper implements GrailsControllerHelper {

	private GrailsApplication application;
	private ApplicationContext applicationContext;
	private Map chainModel = Collections.EMPTY_MAP;

	public SimpleGrailsControllerHelper(GrailsApplication application, ApplicationContext context) {
		super();
		this.application = application;
		this.applicationContext = context;
	}

	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#getControllerClassByName(java.lang.String)
	 */
	public GrailsControllerClass getControllerClassByName(String name) {
		return this.application.getController(name);
	}
	
	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#getControllerClassByURI(java.lang.String)
	 */
	public GrailsControllerClass getControllerClassByURI(String uri) {
		return this.application.getControllerByURI(uri);
	}
	
	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#getControllerInstance(org.codehaus.groovy.grails.commons.GrailsControllerClass)
	 */
	public GroovyObject getControllerInstance(GrailsControllerClass controllerClass) {
		return (GroovyObject)this.applicationContext.getBean(controllerClass.getFullName());
	}
	
	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#handleURI(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	public ModelAndView handleURI(String uri, HttpServletRequest request, HttpServletResponse response) {
		return handleURI(uri,request,response,Collections.EMPTY_MAP);
	}
	
	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#handleActionResponse(org.codehaus.groovy.grails.commons.GrailsControllerClass, java.lang.Object, java.lang.String, java.lang.String)
	 */
	public ModelAndView handleActionResponse( GrailsControllerClass controllerClass,Object returnValue,String closurePropertyName, String viewName) {
		boolean viewNameBlank = (viewName == null || viewName.length() == 0);
		
		if (returnValue == null) {
			if (viewNameBlank) {
				return null;
			} else {
				return new ModelAndView(viewName);
			}
		} else if (returnValue instanceof Map) {
			// remove any Proxy wrappers and set the adaptee as the value
			removeProxiesFromModelObjects((Map)returnValue);
			if (viewNameBlank) {
				throw new NoViewNameDefinedException("Map instance returned by and no view name specified for closure on property [" + closurePropertyName + "] in controller [" + controllerClass.getFullName() + "]!");
			} else {
				Map returnMap = (Map)returnValue;
				if(!this.chainModel.isEmpty()) {
					this.chainModel.putAll( returnMap );
					return new ModelAndView(viewName, this.chainModel);
				}
				else {
					return new ModelAndView(viewName, returnMap);
				}
			}
		} else if (returnValue instanceof ModelAndView) {
			ModelAndView modelAndView = (ModelAndView)returnValue;
			
			// remove any Proxy wrappers and set the adaptee as the value
			Map modelMap = modelAndView.getModel();
			removeProxiesFromModelObjects(modelMap);
			if(!this.chainModel.isEmpty()) {
				this.chainModel.putAll(modelMap);
				modelAndView.addAllObjects(this.chainModel);
			}
			
			if (modelAndView.getView() == null && modelAndView.getViewName() == null) {
				if (viewNameBlank) {
					throw new NoViewNameDefinedException("ModelAndView instance returned by and no view name defined by nor for closure on property [" + closurePropertyName + "] in controller [" + controllerClass.getFullName() + "]!");
				} else {
					modelAndView.setViewName(viewName);
				}
			}
			return modelAndView;
		}
		
		throw new UnsupportedReturnValueException("Return value [" + returnValue + "] is not supported for closure property [" + closurePropertyName + "] in controller [" + controllerClass.getFullName() + "]!");
	}

	/**
	 * If in Proxy's are used in the Groovy context, unproxy (is that a word?) them by setting
	 * the adaptee as the value in the map so that they can be used in non-groovy view technologies
	 *   
	 * @param model The model as a map
	 */
	private void removeProxiesFromModelObjects(Map model) {
		
		for (Iterator keyIter = model.keySet().iterator(); keyIter.hasNext();) {
			Object current = keyIter.next();
			Object modelObject = model.get(current);
			if(modelObject instanceof Proxy) {
				model.put( current, ((Proxy)modelObject).getAdaptee() );
			}			
		}
	}

	/* (non-Javadoc)
	 * @see org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper#handleURI(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.util.Map)
	 */
	public ModelAndView handleURI(String uri, HttpServletRequest request, HttpServletResponse response, Map params) {
		if(uri == null)
			throw new IllegalArgumentException("Controller URI [" + uri + "] cannot be null!");
		
		// step 1: process the uri
		if (uri.indexOf("?") > -1) {
			uri = uri.substring(0, uri.indexOf("?"));
		}		
		if(!uri.startsWith("/"))
			uri = '/' + uri;
		if(uri.endsWith("/"))
			uri = uri.substring(0,uri.length() - 2);
		
		// Step 2: lookup the controller in the application.
		GrailsControllerClass controllerClass = getControllerClassByURI(uri);
		if (controllerClass == null) {
			throw new UnknownControllerException("No controller found for URI [" + uri + "]!");
		}
		//String controllerName = WordUtils.uncapitalize(controllerClass.getName());
		
		// Step 3: load controller from application context.
		GroovyObject controller = getControllerInstance(controllerClass);
		
		// Step 4: get closure property name for URI.
		String closurePropertyName = controllerClass.getClosurePropertyName(uri);
		if (closurePropertyName == null) {
			throw new NoClosurePropertyForURIException("Could not find closure property for URI [" + uri + "] for controller [" + controllerClass.getFullName() + "]!");
		}
		
		// Step 5: get the view name for this URI.
		String viewName = controllerClass.getViewByURI(uri);
		
		
		// Step 6: get closure from closure property
		Closure closure = (Closure)controller.getProperty(closurePropertyName);
		
		// Step 7: process the action
		Object returnValue = handleAction( controller,closure,request,response,params );

		
		// Step 8: determine return value type and handle accordingly
		return handleActionResponse(controllerClass,returnValue,closurePropertyName,viewName);
	}

	public void setChainModel(Map model) {
		this.chainModel  = model;
	}

	public Object handleAction(GroovyObject controller,Closure action, HttpServletRequest request, HttpServletResponse response) {
		return handleAction(controller,action,request,response,Collections.EMPTY_MAP);
	}

	public Object handleAction(GroovyObject controller,Closure action, HttpServletRequest request, HttpServletResponse response, Map params) {
		// Step 3a: Configure a proxy interceptor for controller dynamic methods for this request
		try {
			ControllerDynamicMethodsInterceptor interceptor;
			if(!controller.getMetaClass().getClass().equals( PropertyAccessProxyMetaClass.class )) {				
				interceptor = new ControllerDynamicMethodsInterceptor(controller,this,request,response);
			}
			else {
				ProxyMetaClass pmc = (ProxyMetaClass)controller.getMetaClass(); 
				interceptor = (ControllerDynamicMethodsInterceptor)pmc.getInterceptor(); 
			}
			// if there are additional params add them to the params dynamic property
			if(params != null && !params.isEmpty()) {
				GetParamsDynamicProperty paramsProp = (GetParamsDynamicProperty)interceptor.getDynamicProperty( GetParamsDynamicProperty.PROPERTY_NAME );
				paramsProp.addParams( params );
			}			
			// check the chain model is not empty and add it
			if(!this.chainModel.isEmpty()) {
				// get the "chainModel" property
				GenericDynamicProperty chainProperty = (GenericDynamicProperty)interceptor.getDynamicProperty(ChainDynamicMethod.PROPERTY_CHAIN_MODEL);
				// if it doesn't exist create it
				if(chainProperty == null) {			
					interceptor.addDynamicProperty( new GenericDynamicProperty( ChainDynamicMethod.PROPERTY_CHAIN_MODEL,Map.class,this.chainModel,false ) );
				}
				else {
					// otherwise add to it
					Map chainPropertyModel = (Map)chainProperty.getValue();
					chainPropertyModel.putAll( this.chainModel );
					this.chainModel = chainPropertyModel;
				}
			}

		}
		catch(IntrospectionException ie) {
			throw new ControllerExecutionException("Error creating dynamic controller methods for controller ["+controller.getClass()+"]: " + ie.getMessage(), ie);
		}
		
		// Step 7: determine argument count and execute.
		Object returnValue = null;
		if (action.getParameterTypes().length == 1) {
			// closure may have zero or one parameter, we cannot be sure.
			returnValue = action.call(new GrailsHttpServletRequest(request));
		} else if (action.getParameterTypes().length == 2) {
			returnValue = action.call(new Object[] { new  GrailsHttpServletRequest(request), new GrailsHttpServletResponse(response) });
		} else {
			throw new IncompatibleParameterCountException("Closure on property [" + action + "] in [" + controller.getClass() + "] has an incompatible parameter count [" + action.getParameterTypes().length + "]! Supported values are 0 and 2.");			
		}
		return returnValue;
	}
	
}

{'fraction_non_alphanumeric': 0.10152819993245525, 'fraction_numerical': 0.002617359000337724, 'mean_word_length': 4.869425173439049, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5221175', 'n_tokens_mistral': 7484, 'n_tokens_neox': 6611, 'n_words': 1569}