EMMA Coverage Report (generated Thu Nov 26 15:54:18 CST 2009)
[all classes][org.eclipse.pde.api.tools.internal.model]

COVERAGE SUMMARY FOR SOURCE FILE [ApiModelCache.java]

nameclass, %method, %block, %line, %
ApiModelCache.java100% (2/2)94%  (16/17)93%  (506/542)92%  (117.4/128)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ApiModelCache$Cache100% (1/1)75%  (3/4)69%  (18/26)80%  (4/5)
newInstance (int, int): LRUCache 0%   (0/1)0%   (0/8)0%   (0/1)
ApiModelCache$Cache (ApiModelCache, int, int): void 100% (1/1)100% (8/8)100% (2/2)
close (LRUCache$LRUCacheEntry): boolean 100% (1/1)100% (2/2)100% (1/1)
isEmpty (): boolean 100% (1/1)100% (8/8)100% (1/1)
     
class ApiModelCache100% (1/1)100% (13/13)95%  (488/516)92%  (113.4/123)
removeElementInfo (String, String, String, int): boolean 100% (1/1)87%  (145/166)87%  (30.4/35)
removeElementInfo (IApiElement): boolean 100% (1/1)92%  (47/51)80%  (12/15)
getElementInfo (String, String, String, int): IApiElement 100% (1/1)97%  (59/61)93%  (14/15)
cacheElementInfo (IApiElement): void 100% (1/1)99%  (137/138)97%  (28/29)
<static initializer> 100% (1/1)100% (3/3)100% (2/2)
ApiModelCache (): void 100% (1/1)100% (9/9)100% (3/3)
flushCaches (): void 100% (1/1)100% (9/9)100% (4/4)
flushMemberCache (): void 100% (1/1)100% (7/7)100% (3/3)
getCache (): ApiModelCache 100% (1/1)100% (8/8)100% (3/3)
getCacheKey (String, String, String): String 100% (1/1)100% (19/19)100% (3/3)
getRootName (String): String 100% (1/1)100% (14/14)100% (4/4)
isEmpty (): boolean 100% (1/1)100% (22/22)100% (6/6)
isMemberType (String): boolean 100% (1/1)100% (9/9)100% (1/1)

