/** * */ package net.varkhan.base.management.config; import java.util.*; /** * <b>A delegating configuration</b> * <p/> * * @author varkhan * @date Sep 30, 2010 * @time 6:32:12 AM */ public class DelegateConfiguration implements Configuration { /** * An array of configurations, in order of decreasing priorities */ protected final Configuration[] configs; /** * Creates a new delegating configuration. * * @param configs a variadic array of configurations, in order of decreasing priorities */ public DelegateConfiguration(Configuration... configs) { this.configs=configs==null ? new Configuration[]{} : configs.clone(); } public Object get(String ctx, String key) { for(Configuration conf: configs) { if(conf!=null) { Object val=conf.get(ctx, key); if(val!=null) return val; } } return null; } public Iterable<String> contexts() { HashSet<String> ctxs = new HashSet<String>(); for(Configuration conf: configs) { if(conf!=null) for(String c: conf.contexts()) ctxs.add(c); } return ctxs; } public Configuration.Context context(String ctx) { Configuration.Context[] contexts = new Configuration.Context[configs.length]; for(int i=0;i<configs.length;i++) { Configuration conf=configs[i]; if(conf!=null) contexts[i] = conf.context(ctx); } return new Context(ctx, contexts); } protected static class Context implements Configuration.Context { protected final Configuration.Context[] contexts; protected final String ctx; public Context(String ctx, Configuration.Context... contexts) { this.ctx=ctx; this.contexts=contexts; } @Override public String name() { return ctx; } @Override public boolean has(String key) { for(Configuration.Context ctx : contexts) { if(ctx!=null&&ctx.has(key)) return true; } return false; } @Override public Object get(String key) { // Iterating through configurations in descending priority order // ensures that if a higher-priority conf had this entry, it will // be returned first. for(int i=0;i<contexts.length;) { Configuration.Context ctx=contexts[i++]; if(ctx!=null&&ctx.has(key)) return ctx.get(key); } return null; } @Override public Map<String,?> get() { Map<String,Object> map=new HashMap<String,Object>(); // Iterating through configurations in ascending priority order // ensures that if a higher-priority conf had this entry, it will // override the lower-priority ones. for(int i=contexts.length;i>0;) { Configuration.Context ctx=contexts[--i]; if(ctx!=null) map.putAll(ctx.get()); } return map; } @Override public Iterator<Configuration.Entry> iterator() { return new Iterator<Configuration.Entry>() { private final HashSet<String> seen=new HashSet<String>(); private volatile int prio=0; private volatile Iterator<Configuration.Entry> iter; private volatile Configuration.Entry last = null; @Override public boolean hasNext() { if(last!=null) return true; while(prio<contexts.length) { if(iter==null) iter = contexts[prio].iterator(); while(iter.hasNext()) { Configuration.Entry ent = iter.next(); if(!seen.contains(ent.key())) { last = ent; return true; } } iter = null; prio++; } return false; } @Override public Configuration.Entry next() { if(!hasNext()) throw new NoSuchElementException(); Configuration.Entry ent = last; seen.add(ent.key()); last = null; return ent; } @Override public void remove() { iter.remove(); last = null; } }; } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append("[").append(ctx==null?"":ctx).append("]\n"); for(Configuration.Entry e: this) { buf.append("\t").append(e.key()).append("=").append(e.value()).append("\n"); } return buf.toString(); } } }