Package ns.foundation

Source Code of ns.foundation.NSSelector

package ns.foundation;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;

import ns.foundation._private._NSMethod;


public class NSSelector<T> implements Serializable {
  protected static final Class<?>[] _NoClassArray = new Class[0];
  protected static final Object[] _NoObjectArray = new Object[0];

  protected String _name;
  protected Class<?>[] _types;
  private transient Class<?> _cachedClass;
  private transient _NSMethod _cachedMethod;
  private transient NSMutableDictionary<String, _NSMethod> _classToMethodMapTable = new NSMutableDictionary<String, _NSMethod>(8);

  public static <T> T _safeInvokeSelector(NSSelector<T> selector, Object receiver, Object... parameters) {
    try {
      return selector.invoke(receiver, parameters != null ? parameters : _NoObjectArray);
    } catch (InvocationTargetException e) {
      throw NSForwardException._runtimeExceptionForThrowable(e);
    } catch (IllegalAccessException e) {
      throw new IllegalArgumentException("Either the receiver or the method is not public: " + e.getMessage());
    } catch (NoSuchMethodException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }

  protected NSSelector() {

  }

  public NSSelector(String name) {
    this(name, (Class[]) null);
  }

  public String name() {
    return _name;
  }

  public NSSelector(String name, Class<?>... parameterTypes) {
    if (name == null) {
      throw new IllegalArgumentException("Selector name cannot be null");
    }

    _name = name;
    if (parameterTypes != null) {
      _types = new Class[parameterTypes.length];
      System.arraycopy(parameterTypes, 0, _types, 0, parameterTypes.length);
    } else {
      _types = _NoClassArray;
    }
  }

  @SuppressWarnings("unchecked")
  public T invoke(Object target, Object... parameters) throws IllegalArgumentException, NoSuchMethodException, InvocationTargetException,
      IllegalAccessException {
    _NSMethod method = methodOnObject(target);
    return (T) method.invoke(target, parameters != null ? parameters : new Object[0]);
  }

  public T invoke(Object target) throws IllegalArgumentException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    return invoke(target, _NoObjectArray);
  }

  public static Object invoke(String name, Class<?> parameterTypes[], Object target, Object... parameters) throws IllegalAccessException,
      IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
    NSSelector<?> selector = new NSSelector<Object>(name, parameterTypes);
    return selector.invoke(target, parameters);
  }

  public static Object invoke(String name, Class<?> parameterType, Object target, Object argument) throws IllegalAccessException, IllegalArgumentException,
      InvocationTargetException, NoSuchMethodException {
    if (parameterType == null) {
      throw new IllegalArgumentException("Parameter type cannot be null");
    }
    NSSelector<?> selector = new NSSelector<Object>(name, parameterType);
    return selector.invoke(target, argument);
  }

  public static Object invoke(String name, Class<?> parameterType1, Class<?> parameterType2, Object target, Object argument1, Object argument2)
      throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
    if (parameterType1 == null || parameterType2 == null) {
      throw new IllegalArgumentException("Neither parameter type can be null");
    }
    NSSelector<?> selector = new NSSelector<Object>(name, parameterType1, parameterType2);
    return selector.invoke(target, argument1, argument2);
  }

  public Class<?>[] parameterTypes() {
    if (_types.length == 0) {
      return _types;
    }

    Class<?>[] types = new Class[_types.length];
    System.arraycopy(_types, 0, types, 0, _types.length);
    return types;
  }

  private synchronized _NSMethod _methodOnObject(Object targetObject) {
    Class<?> targetClass = targetObject.getClass();
    if (targetClass == _cachedClass) {
      return _cachedMethod;
    }

    String className = targetClass.getName();
    Object value = _classToMethodMapTable.objectForKey(className);
    if (value == null) {
      try {
        value = _NSReflectionUtilities.methodOnObject(targetObject, _name, _types);
      } catch (NoSuchMethodException exception) {
        exception.printStackTrace();
      }

      if (value == null)
        value = NSKeyValueCoding.NullValue;

      _classToMethodMapTable.takeValueForKey(value, className);

    }

    _NSMethod method = null;
    if (value != NSKeyValueCoding.NullValue) {
      method = (_NSMethod) value;
    }

    _cachedClass = targetClass;
    _cachedMethod = method;
    return method;
  }

  private _NSMethod methodOnObject(Object targetObject) throws NoSuchMethodException {
    if (targetObject == null)
      throw new IllegalArgumentException("Target object cannot be null");

    _NSMethod method = _methodOnObject(targetObject);
    Class<?> targetClass = targetObject.getClass();
    if (method == null)
      throw new NoSuchMethodException("Class " + targetClass.getName() + " does not implement method " + _NSReflectionUtilities._methodSignature(_name, _types));

    return method;
  }

  public static boolean respondsToSelector(Object object, NSSelector<?> selector) {
    return selector._methodOnObject(object) != null;
  }

}
TOP

Related Classes of ns.foundation.NSSelector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.