diff --git a/src/main/java/org/sqids/Sqids.java b/src/main/java/org/sqids/Sqids.java index 4aba293..40d2eb2 100644 --- a/src/main/java/org/sqids/Sqids.java +++ b/src/main/java/org/sqids/Sqids.java @@ -1,62 +1,89 @@ package org.sqids; -import java.util.*; - +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Sqids is designed to generate short YouTube-looking IDs from numbers. + *

+ * This is the Java implementation of https://github.com/sqids/sqids-spec. + * + * This implementation is immutable, thread-safe, no lock is necessary. + */ public class Sqids { - private final String Alphabet; - private final int AlphabetLength; - private final int MinLength; - private final Set BlockList; + private static final int MIN_ALPHABET_LENGTH = 3; + private static final int MIN_LENGTH_LIMIT = 255; + private static final int MIN_BLOCK_LIST_WORD_LENGTH = 3; + + private final String alphabet; + private final int alphabetLength; + private final int minLength; + private final Set blockList; - private Sqids(Builder builder) { - String alphabet = builder.Alphabet; + private Sqids(final Builder builder) { + String alphabet = builder.alphabet; int alphabetLength = alphabet.length(); - int minLength = builder.MinLength; - Set blockList = new HashSet<>(builder.BlockList); + int minLength = builder.minLength; + Set blockList = new HashSet<>(builder.blockList); if (alphabet.getBytes().length != alphabetLength) { throw new IllegalArgumentException("Alphabet cannot contain multibyte characters"); } - int minAlphabetLength = 3; - if (alphabetLength < minAlphabetLength) { - throw new IllegalArgumentException("Alphabet length must be at least " + minAlphabetLength); + if (alphabetLength < MIN_ALPHABET_LENGTH) { + throw new IllegalArgumentException("Alphabet length must be at least " + MIN_ALPHABET_LENGTH); } if (new HashSet<>(Arrays.asList(alphabet.split(""))).size() != alphabetLength) { throw new IllegalArgumentException("Alphabet must contain unique characters"); } - int minLengthLimit = 255; - if (minLength < 0 || minLength > minLengthLimit) { - throw new IllegalArgumentException("Minimum length has to be between 0 and " + minLengthLimit); + if (minLength < 0 || minLength > MIN_LENGTH_LIMIT) { + throw new IllegalArgumentException("Minimum length has to be between 0 and " + MIN_LENGTH_LIMIT); } Set filteredBlockList = new HashSet<>(); List alphabetChars = new ArrayList<>(Arrays.asList(alphabet.toLowerCase().split(""))); for (String word : blockList) { - if (word.length() >= 3) { - String wordLowercased = word.toLowerCase(); - List wordChars = new ArrayList<>(Arrays.asList(wordLowercased.split(""))); + if (word.length() >= MIN_BLOCK_LIST_WORD_LENGTH) { + word = word.toLowerCase(); + List wordChars = Arrays.asList(word.split("")); List intersection = new ArrayList<>(wordChars); intersection.retainAll(alphabetChars); if (intersection.size() == wordChars.size()) { - filteredBlockList.add(wordLowercased); + filteredBlockList.add(word); } } } - this.Alphabet = this.shuffle(alphabet); - this.AlphabetLength = this.Alphabet.length(); - this.MinLength = minLength; - this.BlockList = filteredBlockList; + this.alphabet = this.shuffle(alphabet); + this.alphabetLength = this.alphabet.length(); + this.minLength = minLength; + this.blockList = filteredBlockList; } + /** + * Generate a Sqids' Builder. + * + * @return New Builder instance. + */ public static Builder builder() { return new Builder(); } - public String encode(List numbers) { + /** + * Encode a list of numbers to a Sqids ID. + * + * @param numbers Numbers to encode. + * @return Sqids ID. + */ + public String encode(final List numbers) { if (numbers.isEmpty()) { return ""; } @@ -68,32 +95,41 @@ public String encode(List numbers) { return encodeNumbers(numbers); } - public List decode(String id) { + /** + * Decode a Sqids ID back to numbers. + * + * @param id ID to decode. + * @return List of decoded numbers. + */ + public List decode(final String id) { List ret = new ArrayList<>(); if (id.isEmpty()) { return ret; } - char[] alphabetChars = this.Alphabet.toCharArray(); + final char[] alphabetChars = this.alphabet.toCharArray(); Set alphabetSet = new HashSet<>(); - for (char c : alphabetChars) { + for (final char c : alphabetChars) { alphabetSet.add(c); } - for (char c : id.toCharArray()) { + for (final char c : id.toCharArray()) { if (!alphabetSet.contains(c)) { return ret; } } - char prefix = id.charAt(0); - int offset = this.Alphabet.indexOf(prefix); - String alphabet = new StringBuilder(this.Alphabet.substring(offset)).append(this.Alphabet, 0, offset).reverse().toString(); + final char prefix = id.charAt(0); + final int offset = this.alphabet.indexOf(prefix); + String alphabet = new StringBuilder(this.alphabet.substring(offset)) + .append(this.alphabet, 0, offset) + .reverse() + .toString(); String slicedId = id.substring(1); while (!slicedId.isEmpty()) { - char separator = alphabet.charAt(0); - String[] chunks = slicedId.split(String.valueOf(separator), 2); - int chunksLength = chunks.length; + final char separator = alphabet.charAt(0); + final String[] chunks = slicedId.split(String.valueOf(separator), 2); + final int chunksLength = chunks.length; if (chunksLength > 0) { if (chunks[0].isEmpty()) { return ret; @@ -108,29 +144,30 @@ public List decode(String id) { return ret; } - private String encodeNumbers(List numbers) { + private String encodeNumbers(final List numbers) { return this.encodeNumbers(numbers, 0); } - private String encodeNumbers(List numbers, int increment) { - if (increment > this.AlphabetLength) { + private String encodeNumbers(final List numbers, final int increment) { + if (increment > this.alphabetLength) { throw new RuntimeException("Reached max attempts to re-generate the ID"); } long offset = numbers.size(); for (int i = 0; i < numbers.size(); i++) { - offset = offset + this.Alphabet.charAt((int) (numbers.get(i) % this.AlphabetLength)) + i; + offset = offset + this.alphabet.charAt((int) (numbers.get(i) % this.alphabetLength)) + i; } - offset %= this.AlphabetLength; - offset = (offset + increment) % this.AlphabetLength; + offset %= this.alphabetLength; + offset = (offset + increment) % this.alphabetLength; - StringBuilder alphabetB = new StringBuilder(this.Alphabet.substring((int) offset)).append(this.Alphabet, 0, (int) offset); - char prefix = alphabetB.charAt(0); + final StringBuilder alphabetB = new StringBuilder(this.alphabet.substring((int) offset)) + .append(this.alphabet, 0, (int) offset); + final char prefix = alphabetB.charAt(0); String alphabet = alphabetB.reverse().toString(); - StringBuilder id = new StringBuilder().append(prefix); + final StringBuilder id = new StringBuilder().append(prefix); int numberSize = numbers.size(); for (int i = 0; i < numberSize; i++) { - long num = numbers.get(i); + final long num = numbers.get(i); id.append(toId(num, alphabet.substring(1))); if (i < numberSize - 1) { id.append(alphabet.charAt(0)); @@ -138,11 +175,11 @@ private String encodeNumbers(List numbers, int increment) { } } - if (this.MinLength > id.length()) { + if (this.minLength > id.length()) { id.append(alphabet.charAt(0)); - while (this.MinLength - id.length() > 0) { + while (this.minLength - id.length() > 0) { alphabet = shuffle(alphabet); - id.append(alphabet, 0, Math.min(this.MinLength - id.length(), alphabet.length())); + id.append(alphabet, 0, Math.min(this.minLength - id.length(), alphabet.length())); } } @@ -154,7 +191,7 @@ private String encodeNumbers(List numbers, int increment) { return id.toString(); } - private String shuffle(String alphabet) { + private String shuffle(final String alphabet) { char[] chars = alphabet.toCharArray(); int charLength = chars.length; for (int i = 0, j = charLength - 1; j > 0; i++, j--) { @@ -167,7 +204,7 @@ private String shuffle(String alphabet) { return new String(chars); } - private StringBuilder toId(long num, String alphabet) { + private StringBuilder toId(long num, final String alphabet) { StringBuilder id = new StringBuilder(); char[] chars = alphabet.toCharArray(); int charLength = chars.length; @@ -180,7 +217,7 @@ private StringBuilder toId(long num, String alphabet) { return id.reverse(); } - private long toNumber(String id, String alphabet) { + private long toNumber(final String id, final String alphabet) { char[] chars = alphabet.toCharArray(); int charLength = chars.length; long number = 0; @@ -192,10 +229,10 @@ private long toNumber(String id, String alphabet) { return number; } - private boolean isBlockedId(String id) { + private boolean isBlockedId(final String id) { String lowercaseId = id.toLowerCase(); - for (String word : this.BlockList) { + for (String word : this.blockList) { if (word.length() <= lowercaseId.length()) { if (lowercaseId.length() <= 3 || word.length() <= 3) { if (lowercaseId.equals(word)) { @@ -213,589 +250,632 @@ private boolean isBlockedId(String id) { return false; } + /** + * Default Sqids' {@code Builder}. + */ public static final class Builder { - private String Alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - private int MinLength = 0; - private Set BlockList = new HashSet<>( - Arrays.asList( - "1d10t", - "1d1ot", - "1di0t", - "1diot", - "1eccacu10", - "1eccacu1o", - "1eccacul0", - "1eccaculo", - "1mbec11e", - "1mbec1le", - "1mbeci1e", - "1mbecile", - "a11upat0", - "a11upato", - "a1lupat0", - "a1lupato", - "aand", - "ah01e", - "ah0le", - "aho1e", - "ahole", - "al1upat0", - "al1upato", - "allupat0", - "allupato", - "ana1", - "ana1e", - "anal", - "anale", - "anus", - "arrapat0", - "arrapato", - "arsch", - "arse", - "ass", - "b00b", - "b00be", - "b01ata", - "b0ceta", - "b0iata", - "b0ob", - "b0obe", - "b0sta", - "b1tch", - "b1te", - "b1tte", - "ba1atkar", - "balatkar", - "bastard0", - "bastardo", - "batt0na", - "battona", - "bitch", - "bite", - "bitte", - "bo0b", - "bo0be", - "bo1ata", - "boceta", - "boiata", - "boob", - "boobe", - "bosta", - "bran1age", - "bran1er", - "bran1ette", - "bran1eur", - "bran1euse", - "branlage", - "branler", - "branlette", - "branleur", - "branleuse", - "c0ck", - "c0g110ne", - "c0g11one", - "c0g1i0ne", - "c0g1ione", - "c0gl10ne", - "c0gl1one", - "c0gli0ne", - "c0glione", - "c0na", - "c0nnard", - "c0nnasse", - "c0nne", - "c0u111es", - "c0u11les", - "c0u1l1es", - "c0u1lles", - "c0ui11es", - "c0ui1les", - "c0uil1es", - "c0uilles", - "c11t", - "c11t0", - "c11to", - "c1it", - "c1it0", - "c1ito", - "cabr0n", - "cabra0", - "cabrao", - "cabron", - "caca", - "cacca", - "cacete", - "cagante", - "cagar", - "cagare", - "cagna", - "cara1h0", - "cara1ho", - "caracu10", - "caracu1o", - "caracul0", - "caraculo", - "caralh0", - "caralho", - "cazz0", - "cazz1mma", - "cazzata", - "cazzimma", - "cazzo", - "ch00t1a", - "ch00t1ya", - "ch00tia", - "ch00tiya", - "ch0d", - "ch0ot1a", - "ch0ot1ya", - "ch0otia", - "ch0otiya", - "ch1asse", - "ch1avata", - "ch1er", - "ch1ng0", - "ch1ngadaz0s", - "ch1ngadazos", - "ch1ngader1ta", - "ch1ngaderita", - "ch1ngar", - "ch1ngo", - "ch1ngues", - "ch1nk", - "chatte", - "chiasse", - "chiavata", - "chier", - "ching0", - "chingadaz0s", - "chingadazos", - "chingader1ta", - "chingaderita", - "chingar", - "chingo", - "chingues", - "chink", - "cho0t1a", - "cho0t1ya", - "cho0tia", - "cho0tiya", - "chod", - "choot1a", - "choot1ya", - "chootia", - "chootiya", - "cl1t", - "cl1t0", - "cl1to", - "clit", - "clit0", - "clito", - "cock", - "cog110ne", - "cog11one", - "cog1i0ne", - "cog1ione", - "cogl10ne", - "cogl1one", - "cogli0ne", - "coglione", - "cona", - "connard", - "connasse", - "conne", - "cou111es", - "cou11les", - "cou1l1es", - "cou1lles", - "coui11es", - "coui1les", - "couil1es", - "couilles", - "cracker", - "crap", - "cu10", - "cu1att0ne", - "cu1attone", - "cu1er0", - "cu1ero", - "cu1o", - "cul0", - "culatt0ne", - "culattone", - "culer0", - "culero", - "culo", - "cum", - "cunt", - "d11d0", - "d11do", - "d1ck", - "d1ld0", - "d1ldo", - "damn", - "de1ch", - "deich", - "depp", - "di1d0", - "di1do", - "dick", - "dild0", - "dildo", - "dyke", - "encu1e", - "encule", - "enema", - "enf01re", - "enf0ire", - "enfo1re", - "enfoire", - "estup1d0", - "estup1do", - "estupid0", - "estupido", - "etr0n", - "etron", - "f0da", - "f0der", - "f0ttere", - "f0tters1", - "f0ttersi", - "f0tze", - "f0utre", - "f1ca", - "f1cker", - "f1ga", - "fag", - "fica", - "ficker", - "figa", - "foda", - "foder", - "fottere", - "fotters1", - "fottersi", - "fotze", - "foutre", - "fr0c10", - "fr0c1o", - "fr0ci0", - "fr0cio", - "fr0sc10", - "fr0sc1o", - "fr0sci0", - "fr0scio", - "froc10", - "froc1o", - "froci0", - "frocio", - "frosc10", - "frosc1o", - "frosci0", - "froscio", - "fuck", - "g00", - "g0o", - "g0u1ne", - "g0uine", - "gandu", - "go0", - "goo", - "gou1ne", - "gouine", - "gr0gnasse", - "grognasse", - "haram1", - "harami", - "haramzade", - "hund1n", - "hundin", - "id10t", - "id1ot", - "idi0t", - "idiot", - "imbec11e", - "imbec1le", - "imbeci1e", - "imbecile", - "j1zz", - "jerk", - "jizz", - "k1ke", - "kam1ne", - "kamine", - "kike", - "leccacu10", - "leccacu1o", - "leccacul0", - "leccaculo", - "m1erda", - "m1gn0tta", - "m1gnotta", - "m1nch1a", - "m1nchia", - "m1st", - "mam0n", - "mamahuev0", - "mamahuevo", - "mamon", - "masturbat10n", - "masturbat1on", - "masturbate", - "masturbati0n", - "masturbation", - "merd0s0", - "merd0so", - "merda", - "merde", - "merdos0", - "merdoso", - "mierda", - "mign0tta", - "mignotta", - "minch1a", - "minchia", - "mist", - "musch1", - "muschi", - "n1gger", - "neger", - "negr0", - "negre", - "negro", - "nerch1a", - "nerchia", - "nigger", - "orgasm", - "p00p", - "p011a", - "p01la", - "p0l1a", - "p0lla", - "p0mp1n0", - "p0mp1no", - "p0mpin0", - "p0mpino", - "p0op", - "p0rca", - "p0rn", - "p0rra", - "p0uff1asse", - "p0uffiasse", - "p1p1", - "p1pi", - "p1r1a", - "p1rla", - "p1sc10", - "p1sc1o", - "p1sci0", - "p1scio", - "p1sser", - "pa11e", - "pa1le", - "pal1e", - "palle", - "pane1e1r0", - "pane1e1ro", - "pane1eir0", - "pane1eiro", - "panele1r0", - "panele1ro", - "paneleir0", - "paneleiro", - "patakha", - "pec0r1na", - "pec0rina", - "pecor1na", - "pecorina", - "pen1s", - "pendej0", - "pendejo", - "penis", - "pip1", - "pipi", - "pir1a", - "pirla", - "pisc10", - "pisc1o", - "pisci0", - "piscio", - "pisser", - "po0p", - "po11a", - "po1la", - "pol1a", - "polla", - "pomp1n0", - "pomp1no", - "pompin0", - "pompino", - "poop", - "porca", - "porn", - "porra", - "pouff1asse", - "pouffiasse", - "pr1ck", - "prick", - "pussy", - "put1za", - "puta", - "puta1n", - "putain", - "pute", - "putiza", - "puttana", - "queca", - "r0mp1ba11e", - "r0mp1ba1le", - "r0mp1bal1e", - "r0mp1balle", - "r0mpiba11e", - "r0mpiba1le", - "r0mpibal1e", - "r0mpiballe", - "rand1", - "randi", - "rape", - "recch10ne", - "recch1one", - "recchi0ne", - "recchione", - "retard", - "romp1ba11e", - "romp1ba1le", - "romp1bal1e", - "romp1balle", - "rompiba11e", - "rompiba1le", - "rompibal1e", - "rompiballe", - "ruff1an0", - "ruff1ano", - "ruffian0", - "ruffiano", - "s1ut", - "sa10pe", - "sa1aud", - "sa1ope", - "sacanagem", - "sal0pe", - "salaud", - "salope", - "saugnapf", - "sb0rr0ne", - "sb0rra", - "sb0rrone", - "sbattere", - "sbatters1", - "sbattersi", - "sborr0ne", - "sborra", - "sborrone", - "sc0pare", - "sc0pata", - "sch1ampe", - "sche1se", - "sche1sse", - "scheise", - "scheisse", - "schlampe", - "schwachs1nn1g", - "schwachs1nnig", - "schwachsinn1g", - "schwachsinnig", - "schwanz", - "scopare", - "scopata", - "sexy", - "sh1t", - "shit", - "slut", - "sp0mp1nare", - "sp0mpinare", - "spomp1nare", - "spompinare", - "str0nz0", - "str0nza", - "str0nzo", - "stronz0", - "stronza", - "stronzo", - "stup1d", - "stupid", - "succh1am1", - "succh1ami", - "succhiam1", - "succhiami", - "sucker", - "t0pa", - "tapette", - "test1c1e", - "test1cle", - "testic1e", - "testicle", - "tette", - "topa", - "tr01a", - "tr0ia", - "tr0mbare", - "tr1ng1er", - "tr1ngler", - "tring1er", - "tringler", - "tro1a", - "troia", - "trombare", - "turd", - "twat", - "vaffancu10", - "vaffancu1o", - "vaffancul0", - "vaffanculo", - "vag1na", - "vagina", - "verdammt", - "verga", - "w1chsen", - "wank", - "wichsen", - "x0ch0ta", - "x0chota", - "xana", - "xoch0ta", - "xochota", - "z0cc01a", - "z0cc0la", - "z0cco1a", - "z0ccola", - "z1z1", - "z1zi", - "ziz1", - "zizi", - "zocc01a", - "zocc0la", - "zocco1a", - "zoccola") - ); - - public Builder alphabet(String alphabet) { - if (alphabet != null) - this.Alphabet = alphabet; + /** + * Default Alphabet used by {@code Builder}. + */ + public static final String DEFAULT_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + /** + * Default Minimum length used by {@code Builder}. + */ + public static final int DEFAULT_MIN_LENGTH = 0; + + /** + * Default Block list used by {@code Builder}. + * + * Note: This is a Immutable Set. + */ + public static final Set DEFAULT_BLOCK_LIST = Collections.unmodifiableSet(Stream.of( + "1d10t", + "1d1ot", + "1di0t", + "1diot", + "1eccacu10", + "1eccacu1o", + "1eccacul0", + "1eccaculo", + "1mbec11e", + "1mbec1le", + "1mbeci1e", + "1mbecile", + "a11upat0", + "a11upato", + "a1lupat0", + "a1lupato", + "aand", + "ah01e", + "ah0le", + "aho1e", + "ahole", + "al1upat0", + "al1upato", + "allupat0", + "allupato", + "ana1", + "ana1e", + "anal", + "anale", + "anus", + "arrapat0", + "arrapato", + "arsch", + "arse", + "ass", + "b00b", + "b00be", + "b01ata", + "b0ceta", + "b0iata", + "b0ob", + "b0obe", + "b0sta", + "b1tch", + "b1te", + "b1tte", + "ba1atkar", + "balatkar", + "bastard0", + "bastardo", + "batt0na", + "battona", + "bitch", + "bite", + "bitte", + "bo0b", + "bo0be", + "bo1ata", + "boceta", + "boiata", + "boob", + "boobe", + "bosta", + "bran1age", + "bran1er", + "bran1ette", + "bran1eur", + "bran1euse", + "branlage", + "branler", + "branlette", + "branleur", + "branleuse", + "c0ck", + "c0g110ne", + "c0g11one", + "c0g1i0ne", + "c0g1ione", + "c0gl10ne", + "c0gl1one", + "c0gli0ne", + "c0glione", + "c0na", + "c0nnard", + "c0nnasse", + "c0nne", + "c0u111es", + "c0u11les", + "c0u1l1es", + "c0u1lles", + "c0ui11es", + "c0ui1les", + "c0uil1es", + "c0uilles", + "c11t", + "c11t0", + "c11to", + "c1it", + "c1it0", + "c1ito", + "cabr0n", + "cabra0", + "cabrao", + "cabron", + "caca", + "cacca", + "cacete", + "cagante", + "cagar", + "cagare", + "cagna", + "cara1h0", + "cara1ho", + "caracu10", + "caracu1o", + "caracul0", + "caraculo", + "caralh0", + "caralho", + "cazz0", + "cazz1mma", + "cazzata", + "cazzimma", + "cazzo", + "ch00t1a", + "ch00t1ya", + "ch00tia", + "ch00tiya", + "ch0d", + "ch0ot1a", + "ch0ot1ya", + "ch0otia", + "ch0otiya", + "ch1asse", + "ch1avata", + "ch1er", + "ch1ng0", + "ch1ngadaz0s", + "ch1ngadazos", + "ch1ngader1ta", + "ch1ngaderita", + "ch1ngar", + "ch1ngo", + "ch1ngues", + "ch1nk", + "chatte", + "chiasse", + "chiavata", + "chier", + "ching0", + "chingadaz0s", + "chingadazos", + "chingader1ta", + "chingaderita", + "chingar", + "chingo", + "chingues", + "chink", + "cho0t1a", + "cho0t1ya", + "cho0tia", + "cho0tiya", + "chod", + "choot1a", + "choot1ya", + "chootia", + "chootiya", + "cl1t", + "cl1t0", + "cl1to", + "clit", + "clit0", + "clito", + "cock", + "cog110ne", + "cog11one", + "cog1i0ne", + "cog1ione", + "cogl10ne", + "cogl1one", + "cogli0ne", + "coglione", + "cona", + "connard", + "connasse", + "conne", + "cou111es", + "cou11les", + "cou1l1es", + "cou1lles", + "coui11es", + "coui1les", + "couil1es", + "couilles", + "cracker", + "crap", + "cu10", + "cu1att0ne", + "cu1attone", + "cu1er0", + "cu1ero", + "cu1o", + "cul0", + "culatt0ne", + "culattone", + "culer0", + "culero", + "culo", + "cum", + "cunt", + "d11d0", + "d11do", + "d1ck", + "d1ld0", + "d1ldo", + "damn", + "de1ch", + "deich", + "depp", + "di1d0", + "di1do", + "dick", + "dild0", + "dildo", + "dyke", + "encu1e", + "encule", + "enema", + "enf01re", + "enf0ire", + "enfo1re", + "enfoire", + "estup1d0", + "estup1do", + "estupid0", + "estupido", + "etr0n", + "etron", + "f0da", + "f0der", + "f0ttere", + "f0tters1", + "f0ttersi", + "f0tze", + "f0utre", + "f1ca", + "f1cker", + "f1ga", + "fag", + "fica", + "ficker", + "figa", + "foda", + "foder", + "fottere", + "fotters1", + "fottersi", + "fotze", + "foutre", + "fr0c10", + "fr0c1o", + "fr0ci0", + "fr0cio", + "fr0sc10", + "fr0sc1o", + "fr0sci0", + "fr0scio", + "froc10", + "froc1o", + "froci0", + "frocio", + "frosc10", + "frosc1o", + "frosci0", + "froscio", + "fuck", + "g00", + "g0o", + "g0u1ne", + "g0uine", + "gandu", + "go0", + "goo", + "gou1ne", + "gouine", + "gr0gnasse", + "grognasse", + "haram1", + "harami", + "haramzade", + "hund1n", + "hundin", + "id10t", + "id1ot", + "idi0t", + "idiot", + "imbec11e", + "imbec1le", + "imbeci1e", + "imbecile", + "j1zz", + "jerk", + "jizz", + "k1ke", + "kam1ne", + "kamine", + "kike", + "leccacu10", + "leccacu1o", + "leccacul0", + "leccaculo", + "m1erda", + "m1gn0tta", + "m1gnotta", + "m1nch1a", + "m1nchia", + "m1st", + "mam0n", + "mamahuev0", + "mamahuevo", + "mamon", + "masturbat10n", + "masturbat1on", + "masturbate", + "masturbati0n", + "masturbation", + "merd0s0", + "merd0so", + "merda", + "merde", + "merdos0", + "merdoso", + "mierda", + "mign0tta", + "mignotta", + "minch1a", + "minchia", + "mist", + "musch1", + "muschi", + "n1gger", + "neger", + "negr0", + "negre", + "negro", + "nerch1a", + "nerchia", + "nigger", + "orgasm", + "p00p", + "p011a", + "p01la", + "p0l1a", + "p0lla", + "p0mp1n0", + "p0mp1no", + "p0mpin0", + "p0mpino", + "p0op", + "p0rca", + "p0rn", + "p0rra", + "p0uff1asse", + "p0uffiasse", + "p1p1", + "p1pi", + "p1r1a", + "p1rla", + "p1sc10", + "p1sc1o", + "p1sci0", + "p1scio", + "p1sser", + "pa11e", + "pa1le", + "pal1e", + "palle", + "pane1e1r0", + "pane1e1ro", + "pane1eir0", + "pane1eiro", + "panele1r0", + "panele1ro", + "paneleir0", + "paneleiro", + "patakha", + "pec0r1na", + "pec0rina", + "pecor1na", + "pecorina", + "pen1s", + "pendej0", + "pendejo", + "penis", + "pip1", + "pipi", + "pir1a", + "pirla", + "pisc10", + "pisc1o", + "pisci0", + "piscio", + "pisser", + "po0p", + "po11a", + "po1la", + "pol1a", + "polla", + "pomp1n0", + "pomp1no", + "pompin0", + "pompino", + "poop", + "porca", + "porn", + "porra", + "pouff1asse", + "pouffiasse", + "pr1ck", + "prick", + "pussy", + "put1za", + "puta", + "puta1n", + "putain", + "pute", + "putiza", + "puttana", + "queca", + "r0mp1ba11e", + "r0mp1ba1le", + "r0mp1bal1e", + "r0mp1balle", + "r0mpiba11e", + "r0mpiba1le", + "r0mpibal1e", + "r0mpiballe", + "rand1", + "randi", + "rape", + "recch10ne", + "recch1one", + "recchi0ne", + "recchione", + "retard", + "romp1ba11e", + "romp1ba1le", + "romp1bal1e", + "romp1balle", + "rompiba11e", + "rompiba1le", + "rompibal1e", + "rompiballe", + "ruff1an0", + "ruff1ano", + "ruffian0", + "ruffiano", + "s1ut", + "sa10pe", + "sa1aud", + "sa1ope", + "sacanagem", + "sal0pe", + "salaud", + "salope", + "saugnapf", + "sb0rr0ne", + "sb0rra", + "sb0rrone", + "sbattere", + "sbatters1", + "sbattersi", + "sborr0ne", + "sborra", + "sborrone", + "sc0pare", + "sc0pata", + "sch1ampe", + "sche1se", + "sche1sse", + "scheise", + "scheisse", + "schlampe", + "schwachs1nn1g", + "schwachs1nnig", + "schwachsinn1g", + "schwachsinnig", + "schwanz", + "scopare", + "scopata", + "sexy", + "sh1t", + "shit", + "slut", + "sp0mp1nare", + "sp0mpinare", + "spomp1nare", + "spompinare", + "str0nz0", + "str0nza", + "str0nzo", + "stronz0", + "stronza", + "stronzo", + "stup1d", + "stupid", + "succh1am1", + "succh1ami", + "succhiam1", + "succhiami", + "sucker", + "t0pa", + "tapette", + "test1c1e", + "test1cle", + "testic1e", + "testicle", + "tette", + "topa", + "tr01a", + "tr0ia", + "tr0mbare", + "tr1ng1er", + "tr1ngler", + "tring1er", + "tringler", + "tro1a", + "troia", + "trombare", + "turd", + "twat", + "vaffancu10", + "vaffancu1o", + "vaffancul0", + "vaffanculo", + "vag1na", + "vagina", + "verdammt", + "verga", + "w1chsen", + "wank", + "wichsen", + "x0ch0ta", + "x0chota", + "xana", + "xoch0ta", + "xochota", + "z0cc01a", + "z0cc0la", + "z0cco1a", + "z0ccola", + "z1z1", + "z1zi", + "ziz1", + "zizi", + "zocc01a", + "zocc0la", + "zocco1a", + "zoccola").collect(Collectors.toSet())); + + private String alphabet = DEFAULT_ALPHABET; + private int minLength = 0; + private Set blockList = DEFAULT_BLOCK_LIST; + + /** + * Set {@code Builder}'s alphabet. + * + * @param alphabet The new {@code Builder}'s alphabet + * @return this {@code Builder} object + */ + public Builder alphabet(final String alphabet) { + if (alphabet != null) { + this.alphabet = alphabet; + } return this; } - public Builder minLength(int minLength) { - this.MinLength = minLength; + /** + * Set {@code Builder}'s minimum length. + * + * @param minLength The new {@code Builder}'s minimum length. + * @return this {@code Builder} object + */ + public Builder minLength(final int minLength) { + this.minLength = minLength; return this; } - public Builder blockList(Set blockList) { - if (blockList != null) - this.BlockList = blockList; + /** + * Set {@code Builder}'s block list. + * + * @param blockList The new {@code Builder}'s block list. A copy will be created. + * @return this {@code Builder} object + */ + public Builder blockList(final Set blockList) { + if (blockList != null) { + this.blockList = Collections.unmodifiableSet(new HashSet<>(blockList)); + } return this; } + /** + * Returns a newly-created {@code Sqids} based on the contents of this {@code Builder}. + * + * @return New Sqids instance. + */ public Sqids build() { return new Sqids(this); } diff --git a/src/test/java/org/sqids/AlphabetTests.java b/src/test/java/org/sqids/AlphabetTests.java index 4b8b5f2..0de444d 100644 --- a/src/test/java/org/sqids/AlphabetTests.java +++ b/src/test/java/org/sqids/AlphabetTests.java @@ -1,11 +1,11 @@ package org.sqids; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - import java.util.Arrays; import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + public class AlphabetTests { @Test public void simpleAlphabet() { diff --git a/src/test/java/org/sqids/BlockListTests.java b/src/test/java/org/sqids/BlockListTests.java index bd3848f..96bf991 100644 --- a/src/test/java/org/sqids/BlockListTests.java +++ b/src/test/java/org/sqids/BlockListTests.java @@ -1,12 +1,12 @@ package org.sqids; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - import java.util.Arrays; import java.util.HashSet; import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + public class BlockListTests { @Test public void blockList() { diff --git a/src/test/java/org/sqids/EncodeTests.java b/src/test/java/org/sqids/EncodeTests.java index 21b20ba..f66c070 100644 --- a/src/test/java/org/sqids/EncodeTests.java +++ b/src/test/java/org/sqids/EncodeTests.java @@ -1,10 +1,14 @@ package org.sqids; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.util.*; - public class EncodeTests { private final Sqids sqids = Sqids.builder().build(); diff --git a/src/test/java/org/sqids/MinLengthTests.java b/src/test/java/org/sqids/MinLengthTests.java index 9c035eb..f73d47c 100644 --- a/src/test/java/org/sqids/MinLengthTests.java +++ b/src/test/java/org/sqids/MinLengthTests.java @@ -1,10 +1,14 @@ package org.sqids; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.util.*; - public class MinLengthTests { private final int minLength = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".length();