Skip to content

Commit

Permalink
Added preprocessRecord() to the Java SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
barrycaceres committed Oct 3, 2024
1 parent 71a152a commit aa10d35
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/main/java/com/senzing/sdk/SzEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,39 @@ String addRecord(SzRecordKey recordKey,
Set<SzFlag> flags)
throws SzUnknownDataSourceException, SzBadInputException, SzException;

/**
* Performs a hypothetical load of a the record described by the specified
* {@link String} record definition using the specified {@link Set} of
* {@link SzFlag} values.
* <p>
* The specified {@link Set} of {@link SzFlag} instances may contain any
* {@link SzFlag} value, but only flags belonging to the {@link
* SzFlagUsageGroup#SZ_RECORD} group will be recognized (other {@link SzFlag}
* instances will be ignored). <b>NOTE:</b> {@link java.util.EnumSet}
* offers an efficient means of constructing a {@link Set} of {@link SzFlag}.
*
* @param recordDefinition The {@link String} that defines the record, typically
* in JSON format.
*
* @param flags The optional {@link Set} of {@link SzFlag} instances belonging
* to the {@link SzFlagUsageGroup#SZ_RECORD} group to control how
* the operation is performed and the content of the response, or
* <code>null</code> to default to {@link
* SzFlag#SZ_RECORD_DEFAULT_FLAGS}.
*
* @return The JSON {@link String} result produced by preprocessing the record
* (depending on the specified flags).
*
* @throws SzException If a failure occurs.
*
* @see SzFlag#SZ_ENTITY_INCLUDE_INTERNAL_FEATURES
* @see SzFlag#SZ_ENTITY_INCLUDE_RECORD_FEATURE_DETAILS
* @see SzFlag#SZ_ENTITY_INCLUDE_RECORD_FEATURE_STATS
* @see SzFlagUsageGroup#SZ_RECORD
*/
String preprocessRecord(String recordDefinition, Set<SzFlag> flags)
throws SzException;

/**
* Delete a previously loaded record identified by the data source
* code and record ID from the specified {@link SzRecordKey}. This
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/com/senzing/sdk/core/NativeEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,24 @@ int addRecordWithInfo(String dataSourceCode,
long flags,
StringBuffer response);

/**
* Peforms a hypothetical load of the specified JSON record without
* actually loading the record responding with a JSON document describing
* how the record would be loaded and how the repository would be changed.
*
* @param jsonData A JSON document containing the attribute information for
* the record.
* @param flags The flags to control how the operation is performed and
* specifically the content of the response JSON document.
* @param response A {@link StringBuffer} for returning the response document.
*
* @return Zero (0) on success and non-zero on failure.
*/
int preprocessRecord(String jsonData,
long flags,
StringBuffer response);


/**
* Delete the record that has already been loaded.
*
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/senzing/sdk/core/NativeEngineJni.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ public native int addRecordWithInfo(String dataSourceCode,
long flags,
StringBuffer response);

/**
* {@inheritDoc}
*/
public native int preprocessRecord(String jsonData,
long flags,
StringBuffer response);


/**
* {@inheritDoc}
*/
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/com/senzing/sdk/core/SzCoreEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,33 @@ public String addRecord(SzRecordKey recordKey,
});
}

/**
* {@inheritDoc}
* <p>
* Implemented to call the underlying native API.
*/
@Override
public String preprocessRecord(String recordDefinition,
Set<SzFlag> flags)
throws SzException
{
return this.env.execute(() -> {
// clear out the SDK-specific flags
long downstreamFlags = SzFlag.toLong(flags) & SDK_FLAG_MASK;

StringBuffer sb = new StringBuffer();

int returnCode = this.nativeApi.preprocessRecord(
recordDefinition, downstreamFlags, sb);

// check the return code
this.env.handleReturnCode(returnCode, this.nativeApi);

// return the result
return sb.toString();
});
}

