<commit_before>/**
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
package org.appcelerator.titanium.kroll;

import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import org.appcelerator.titanium.ContextSpecific;
import org.appcelerator.titanium.TiApplication;
import org.appcelerator.titanium.TiContext;
import org.appcelerator.titanium.TiDict;
import org.appcelerator.titanium.TiModule;
import org.appcelerator.titanium.TiProxy;
import org.appcelerator.titanium.kroll.KrollMethod.KrollMethodType;
import org.appcelerator.titanium.util.Log;
import org.appcelerator.titanium.util.TiConfig;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

public class KrollObject extends ScriptableObject
{
	private static final String LCAT = "KrollObject";
	private static final boolean DBG = TiConfig.LOGD && false; //TODO remove force false

	private static final long serialVersionUID = 1L;

	protected WeakReference<KrollContext> weakKrollContext;
	protected WeakReference<TiApplication> weakApplication;
	protected Object target;

	public KrollObject(KrollContext kroll) {
		this(kroll, null);
	}

	public KrollObject(KrollContext kroll, Object target)
	{
		super(kroll.getScope(), null);
		weakKrollContext = new WeakReference<KrollContext>(kroll);
		this.target = target;
		initApplication(kroll);
	}

	public KrollObject(KrollObject parent, Object target)
	{
		super(parent, null);
		weakKrollContext = new WeakReference<KrollContext>(parent.getKrollContext());
		this.target = target;
		initApplication(parent.getKrollContext());
	}

	private void initApplication(KrollContext kroll) {
		if (kroll != null) {
			TiContext tiContext = kroll.getTiContext();
			if (tiContext != null) {
				weakApplication = new WeakReference<TiApplication>((TiApplication) tiContext.getActivity().getApplication());
			}
		}
	}

	@Override
	public String getClassName() {
		return "KrollObject";
	}

	public Object getTarget() {
		return target;
	}

	public KrollContext getKrollContext() {
		return weakKrollContext.get();
	}

	protected String getModulePath() {
		KrollContext kroll = weakKrollContext.get();
		Scriptable scope = kroll.getScope();

		if (DBG) {
			Log.e(LCAT, "getModulePath(): " + getClassName());
		}
		if (target != null) {
			if (DBG) {
				Log.e(LCAT, "targetPath: " + target.getClass().getPackage().getName());
			}
			return target.getClass().getPackage().getName() + ".";
		}

		if (scope.getParentScope() == null) {
			return "ti.modules." + getClassName().toLowerCase() + ".";
		} else {
			return ((KrollObject) scope.getParentScope()).getModulePath() +
				getClassName().toLowerCase() + ".";
		}
	}

	@Override
	public Object get(String name, Scriptable start)
	{
		if (this.has(name, start)) {
			return super.get(name, start);
		}
		if (target instanceof TiProxy) {
			TiDict constants = ((TiProxy) target).getConstants();
			if (constants != null) {
				if (constants.containsKey(name)) {
					Object value = constants.get(name);
					super.putConst(name, start, value);
					return value;
				}
			}
		}

		if (DBG) {
			Log.d(LCAT, "get name: " + name);
		}
		Object o = NOT_FOUND;

		// If starts with Capital letter see if there is a module for it.
		if (name.matches("^[A-Z].*") || name.matches("iPhone")) {
			Object p = loadModule(name);
			if (p != null) {
				o = new KrollObject(this, p);
				put(name, this, o);
				((TiModule) p).postCreate();
			}
		} else {
			if (DBG) {
				Log.d(LCAT, "Start: " + start.getClassName() + " looking for method:" + name);
			}
			o = handleMethodOrProperty(name, start, true, null);
		}

		return o;
	}

	@Override
	public Object getDefaultValue(Class<?> typeHint) {
		//return super.getDefaultValue(typeHint);
		if (typeHint == null || typeHint == String.class) {
			if (target != null) {
				return target.toString();
			}
		} else if (typeHint == Number.class) {
			if (target != null) {
				return (Number) target;
			}
		} else if (typeHint == Boolean.class) {
			if (target != null) {
				return (Boolean) target;
			}
		} else if (typeHint == Scriptable.class) {
			return toString();
		}

		return super.getDefaultValue(typeHint);
	}

	private Object handleMethodOrProperty(String name, Scriptable start, boolean retrieveValue, Object value)
	{
		// optimization, check to see if dynamic property of TiProxy and if so, 
		// immediately return the value -- this will allow the setting of properties
		// and methods with the same name but prefer dynamic properties over methods
		if (target instanceof TiProxy)
		{
			TiProxy proxy = (TiProxy)target;
			if (proxy.hasDynamicValue(name))
			{
				return handleDynamicProperty(name, name, start, retrieveValue, value);
			}
		}
		
		Object o = NOT_FOUND;

		String pname = name;
		

//		if (name.equals("valueOf") || name.equals("toString")) {
//			KrollMethod km = new KrollMethod(this, value, null, KrollMethodType.KrollMethodInvoke);
//			put(name, this, km);
//			o = value;
//		}

		if(name.startsWith("get") || name.startsWith("set")) {
			pname = name.substring(3,4);
			pname = pname.toLowerCase();
			if (name.length() > 4) {
				pname += name.substring(4);
			}
		}

		Method getMethod = (Method) loadMethod(target.getClass(), buildMethodName("get", pname));
		Method setMethod = (Method) loadMethod(target.getClass(), buildMethodName("set", pname));
		boolean isGetter = getMethod != null && getMethod.getParameterTypes().length == 0;
		boolean isSetter = setMethod != null && setMethod.getParameterTypes().length == 1;

		if (isGetter || isSetter) {
			if (DBG) {
				Log.d(LCAT, "Treating as property: " + pname);
			}
			boolean getRetrieved = false;
			if (getMethod != null) {
				// add getter
				KrollMethod km = null;

				Method propertyMethod = (Method) loadMethod(target.getClass(), pname);
				if (propertyMethod != null) {
					km = new KrollMethod(this, target, propertyMethod, KrollMethodType.KrollMethodGetter);
					put(pname, this, km);
					retrieveValue = false;
					o = km;
				} else {
					km  = new KrollMethod(this, target, getMethod, KrollMethodType.KrollMethodPropertyGetter);
					setGetterOrSetter(pname, 0, km, false);
				}

				// add get method
				km = new KrollMethod(this, target, getMethod, KrollMethodType.KrollMethodGetter);
				put(buildMethodName("get", pname), this, km);

				if(retrieveValue && pname.equals(name)) {
					try {
						// get value from native
						o = KrollObject.fromNative(getMethod.invoke(target, new Object[0]), getKrollContext());
						getRetrieved = true;
					} catch (InvocationTargetException e) {
						Log.e(LCAT, "Error getting property: " + e.getMessage(), e);
						Context.throwAsScriptRuntimeEx(e);
					}catch (IllegalAccessException e) {
						Log.e(LCAT, "Error getting property: " + e.getMessage(), e);
						Context.throwAsScriptRuntimeEx(e);
					}
				} else {
					o = km;
				}
			}

			if (setMethod != null) {
				// add setter
				KrollMethod km  = new KrollMethod(this, target, setMethod, KrollMethodType.KrollMethodPropertySetter);
				setGetterOrSetter(pname, 0, km, true);

				// add set method
				km = new KrollMethod(this, target, setMethod, KrollMethodType.KrollMethodSetter);
				put(buildMethodName("set", pname), this, km);
				if (!getRetrieved) {
					o = km;
				}
				// pass value through to native
				if (!retrieveValue) {
					Object[] args = new Object[1];
					args[0] = value;

					try {
						setMethod.invoke(target, argsForMethod(setMethod, args, getKrollContext().getTiContext()));
					} catch (InvocationTargetException e) {
						Log.e(LCAT, "Error setting property: " + e.getMessage(), e);
						Context.throwAsScriptRuntimeEx(e);
					}catch (IllegalAccessException e) {
						Log.e(LCAT, "Error setting property: " + e.getMessage(), e);
						Context.throwAsScriptRuntimeEx(e);
					}
				}<commit_msg>The getter was being mistakenly overridden with the setter. Was discovered while working on #1315<commit_after>/**
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
package org.appcelerator.titanium.kroll;

import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import org.appcelerator.titanium.ContextSpecific;
import org.appcelerator.titanium.TiApplication;
import org.appcelerator.titanium.TiContext;
import org.appcelerator.titanium.TiDict;
import org.appcelerator.titanium.TiModule;
import org.appcelerator.titanium.TiProxy;
import org.appcelerator.titanium.kroll.KrollMethod.KrollMethodType;
import org.appcelerator.titanium.util.Log;
import org.appcelerator.titanium.util.TiConfig;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

public class KrollObject extends ScriptableObject
{
	private static final String LCAT = "KrollObject";
	private static final boolean DBG = TiConfig.LOGD && false; //TODO remove force false

	private static final long serialVersionUID = 1L;

	protected WeakReference<KrollContext> weakKrollContext;
	protected WeakReference<TiApplication> weakApplication;
	protected Object target;

	public KrollObject(KrollContext kroll) {
		this(kroll, null);
	}

	public KrollObject(KrollContext kroll, Object target)
	{
		super(kroll.getScope(), null);
		weakKrollContext = new WeakReference<KrollContext>(kroll);
		this.target = target;
		initApplication(kroll);
	}

	public KrollObject(KrollObject parent, Object target)
	{
		super(parent, null);
		weakKrollContext = new WeakReference<KrollContext>(parent.getKrollContext());
		this.target = target;
		initApplication(parent.getKrollContext());
	}

	private void initApplication(KrollContext kroll) {
		if (kroll != null) {
			TiContext tiContext = kroll.getTiContext();
			if (tiContext != null) {
				weakApplication = new WeakReference<TiApplication>((TiApplication) tiContext.getActivity().getApplication());
			}
		}
	}

	@Override
	public String getClassName() {
		return "KrollObject";
	}

	public Object getTarget() {
		return target;
	}

	public KrollContext getKrollContext() {
		return weakKrollContext.get();
	}

	protected String getModulePath() {
		KrollContext kroll = weakKrollContext.get();
		Scriptable scope = kroll.getScope();

		if (DBG) {
			Log.e(LCAT, "getModulePath(): " + getClassName());
		}
		if (target != null) {
			if (DBG) {
				Log.e(LCAT, "targetPath: " + target.getClass().getPackage().getName());
			}
			return target.getClass().getPackage().getName() + ".";
		}

		if (scope.getParentScope() == null) {
			return "ti.modules." + getClassName().toLowerCase() + ".";
		} else {
			return ((KrollObject) scope.getParentScope()).getModulePath() +
				getClassName().toLowerCase() + ".";
		}
	}

	@Override
	public Object get(String name, Scriptable start)
	{
		if (this.has(name, start)) {
			return super.get(name, start);
		}
		if (target instanceof TiProxy) {
			TiDict constants = ((TiProxy) target).getConstants();
			if (constants != null) {
				if (constants.containsKey(name)) {
					Object value = constants.get(name);
					super.putConst(name, start, value);
					return value;
				}
			}
		}

		if (DBG) {
			Log.d(LCAT, "get name: " + name);
		}
		Object o = NOT_FOUND;

		// If starts with Capital letter see if there is a module for it.
		if (name.matches("^[A-Z].*") || name.matches("iPhone")) {
			Object p = loadModule(name);
			if (p != null) {
				o = new KrollObject(this, p);
				put(name, this, o);
				((TiModule) p).postCreate();
			}
		} else {
			if (DBG) {
				Log.d(LCAT, "Start: " + start.getClassName() + " looking for method:" + name);
			}
			o = handleMethodOrProperty(name, start, true, null);
		}

		return o;
	}

	@Override
	public Object getDefaultValue(Class<?> typeHint) {
		//return super.getDefaultValue(typeHint);
		if (typeHint == null || typeHint == String.class) {
			if (target != null) {
				return target.toString();
			}
		} else if (typeHint == Number.class) {
			if (target != null) {
				return (Number) target;
			}
		} else if (typeHint == Boolean.class) {
			if (target != null) {
				return (Boolean) target;
			}
		} else if (typeHint == Scriptable.class) {
			return toString();
		}

		return super.getDefaultValue(typeHint);
	}

	private Object handleMethodOrProperty(String name, Scriptable start, boolean retrieveValue, Object value)
	{
		// optimization, check to see if dynamic property of TiProxy and if so, 
		// immediately return the value -- this will allow the setting of properties
		// and methods with the same name but prefer dynamic properties over methods
		if (target instanceof TiProxy)
		{
			TiProxy proxy = (TiProxy)target;
			if (proxy.hasDynamicValue(name))
			{
				return handleDynamicProperty(name, name, start, retrieveValue, value);
			}
		}
		
		Object o = NOT_FOUND;

		String pname = name;
		

//		if (name.equals("valueOf") || name.equals("toString")) {
//			KrollMethod km = new KrollMethod(this, value, null, KrollMethodType.KrollMethodInvoke);
//			put(name, this, km);
//			o = value;
//		}

		if(name.startsWith("get") || name.startsWith("set")) {
			pname = name.substring(3,4);
			pname = pname.toLowerCase();
			if (name.length() > 4) {
				pname += name.substring(4);
			}
		}

		Method getMethod = (Method) loadMethod(target.getClass(), buildMethodName("get", pname));
		Method setMethod = (Method) loadMethod(target.getClass(), buildMethodName("set", pname));
		boolean isGetter = getMethod != null && getMethod.getParameterTypes().length == 0;
		boolean isSetter = setMethod != null && setMethod.getParameterTypes().length == 1;

		if (isGetter || isSetter) {
			if (DBG) {
				Log.d(LCAT, "Treating as property: " + pname);
			}
			boolean getRetrieved = false;
			if (getMethod != null) {
				// add getter
				KrollMethod km = null;

				Method propertyMethod = (Method) loadMethod(target.getClass(), pname);
				if (propertyMethod != null) {
					km = new KrollMethod(this, target, propertyMethod, KrollMethodType.KrollMethodGetter);
					put(pname, this, km);
					retrieveValue = false;
					o = km;
				} else {
					km  = new KrollMethod(this, target, getMethod, KrollMethodType.KrollMethodPropertyGetter);
					setGetterOrSetter(pname, 0, km, false);
				}

				// add get method
				km = new KrollMethod(this, target, getMethod, KrollMethodType.KrollMethodGetter);
				put(buildMethodName("get", pname), this, km);

				if(retrieveValue && pname.equals(name)) {
					try {
						// get value from native
						o = KrollObject.fromNative(getMethod.invoke(target, new Object[0]), getKrollContext());
						getRetrieved = true;
					} catch (InvocationTargetException e) {
						Log.e(LCAT, "Error getting property: " + e.getMessage(), e);
						Context.throwAsScriptRuntimeEx(e);
					}catch (IllegalAccessException e) {
						Log.e(LCAT, "Error getting property: " + e.getMessage(), e);
						Context.throwAsScriptRuntimeEx(e);
					}
				} else {
					if (name.startsWith("get")) {
						o = km;
					}
				}
			}

			if (setMethod != null) {
				// add setter
				KrollMethod km  = new KrollMethod(this, target, setMethod, KrollMethodType.KrollMethodPropertySetter);
				setGetterOrSetter(pname, 0, km, true);

				// add set method
				km = new KrollMethod(this, target, setMethod, KrollMethodType.KrollMethodSetter);
				put(buildMethodName("set", pname), this, km);
				if (!getRetrieved) {
					if (name.startsWith("set")) {
						o = km;
					}
				}
				// pass value through to native
				if (!retrieveValue) {
					Object[] args = new Object[1];
					args[0] = value;

					try {
						setMethod.invoke(target, argsForMethod(setMethod, args, getKrollContext().getTiContext()));
					} catch (InvocationTargetException e) {
						Log.e(LCAT, "Error setting property: " + e.getMessage(), e);
						Context.throwAsScriptRuntimeEx(e);
					}catch (IllegalAccessException e) {
						Log.e(LCAT, "Error setting property: " + e.getMessage(), e);
						Context.throwAsScriptRuntimeEx(e);
					}
				}
{'fraction_non_alphanumeric': 0.12966461974492205, 'fraction_numerical': 0.0025980160604629193, 'mean_word_length': 3.795300113250283, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, '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': '4741259', 'n_tokens_mistral': 6315, 'n_tokens_neox': 5375, 'n_words': 1310}