text:
#import "ORKESerialization.h"

@import ResearchKit.Private;

@import MapKit;

static NSString *ORKEStringFromDateISO8601(NSDate *date) {
    static NSDateFormatter *formatter = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        formatter = [[NSDateFormatter alloc] init];
        [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
        [formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
    });
    return [formatter stringFromDate:date];
}

static NSDate *ORKEDateFromStringISO8601(NSString *string) {
    static NSDateFormatter *formatter = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        formatter = [[NSDateFormatter alloc] init];
        [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
        [formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
    });
    return [formatter dateFromString:string];
}

static NSArray *ORKNumericAnswerStyleTable() {
    static NSArray *table = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        table = @[@"decimal", @"integer"];
    });
    return table;
}

static id tableMapForward(NSInteger index, NSArray *table) {
    return table[index];
}

static NSInteger tableMapReverse(id value, NSArray *table) {
    NSUInteger idx = [table indexOfObject:value];
    if (idx == NSNotFound)
    {
        idx = 0;
    }
    return idx;
}

static NSDictionary *dictionaryFromCGPoint(CGPoint p) {
    return @{ @"x": @(p.x), @"y": @(p.y) };
}

static NSDictionary *dictionaryFromCGSize(CGSize s) {
    return @{ @"h": @(s.height), @"w": @(s.width) };
}

static NSDictionary *dictionaryFromCGRect(CGRect r) {
    return @{ @"origin": dictionaryFromCGPoint(r.origin), @"size": dictionaryFromCGSize(r.size) };
}

static NSDictionary *dictionaryFromUIEdgeInsets(UIEdgeInsets i) {
    return @{ @"top": @(i.top), @"left": @(i.left), @"bottom": @(i.bottom), @"right": @(i.right) };
}

static CGSize sizeFromDictionary(NSDictionary *dict) {
    return (CGSize){.width = ((NSNumber *)dict[@"w"]).doubleValue, .height = ((NSNumber *)dict[@"h"]).doubleValue };
}

static CGPoint pointFromDictionary(NSDictionary *dict) {
    return (CGPoint){.x = ((NSNumber *)dict[@"x"]).doubleValue, .y = ((NSNumber *)dict[@"y"]).doubleValue};
}

static CGRect rectFromDictionary(NSDictionary *dict) {
    return (CGRect){.origin = pointFromDictionary(dict[@"origin"]), .size = sizeFromDictionary(dict[@"size"])};
}

static UIEdgeInsets edgeInsetsFromDictionary(NSDictionary *dict) {
    return (UIEdgeInsets){.top = ((NSNumber *)dict[@"top"]).doubleValue, .left = ((NSNumber *)dict[@"left"]).doubleValue, .bottom = ((NSNumber *)dict[@"bottom"]).doubleValue, .right = ((NSNumber *)dict[@"right"]).doubleValue};
}

static NSDictionary *dictionaryFromCoordinate (CLLocationCoordinate2D coordinate) {
    return @{ @"latitude": @(coordinate.latitude), @"longitude": @(coordinate.longitude) };
}

static CLLocationCoordinate2D coordinateFromDictionary(NSDictionary *dict) {
    return (CLLocationCoordinate2D){.latitude = ((NSNumber *)dict[@"latitude"]).doubleValue, .longitude = ((NSNumber *)dict[@"longitude"]).doubleValue };
}

static ORKNumericAnswerStyle ORKNumericAnswerStyleFromString(NSString *s) {
    return tableMapReverse(s, ORKNumericAnswerStyleTable());
}

static NSString *ORKNumericAnswerStyleToString(ORKNumericAnswerStyle style) {
    return tableMapForward(style, ORKNumericAnswerStyleTable());
}

static NSMutableDictionary *ORKESerializationEncodingTable();
static id propFromDict(NSDictionary *dict, NSString *propName);
static NSArray *classEncodingsForClass(Class c) ;
static id objectForJsonObject(id input, Class expectedClass, ORKESerializationJSONToObjectBlock converterBlock) ;

#define ESTRINGIFY2( x) #x
#define ESTRINGIFY(x) ESTRINGIFY2(x)

#define ENTRY(entryName, bb, props) @ESTRINGIFY(entryName) : [[ORKESerializableTableEntry alloc] initWithClass:[entryName class] initBlock:bb properties: props]

#define PROPERTY(x, vc, cc, ww, jb, ob) @ESTRINGIFY(x) : ([[ORKESerializableProperty alloc] initWithPropertyName:@ESTRINGIFY(x) valueClass:[vc class] containerClass:[cc class] writeAfterInit:ww objectToJSONBlock:jb jsonToObjectBlock:ob ])

#define DYNAMICCAST(x, c) ((c *) ([x isKindOfClass:[c class]] ? x : nil))

@interface ORKESerializableTableEntry : NSObject

- (instancetype)initWithClass:(Class)class
                    initBlock:(ORKESerializationInitBlock)initBlock
                   properties:(NSDictionary *)properties;

@property (nonatomic) Class class;
@property (nonatomic, copy) ORKESerializationInitBlock initBlock;
@property (nonatomic, strong) NSMutableDictionary *properties;

@end

@interface ORKESerializableProperty : NSObject

- (instancetype)initWithPropertyName:(NSString *)propertyName
                          valueClass:(Class)valueClass
                      containerClass:(Class)containerClass
                      writeAfterInit:(BOOL)writeAfterInit
                   objectToJSONBlock:(ORKESerializationObjectToJSONBlock)objectToJSON
                   jsonToObjectBlock:(ORKESerializationJSONToObjectBlock)jsonToObjectBlock;

@property (nonatomic, copy) NSString *propertyName;
@property (nonatomic) Class valueClass;
@property (nonatomic) Class containerClass;
@property (nonatomic) BOOL writeAfterInit;
@property (nonatomic, copy) ORKESerializationObjectToJSONBlock objectToJSONBlock;
@property (nonatomic, copy) ORKESerializationJSONToObjectBlock jsonToObjectBlock;

@end

@implementation ORKESerializableTableEntry

- (instancetype)initWithClass:(Class)class
                    initBlock:(ORKESerializationInitBlock)initBlock
                   properties:(NSDictionary *)properties {
    self = [super init];
    if (self) {
        _class = class;
        self.initBlock = initBlock;
        self.properties = [properties mutableCopy];
    }
    return self;
}

@end

@implementation ORKESerializableProperty

- (instancetype)initWithPropertyName:(NSString *)propertyName
                          valueClass:(Class)valueClass
                      containerClass:(Class)containerClass
                      writeAfterInit:(BOOL)writeAfterInit
                   objectToJSONBlock:(ORKESerializationObjectToJSONBlock)objectToJSON
                   jsonToObjectBlock:(ORKESerializationJSONToObjectBlock)jsonToObjectBlock {
    self = [super init];
    if (self) {
        self.propertyName = propertyName;
        self.valueClass = valueClass;
        self.containerClass = containerClass;
        self.writeAfterInit = writeAfterInit;
        self.objectToJSONBlock = objectToJSON;
        self.jsonToObjectBlock = jsonToObjectBlock;
    }
    return self;
}

@end

static NSString *_ClassKey = @"_class";

static id propFromDict(NSDictionary *dict, NSString *propName) {
    NSArray *classEncodings = classEncodingsForClass(NSClassFromString(dict[_ClassKey]));
    ORKESerializableProperty *propertyEntry = nil;
    for (ORKESerializableTableEntry *classEncoding in classEncodings) {

        NSDictionary *propertyEncoding = classEncoding.properties;
        propertyEntry = propertyEncoding[propName];
        if (propertyEntry != nil) {
            break;
        }
    }
    NSCAssert(propertyEntry != nil, @"Unexpected property %@ for class %@", propName, dict[_ClassKey]);

    Class containerClass = propertyEntry.containerClass;
    Class propertyClass = propertyEntry.valueClass;
    ORKESerializationJSONToObjectBlock converterBlock = propertyEntry.jsonToObjectBlock;

    id input = dict[propName];
    id output = nil;
    if (input != nil) {
        if ([containerClass isSubclassOfClass:[NSArray class]]) {
            NSMutableArray *outputArray = [NSMutableArray array];
            for (id value in DYNAMICCAST(input, NSArray)) {
                id convertedValue = objectForJsonObject(value, propertyClass, converterBlock);
                NSCAssert(convertedValue != nil, @"Could not convert to object of class %@", propertyClass);
                [outputArray addObject:convertedValue];
            }
            output = outputArray;
        } else if ([containerClass isSubclassOfClass:[NSDictionary class]]) {
            NSMutableDictionary *outputDictionary = [NSMutableDictionary dictionary];
            for (NSString *key in [DYNAMICCAST(input, NSDictionary) allKeys]) {
                id convertedValue = objectForJsonObject(DYNAMICCAST(input, NSDictionary)[key], propertyClass, converterBlock);
                NSCAssert(convertedValue != nil, @"Could not convert to object of class %@", propertyClass);
                outputDictionary[key] = convertedValue;
            }
            output = outputDictionary;
        } else {
            NSCAssert(containerClass == [NSObject class], @"Unexpected container class %@", containerClass);

            output = objectForJsonObject(input, propertyClass, converterBlock);
        }
    }
    return output;
}

#define NUMTOSTRINGBLOCK(table) ^id(id num) { return table[((NSNumber *)num).integerValue]; }
#define STRINGTONUMBLOCK(table) ^id(id string) { NSUInteger index = [table indexOfObject:string]; \
    NSCAssert(index != NSNotFound, @"Expected valid entry from table %@", table); \
    return @(index); \
}

@implementation ORKESerializer

static NSArray *ORKChoiceAnswerStyleTable() {
    static NSArray *table;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        table = @[@"singleChoice", @"multipleChoice"];
    });

    return table;
}

static NSArray *ORKDateAnswerStyleTable() {
    static NSArray *table = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        table = @[@"dateTime", @"date"];
    });
    return table;
}

static NSArray *buttonIdentifierTable() {
    static NSArray *table = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        table = @[@"none", @"left", @"right"];
    });
    return table;
}

static NSArray *memoryGameStatusTable() {
    static NSArray *table = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        table = @[@"unknown", @"success", @"failure", @"timeout"];
    });
    return table;
}

