alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (AS_NS_ConversionUtils.m)

This example Java source code file (AS_NS_ConversionUtils.m) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

desctype, float64, javaapplescriptengineadditions, nsappleeventdescriptor, nsarray, nsdate, nsdictionary, nsexception, nsmutabledictionary, nsnull, nsnumber, nsstring, nsvalue, sint16

The AS_NS_ConversionUtils.m Java example source code

/*
 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

//
//    Most of this is adapted from Ken Ferry's KFAppleScript Additions, contributed with permission
//    http://homepage.mac.com/kenferry/software.html
//

#import "AS_NS_ConversionUtils.h"

#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>


@interface NSAppleEventDescriptor (JavaAppleScriptEngineAdditionsPrivate)

// just returns self.  This means that you can pass custom descriptors
// to -[NSAppleScript executeHandler:error:withParameters:].
- (NSAppleEventDescriptor *)aeDescriptorValue;

// working with primitive descriptor types
+ (id)descriptorWithInt16:(SInt16)val;
- (SInt16)int16Value;
+ (id)descriptorWithUnsignedInt32:(UInt32)val;
- (UInt32)unsignedInt32Value;
+ (id)descriptorWithFloat32:(Float32)val;
- (Float32)float32Value;
+ (id)descriptorWithFloat64:(Float64)val;
- (Float64)float64Value;
+ (id)descriptorWithLongDateTime:(LongDateTime)val;
- (LongDateTime)longDateTimeValue;


// These are the methods for converting AS objects to objective-C objects.
// -[NSAppleEventDescriptor objCObjectValue] is the general method for converting
// AS objects to ObjC objects, and is called by -[NSAppleScript executeHandler:error:withParameters:].
// It does no work itself.  It finds a handler based on the type of the descriptor and lets that
// handler object do the work.  If there is no handler type registered for a the type of a descriptor,
// the raw descriptor is returned.
//
// You can designate a handlers for descriptor types with
// +[NSAppleEventDescriptor registerConversionHandler:selector:forDescriptorTypes:].  Please note
// that this method does _not_ retain the handler object (for now anyway).  The selector should
// take a single argument, a descriptor to translate, and should return an object.  An example such
// selector is @selector(dictionaryWithAEDesc:), for which the handler object would be [NSDictionary class].
//
// A number of handlers are designated by default.  The methods and objects can be easily inferred (or check
// the implementation), but the automatically handled types are
//    typeUnicodeText,
//    typeText,
//    typeUTF8Text,
//    typeCString,
//    typeChar,
//    typeBoolean,
//    typeTrue,
//    typeFalse,
//    typeSInt16,
//    typeSInt32,
//    typeUInt32,
//    typeSInt64,
//    typeIEEE32BitFloatingPoint,
//    typeIEEE64BitFloatingPoint,
//    type128BitFloatingPoint,
//    typeAEList,
//    typeAERecord,
//    typeLongDateTime,
//    typeNull.
+ (void)registerConversionHandler:(id)anObject selector:(SEL)aSelector forDescriptorTypes:(DescType)firstType, ...;
+ (void) jaseSetUpHandlerDict;
@end

// wrap the NSAppleEventDescriptor string methods
@interface NSString (JavaAppleScriptEngineAdditions)
- (NSAppleEventDescriptor *)aeDescriptorValue;
+ (NSString *)stringWithAEDesc:(NSAppleEventDescriptor *)desc;
@end

// wrap the NSAppleEventDescriptor longDateTime methods
@interface NSDate (JavaAppleScriptEngineAdditions)
- (NSAppleEventDescriptor *)aeDescriptorValue;
+ (NSDate *)dateWithAEDesc:(NSAppleEventDescriptor *)desc;
@end

// these are fairly complicated methods, due to having to try to match up the various
// AS number types (see NSAppleEventDescriptor for the primitive number methods)
// with NSNumber variants.  For complete behavior it's best to look at the implementation.
// Some notes:
//    NSNumbers created with numberWithBool should be correctly translated to AS booleans and vice versa.
//    NSNumbers created with large integer types may have to be translated to AS doubles,
//      so be careful if checking equality (you may have to check equality within epsilon).
//    Since NSNumbers can't remember if they were created with an unsigned value,
//      [[NSNumber numberWithUnsignedChar:255] aeDescriptorValue] is going to get you an AS integer
//      with value -1.  If you really need a descriptor with an unsigned value, you'll need to do it
//      manually using the primitive methods on NSAppleEventDescriptor.  The resulting descriptor
//      can still be passed to AS with -[NSAppleScript executeHandler:error:withParameters:].
@interface NSNumber (JavaAppleScriptEngineAdditions)
- (NSAppleEventDescriptor *)aeDescriptorValue;
+ (id)numberWithAEDesc:(NSAppleEventDescriptor *)desc;
@end

// Here we're following the behavior described in the CocoaScripting release note.
//
// NSPoint -> list of two numbers: {x, y}
// NSRange -> list of two numbers: {begin offset, end offset}
// NSRect  -> list of four numbers: {left, bottom, right, top}
// NSSize  -> list of two numbers: {width, height}
@interface NSValue (JavaAppleScriptEngineAdditions)
- (NSAppleEventDescriptor *)aeDescriptorValue;
@end

// No need for ObjC -> AS conversion here, we fall through to NSObject as a collection.
// For AS -> ObjC conversion, we build an array using the primitive list methods on
// NSAppleEventDescriptor.
@interface NSArray (JavaAppleScriptEngineAdditions)
+ (NSArray *)arrayWithAEDesc:(NSAppleEventDescriptor *)desc;
@end


// Please see the CocoaScripting release note for behavior.  It's kind of complicated.
//
// methods wrap the primitive record methods on NSAppleEventDescriptor.
@interface NSDictionary (JavaAppleScriptEngineAdditions)
- (NSAppleEventDescriptor *)aeDescriptorValue;
+ (NSDictionary *)dictionaryWithAEDesc:(NSAppleEventDescriptor *)desc;
@end

// be aware that a null descriptor does not correspond to the 'null' keyword in
// AppleScript - it's more like nothing at all.  For example, the return
// from an empty handler.
@interface NSNull (JavaAppleScriptEngineAdditions)
- (NSAppleEventDescriptor *)aeDescriptorValue;
+ (NSNull *)nullWithAEDesc:(NSAppleEventDescriptor *)desc;
@end


@interface NSNumber (JavaAppleScriptEngineAdditionsPrivate)
+ (id) jaseNumberWithSignedIntP:(void *)int_p byteCount:(int)bytes;
+ (id) jaseNumberWithUnsignedIntP:(void *)int_p byteCount:(int)bytes;
+ (id) jaseNumberWithFloatP:(void *)float_p byteCount:(int)bytes;
@end


@implementation NSObject (JavaAppleScriptEngineAdditions)

- (NSAppleEventDescriptor *)aeDescriptorValue {
    // collections go to lists
    if (![self respondsToSelector:@selector(objectEnumerator)]) {
        // encode the description as a fallback - this is pretty useless, only helpful for debugging
        return [[self description] aeDescriptorValue];
    }

    NSAppleEventDescriptor *resultDesc = [NSAppleEventDescriptor listDescriptor];
    NSEnumerator *objectEnumerator = [(id)self objectEnumerator];

    unsigned int i = 1; // apple event descriptors are 1-indexed
    id currentObject;
    while((currentObject = [objectEnumerator nextObject]) != nil) {
        [resultDesc insertDescriptor:[currentObject aeDescriptorValue] atIndex:i++];
    }

    return resultDesc;
}

@end


@implementation NSArray (JavaAppleScriptEngineAdditions)

// don't need to override aeDescriptorValue, the NSObject will treat the array as a collection
+ (NSArray *)arrayWithAEDesc:(NSAppleEventDescriptor *)desc {
    NSAppleEventDescriptor *listDesc = [desc coerceToDescriptorType:typeAEList];
    NSMutableArray *resultArray = [NSMutableArray array];

    // apple event descriptors are 1-indexed
    unsigned int listCount = [listDesc numberOfItems];
    unsigned int i;
    for (i = 1; i <= listCount; i++) {
        [resultArray addObject:[[listDesc descriptorAtIndex:i] objCObjectValue]];
    }

    return resultArray;
}

@end


@implementation NSDictionary (JavaAppleScriptEngineAdditions)

- (NSAppleEventDescriptor *)aeDescriptorValue {
    NSAppleEventDescriptor *resultDesc = [NSAppleEventDescriptor recordDescriptor];
    NSMutableArray *userFields = [NSMutableArray array];
    NSArray *keys = [self allKeys];

    unsigned int keyCount = [keys count];
    unsigned int i;
    for (i = 0; i < keyCount; i++) {
        id key = [keys objectAtIndex:i];

        if ([key isKindOfClass:[NSNumber class]]) {
            [resultDesc setDescriptor:[[self objectForKey:key] aeDescriptorValue] forKeyword:[(NSNumber *)key intValue]];
        } else if ([key isKindOfClass:[NSString class]]) {
            [userFields addObject:key];
            [userFields addObject:[self objectForKey:key]];
        }
    }

    if ([userFields count] > 0) {
        [resultDesc setDescriptor:[userFields aeDescriptorValue] forKeyword:keyASUserRecordFields];
    }

    return resultDesc;
}

+ (NSDictionary *)dictionaryWithAEDesc:(NSAppleEventDescriptor *)desc {
    NSAppleEventDescriptor *recDescriptor = [desc coerceToDescriptorType:typeAERecord];
    NSMutableDictionary *resultDict = [NSMutableDictionary dictionary];

    // NSAppleEventDescriptor uses 1 indexing
    unsigned int recordCount = [recDescriptor numberOfItems];
    unsigned int recordIndex;
    for (recordIndex = 1; recordIndex <= recordCount; recordIndex++) {
        AEKeyword keyword = [recDescriptor keywordForDescriptorAtIndex:recordIndex];

        if(keyword == keyASUserRecordFields) {
            NSAppleEventDescriptor *listDescriptor = [recDescriptor descriptorAtIndex:recordIndex];

            // NSAppleEventDescriptor uses 1 indexing
            unsigned int listCount = [listDescriptor numberOfItems];
            unsigned int listIndex;
            for (listIndex = 1; listIndex <= listCount; listIndex += 2) {
                id keyObj = [[listDescriptor descriptorAtIndex:listIndex] objCObjectValue];
                id valObj = [[listDescriptor descriptorAtIndex:listIndex+1] objCObjectValue];

                [resultDict setObject:valObj forKey:keyObj];
            }
        } else {
            id keyObj = [NSNumber numberWithInt:keyword];
            id valObj = [[recDescriptor descriptorAtIndex:recordIndex] objCObjectValue];

            [resultDict setObject:valObj forKey:keyObj];
        }
    }

    return resultDict;
}

@end


@implementation NSString (JavaAppleScriptEngineAdditions)

- (NSAppleEventDescriptor *)aeDescriptorValue {
    return [NSAppleEventDescriptor descriptorWithString:self];
}

+ (NSString *)stringWithAEDesc:(NSAppleEventDescriptor *)desc {
    return [desc stringValue];
}

+ (NSString *)versionWithAEDesc:(NSAppleEventDescriptor *)desc {
    const AEDesc *aeDesc = [desc aeDesc];
    VersRec v;
    AEGetDescData(aeDesc, &v, sizeof(v));
    return [[[NSString alloc] initWithBytes:&v.shortVersion[1] length:StrLength(v.shortVersion) encoding:NSUTF8StringEncoding] autorelease];
}

@end


@implementation NSNull (JavaAppleScriptEngineAdditions)

- (NSAppleEventDescriptor *)aeDescriptorValue {
    return [NSAppleEventDescriptor nullDescriptor];
}

+ (NSNull *)nullWithAEDesc:(NSAppleEventDescriptor *)desc {
    return [NSNull null];
}

@end


@implementation NSDate (JavaAppleScriptEngineAdditions)

- (NSAppleEventDescriptor *)aeDescriptorValue {
    LongDateTime ldt;
    UCConvertCFAbsoluteTimeToLongDateTime(CFDateGetAbsoluteTime((CFDateRef)self), &ldt);
    return [NSAppleEventDescriptor descriptorWithLongDateTime:ldt];
}

+ (NSDate *)dateWithAEDesc:(NSAppleEventDescriptor *)desc {
    CFAbsoluteTime absTime;
    UCConvertLongDateTimeToCFAbsoluteTime([desc longDateTimeValue], &absTime);
    NSDate *resultDate = (NSDate *)CFDateCreate(NULL, absTime);
    return [resultDate autorelease];
}

@end



static inline int areEqualEncodings(const char *enc1, const char *enc2) {
    return (strcmp(enc1, enc2) == 0);
}

@implementation NSNumber (JavaAppleScriptEngineAdditions)

-(id)jaseDescriptorValueWithFloatP:(void *)float_p byteCount:(int)bytes {
    float floatVal;
    if (bytes < sizeof(Float32)) {
        floatVal = [self floatValue];
        float_p = &floatVal;
        bytes = sizeof(floatVal);
    }

    double doubleVal;
    if (bytes > sizeof(Float64)) {
        doubleVal = [self doubleValue];
        float_p = &doubleVal;
        bytes = sizeof(doubleVal);
    }

    if (bytes == sizeof(Float32)) {
        return [NSAppleEventDescriptor descriptorWithFloat32:*(Float32 *)float_p];
    }

    if (bytes == sizeof(Float64)) {
        return [NSAppleEventDescriptor descriptorWithFloat64:*(Float64 *)float_p];
    }

    [NSException raise:NSInvalidArgumentException
                format:@"Cannot create an NSAppleEventDescriptor for float with %d bytes of data.",  bytes];

    return nil;
}

-(id)jaseDescriptorValueWithSignedIntP:(void *)int_p byteCount:(int)bytes {
    int intVal;

    if (bytes < sizeof(SInt16)) {
        intVal = [self intValue];
        int_p = &intVal;
        bytes = sizeof(intVal);
    }

    if (bytes == sizeof(SInt16)) {
        return [NSAppleEventDescriptor descriptorWithInt16:*(SInt16 *)int_p];
    }

    if (bytes == sizeof(SInt32)) {
        return [NSAppleEventDescriptor descriptorWithInt32:*(SInt32 *)int_p];
    }

    double val = [self doubleValue];
    return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];
}

-(id)jaseDescriptorValueWithUnsignedIntP:(void *)int_p byteCount:(int)bytes {
    unsigned int uIntVal;

    if (bytes < sizeof(UInt32)) {
        uIntVal = [self unsignedIntValue];
        int_p = &uIntVal;
        bytes = sizeof(uIntVal);
    }

    if (bytes == sizeof(UInt32)) {
        return [NSAppleEventDescriptor descriptorWithUnsignedInt32:*(UInt32 *)int_p];
    }

    double val = (double)[self unsignedLongLongValue];
    return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];
}

- (NSAppleEventDescriptor *)aeDescriptorValue {
    // NSNumber is unfortunately complicated, because the applescript
    // type we should use depends on the c type that our NSNumber corresponds to

    const char *type = [self objCType];

    // convert
    if (areEqualEncodings(type, @encode(BOOL))) {
        return [NSAppleEventDescriptor descriptorWithBoolean:[self boolValue]];
    }

    if (areEqualEncodings(type, @encode(char))) {
        char val = [self charValue];
        return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(short))) {
        short val = [self shortValue];
        return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(int))) {
        int val = [self intValue];
        return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(long))) {
        long val = [self longValue];
        return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(long long))) {
        long long val = [self longLongValue];
        return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(unsigned char))) {
        unsigned char val = [self unsignedCharValue];
        return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(unsigned short))) {
        unsigned short val = [self unsignedShortValue];
        return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(unsigned int))) {
        unsigned int val = [self unsignedIntValue];
        return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(unsigned long))) {
        unsigned long val = [self unsignedLongValue];
        return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(unsigned long long))) {
        unsigned long long val = [self unsignedLongLongValue];
        return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(float))) {
        float val = [self floatValue];
        return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];
    }

    if (areEqualEncodings(type, @encode(double))) {
        double val = [self doubleValue];
        return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];
    }

    [NSException raise:@"jaseUnsupportedAEDescriptorConversion"
                format:@"JavaAppleScriptEngineAdditions: conversion of an NSNumber with objCType '%s' to an aeDescriptor is not supported.", type];

    return nil;
}

+ (id)numberWithAEDesc:(NSAppleEventDescriptor *)desc {
    DescType type = [desc descriptorType];

    if ((type == typeTrue) || (type == typeFalse) || (type == typeBoolean)) {
        return [NSNumber numberWithBool:[desc booleanValue]];
    }

    if (type == typeSInt16) {
        SInt16 val = [desc int16Value];
        return [NSNumber jaseNumberWithSignedIntP:&val byteCount:sizeof(val)];
    }

    if (type == typeSInt32) {
        SInt32 val = [desc int32Value];
        return [NSNumber jaseNumberWithSignedIntP:&val byteCount:sizeof(val)];
    }

    if (type == typeUInt32) {
        UInt32 val = [desc unsignedInt32Value];
        return [NSNumber jaseNumberWithUnsignedIntP:&val byteCount:sizeof(val)];
    }

    if (type == typeIEEE32BitFloatingPoint) {
        Float32 val = [desc float32Value];
        return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)];
    }

    if (type == typeIEEE64BitFloatingPoint) {
        Float64 val = [desc float64Value];
        return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)];
    }

    // try to coerce to 64bit floating point
    desc = [desc coerceToDescriptorType:typeIEEE64BitFloatingPoint];
    if (desc != nil) {
        Float64 val = [desc float64Value];
        return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)];
    }

    [NSException raise:@"jaseUnsupportedAEDescriptorConversion"
                format:@"JavaAppleScriptEngineAdditions: conversion of an NSAppleEventDescriptor with objCType '%s' to an aeDescriptor is not supported.", type];

    return nil;
}

+ (id) jaseNumberWithSignedIntP:(void *)int_p byteCount:(int)bytes {
    if (bytes == sizeof(char)) {
        return [NSNumber numberWithChar:*(char *)int_p];
    }

    if (bytes == sizeof(short)) {
        return [NSNumber numberWithShort:*(short *)int_p];
    }

    if (bytes == sizeof(int)) {
        return [NSNumber numberWithInt:*(int *)int_p];
    }

    if (bytes == sizeof(long)) {
        return [NSNumber numberWithLong:*(long *)int_p];
    }

    if (bytes == sizeof(long long)) {
        return [NSNumber numberWithLongLong:*(long long *)int_p];
    }

    [NSException raise:NSInvalidArgumentException
                format:@"NSNumber jaseNumberWithSignedIntP:byteCount: number with %i bytes not supported.", bytes];

    return nil;
}

+ (id) jaseNumberWithUnsignedIntP:(void *)int_p byteCount:(int)bytes {
    if (bytes == sizeof(unsigned char)) {
        return [NSNumber numberWithUnsignedChar:*(unsigned char *)int_p];
    }

    if (bytes == sizeof(unsigned short)) {
        return [NSNumber numberWithUnsignedShort:*(unsigned short *)int_p];
    }

    if (bytes == sizeof(unsigned int)) {
        return [NSNumber numberWithUnsignedInt:*(unsigned int *)int_p];
    }

    if (bytes == sizeof(unsigned long)) {
        return [NSNumber numberWithUnsignedLong:*(unsigned long *)int_p];
    }

    if (bytes == sizeof(unsigned long long)) {
        return [NSNumber numberWithUnsignedLongLong:*(unsigned long long *)int_p];
    }

    [NSException raise:NSInvalidArgumentException
                format:@"NSNumber numberWithUnsignedInt:byteCount: number with %i bytes not supported.", bytes];

    return nil;
}

+ (id) jaseNumberWithFloatP:(void *)float_p byteCount:(int)bytes {
    if (bytes == sizeof(float)) {
        return [NSNumber numberWithFloat:*(float *)float_p];
    }

    if (bytes == sizeof(double)) {
        return [NSNumber numberWithFloat:*(double *)float_p];
    }

    [NSException raise:NSInvalidArgumentException
                format:@"NSNumber numberWithFloat:byteCount: floating point number with %i bytes not supported.", bytes];

    return nil;
}

@end

@implementation NSValue (JavaAppleScriptEngineAdditions)

- (NSAppleEventDescriptor *)aeDescriptorValue {
    const char *type = [self objCType];

    if (areEqualEncodings(type, @encode(NSSize))) {
        NSSize size = [self sizeValue];
        return [[NSArray arrayWithObjects:
                 [NSNumber numberWithFloat:size.width],
                 [NSNumber numberWithFloat:size.height], nil] aeDescriptorValue];
    }

    if (areEqualEncodings(type, @encode(NSPoint))) {
        NSPoint point = [self pointValue];
        return [[NSArray arrayWithObjects:
                 [NSNumber numberWithFloat:point.x],
                 [NSNumber numberWithFloat:point.y], nil] aeDescriptorValue];
    }

    if (areEqualEncodings(type, @encode(NSRange))) {
        NSRange range = [self rangeValue];
        return [[NSArray arrayWithObjects:
                 [NSNumber numberWithUnsignedInt:range.location],
                 [NSNumber numberWithUnsignedInt:range.location + range.length], nil] aeDescriptorValue];
    }

    if (areEqualEncodings(type, @encode(NSRect))) {
        NSRect rect = [self rectValue];
        return [[NSArray arrayWithObjects:
                 [NSNumber numberWithFloat:rect.origin.x],
                 [NSNumber numberWithFloat:rect.origin.y],
                 [NSNumber numberWithFloat:rect.origin.x + rect.size.width],
                 [NSNumber numberWithFloat:rect.origin.y + rect.size.height], nil] aeDescriptorValue];
    }

    [NSException raise:@"jaseUnsupportedAEDescriptorConversion"
                format:@"JavaAppleScriptEngineAdditions: conversion of an NSNumber with objCType '%s' to an aeDescriptor is not supported.", type];

    return nil;
}

@end


@implementation NSImage (JavaAppleScriptEngineAdditions)

- (NSAppleEventDescriptor *)aeDescriptorValue {
    NSData *data = [self TIFFRepresentation];
    return [NSAppleEventDescriptor descriptorWithDescriptorType:typeTIFF data:data];
}

+ (NSImage *)imageWithAEDesc:(NSAppleEventDescriptor *)desc {
    const AEDesc *d = [desc aeDesc];
    NSMutableData *data = [NSMutableData dataWithLength:AEGetDescDataSize(d)];
    AEGetDescData(d, [data mutableBytes], [data length]);
    return [[[NSImage alloc] initWithData:data] autorelease];
}

@end



@implementation NSAppleEventDescriptor (JavaAppleScriptEngineAdditions)

// we're going to leak this.  It doesn't matter much for running apps, but
// for developers it might be nice to try to dispose of it (so it would not clutter the
// output when testing for leaks)
static NSMutableDictionary *handlerDict = nil;

- (id)objCObjectValue {
    if (handlerDict == nil) [NSAppleEventDescriptor jaseSetUpHandlerDict];

    id returnObj;
    DescType type = [self descriptorType];
    NSInvocation *handlerInvocation = [handlerDict objectForKey:[NSValue valueWithBytes:&type objCType:@encode(DescType)]];
    if (handlerInvocation == nil) {
        if (type == typeType) {
            DescType subType;
            AEGetDescData([self aeDesc], &subType, sizeof(subType));
            if (subType == typeNull) return [NSNull null];
        }
        // return raw apple event descriptor if no handler is registered
        returnObj = self;
    } else {
        [handlerInvocation setArgument:&self atIndex:2];
        [handlerInvocation invoke];
        [handlerInvocation getReturnValue:&returnObj];
    }

    return returnObj;
}

// FIXME - error checking, non nil handler
+ (void)registerConversionHandler:(id)anObject selector:(SEL)aSelector forDescriptorTypes:(DescType)firstType, ... {
    if (handlerDict == nil) [NSAppleEventDescriptor jaseSetUpHandlerDict];

    NSInvocation *handlerInvocation = [NSInvocation invocationWithMethodSignature:[anObject methodSignatureForSelector:aSelector]];
    [handlerInvocation setTarget:anObject];
    [handlerInvocation setSelector:aSelector];

    DescType aType = firstType;
    va_list typesList;
    va_start(typesList, firstType);
    do {
        NSValue *type = [NSValue valueWithBytes:&aType objCType:@encode(DescType)];
        [handlerDict setObject:handlerInvocation forKey:type];
    } while((aType = va_arg(typesList, DescType)) != 0);
    va_end(typesList);
}


- (NSAppleEventDescriptor *)aeDescriptorValue {
    return self;
}

+ (id)descriptorWithInt16:(SInt16)val {
    return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt16 bytes:&val length:sizeof(val)];
}

- (SInt16)int16Value {
    SInt16 retValue;
    [[[self coerceToDescriptorType:typeSInt16] data] getBytes:&retValue];
    return retValue;
}

+ (id)descriptorWithUnsignedInt32:(UInt32)val {
    return [NSAppleEventDescriptor descriptorWithDescriptorType:typeUInt32 bytes:&val length:sizeof(val)];
}

- (UInt32)unsignedInt32Value {
    UInt32 retValue;
    [[[self coerceToDescriptorType:typeUInt32] data] getBytes:&retValue];
    return retValue;
}


+ (id)descriptorWithFloat32:(Float32)val {
    return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE32BitFloatingPoint bytes:&val length:sizeof(val)];
}

- (Float32)float32Value {
    Float32 retValue;
    [[[self coerceToDescriptorType:typeIEEE32BitFloatingPoint] data] getBytes:&retValue];
    return retValue;
}


+ (id)descriptorWithFloat64:(Float64)val {
    return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&val length:sizeof(val)];
}

- (Float64)float64Value {
    Float64 retValue;
    [[[self coerceToDescriptorType:typeIEEE64BitFloatingPoint] data] getBytes:&retValue];
    return retValue;
}

+ (id)descriptorWithLongDateTime:(LongDateTime)val {
    return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&val length:sizeof(val)];
}

- (LongDateTime)longDateTimeValue {
    LongDateTime retValue;
    [[[self coerceToDescriptorType:typeLongDateTime] data] getBytes:&retValue];
    return retValue;
}

+ (void)jaseSetUpHandlerDict {
    handlerDict = [[NSMutableDictionary alloc] init];

    // register default handlers
    // types are culled from AEDataModel.h and AERegistry.h

    // string -> NSStrings
    [NSAppleEventDescriptor registerConversionHandler:[NSString class] selector:@selector(stringWithAEDesc:) forDescriptorTypes:
     typeUnicodeText, typeText, typeUTF8Text, typeCString, typeChar, nil];

    // number/bool -> NSNumber
    [NSAppleEventDescriptor registerConversionHandler:[NSNumber class] selector:@selector(numberWithAEDesc:) forDescriptorTypes:
     typeBoolean, typeTrue, typeFalse,
     typeSInt16, typeSInt32, typeUInt32, typeSInt64,
     typeIEEE32BitFloatingPoint, typeIEEE64BitFloatingPoint, type128BitFloatingPoint, nil];

    // list -> NSArray
    [NSAppleEventDescriptor registerConversionHandler:[NSArray class] selector:@selector(arrayWithAEDesc:) forDescriptorTypes:typeAEList, nil];

    // record -> NSDictionary
    [NSAppleEventDescriptor registerConversionHandler:[NSDictionary class] selector:@selector(dictionaryWithAEDesc:) forDescriptorTypes:typeAERecord, nil];

    // date -> NSDate
    [NSAppleEventDescriptor registerConversionHandler:[NSDate class] selector:@selector(dateWithAEDesc:) forDescriptorTypes:typeLongDateTime, nil];

    // images -> NSImage
    [NSAppleEventDescriptor registerConversionHandler:[NSImage class] selector:@selector(imageWithAEDesc:) forDescriptorTypes:
     typeTIFF, typeJPEG, typeGIF, typePict, typeIconFamily, typeIconAndMask, nil];

    // vers -> NSString
    [NSAppleEventDescriptor registerConversionHandler:[NSString class] selector:@selector(versionWithAEDesc:) forDescriptorTypes:typeVersion, nil];

    // null -> NSNull
    [NSAppleEventDescriptor registerConversionHandler:[NSNull class] selector:@selector(nullWithAEDesc:) forDescriptorTypes:typeNull, nil];
}

@end

Other Java examples (source code examples)

Here is a short list of links related to this Java AS_NS_ConversionUtils.m source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.