Package org.rococoa.internal

Source Code of org.rococoa.internal.NSObjectTypeConverter

/**
*
*/
package org.rococoa.internal;

import org.rococoa.Foundation;
import org.rococoa.ID;
import org.rococoa.NSObject;
import org.rococoa.Rococoa;
import org.rococoa.Selector;

import com.sun.jna.FromNativeContext;
import com.sun.jna.FunctionResultContext;
import com.sun.jna.NativeMapped;
import com.sun.jna.ToNativeContext;
import com.sun.jna.TypeConverter;

/**
* A JNA TypeConverter that gets the ID from an NSObject when passing it into
* native code, and creates an instance of subclass of NSObject to wrap an id
* when receiving one from native code.
*/
class NSObjectTypeConverter<T extends NSObject> implements TypeConverter {
   
    private static final NativeMapped nativeLongConverter = new ID();

    private final Class<T> javaType;

    public NSObjectTypeConverter(Class<T> javaType) {
        this.javaType = javaType;
    }

    public Class<?> nativeType() {
        // we can't return NativeLong here - has to be a primitive type, so
        // delegate so that we are 32/64 correct
        return nativeLongConverter.nativeType();
    }

    // Takes an Integer or Long representing id (32 or 64 bit respectively)
    // and returns an NSObject of javaType with that id.
    public T fromNative(Object nativeValue, FromNativeContext context) {
        Number nativeValueAsNumber = (Number) nativeValue;
        if (nativeValueAsNumber == null)
            return null;
        ID id = ID.fromLong(nativeValueAsNumber.longValue());
        if (id.isNull())
            return null;           
        boolean shouldRetain = shouldRetainFor(context);       
        return Rococoa.wrap(id, javaType, shouldRetain);
    }
   
    // Takes an NSObject and returns its id as Integer or Long
    public Object toNative(Object value, ToNativeContext context) {
        if (value == null)
            return null;
        NSObject valueAsNSObject = (NSObject) value;
        ID idToReturn = valueAsNSObject.id();
        return idToReturn.toNative();
    }
   
    // For tests only
    boolean convertsJavaType(Class<?> javaType) {
  return this.javaType == javaType;
    }
   
    private boolean shouldRetainFor(FromNativeContext context) {
  // Generally we should default to retaining, as by default NSObjects that
  // are returned from methods are owned by the current autorelease pool and
  // unless we retain will be dealloc'ed when is is drained. 
  if (context == null || !(context instanceof FunctionResultContext))
      return true;

  // The exception is if this conversion is for an object that we own, because
  // the selector name matches those
  FunctionResultContext resultContext = (FunctionResultContext) context;
  Object[] arguments = resultContext.getArguments();
  if (arguments.length < 2)
      return true;
  if (!(arguments[1] instanceof Selector))
      return true;
 
  boolean dontRetain = Foundation.selectorNameMeansWeOwnReturnedObject(((Selector) arguments[1]).getName());
  return !dontRetain; // OK Smartarse, you express it better.
    }
}
TOP

Related Classes of org.rococoa.internal.NSObjectTypeConverter

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.