Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,23 +117,26 @@ See example application here: [https://github.com/featurevisor/featurevisor-exam
The SDK can be initialized by passing [datafile](https://featurevisor.com/docs/building-datafiles/) content directly:

```java
import com.featurevisor.sdk.Instance;
import com.featurevisor.types.DatafileContent;
import com.featurevisor.sdk.Featurevisor;

// Load datafile content
String datafileUrl = "https://cdn.yoursite.com/datafile.json";
String datafileContent = "..." // ... load your datafile content

// Parse the JSON into DatafileContent object
DatafileContent datafile = DatafileContent.fromJson(datafileContent);
String datafileContent = "..." // load your datafile content

// Create SDK instance
Instance f = new Instance(
new Instance.InstanceOptions()
.datafile(datafileContent)
Featurevisor f = Featurevisor.createInstance(datafileContent);
```

or by constructing a `Featurevisor.Options` object:

```java
Featurevisor f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafileContent)
);
```

We will learn about several different options in the next sections.

## Evaluation types

We can evaluate 3 types of values against a particular [feature](https://featurevisor.com/docs/features/):
Expand Down Expand Up @@ -170,8 +173,8 @@ Map<String, Object> initialContext = new HashMap<>();
initialContext.put("deviceId", "123");
initialContext.put("country", "nl");

Instance f = new Instance(new Instance.InstanceOptions()
.datafile(datafile)
Featurevisor f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafileContent)
.context(initialContext));
```

Expand Down Expand Up @@ -357,7 +360,7 @@ Map<String, Object> anotherFeatureSticky = new HashMap<>();
anotherFeatureSticky.put("enabled", false);
stickyFeatures.put("anotherFeatureKey", anotherFeatureSticky);

Instance f = new Instance(new Instance.InstanceOptions()
Featurevisor f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafile)
.sticky(stickyFeatures));
```
Expand Down Expand Up @@ -433,7 +436,7 @@ Setting `debug` level will print out all logs, including `info`, `warn`, and `er
```java
import com.featurevisor.sdk.Logger;

Instance f = new Instance(new Instance.InstanceOptions()
Featurevisor f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafile)
.logLevel(Logger.LogLevel.DEBUG));
```
Expand All @@ -457,7 +460,7 @@ Logger customLogger = Logger.createLogger(new Logger.CreateLoggerOptions()
System.out.println("[" + level + "] " + message);
}));

Instance f = new Instance(new Instance.InstanceOptions()
Featurevisor f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafile)
.logger(customLogger));
```
Expand All @@ -470,7 +473,7 @@ Logger customLogger = new Logger(Logger.LogLevel.INFO, (level, message, details)
System.out.println("[" + level + "] " + message);
});

Instance f = new Instance(new Instance.InstanceOptions()
Featurevisor f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafile)
.logger(customLogger));
```
Expand Down Expand Up @@ -637,7 +640,7 @@ You can register hooks at the time of SDK initialization:
List<Map<String, Object>> hooks = new ArrayList<>();
hooks.add(myCustomHook);

Instance f = new Instance(new Instance.InstanceOptions()
Featurevisor f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafile)
.hooks(hooks));
```
Expand All @@ -662,7 +665,7 @@ That's where child instances come in handy:
Map<String, Object> childContext = new HashMap<>();
childContext.put("userId", "123");

