/******************************************************************************* * Copyright (c) 2008 Ralf Ebert * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ralf Ebert - initial API and implementation *******************************************************************************/ package com.swtxml.util.context; import java.util.ArrayList; import java.util.List; import com.swtxml.adapter.IAdaptable; /** * Context is a threadlocal list of adapter objects. This is used while parsing * or processing nodes if context information is required but the object needing * the information is not responsible for obtaining it. Then some outer object * needs to establish the Context by calling Context.addAdapter(). * * @author Ralf Ebert <info@ralfebert.de> */ public class Context { private static final ThreadLocal<Context> context = new ThreadLocal<Context>(); private final List<IAdaptable> adapters; Context() { this.adapters = new ArrayList<IAdaptable>(); } Context(Context ctx) { this.adapters = new ArrayList<IAdaptable>(ctx.adapters); } public static void dump() { System.out.println(context.get()); } /** * Checks if an adapter to clazz is available in this context. Returns this * adapter or null if none available. */ @SuppressWarnings("unchecked") public static <A> A adaptTo(Class<A> clazz) { Context ctx = context.get(); if (ctx == null) { return null; } for (IAdaptable adapter : ctx.adapters) { Object obj = adapter.getAdapter(clazz); if (obj != null) { return (A) obj; } } return null; } /** * Makes the context adaptable using the given adapter object. Calls to * Context.adaptTo will be delegated to all added adapter adaptTo methods. */ public static void addAdapter(IAdaptable adapter) { Context ctx = context.get(); if (ctx == null) { ctx = new Context(); context.set(ctx); } ctx.adapters.add(adapter); } /** * Runs the given runnable with an inner Context. You will see everything * which was in the outer (original) Context, but changes will be only * visible in the inner context. */ public static void runWith(Runnable runnable) { Context oldContext = Context.context.get(); if (oldContext != null) { Context.context.set(new Context(oldContext)); } try { runnable.run(); } finally { Context.context.set(oldContext); } } public static void clear() { context.set(null); } @Override public String toString() { return "Context[" + adapters + "]"; } }