Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api): Accepting all types for attributes values #309

Merged
merged 8 commits into from
Oct 23, 2018
2 changes: 1 addition & 1 deletion OptimizelySDKCore/OptimizelySDKCore/OPTLYAudience.m
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ - (void)setConditionsWithNSString:(NSString *)string {
}
}

- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *,NSString *> *)attributes {
- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *, NSObject *> *)attributes {
for (NSObject<OPTLYCondition> *condition in self.conditions) {
if ([condition evaluateConditionsWithAttributes:attributes]) {
// if user satisfies any conditions, return true.
Expand Down
2 changes: 1 addition & 1 deletion OptimizelySDKCore/OptimizelySDKCore/OPTLYBaseCondition.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
/// Condition type
@property (nonatomic, strong) NSString *type;
/// Condition value
@property (nonatomic, strong) NSString *value;
@property (nonatomic, strong) NSObject *value;

+(BOOL)isBaseConditionJSON:(NSData *)jsonData;

Expand Down
6 changes: 3 additions & 3 deletions OptimizelySDKCore/OptimizelySDKCore/OPTLYBaseCondition.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ + (BOOL) isBaseConditionJSON:(NSData *)jsonData {
}
}

- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *,NSString *> *)attributes {
- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *, NSObject *> *)attributes {
if (attributes == nil) {
// if the user did not pass in attributes, return false
return false;
}
else {
// check user attribute value for the condition against our condition value
return [self.value isEqualToString:attributes[self.name]];
// check user attribute value for the condition against our condition value
return [self.value isEqual:attributes[self.name]];
}
}

Expand Down
2 changes: 1 addition & 1 deletion OptimizelySDKCore/OptimizelySDKCore/OPTLYCondition.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
/**
* Evaluate the condition against the user attributes.
*/
- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *, NSString *> *)attributes;
- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *, NSObject *> *)attributes;

@end

Expand Down
6 changes: 3 additions & 3 deletions OptimizelySDKCore/OptimizelySDKCore/OPTLYCondition.m
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ @implementation OPTLYCondition

@implementation OPTLYAndCondition

- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *,NSString *> *)attributes {
- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *, NSObject *> *)attributes {
for (NSObject<OPTLYCondition> *condition in self.subConditions) {
// if any of our sub conditions are false
if (![condition evaluateConditionsWithAttributes:attributes]) {
Expand All @@ -131,7 +131,7 @@ - (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *,NSString *> *)

@implementation OPTLYOrCondition

- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *,NSString *> *)attributes {
- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *, NSObject *> *)attributes {
for (NSObject<OPTLYCondition> *condition in self.subConditions) {
// if any of our sub conditions are true
if ([condition evaluateConditionsWithAttributes:attributes]) {
Expand All @@ -147,7 +147,7 @@ - (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *,NSString *> *)

@implementation OPTLYNotCondition

- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *,NSString *> *)attributes {
- (BOOL)evaluateConditionsWithAttributes:(NSDictionary<NSString *, NSObject *> *)attributes {
// return the negative of the subcondition
return ![self.subCondition evaluateConditionsWithAttributes:attributes];
}
Expand Down
4 changes: 2 additions & 2 deletions OptimizelySDKCore/OptimizelySDKCore/OPTLYEventBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_END
- (nullable NSDictionary *)buildImpressionEventForUser:(nonnull NSString *)userId
experiment:(nonnull OPTLYExperiment *)experiment
variation:(nonnull OPTLYVariation *)variation
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;

/**
* Create the parameters for a conversion event.
Expand All @@ -59,7 +59,7 @@ NS_ASSUME_NONNULL_END
event:(nonnull OPTLYEvent *)event
decisions:(nonnull NSArray<NSDictionary *> *)decisions
eventTags:(nullable NSDictionary *)eventTags
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;
@end

@interface OPTLYEventBuilderDefault : NSObject<OPTLYEventBuilder>
Expand Down
53 changes: 43 additions & 10 deletions OptimizelySDKCore/OptimizelySDKCore/OPTLYEventBuilder.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ -(instancetype)initWithConfig:(OPTLYProjectConfig *)config {
-(NSDictionary *)buildImpressionEventForUser:(NSString *)userId
experiment:(OPTLYExperiment *)experiment
variation:(OPTLYVariation *)variation
attributes:(NSDictionary<NSString *,NSString *> *)attributes {
attributes:(NSDictionary<NSString *, NSObject *> *)attributes {
if (!self.config) {
return nil;
}
Expand All @@ -71,7 +71,7 @@ -(NSDictionary *)buildConversionEventForUser:(NSString *)userId
event:(OPTLYEvent *)event
decisions:(NSArray<NSDictionary *> *)decisions
eventTags:(NSDictionary *)eventTags
attributes:(NSDictionary<NSString *,NSString *> *)attributes {
attributes:(NSDictionary<NSString *, NSObject *> *)attributes {

if (!self.config) {
return nil;
Expand All @@ -87,7 +87,7 @@ -(NSDictionary *)buildConversionEventForUser:(NSString *)userId
}

- (NSDictionary *)createCommonParamsForUser:(NSString *)userId
attributes:(NSDictionary<NSString *, NSString *> *)attributes {
attributes:(NSDictionary<NSString *, NSObject *> *)attributes {
NSMutableDictionary *commonParams = [NSMutableDictionary new];

NSMutableDictionary *visitor = [NSMutableDictionary new];
Expand Down Expand Up @@ -199,15 +199,15 @@ - (NSDictionary *)filterEventTags:(NSDictionary *)eventTags {
}

- (NSArray *)createUserFeatures:(OPTLYProjectConfig *)config
attributes:(NSDictionary *)attributes {
attributes:(NSDictionary<NSString *, NSObject *> *)attributes {

NSNumber *botFiltering = config.botFiltering;
NSMutableArray *features = [NSMutableArray new];
NSArray *attributeKeys = [attributes allKeys];

for (NSString *attributeKey in attributeKeys) {
NSString *attributeValue = attributes[attributeKey];
if ([OPTLYEventBuilderDefault isEmptyString:attributeValue]) {
NSObject *attributeValue = attributes[attributeKey];
if (![OPTLYEventBuilderDefault isValidAttributeValue:attributeValue]) {
NSString *logMessage = [NSString stringWithFormat:OPTLYLoggerMessagesAttributeValueInvalidFormat, attributeKey];
[config.logger logMessage:logMessage withLevel:OptimizelyLogLevelDebug];
continue;
Expand Down Expand Up @@ -252,10 +252,43 @@ + (NSString *)stringOrEmpty:(NSString *)str {
return string;
}

+ (BOOL)isEmptyString:(NSString*)str {
return (str == nil
|| [str isKindOfClass:[NSNull class]]
|| [str length] == 0);
+ (BOOL)isEmptyString:(NSObject *)str {
return (!str
|| ![str isKindOfClass:[NSString class]]
|| [(NSString *)str isEqualToString:@""]);
}

+ (BOOL)isValidAttributeValue:(NSObject *)value {
// check value is NSObject
if (!value) {
return false;
}
// check value is NSString
if ([value isKindOfClass:[NSString class]]) {
return true;
}
NSNumber *number = (NSNumber *)value;
// check value is NSNumber
if (number) {
const char *objCType = [number objCType];
// check NSNumber is of type int, double, bool
return (strcmp(objCType, @encode(short)) == 0)
|| (strcmp(objCType, @encode(unsigned short)) == 0)
|| (strcmp(objCType, @encode(int)) == 0)
|| (strcmp(objCType, @encode(unsigned int)) == 0)
|| (strcmp(objCType, @encode(long)) == 0)
|| (strcmp(objCType, @encode(unsigned long)) == 0)
|| (strcmp(objCType, @encode(long long)) == 0)
|| (strcmp(objCType, @encode(unsigned long long)) == 0)
|| (strcmp(objCType, @encode(float)) == 0)
|| (strcmp(objCType, @encode(double)) == 0)
|| (strcmp(objCType, @encode(char)) == 0)
|| (strcmp(objCType, @encode(unsigned char)) == 0)
|| (strcmp(objCType, @encode(bool)) == 0)
|| [number isEqual:@YES]
|| [number isEqual:@NO];
}
return false;
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ typedef NS_ENUM(NSUInteger, OPTLYNotificationType) {

typedef void (^ActivateListener)(OPTLYExperiment * _Nonnull experiment,
NSString * _Nonnull userId,
NSDictionary<NSString *,NSString *> * _Nonnull attributes,
NSDictionary<NSString *, NSObject *> * _Nonnull attributes,
OPTLYVariation * _Nonnull variation,
NSDictionary<NSString *,NSObject *> * _Nonnull event);

typedef void (^TrackListener)(NSString * _Nonnull eventKey,
NSString * _Nonnull userId,
NSDictionary<NSString *,NSString *> * _Nonnull attributes,
NSDictionary<NSString *, NSObject *> * _Nonnull attributes,
NSDictionary * _Nonnull eventTags,
NSDictionary<NSString *,NSObject *> * _Nonnull event);

Expand Down
2 changes: 1 addition & 1 deletion OptimizelySDKCore/OptimizelySDKCore/OPTLYProjectConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ __attribute((deprecated("Use OPTLYProjectConfig initWithBuilder method instead."
*/
- (nullable OPTLYVariation *)getVariationForExperiment:(nonnull NSString *)experimentKey
userId:(nonnull NSString *)userId
attributes:(nullable NSDictionary<NSString *,NSString *> *)attributes
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes
bucketer:(nullable id<OPTLYBucketer>)bucketer;

@end
2 changes: 1 addition & 1 deletion OptimizelySDKCore/OptimizelySDKCore/OPTLYProjectConfig.m
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ - (NSDictionary *)generateAttributeToKeyMap
// TODO: Remove bucketer from parameters -- this is not needed
- (OPTLYVariation *)getVariationForExperiment:(NSString *)experimentKey
userId:(NSString *)userId
attributes:(NSDictionary<NSString *,NSString *> *)attributes
attributes:(NSDictionary<NSString *, NSObject *> *)attributes
bucketer:(id<OPTLYBucketer>)bucketer
{
OPTLYExperiment *experiment = [self getExperimentForKey:experimentKey];
Expand Down
22 changes: 11 additions & 11 deletions OptimizelySDKCore/OptimizelySDKCore/Optimizely.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
*/
- (nullable OPTLYVariation *)activate:(nonnull NSString *)experimentKey
userId:(nonnull NSString *)userId
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;

#pragma mark - getVariation methods
/**
Expand All @@ -90,7 +90,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
*/
- (nullable OPTLYVariation *)variation:(nonnull NSString *)experimentKey
userId:(nonnull NSString *)userId
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;

#pragma mark - Forced Variation Methods
/**
Expand Down Expand Up @@ -135,7 +135,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
* @param attributes The user's attributes.
* @return YES if feature is enabled, false otherwise.
*/
- (BOOL)isFeatureEnabled:(nullable NSString *)featureKey userId:(nullable NSString *)userId attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
- (BOOL)isFeatureEnabled:(nullable NSString *)featureKey userId:(nullable NSString *)userId attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;

/**
* Gets boolean feature variable value.
Expand All @@ -148,7 +148,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
- (nullable NSNumber *)getFeatureVariableBoolean:(nullable NSString *)featureKey
variableKey:(nullable NSString *)variableKey
userId:(nullable NSString *)userId
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;

/**
* Gets double feature variable value.
Expand All @@ -161,7 +161,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
- (nullable NSNumber *)getFeatureVariableDouble:(nullable NSString *)featureKey
variableKey:(nullable NSString *)variableKey
userId:(nullable NSString *)userId
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;

/**
* Gets integer feature variable value.
Expand All @@ -174,7 +174,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
- (nullable NSNumber *)getFeatureVariableInteger:(nullable NSString *)featureKey
variableKey:(nullable NSString *)variableKey
userId:(nullable NSString *)userId
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;

/**
* Gets string feature variable value.
Expand All @@ -187,7 +187,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
- (nullable NSString *)getFeatureVariableString:(nullable NSString *)featureKey
variableKey:(nullable NSString *)variableKey
userId:(nullable NSString *)userId
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;

/**
* Get array of features that are enabled for the user.
Expand All @@ -196,7 +196,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
* @return NSArray<NSString> Array of feature keys that are enabled for the user.
*/
- (NSArray<NSString *> *_Nonnull)getEnabledFeatures:(nullable NSString *)userId
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes;

#pragma mark - trackEvent methods
/**
Expand All @@ -215,7 +215,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
*/
- (void)track:(nonnull NSString *)eventKey
userId:(nonnull NSString *)userId
attributes:(nonnull NSDictionary<NSString *, NSString *> *)attributes;
attributes:(nonnull NSDictionary<NSString *, NSObject *> *)attributes;

/**
* Track an event
Expand All @@ -236,7 +236,7 @@ typedef NS_ENUM(NSInteger, OPTLYLiveVariableError) {
*/
- (void)track:(nonnull NSString *)eventKey
userId:(nonnull NSString *)userId
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes
eventTags:(nullable NSDictionary<NSString *, id> *)eventTags;

////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -584,7 +584,7 @@ __attribute((deprecated("Use Optimizely initWithBuilder method instead.")));
*/
- (void)track:(nonnull NSString *)eventKey
userId:(nonnull NSString *)userId
attributes:(nullable NSDictionary<NSString *, NSString *> *)attributes
attributes:(nullable NSDictionary<NSString *, NSObject *> *)attributes
eventTags:(nullable NSDictionary<NSString *, id> *)eventTags;

@end
Loading