Skip to content

Commit

Permalink
Added apoc.text.random(length, [valid_chars]) - Fixes #563
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-cowley authored and jexp committed Sep 12, 2017
1 parent 86aec4e commit 43fa521
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
27 changes: 26 additions & 1 deletion src/main/java/apoc/text/Strings.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
import java.net.URLEncoder;
import java.text.Normalizer;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;

import static java.lang.Math.toIntExact;
import static java.util.Arrays.asList;

/**
Expand Down Expand Up @@ -197,12 +200,34 @@ public String format(@Name("text") String text, @Name("params") List<Object> par
if (params == null) return text;
return String.format(Locale.ENGLISH,text, params.toArray());
}

@UserFunction
@Description("apoc.text.slug(text, delim) - slug the text with the given delimiter")
public String slug(@Name("text") String text, @Name(value = "delim", defaultValue = "-") String delim) {
if (text == null) return null;
if (delim == null) return null;
return text.trim().replaceAll("[\\W\\s]+", delim);
}


private static final String lower = "abcdefghijklmnopqrstuvwxyz";
private static final String upper = lower.toUpperCase();
private static final String numeric = "0123456789";

@UserFunction
@Description("apoc.text.random(length, valid) YIELD value - generate a random string")
public String random(final @Name("length") long length, @Name(value = "valid", defaultValue = "A-Za-z0-9") String valid) {
valid = valid.replaceAll("A-Z", upper).replaceAll("a-z", lower).replaceAll("0-9", numeric);

StringBuilder output = new StringBuilder( toIntExact(length) );

ThreadLocalRandom rand = ThreadLocalRandom.current();

while ( output.length() < length ) {
output.append( valid.charAt( rand.nextInt(valid.length()) ) );
}

return output.toString();
}

}
24 changes: 24 additions & 0 deletions src/test/java/apoc/text/StringsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@
import org.neo4j.helpers.collection.Iterators;
import org.neo4j.test.TestGraphDatabaseFactory;

import static java.lang.Math.toIntExact;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static apoc.util.MapUtil.map;
import static apoc.util.TestUtil.testCall;
import static apoc.util.TestUtil.testResult;
import static org.junit.Assert.*;


/**
* @author mh
* @since 05.05.16
Expand Down Expand Up @@ -326,4 +330,24 @@ public void testSlug() {
testCall(db, "RETURN apoc.text.slug('a- b','-') AS value", row -> assertEquals("a-b", row.get("value")));
testCall(db, "RETURN apoc.text.slug('a b c') AS value", row -> assertEquals("a-b-c", row.get("value")));
}

@Test
public void testRandom() {
Long length = 10L;
String valid = "A-Z0-9";

testCall(
db,
"RETURN apoc.text.random({length}, {valid}) as value",
map("length", length, "valid", valid),
row -> {
String value = row.get("value").toString();

Pattern pattern = Pattern.compile("^(["+valid+"]{"+ toIntExact(length) +"})$");
Matcher matcher = pattern.matcher(value);

assertTrue("String +" +value+ "+ should match the supplied pattern "+ pattern.toString(), matcher.matches());
}
);
}
}

0 comments on commit 43fa521

Please sign in to comment.