/**
* {@inheritDoc}
* <p>
Expand Down
122 changes: 122 additions & 0 deletions src/test/java/com/senzing/sdk/core/SzCoreEngineWriteTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.parallel.Execution;
Expand Down Expand Up @@ -261,6 +264,29 @@ public class SzCoreEngineWriteTest extends AbstractTest {
WRITE_FLAG_SETS = Collections.unmodifiableList(list);
}

private static final List<Set<SzFlag>> RECORD_FLAG_SETS;
static {
List<Set<SzFlag>> list = new LinkedList<>();
list.add(null);
list.add(SZ_NO_FLAGS);
list.add(SZ_RECORD_DEFAULT_FLAGS);
list.add(SZ_RECORD_ALL_FLAGS);
list.add(Collections.unmodifiableSet(EnumSet.of(
SZ_ENTITY_INCLUDE_RECORD_MATCHING_INFO,
SZ_ENTITY_INCLUDE_RECORD_UNMAPPED_DATA)));
list.add(Collections.unmodifiableSet(EnumSet.of(
SZ_ENTITY_INCLUDE_INTERNAL_FEATURES,
SZ_ENTITY_INCLUDE_RECORD_FEATURE_DETAILS,
SZ_ENTITY_INCLUDE_RECORD_FEATURE_STATS)));
list.add(Collections.unmodifiableSet(EnumSet.of(
SZ_ENTITY_INCLUDE_RECORD_FEATURE_DETAILS,
SZ_ENTITY_INCLUDE_RECORD_FEATURE_STATS)));
list.add(Collections.unmodifiableSet(EnumSet.of(
SZ_ENTITY_INCLUDE_RECORD_TYPES,
SZ_ENTITY_INCLUDE_RECORD_JSON_DATA)));
RECORD_FLAG_SETS = Collections.unmodifiableList(list);
}

private static final Map<SzRecordKey, Long> LOADED_RECORD_MAP
= Collections.synchronizedMap(new LinkedHashMap<>());

Expand Down Expand Up @@ -480,6 +506,102 @@ public void teardownEnvironment() {
}
}

public List<Arguments> getPreprocessRecordArguments() {
List<Arguments> result = new LinkedList<>();
int count = Math.min(NEW_RECORD_KEYS.size(), NEW_RECORDS.size());
Iterator<SzRecordKey> keyIter = NEW_RECORD_KEYS.iterator();
Iterator<SzRecord> recordIter = NEW_RECORDS.iterator();

Iterator<Set<SzFlag>> flagSetIter = circularIterator(RECORD_FLAG_SETS);

for (int index = 0; index < count; index++) {
SzRecordKey key = keyIter.next();
SzRecord record = recordIter.next();
Class<?> exceptionType = null;
Set<SzFlag> flagSet = flagSetIter.next();

record = new SzRecord(key, record);

result.add(Arguments.of(record, flagSet, exceptionType));
}

return result;
}

@ParameterizedTest
@MethodSource("getPreprocessRecordArguments")
@Order(5)
void testPreprocessRecord(SzRecord record,
Set<SzFlag> flags,
Class<?> expectedExceptionType)
{
String testData = "record=[ " + record + " ], withFlags=[ "
+ SzFlag.toString(flags) + " ], expectedException=[ "
+ expectedExceptionType + " ]";

this.performTest(() -> {
try {
SzEngine engine = this.env.getEngine();

String result = engine.preprocessRecord(record.toString(),
flags);

if (expectedExceptionType != null) {
fail("Unexpectedly succeeded in adding record: " + testData);
}

// parse the result as JSON and check that it parses
JsonObject jsonObject = parseJsonObject(result);

if (flags == null || flags.size() == 0) {
assertEquals(0, jsonObject.size(),
"Unexpected return properties on preprocess: "
+ testData + ", " + result);
} else {
if (flags.contains(SZ_ENTITY_INCLUDE_RECORD_UNMAPPED_DATA)) {
assertTrue(jsonObject.containsKey("UNMAPPED_DATA"),
"Did not get UNMAPPED_DATA property with "
+ "SZ_ENTITY_INCLUDE_RECORD_UNMAPPED_DATA: "
+ testData + ", " + result);
}
if (flags.contains(SZ_ENTITY_INCLUDE_RECORD_JSON_DATA)) {
assertTrue(jsonObject.containsKey("JSON_DATA"),
"Did not get JSON_DATA property with "
+ "SZ_ENTITY_INCLUDE_RECORD_JSON_DATA: "
+ testData + ", " + result);
}
if (flags.contains(SZ_ENTITY_INCLUDE_RECORD_FEATURE_DETAILS)) {
assertTrue(jsonObject.containsKey("FEATURES"),
"Did not get FEATURES property with "
+ "SZ_ENTITY_INCLUDE_RECORD_FEATURE_DETAILS: "
+ testData + ", " + result);
}
}

} catch (Exception e) {
String description = "";
if (e instanceof SzException) {
SzException sze = (SzException) e;
description = "errorCode=[ " + sze.getErrorCode()
+ " ], exception=[ " + e.toString() + " ]";
} else {
description = "exception=[ " + e.toString() + " ]";
}

if (expectedExceptionType == null) {
fail("Unexpectedly failed preprocessing a record: "
+ testData + ", " + description, e);

} else if (expectedExceptionType != e.getClass()) {
assertInstanceOf(
expectedExceptionType, e,
"preprocessRecord() failed with an unexpected exception type: "
+ testData + ", " + description);
}
}
});
}

public List<Arguments> getAddRecordArguments() {
List<Arguments> result = new LinkedList<>();
int count = Math.min(NEW_RECORD_KEYS.size(), NEW_RECORDS.size());
Expand Down

0 comments on commit aa10d35

Please sign in to comment.