Instance childF = f.spawn(childContext);
ChildInstance childF = f.spawn(childContext);
```

Now you can pass the child instance where your individual request is being handled, and you can continue to evaluate features targeting that specific user alone:
Expand Down
65 changes: 32 additions & 33 deletions src/main/java/com/featurevisor/cli/CLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import picocli.CommandLine.Parameters;

import com.featurevisor.sdk.Featurevisor;
import com.featurevisor.sdk.Instance;
import com.featurevisor.sdk.Logger;
import com.featurevisor.sdk.DatafileReader;
import com.featurevisor.types.DatafileContent;
Expand Down Expand Up @@ -250,9 +249,9 @@ private TestResult testFeature(Map<String, Object> assertion, String featureKey,
Map<String, Object> sticky = (Map<String, Object>) assertion.getOrDefault("sticky", new HashMap<>());

// Update the SDK instance context and sticky values for this assertion
if (f instanceof Instance) {
((Instance) f).setContext(context, true);
((Instance) f).setSticky(sticky, true);
if (f instanceof Featurevisor) {
((Featurevisor) f).setContext(context, true);
((Featurevisor) f).setSticky(sticky, true);
} else if (f instanceof com.featurevisor.sdk.ChildInstance) {
((com.featurevisor.sdk.ChildInstance) f).setContext(context, true);
((com.featurevisor.sdk.ChildInstance) f).setSticky(sticky, true);
Expand All @@ -274,7 +273,7 @@ private TestResult testFeature(Map<String, Object> assertion, String featureKey,

// Test expectedVariation
if (assertion.containsKey("expectedVariation")) {
Instance.OverrideOptions options = new Instance.OverrideOptions();
Featurevisor.OverrideOptions options = new Featurevisor.OverrideOptions();
if (assertion.containsKey("defaultVariationValue")) {
options.setDefaultVariationValue(assertion.get("defaultVariationValue").toString());
}
Expand Down Expand Up @@ -308,7 +307,7 @@ private TestResult testFeature(Map<String, Object> assertion, String featureKey,
}
}

Instance.OverrideOptions options = new Instance.OverrideOptions();
Featurevisor.OverrideOptions options = new Featurevisor.OverrideOptions();
if (defaultVariableValues.containsKey(variableKey)) {
options.setDefaultVariableValue(defaultVariableValues.get(variableKey));
}
Expand Down Expand Up @@ -347,7 +346,7 @@ private TestResult testFeature(Map<String, Object> assertion, String featureKey,
if (expectedEvaluations.containsKey("variation")) {
@SuppressWarnings("unchecked")
Map<String, Object> variationEvaluation = (Map<String, Object>) expectedEvaluations.get("variation");
Instance.OverrideOptions options = new Instance.OverrideOptions();
Featurevisor.OverrideOptions options = new Featurevisor.OverrideOptions();
if (assertion.containsKey("defaultVariationValue")) {
options.setDefaultVariationValue(assertion.get("defaultVariationValue").toString());
}
Expand Down Expand Up @@ -378,7 +377,7 @@ private TestResult testFeature(Map<String, Object> assertion, String featureKey,
@SuppressWarnings("unchecked")
Map<String, Object> expectedEvaluation = (Map<String, Object>) entry.getValue();

Instance.OverrideOptions options = new Instance.OverrideOptions();
Featurevisor.OverrideOptions options = new Featurevisor.OverrideOptions();
if (defaultVariableValues.containsKey(variableKey)) {
options.setDefaultVariableValue(defaultVariableValues.get(variableKey));
}
Expand Down Expand Up @@ -427,55 +426,55 @@ private TestResult testFeature(Map<String, Object> assertion, String featureKey,
* Helper methods to work with both Instance and ChildInstance
*/
private boolean isEnabled(Object f, String featureKey, Map<String, Object> context) {
if (f instanceof Instance) {
return ((Instance) f).isEnabled(featureKey, context);
if (f instanceof Featurevisor) {
return ((Featurevisor) f).isEnabled(featureKey, context);
} else if (f instanceof com.featurevisor.sdk.ChildInstance) {
return ((com.featurevisor.sdk.ChildInstance) f).isEnabled(featureKey, context);
}
return false;
}

private Object getVariation(Object f, String featureKey, Map<String, Object> context, Instance.OverrideOptions options) {
if (f instanceof Instance) {
return ((Instance) f).getVariation(featureKey, context, options);
private Object getVariation(Object f, String featureKey, Map<String, Object> context, Featurevisor.OverrideOptions options) {
if (f instanceof Featurevisor) {
return ((Featurevisor) f).getVariation(featureKey, context, options);
} else if (f instanceof com.featurevisor.sdk.ChildInstance) {
return ((com.featurevisor.sdk.ChildInstance) f).getVariation(featureKey, context, options);
}
return null;
}

private Object getVariable(Object f, String featureKey, String variableKey, Map<String, Object> context, Instance.OverrideOptions options) {
if (f instanceof Instance) {
return ((Instance) f).getVariable(featureKey, variableKey, context, options);
private Object getVariable(Object f, String featureKey, String variableKey, Map<String, Object> context, Featurevisor.OverrideOptions options) {
if (f instanceof Featurevisor) {
return ((Featurevisor) f).getVariable(featureKey, variableKey, context, options);
} else if (f instanceof com.featurevisor.sdk.ChildInstance) {
return ((com.featurevisor.sdk.ChildInstance) f).getVariable(featureKey, variableKey, context, options);
}
return null;
}

private com.featurevisor.sdk.Evaluation evaluateFlag(Object f, String featureKey, Map<String, Object> context) {
if (f instanceof Instance) {
return ((Instance) f).evaluateFlag(featureKey, context);
if (f instanceof Featurevisor) {
return ((Featurevisor) f).evaluateFlag(featureKey, context);
} else if (f instanceof com.featurevisor.sdk.ChildInstance) {
// ChildInstance doesn't have evaluateFlag, so we'll skip this test for child instances
return null;
}
return null;
}

private com.featurevisor.sdk.Evaluation evaluateVariation(Object f, String featureKey, Map<String, Object> context, Instance.OverrideOptions options) {
if (f instanceof Instance) {
return ((Instance) f).evaluateVariation(featureKey, context, options);
private com.featurevisor.sdk.Evaluation evaluateVariation(Object f, String featureKey, Map<String, Object> context, Featurevisor.OverrideOptions options) {
if (f instanceof Featurevisor) {
return ((Featurevisor) f).evaluateVariation(featureKey, context, options);
} else if (f instanceof com.featurevisor.sdk.ChildInstance) {
// ChildInstance doesn't have evaluateVariation, so we'll skip this test for child instances
return null;
}
return null;
}

private com.featurevisor.sdk.Evaluation evaluateVariable(Object f, String featureKey, String variableKey, Map<String, Object> context, Instance.OverrideOptions options) {
if (f instanceof Instance) {
return ((Instance) f).evaluateVariable(featureKey, variableKey, context, options);
private com.featurevisor.sdk.Evaluation evaluateVariable(Object f, String featureKey, String variableKey, Map<String, Object> context, Featurevisor.OverrideOptions options) {
if (f instanceof Featurevisor) {
return ((Featurevisor) f).evaluateVariable(featureKey, variableKey, context, options);
} else if (f instanceof com.featurevisor.sdk.ChildInstance) {
// ChildInstance doesn't have evaluateVariable, so we'll skip this test for child instances
return null;
Expand All @@ -484,8 +483,8 @@ private com.featurevisor.sdk.Evaluation evaluateVariable(Object f, String featur
}

private com.featurevisor.sdk.ChildInstance spawn(Object f, Map<String, Object> context) {
if (f instanceof Instance) {
return ((Instance) f).spawn(context);
if (f instanceof Featurevisor) {
return ((Featurevisor) f).spawn(context);
} else if (f instanceof com.featurevisor.sdk.ChildInstance) {
// ChildInstance doesn't have spawn, so we'll return null
return null;
Expand Down Expand Up @@ -577,11 +576,11 @@ private void test() {
return;
}

// Create SDK instances for each environment
Map<String, Instance> sdkInstancesByEnvironment = new HashMap<>();
// Create SDK instances for each environment
Map<String, Featurevisor> sdkInstancesByEnvironment = new HashMap<>();
for (String environment : environments) {
DatafileContent datafile = datafilesByEnvironment.get(environment);
Instance instance = Featurevisor.createInstance(new Instance.InstanceOptions()
Featurevisor instance = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafile)
.logLevel(level));
sdkInstancesByEnvironment.put(environment, instance);
Expand Down Expand Up @@ -610,7 +609,7 @@ private void test() {

if (test.containsKey("feature")) {
String environment = (String) assertion.get("environment");
Instance f = sdkInstancesByEnvironment.get(environment);
Featurevisor f = sdkInstancesByEnvironment.get(environment);

// If "at" parameter is provided, create a new SDK instance with the specific hook
if (assertion.containsKey("at")) {
Expand All @@ -631,7 +630,7 @@ private void test() {
hooksManager.add(new HooksManager.Hook("at-parameter")
.bucketValue((options) -> (int) (atValue * 1000)));

f = Featurevisor.createInstance(new Instance.InstanceOptions()
f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafile)
.logLevel(level)
.hooks(hooksManager.getAll()));
Expand Down Expand Up @@ -710,7 +709,7 @@ private void benchmark() {
Logger.LogLevel level = getLoggerLevel();
Map<String, DatafileContent> datafilesByEnvironment = buildDatafiles(rootDirectoryPath, Arrays.asList(environment));

Instance f = Featurevisor.createInstance(new Instance.InstanceOptions()
Featurevisor f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafilesByEnvironment.get(environment))
.logLevel(level));

Expand Down Expand Up @@ -773,7 +772,7 @@ private void assessDistribution() {

Map<String, DatafileContent> datafilesByEnvironment = buildDatafiles(rootDirectoryPath, Arrays.asList(environment));

Instance f = Featurevisor.createInstance(new Instance.InstanceOptions()
Featurevisor f = Featurevisor.createInstance(new Featurevisor.Options()
.datafile(datafilesByEnvironment.get(environment))
.logLevel(getLoggerLevel()));

Expand Down
Loading