EnabledManager -- improved -- by Erik van Oosten

This code accompanies the article Evaluating Simon.

Quick download link:
EnabledManager -- improved --.java

package org.javasimon;

import org.javasimon.utils.SimonUtils;

import java.util.Map;
import java.util.HashMap;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * EnabledManager implements methods called from SimonManager if the Simon API is enabled.
 *
 * @author <a href="mailto:virgo47@gmail.com">Richard "Virgo" Richter</a>
 * @created Aug 16, 2008
 */
class EnabledManager implements Manager {
	static final Manager INSTANCE = new EnabledManager();

	private static final int clientCodeStackIndex;

	private final ConcurrentMap<String, AbstractSimon> allSimons =
            new ConcurrentHashMap<String, AbstractSimon>(1000, 0.7f, 50);

	private UnknownSimon rootSimon;

	static {
		int i = 1;
		for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
			i++;
			if (ste.getClassName().equals(EnabledManager.class.getName())) {
				break;
			}
		}
		clientCodeStackIndex = i;
	}

	/**
	 * {@inheritDoc}
	 */
	public Simon getSimon(String name) {
		return allSimons.get(name);
	}

	/**
	 * {@inheritDoc}
	 */
	public synchronized void destroySimon(String name) {
		if (name.equals(SimonManager.ROOT_SIMON_NAME)) {
			throw new SimonException("Root Simon cannot be destroyed!");
		}
		AbstractSimon simon = allSimons.remove(name);
		if (simon.getChildren().size() > 0) {
			replaceSimon(simon, UnknownSimon.class);
		} else {
			((AbstractSimon) simon.getParent()).replaceChild(simon, null);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public synchronized void clear() {
		allSimons.clear();
		rootSimon = new UnknownSimon(SimonManager.ROOT_SIMON_NAME);
		allSimons.put(SimonManager.ROOT_SIMON_NAME, rootSimon);
	}

	/**
	 * {@inheritDoc}
	 */
	public synchronized Counter getCounter(String name) {
		return (Counter) getOrCreateSimon(name, CounterImpl.class);
	}

	/**
	 * {@inheritDoc}
	 */
	public Stopwatch getStopwatch(String name) {
        Stopwatch stopwatch = (Stopwatch) allSimons.get(name);
        if (stopwatch != null) {
            return stopwatch;
        } else {
            return (Stopwatch) getOrCreateSimon(name, StopwatchImpl.class);
        }
    }

	/**
	 * {@inheritDoc}
	 */
	public synchronized UnknownSimon getUnknown(String name) {
		return (UnknownSimon) getOrCreateSimon(name, UnknownSimon.class);
	}

	/**
	 * {@inheritDoc}
	 */
	public String generateName(String suffix, boolean includeMethodName) {
		StackTraceElement stackElement = Thread.currentThread().getStackTrace()[clientCodeStackIndex];
		StringBuilder nameBuilder = new StringBuilder(stackElement.getClassName());
		if (includeMethodName) {
			nameBuilder.append('.').append(stackElement.getMethodName());
		}
		if (suffix != null) {
			nameBuilder.append(suffix);
		}
		return nameBuilder.toString();
	}

	/**
	 * {@inheritDoc}
	 */
	public Simon getRootSimon() {
		return rootSimon;
	}

	/**
	 * {@inheritDoc}
	 */
	public Collection<String> simonNames() {
		return allSimons.keySet();
	}

	// name can be null in case of "anonymous" Simons
	private synchronized Simon getOrCreateSimon(String name, Class<? extends AbstractSimon> simonClass) {
		AbstractSimon simon = null;
		if (name != null) {
			if (name.equals(SimonManager.ROOT_SIMON_NAME)) {
				throw new SimonException("Root Simon cannot be replaced or recreated!");
			}
			simon = allSimons.get(name);
		}
		if (simon == null) {
			if (name != null && !SimonUtils.checkName(name)) {
				throw new SimonException("Simon name must match following pattern: '" + SimonUtils.NAME_PATTERN.pattern() + '\'');
			}
			simon = newSimon(name, simonClass);
		} else if (simon instanceof UnknownSimon) {
			simon = replaceSimon(simon, simonClass);
		} else {
			if (!(simonClass.isInstance(simon))) {
				throw new SimonException("Simon named '" + name + "' already exists and its type is '" + simon.getClass().getName() + "' while requested type is '" + simonClass.getName() + "'.");
			}
		}
		return simon;
	}

	private AbstractSimon replaceSimon(AbstractSimon simon, Class<? extends AbstractSimon> simonClass) {
		AbstractSimon newSimon = instantiateSimon(simon.getName(), simonClass);
		newSimon.enabled = simon.enabled;

		// fixes parent link and parent's children list
		((AbstractSimon) simon.getParent()).replaceChild(simon, newSimon);

		// fixes children list and all children's parent link
		for (Simon child : simon.getChildren()) {
			newSimon.addChild((AbstractSimon) child);
			((AbstractSimon) child).setParent(newSimon);
		}

		allSimons.put(simon.getName(), newSimon);
		return newSimon;
	}

	private AbstractSimon newSimon(String name, Class<? extends AbstractSimon> simonClass) {
		AbstractSimon simon = instantiateSimon(name, simonClass);
		if (name != null) {
			addToHierarchy(simon, name);
		}
		return simon;
	}

	private AbstractSimon instantiateSimon(String name, Class<? extends AbstractSimon> simonClass) {
		AbstractSimon simon;
		try {
			Constructor<? extends AbstractSimon> constructor = simonClass.getDeclaredConstructor(String.class);
			simon = constructor.newInstance(name);
		} catch (NoSuchMethodException e) {
			throw new SimonException(e);
		} catch (InvocationTargetException e) {
			throw new SimonException(e);
		} catch (IllegalAccessException e) {
			throw new SimonException(e);
		} catch (InstantiationException e) {
			throw new SimonException(e);
		}
		return simon;
	}

	private void addToHierarchy(AbstractSimon simon, String name) {
		int ix = name.lastIndexOf(SimonManager.HIERARCHY_DELIMITER);
		AbstractSimon parent = rootSimon;
		if (ix != -1) {
			String parentName = name.substring(0, ix);
			parent = allSimons.get(parentName);
			if (parent == null) {
				parent = new UnknownSimon(parentName);
				addToHierarchy(parent, parentName);
			}
		}
		parent.addChild(simon);
        allSimons.put(name, simon);
	}
}