1/*******************************************************************************
2 * Copyright (c) 2009 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *     IBM Corporation - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.pde.api.tools.internal.model;
12 
13import org.eclipse.core.runtime.CoreException;
14import org.eclipse.jdt.internal.core.OverflowingLRUCache;
15import org.eclipse.jdt.internal.core.util.LRUCache;
16import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
17import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
18import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement;
19 
20/**
21 * Manages the caches of {@link IApiElement}s
22 * 
23 * @since 1.0.2
24 */
25public final class ApiModelCache {
26 
27        /**
28         * Cache used for {@link IApiElement}s
29         */
30        class Cache extends OverflowingLRUCache {
31 
32                /**
33                 * Constructor
34                 * @param size
35                 * @param overflow
36                 */
37                public Cache(int size, int overflow) {
38                        super(size, overflow);
39                }
40 
41                /* (non-Javadoc)
42                 * @see org.eclipse.jdt.internal.core.OverflowingLRUCache#close(org.eclipse.jdt.internal.core.util.LRUCache.LRUCacheEntry)
43                 */
44                protected boolean close(LRUCacheEntry entry) {
45                        return true;
46                }
47 
48                /* (non-Javadoc)
49                 * @see org.eclipse.jdt.internal.core.OverflowingLRUCache#newInstance(int, int)
50                 */
51                protected LRUCache newInstance(int size, int newOverflow) {
52                        return new Cache(size, newOverflow);
53                }
54                
55                /**
56                 * Returns if the cache has any elements in it or not
57                 * 
58                 * @return true if the cache has no entries, false otherwise
59                 */
60                public boolean isEmpty() {
61                        return !keys().hasMoreElements();
62                }
63        }
64        
65        static final int DEFAULT_CACHE_SIZE = 100;
66        static final int DEFAULT_OVERFLOW = (int)(DEFAULT_CACHE_SIZE * 0.1f);
67        static ApiModelCache fInstance = null;
68        
69        Cache fRootCache = null;
70        Cache fMemberTypeCache = null;
71        
72        /**
73         * Constructor - no instantiation
74         */
75        private ApiModelCache() {}
76        
77        /**
78         * Returns the singleton instance of this cache
79         * 
80         * @return the cache
81         */
82        public static synchronized ApiModelCache getCache() {
83                if(fInstance == null) {
84                        fInstance = new ApiModelCache();
85                }
86                return fInstance;
87        }
88        
89        /**
90         * Returns the key to use in a cache. The key is of the form:
91         * <code>[baselineid].[componentid].[typename]</code><br>
92         * 
93         * @param baseline
94         * @param component
95         * @param typename
96         * @return the member type cache key to use
97         */
98        private String getCacheKey(String baseline, String component, String typename) {
99                StringBuffer buffer = new StringBuffer();
100                buffer.append(baseline).append('.').append(component).append('.').append(typename);
101                return buffer.toString();
102        }
103        
104        /**
105         * Caches the given {@link IApiElement} in the correct cache based on its type.
106         * 
107         * @param element the element to cache
108         * @throws CoreException if there is a problem accessing any of the {@link IApiElement} info
109         * in order to cache it - pass the exception along.
110         */
111        public void cacheElementInfo(IApiElement element) throws CoreException {
112                switch(element.getType()) {
113                        case IApiElement.TYPE: {
114                                if(fRootCache == null) {
115                                        fRootCache = new Cache(DEFAULT_CACHE_SIZE, DEFAULT_OVERFLOW);
116                                }
117                                IApiComponent comp = element.getApiComponent();
118                                if(comp != null) {
119                                        IApiBaseline baseline = comp.getBaseline();
120                                        String id = comp.getId();
121                                        if(id == null) {
122                                                return;
123                                        }
124                                        Cache compcache = (Cache) fRootCache.get(baseline.getName());
125                                        if(compcache == null) {
126                                                compcache = new Cache(DEFAULT_CACHE_SIZE, DEFAULT_OVERFLOW);
127                                                fRootCache.put(baseline.getName(), compcache);
128                                        }
129                                        Cache typecache = (Cache) compcache.get(id);
130                                        if(typecache == null) {
131                                                typecache = new Cache(DEFAULT_CACHE_SIZE, DEFAULT_OVERFLOW);
132                                                compcache.put(comp.getId(), typecache);
133                                        }
134                                        ApiType type = (ApiType) element;
135                                        if(type.isMemberType() || isMemberType(type.getName()) /*cache even a root type with a '$' in its name here as well*/) {
136                                                if(this.fMemberTypeCache == null) {
137                                                        this.fMemberTypeCache = new Cache(DEFAULT_CACHE_SIZE, DEFAULT_OVERFLOW);
138                                                }
139                                                String key = getCacheKey(baseline.getName(), id, getRootName(type.getName()));
140                                                Cache mcache = (Cache) this.fMemberTypeCache.get(key);
141                                                if(mcache == null) {
142                                                        mcache = new Cache(DEFAULT_CACHE_SIZE, DEFAULT_OVERFLOW);
143                                                        this.fMemberTypeCache.put(key, mcache);
144                                                }
145                                                mcache.put(type.getName(), type);
146                                        }
147                                        else {
148                                                typecache.put(element.getName(), element);
149                                        }
150                                }
151                                break;
152                        }
153                }
154        }
155        
156        /**
157         * Returns the root type name assuming that the '$' char is a member type boundary 
158         * @param typename
159         * @return the pruned name or the original name
160         */
161        private String getRootName(String typename) {
162                int idx = typename.indexOf('$');
163                if(idx > -1) {
164                        return typename.substring(0, idx);
165                }
166                return typename;
167        }
168        
169        /**
170         * Method to see if the type boundary char appears in the type name
171         * @param typename
172         * @return true if the type name contains '$' false otherwise
173         */
174        private boolean isMemberType(String typename) {
175                return typename.indexOf('$') > -1;
176        }
177        
178        /**
179         * Returns the {@link IApiElement} infos for the element referenced by the given 
180         * identifier and of the given type.
181         * 
182         * @param baselineid the id of the baseline the component + element belongs to
183         * @param componentid the id of the {@link IApiComponent} the element resides in
184         * @param identifier for example the qualified name of the type or the id of an API component
185         * @param type the kind of the element to look for info for
186         * 
187         * @return the cached {@link IApiElement} or <code>null</code> if no such element is cached
188         */
189        public IApiElement getElementInfo(String baselineid, String componentid, String identifier, int type) {
190                if(baselineid == null || componentid == null) {
191                        return null;
192                }
193                switch(type) {
194                        case IApiElement.TYPE: {
195                                if(isMemberType(identifier)) {
196                                        if(this.fMemberTypeCache != null) {
197                                                Cache mcache = (Cache) this.fMemberTypeCache.get(getCacheKey(baselineid, componentid, getRootName(identifier)));
198                                                if(mcache != null) {
199                                                        return (IApiElement) mcache.get(identifier);
200                                                }
201                                        }
202                                }
203                                else {
204                                        if(this.fRootCache != null) {
205                                                Cache compcache = (Cache) fRootCache.get(baselineid);
206                                                if(compcache != null) {
207                                                        Cache typecache = (Cache) compcache.get(componentid);
208                                                        if(typecache != null && identifier != null) {
209                                                                return (IApiElement) typecache.get(identifier);
210                                                        }
211                                                }
212                                        }
213                                }
214                                break;
215                        }
216                }
217                return null;
218        }
219        
220        /**
221         * Removes the {@link IApiElement} from the given component (given its id) with
222         * the given identifier and of the given type.
223         * 
224         * @param componentid the id of the component the element resides in
225         * @param identifier the id (name) of the element to remove
226         * @param type the type of the element (TYPE, METHOD, FIELD, etc)
227         * 
228         * @return true if the element was removed, false otherwise
229         */
230        public boolean removeElementInfo(String baselineid, String componentid, String identifier, int type) {
231                if(baselineid == null) {
232                        return false;
233                }
234                switch(type) {
235                        case IApiElement.TYPE: {
236                                if(componentid != null && identifier != null) {
237                                        boolean removed = true;
238                                        //clean member type cache
239                                        if(this.fMemberTypeCache != null) {
240                                                if(isMemberType(identifier)) {
241                                                        Cache mcache = (Cache) this.fMemberTypeCache.get(getCacheKey(baselineid, componentid, getRootName(identifier)));
242                                                        if(mcache != null) {
243                                                                return mcache.remove(identifier) != null;
244                                                        }
245                                                }
246                                                else {
247                                                        this.fMemberTypeCache.remove(getCacheKey(baselineid, componentid, getRootName(identifier)));
248                                                }
249                                        }
250                                        if(fRootCache != null) {
251                                                Cache compcache = (Cache) fRootCache.get(baselineid);
252                                                if(compcache != null) {
253                                                        Cache typecache = (Cache) compcache.get(componentid);
254                                                        if(typecache != null) {
255                                                                removed &= typecache.remove(identifier) != null;
256                                                                if(typecache.isEmpty()) {
257                                                                        removed &= compcache.remove(componentid) != null;
258                                                                }
259                                                                if(compcache.isEmpty()) {
260                                                                        removed &= fRootCache.remove(baselineid) != null;
261                                                                }
262                                                                return removed;
263                                                        }
264                                                        
265                                                }
266                                        }
267                                        else {
268                                                return false;
269                                        }
270                                }
271                                break;
272                        }
273                        case IApiElement.COMPONENT: {
274                                flushMemberCache();
275                                if(fRootCache != null && componentid != null) {
276                                        Cache compcache = (Cache) fRootCache.get(baselineid);
277                                        if(compcache != null) {
278                                                boolean removed = compcache.remove(componentid) != null;
279                                                if(compcache.isEmpty()) {
280                                                        removed &= fRootCache.remove(baselineid) != null;
281                                                }
282                                                return removed;
283                                        }
284                                }
285                                break;
286                        }
287                        case IApiElement.BASELINE: {
288                                flushMemberCache();
289                                if(fRootCache != null) {
290                                        return fRootCache.remove(baselineid) != null;
291                                }
292                                break;
293                        }
294                }
295                return false;
296        }
297        
298        /**
299         * Removes the given {@link IApiElement} info from the cache and returns it if present
300         * @param element
301         * @return true if the {@link IApiElement} was removed false otherwise
302         * @throws CoreException if there is a problem accessing any of the {@link IApiElement} info
303         * in order to remove it from the cache - pass the exception along.
304         */
305        public boolean removeElementInfo(IApiElement element) {
306                if(element == null) {
307                        return false;
308                }
309                 switch(element.getType()) {
310                        case IApiElement.COMPONENT:
311                        case IApiElement.TYPE: {
312                                if(fRootCache != null) {
313                                        IApiComponent comp = element.getApiComponent();
314                                        if(comp != null) {
315                                                try {
316                                                        IApiBaseline baseline = comp.getBaseline();
317                                                        return removeElementInfo(baseline.getName(), comp.getId(), element.getName(), element.getType());
318                                                }
319                                                catch(CoreException ce) {}
320                                        }
321                                }
322                                break;
323                        }
324                        case IApiElement.BASELINE: {
325                                flushMemberCache();
326                                if(fRootCache != null) {
327                                        IApiBaseline baseline = (IApiBaseline) element;
328                                        return fRootCache.remove(baseline.getName()) != null;
329                                }
330                                break;
331                        }
332                }
333                return false;
334        }
335        
336        /**
337         * Clears out all cached information.
338         */
339        public void flushCaches() {
340                if(fRootCache != null) {
341                        fRootCache.flush();
342                }
343                flushMemberCache();
344        }
345        
346        /**
347         * Flushes the cache of member types
348         */
349        private void flushMemberCache() {
350                if(this.fMemberTypeCache != null) {
351                        this.fMemberTypeCache.flush();
352                }
353        }
354        
355        /**
356         * Returns if the cache has any elements in it or not
357         * 
358         * @return true if the cache has no entries, false otherwise
359         */
360        public boolean isEmpty() {
361                boolean empty = true;
362                if(fRootCache != null) {
363                        empty &= fRootCache.isEmpty();
364                }
365                if(this.fMemberTypeCache != null) {
366                        empty &= this.fMemberTypeCache.isEmpty();
367                }
368                return empty;
369        }
370}

[all classes][org.eclipse.pde.api.tools.internal.model]
EMMA 2.0.5312 EclEmma Fix 1 (C) Vladimir Roubtsov