OSDN Git Service

NeverNote 0.88.
[neighbornote/NeighborNote.git] / src / com / swabunga / spell / engine / SpellDictionaryCachedDichoDisk.java
1 /*\rJazzy - a Java library for Spell Checking\rCopyright (C) 2001 Mindaugas Idzelis\rFull text of license can be found in LICENSE.txt\r\rThis library is free software; you can redistribute it and/or\rmodify it under the terms of the GNU Lesser General Public\rLicense as published by the Free Software Foundation; either\rversion 2.1 of the License, or (at your option) any later version.\r\rThis library is distributed in the hope that it will be useful,\rbut WITHOUT ANY WARRANTY; without even the implied warranty of\rMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\rLesser General Public License for more details.\r\rYou should have received a copy of the GNU Lesser General Public\rLicense along with this library; if not, write to the Free Software\rFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r*/\rpackage com.swabunga.spell.engine;\r\rimport java.io.File;\rimport java.io.FileInputStream;\rimport java.io.FileNotFoundException;\rimport java.io.FileOutputStream;\rimport java.io.IOException;\rimport java.io.ObjectInputStream;\rimport java.io.ObjectOutputStream;\rimport java.io.Serializable;\rimport java.util.HashMap;\rimport java.util.Iterator;\rimport java.util.List;\r\r/**\r * Yet another <code>SpellDictionary</code> this one is based on Damien Guillaume's\r * Diskbased dictionary but adds a cache to try to improve abit on performance.\r *\r * @author Robert Gustavsson\r * @version 0.01\r */\r\rpublic class SpellDictionaryCachedDichoDisk extends SpellDictionaryDichoDisk {\r    \r    // Only used for testing to measure the effectiveness of the cache.\r    static public int hits=0;\r    static public int codes=0;\r\r    public static final String JAZZY_DIR=".jazzy";\r    public static final String PRE_CACHE_FILE_EXT=".pre";\r\r    private static int  MAX_CACHED=10000;\r\r    @SuppressWarnings("unchecked")\r  private final HashMap     suggestionCache=new HashMap(MAX_CACHED);\r    private String      preCacheFileName;\r    private String      preCacheDir;\r\r    /**\r     * Dictionary Convienence Constructor.\r     */\r    public SpellDictionaryCachedDichoDisk(File wordList)\r                                     throws FileNotFoundException, IOException {\r        super(wordList);\r        loadPreCache(wordList);\r    }\r    \r    /**\r     * Dictionary Convienence Constructor.\r     */\r    public SpellDictionaryCachedDichoDisk(File wordList, String encoding)\r                                     throws FileNotFoundException, IOException {\r        super(wordList, encoding);\r        loadPreCache(wordList);\r    }\r\r    /**\r     * Dictionary constructor that uses an aspell phonetic file to\r     * build the transformation table.\r     */\r\r    public SpellDictionaryCachedDichoDisk(File wordList, File phonetic)\r                                     throws FileNotFoundException, IOException {\r        super(wordList, phonetic);\r        loadPreCache(wordList);\r    }\r\r    /**\r     * Dictionary constructor that uses an aspell phonetic file to\r     * build the transformation table.\r     */\r    public SpellDictionaryCachedDichoDisk(File wordList, File phonetic, String encoding)\r                                     throws FileNotFoundException, IOException {\r        super(wordList, phonetic, encoding);\r        loadPreCache(wordList);\r    }\r\r    /**\r     * Add a word permanantly to the dictionary (and the dictionary file).\r     * <i>not implemented !</i>\r     */\r    @Override\r     public void addWord(String word) {\r        System.err.println("error: addWord is not implemented for SpellDictionaryCachedDichoDisk");\r    }\r\r    /**\r     * Clears the cache.\r     */\r    public void clearCache(){\r        suggestionCache.clear();\r    }\r\r    /**\r     * Returns a list of strings (words) for the code.\r     */\r    @Override\r      @SuppressWarnings("unchecked")\r public List getWords(String code) {\r        List list;\r        codes++;\r        if(suggestionCache.containsKey(code)){\r            hits++;\r            list=getCachedList(code);\r            return list;\r        }\r        list=super.getWords(code);\r        addToCache(code,list);\r        \r        return list;\r    }\r    /**\r     * This method returns the cached suggestionlist and also moves the code to\r     * the top of the codeRefQueue to indicate this code has resentlly been\r     * referenced.\r     */\r    @SuppressWarnings("unchecked")\r    private List getCachedList(String code){\r        CacheObject obj=(CacheObject)suggestionCache.get(code);\r        obj.setRefTime();\r        return obj.getSuggestionList();\r    }\r\r    /**\r     * Adds a code and it's suggestion list to the cache.\r     */\r    @SuppressWarnings("unchecked")\r private void addToCache(String code, List l){\r        String      c=null;\r        String      lowestCode=null;\r        long        lowestTime=Long.MAX_VALUE;\r        Iterator    it;\r        CacheObject obj;\r\r        if(suggestionCache.size()>=MAX_CACHED){\r            it=suggestionCache.keySet().iterator();\r            while(it.hasNext()){\r                c=(String)it.next();\r                obj=(CacheObject)suggestionCache.get(c);\r                if(obj.getRefTime()==0){\r                    lowestCode=c;\r                    break;\r                }\r                if(lowestTime>obj.getRefTime()){\r                    lowestCode=c;\r                    lowestTime=obj.getRefTime();\r                }\r            }\r            suggestionCache.remove(lowestCode);\r        }        \r        suggestionCache.put(code,new CacheObject(l));\r    }\r\r    /**\r     * Load the cache from file. The cach file has the same name as the \r     * dico file with the .pre extension added.\r     */\r    @SuppressWarnings("unchecked")\r      private void loadPreCache(File dicoFile)throws IOException{\r        String              code;\r        List                suggestions;\r        long                size,\r                            time;\r        File                preFile;\r        ObjectInputStream   in;\r\r        preCacheDir=System.getProperty("user.home")+"/"+JAZZY_DIR;\r        preCacheFileName=preCacheDir+"/"+dicoFile.getName()+PRE_CACHE_FILE_EXT;\r        //System.out.println(preCacheFileName);\r        preFile=new File(preCacheFileName);\r        if(!preFile.exists()){\r            System.err.println("No precache file");\r            return;\r        }\r        //System.out.println("Precaching...");\r        in=new ObjectInputStream(new FileInputStream(preFile));\r        try{\r            size=in.readLong();\r            for(int i=0;i<size;i++){\r                code=(String)in.readObject();\r                time=in.readLong();\r                suggestions=(List)in.readObject();\r                suggestionCache.put(code,new CacheObject(suggestions,time));\r            }\r        }catch(ClassNotFoundException ex){\r            System.out.println(ex.getMessage());\r        }\r        in.close();\r    }\r\r    /**\r     * Saves the current cache to file.\r     */\r    @SuppressWarnings("unchecked")\r  public void saveCache() throws IOException{\r        String              code;\r        CacheObject         obj;\r        File                preFile,\r                            preDir;\r        ObjectOutputStream  out;\r        Iterator            it;\r\r        if(preCacheFileName==null || preCacheDir==null){\r            System.err.println("Precache filename has not been set.");\r            return;\r        }\r        //System.out.println("Saving cache to precache file...");\r        preDir=new File(preCacheDir);\r        if(!preDir.exists())\r            preDir.mkdir();\r        preFile=new File(preCacheFileName);\r        out=new ObjectOutputStream(new FileOutputStream(preFile));\r        it=suggestionCache.keySet().iterator();\r        out.writeLong(suggestionCache.size());\r        while(it.hasNext()){\r            code=(String)it.next();\r            obj=(CacheObject)suggestionCache.get(code);\r            out.writeObject(code);\r            out.writeLong(obj.getRefTime());\r            out.writeObject(obj.getSuggestionList());\r        }\r        out.close();\r    }\r\r    // INNER CLASSES\r    // ------------------------------------------------------------------------\r    @SuppressWarnings("serial")\r       private class CacheObject implements Serializable{\r    \r        @SuppressWarnings("unchecked")\r         private List    suggestions=null;\r        private long    refTime=0;\r\r        @SuppressWarnings("unchecked")\r           public CacheObject(List list){\r            this.suggestions=list;\r        }\r\r        @SuppressWarnings("unchecked")\r            public CacheObject(List list, long time){\r            this.suggestions=list;\r            this.refTime=time;\r        }\r        \r        @SuppressWarnings("unchecked")\r          public List getSuggestionList(){\r            return suggestions;\r        }\r\r        public void setRefTime(){\r            refTime=System.currentTimeMillis();\r        }\r\r        public long getRefTime(){\r            return refTime;\r        }\r    }\r}\r