001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.type.collection.list;
020
021import icy.file.FileUtil;
022import icy.preferences.XMLPreferences;
023import icy.util.StringUtil;
024
025import java.io.File;
026import java.util.Arrays;
027
028/**
029 * @author stephane
030 */
031public class RecentFileList extends RecentList
032{
033    protected final static int NB_MAX_ENTRY = 10;
034    protected final static int NB_MAX_FILE = 1000;
035
036    protected final static String ID_NB_FILE = "nbFile";
037    protected final static String ID_FILE = "file";
038
039    public RecentFileList(XMLPreferences preferences)
040    {
041        super(preferences, NB_MAX_ENTRY);
042
043        // clean the list
044        clean();
045    }
046
047    public void addEntry(String[] paths)
048    {
049        // check we are under files limit
050        if (paths.length > NB_MAX_FILE)
051            return;
052
053        final String[] adjPaths = adjust(paths);
054
055        // first remove previous entry
056        final int ind = find(adjPaths);
057
058        synchronized (list)
059        {
060            if (ind != -1)
061                list.remove(ind);
062        }
063
064        // add the list
065        super.addEntry(adjPaths);
066    }
067
068    private static String[] adjust(String[] paths)
069    {
070        final String[] result = new String[paths.length];
071
072        for (int i = 0; i < paths.length; i++)
073            result[i] = FileUtil.getGenericPath(paths[i]);
074
075        return result;
076    }
077
078    public void addEntry(File[] files)
079    {
080        // check we are under files limit
081        if (files.length > NB_MAX_FILE)
082            return;
083
084        final String[] filenames = new String[files.length];
085
086        for (int i = 0; i < files.length; i++)
087            filenames[i] = files[i].getAbsolutePath();
088
089        addEntry(filenames);
090    }
091
092    protected int find(String[] filenames)
093    {
094        synchronized (list)
095        {
096            for (int i = 0; i < list.size(); i++)
097                if (Arrays.equals((String[]) list.get(i), filenames))
098                    return i;
099        }
100
101        return -1;
102    }
103
104    @Override
105    public String[] getEntry(int index)
106    {
107        return (String[]) super.getEntry(index);
108    }
109
110    public File[] getEntryAsFiles(int index)
111    {
112        final String[] filenames = getEntry(index);
113        final File[] result = new File[filenames.length];
114
115        for (int i = 0; i < filenames.length; i++)
116            result[i] = new File(filenames[i]);
117
118        return result;
119    }
120
121    public String getEntryAsName(int index, int maxlen, boolean tailLimit)
122    {
123        final String[] filenames = getEntry(index);
124
125        if ((filenames == null) || (filenames.length == 0))
126            return "";
127
128        if (filenames.length == 1)
129            return StringUtil.limit(filenames[0], maxlen, tailLimit);
130
131        String result = filenames[0];
132
133        for (int i = 1; i < filenames.length; i++)
134            result += ", " + FileUtil.getFileName(filenames[i]);
135
136        return "[" + StringUtil.limit(result, maxlen, tailLimit) + "]";
137    }
138
139    /**
140     * Remove invalid files from the list
141     */
142    public void clean()
143    {
144        for (int i = list.size() - 1; i >= 0; i--)
145        {
146            final File[] files = getEntryAsFiles(i);
147
148            boolean allExists = true;
149            for (File file : files)
150                allExists = allExists && file.exists();
151
152            synchronized (list)
153            {
154                // one of the files doesn't exist anymore ?
155                if (!allExists)
156                    // remove it from the list
157                    list.remove(i);
158            }
159        }
160
161        // save to pref
162        save();
163        // inform about change
164        changed();
165    }
166
167    @Override
168    protected String[] loadEntry(String key)
169    {
170        if (preferences.nodeExists(key))
171        {
172            final XMLPreferences pref = preferences.node(key);
173
174            if (pref != null)
175            {
176                synchronized (pref)
177                {
178                    // load size
179                    final int numFile = pref.getInt(ID_NB_FILE, 0);
180                    final String[] result = new String[numFile];
181
182                    // load filenames
183                    for (int i = 0; i < numFile; i++)
184                        result[i] = pref.get(ID_FILE + i, "");
185
186                    return result;
187                }
188            }
189        }
190
191        return null;
192    }
193
194    @Override
195    protected void saveEntry(String key, Object value)
196    {
197        final XMLPreferences pref = preferences.node(key);
198
199        // need to check as preferences can have been cleared here
200        if (pref != null)
201        {
202            synchronized (pref)
203            {
204                // remove all children
205                pref.removeChildren();
206
207                // then save
208                if (value != null)
209                {
210                    final String[] filenames = (String[]) value;
211                    final int numFile = filenames.length;
212
213                    // save size
214                    pref.putInt(ID_NB_FILE, numFile);
215
216                    // save filenames
217                    for (int i = 0; i < numFile; i++)
218                        pref.put(ID_FILE + i, filenames[i]);
219                }
220                else
221                {
222                    // save size
223                    pref.putInt(ID_NB_FILE, 0);
224                }
225
226                // then clean
227                pref.clean();
228            }
229        }
230    }
231}