static NSArray *numberFormattingStyleTable() {
    static NSArray *table = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        table = @[@"default", @"percent"];
    });
    return table;
}

#define GETPROP(d,x) getter(d, @ESTRINGIFY(x))
static NSMutableDictionary *ORKESerializationEncodingTable() {
    static dispatch_once_t onceToken;
    static NSMutableDictionary *encondingTable = nil;
    dispatch_once(&onceToken, ^{
encondingTable =
[@{
   ENTRY(ORKResultSelector,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             ORKResultSelector *selector = [[ORKResultSelector alloc] initWithTaskIdentifier:GETPROP(dict, taskIdentifier)
                                                                          stepIdentifier:GETPROP(dict, stepIdentifier)
                                                                        resultIdentifier:GETPROP(dict, resultIdentifier)];
             return selector;
         },(@{
            PROPERTY(taskIdentifier, NSString, NSObject, YES, nil, nil),
            PROPERTY(stepIdentifier, NSString, NSObject, YES, nil, nil),
            PROPERTY(resultIdentifier, NSString, NSObject, YES, nil, nil),
            })),
   ENTRY(ORKPredicateStepNavigationRule,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             ORKPredicateStepNavigationRule *rule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:GETPROP(dict, resultPredicates)
                                                                                destinationStepIdentifiers:GETPROP(dict, destinationStepIdentifiers)
                                                                                defaultStepIdentifier:GETPROP(dict, defaultStepIdentifier)
                                                                                validateArrays:NO];
             return rule;
         },(@{
              PROPERTY(resultPredicates, NSPredicate, NSArray, NO, nil, nil),
              PROPERTY(destinationStepIdentifiers, NSString, NSArray, NO, nil, nil),
              PROPERTY(defaultStepIdentifier, NSString, NSObject, NO, nil, nil),
              PROPERTY(additionalTaskResults, ORKTaskResult, NSArray, YES, nil, nil)
              })),
   ENTRY(ORKDirectStepNavigationRule,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             ORKDirectStepNavigationRule *rule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:GETPROP(dict, destinationStepIdentifier)];
             return rule;
         },(@{
              PROPERTY(destinationStepIdentifier, NSString, NSObject, NO, nil, nil),
              })),
   ENTRY(ORKAudioLevelNavigationRule,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             ORKAudioLevelNavigationRule *rule = [[ORKAudioLevelNavigationRule alloc] initWithAudioLevelStepIdentifier:GETPROP(dict, audioLevelStepIdentifier)                                                                                destinationStepIdentifier:GETPROP(dict, destinationStepIdentifier)
                                                                                recordingSettings:GETPROP(dict, recordingSettings)];
             return rule;
         },(@{
              PROPERTY(audioLevelStepIdentifier, NSString, NSObject, NO, nil, nil),
              PROPERTY(destinationStepIdentifier, NSString, NSObject, NO, nil, nil),
              PROPERTY(recordingSettings, NSDictionary, NSObject, NO, nil, nil),
              })),
   ENTRY(ORKOrderedTask,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:GETPROP(dict, identifier)
                                                                         steps:GETPROP(dict, steps)];
             return task;
         },(@{
              PROPERTY(identifier, NSString, NSObject, NO, nil, nil),
              PROPERTY(steps, ORKStep, NSArray, NO, nil, nil)
              })),
   ENTRY(ORKNavigableOrderedTask,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:GETPROP(dict, identifier)
                                                                                steps:GETPROP(dict, steps)];
             return task;
         },(@{
              PROPERTY(stepNavigationRules, ORKStepNavigationRule, NSMutableDictionary, YES, nil, nil),
              PROPERTY(skipStepNavigationRules, ORKSkipStepNavigationRule, NSMutableDictionary, YES, nil, nil),
              PROPERTY(shouldReportProgress, NSNumber, NSObject, YES, nil, nil),
              })),
   ENTRY(ORKStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             ORKStep *step = [[ORKStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
             return step;
         },
         (@{
            PROPERTY(identifier, NSString, NSObject, NO, nil, nil),
            PROPERTY(optional, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(title, NSString, NSObject, YES, nil, nil),
            PROPERTY(text, NSString, NSObject, YES, nil, nil),
            PROPERTY(shouldTintImages, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(useSurveyMode, NSNumber, NSObject, YES, nil, nil)
            })),
   ENTRY(ORKReviewStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             ORKReviewStep *reviewStep = [ORKReviewStep standaloneReviewStepWithIdentifier:GETPROP(dict, identifier)
                                                                                steps:GETPROP(dict, steps)
                                                                              resultSource:GETPROP(dict, resultSource)];
             return reviewStep;
         },
         (@{
            PROPERTY(steps, ORKStep, NSArray, NO, nil, nil),
            PROPERTY(resultSource, ORKTaskResult, NSObject, NO, nil, nil),
            PROPERTY(excludeInstructionSteps, NSNumber, NSObject, YES, nil, nil)
            })),
   ENTRY(ORKVisualConsentStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKVisualConsentStep alloc] initWithIdentifier:GETPROP(dict, identifier)
                                                            document:GETPROP(dict, consentDocument)];
         },
         @{
           PROPERTY(consentDocument, ORKConsentDocument, NSObject, NO, nil, nil)
           }),
   ENTRY(ORKPasscodeStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKPasscodeStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
           PROPERTY(passcodeType, NSNumber, NSObject, YES, nil, nil)
           })),
   ENTRY(ORKWaitStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKWaitStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
           PROPERTY(indicatorType, NSNumber, NSObject, YES, nil, nil)
           })),
   ENTRY(ORKRecorderConfiguration,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             ORKRecorderConfiguration *recorderConfiguration = [[ORKRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier)];
             return recorderConfiguration;
         },
         (@{
            PROPERTY(identifier, NSString, NSObject, NO, nil, nil),
            })),
   ENTRY(ORKQuestionStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKQuestionStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(answerFormat, ORKAnswerFormat, NSObject, YES, nil, nil),
            PROPERTY(placeholder, NSString, NSObject, YES, nil, nil)
            })),
   ENTRY(ORKInstructionStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKInstructionStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(detailText, NSString, NSObject, YES, nil, nil),
            })),
   ENTRY(ORKCompletionStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKCompletionStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            })),
   ENTRY(ORKCountdownStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKCountdownStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            })),
   ENTRY(ORKHealthQuantityTypeRecorderConfiguration,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKHealthQuantityTypeRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier) healthQuantityType:GETPROP(dict, quantityType) unit:GETPROP(dict, unit)];
         },
         (@{
            PROPERTY(quantityType, HKQuantityType, NSObject, NO,
                     ^id(id type) { return [(HKQuantityType *)type identifier]; },
                     ^id(id string) { return [HKQuantityType quantityTypeForIdentifier:string]; }),
            PROPERTY(unit, HKUnit, NSObject, NO,
                     ^id(id unit) { return [(HKUnit *)unit unitString]; },
                     ^id(id string) { return [HKUnit unitFromString:string]; }),
            })),
   ENTRY(ORKActiveStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKActiveStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(stepDuration, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldShowDefaultTimer, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldSpeakCountDown, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldSpeakRemainingTimeAtHalfway, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldStartTimerAutomatically, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldPlaySoundOnStart, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldPlaySoundOnFinish, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldVibrateOnStart, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldVibrateOnFinish, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldUseNextAsSkipButton, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(shouldContinueOnFinish, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(spokenInstruction, NSString, NSObject, YES, nil, nil),
            PROPERTY(finishedSpokenInstruction, NSString, NSObject, YES, nil, nil),
            PROPERTY(recorderConfigurations, ORKRecorderConfiguration, NSArray, YES, nil, nil),
            })),
   ENTRY(ORKAudioStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKAudioStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            })),
  ENTRY(ORKToneAudiometryStep,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKToneAudiometryStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
        },
        (@{
           PROPERTY(toneDuration, NSNumber, NSObject, YES, nil, nil),
           })),
   ENTRY(ORKToneAudiometryPracticeStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKToneAudiometryPracticeStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{})),
   ENTRY(ORKHolePegTestPlaceStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKHolePegTestPlaceStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(movingDirection, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(dominantHandTested, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(numberOfPegs, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(threshold, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(rotated, NSNumber, NSObject, YES, nil, nil)
            })),
   ENTRY(ORKHolePegTestRemoveStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKHolePegTestRemoveStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(movingDirection, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(dominantHandTested, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(numberOfPegs, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(threshold, NSNumber, NSObject, YES, nil, nil)
            })),
   ENTRY(ORKImageCaptureStep,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKImageCaptureStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
        },
        (@{
            PROPERTY(templateImageInsets, NSValue, NSObject, YES,
                ^id(id value) { return value?dictionaryFromUIEdgeInsets(((NSValue *)value).UIEdgeInsetsValue):nil; },
                ^id(id dict) { return [NSValue valueWithUIEdgeInsets:edgeInsetsFromDictionary(dict)]; }),
            PROPERTY(accessibilityHint, NSString, NSObject, YES, nil, nil),
            PROPERTY(accessibilityInstructions, NSString, NSObject, YES, nil, nil),
            })),
  ENTRY(ORKSignatureStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKSignatureStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            })),
  ENTRY(ORKSpatialSpanMemoryStep,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKSpatialSpanMemoryStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
        },
        (@{
          PROPERTY(initialSpan, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(minimumSpan, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(maximumSpan, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(playSpeed, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(maximumTests, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(maximumConsecutiveFailures, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(requireReversal, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(customTargetPluralName, NSString, NSObject, YES, nil, nil),
          })),
  ENTRY(ORKWalkingTaskStep,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKWalkingTaskStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
        },
        (@{
          PROPERTY(numberOfStepsPerLeg, NSNumber, NSObject, YES, nil, nil),
          })),
   ENTRY(ORKTableStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKTableStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(items, NSObject, NSArray, YES, nil, nil),
            })),
   ENTRY(ORKTimedWalkStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKTimedWalkStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(distanceInMeters, NSNumber, NSObject, YES, nil, nil),
            })),
   ENTRY(ORKPSATStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKPSATStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(presentationMode, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(interStimulusInterval, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(stimulusDuration, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(seriesLength, NSNumber, NSObject, YES, nil, nil),
            })),
   ENTRY(ORKReactionTimeStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKReactionTimeStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(maximumStimulusInterval, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(minimumStimulusInterval, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(timeout, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(numberOfAttempts, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(thresholdAcceleration, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(successSound, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(timeoutSound, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(failureSound, NSNumber, NSObject, YES, nil, nil),
            })),
   ENTRY(ORKTappingIntervalStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKTappingIntervalStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            })),
   ENTRY(ORKTowerOfHanoiStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKTowerOfHanoiStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
         },
         (@{
            PROPERTY(numberOfDisks, NSNumber, NSObject, YES, nil, nil),
            })),
  ENTRY(ORKAccelerometerRecorderConfiguration,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier) frequency:((NSNumber *)GETPROP(dict, frequency)).doubleValue];
        },
        (@{
          PROPERTY(frequency, NSNumber, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKAudioRecorderConfiguration,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKAudioRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier) recorderSettings:GETPROP(dict, recorderSettings)];
        },
        (@{
          PROPERTY(recorderSettings, NSDictionary, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKConsentDocument,
        nil,
        (@{
          PROPERTY(title, NSString, NSObject, NO, nil, nil),
          PROPERTY(sections, ORKConsentSection, NSArray, NO, nil, nil),
          PROPERTY(signaturePageTitle, NSString, NSObject, NO, nil, nil),
          PROPERTY(signaturePageContent, NSString, NSObject, NO, nil, nil),
          PROPERTY(signatures, ORKConsentSignature, NSArray, NO, nil, nil),
          PROPERTY(htmlReviewContent, NSString, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKConsentSharingStep,
        ^(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKConsentSharingStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
        },
        (@{
           PROPERTY(localizedLearnMoreHTMLContent, NSString, NSObject, YES, nil, nil),
           })),
  ENTRY(ORKConsentReviewStep,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKConsentReviewStep alloc] initWithIdentifier:GETPROP(dict, identifier) signature:GETPROP(dict, signature) inDocument:GETPROP(dict,consentDocument)];
        },
        (@{
          PROPERTY(consentDocument, ORKConsentDocument, NSObject, NO, nil, nil),
          PROPERTY(reasonForConsent, NSString, NSObject, YES, nil, nil),
          PROPERTY(signature, ORKConsentSignature, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKFitnessStep,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKFitnessStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
        },
        (@{
           })),
  ENTRY(ORKConsentSection,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKConsentSection alloc] initWithType:((NSNumber *)GETPROP(dict, type)).integerValue];
        },
        (@{
          PROPERTY(type, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(title, NSString, NSObject, YES, nil, nil),
          PROPERTY(formalTitle, NSString, NSObject, YES, nil, nil),
          PROPERTY(summary, NSString, NSObject, YES, nil, nil),
          PROPERTY(content, NSString, NSObject, YES, nil, nil),
          PROPERTY(htmlContent, NSString, NSObject, YES, nil, nil),
          PROPERTY(contentURL, NSURL, NSObject, YES,
                   ^id(id url) { return [(NSURL *)url absoluteString]; },
                   ^id(id string) { return [NSURL URLWithString:string]; }),
          PROPERTY(customLearnMoreButtonTitle, NSString, NSObject, YES, nil, nil),
          PROPERTY(customAnimationURL, NSURL, NSObject, YES,
                   ^id(id url) { return [(NSURL *)url absoluteString]; },
                   ^id(id string) { return [NSURL URLWithString:string]; }),
          PROPERTY(omitFromDocument, NSNumber, NSObject, YES, nil, nil),
          })),
  ENTRY(ORKConsentSignature,
        nil,
        (@{
          PROPERTY(identifier, NSString, NSObject, YES, nil, nil),
          PROPERTY(title, NSString, NSObject, YES, nil, nil),
          PROPERTY(givenName, NSString, NSObject, YES, nil, nil),
          PROPERTY(familyName, NSString, NSObject, YES, nil, nil),
          PROPERTY(signatureDate, NSString, NSObject, YES, nil, nil),
          PROPERTY(requiresName, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(requiresSignatureImage, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(signatureDateFormatString, NSString, NSObject, YES, nil, nil),
          })),
  ENTRY(ORKRegistrationStep,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKRegistrationStep alloc] initWithIdentifier:GETPROP(dict, identifier) title:GETPROP(dict, title) text:GETPROP(dict, text) options:((NSNumber *)GETPROP(dict, options)).integerValue];
        },
        (@{
           PROPERTY(options, NSNumber, NSObject, NO, nil, nil)
           })),
   ENTRY(ORKVerificationStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKVerificationStep alloc] initWithIdentifier:GETPROP(dict, identifier) text:GETPROP(dict, text) verificationViewControllerClass:NSClassFromString(GETPROP(dict, verificationViewControllerString))];
         },
         (@{
            PROPERTY(verificationViewControllerString, NSString, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKLoginStep,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKLoginStep alloc] initWithIdentifier:GETPROP(dict, identifier) title:GETPROP(dict, title) text:GETPROP(dict, text) loginViewControllerClass:NSClassFromString(GETPROP(dict, loginViewControllerString))];
         },
         (@{
            PROPERTY(loginViewControllerString, NSString, NSObject, NO, nil, nil)
            })),
  ENTRY(ORKDeviceMotionRecorderConfiguration,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier) frequency:((NSNumber *)GETPROP(dict, frequency)).doubleValue];
        },
        (@{
          PROPERTY(frequency, NSNumber, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKFormStep,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKFormStep alloc] initWithIdentifier:GETPROP(dict, identifier)];
        },
        (@{
          PROPERTY(formItems, ORKFormItem, NSArray, YES, nil, nil)
          })),
  ENTRY(ORKFormItem,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKFormItem alloc] initWithIdentifier:GETPROP(dict, identifier) text:GETPROP(dict, text) answerFormat:GETPROP(dict, answerFormat)];
        },
        (@{
          PROPERTY(identifier, NSString, NSObject, NO, nil, nil),
          PROPERTY(optional, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(text, NSString, NSObject, NO, nil, nil),
          PROPERTY(placeholder, NSString, NSObject, YES, nil, nil),
          PROPERTY(answerFormat, ORKAnswerFormat, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKHealthKitCharacteristicTypeAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKHealthKitCharacteristicTypeAnswerFormat alloc] initWithCharacteristicType:GETPROP(dict, characteristicType)];
        },
        (@{
          PROPERTY(characteristicType, HKCharacteristicType, NSObject, NO,
                   ^id(id type) { return [(HKCharacteristicType *)type identifier]; },
                   ^id(id string) { return [HKCharacteristicType characteristicTypeForIdentifier:string]; }),
          PROPERTY(defaultDate, NSDate, NSObject, YES,
                   ^id(id date) { return [ORKResultDateTimeFormatter() stringFromDate:date]; },
                   ^id(id string) { return [ORKResultDateTimeFormatter() dateFromString:string]; }),
          PROPERTY(minimumDate, NSDate, NSObject, YES,
                   ^id(id date) { return [ORKResultDateTimeFormatter() stringFromDate:date]; },
                   ^id(id string) { return [ORKResultDateTimeFormatter() dateFromString:string]; }),
          PROPERTY(maximumDate, NSDate, NSObject, YES,
                   ^id(id date) { return [ORKResultDateTimeFormatter() stringFromDate:date]; },
                   ^id(id string) { return [ORKResultDateTimeFormatter() dateFromString:string]; }),
          PROPERTY(calendar, NSCalendar, NSObject, YES,
                   ^id(id calendar) { return [(NSCalendar *)calendar calendarIdentifier]; },
                   ^id(id string) { return [NSCalendar calendarWithIdentifier:string]; }),
          })),
  ENTRY(ORKHealthKitQuantityTypeAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKHealthKitQuantityTypeAnswerFormat alloc] initWithQuantityType:GETPROP(dict, quantityType) unit:GETPROP(dict, unit) style:((NSNumber *)GETPROP(dict, numericAnswerStyle)).integerValue];
        },
        (@{
          PROPERTY(unit, HKUnit, NSObject, NO,
                   ^id(id unit) { return [(HKUnit *)unit unitString]; },
                   ^id(id string) { return [HKUnit unitFromString:string]; }),
          PROPERTY(quantityType, HKQuantityType, NSObject, NO,
                   ^id(id type) { return [(HKQuantityType *)type identifier]; },
                   ^id(id string) { return [HKQuantityType quantityTypeForIdentifier:string]; }),
          PROPERTY(numericAnswerStyle, NSNumber, NSObject, NO,
                   ^id(id num) { return ORKNumericAnswerStyleToString(((NSNumber *)num).integerValue); },
                   ^id(id string) { return @(ORKNumericAnswerStyleFromString(string)); }),
          })),
  ENTRY(ORKAnswerFormat,
        nil,
        (@{
          })),
  ENTRY(ORKValuePickerAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKValuePickerAnswerFormat alloc] initWithTextChoices:GETPROP(dict, textChoices)];
        },
        (@{
          PROPERTY(textChoices, ORKTextChoice, NSArray, NO, nil, nil),

          })),
  ENTRY(ORKImageChoiceAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKImageChoiceAnswerFormat alloc] initWithImageChoices:GETPROP(dict, imageChoices)];
        },
        (@{
          PROPERTY(imageChoices, ORKImageChoice, NSArray, NO, nil, nil),
          })),
  ENTRY(ORKTextChoiceAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKTextChoiceAnswerFormat alloc] initWithStyle:((NSNumber *)GETPROP(dict, style)).integerValue textChoices:GETPROP(dict, textChoices)];
        },
        (@{
          PROPERTY(style, NSNumber, NSObject, NO, NUMTOSTRINGBLOCK(ORKChoiceAnswerStyleTable()), STRINGTONUMBLOCK(ORKChoiceAnswerStyleTable())),
          PROPERTY(textChoices, ORKTextChoice, NSArray, NO, nil, nil),
          })),
  ENTRY(ORKTextChoice,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKTextChoice alloc] initWithText:GETPROP(dict, text) detailText:GETPROP(dict, detailText) value:GETPROP(dict, value) exclusive:((NSNumber *)GETPROP(dict, exclusive)).boolValue];
        },
        (@{
          PROPERTY(text, NSString, NSObject, NO, nil, nil),
          PROPERTY(value, NSObject, NSObject, NO, nil, nil),
          PROPERTY(detailText, NSString, NSObject, NO, nil, nil),
          PROPERTY(exclusive, NSNumber, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKImageChoice,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKImageChoice alloc] initWithNormalImage:nil selectedImage:nil text:GETPROP(dict, text) value:GETPROP(dict, value)];
        },
        (@{
          PROPERTY(text, NSString, NSObject, NO, nil, nil),
          PROPERTY(value, NSObject, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKTimeOfDayAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKTimeOfDayAnswerFormat alloc] initWithDefaultComponents:GETPROP(dict, defaultComponents)];
        },
        (@{
          PROPERTY(defaultComponents, NSDateComponents, NSObject, NO,
                   ^id(id components) { return ORKTimeOfDayStringFromComponents(components);  },
                   ^id(id string) { return ORKTimeOfDayComponentsFromString(string); })
          })),
  ENTRY(ORKDateAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKDateAnswerFormat alloc] initWithStyle:((NSNumber *)GETPROP(dict, style)).integerValue defaultDate:GETPROP(dict, defaultDate) minimumDate:GETPROP(dict, minimumDate) maximumDate:GETPROP(dict, maximumDate) calendar:GETPROP(dict, calendar)];
        },
        (@{
          PROPERTY(style, NSNumber, NSObject, NO,
                   NUMTOSTRINGBLOCK(ORKDateAnswerStyleTable()),
                   STRINGTONUMBLOCK(ORKDateAnswerStyleTable())),
          PROPERTY(calendar, NSCalendar, NSObject, NO,
                   ^id(id calendar) { return [(NSCalendar *)calendar calendarIdentifier]; },
                   ^id(id string) { return [NSCalendar calendarWithIdentifier:string]; }),
          PROPERTY(minimumDate, NSDate, NSObject, NO,
                   ^id(id date) { return [ORKResultDateTimeFormatter() stringFromDate:date]; },
                   ^id(id string) { return [ORKResultDateTimeFormatter() dateFromString:string]; }),
          PROPERTY(maximumDate, NSDate, NSObject, NO,
                   ^id(id date) { return [ORKResultDateTimeFormatter() stringFromDate:date]; },
                   ^id(id string) { return [ORKResultDateTimeFormatter() dateFromString:string]; }),
          PROPERTY(defaultDate, NSDate, NSObject, NO,
                   ^id(id date) { return [ORKResultDateTimeFormatter() stringFromDate:date]; },
                   ^id(id string) { return [ORKResultDateTimeFormatter() dateFromString:string]; }),
          })),
  ENTRY(ORKNumericAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKNumericAnswerFormat alloc] initWithStyle:((NSNumber *)GETPROP(dict, style)).integerValue unit:GETPROP(dict, unit) minimum:GETPROP(dict, minimum) maximum:GETPROP(dict, maximum)];
        },
        (@{
          PROPERTY(style, NSNumber, NSObject, NO,
                   ^id(id num) { return ORKNumericAnswerStyleToString(((NSNumber *)num).integerValue); },
                   ^id(id string) { return @(ORKNumericAnswerStyleFromString(string)); }),
          PROPERTY(unit, NSString, NSObject, NO, nil, nil),
          PROPERTY(minimum, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(maximum, NSNumber, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKScaleAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKScaleAnswerFormat alloc] initWithMaximumValue:((NSNumber *)GETPROP(dict, maximum)).integerValue minimumValue:((NSNumber *)GETPROP(dict, minimum)).integerValue defaultValue:((NSNumber *)GETPROP(dict, defaultValue)).integerValue step:((NSNumber *)GETPROP(dict, step)).integerValue vertical:((NSNumber *)GETPROP(dict, vertical)).boolValue maximumValueDescription:GETPROP(dict, maximumValueDescription) minimumValueDescription:GETPROP(dict, minimumValueDescription)];
        },
        (@{
          PROPERTY(minimum, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(maximum, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(defaultValue, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(step, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(vertical, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(maximumValueDescription, NSString, NSObject, NO, nil, nil),
          PROPERTY(minimumValueDescription, NSString, NSObject, NO, nil, nil),
          PROPERTY(gradientColors, UIColor, NSArray, YES, nil, nil),
          PROPERTY(gradientLocations, NSNumber, NSArray, YES, nil, nil)
          })),
  ENTRY(ORKContinuousScaleAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKContinuousScaleAnswerFormat alloc] initWithMaximumValue:((NSNumber *)GETPROP(dict, maximum)).doubleValue minimumValue:((NSNumber *)GETPROP(dict, minimum)).doubleValue defaultValue:((NSNumber *)GETPROP(dict, defaultValue)).doubleValue maximumFractionDigits:((NSNumber *)GETPROP(dict, maximumFractionDigits)).integerValue vertical:((NSNumber *)GETPROP(dict, vertical)).boolValue maximumValueDescription:GETPROP(dict, maximumValueDescription) minimumValueDescription:GETPROP(dict, minimumValueDescription)];
        },
        (@{
          PROPERTY(minimum, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(maximum, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(defaultValue, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(maximumFractionDigits, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(vertical, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(numberStyle, NSNumber, NSObject, YES,
                   ^id(id numeric) { return tableMapForward(((NSNumber *)numeric).integerValue, numberFormattingStyleTable()); },
                   ^id(id string) { return @(tableMapReverse(string, numberFormattingStyleTable())); }),
          PROPERTY(maximumValueDescription, NSString, NSObject, NO, nil, nil),
          PROPERTY(minimumValueDescription, NSString, NSObject, NO, nil, nil),
          PROPERTY(gradientColors, UIColor, NSArray, YES, nil, nil),
          PROPERTY(gradientLocations, NSNumber, NSArray, YES, nil, nil)
          })),
   ENTRY(ORKTextScaleAnswerFormat,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKTextScaleAnswerFormat alloc] initWithTextChoices:GETPROP(dict, textChoices) defaultIndex:[GETPROP(dict, defaultIndex) doubleValue] vertical:[GETPROP(dict, vertical) boolValue]];
         },
         (@{
            PROPERTY(textChoices, ORKTextChoice, NSArray<ORKTextChoice *>, NO, nil, nil),
            PROPERTY(defaultIndex, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(vertical, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(gradientColors, UIColor, NSArray, YES, nil, nil),
            PROPERTY(gradientLocations, NSNumber, NSArray, YES, nil, nil)
            })),
  ENTRY(ORKTextAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKTextAnswerFormat alloc] initWithMaximumLength:((NSNumber *)GETPROP(dict, maximumLength)).integerValue];
        },
        (@{
          PROPERTY(maximumLength, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(validationRegex, NSString, NSObject, YES, nil, nil),
          PROPERTY(invalidMessage, NSString, NSObject, YES, nil, nil),
          PROPERTY(autocapitalizationType, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(autocorrectionType, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(spellCheckingType, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(keyboardType, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(multipleLines, NSNumber, NSObject, YES, nil, nil),
          PROPERTY(secureTextEntry, NSNumber, NSObject, YES, nil, nil)
          })),
   ENTRY(ORKEmailAnswerFormat,
         nil,
         (@{
            })),
   ENTRY(ORKConfirmTextAnswerFormat,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKConfirmTextAnswerFormat alloc] initWithOriginalItemIdentifier:GETPROP(dict, originalItemIdentifier) errorMessage:GETPROP(dict, errorMessage)];
         },
         (@{
            PROPERTY(originalItemIdentifier, NSString, NSObject, NO, nil, nil),
            PROPERTY(errorMessage, NSString, NSObject, NO, nil, nil),
            PROPERTY(maximumLength, NSNumber, NSObject, YES, nil, nil)
            })),
  ENTRY(ORKTimeIntervalAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKTimeIntervalAnswerFormat alloc] initWithDefaultInterval:((NSNumber *)GETPROP(dict, defaultInterval)).doubleValue step:((NSNumber *)GETPROP(dict, step)).integerValue];
        },
        (@{
          PROPERTY(defaultInterval, NSNumber, NSObject, NO, nil, nil),
          PROPERTY(step, NSNumber, NSObject, NO, nil, nil),
          })),
  ENTRY(ORKBooleanAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKBooleanAnswerFormat alloc] init];
        },
        (@{
          })),
   ENTRY(ORKHeightAnswerFormat,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKHeightAnswerFormat alloc] initWithMeasurementSystem:((NSNumber *)GETPROP(dict, measurementSystem)).integerValue];
         },
         (@{
            PROPERTY(measurementSystem, NSNumber, NSObject, NO, nil, nil),
            })),
  ENTRY(ORKLocationAnswerFormat,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKLocationAnswerFormat alloc] init];
        },
        (@{
          PROPERTY(useCurrentLocation, NSNumber, NSObject, YES, nil, nil)
          })),
  ENTRY(ORKLocationRecorderConfiguration,
        ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
            return [[ORKLocationRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict,identifier)];
        },
        (@{
          })),
   ENTRY(ORKPedometerRecorderConfiguration,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKPedometerRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict,identifier)];
         },
        (@{
          })),
   ENTRY(ORKTouchRecorderConfiguration,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKTouchRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict,identifier)];
         },
        (@{
          })),
  ENTRY(ORKResult,
        nil,
        (@{
           PROPERTY(identifier, NSString, NSObject, NO, nil, nil),
           PROPERTY(startDate, NSDate, NSObject, YES,
                    ^id(id date) { return ORKEStringFromDateISO8601(date); },
                    ^id(id string) { return ORKEDateFromStringISO8601(string); }),
           PROPERTY(endDate, NSDate, NSObject, YES,
                    ^id(id date) { return ORKEStringFromDateISO8601(date); },
                    ^id(id string) { return ORKEDateFromStringISO8601(string); }),
           PROPERTY(userInfo, NSDictionary, NSObject, YES, nil, nil)
           })),
  ENTRY(ORKTappingSample,
        nil,
        (@{
           PROPERTY(timestamp, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(duration, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(buttonIdentifier, NSNumber, NSObject, NO,
                    ^id(id numeric) { return tableMapForward(((NSNumber *)numeric).integerValue, buttonIdentifierTable()); },
                    ^id(id string) { return @(tableMapReverse(string, buttonIdentifierTable())); }),
           PROPERTY(location, NSValue, NSObject, NO,
                    ^id(id value) { return value?dictionaryFromCGPoint(((NSValue *)value).CGPointValue):nil; },
                    ^id(id dict) { return [NSValue valueWithCGPoint:pointFromDictionary(dict)]; })
           })),
  ENTRY(ORKTappingIntervalResult,
        nil,
        (@{
           PROPERTY(samples, ORKTappingSample, NSArray, NO, nil, nil),
           PROPERTY(stepViewSize, NSValue, NSObject, NO,
                    ^id(id value) { return value?dictionaryFromCGSize(((NSValue *)value).CGSizeValue):nil; },
                    ^id(id dict) { return [NSValue valueWithCGSize:sizeFromDictionary(dict)]; }),
           PROPERTY(buttonRect1, NSValue, NSObject, NO,
                    ^id(id value) { return value?dictionaryFromCGRect(((NSValue *)value).CGRectValue):nil; },
                    ^id(id dict) { return [NSValue valueWithCGRect:rectFromDictionary(dict)]; }),
           PROPERTY(buttonRect2, NSValue, NSObject, NO,
                    ^id(id value) { return value?dictionaryFromCGRect(((NSValue *)value).CGRectValue):nil; },
                    ^id(id dict) { return [NSValue valueWithCGRect:rectFromDictionary(dict)]; })
           })),
  ENTRY(ORKSpatialSpanMemoryGameTouchSample,
        nil,
        (@{
           PROPERTY(timestamp, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(targetIndex, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(correct, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(location, NSValue, NSObject, NO,
                    ^id(id value) { return value?dictionaryFromCGPoint(((NSValue *)value).CGPointValue):nil; },
                    ^id(id dict) { return [NSValue valueWithCGPoint:pointFromDictionary(dict)]; })
           })),
  ENTRY(ORKSpatialSpanMemoryGameRecord,
        nil,
        (@{
           PROPERTY(seed, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(sequence, NSNumber, NSArray, NO, nil, nil),
           PROPERTY(gameSize, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(gameStatus, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(score, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(touchSamples, ORKSpatialSpanMemoryGameTouchSample, NSArray, NO,
                    ^id(id numeric) { return tableMapForward(((NSNumber *)numeric).integerValue, memoryGameStatusTable()); },
                    ^id(id string) { return @(tableMapReverse(string, memoryGameStatusTable())); }),
           PROPERTY(targetRects, NSValue, NSArray, NO,
                    ^id(id value) { return value?dictionaryFromCGRect(((NSValue *)value).CGRectValue):nil; },
                    ^id(id dict) { return [NSValue valueWithCGRect:rectFromDictionary(dict)]; })
           })),
  ENTRY(ORKSpatialSpanMemoryResult,
        nil,
        (@{
           PROPERTY(score, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(numberOfGames, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(numberOfFailures, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(gameRecords, ORKSpatialSpanMemoryGameRecord, NSArray, NO, nil, nil)
           })),
  ENTRY(ORKFileResult,
        nil,
        (@{
           PROPERTY(contentType, NSString, NSObject, NO, nil, nil),
           PROPERTY(fileURL, NSURL, NSObject, NO,
                    ^id(id url) { return [url absoluteString]; },
                    ^id(id string) { return [NSURL URLWithString:string]; })
           })),
  ENTRY(ORKToneAudiometrySample,
        nil,
        (@{
           PROPERTY(frequency, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(channel, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(amplitude, NSNumber, NSObject, NO, nil, nil)
           })),
  ENTRY(ORKToneAudiometryResult,
        nil,
        (@{
           PROPERTY(outputVolume, NSNumber, NSObject, NO, nil, nil),
           PROPERTY(samples, ORKToneAudiometrySample, NSArray, NO, nil, nil),
           })),
   ENTRY(ORKReactionTimeResult,
         nil,
         (@{
            PROPERTY(timestamp, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(fileResult, ORKResult, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKTimedWalkResult,
         nil,
         (@{
            PROPERTY(distanceInMeters, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(timeLimit, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(duration, NSNumber, NSObject, NO, nil, nil),
           })),
   ENTRY(ORKPSATSample,
         nil,
         (@{
            PROPERTY(correct, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(digit, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(answer, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(time, NSNumber, NSObject, NO, nil, nil),
            })),
   ENTRY(ORKPSATResult,
         nil,
         (@{
            PROPERTY(presentationMode, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(interStimulusInterval, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(stimulusDuration, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(length, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(totalCorrect, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(totalDyad, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(totalTime, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(initialDigit, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(samples, ORKPSATSample, NSArray, NO, nil, nil),
            })),
   ENTRY(ORKTowerOfHanoiResult,
         nil,
         (@{
            PROPERTY(puzzleWasSolved, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(moves, ORKTowerOfHanoiMove, NSArray, YES, nil, nil),
            })),
   ENTRY(ORKTowerOfHanoiMove,
         nil,
         (@{
            PROPERTY(timestamp, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(donorTowerIndex, NSNumber, NSObject, YES, nil, nil),
            PROPERTY(recipientTowerIndex, NSNumber, NSObject, YES, nil, nil),
            })),
   ENTRY(ORKHolePegTestSample,
         nil,
         (@{
            PROPERTY(time, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(distance, NSNumber, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKHolePegTestResult,
         nil,
         (@{
            PROPERTY(movingDirection, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(dominantHandTested, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(numberOfPegs, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(threshold, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(rotated, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(totalSuccesses, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(totalFailures, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(totalTime, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(totalDistance, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(samples, ORKHolePegTestSample, NSArray, NO, nil, nil),
            })),
   ENTRY(ORKPasscodeResult,
         nil,
         (@{
            PROPERTY(passcodeSaved, NSNumber, NSObject, YES, nil, nil),
            })),
    ENTRY(ORKQuestionResult,
         nil,
         (@{
            PROPERTY(questionType, NSNumber, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKDataResult,
         nil,
         (@{
            PROPERTY(contentType, NSString, NSObject, YES, nil, nil),
            PROPERTY(filename, NSString, NSObject, YES, nil, nil),
            })),
   ENTRY(ORKScaleQuestionResult,
         nil,
         (@{
            PROPERTY(scaleAnswer, NSNumber, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKChoiceQuestionResult,
         nil,
         (@{
            PROPERTY(choiceAnswers, NSObject, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKBooleanQuestionResult,
         nil,
         (@{
            PROPERTY(booleanAnswer, NSNumber, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKTextQuestionResult,
         nil,
         (@{
            PROPERTY(textAnswer, NSString, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKNumericQuestionResult,
         nil,
         (@{
            PROPERTY(numericAnswer, NSNumber, NSObject, NO, nil, nil),
            PROPERTY(unit, NSString, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKTimeOfDayQuestionResult,
         nil,
         (@{
            PROPERTY(dateComponentsAnswer, NSDateComponents, NSObject, NO,
                     ^id(id dateComponents) { return ORKTimeOfDayStringFromComponents(dateComponents); },
                     ^id(id string) { return ORKTimeOfDayComponentsFromString(string); })
            })),
   ENTRY(ORKTimeIntervalQuestionResult,
         nil,
         (@{
            PROPERTY(intervalAnswer, NSNumber, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKDateQuestionResult,
         nil,
         (@{
            PROPERTY(dateAnswer, NSDate, NSObject, NO,
                     ^id(id date) { return ORKEStringFromDateISO8601(date); },
                     ^id(id string) { return ORKEDateFromStringISO8601(string); }),
            PROPERTY(calendar, NSCalendar, NSObject, NO,
                     ^id(id calendar) { return [(NSCalendar *)calendar calendarIdentifier]; },
                     ^id(id string) { return [NSCalendar calendarWithIdentifier:string]; }),
            PROPERTY(timeZone, NSTimeZone, NSObject, NO,
                     ^id(id timezone) { return @([timezone secondsFromGMT]); },
                     ^id(id number) { return [NSTimeZone timeZoneForSecondsFromGMT:((NSNumber *)number).doubleValue]; })
            })),
   ENTRY(ORKLocation,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             CLLocationCoordinate2D coordinate = coordinateFromDictionary(dict[@ESTRINGIFY(coordinate)]);
             return [[ORKLocation alloc] initWithCoordinate:coordinate
                                                     region:GETPROP(dict, region)
                                                  userInput:GETPROP(dict, userInput)
                                          addressDictionary:GETPROP(dict, addressDictionary)];
         },
         (@{
            PROPERTY(userInput, NSString, NSObject, NO, nil, nil),
            PROPERTY(addressDictionary, NSString, NSDictionary, NO, nil, nil),
            PROPERTY(coordinate, NSValue, NSObject, NO,
                     ^id(id value) { return value ? dictionaryFromCoordinate(((NSValue *)value).MKCoordinateValue) : nil; },
                     ^id(id dict) { return [NSValue valueWithMKCoordinate:coordinateFromDictionary(dict)]; }),
            PROPERTY(region, CLCircularRegion, NSObject, NO,
                     ^id(id value) {
                         if ( nil == value ) {
                             return nil;
                         }
                         CLCircularRegion *region = value;
                         NSMutableDictionary *dict = [NSMutableDictionary dictionary];
                         dict[@"coordinate"] = dictionaryFromCoordinate(region.center);
                         dict[@"radius"] = @(region.radius);
                         dict[@"identifier"] = region.identifier;
                         return dict;
                     },
                     ^id(id dict) {
                         NSDictionary *regionDict = dict;
                         if (nil == regionDict) {
                             return nil;
                         }
                         CLLocationCoordinate2D coordinate = coordinateFromDictionary(regionDict[@"coordinate"]);
                         NSNumber *radius = regionDict[@"radius"];
                         NSString *identifier = regionDict[@"identifier"];
                         return [[CLCircularRegion alloc] initWithCenter:coordinate radius:radius.doubleValue identifier:identifier];
                     }),
            })),
   ENTRY(ORKLocationQuestionResult,
         nil,
         (@{
            PROPERTY(locationAnswer, ORKLocation, NSObject, NO, nil, nil)
            })),
   ENTRY(ORKConsentSignatureResult,
         nil,
         (@{
            PROPERTY(signature, ORKConsentSignature, NSObject, YES, nil, nil),
            PROPERTY(consented, NSNumber, NSObject, YES, nil, nil),
            })),
   ENTRY(ORKSignatureResult,
         nil,
         (@{
            })),
   ENTRY(ORKCollectionResult,
         nil,
         (@{
            PROPERTY(results, ORKResult, NSArray, YES, nil, nil)
            })),
   ENTRY(ORKTaskResult,
         ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) {
             return [[ORKTaskResult alloc] initWithTaskIdentifier:GETPROP(dict, identifier) taskRunUUID:GETPROP(dict, taskRunUUID) outputDirectory:GETPROP(dict, outputDirectory)];
         },
         (@{
            PROPERTY(taskRunUUID, NSUUID, NSObject, NO,
                     ^id(id uuid) { return [uuid UUIDString]; },
                     ^id(id string) { return [[NSUUID alloc] initWithUUIDString:string]; }),
            PROPERTY(outputDirectory, NSURL, NSObject, NO,
                     ^id(id url) { return [url absoluteString]; },
                     ^id(id string) { return [NSURL URLWithString:string]; })
            })),
   ENTRY(ORKStepResult,
         nil,
         (@{
            PROPERTY(enabledAssistiveTechnology, NSString, NSObject, YES, nil, nil),
            })),

   } mutableCopy];
    });
    return encondingTable;
}
#undef GETPROP

static NSArray *classEncodingsForClass(Class c) {
    NSDictionary *encodingTable = ORKESerializationEncodingTable();

    NSMutableArray *classEncodings = [NSMutableArray array];
    Class sc = c;
    while (sc != nil) {
        NSString *className = NSStringFromClass(sc);
        ORKESerializableTableEntry *classEncoding = encodingTable[className];
        if (classEncoding) {
            [classEncodings addObject:classEncoding];
        }
        sc = [sc superclass];
    }
    return classEncodings;
}

static id objectForJsonObject(id input, Class expectedClass, ORKESerializationJSONToObjectBlock converterBlock) {
    id output = nil;
    if (converterBlock != nil) {
        input = converterBlock(input);
    }

    if (expectedClass != nil && [input isKindOfClass:expectedClass]) {
        // Input is already of the expected class, do nothing
        output = input;
    } else if ([input isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dict = (NSDictionary *)input;
        NSString *className = input[_ClassKey];
        if (expectedClass != nil) {
            NSCAssert([NSClassFromString(className) isSubclassOfClass:expectedClass], @"Expected subclass of %@ but got %@", expectedClass, className);
        }
        NSArray *classEncodings = classEncodingsForClass(NSClassFromString(className));
        NSCAssert([classEncodings count] > 0, @"Expected serializable class but got %@", className);

        ORKESerializableTableEntry *leafClassEncoding = classEncodings.firstObject;
        ORKESerializationInitBlock initBlock = leafClassEncoding.initBlock;
        BOOL writeAllProperties = YES;
        if (initBlock != nil) {
            output = initBlock(dict,
                               ^id(NSDictionary *dict, NSString *param) {
                                   return propFromDict(dict, param); });
            writeAllProperties = NO;
        } else {
            output = [[NSClassFromString(className) alloc] init];
        }

        for (NSString *key in [dict allKeys]) {
            if ([key isEqualToString:_ClassKey]) {
                continue;
            }

            BOOL haveSetProp = NO;
            for (ORKESerializableTableEntry *encoding in classEncodings) {
                NSDictionary *propertyTable = encoding.properties;
                ORKESerializableProperty *propertyEntry = propertyTable[key];
                if (propertyEntry != nil) {
                    // Only write the property if it has not already been set during init
                    if (writeAllProperties || propertyEntry.writeAfterInit) {
                        [output setValue:propFromDict(dict,key) forKey:key];
                    }
                    haveSetProp = YES;
                    break;
                }
            }
            NSCAssert(haveSetProp, @"Unexpected property on %@: %@", className, key);
        }

    } else {
        NSCAssert(0, @"Unexpected input of class %@ for %@", [input class], expectedClass);
    }
    return output;
}

static BOOL isValid(id object) {
    return [NSJSONSerialization isValidJSONObject:object] || [object isKindOfClass:[NSNumber class]] || [object isKindOfClass:[NSString class]] || [object isKindOfClass:[NSNull class]];
}

static id jsonObjectForObject(id object) {
    if (object == nil) {
        // Leaf: nil
        return nil;
    }

    id jsonOutput = nil;
    Class c = [object class];

    NSArray *classEncodings = classEncodingsForClass(c);

    if ([classEncodings count]) {
        NSMutableDictionary *encodedDict = [NSMutableDictionary dictionary];
        encodedDict[_ClassKey] = NSStringFromClass(c);

        for (ORKESerializableTableEntry *encoding in classEncodings) {
            NSDictionary *propertyTable = encoding.properties;
            for (NSString *propertyName in [propertyTable allKeys]) {
                ORKESerializableProperty *propertyEntry = propertyTable[propertyName];
                ORKESerializationObjectToJSONBlock converter = propertyEntry.objectToJSONBlock;
                Class containerClass = propertyEntry.containerClass;
                id valueForKey = [object valueForKey:propertyName];
                if (valueForKey != nil) {
                    if ([containerClass isSubclassOfClass:[NSArray class]]) {
                        NSMutableArray *a = [NSMutableArray array];
                        for (id valueItem in valueForKey) {
                            id outputItem;
                            if (converter != nil) {
                                outputItem = converter(valueItem);
                                NSCAssert(isValid(valueItem), @"Expected valid JSON object");
                            } else {
                                // Recurse for each property
                                outputItem = jsonObjectForObject(valueItem);
                            }
                            [a addObject:outputItem];
                        }
                        valueForKey = a;
                    } else {
                        if (converter != nil) {
                            valueForKey = converter(valueForKey);
                            NSCAssert((valueForKey == nil) || isValid(valueForKey), @"Expected valid JSON object");
                        } else {
                            // Recurse for each property
                            valueForKey = jsonObjectForObject(valueForKey);
                        }
                    }
                }

                if (valueForKey != nil) {
                    encodedDict[propertyName] = valueForKey;
                }
            }
        }

        jsonOutput = encodedDict;
    } else if ([c isSubclassOfClass:[NSArray class]]) {
        NSArray *inputArray = (NSArray *)object;
        NSMutableArray *encodedArray = [NSMutableArray arrayWithCapacity:[inputArray count]];
        for (id input in inputArray) {
            // Recurse for each array element
            [encodedArray addObject:jsonObjectForObject(input)];
        }
        jsonOutput = encodedArray;
    } else if ([c isSubclassOfClass:[NSDictionary class]]) {
        NSDictionary *inputDict = (NSDictionary *)object;
        NSMutableDictionary *encodedDictionary = [NSMutableDictionary dictionaryWithCapacity:[inputDict count]];
        for (NSString *key in [inputDict allKeys] ) {
            // Recurse for each dictionary value
            encodedDictionary[key] = jsonObjectForObject(inputDict[key]);
        }
        jsonOutput = encodedDictionary;
    } else if (![c isSubclassOfClass:[NSPredicate class]]) {  // Ignore NSPredicate which cannot be easily serialized for now
        NSCAssert(isValid(object), @"Expected valid JSON object");

        // Leaf: native JSON object
        jsonOutput = object;
    }

    return jsonOutput;
}

+ (NSDictionary *)JSONObjectForObject:(id)object error:(NSError **)error {
    id json = jsonObjectForObject(object);
    return json;
}

+ (id)objectFromJSONObject:(NSDictionary *)object error:(NSError **)error {
    return objectForJsonObject(object, nil, nil);
}

+ (NSData *)JSONDataForObject:(id)object error:(NSError **)error {
    id json = jsonObjectForObject(object);
    return [NSJSONSerialization dataWithJSONObject:json options:(NSJSONWritingOptions)0 error:error];
}

+ (id)objectFromJSONData:(NSData *)data error:(NSError **)error {
    id json = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingOptions)0 error:error];
    id ret = nil;
    if (json != nil) {
        ret = objectForJsonObject(json, nil, nil);
    }
    return ret;
}

+ (NSArray *)serializableClasses {
    NSMutableArray *a = [NSMutableArray array];
    NSDictionary *table = ORKESerializationEncodingTable();
    for (NSString *key in [table allKeys]) {
        [a addObject:NSClassFromString(key)];
    }
    return a;
}

@end

@implementation ORKESerializer(Registration)

+ (void)registerSerializableClass:(Class)serializableClass
                        initBlock:(ORKESerializationInitBlock)initBlock {
    NSMutableDictionary *encodingTable = ORKESerializationEncodingTable();

    ORKESerializableTableEntry *entry = encodingTable[NSStringFromClass(serializableClass)];
    if (entry) {
        entry.class = serializableClass;
        entry.initBlock = initBlock;
    } else {
        entry = [[ORKESerializableTableEntry alloc] initWithClass:serializableClass initBlock:initBlock properties:@{}];
        encodingTable[NSStringFromClass(serializableClass)] = entry;
    }
}

+ (void)registerSerializableClassPropertyName:(NSString *)propertyName
                                     forClass:(Class)serializableClass
                                   valueClass:(Class)valueClass
                               containerClass:(Class)containerClass
                               writeAfterInit:(BOOL)writeAfterInit
                            objectToJSONBlock:(ORKESerializationObjectToJSONBlock)objectToJSON
                            jsonToObjectBlock:(ORKESerializationJSONToObjectBlock)jsonToObjectBlock {
    NSMutableDictionary *encodingTable = ORKESerializationEncodingTable();

    ORKESerializableTableEntry *entry = encodingTable[NSStringFromClass(serializableClass)];
    if (!entry) {
        entry = [[ORKESerializableTableEntry alloc] initWithClass:serializableClass initBlock:nil properties:@{}];
        encodingTable[NSStringFromClass(serializableClass)] = entry;
    }

    ORKESerializableProperty *property = entry.properties[propertyName];
    if (property == nil) {
        property = [[ORKESerializableProperty alloc] initWithPropertyName:propertyName
                                                               valueClass:valueClass
                                                           containerClass:containerClass
                                                           writeAfterInit:writeAfterInit
                                                        objectToJSONBlock:objectToJSON
                                                        jsonToObjectBlock:jsonToObjectBlock];
        entry.properties[propertyName] = property;
    } else {
        property.propertyName = propertyName;
        property.valueClass = valueClass;
        property.containerClass = containerClass;
        property.writeAfterInit = writeAfterInit;
        property.objectToJSONBlock = objectToJSON;
        property.jsonToObjectBlock = jsonToObjectBlock;
    }
}

@end

redpajama_set_name: RedPajamaGithub


It is always surprising to read through Zenit Catholic News and find my interview. The Zenit.org news interviewed me a few weeks ago and wonder of wonders — there it was today!
The interview was given in honor of Pope Benedict's proclamation that this was the year of St. Paul in honor of the 2000th anniversary of his birth. Since we filmed St. Paul's life story in six countries, they interviewed me about Paul and his life. You can read "In St. Paul's Footprints" here.
To find out more about our DVD documentary of St. Paul entitled "St. Paul: Contending for the Faith" click on the picture.


text:
Q: What spell was Gandalf summoning in The Hobbit: The Battle of the Five Armies? In the movie the Hobbit Battle of Five Armies, during Gandalf captivity in Dol Guldur (inside the cage), he and Radagast were whispering a spell, what kind of spell is that and what does it do?

A: Radagast is whispering part of his healing spell (from healing Sebastian the Hedgehog in AUJ). Specifically, he's saying "Na coilerya en-vinyanta", which is Quenya for "Let (your) life be renewed." So Radagast is trying a little at-a-distance Wizard First Aid. I've been unable to find a direct transcript of what Gandalf is whispering. My first assumption was that it was some sort of healing or protection spell, but over time I started thinking that it was a call for help (to either Radagast or Galadriel) in Sindarin or Quenya. Someone on another site said that they watched the film in China, and the subtitles while he was in the cage read "Valar, please come and protect me," so it's probable that Gandalf is actually praying for help rather than casting a spell.

A: My thought was that it was a quieter version of the same spell of opening he tried using on the doors of Moria's secret entrance in The Fellowship of the Ring, in an attempt to get the cage door open.

redpajama_set_name: RedPajamaStackExchange


VET teacher education in Australian universities: who are the students and what are their views about their courses?
View more >In Australia, the question of the level and nature of qualifications for vocational education and training (VET) teachers is a highly contested and political topic. VET teachers are only required to have a pre-university, certificate level pedagogical qualification, the Certificate IV in Training and Assessment. They possess substantially lower-level qualifications than teachers in other education sectors, although this was not always the case. The paper reports on research which investigated the experiences of VET teacher-education students studying for university qualifications. The research was undertaken in response to requests from policy stakeholders for evidence about the efficacy of higher-level qualifications. The research indicated student satisfaction with their courses and an alignment between what they saw as the benefits with the identified challenges of VET teaching. They also suggested areas for improvement. The findings are analysed with relation to the findings of a Productivity Commission inquiry into the VET workforce, which identified a number of capability gaps.


Narconon Success Video - Gary J.
My son was a good kid. I'm sure he had exposure to alcohol to excess or over indulged, probably from late high school to college age. From there he went directly into law enforcement.
There's a lot of stress. He saw a lot of the dirtier side of life. He saw murders and dope deals and, you know, all the seedier side of things we see on the news, he was in the middle of it.
And knowing other law enforcement agents that they would do that all day long, go to a local cop bar, if you will, and relive all that all night. So he was constantly on a high and resorted to alcohol, I think as just part of the scene.
And he was not participating with family for probably six months or so.
He had absented himself from the, from the parties, the Christmas activities, the get-togethers, the summers, that sort of stuff.
I think he talked to the Intake Counselor here over a series of probably two or three weeks.
Then I brought him with his stuff and turned him over. And then he went through the program.
He got healthier, he got to — his head was on straight, if you will. And of course, being away from the alcohol, he was back to his old self.
Narconon gave me my son back. And gave our family a brother, an uncle. He's back. So, he's what we were missing. It completed the circle.
It seemed to capture his spirit, return him to his useful life. And working here now, he's just bringing all his abilities to fruition. So I'm really grateful.


text:
Measuring Stigma in Order to Beat It
Author Jason Langendorf Published on November 3, 2021 3 min read
Shatterproof's new Addiction Stigma Index harnesses data to provide a road map to better policies and better treatment
By Jason Langendorf
Imagine a phenomenon that contributes to tens of thousands of preventable deaths annually, as well as the ongoing suffering of millions more and a public financial toll amounting to hundreds of billions of dollars each year. We'd waste no time addressing this problem, right?
That's the hope behind the recently released Addiction Stigma Index, a sweeping survey that attempts to measure stigma by assessing attitudes about substance use and people who use substances. Created by Shatterproof in conjunction with The Hartford financial services and insurance company and Indiana University, the index attempts to bring a focus to one of the more insidious obstacles to treatment and recovery success.
"We believe the lack of measurement around stigma has made it extremely difficult to reduce and track and monitor," says Matthew Stefanko, director of Shatterproof's National Stigma Initiative. "Because of that, we were able to work with a lot of leading researchers in the space to develop the index. We think it's going to be one of the most important tools that our country has in addressing stigma and ultimately ensuring that we are confronting this critical driver of the addiction crisis as effectively as possible."
What the Index Tracks
Shatterproof has identified four types of addiction stigma as priorities: public, structural, self and stigma against medication-assisted treatment (MAT) for opioid use disorder. In its survey of nearly 8,000 U.S. residents, the organization relied on more than 50 validated stigma measures that factor in these priorities. A small sample of the survey's key findings:
75.2% of the public do not believe that a person with an SUD is experiencing a chronic medical illness, as are those with diabetes, arthritis or heart disease
65.4% of respondents indicated that they would not want someone with a substance use disorder (SUD) marrying into their family
46.1% of respondents with an opioid use disorder expressed feeling ashamed of themselves
The manifestation of stigma can range from soft prejudice to employment discrimination to the underprescription and over-restriction of MAT, and its effects are often dynamic. Not only does structural stigma limit resources and influence policy, but people with SUD also are prone to internalize negative stereotypes, which can lead to the sort of isolation that perpetuates addiction.
"Most other measurement tools look at one of those pictures at a time," Stefanko says. "They might look at how healthcare professionals feel about someone with a substance use disorder. They might try to understand how the public feels, but they're not putting together this complete picture that we believe we can, because of the expansiveness of this tool."
How the Index Can Be Used
Caregivers and researchers in the addiction treatment space often point to stigma as a barrier for people with SUD, and much of the public—although some of it still unconvinced—has come to understand the harm of stigma in a theoretical sense. But Shatterproof's Stigma Index helps spell out, plainly and precisely, how stigma hampers access to treatment and jeopardizes recovery.
It's something that we can utilize when we go to federal policymakers and legislators, and have conversations with them about both the importance of stigma and also how little progress we've made. We've never been able to do that."
—Mark Stefanko, Shatterproof
Stefanko acknowledges the benefit of bringing a more concrete understanding to a nuanced subject, and he says Shatterproof is actively seeking organizations to partner with—"folks that might be interested in using this in their own backyard." But one result from the survey, he emphasizes, has value over all others: data. Because Shatterproof will be conducting research for the index over a multiyear period, its initial findings have been vital in establishing a baseline from which progress can be tracked and measured.
"It's something that we can utilize when we go to federal policymakers and legislators, and have conversations with them about both the importance of stigma and also how little progress we've made," Stefanko says. "We've never been able to do that."
"So there have been tens of millions of dollars spent on media campaigns, communications efforts and training, and it's hard to know what kinds of changes we've been able to make in the country over the last few years. We could have been moving in the right direction or we could have not—and there was no data to give us an indication of the progress, or lack thereof, in one place. We'll derive a lot of benefits from this."
Photo: Anne Nygård
addiction dataAddiction Stigma IndexShatterproofstigma
The Workforce Shortage in Addiction Care Reaches a Crisis Stage
Hard Knocks: Incarcerated Women with Addiction
Category New & Next
Addiction Treatment Needs Standardized Measures
A New Data Tool Identifies Addiction Treatment Deserts
Published on September 7, 2022 5 min read
Category From the Journals
Modeling the Future of the Opioid Crisis
Pain Relief Without Opioids?

redpajama_set_name: RedPajamaCommonCrawl


Hello my lovlies! Who is loving the Christmas season right now? Also what does the Christmas/Holiday season look like for you? Right now for me it's actually rather warm. Im so used to a cold holiday season since i used to live in Washington. We usually got a white Holiday, but here in Texas its actually kind of bi-polar. One moment its cold and the next its in the in the high 80's or 90's which i dont mind at all. I have Latin blood in me, so living in a cold state was always very hard for me.
Speaking of the holiday season, if you've followed along with our blogs, you know that a few months ago i went to Charlotte Russe and basically bought the whole entire store.
Anyway, when i did go it was August, and i decided to get to perfumes. Now i dont normally use perfumes like this. Im more of an essential oils type of girl, but during the move to Texas i had lost my essential oil rollers so, sad life please pity me (JUST KIDDING). Since i had lost my dear rollers, i decided to get two perfumes, one was a more summery fragrance (coconunt) and the other was more of a fall fragrance, which is the one that i will be reviewing today.
I have been using this perfume every day since i got it. I love how its not an over powering scent, its very natral low scent that is perfect for fall! You can definitley smell the vanilla and sugar, and its all really subtile which i love.
I really dont like over powering or very obvious fragranes, and thats why i mostly use essential oils, and this warm vanilla scent is truly amazing. I highly recommend going out and getting yourselves a little bottle of your own!
Well thats it for todays blog!
Comment down below what your favorite fragrance is!
Previous postLife Update: First Semester of College!


Walter Presents, a curated SVOD video streaming service specializing in offering ad free foreign language dramas, to reportedly launch in the US at $6.99 per month starting this March. The service is available on web platforms for now through WalterPresents.com.
Walter Presents plans to launch in 34 series from 12 countries, including Brazil, France, Germany, Argentina and the Netherlands and plans to premiere two new series each month. The OTT service aims is to host more than 500 hours of premium TV in its first year.


Searching for Pearl City movers to handle your upcoming relocation and storage needs? Rely on Coleman Hawaii Movers' Pearl City moving company for a successful relocation. The 31,000 residents of this beautiful Hawaiian city depend on our Pearl City moving company for their residential and commercial moves. Our state-of-the-art storage facilities are able to accommodate all of your short- or long-term storage needs. Our Pearl City moving experts work exhaustively to ensure that we exceed your relocation expectations. Coleman Hawaii Movers' Pearl City moving is the superior moving company for a successful relocation. You can count on our Pearl City movers when it comes to full-service residential and commercial moves; government, military and corporate relocation; storage and warehousing; high-value product shipping and more high-quality services. As an agent of Allied Van Lines, customers can depend on our global capabilities for their important moving and storage needs.
Household Moving: Depend on our exceptional Pearl City household moving services to ensure the secure and efficient transport of your household items, regardless of where in the world you are heading.
Business & Office Moving: You can count on our Pearl City moving and storage company's unmatched business and office moving services to minimize your downtime during your relocation.
Corporate Relocation: Our Pearl City commercial moving company's corporate relocation services will ensure that we meet the needs of your business and employees during your move.
International Moving: Our global resources at Coleman Hawaii Movers' Pearl City moving company make it possible for us to smoothly move your family, business, employees and high-value items anywhere in the world.
Whether you're moving locally or relocating to a long distance or international destination, our Pearl City movers will oversee every detail to ensure a seamless process from start to finish. With the backing of Allied Van Lines, we can easily coordinate any size basic or specialized move. Our top-quality fleet, state-of-the-art equipment, advanced technology and highly trained Pearl City movers will provide a smooth transition to any location in the world. Coleman Hawaii Movers is a full-service relocation and storage company, meaning we offer both traditional and highly specialized moving operations as well as flexible storage solutions. Our Pearl City movers will work with you to customize our wide array of moving services to personalize a solution around your exact needs and budget.
Looking for Pearl City movers? You can't beat the skilled team at Coleman Hawaii Movers. Fill out a form online or call us at our Pearl City moving company for your free moving quote today. We look forward to meeting your Pearl City moving requirements.


It is in specs sheet. Most galvos will do 20 but some will 40....CT for ex. will do 40.
If you want to determine the angle based on what you are projected do this.
(1) Measure height or width and divide it by 2 and call that value Y.
(2) Measure distance from image to scanner mirrors and call it X.
(3) Divide Y by X and do inverse tan to get an angle.
(4) The angle you get is physical scanner angle.
(5) Double the angle to get the optical angle.
All of this is based on the formula: tan(angle) = opp / adjacent.
I hope my math is right because that's how I do it at home.
I like to use the little table on the Pangolin site. I always seem to look for it there and can never find it. Then I come here and search for a post where dave has it linked... I know he has done it a few times.


text:
BRP'S CAN-AM COMMANDER WINS MOROCCO RALLY
Chilean Racers Francisco Lopez and Claudio Troncoso Make History as First SxS to Finish African Rally
Morocco, Africa, November 1, 2011– BRP's Can-Am Commander SxS, driven by Francisco Lopez and co-pilot Claudio Troncoso, won the Morocco Rally in the UTV category after covering 2,000 kilometres of challenging African terrains. The duo made international headlines last week due to their impressive finish in the Morocco Rally, becoming the only SxS competitor to complete the six grueling stages of the 2011 edition, in addition to placing 21st within the car category.
Lopez and his Can-Am Nextel Team attributed their victory to the pilots' experience, the Can-Am Commander SxS's outstanding performance, and the unwavering support of Jaton Racing, a Spanish company that prepared the side-by-side vehicle for the race, and provided mechanical assistance through its duration.
"Our starting objective for the race was clear: test the Can-Am Commander SxS's capacity in difficult terrains to ensure a solid performance in the 2012 Dakar. We weren't aspiring to win," Lopez commented after the race. "By the last day, we had a new objective: become the first SxS vehicle in the history of the UTV class to finish the Morocco Rally."
The Can-Am Nextel Team, who drew substantial media attention during its first appearance in the 2011 Dakar, set their sights on the Moroccan desert in early 2011. The purpose was to learn from BRP's Can-Am Commander SxS's performance in a rally that would allow them to adapt the unit and ensure a victorious 2012 Dakar appearance in the UTV category.
"BRP's Can-Am Commander SxS reflects our DNA in its purest tradition," said Chris Dawson, vice-president and general manager, International division. "This very unique side-by-side has been designed to bring a new level of power, cutting-edge design and meaningful innovations. To finish first in its category in its first test – the only SxS to complete the race – certainly delivers on our promise."
The Can-Am Nextel Team will take the wheel of a 2011 Can-Am Commander SxS in a quest to secure its second international rally victory in the UTV segment at the 34th edition of the Dakar Rally.
Bombardier Recreational Products Inc. (BRP), a privately held company, is a world leader in the design, development, manufacturing, distribution and marketing of motorised recreational vehicles. Its portfolio of brands and products includes: Ski-Doo and Lynx snowmobiles, Sea Doo watercraft and boats, Evinrude and Johnson outboard engines, Can-Am all terrain and side-by-side vehicles and roadsters, as well as Rotax engines. BRP products are distributed in more than 100 countries.
www.brp.com
Sea-Doo, Ski-Doo, Lynx, Evinrude, Johnson, Can-Am, Rotax and the BRP logo are trademarks of Bombardier Recreational Products Inc. or its affiliates. All other trademarks are the property of their respective owners.
UTVGuide.net Blog or on Facebook
Side X Side Outfitterz Announces the Spring Grand Canyon Schedule
Polaris announces Corrective Action for RZR XP Turbo Recall
Air Lift Offers LoadLifter Air Spring Kit for 2015 Ford F-450


text:
Q: How to use MuPDF library to make a Mac application for viewing XPS documents? I need to make a Mac application to view XPS documents on Mac. I know that MuPDF is able to render XPS documents . I searched extensively on the web about using MuPDF library to make a mac application for viewing XPS. But I got no any idea to start . I also did not find any proper documentation for such. I found a sample project for iOS that can do the same but it is not building. I would be grateful if anyone could help me out ! Thanks in advance.

A: I'm able to build the mupdf iOS project by cloning the main mupdf git repo, running git submodule update --init, opening platform/ios/MuPDF.xcodeproj and building as normal.
If that doesn't work for you, can you edit your question to include the exact error message?
I am not aware of an mupdf example for Mac OS X, however you should be able to follow the iOS MuPageViewNormal.m code and do something fairly similar, probably using NSScrollView. If you're only trying to display XPS then you won't need to worry about all the code to do with annotations etc.
(The standard x11 mupdf can be built for Mac OS X, but this isn't a native Mac app so is unlikely to help you.)


Why Our Copiers in Chicago Work for You!
What do we do different? One of the main things we do is that we analyze your actual use and your actual copier needs. We work hard no to sell you an $8,000 copier which a $2,000 copier should be able to do. We are also a networking company in Chicago. So, our goal is to help the computer work you do make sense with the copiers and the multi-functions we'd sell.
What size of paper do you use?
What volume of pages do you use?
What special applications need to work?
Do you need color or black and white?
As you answer these questions, our copier specialists will be able to help you find an appropriate copier in Chigago for your specific needs!


Who said that art and design are separate entities? Namuzaj is a startup founded by Nour Arabi, an interior architect and furniture designer. Namuzaj dances between the art and design disciplines and experiments with doodles, turning them into functional products. Namuzaj has no boundaries, dealing with paintings, furniture, interior etc. with all creative outcomes being considered as 'Namazej' or prototypes.


You've probably heard the old New York joke: How do you get to Carnegie Hall? Practice, practice, practice! It's silly, yet it's also good advice—advice you should keep in mind the next time you have a speech or a presentation to give.
I'm a professional speaker, and I'll let you in on a secret: The pros always practice, even if it's a speech they've given many times before. Familiarizing yourself with the rhythms of your speech is the best way to gain confidence and to keep from stumbling.
It's not only important that you practice, but that you do so the right way. Let me offer a few quick tips.
Stand up and be mobile. You're probably not going to be sitting still while you deliver your speech (at least I hope not)—so why would you practice that way? Allow yourself to be energized by the material. Find an open room where you can amble around a bit while you rehearse.
Speak up. You should practice your speech out loud—and yes, this really is something that needs to be said. A lot of folks think mentally reviewing your slides counts as practicing. It doesn't! You need to hear the sound of your own voice.
Put the text away. You don't want to be reading from your manuscript during your speech, although it's fine to have bullet points on a notecard. Try to go through it a few times without having a text handy.
Go to the venue. This isn't always possible, but if you can practice in the room where you're going to be giving the presentation, that's always a good idea. Again, familiarity brings comfort and confidence!
Practice with an audience. Again, not always possible—but if you have a spouse/friend/co-worker who can serve as a test audience and then provide you with feedback, that can be invaluable.
Get a coach. This isn't a step everyone needs to take, but if you really want to take your presentation game to the next level, working with a coach can certainly be effective.
Incidentally, I provide a range of executive coaching services—so if you want someone to work with you on public speaking, that's well within my wheelhouse. Let's talk more about your goals; reach out to me today! You can contact Dr. Rick at www.rickgoodman.com or call 888-267-6098.


July 6, 2018 Telecom Industry NewsComments are off for this post.
telecomJuly 6, 2018Comments are off for this post.
(Telecompaper) Rodriguez will take the place of Baptiest Coopmans, who has been acting CTO since late December. Coopmans will help with the transition and then assume the position of senior VP for operations.