Initial import
[SaveMySugar/android-savemysugar.git] / src / main / java / it / ao2 / savemysugar / morse / MorseTranslator.java
1 /*
2  * Morse Code Translator Java class
3  *
4  * Copyright (C) 2015  Antonio Ospite <ao2@ao2.it>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * ---------------------------------------------------------------------------
20  *
21  * The code was initially based on:
22  *
23  *   - Morse.java by Stephen C Phillips:
24  *     http://morsecode.scphillips.com/Morse.java
25  *     Copyright (C) 1999-2004  Stephen C Phillips <steve@scphillips.com>
26  *
27  *   - NMorse.java by Michael R Ditto:
28  *     http://www.omnicron.com/~ford/java/NMorse.java
29  *     Copyright (C) 2001  Michael R Ditto <ford@omnicron.com>
30  *
31  * ---------------------------------------------------------------------------
32  *
33  * The specification of the International Morse Code is in ITU-R M.1677-1
34  * (10/2009), Annex 1.
35  *
36  * The terminology used here may differ from the one used in some other
37  * places, so here is some nomenclature:
38  *
39  *     symbol: one of . (dot), - (dash), ' ' (signal separator),
40  *         '/' (word separator)
41  *
42  *     character: a letter of the alphabet, a number, a punctuation mark, or
43  *         a ' ' (text word separator)
44  *
45  *     signal: a sequence of . and - symbols which encode a character,
46  *         or a '/' (Morse word separator)
47  *
48  *     word: a sequence of characters not containing a ' ', or
49  *         a sequence of signals not containing a '/'
50  *
51  *     text: a sequence of characters
52  *
53  *     morse: a sequence of signals separated by ' '
54  *
55  * NOTE:
56  * signals are separated by a ' ' (signal separator), characters are not
57  * separated one from the other.
58  *
59  * This class defines a subset of the signals in Section 1 of the
60  * aforementioned specification, plus a word space, and it does not make
61  * assumptions about their actual transmission.
62  */
63
64 package it.ao2.util.morse;
65
66 import java.util.Arrays;
67 import java.util.Enumeration;
68 import java.util.Hashtable;
69 import java.util.Iterator;
70 import java.util.Locale;
71
72 public class MorseTranslator {
73     private Hashtable<Character, String> mSignalsTable;
74     private Hashtable<String, Character> mCharactersTable;
75
76     public MorseTranslator() {
77         mSignalsTable = new Hashtable<Character, String>();
78
79         // Letters
80         mSignalsTable.put(Character.valueOf('a'), ".-");
81         mSignalsTable.put(Character.valueOf('b'), "-...");
82         mSignalsTable.put(Character.valueOf('c'), "-.-.");
83         mSignalsTable.put(Character.valueOf('d'), "-..");
84         mSignalsTable.put(Character.valueOf('e'), ".");
85         mSignalsTable.put(Character.valueOf('f'), "..-.");
86         mSignalsTable.put(Character.valueOf('g'), "--.");
87         mSignalsTable.put(Character.valueOf('h'), "....");
88         mSignalsTable.put(Character.valueOf('i'), "..");
89         mSignalsTable.put(Character.valueOf('j'), ".---");
90         mSignalsTable.put(Character.valueOf('k'), "-.-");
91         mSignalsTable.put(Character.valueOf('l'), ".-..");
92         mSignalsTable.put(Character.valueOf('m'), "--");
93         mSignalsTable.put(Character.valueOf('n'), "-.");
94         mSignalsTable.put(Character.valueOf('o'), "---");
95         mSignalsTable.put(Character.valueOf('p'), ".--.");
96         mSignalsTable.put(Character.valueOf('q'), "--.-");
97         mSignalsTable.put(Character.valueOf('r'), ".-.");
98         mSignalsTable.put(Character.valueOf('s'), "...");
99         mSignalsTable.put(Character.valueOf('t'), "-");
100         mSignalsTable.put(Character.valueOf('u'), "..-");
101         mSignalsTable.put(Character.valueOf('v'), "...-");
102         mSignalsTable.put(Character.valueOf('w'), ".--");
103         mSignalsTable.put(Character.valueOf('x'), "-..-");
104         mSignalsTable.put(Character.valueOf('y'), "-.--");
105         mSignalsTable.put(Character.valueOf('z'), "--..");
106         // Figures
107         mSignalsTable.put(Character.valueOf('1'), ".----");
108         mSignalsTable.put(Character.valueOf('2'), "..---");
109         mSignalsTable.put(Character.valueOf('3'), "...--");
110         mSignalsTable.put(Character.valueOf('4'), "....-");
111         mSignalsTable.put(Character.valueOf('5'), ".....");
112         mSignalsTable.put(Character.valueOf('6'), "-....");
113         mSignalsTable.put(Character.valueOf('7'), "--...");
114         mSignalsTable.put(Character.valueOf('8'), "---..");
115         mSignalsTable.put(Character.valueOf('9'), "----.");
116         mSignalsTable.put(Character.valueOf('0'), "-----");
117         // Punctuation marks and miscellaneous signs
118         mSignalsTable.put(Character.valueOf('.'), ".-.-.-");
119         mSignalsTable.put(Character.valueOf(','), "--..--");
120         mSignalsTable.put(Character.valueOf(':'), "---...");
121         mSignalsTable.put(Character.valueOf('?'), "..--..");
122         mSignalsTable.put(Character.valueOf('\''), ".----.");
123         mSignalsTable.put(Character.valueOf('-'), "-....-");
124         mSignalsTable.put(Character.valueOf('/'), "-..-.");
125         mSignalsTable.put(Character.valueOf('('), "-.--.-");
126         mSignalsTable.put(Character.valueOf(')'), "-.--.-");
127         mSignalsTable.put(Character.valueOf('"'), ".-..-.");
128         mSignalsTable.put(Character.valueOf('='), "-...-");
129         mSignalsTable.put(Character.valueOf('+'), ".-.-.");
130         mSignalsTable.put(Character.valueOf('x'), "-..-");
131         mSignalsTable.put(Character.valueOf('@'), ".--.-.");
132
133         // Represent the word space as a signal with only one "/" symbol
134         mSignalsTable.put(Character.valueOf(' '), "/");
135
136         mCharactersTable = new Hashtable<String, Character>();
137
138         Enumeration<Character> list = mSignalsTable.keys();
139         while (list.hasMoreElements()) {
140             Character c = list.nextElement();
141             String s = mSignalsTable.get(c);
142             mCharactersTable.put(s, c);
143         }
144     }
145
146     public String sanitizeText(String text) {
147         String sanitizedText;
148
149         sanitizedText = text.toLowerCase(Locale.US);
150         sanitizedText = sanitizedText.replaceAll("[^a-z0-9.,:?\'/()\"=+;_$@ -]", "");
151         sanitizedText = sanitizedText.replaceAll("\\s+", " ");
152         return sanitizedText;
153     }
154
155     public String charToSignal(Character character) {
156         character = Character.toLowerCase(character);
157
158         if (mSignalsTable.containsKey(character)) {
159             return mSignalsTable.get(character);
160         } else {
161             return "";
162         }
163     }
164
165     public String textToMorse(String text, boolean sanitize) {
166         if (sanitize) {
167             text = sanitizeText(text);
168         }
169
170         StringBuffer morse = new StringBuffer();
171         for (int i = 0; i < text.length(); i++) {
172             //Character ch = Character.valueOf(text.charAt(i));
173             Character character = text.charAt(i);
174
175             morse.append(charToSignal(character));
176
177             if (i < text.length() - 1) {
178                 morse.append(" ");
179             }
180         }
181
182         return morse.toString();
183     }
184
185     public String textToMorse(String text) {
186         return textToMorse(text, true);
187     }
188
189     public String sanitizeMorse(String morse) {
190         String sanitizedMorse;
191
192         sanitizedMorse = morse.replaceAll("_", "-");
193         sanitizedMorse = sanitizedMorse.replaceAll("[^\\-\\.\\/]", " ");
194         sanitizedMorse = sanitizedMorse.replaceAll("\\s+", " ");
195         sanitizedMorse = sanitizedMorse.replaceAll("( ?/ ?)+", " / ");
196         return sanitizedMorse;
197     }
198
199     public Character signalToCharacter(String signal) {
200         if (mCharactersTable.containsKey(signal)) {
201             return mCharactersTable.get(signal);
202         } else {
203             return '*';
204         }
205     }
206
207     public String morseToText(String morse, boolean sanitize) {
208         if (sanitize) {
209             morse = sanitizeMorse(morse);
210         }
211
212         StringBuffer text = new StringBuffer();
213         Iterator<String> signals = Arrays.asList(morse.split(" ")).iterator();
214         while (signals.hasNext()) {
215             String signal = signals.next();
216             text.append(signalToCharacter(signal));
217         }
218
219         return text.toString();
220     }
221
222     public String morseToText(String morse) {
223         return morseToText(morse, true);
224     }
225 }