Package org.albite.dictionary

Source Code of org.albite.dictionary.Dictionary$DictEntries

//#condition !(TinyMode || TinyModeExport || LightMode || LightModeExport)
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package org.albite.dictionary;

import java.io.IOException;
import java.lang.ref.WeakReference;
import org.albite.albite.AlbiteMIDlet;
import org.albite.io.RandomReadingFile;
import org.albite.lang.AlbiteCharacter;
import org.albite.lang.TextTools;

/**
*
* @author albus
*/
public class Dictionary {

    public static final String      FILE_EXTENSION          = ".ald";
    public static final int         MAGIC_NUMBER            = 1095516740;

    private static final String     WORD_NOT_FOUND          = "Word not found.";

    /*
     * This one had better be a odd value, so that the suggestions would be
     * centered around a "best-find" word.
     */
    private static final int        NUMBER_OF_SUGGESTIONS   = 21;

    private final RandomReadingFile file;
    private final int               indexPosition;
    private WeakReference           indexEntries            = null;

    private String                  title;
    private String                  language;

    public Dictionary(final String filename)
            throws DictionaryException {

        try {
            this.file = new RandomReadingFile(filename);
//        } catch (IOException e) {
        } catch (Exception e) {
            throw new DictionaryException(e.toString());
        }

        try {
            /*
             * Check magic number
             */
            if (file.readInt() != MAGIC_NUMBER) {
                throw new DictionaryException();
            }

            /*
             * Read header
             */
            title = file.readUTF();
            language = file.readUTF();
            indexPosition = file.readInt();
        } catch (Exception e) {
            throw new DictionaryException("Dictionary is corrupted");
        }
    }

    /**
     * Loads the index
     * @throws DictionaryException
     */
    private DictEntries load() throws DictionaryException {
        if (indexEntries != null) {
            final DictEntries entries = (DictEntries) indexEntries.get();

            if (entries != null) {

                /*
                 * Dict already loaded.
                 */
                return entries;
            }
        }

        try {
            file.seek(indexPosition);

            final int wordsCount = file.readInt();

            final char[][]  indexEntryNames     = new char[wordsCount][];
            final int[]     indexEntryPositions = new int[wordsCount];

            for (int i = 0; i < wordsCount; i++) {
                indexEntryNames[i] = file.readUTFchars();
                indexEntryPositions[i] = file.readInt();
            }

            DictEntries entries =
                    new DictEntries(indexEntryNames, indexEntryPositions);

            indexEntries = new WeakReference(entries);
            return entries;
        } catch (Exception e) {
            throw new DictionaryException("Cannot load dictionary index");
        } catch (OutOfMemoryError e) {
            throw new DictionaryException("Out of memory while loading index");
        }
    }

    /**
     * Unloads the index, thus freeing memory.
     */
    public final void unload() {
        indexEntries = null;
    }

    public final String[] lookUp(final String lookingFor)
            throws DictionaryException {

        final DictEntries de = load();

        //#debug
        AlbiteMIDlet.LOGGER.log("lowercasing");
        final char[] text =
                AlbiteCharacter.toLowerCase(lookingFor.toCharArray());

        //#debug
        AlbiteMIDlet.LOGGER.log("binary search");
        int searchResult = TextTools.binarySearch(de.names, text);

        if (searchResult >= 0) {
            /*
             * The word was found, so no suggestions neccessary.
             */

            //#debug
            AlbiteMIDlet.LOGGER.log("word found. getting definitions");
            return new String[] {getDefinition(searchResult)};
        }

        /*
         * We need to increment the found index by one
         * as it has been decreased by one by the indexSearch method.
         */
        searchResult = -searchResult + 1;

        /*
         * Returns a maximum of 11 suggestions.
         */
        final int offset = NUMBER_OF_SUGGESTIONS / 2;

        int left  = searchResult - offset;
        int right = searchResult + offset;

        /*
         * First check left side, if the "center" (i.e. searchResult)
         * is too much in the left
         */
        if (left < 0) {
            left = 0;
            right = NUMBER_OF_SUGGESTIONS;
        }

        /*
         * Check if the "center" is too much in the right.
         */
        if (right >= de.names.length) {
            right = de.names.length - 1;
            left = right - NUMBER_OF_SUGGESTIONS;
        }

        /*
         * This might happen in the extreme case of a dictionary
         * having less number of items than NUMBER_OF_SUGGESTIONS
         * However, this might be quite possible for a simple
         * in-book dictionary.
         */
        if (left < 0) {
            left = 0;
        }

        final int len = right - left + 1;

        final String[] res = new String[len];

        for (int i = 0; i < len; i++) {
            res[i] = new String(de.names[left + i]);
        }

        //#debug
        AlbiteMIDlet.LOGGER.log("returning suggestions");
        return res;
    }

    public final String getDefinition(final String lookingFor)
            throws DictionaryException {

        final DictEntries de = load();

        final char[] text = lookingFor.toCharArray();
        final int searchResult = TextTools.binarySearch(de.names, text);

        if (searchResult < 0) {
            return WORD_NOT_FOUND;
        }

        return getDefinition(searchResult);
    }

    private String getDefinition(final int index)
            throws DictionaryException {

        final DictEntries de = load();

        if (index < 0 || index > de.positions.length) {
            return WORD_NOT_FOUND;
        }

        final int pos = de.positions[index];

        try {
            file.seek(pos);

            final String s = file.readUTF();
            return s;
        } catch (Exception e) {
            return WORD_NOT_FOUND;
        }
    }

    private class DictEntries {
        final char[][]  names;
        final int[]     positions;

        DictEntries(final char[][] names, final int[] positions) {
            this.names = names;
            this.positions = positions;
        }
    }

    public final String getTitle() {
        return title;
    }

    public final String getLanguage() {
        return language;
    }

    public final void close() throws IOException {
        file.close();
    }
}
TOP

Related Classes of org.albite.dictionary.Dictionary$DictEntries

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.