1 cananian 1.1 // GenericContextFactory.java, created Tue Feb 26 03:57:04 2002 by cananian 2 cananian 1.1 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1 package harpoon.Analysis; 5 cananian 1.1 6 cananian 1.1 import java.util.Arrays; 7 cananian 1.1 import java.util.Collections; 8 cananian 1.1 import java.util.HashMap; 9 cananian 1.1 import java.util.List; 10 cananian 1.1 import java.util.Map; 11 cananian 1.1 /** 12 cananian 1.1 * A <code>GenericContextFactory</code> can create <code>Context</code> 13 cananian 1.1 * objects for any desired level of context-sensitivity. 14 cananian 1.1 * The context-sensitivity and caching behavior is specified in the 15 cananian 1.1 * <code>GenericContextFactory</code>'s constructor. 16 cananian 1.1 * 17 cananian 1.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 18 cananian 1.4 * @version $Id: GenericContextFactory.java,v 1.4 2004/02/08 01:49:03 cananian Exp $ 19 cananian 1.1 * @see Context 20 cananian 1.1 */ 21 cananian 1.3 public class GenericContextFactory<E> { 22 cananian 1.1 private final int CONTEXT_SENSITIVITY; 23 cananian 1.3 private final Map<Context<E>,Context<E>> cache; 24 cananian 1.3 private final Context<E> root; 25 cananian 1.1 26 cananian 1.1 /** Creates a <code>GenericContextFactory</code>. */ 27 cananian 1.1 public GenericContextFactory(int context_sensitivity, boolean use_cache) { 28 cananian 1.1 this.CONTEXT_SENSITIVITY = context_sensitivity; 29 cananian 1.3 this.cache = use_cache ? new HashMap<Context<E>,Context<E>>() : null; 30 cananian 1.1 this.root = new ContextImpl(); 31 cananian 1.1 if (this.cache!=null) 32 cananian 1.1 cache.put(this.root, this.root); 33 cananian 1.1 } 34 cananian 1.3 // XXX should return a bivariant context; adding something to it 35 cananian 1.3 // will make the context invariant. 36 cananian 1.3 public Context<E> makeEmptyContext() { return root; } 37 cananian 1.1 38 cananian 1.3 private class ContextImpl extends Context<E> { 39 cananian 1.3 final E[] items; 40 cananian 1.3 List<E> cached_list = null; 41 cananian 1.4 ContextImpl() { this((E[])new Object[0]); } 42 cananian 1.3 ContextImpl(E[] items) { this.items = items; } 43 cananian 1.3 public Context<E> addElement(E o) { 44 cananian 1.1 // truncate context at CONTEXT_SENSITIVITY items. 45 cananian 1.4 E[] nitems = (E[]) 46 cananian 1.4 new Object[Math.min(CONTEXT_SENSITIVITY, items.length+1)]; 47 cananian 1.1 if (nitems.length>0) 48 cananian 1.1 nitems[nitems.length-1] = o; 49 cananian 1.1 if (nitems.length>1) 50 cananian 1.2 System.arraycopy(items, items.length-(nitems.length-1), 51 cananian 1.2 nitems, 0, nitems.length-1); 52 cananian 1.3 Context<E> nc = new ContextImpl(nitems); 53 cananian 1.1 // maybe cache. 54 cananian 1.1 if (cache!=null) 55 cananian 1.1 if (!cache.containsKey(nc)) 56 cananian 1.1 cache.put(nc, nc); 57 cananian 1.1 else 58 cananian 1.3 nc = cache.get(nc); 59 cananian 1.1 // ta-da! 60 cananian 1.1 return nc; 61 cananian 1.1 } 62 cananian 1.3 public List<E> asList() { 63 cananian 1.3 List<E> l = cached_list; 64 cananian 1.1 if (l==null) { 65 cananian 1.1 l = Collections.unmodifiableList(Arrays.asList(items)); 66 cananian 1.1 if (cache!=null) 67 cananian 1.1 cached_list = l; 68 cananian 1.1 } 69 cananian 1.1 return l; 70 cananian 1.1 } 71 cananian 1.1 } 72 cananian 1.1 }