/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.vertical.engine.handlers; import java.text.Normalizer; import java.util.regex.Pattern; import com.google.common.collect.ImmutableMap; /** * based on work from http://stackoverflow.com/questions/1453171/n-n-n-or-remove-diacritical-marks-from-unicode-cha */ public class NameGenerator { public static final String DEFAULT_REPLACE = ""; public static final String NOT_ASCII = "[^\\p{ASCII}]"; public static final String DIACRITICAL = "[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+"; /* special regexp char ranges relevant for simplification -> see http://docstore.mik.ua/orelly/perl/prog3/ch05_04.htm InCombiningDiacriticalMarks: special marks that are part of "normal" \u00e4, \u00f6, \u00ee etc.. IsSk: Symbol, Modifier see http://www.fileformat.info/info/unicode/category/Sk/list.htm IsLm: Letter, Modifier see http://www.fileformat.info/info/unicode/category/Lm/list.htm */ public static final Pattern DIACRITICS = Pattern.compile( DIACRITICAL ); // dots and @ sign are not touched, see CMS-1806 private static final ImmutableMap<Character, String> NON_DIACRITICS = ImmutableMap.<Character, String>builder() //remove crap strings with no semantics .put( '\"', "" ) .put( '\'', "" ) //keep relevant characters as separation .put( ' ', DEFAULT_REPLACE ) .put( ']', DEFAULT_REPLACE ) .put( '[', DEFAULT_REPLACE ) .put( ')', DEFAULT_REPLACE ) .put( '(', DEFAULT_REPLACE ) .put( '=', DEFAULT_REPLACE ) .put( '!', DEFAULT_REPLACE ) .put( '/', DEFAULT_REPLACE ) .put( '\\', DEFAULT_REPLACE ) .put( '&', DEFAULT_REPLACE ) .put( ',', DEFAULT_REPLACE ) .put( '?', DEFAULT_REPLACE ) .put( '\u00b0', DEFAULT_REPLACE ) //remove ?? is diacritic? .put( '|', DEFAULT_REPLACE ) .put( '<', DEFAULT_REPLACE ) .put( '>', DEFAULT_REPLACE ) .put( ';', DEFAULT_REPLACE ) .put( ':', DEFAULT_REPLACE ) .put( '#', DEFAULT_REPLACE ) .put( '~', DEFAULT_REPLACE ) .put( '+', DEFAULT_REPLACE ) .put( '*', DEFAULT_REPLACE ) //replace non-diacritics as their equivalent chars .put( '\u0141', "l" ) // BiaLystock .put( '\u0142', "l" ) // Bialystock .put( '\u00df', "ss" ) .put( '\u00e6', "ae") .put( '\u00f8', "o") .put( '\u00a9', "c" ) .put( '\u00D0', "d") // all \u00d0 \u00f0 from http://de.wikipedia.org/wiki/%C3%90 .put( '\u00F0', "d" ) .put( '\u0110', "d") .put( '\u0111', "d") .put( '\u0189', "d") .put( '\u0256', "d") .put( '\u00DE', "th") // thorn \u00de .put( '\u00FE', "th" ) // thorn \u00fe // cyrillic letters transliteration // big letters .put( '\u0410', "a" ) // А .put( '\u0411', "b" ) // Б .put( '\u0412', "v" ) // В .put( '\u0413', "g" ) // Г .put( '\u0414', "d" ) // Д .put( '\u0415', "e" ) // Е .put( '\u0401', "jo" ) // Ё .put( '\u0416', "zh" ) // Ж .put( '\u0417', "z" ) // З .put( '\u0418', "i" ) // И .put( '\u0419', "j" ) // Й .put( '\u041a', "k" ) // К .put( '\u041b', "l" ) // Л .put( '\u041c', "m" ) // М .put( '\u041d', "n" ) // Н .put( '\u041e', "o" ) // О .put( '\u041f', "p" ) // П .put( '\u0420', "r" ) // Р .put( '\u0421', "s" ) // С .put( '\u0422', "t" ) // Т .put( '\u0423', "u" ) // У .put( '\u0424', "f" ) // Ф .put( '\u0425', "h" ) // Х .put( '\u0426', "c" ) // Ц .put( '\u0427', "ch" ) // Ч .put( '\u0428', "sh" ) // Ш .put( '\u0429', "sch" ) // Щ .put( '\u042a', "" ) // Ъ .put( '\u042b', "y" ) // Ы .put( '\u042c', "" ) // Ь .put( '\u042d', "eh" ) // Э .put( '\u042e', "ju" ) // Ю .put( '\u042f', "ja" ) // Я // small letters .put( '\u0430', "a" ) // а .put( '\u0431', "b" ) // б .put( '\u0432', "v" ) // в .put( '\u0433', "g" ) // г .put( '\u0434', "d" ) // д .put( '\u0435', "e" ) // е .put( '\u0451', "jo" ) // ё .put( '\u0436', "zh" ) // ж .put( '\u0437', "z" ) // з .put( '\u0438', "i" ) // и .put( '\u0439', "j" ) // й .put( '\u043a', "k" ) // к .put( '\u043b', "l" ) // л .put( '\u043c', "m" ) // м .put( '\u043d', "n" ) // н .put( '\u043e', "o" ) // о .put( '\u043f', "p" ) // п .put( '\u0440', "r" ) // р .put( '\u0441', "s" ) // с .put( '\u0442', "t" ) // т .put( '\u0443', "u" ) // у .put( '\u0444', "f" ) // ф .put( '\u0445', "h" ) // х .put( '\u0446', "c" ) // ц .put( '\u0447', "ch" ) // ч .put( '\u0448', "sh" ) // ш .put( '\u0449', "sch" ) // щ .put( '\u044a', "" ) // ъ .put( '\u044b', "y" ) // ы .put( '\u044c', "" ) // ь .put( '\u044d', "eh" ) // э .put( '\u044e', "ju" ) // ю .put( '\u044f', "ja" ) // я // others .put( '\u0406', "i" ) // І .put( '\u0472', "fh" ) // Ѳ .put( '\u0462', "je" ) // Ѣ .put( '\u0474', "yh" ) // Ѵ .put( '\u0490', "gj" ) // Ґ .put( '\u0403', "gj" ) // Ѓ .put( '\u0404', "ye" ) // Є .put( '\u0407', "yi" ) // Ї .put( '\u0405', "dz" ) // Ѕ .put( '\u0408', "jj" ) // Ј .put( '\u0409', "lj" ) // Љ .put( '\u040a', "nj" ) // Њ .put( '\u040c', "kj" ) // Ќ .put( '\u040f', "dj" ) // Џ .put( '\u040e', "uj" ) // Ў .put( '\u0456', "i" ) // і .put( '\u0473', "fh" ) // ѳ .put( '\u0463', "je" ) // ѣ .put( '\u0475', "yh" ) // ѵ .put( '\u0491', "gj" ) // ґ .put( '\u0453', "gj" ) // ѓ .put( '\u0454', "ye" ) // є .put( '\u0457', "yi" ) // ї .put( '\u0455', "dz" ) // ѕ .put( '\u0458', "jj" ) // ј .put( '\u0459', "lj" ) // љ .put( '\u045a', "nj" ) // њ .put( '\u045c', "kj" ) // ќ .put( '\u045f', "dj" ) // џ .put( '\u045e', "uj" ) // ў // greek // big letters .put( '\u03b1', "a" ) // Α .put( '\u03b2', "b" ) // Β .put( '\u03b3', "g" ) // Γ .put( '\u03b4', "d" ) // Δ .put( '\u03b5', "e" ) // Ε .put( '\u03b6', "z" ) // Ζ .put( '\u03b7', "e" ) // Η .put( '\u03b8', "th" ) // Θ .put( '\u03b9', "i" ) // Ι .put( '\u03ba', "c" ) // Κ .put( '\u03bb', "l" ) // Λ .put( '\u03bc', "m" ) // Μ .put( '\u03bd', "n" ) // Ν .put( '\u03be', "x" ) // Ξ .put( '\u03bf', "o" ) // Ο .put( '\u03c0', "p" ) // Π .put( '\u03c1', "r" ) // Ρ .put( '\u03c3', "s" ) // Σ .put( '\u03c4', "t" ) // Τ .put( '\u03c5', "y" ) // Υ .put( '\u03c6', "ph" ) // Φ .put( '\u03c7', "ch" ) // Χ .put( '\u03c8', "ps" ) // Ψ .put( '\u03c9', "o" ) // Ω // small letters .put( '\u0391', "a" ) // α .put( '\u0392', "b" ) // β .put( '\u0393', "g" ) // γ .put( '\u0394', "d" ) // δ .put( '\u0395', "e" ) // ε .put( '\u0396', "z" ) // ζ .put( '\u0397', "e" ) // η .put( '\u0398', "th" ) // θ .put( '\u0399', "i" ) // ι .put( '\u039a', "c" ) // κ .put( '\u039b', "l" ) // λ .put( '\u039c', "m" ) // μ .put( '\u039d', "n" ) // ν .put( '\u039e', "x" ) // ξ .put( '\u039f', "o" ) // ο .put( '\u03a0', "p" ) // π .put( '\u03a1', "r" ) // ρ .put( '\u03a3', "s" ) // σ .put( '\u03a4', "t" ) // τ .put( '\u03a5', "y" ) // υ .put( '\u03a6', "ph" ) // φ .put( '\u03a7', "ch" ) // χ .put( '\u03a8', "ps" ) // ψ .put( '\u03a9', "o" ) // ω .build(); public static String transcribeName( final String string ) { final String name = transcribe( string ); if ( name == null || name.length() == 0 ) { final int random = (int) ( Math.random() * 10000 ); return String.format( "user%04d", random ); } return name; } public static String transcribe( final String string ) { if ( string == null ) { return null; } final StringBuilder stringBuilder = new StringBuilder(); final int length = string.length(); final char[] characters = new char[length]; string.getChars( 0, length, characters, 0 ); for ( final char character : characters ) { final String replace = NON_DIACRITICS.get( character ); final String toReplace = replace == null ? String.valueOf( character ) : replace; stringBuilder.append( toReplace ); } final String normalized = Normalizer.normalize( stringBuilder, Normalizer.Form.NFD ); final String diacriticsCleaned = DIACRITICS.matcher( normalized ).replaceAll( DEFAULT_REPLACE ); final String nonAsciiCleaned = diacriticsCleaned.replaceAll( NOT_ASCII, DEFAULT_REPLACE ); final String lowerCase = nonAsciiCleaned.toLowerCase(); return lowerCase; } }