1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 package com.sun.star.lib.uno.protocols.urp; 29 30 import java.util.HashMap; 31 32 /** 33 An LRU cache for arbitrary objects. 34 35 This class is not synchronized, as any necessary synchronization will already 36 take place in the client. 37 */ 38 final class Cache { 39 /** 40 Create a cache. 41 42 @param size the maximum cache size, must be between 0, inclusive, and 43 NOT_CACHED, exclusive 44 */ 45 public Cache(int size) { 46 maxSize = size; 47 } 48 49 public int add(boolean[] found, Object content) { 50 Entry e = (Entry) map.get(content); 51 found[0] = e != null; 52 if (e == null) { 53 if (map.size() < maxSize) { 54 // There is still room for a new entry at the front: 55 e = new Entry(content, map.size(), null, first); 56 if (first == null) { 57 last = e; 58 } else { 59 first.prev = e; 60 } 61 first = e; 62 } else if (last != null) { 63 // Take last entry out and recycle as new front: 64 map.remove(last.content); 65 e = last; 66 e.content = content; 67 if (first != last) { 68 // Reached only if maxSize > 1: 69 last = last.prev; 70 last.next = null; 71 e.prev = null; 72 e.next = first; 73 first.prev = e; 74 first = e; 75 } 76 } else { 77 // Reached iff maxSize == 0: 78 return NOT_CACHED; 79 } 80 map.put(content, e); 81 } else if (e != first) { 82 // Move to front (reached only if maxSize > 1): 83 e.prev.next = e.next; 84 if (e.next == null) { 85 last = e.prev; 86 } else { 87 e.next.prev = e.prev; 88 } 89 e.prev = null; 90 e.next = first; 91 first.prev = e; 92 first = e; 93 } 94 return e.index; 95 } 96 97 public static final int NOT_CACHED = 0xFFFF; 98 99 private static final class Entry { 100 public Entry(Object content, int index, Entry prev, Entry next) { 101 this.content = content; 102 this.index = index; 103 this.prev = prev; 104 this.next = next; 105 } 106 107 public Object content; 108 public int index; 109 public Entry prev; 110 public Entry next; 111 } 112 113 // first/last form a list of 0 to maxSize entries, most recently used first; 114 // map contains the same entries; each entry has a unique index in the range 115 // 0 to maxSize - 1 116 private final int maxSize; 117 private final HashMap map = new HashMap(); // from Object to Entry 118 private Entry first = null; 119 private Entry last = null; 120 } 121