Skip to content

Commit

Permalink
Merge pull request #253 from fuchsst/add-uuid-provided-function
Browse files Browse the repository at this point in the history
Add UUID provided function
  • Loading branch information
larsga authored Apr 13, 2022
2 parents a0538e5 + a6652d6 commit 6377fcc
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
Expand Down Expand Up @@ -103,6 +104,7 @@ public class BuiltinFunctions {
functions.put("to-json", new BuiltinFunctions.ToJson());
functions.put("replace", new BuiltinFunctions.Replace());
functions.put("trim", new BuiltinFunctions.Trim());
functions.put("uuid", new BuiltinFunctions.Uuid());

// BOOLEAN
functions.put("not", new BuiltinFunctions.Not());
Expand Down Expand Up @@ -974,6 +976,48 @@ public JsonNode call(JsonNode input, JsonNode[] arguments) {
}
}

// ===== UUID

public static class Uuid extends AbstractFunction {

public Uuid() {
super("uuid", 0, 2);
}

private long maskMSB(long number) {
final long version = 1 << 12;
long least12SignificantBit = (number & 0x000000000000FFFFL) >> 4;
return (number & 0xFFFFFFFFFFFF0000L) + version + least12SignificantBit;
}

private long maskLSB(long number) {
final long LSB_MASK = 0x3FFFFFFFFFFFFFFFL;
final long LSB_VARIANT3_BITFLAG = 0x8000000000000000L;
return (number & LSB_MASK) + LSB_VARIANT3_BITFLAG;
}

public JsonNode call(JsonNode input, JsonNode[] arguments) {
String uuid;
if (arguments.length == 0) {
uuid = UUID.randomUUID().toString();
} else if (arguments.length == 2) {
// NIL UUID is a special case defined in 4.1.7 of the RFC (https://www.ietf.org/rfc/rfc4122.txt)
if (arguments[0].isNull() && arguments[1].isNull()) {
uuid = "00000000-0000-0000-0000-000000000000";
} else {
long msb = NodeUtils.number(arguments[0], null).asLong();
long lsb = NodeUtils.number(arguments[1], null).asLong();
uuid = new UUID(maskMSB(msb), maskLSB(lsb)).toString();
}
} else {
throw new JsltException("Build-in UUID function must be called with either none or two parameters.");
}

return new TextNode(uuid);
}
}


// ===== JOIN

public static class Join extends AbstractFunction {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.schibsted.spt.data.jslt.buildinfunctions;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.schibsted.spt.data.jslt.Expression;
import com.schibsted.spt.data.jslt.JsltException;
import com.schibsted.spt.data.jslt.Parser;
import com.schibsted.spt.data.jslt.TestBase;
import org.junit.Test;

import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

public class UuidTest extends TestBase {
private static ObjectMapper mapper = new ObjectMapper();

@Test
public void testUuidWithoutParameterMatchesRegex() throws JsonProcessingException {
Expression given = Parser.compileString("uuid()");
String actual = mapper.writeValueAsString(given.apply(null));

String uuidRegex = "^\"[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\"$";
assertTrue(actual.matches(uuidRegex));
}

@Test
public void testUuidWithoutParameterGeneratesRandomValues() throws JsonProcessingException {
Expression given = Parser.compileString("{ \"uuid1\" : uuid(), \"uuid2\" : uuid() }");
JsonNode result = given.apply(null);
String actual1 = mapper.writeValueAsString(result.findValue("uuid1"));
String actual2 = mapper.writeValueAsString(result.findValue("uuid2"));

assertNotEquals(actual1, actual2);
}

@Test(expected = JsltException.class)
public void testUuidWithOneParameterRaisesJsltException() {
Expression given = Parser.compileString("uuid(123)");
given.apply(null);
}
}
35 changes: 35 additions & 0 deletions core/src/test/resources/function-tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,41 @@
"input" : "\"a\"",
"output": "\"a\""
},
{
"query": "uuid(9223372036854775807, 9223372036854775807)",
"input" : "null",
"output": "\"7fffffff-ffff-1fff-bfff-ffffffffffff\""
},
{
"query": "uuid(-9223372036854775808, -9223372036854775808)",
"input" : "null",
"output": "\"80000000-0000-1000-8000-000000000000\""
},
{
"query": "uuid(0, 0)",
"input" : "null",
"output": "\"00000000-0000-1000-8000-000000000000\""
},
{
"query": "uuid(null, 9223372036854775807)",
"input" : "null",
"output": "\"00000000-0000-1000-bfff-ffffffffffff\""
},
{
"query": "uuid(9223372036854775807, null)",
"input" : "null",
"output": "\"7fffffff-ffff-1fff-8000-000000000000\""
},
{
"query": "uuid(1234567890, 1234567890)",
"input" : "null",
"output": "\"00000000-4996-102d-8000-0000499602d2\""
},
{
"query": "uuid(null, null)",
"input" : "null",
"output": "\"00000000-0000-0000-0000-000000000000\""
},
{
"query": "min(1, 2)",
"input" : "null",
Expand Down
16 changes: 16 additions & 0 deletions functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,22 @@ trim(false) => "false"
trim(null) => null
```

### _uuid(long, long) -> string_

Generates a formatted UUID string with dashes.
If no parameter are passed, a random UUID version 4 will be generated.
If two parameter are passed, a UUID version 1 is generated based on two long values where the first parameter represents the MSB (most significant bytes) and the second parameter the LSB (least significant bytes) of the UUID.
If both parameter are null a NIL UUID (00000000-0000-0000-0000-000000000000 is generated)

Examples:

```
uuid() => "b02c39c0-6f8f-4250-97cd-78500af36e27"
uuid(1234567890, 1234567890) => "00000000-4996-102d-8000-0000499602d2"
uuid(0, 0) => "00000000-0000-1000-8000-000000000000"
uuid(null, null) => "00000000-0000-0000-0000-000000000000"
```

<!-- BOOLEAN ================================================================-->

## Boolean functions
Expand Down

0 comments on commit 6377fcc

Please sign in to comment.