Find and print results

Julien LepillerSun Apr 14 11:25:44+0200 2019

82b137f

Find and print results

app/src/main/java/eu/lepiller/nani/MainActivity.java

22
33
import android.content.Intent;
44
import android.os.Bundle;
5-
import android.support.design.widget.FloatingActionButton;
6-
import android.support.design.widget.Snackbar;
75
import android.support.v7.app.AppCompatActivity;
86
import android.support.v7.widget.Toolbar;
97
import android.view.View;

119
import android.view.MenuItem;
1210
import android.widget.Button;
1311
import android.widget.EditText;
14-
import android.widget.ListView;
12+
import android.widget.LinearLayout;
13+
import android.widget.TextView;
1514
1615
import java.util.ArrayList;
1716
1817
import eu.lepiller.nani.dictionary.DictionaryFactory;
1918
import eu.lepiller.nani.result.Result;
20-
import eu.lepiller.nani.result.ResultAdapter;
2119
2220
public class MainActivity extends AppCompatActivity {
2321

2826
        Toolbar toolbar = findViewById(R.id.toolbar);
2927
        setSupportActionBar(toolbar);
3028
31-
        final Button search_button = (Button) findViewById(R.id.search_button);
32-
        final EditText search_form = (EditText) findViewById(R.id.search_form);
33-
        final ListView result_view = (ListView) findViewById(R.id.results_view);
29+
        final Button search_button = findViewById(R.id.search_button);
30+
        final EditText search_form = findViewById(R.id.search_form);
31+
        final LinearLayout result_view = findViewById(R.id.results_view);
3432
3533
        search_button.setOnClickListener(new View.OnClickListener() {
3634
            @Override
3735
            public void onClick(View v) {
3836
                String text = search_form.getText().toString();
3937
                ArrayList<Result> searchResult = DictionaryFactory.search(getApplicationContext(), text);
40-
                result_view.setAdapter(new ResultAdapter(getApplicationContext(), searchResult));
38+
39+
                result_view.removeAllViews();
40+
                int num = 0;
41+
                for(Result result: searchResult) {
42+
                    num++;
43+
                    if (num > 10)
44+
                        break;
45+
                    View child_result = getLayoutInflater().inflate(R.layout.layout_result, result_view, false);
46+
47+
                    TextView kanji_view = child_result.findViewById(R.id.kanji_view);
48+
                    LinearLayout senses_view = child_result.findViewById(R.id.sense_view);
49+
                    TextView additional_info = child_result.findViewById(R.id.additional_info_view);
50+
51+
                    // Populate the data into the template view using the data object
52+
                    kanji_view.setText(result.getKanji());
53+
54+
                    StringBuilder additional = new StringBuilder();
55+
                    boolean separator = false;
56+
                    for(String s: result.getAlternatives()) {
57+
                        if(separator)
58+
                            additional.append(getResources().getString(R.string.sense_separator));
59+
                        else
60+
                            separator = true;
61+
                        additional.append(s);
62+
                    }
63+
                    additional_info.setText(String.format(getResources().getString(R.string.sense_alternatives), additional.toString()));
64+
65+
                    senses_view.removeAllViews();
66+
67+
                    int sense_pos = 1;
68+
                    for(Result.Sense sense: result.getSenses()) {
69+
                        View child = getLayoutInflater().inflate(R.layout.layout_sense, senses_view, false);
70+
                        TextView id_view = child.findViewById(R.id.id_view);
71+
                        TextView sense_view = child.findViewById(R.id.definition_view);
72+
73+
                        id_view.setText(String.format(getResources().getString(R.string.sense_number), sense_pos));
74+
75+
                        StringBuilder sb = new StringBuilder();
76+
                        boolean separator1 = false;
77+
                        for(String s: sense.getGlosses()) {
78+
                            if(separator1)
79+
                                sb.append(getResources().getString(R.string.sense_separator));
80+
                            else
81+
                                separator1 = true;
82+
                            sb.append(s);
83+
                        }
84+
                        sense_view.setText(sb.toString());
85+
86+
                        senses_view.addView(child);
87+
                        sense_pos++;
88+
                    }
89+
90+
                    result_view.addView(child_result);
91+
                }
4192
            }
4293
        });
4394
    }

app/src/main/java/eu/lepiller/nani/dictionary/DictionaryFactory.java

1414
    private DictionaryFactory(Context context) {
1515
        dictionaries = new ArrayList<>();
1616
        dictionaries.add(new JMDict("example_jmdict",
17-
                context.getString(R.string.dico_example),
17+
                context.getString(R.string.dico_jmdict_example),
1818
                context.getCacheDir(),
19-
                "https://xana.lepiller.eu/nani/dico/example_jmdict"));
20-
21-
        dictionaries.add(new JMDict("example_jmdict",
22-
                context.getString(R.string.dico_example),
23-
                context.getCacheDir(),
24-
                "https://xana.lepiller.eu/nani/dico/example_jmdict"));
25-
26-
        dictionaries.add(new JMDict("example_jmdict",
27-
                context.getString(R.string.dico_example),
19+
                "https://xana.lepiller.eu/nani/dico/example.nani"));
20+
        dictionaries.add(new JMDict("JMdict_e",
21+
                context.getString(R.string.dico_jmdict_e),
2822
                context.getCacheDir(),
29-
                "https://xana.lepiller.eu/nani/dico/example_jmdict"));
23+
                "https://xana.lepiller.eu/nani/dico/JMdict_e.nani"));
