@@ -16,23 +16,21 @@ class NaturalPersonTenDigitsCodeCalculator {
16
16
private final NaturalPerson person ;
17
17
18
18
private static final String [] SPECIAL_PARTICLES =
19
- {"DE" , "LA" , "LAS" , "MC" , "VON" , "DEL" , "LOS" , "Y" , "MAC" , "VAN" , "MI" };
20
-
21
- private static final String [] FORBIDDEN_WORDS = { "BUEI" , "BUEY" , "CACA" , "CACO" , "CAGA" , "CAGO" , "CAKA" , "CAKO" , "COGE" , "COJA" , "COJE" , "COJI" , "COJO" , "CULO" , "FETO" , "GUEY" , "JOTO" , "KACA" , "KACO" , "KAGA" , "KAGO" , "KOGE" , "KOJO" , "KAKA" , "KULO" , "MAME" , "MAMO" , "MEAR" , "MEAS" , "MEON" , "MION" , "MOCO" , "MULA" , "PEDA" , "PEDO" , "PENE" , "PUTA" , "PUTO" , "QULO" , "RATA" , "RUIN" };
19
+ {"DAS" , "DA" , "DEL" , "DER" , "DE" , "DIE" , "DI" , "DD" , "EL" , "LES" , "LA" , "LOS" , "LAS" , "LES" , "LE" , "MAC" , "MC" , "VAN" , "VON" , "Y" };
22
20
21
+ private static final String [] FORBIDDEN_WORDS = {"BACA" , "BAKA" , "BUEI" , "BUEY" , "CACA" , "CACO" , "CAGA" , "CAGO" , "CAKA" , "CAKO" , "COGE" , "COGI" , "COJA" , "COJE" , "COJI" , "COJO" , "COLA" , "CULO" , "FALO" , "FETO" , "GETA" , "GUEI" , "GUEY" , "JETA" , "JOTO" , "KACA" , "KACO" , "KAGA" , "KAGO" , "KAKA" , "KAKO" , "KOGE" , "KOGI" , "KOJA" , "KOJE" , "KOJI" , "KOJO" , "KOLA" , "KULO" , "LILO" , "LOCA" , "LOCO" , "LOKA" , "LOKO" , "MAME" , "MAMO" , "MEAR" , "MEAS" , "MEON" , "MIAR" , "MION" , "MOCO" , "MOKO" , "MULA" , "MULO" , "NACA" , "NACO" , "PEDA" , "PEDO" , "PENE" , "PIPI" , "PITO" , "POPO" , "PUTA" , "PUTO" , "QULO" , "RATA" , "ROBA" , "ROBE" , "ROBO" , "RUIN" , "SENO" , "TETA" , "VACA" , "VAGA" , "VAGO" , "VAKA" , "VUEI" , "VUEY" , "WUEI" , "WUEY" };
23
22
24
23
NaturalPersonTenDigitsCodeCalculator (NaturalPerson person ) {
25
-
26
24
this .person = person ;
27
25
}
28
26
29
27
public String calculate () {
30
-
31
- return obfuscateForbiddenWords (nameCode ()) + birthdayCode ();
28
+ String a = nameCode ();
29
+ String b = StringUtils .stripAccents (a );
30
+ return obfuscateForbiddenWords (b ) + birthdayCode ();
32
31
}
33
32
34
33
private String obfuscateForbiddenWords (String nameCode ) {
35
-
36
34
for (String forbidden : FORBIDDEN_WORDS ) {
37
35
if (forbidden .equals (nameCode )) {
38
36
return nameCode .substring (0 , 3 ) + "X" ;
@@ -42,7 +40,6 @@ private String obfuscateForbiddenWords(String nameCode) {
42
40
}
43
41
44
42
private String nameCode () {
45
-
46
43
if (isFirstLastNameEmpty ()) {
47
44
return firstLastNameEmptyForm ();
48
45
} else if (isSecondLastNameEmpty ()) {
@@ -55,114 +52,108 @@ private String nameCode() {
55
52
}
56
53
57
54
private String secondLastNameEmptyForm () {
58
-
59
55
return firstTwoLettersOf (person .firstLastName )
60
56
+ firstTwoLettersOf (filterName (person .name ));
61
57
}
62
58
63
59
private String birthdayCode () {
64
-
65
60
return lastTwoDigitsOf (person .year )
66
61
+ formattedInTwoDigits (person .month )
67
62
+ formattedInTwoDigits (person .day );
68
63
}
69
64
70
65
private boolean isSecondLastNameEmpty () {
71
-
72
66
return StringUtils .isEmpty (normalize (person .secondLastName ));
73
67
}
74
68
75
69
private String firstLastNameEmptyForm () {
76
-
77
70
return firstTwoLettersOf (person .secondLastName )
78
71
+ firstTwoLettersOf (filterName (person .name ));
79
72
}
80
73
81
74
private boolean isFirstLastNameEmpty () {
82
-
83
75
return StringUtils .isEmpty (normalize (person .firstLastName ));
84
76
}
85
77
86
78
private String firstLastNameTooShortForm () {
87
-
88
79
return firstLetterOf (person .firstLastName )
89
80
+ firstLetterOf (person .secondLastName )
90
81
+ firstTwoLettersOf (filterName (person .name ));
91
82
}
92
83
93
84
private String firstTwoLettersOf (String word ) {
94
-
95
- String normalizedWord = normalize (word );
96
- return normalizedWord .substring (0 , 2 );
85
+ String normalizedWord = normalize (word ).replace (" " , "" );
86
+ return normalizedWord .length () > 1 ? normalizedWord .substring (0 , 2 ) : normalizedWord .concat ("X" );
97
87
}
98
88
99
89
private boolean isFirstLastNameIsTooShort () {
100
-
101
90
return normalize (person .firstLastName ).length () <= 2 ;
102
91
}
103
92
104
93
private String normalForm () {
105
-
106
94
return firstLetterOf (person .firstLastName )
107
95
+ firstVowelExcludingFirstCharacterOf (person .firstLastName )
108
96
+ firstLetterOf (person .secondLastName )
109
97
+ firstLetterOf (filterName (person .name ));
110
98
}
111
99
112
100
private String filterName (String name ) {
113
-
114
- return normalize (name )
115
- .trim ()
116
- .replaceFirst ("^(MA|MA.|MARIA|JOSE)\\ s+" , "" );
101
+ return normalize (name ).trim ()
102
+ .replaceFirst ("^(MARIA|MA\\ .|MA|M\\ .|M|JOSE|J|J\\ .|DA|DAS|DE|DEL|DER|DI|DIE|DD|EL|LA|LAS|LOS|LE|LES|MAC|MC|VAN|VON|Y)\\ s+" , "" );
117
103
}
118
104
119
105
private String formattedInTwoDigits (int number ) {
120
-
121
106
return String .format (Locale .getDefault (), "%02d" , number );
122
107
}
123
108
124
109
private String lastTwoDigitsOf (int number ) {
125
-
126
110
return formattedInTwoDigits (number % 100 );
127
111
}
128
112
129
113
private String firstLetterOf (String word ) {
130
-
131
114
String normalizedWord = normalize (word );
132
115
return String .valueOf (normalizedWord .charAt (0 ));
133
116
}
134
117
135
118
private String normalize (String word ) {
136
-
137
- if (StringUtils .isEmpty (word )) {
119
+ if (StringUtils .isEmpty (word ))
138
120
return word ;
139
- } else {
140
- String normalizedWord = StringUtils .stripAccents (word ).toUpperCase ();
141
- return removeSpecialParticles (normalizedWord , SPECIAL_PARTICLES );
121
+
122
+ String cleanedWord = word .replaceAll ("[\\ -.',´`’\\ \\ /]" , "" );
123
+ if (StringUtils .isEmpty (cleanedWord )) {
124
+ return cleanedWord ;
142
125
}
143
- }
144
126
145
- private String removeSpecialParticles ( String word , String [] specialParticles ) {
127
+ String normalizedWord = stripAccentsExcludingNTilde ( cleanedWord );
146
128
147
- StringBuilder newWord = new StringBuilder (word );
148
- for (String particle : specialParticles ) {
149
- String [] particlePositions = {particle + " " , " " + particle };
150
- for (String p : particlePositions )
151
- while (newWord .toString ().contains (p )) {
152
- int i = newWord .toString ().indexOf (p );
153
- newWord .delete (i , i + p .length ());
154
- }
155
- }
156
- return newWord .toString ();
129
+ return removeSpecialParticles (normalizedWord );
157
130
}
158
131
159
- private String firstVowelExcludingFirstCharacterOf (String word ) {
132
+ private String removeSpecialParticles (String word ) {
133
+ String particlesRegex = String .join ("|" , SPECIAL_PARTICLES ); // convert the array to a regex OR sequence
134
+ Pattern pattern = Pattern .compile ("\\ b(" + particlesRegex + ")\\ b" , Pattern .CASE_INSENSITIVE ); // match the particles only if they are whole words
135
+ Matcher matcher = pattern .matcher (word );
136
+ String result = matcher .replaceAll (" " ); // replace all special particles with space
137
+ return result .trim (); // remove any leading and trailing spaces
138
+ }
160
139
140
+ private String firstVowelExcludingFirstCharacterOf (String word ) {
161
141
String normalizedWord = normalize (word ).substring (1 );
162
142
Matcher m = VOWEL_PATTERN .matcher (normalizedWord );
163
143
if (!m .find ()) {
164
144
return "X" ;
165
145
}
166
146
return String .valueOf (normalizedWord .charAt (m .start ()));
167
147
}
148
+
149
+ private String stripAccentsExcludingNTilde (String input ) {
150
+ if (StringUtils .isEmpty (input ))
151
+ return input ;
152
+
153
+ input = input .toUpperCase ();
154
+ input = input .replace ("Ñ" , "$" );
155
+ input = StringUtils .stripAccents (input );
156
+ input = input .replace ("$" , "Ñ" );
157
+ return input .replaceAll ("[^A-Z0-9&Ñ ]" , "" );
158
+ }
168
159
}
0 commit comments