source: extensions/jiwigo/trunk/src/main/java/fr/mael/jiwigo/transverse/ImagesManagement.java @ 10808

Last change on this file since 10808 was 10808, checked in by mlg, 13 years ago

Adds a maximum size for the cache
Will limit memory consumption.

File size: 9.2 KB
Line 
1package fr.mael.jiwigo.transverse;
2
3import java.awt.image.BufferedImage;
4import java.net.URL;
5import java.util.ArrayList;
6import java.util.Collections;
7import java.util.Date;
8import java.util.HashMap;
9import java.util.Iterator;
10import java.util.List;
11import java.util.Map;
12
13import javax.imageio.ImageIO;
14
15import fr.mael.jiwigo.om.Image;
16import fr.mael.jiwigo.transverse.exception.JiwigoException;
17import fr.mael.jiwigo.transverse.util.Tools;
18import fr.mael.jiwigo.transverse.util.spring.SpringUtils;
19
20/**
21   Copyright (c) 2010, Mael
22   All rights reserved.
23
24   Redistribution and use in source and binary forms, with or without
25   modification, are permitted provided that the following conditions are met:
26    * Redistributions of source code must retain the above copyright
27      notice, this list of conditions and the following disclaimer.
28    * Redistributions in binary form must reproduce the above copyright
29      notice, this list of conditions and the following disclaimer in the
30      documentation and/or other materials provided with the distribution.
31    * Neither the name of jiwigo nor the
32      names of its contributors may be used to endorse or promote products
33      derived from this software without specific prior written permission.
34
35   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
36   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
37   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38   DISCLAIMED. IN NO EVENT SHALL Mael BE LIABLE FOR ANY
39   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
41   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
42   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
46 * @author mael
47 * Management of the real sized pictures
48 */
49public class ImagesManagement {
50    /**
51     * Logger
52     */
53    public static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
54            .getLog(ImagesManagement.class);
55    /**
56     * the index of the current image
57     */
58    private int currentImageIndex;
59    /**
60     * the current image
61     */
62    private Image currentImage;
63    /**
64     * images list
65     */
66    private List<Image> listImage;
67
68    /**
69     * cache allows to keep the images in the ram
70     */
71    private HashMap<Integer, CacheObjectManagement> imageCache = new HashMap<Integer, CacheObjectManagement>();
72
73    /**
74     * cache allows to keep the thumbnails in the ram
75     */
76    private HashMap<Integer, CacheObjectManagement> thumbnailsCache = new HashMap<Integer, CacheObjectManagement>();
77
78    /**
79     * If true : the application won't ask the privacy level
80     * to the user each time he adds pictures
81     */
82    private boolean rememberPrivacyLevel = false;
83
84    /**
85     * if true : the user is currently uploading pictures
86     */
87    private boolean isUploading = false;
88    /**
89     * the privacy level to apply to the pictures
90     */
91    private int privacyLevel = 1;
92    /**
93     * boolean that defines if the application is sending files
94     *
95     */
96    private boolean sendingFiles = false;
97
98    /**
99     * integer that contains the current category of the browser
100     * it allows to empty the list of images if the category changes
101     */
102    private Integer currentCategory = -1;
103
104    private static Integer IMAGE_CACHE_SIZE = 20;
105
106    /**
107     * singleton
108     */
109    private static ImagesManagement instance;
110
111    private ImagesManagement() {
112    }
113
114    public static ImagesManagement getInstance() {
115        if (instance == null) {
116            instance = new ImagesManagement();
117        }
118        return instance;
119    }
120
121    /**
122     * gets the current image
123     * @return the image
124     */
125    public Image getCurrentImage() {
126        //return LIST_IMAGE.get(CURRENT_IMAGE_INDEX);
127        return currentImage;
128    }
129
130    /**
131     * next image
132     */
133    public void next() {
134        if (currentImageIndex != listImage.size() - 1) {
135            currentImageIndex++;
136        } else {
137            currentImageIndex = 0;
138        }
139        currentImage = listImage.get(currentImageIndex);
140    }
141
142    /**
143     * previous image
144     */
145    public void previous() {
146        if (currentImageIndex != 0) {
147            currentImageIndex--;
148        } else {
149            currentImageIndex = listImage.size() - 1;
150        }
151        currentImage = listImage.get(currentImageIndex);
152    }
153
154    /**
155     *
156     * @param image the current image
157     */
158    public void setCurrentImage(Image image) {
159        if (!image.getIdCategory().equals(currentCategory)) {
160            try {
161                listImage = SpringUtils.getImageService().listByCategory(image.getIdCategory(), true);
162                currentCategory = image.getIdCategory();
163            } catch (JiwigoException e) {
164                LOG.error(Tools.getStackTrace(e));
165            }
166        }
167        currentImage = image;
168        int compteur = 0;
169        for (Image im : listImage) {
170            if (im.getIdentifier().equals(image.getIdentifier())) {
171                currentImageIndex = compteur;
172                return;
173            }
174            compteur++;
175        }
176    }
177
178    /**
179     * Method that allows to keep a maximum number of images in the cache
180     * @param cache
181     * @param maxSize
182     */
183    private void checkCache(HashMap<Integer, CacheObjectManagement> cache, Integer maxSize) {
184        if (cache.size() == maxSize) {
185            Integer objectsToRemove = (maxSize / 4);
186            if (LOG.isDebugEnabled()) {
187                LOG.debug("Cache has reached max size cleaning " + objectsToRemove + " objects");
188            }
189            ArrayList as = new ArrayList(cache.entrySet());
190
191            Collections.sort(as, new CacheObjectManagementComparator());
192            Iterator i = as.iterator();
193            for (int j = 0; j < objectsToRemove; j++) {
194                Integer key = (Integer) ((Map.Entry) i.next()).getKey();
195                if (LOG.isDebugEnabled()) {
196                    CacheObjectManagement cacheObject = cache.get(key);
197                    String debugStr = "";
198                    for (Integer id : cache.keySet()) {
199                        debugStr += "\t" + id + " : " + cache.get(id).getLastAccessDate() + "\n";
200                    }
201                    LOG.debug("Available object : \n" + debugStr);
202                    LOG.debug("Removed object : " + key + " : " + cacheObject.getLastAccessDate());
203                }
204
205                CacheObjectManagement object = cache.remove(key);
206                object = null;
207            }
208            if (LOG.isDebugEnabled()) {
209                String debugStr = "";
210                for (Integer id : cache.keySet()) {
211                    debugStr += "\t" + id + " : " + cache.get(id).getLastAccessDate() + "\n";
212                }
213                LOG.debug("Cache size is now " + cache.size() + ". Cache now contains : \n" + debugStr);
214            }
215        }
216    }
217
218    /**
219     * Function that allows to load images once
220     * to decrease response delays
221     * @return the image
222     */
223    public BufferedImage getCurrentBufferedImage() {
224        if (imageCache.get(currentImage.getIdentifier()) == null) {
225            try {
226                checkCache(imageCache, IMAGE_CACHE_SIZE);
227                BufferedImage img = ImageIO.read(new URL(currentImage.getUrl()));
228                CacheObjectManagement cacheObject = new CacheObjectManagement(img, new Date());
229                imageCache.put(currentImage.getIdentifier(), cacheObject);
230                if (LOG.isDebugEnabled()) {
231                    LOG.debug("Adding image to cache : " + currentImage.getIdentifier() + " : "
232                            + cacheObject.getLastAccessDate());
233                }
234            } catch (Exception e) {
235                LOG.error(Tools.getStackTrace(e));
236            }
237        }
238        CacheObjectManagement cacheObject = imageCache.get(currentImage.getIdentifier());
239        cacheObject.setLastAccessDate(new Date());
240        return cacheObject.getImage();
241    }
242
243    /**
244     * Function that allows to load thimbnails once
245     * to decrease response delays
246     * @return the image
247     */
248    public BufferedImage getMiniatureBufferedImage(Image image) {
249        if (thumbnailsCache.get(image.getIdentifier()) == null) {
250            try {
251                BufferedImage img = ImageIO.read(new URL(image.getThumbnailUrl()));
252                CacheObjectManagement cacheObject = new CacheObjectManagement(img, new Date());
253                thumbnailsCache.put(image.getIdentifier(), cacheObject);
254            } catch (Exception e) {
255                LOG.error(Tools.getStackTrace(e));
256            }
257        }
258        CacheObjectManagement cacheObject = thumbnailsCache.get(image.getIdentifier());
259        cacheObject.setLastAccessDate(new Date());
260        return cacheObject.getImage();
261    }
262
263    /**
264     * @return the listImage
265     */
266    public List<Image> getListImage() {
267        return listImage;
268    }
269
270    /**
271     * @param listImage the listImage to set
272     */
273    public void setListImage(List<Image> listImage) {
274        this.listImage = listImage;
275    }
276
277    /**
278     * @return the rememberPrivacyLevel
279     */
280    public boolean isRememberPrivacyLevel() {
281        return rememberPrivacyLevel;
282    }
283
284    /**
285     * @param rememberPrivacyLevel the rememberPrivacyLevel to set
286     */
287    public void setRememberPrivacyLevel(boolean rememberPrivacyLevel) {
288        this.rememberPrivacyLevel = rememberPrivacyLevel;
289    }
290
291    /**
292     * @return the sendingFiles
293     */
294    public boolean isSendingFiles() {
295        return sendingFiles;
296    }
297
298    /**
299     * @param sendingFiles the sendingFiles to set
300     */
301    public void setSendingFiles(boolean sendingFiles) {
302        this.sendingFiles = sendingFiles;
303    }
304
305    /**
306     * @return the privacyLevel
307     */
308    public int getPrivacyLevel() {
309        return privacyLevel;
310    }
311
312    /**
313     * @param privacyLevel the privacyLevel to set
314     */
315    public void setPrivacyLevel(int privacyLevel) {
316        this.privacyLevel = privacyLevel;
317    }
318
319}
Note: See TracBrowser for help on using the repository browser.