3024
    }
3125
3226
    public static ArrayList<Result> search(Context context, String text) {

3630
        ArrayList<Result> results = new ArrayList<>();
3731
        for(Dictionary d: dictionaries) {
3832
            if (d instanceof JMDict) {
39-
                results.addAll(d.search(text));
33+
                ArrayList<Result> dr = ((JMDict) d).search(text);
34+
                if(dr != null)
35+
                    results.addAll(dr);
4036
            }
4137
        }
4238
        return results;

app/src/main/java/eu/lepiller/nani/dictionary/JMDict.java

11
package eu.lepiller.nani.dictionary;
22
3+
import android.support.annotation.RequiresPermission;
4+
import android.util.Log;
5+
36
import java.io.File;
4-
import java.io.FileInputStream;
57
import java.io.FileNotFoundException;
6-
import java.io.InputStream;
8+
import java.io.FileReader;
9+
import java.io.IOException;
10+
import java.io.RandomAccessFile;
711
import java.net.MalformedURLException;
812
import java.net.URL;
13+
import java.nio.charset.StandardCharsets;
914
import java.util.ArrayList;
15+
import java.util.Arrays;
1016
import java.util.HashMap;
1117
import java.util.Map;
1218

1420
import eu.lepiller.nani.result.Result;
1521
1622
public class JMDict extends Dictionary {
23+
    final static String TAG = "JMDICT";
1724
    private String mUrl;
1825
1926
    JMDict(String name, String description, File cacheDir, String url) {

5966
        file.delete();
6067
    }
6168
62-
    public ArrayList<Result> search(String text) {
63-
        ArrayList<Result> results = new ArrayList<>();
69+
    private ArrayList<String> getStringList(RandomAccessFile file) throws IOException {
70+
        ArrayList<String> results = new ArrayList<>();
71+
        int number = file.readInt();
72+
        for(int i=0; i<number; i++) {
73+
            int l = file.readInt();
74+
            byte[] str = new byte[l];
75+
            file.read(str);
76+
            results.add(new String(str, "UTF-8"));
77+
        }
78+
        return results;
79+
    }
80+
81+
    private String getString(RandomAccessFile file) throws IOException {
82+
        int l = file.readInt();
83+
        byte[] str = new byte[l];
84+
        file.read(str);
85+
        return new String(str, "UTF-8");
86+
    }
87+
88+
    private Result getValue(RandomAccessFile file, long pos) throws IOException {
89+
        file.seek(pos);
90+
        ArrayList<String> kanjis = getStringList(file);
91+
92+
        ArrayList<Result.Reading> readings = new ArrayList<>();
93+
        int reading_number = file.readInt();
94+
        for(int i=0; i<reading_number; i++) {
95+
            ArrayList<String> reading_kanjis = getStringList(file);
96+
            ArrayList<String> reading_infos = getStringList(file);
97+
            ArrayList<String> reading_readings = getStringList(file);
98+
            Result.Reading r = new Result.Reading(reading_kanjis, reading_infos, reading_readings);
99+
            readings.add(r);
100+
        }
101+
102+
        ArrayList<Result.Sense> senses = new ArrayList<>();
103+
        int meaning_number = file.readInt();
104+
        for(int i=0; i<meaning_number; i++) {
105+
            ArrayList<String> sense_references = getStringList(file);
106+
            ArrayList<String> sense_limits = getStringList(file);
107+
            ArrayList<String> sense_infos = getStringList(file);
108+
            ArrayList<Result.Source> sense_sources = new ArrayList<>();
109+
            int source_number = file.readInt();
110+
            for(int j=0; j<source_number; j++) {
111+
                ArrayList<String> source_content = getStringList(file);
112+
                boolean source_wasei = file.read() != 0;
113+
                String source_type = getString(file);
114+
                String source_language = getString(file);
115+
                sense_sources.add(new Result.Source(source_content, source_wasei, source_type, source_language));
116+
            }
117+
            ArrayList<String> sense_tags = getStringList(file);
118+
            ArrayList<String> sense_glosses = getStringList(file);
119+
            String sense_language = getString(file);
120+
            senses.add(new Result.Sense(sense_references, sense_limits, sense_infos, sense_sources,
121+
                    sense_tags, sense_glosses, sense_language));
122+
        }
123+
        return new Result(kanjis, readings, senses);
124+
    }
125+
126+
    private ArrayList<Integer> getValues(RandomAccessFile file, long triePos) throws IOException {
127+
        file.seek(triePos);
128+
        Log.d(TAG, "Getting value");
129+
        int valuesLength = file.readInt();
130+
        ArrayList<Integer> results = new ArrayList<>();
131+
132+
        Log.d(TAG, "Number of values: " + valuesLength);
133+
        for(int i=0; i<valuesLength; i++) {
134+
            results.add(file.readInt());
135+
        }
136+
137+
        int transitionLength = file.readInt();
138+
        Log.d(TAG, "Number of transitions: " + transitionLength);
139+
        int[] others = new int[transitionLength];
140+
        for(int i=0; i<transitionLength; i++) {
141+
            file.skipBytes(1);
142+
            others[i] = file.readInt();
143+
        }
144+
145+
        for(int i=0; i<transitionLength; i++) {
146+
            results.addAll(getValues(file, others[i]));
147+
        }
148+
149+
        Log.d(TAG, "result size: " + results.size());
150+
        return results;
151+
    }
152+
153+
    private ArrayList<Integer> searchTrie(RandomAccessFile file, long triePos, byte[] txt) throws IOException {
154+
        Log.d(TAG, "searchTrie: " + triePos);
155+
        Log.d(TAG, "Remaining transitions: " + new String(txt, "UTF-8"));
156+
        file.seek(triePos);
157+
        Log.d(TAG, "pointer: " + file.getFilePointer());
158+
        if(txt.length == 0) {
159+
            return getValues(file, triePos);
160+
        } else {
161+
            int valuesLength = file.readInt();
162+
            Log.d(TAG, "number of values: " + valuesLength);
163+
            /*for(int i=0; i<valuesLength; i++) {
164+
                int strLen = file.readInt();
165+
                byte[] s = new byte[strLen];
166+
                file.read(s);
167+
                //Log.d(TAG, "Value of size " + strLen + ": " + new String(s, "UTF-8"));
168+
                file.skipBytes(strLen*4);
169+
            }*/
170+
            file.skipBytes(valuesLength * 4);
171+
172+
            int transitionLength = file.readInt();
173+
            Log.d(TAG, "number of transitions: " + transitionLength);
174+
175+
            for(int i = 0; i < transitionLength; i++) {
176+
                byte letter = file.readByte();
177+
                Log.d(TAG, "Possible transition " + letter + "; Expected transition: " + txt[0]);
178+
                if(letter == txt[0]) {
179+
                    Log.d(TAG, "Taking transition "+letter);
180+
                    byte[] ntxt = new byte[txt.length-1];
181+
                    System.arraycopy(txt, 1, ntxt, 0, txt.length-1);
182+
                    return searchTrie(file, file.readInt(), ntxt);
183+
                } else {
184+
                    file.skipBytes(4);
185+
                }
186+
            }
187+
188+
            return null;
189+
        }
190+
    }
191+
192+
    ArrayList<Result> search(String text) {
64193
        if (isDownloaded()) {
65-
            // Actually read the file and find something
66194
            try {
67-
                InputStream is = new FileInputStream(getFile());
68-
            } catch (FileNotFoundException ignored) {
195+
                RandomAccessFile file = new RandomAccessFile(getFile(), "r");
196+
                byte[] header = new byte[14];
197+
                int l = file.read(header);
198+
                if (l != header.length)
199+
                    return null;
200+
201+
                // Check file format version
202+
                if(!Arrays.equals(header, "NANI_JMDICT001".getBytes()))
203+
                    return null;
204+
205+
                byte[] search = text.getBytes();
206+
207+
                long kanjiTriePos = file.readInt();
208+
                long readingTriePos = file.readInt();
209+
                long meaningTriePos = file.readInt();
210+
211+
                Log.d(TAG, "Search in: " + getFile());
212+
                Log.d(TAG, "kanji: " + kanjiTriePos);
213+
                Log.d(TAG, "reading: " + readingTriePos);
214+
                Log.d(TAG, "meaning: " + meaningTriePos);
215+
216+
                ArrayList<Integer> results = searchTrie(file, kanjiTriePos, search);
217+
                if(results == null || results.isEmpty())
218+
                    results = searchTrie(file, readingTriePos, search);
219+
                if(results == null || results.isEmpty())
220+
                    results = searchTrie(file, meaningTriePos, search);
221+
222+
                if(results == null || results.isEmpty())
223+
                    return null;
224+
225+
                ArrayList<Result> r = new ArrayList<>();
226+
                ArrayList<Integer> uniqResults = new ArrayList<>();
227+
                for(Integer i: results) {
228+
                    if(!uniqResults.contains(i))
229+
                        uniqResults.add(i);
230+
                }
231+
232+
                for(Integer i: uniqResults) {
233+
                    r.add(getValue(file, i));
234+
                }
235+
                return r;
236+
            } catch (FileNotFoundException e) {
237+
                e.printStackTrace();
238+
            } catch (IOException e) {
239+
                e.printStackTrace();
69240
            }
70241
        }
71-
        return results;
242+
        return null;
72243
    }
73244
}

app/src/main/java/eu/lepiller/nani/result/Result.java

11
package eu.lepiller.nani.result;
22
3-
import java.lang.reflect.Array;
43
import java.util.ArrayList;
54
65
public class Result {
7-
    enum Tag {
8-
        // Obtained by:
9-
        //   cat entities | cut -c 10- | sed -e 's|">$||' -e 's| "|, // |' -e 's|^\([^,]\)|\U\1|'
10-
        // and modifing things a bit ;)
11-
        MA, // martial arts term
12-
        X, // rude or X-rated term (not displayed in educational software)
13-
        Abbr, // abbreviation
14-
        Adj_i, // adjective (keiyoushi)
15-
        Adj_ix, // adjective (keiyoushi) - yoi/ii class
16-
        Adj_na, // adjectival nouns or quasi-adjectives (keiyodoshi)
17-
        Adj_no, // nouns which may take the genitive case particle `no'
18-
        Adj_pn, // pre-noun adjectival (rentaishi)
19-
        Adj_t, // `taru' adjective
20-
        Adj_1f, // noun or verb acting prenominally
21-
        Adv, // adverb (fukushi)
22-
        Adv_to, // adverb taking the `to' particle
23-
        Arch, // archaism
24-
        Ateji, // ateji (phonetic) reading
25-
        Aux, // auxiliary
26-
        Aux_v, // auxiliary verb
27-
        Aux_adj, // auxiliary adjective
28-
        Buddh, // Buddhist term
29-
        Chem, // chemistry term
30-
        Chn, // children's language
31-
        Col, // colloquialism
32-
        Comp, // computer terminology
33-
        Conj, // conjunction
34-
        Cop_da, // copula
35-
        Ctr, // counter
36-
        Derog, // derogatory
37-
        EK, // exclusively kanji
38-
        Ek, // exclusively kana
39-
        Exp, // expressions (phrases, clauses, etc.)
40-
        Fam, // familiar language
41-
        Fem, // female term or language
42-
        Food, // food term
43-
        Geom, // geometry term
44-
        Gikun, // gikun (meaning as reading) or jukujikun (special kanji reading)
45-
        Hon, // honorific or respectful (sonkeigo) language
46-
        Hum, // humble (kenjougo) language
47-
        IK, // word containing irregular kanji usage
48-
        Id, // idiomatic expression
49-
        Ik, // word containing irregular kana usage
50-
        Int, // interjection (kandoushi)
51-
        Io, // irregular okurigana usage
52-
        Iv, // irregular verb
53-
        Ling, // linguistics terminology
54-
        M_sl, // manga slang
55-
        Male, // male term or language
56-
        Male_sl, // male slang
57-
        Math, // mathematics
58-
        Mil, // military
59-
        N, // noun (common) (futsuumeishi)
60-
        N_adv, // adverbial noun (fukushitekimeishi)
61-
        N_suf, // noun, used as a suffix
62-
        N_pref, // noun, used as a prefix
63-
        N_t, // noun (temporal) (jisoumeishi)
64-
        Num, // numeric
65-
        OK, // word containing out-dated kanji
66-
        Obs, // obsolete term
67-
        Obsc, // obscure term
68-
        Ok, // out-dated or obsolete kana usage
69-
        Oik, // old or irregular kana form
70-
        On_mim, // onomatopoeic or mimetic word
71-
        Pn, // pronoun
72-
        Poet, // poetical term
73-
        Pol, // polite (teineigo) language
74-
        Pref, // prefix
75-
        Proverb, // proverb
76-
        Prt, // particle
77-
        Physics, // physics terminology
78-
        Quote, // quotation
79-
        Rare, // rare
80-
        Sens, // sensitive
81-
        Sl, // slang
82-
        Suf, // suffix
83-
        UK, // word usually written using kanji alone
84-
        Uk, // word usually written using kana alone
85-
        Unc, // unclassified
86-
        Yoji, // yojijukugo
87-
        V1, // Ichidan verb
88-
        V1_s, // Ichidan verb - kureru special class
89-
        V2a_s, // Nidan verb with 'u' ending (archaic)
90-
        V4h, // Yodan verb with `hu/fu' ending (archaic)
91-
        V4r, // Yodan verb with `ru' ending (archaic)
92-
        V5aru, // Godan verb - -aru special class
93-
        V5b, // Godan verb with `bu' ending
94-
        V5g, // Godan verb with `gu' ending
95-
        V5k, // Godan verb with `ku' ending
96-
        V5k_s, // Godan verb - Iku/Yuku special class
97-
        V5m, // Godan verb with `mu' ending
98-
        V5n, // Godan verb with `nu' ending
99-
        V5r, // Godan verb with `ru' ending
100-
        V5r_i, // Godan verb with `ru' ending (irregular verb)
101-
        V5s, // Godan verb with `su' ending
102-
        V5t, // Godan verb with `tsu' ending
103-
        V5u, // Godan verb with `u' ending
104-
        V5u_s, // Godan verb with `u' ending (special class)
105-
        V5uru, // Godan verb - Uru old class verb (old form of Eru)
106-
        Vz, // Ichidan verb - zuru verb (alternative form of -jiru verbs)
107-
        Vi, // intransitive verb
108-
        Vk, // Kuru verb - special class
109-
        Vn, // irregular nu verb
110-
        Vr, // irregular ru verb, plain form ends with -ri
111-
        Vs, // noun or participle which takes the aux. verb suru
112-
        Vs_c, // su verb - precursor to the modern suru
113-
        Vs_s, // suru verb - special class
114-
        Vs_i, // suru verb - included
115-
        Kyb, // Kyoto-ben
116-
        Osb, // Osaka-ben
117-
        Ksb, // Kansai-ben
118-
        Ktb, // Kantou-ben
119-
        Tsb, // Tosa-ben
120-
        Thb, // Touhoku-ben
121-
        Tsug, // Tsugaru-ben
122-
        Kyu, // Kyuushuu-ben
123-
        Rkb, // Ryuukyuu-ben
124-
        Nab, // Nagano-ben
125-
        Hob, // Hokkaido-ben
126-
        Vt, // transitive verb
127-
        Vulg, // vulgar expression or word
128-
        Adj_kari, // `kari' adjective (archaic)
129-
        Adj_ku, // `ku' adjective (archaic)
130-
        Adj_shiku, // `shiku' adjective (archaic)
131-
        Adj_nari, // archaic/formal form of na-adjective
132-
        N_pr, // proper noun
133-
        V_unspec, // verb unspecified
134-
        V4k, // Yodan verb with `ku' ending (archaic)
135-
        V4g, // Yodan verb with `gu' ending (archaic)
136-
        V4s, // Yodan verb with `su' ending (archaic)
137-
        V4t, // Yodan verb with `tsu' ending (archaic)
138-
        V4n, // Yodan verb with `nu' ending (archaic)
139-
        V4b, // Yodan verb with `bu' ending (archaic)
140-
        V4m, // Yodan verb with `mu' ending (archaic)
141-
        V2k_k, // Nidan verb (upper class) with `ku' ending (archaic)
142-
        V2g_k, // Nidan verb (upper class) with `gu' ending (archaic)
143-
        V2t_k, // Nidan verb (upper class) with `tsu' ending (archaic)
144-
        V2d_k, // Nidan verb (upper class) with `dzu' ending (archaic)
145-
        V2h_k, // Nidan verb (upper class) with `hu/fu' ending (archaic)
146-
        V2b_k, // Nidan verb (upper class) with `bu' ending (archaic)
147-
        V2m_k, // Nidan verb (upper class) with `mu' ending (archaic)
148-
        V2y_k, // Nidan verb (upper class) with `yu' ending (archaic)
149-
        V2r_k, // Nidan verb (upper class) with `ru' ending (archaic)
150-
        V2k_s, // Nidan verb (lower class) with `ku' ending (archaic)
151-
        V2g_s, // Nidan verb (lower class) with `gu' ending (archaic)
152-
        V2s_s, // Nidan verb (lower class) with `su' ending (archaic)
153-
        V2z_s, // Nidan verb (lower class) with `zu' ending (archaic)
154-
        V2t_s, // Nidan verb (lower class) with `tsu' ending (archaic)
155-
        V2d_s, // Nidan verb (lower class) with `dzu' ending (archaic)
156-
        V2n_s, // Nidan verb (lower class) with `nu' ending (archaic)
157-
        V2h_s, // Nidan verb (lower class) with `hu/fu' ending (archaic)
158-
        V2b_s, // Nidan verb (lower class) with `bu' ending (archaic)
159-
        V2m_s, // Nidan verb (lower class) with `mu' ending (archaic)
160-
        V2y_s, // Nidan verb (lower class) with `yu' ending (archaic)
161-
        V2r_s, // Nidan verb (lower class) with `ru' ending (archaic)
162-
        V2w_s, // Nidan verb (lower class) with `u' ending and `we' conjugation (archaic)
163-
        Archit, // architecture term
164-
        Astron, // astronomy, etc. term
165-
        Baseb, // baseball term
166-
        Biol, // biology term
167-
        Bot, // botany term
168-
        Bus, // business term
169-
        Econ, // economics term
170-
        Engr, // engineering term
171-
        Finc, // finance term
172-
        Geol, // geology, etc. term
173-
        Law, // law, etc. term
174-
        Mahj, // mahjong term
175-
        Med, // medicine, etc. term
176-
        Music, // music term
177-
        Shinto, // Shinto term
178-
        Shogi, // shogi term
179-
        Sports, // sports term
180-
        Sumo, // sumo term
181-
        Zool, // zoology term
182-
        Joc, // jocular, humorous term
183-
        Anat, // anatomical term
6+
    public static class Source {
7+
        private ArrayList<String> content;
8+
        private boolean wasei;
9+
        private String type, language;
10+
11+
        public Source(ArrayList<String> content, boolean wasei, String type, String language) {
12+
            this.content = content;
13+
            this.wasei = wasei;
14+
            this.type = type;
15+
            this.language = language;
16+
        }
18417
    }
18518
18619
    public static class Sense {
187-
        private ArrayList<String> senses;
188-
        private ArrayList<Tag> tags;
20+
        private ArrayList<String> references, limits, infos, tags, glosses;
21+
        private String language;
22+
        private ArrayList<Source> sources;
18923
190-
        public Sense(ArrayList<String> senses, ArrayList<Tag> tags) {
191-
            this.senses = senses;
24+
        public Sense(ArrayList<String> references, ArrayList<String> limits, ArrayList<String> infos,
25+
                     ArrayList<Source> sources, ArrayList<String> tags, ArrayList<String> glosses,
26+
                     String language) {
27+
            this.references = references;
28+
            this.limits = limits;
29+
            this.infos = infos;
30+
            this.sources = sources;
19231
            this.tags = tags;
32+
            this.glosses = glosses;
33+
            this.language = language;
34+
        }
35+
36+
        public ArrayList<String> getGlosses() {
37+
            return glosses;
38+
        }
39+
    }
40+
41+
    public static class Reading {
42+
        private ArrayList<String> kanjis, infos, readings;
43+
44+
        public Reading(ArrayList<String> kanjis, ArrayList<String> infos, ArrayList<String> readings) {
45+
            this.kanjis = kanjis;
46+
            this.infos = infos;
47+
            this.readings = readings;
19348
        }
19449
    }
19550
196-
    private String kanji, kana;
51+
    private ArrayList<String> kanjis;
52+
    private ArrayList<Reading> readings;
19753
    private ArrayList<Sense> senses;
198-
    private ArrayList<String> alternatives;
199-
    private ArrayList<Tag> tags;
20054
201-
    public Result(String kanji, String kana, ArrayList<Sense> senses, ArrayList<String> alternatives) {
202-
        this.kanji = kanji;
203-
        this.kana = kana;
55+
    public Result(ArrayList<String> kanjis, ArrayList<Reading> readings, ArrayList<Sense> senses) {
56+
        this.kanjis = kanjis;
57+
        this.readings = readings;
20458
        this.senses = senses;
205-
        this.alternatives = alternatives;
20659
    }
20760
20861
    public String getKanji() {
209-
        return kanji;
62+
        String k = "";
63+
        if(kanjis.size() > 0)
64+
            k = kanjis.get(0);
65+
        return k;
21066
    }
21167
212-
    public String getKana() {
213-
        return kana;
68+
    public ArrayList<String> getAlternatives() {
69+
        return kanjis;
21470
    }
21571
21672
    public ArrayList<Sense> getSenses() {
21773
        return senses;
21874
    }
21975
220-
    public ArrayList<String> getAlternatives() {
221-
        return alternatives;
76+
    public ArrayList<Reading> getReadings() {
77+
        return readings;
22278
    }
22379
}

app/src/main/java/eu/lepiller/nani/result/ResultAdapter.java unknown status 2

1-
package eu.lepiller.nani.result;
2-
3-
import android.content.Context;
4-
import android.view.LayoutInflater;
5-
import android.view.View;
6-
import android.view.ViewGroup;
7-
import android.widget.ArrayAdapter;
8-
import android.widget.TextView;
9-
10-
import java.util.ArrayList;
11-
12-
import eu.lepiller.nani.R;
13-
14-
public class ResultAdapter extends ArrayAdapter<Result> {
15-
    Context context;
16-
    public ResultAdapter(Context context, ArrayList<Result> results) {
17-
        super(context, 0, results);
18-
        this.context = context;
19-
    }
20-
21-
    @Override
22-
    public View getView(int position, View convertView, ViewGroup parent) {
23-
        // Get the data item for this position
24-
        Result result = getItem(position);
25-
26-
        // Check if an existing view is being reused, otherwise inflate the view
27-
        if (convertView == null) {
28-
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.layout_result, parent, false);
29-
        }
30-
31-
        if (result == null) {
32-
            return convertView;
33-
        }
34-
35-
        // Lookup view for data population
36-
        TextView kanji_view = convertView.findViewById(R.id.kanji_view);
37-
38-
        // Populate the data into the template view using the data object
39-
        kanji_view.setText(result.getKanji());
40-
41-
        // Return the completed view to render on screen
42-
        return convertView;
43-
    }
44-
}

app/src/main/res/layout/activity_about.xml

5353
            android:layout_marginEnd="8dp"
5454
            android:layout_marginRight="8dp"
5555
            android:text="@string/data_intro"
56-
            android:textColor="@color/colorPrimary"
5756
            app:layout_constraintEnd_toEndOf="parent"
5857
            app:layout_constraintStart_toStartOf="parent"
5958
            app:layout_constraintTop_toBottomOf="@+id/textView6" />

103102
            android:layout_marginEnd="8dp"
104103
            android:layout_marginRight="8dp"
105104
            android:text="@string/license_text"
106-
            android:textColor="@color/colorPrimary"
107105
            app:layout_constraintEnd_toEndOf="parent"
108106
            app:layout_constraintStart_toStartOf="parent"
109107
            app:layout_constraintTop_toBottomOf="@+id/textView2" />

133131
            android:layout_marginEnd="8dp"
134132
            android:layout_marginRight="8dp"
135133
            android:text="@string/nani_about"
136-
            android:textColor="@color/colorPrimary"
137134
            app:layout_constraintEnd_toEndOf="parent"
138135
            app:layout_constraintStart_toStartOf="parent"
139136
            app:layout_constraintTop_toBottomOf="@+id/textView5" />

app/src/main/res/layout/content_dictionary.xml

11
<?xml version="1.0" encoding="utf-8"?>
2-
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
    xmlns:app="http://schemas.android.com/apk/res-auto"
44
    xmlns:tools="http://schemas.android.com/tools"
55
    android:layout_width="match_parent"

1717
        android:layout_marginTop="32dp"
1818
        android:layout_marginEnd="8dp"
1919
        android:layout_marginRight="8dp"
20-
        android:layout_marginBottom="8dp"
21-
        app:layout_constraintBottom_toBottomOf="parent"
22-
        app:layout_constraintEnd_toEndOf="parent"
23-
        app:layout_constraintStart_toStartOf="parent"
24-
        app:layout_constraintTop_toTopOf="parent" />
25-
</android.support.constraint.ConstraintLayout>
25>
260>
\ No newline at end of file
20+
        android:layout_marginBottom="8dp" />
21+
</LinearLayout>
21<
022<
\ No newline at end of file

app/src/main/res/layout/content_main.xml

11
<?xml version="1.0" encoding="utf-8"?>
2-
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
    xmlns:app="http://schemas.android.com/apk/res-auto"
44
    xmlns:tools="http://schemas.android.com/tools"
55
    android:layout_width="match_parent"
66
    android:layout_height="match_parent"
7+
    android:orientation="vertical"
78
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
89
    tools:context=".MainActivity"
910
    tools:showIn="@layout/activity_main">
1011
11-
    <Button
12-
        android:id="@+id/search_button"
13-
        android:layout_width="wrap_content"
12+
    <LinearLayout
13+
        android:id="@+id/linearLayout4"
14+
        android:layout_width="match_parent"
1415
        android:layout_height="wrap_content"
15-
        android:layout_marginStart="8dp"
16-
        android:layout_marginLeft="8dp"
17-
        android:layout_marginTop="32dp"
18-
        android:layout_marginEnd="16dp"
19-
        android:layout_marginRight="16dp"
20-
        android:text="@string/search_button"
21-
        app:layout_constraintEnd_toEndOf="parent"
22-
        app:layout_constraintStart_toEndOf="@+id/search_form"
23-
        app:layout_constraintTop_toTopOf="parent" />
16+
        android:layout_marginTop="8dp"
17+
        android:orientation="horizontal">
2418
25-
    <EditText
26-
        android:id="@+id/search_form"
27-
        android:layout_width="wrap_content"
28-
        android:layout_height="wrap_content"
29-
        android:layout_marginStart="16dp"
30-
        android:layout_marginLeft="16dp"
31-
        android:layout_marginTop="32dp"
32-
        android:ems="10"
33-
        android:hint="@string/search_hint"
34-
        android:inputType="text"
35-
        app:layout_constraintStart_toStartOf="parent"
36-
        app:layout_constraintTop_toTopOf="parent" />
19+
        <EditText
20+
            android:id="@+id/search_form"
21+
            android:layout_width="0dp"
22+
            android:layout_height="wrap_content"
23+
            android:layout_marginStart="16dp"
24+
            android:layout_marginLeft="16dp"
25+
            android:layout_marginTop="32dp"
26+
            android:layout_weight="1"
27+
            android:ems="10"
28+
            android:importantForAutofill="no"
29+
            android:hint="@string/search_hint"
30+
            android:inputType="text" />
31+
32+
        <Button
33+
            android:id="@+id/search_button"
34+
            android:layout_width="wrap_content"
35+
            android:layout_height="wrap_content"
36+
            android:layout_marginStart="8dp"
37+
            android:layout_marginLeft="8dp"
38+
            android:layout_marginTop="32dp"
39+
            android:layout_marginEnd="16dp"
40+
            android:layout_marginRight="16dp"
41+
            android:text="@string/search_button" />
42+
    </LinearLayout>
43+
44+
    <ScrollView
45+
        android:layout_weight="1"
46+
        android:layout_width="match_parent"
47+
        android:layout_height="0dp">
48+
        <LinearLayout
49+
            android:orientation="vertical"
50+
            android:id="@+id/results_view"
51+
            android:layout_width="match_parent"
52+
            android:layout_height="wrap_content"
53+
            android:layout_marginTop="16dp"
54+
            android:layout_marginBottom="8dp" />
55+
    </ScrollView>
3756
38-
    <ListView
39-
        android:id="@+id/results_view"
40-
        android:layout_width="395dp"
41-
        android:layout_height="579dp"
42-
        android:layout_marginStart="8dp"
43-
        android:layout_marginLeft="8dp"
44-
        android:layout_marginTop="16dp"
45-
        android:layout_marginEnd="8dp"
46-
        android:layout_marginRight="8dp"
47-
        android:layout_marginBottom="8dp"
48-
        app:layout_constraintBottom_toBottomOf="parent"
49-
        app:layout_constraintEnd_toEndOf="parent"
50-
        app:layout_constraintStart_toStartOf="parent"
51-
        app:layout_constraintTop_toBottomOf="@+id/search_form" />
52-
</android.support.constraint.ConstraintLayout>
52>
530>
\ No newline at end of file
57+
</LinearLayout>
57<
058<
\ No newline at end of file

app/src/main/res/layout/layout_result.xml

11
<?xml version="1.0" encoding="utf-8"?>
22
<LinearLayout
33
    xmlns:android="http://schemas.android.com/apk/res/android"
4-
    xmlns:app="http://schemas.android.com/apk/res-auto"
5-
    xmlns:tools="http://schemas.android.com/tools"
64
    android:layout_width="match_parent"
7-
    android:layout_height="wrap_content">
5+
    android:layout_height="wrap_content"
6+
    android:layout_marginBottom="32dp">
87
98
    <TextView
109
        android:id="@+id/kanji_view"
11-
        android:layout_width="64dp"
12-
        android:layout_height="64dp"
10+
        android:layout_width="96dp"
11+
        android:layout_height="wrap_content"
1312
        android:layout_gravity="center"
1413
        android:layout_weight="0"
15-
        android:contentDescription="@string/icon_description" />
14+
        android:contentDescription="@string/icon_description"
15+
        android:textIsSelectable="true"
16+
        android:textSize="@dimen/title_size" />
1617
17-
    <ScrollView
18-
        android:layout_width="match_parent"
19-
        android:layout_height="match_parent"
20-
        android:layout_weight="0">
18+
    <LinearLayout
19+
        android:layout_width="wrap_content"
20+
        android:layout_height="wrap_content"
21+
        android:layout_gravity="center"
22+
        android:layout_weight="100"
23+
        android:orientation="vertical">
2124
2225
        <LinearLayout
23-
            android:layout_width="wrap_content"
24-
            android:layout_height="wrap_content"
25-
            android:layout_gravity="center"
26-
            android:layout_weight="100"
27-
            android:orientation="vertical">
26+
            android:orientation="vertical"
27+
            android:id="@+id/sense_view"
28+
            android:layout_width="match_parent"
29+
            android:layout_height="0dp"
30+
            android:layout_weight="1">
2831
29-
            <ListView
30-
                android:id="@+id/sense_view"
31-
                android:layout_width="wrap_content"
32-
                android:layout_height="wrap_content" />
33-
34-
            <TextView
35-
                android:id="@+id/additional_info_view"
36-
                android:layout_width="match_parent"
37-
                android:layout_height="wrap_content"
38-
                android:layout_marginStart="8dp"
39-
                android:layout_marginLeft="8dp"
40-
                android:layout_marginTop="8dp"
41-
                android:layout_marginEnd="8dp"
42-
                android:layout_marginRight="8dp" />
4332
        </LinearLayout>
44-
    </ScrollView>
4533
34+
        <TextView
35+
            android:id="@+id/additional_info_view"
36+
            android:layout_width="match_parent"
37+
            android:layout_height="wrap_content"
38+
            android:layout_marginStart="8dp"
39+
            android:layout_marginLeft="8dp"
40+
            android:layout_marginTop="8dp"
41+
            android:layout_marginEnd="8dp"
42+
            android:layout_marginRight="8dp"
43+
            android:textIsSelectable="true" />
44+
    </LinearLayout>
4645
</LinearLayout>
4645=
4746=
\ No newline at end of file

app/src/main/res/layout/layout_sense.xml unknown status 1

1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout
3+
    xmlns:android="http://schemas.android.com/apk/res/android"
4+
    android:layout_width="match_parent"
5+
    android:layout_height="wrap_content">
6+
7+
    <TextView
8+
        android:id="@+id/id_view"
9+
        android:layout_width="wrap_content"
10+
        android:layout_height="wrap_content"
11+
        android:layout_margin="8dp"
12+
        android:layout_marginEnd="16dp"
13+
        android:layout_marginRight="16dp"
14+
        android:text="id" />
15+
16+
    <TextView
17+
        android:id="@+id/definition_view"
18+
        android:layout_width="0dp"
19+
        android:layout_height="wrap_content"
20+
        android:layout_margin="8dp"
21+
        android:layout_weight="1"
22+
        android:text="definition" />
23+
</LinearLayout>
23<
024<
\ No newline at end of file

app/src/main/res/values/strings.xml

1313
    <string name="icon_description">Icon</string>
1414
1515
    <!-- Dictionnary descriptions -->
16-
    <string name="dico_example">An example dictionary with only an entry for ?????? (gathering up). Used in development.</string>
16+
    <string name="dico_jmdict_example">Japanese/English dictionary for test purposes. Do not use.</string>
17+
    <string name="dico_jmdict_e">Japanese/English dictionary from the Electronic Dictionary Research and Development Group.\n~80 MB, ~180,000 entries.</string>
18+
19+
    <!-- Result view -->
20+
    <string name="sense_number">%d.</string>
21+
    <string name="sense_separator">"; "</string>
22+
    <string name="sense_alternatives">Alternative forms: %s</string>
1723
1824
    <!-- JMdict tags, obtained with
1925
         cat entities | cut -c 10- | sed -e 's|">$||' -e 's|.* "|<item>|' -e 's|$|</item>|' -e "s|\`|'|g" | sed "s|'|\\\'|g"