Package net.sf.jiga.xtended.kernel

Source Code of net.sf.jiga.xtended.kernel.DebugMap

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.sf.jiga.xtended.kernel;

import java.io.PrintStream;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.sf.jiga.xtended.JXAException;
import net.sf.jiga.xtended.ui.Ant;

/**
*
*
* This maps all registered Debugger's management, so that enabling
* JXAenvUtils._debug can be reflected to all registered Debugger's, also it can
* dis/enable each Debugger seperately.
* {@linkplain #associateJXADebug(Class)}, {@linkplain #associateJXADebugSys(Class)}
* or {@linkplain #associateDebugLevel(Class)} to initialize debugging level for
* a defined Class
* {@linkplain #setDebugLevelEnabled(boolean, Class)}, {@linkplain #setJXADebugSysEnabled(boolean, Class)}
* or {@linkplain #setDebuggerEnabled(boolean, Class, Level)} to enable/disable
* debug level NOTICE : methods named *Debug* are related to jxa.debug property,
* and those named *DebugSys* to jxa.debugSys property. The *Debugger* ones are
* for Level's of debugging generated by {@linkplain #newDebugLevel()}.
*
* @author www.b23prodtm.info
*
*/
public class DebugMap {

    private class SoftDebugger extends SoftReference {

        final String className;

        /**
         *
         */
        public SoftDebugger(Class<? extends Debugger> d) {
            super(d, refQueue);
            this.className = d.getName();
        }
    }
    private BigBitStack bits = new BigBitStack();
    private Level jxaDebug = newDebugLevel();
    private Level jxaDebugSys = newDebugLevel();
    /**
     *
     * @see Ant#JXA_DEBUG_VOID
     */
    public Level _VOID = newDebugLevel(), _SYS = jxaDebugSys, _JXA = jxaDebug;
    /**
     * global debugger bitmap
     */
    private Level bitMap = Level.NoDebug;
    /**
     * running classes
     */
    private Map<String, SoftDebugger> instances = Collections.synchronizedMap(new HashMap<String, SoftDebugger>());
    /**
     * associated classes to level
     */
    private Map<String, Level> instancesClass = Collections.synchronizedMap(new HashMap<String, Level>());
    private ReferenceQueue refQueue = new ReferenceQueue();

    private DebugMap() {
    }
    private static DebugMap _instance = _getInstance();

    private Level getJXADebugState() {
        return (JXAenvUtils._debug ? jxaDebug : Level.NoDebug).or(JXAenvUtils._debugSys ? jxaDebugSys : Level.NoDebug).or(JXAenvUtils._getSysBoolean(Ant.JXA_DEBUG_VOID) ? _VOID : Level.NoDebug);
    }

    private void cleanup() {
        SoftDebugger sd = null;
        while ((sd = (SoftDebugger) refQueue.poll()) != null) {
            instances.remove(sd.className);
            instancesClass.remove(sd.className);
        }
    }

    /**
     * whole associated bitmap for that debugger
     */
    private Level bitMap(Class<? extends Debugger> d) {
        Level lvl = instancesClass.get(d.getName());
        if (lvl != null) {
            return lvl;
        } else {
            return Level.NoDebug;
        }
    }

    /**
     * associated bits for that debugger and level
     */
    private Level levelBits(Class<? extends Debugger> d, Level level) {
        Level lvl = bitMap(d);
        return lvl.and(new Level(bits._getMask(level.n)).or(level));
    }

    /**
     * defined level for debugger
     *
     * @return true if and only if the debugger is associated to Level and the
     * Debugger has not been disabled
     */
    private boolean isDebuggerEnabled(Class<? extends Debugger> d, Level level) {
        Level b = levelBits(d, level);
        /*
         * compare associated bitmap against current state bitmap
         */
        Level r = bitMap.or(getJXADebugState()).and(b);
        /*
         * either associated level is enabled or the debugger is enabled with
         * that level
         */
        return !r.equals(Level.NoDebug);
    }

    /**
     * defined level
     *
     * @param level
     * @return
     */
    public boolean isDebugLevelEnabled(Level level) {
        return bitMap.or(getJXADebugState()).and(level).equals(level);
    }

    /**
     * specified debugger only (on associated level if it exists)
     *
     * @param enable
     * @param d
     */
    public void setDebuggerEnabled(boolean enable, Class<? extends Debugger> d) {
        Level level = bitMap(d);
        setDebuggerEnabled(enable, d, level.equals(Level.NoDebug) ? newDebugLevel() : level);
    }

    /**
     * defines the debugger at specified level
     *
     * @param enable
     * @param d
     * @param level
     */
    public void setDebuggerEnabled(boolean enable, Class<? extends Debugger> d, Level level) {
        Level lvl = Level.NoDebug;
        cleanup();
        assert !new Level(bits._getAllBitRanges()).and(level).equals(Level.NoDebug) : "no valid level (use newDebugLevel() as level)";
        /**
         * just add/remove the "finger-print" of this Debugger according to the
         * selected level in bitmap
         */
        if (enable) {
            associateDebugLevel(d, level);
            lvl = levelBits(d, level);
            bitMap = bitMap.or(new Level(bits._getAllBits()).and(lvl));
            if (isDebugLevelEnabled(_VOID)) {
                System.out.println("enabled debugger " + d.getSimpleName());
            }
        } else {
            deassociateDebugLevel(d, level);
            lvl = levelBits(d, level);
            bitMap = bitMap.andNot(new Level(bits._getAllBits()).and(lvl));
            if (isDebugLevelEnabled(_VOID)) {
                System.out.println("disabled debugger " + d.getSimpleName());
            }
        }
    }

    /**
     * dis/enable a defined level
     *
     * @param enable
     * @param level
     */
    public void setDebugLevelEnabled(boolean enable, Level level) {
        /**
         * add/remove the level range in bitmap
         */
        if (enable) { /*
             * enable Level bit
             */

            bitMap = bitMap.or(level.and(new Level(bits._getAllBitRanges())));
            if (isDebugLevelEnabled(_VOID)) {
                System.out.println("enabled debuglevel " + level.toString());
            }
        } else { /*
             * remove whole level and associated (mask) bits
             */

            bitMap = bitMap.andNot(new Level(bits._getMask(level.n)).or(level));
        }
        if (isDebugLevelEnabled(_VOID)) {
            System.out.println("disabled debuglevel " + level.toString());
        }
    }

    /**
     * @return
     */
    public final static DebugMap _getInstance() {
        return _instance != null ? _instance : (_instance = new DebugMap());
    }

    /**
     * defines a new custom level (store it as a final int !)
     *
     * @return
     */
    public Level newDebugLevel() {
        return newDebugLevel(null);
    }

    /**
     * defines a new custom level (store it as a final int !) and associate the
     * specified Class to it, so that whenever the debugLevel is enabled, this
     * class is set as debugged too.
     *
     * @return
     */
    public Level newDebugLevel(Class<? extends Debugger> clazz) {
        Level l = new Level(bits._newBitRange());
        if (clazz != null) {
            associateDebugLevel(clazz, l);
        }
        return l;
    }

    /**
     * JXAenvUtils._debug level
     *
     * @param d
     * @return
     * @deprecated #isJXADebugEnabled(Class)
     */
    public boolean isJXADebugEnabled(Debugger d) {
        return isDebuggerEnabled(d.getClass(), jxaDebug);
    }

    /**
     * JXAenvUtils._debugSys level
     *
     * @param d
     * @return
     * @deprecated #isJXADebugSysEnabled(Class)
     */
    public boolean isJXADebugSysEnabled(Debugger d) {
        return isDebuggerEnabled(d.getClass(), jxaDebugSys);
    }

    /**
     * JXAenvUtils._debug level
     *
     * @param b
     * @param d
     */
    public void setJXADebugEnabled(boolean b, Class<? extends Debugger> d) {
        setDebuggerEnabled(b, d, jxaDebug);
    }

    /**
     * JXAenvUtils._debugSys level
     *
     * @param b
     * @param d
     */
    public void setJXADebugSysEnabled(boolean b, Class<? extends Debugger> d) {
        setDebuggerEnabled(b, d, jxaDebugSys);
    }

    /**
     * JXAenvUtils._debug level
     *
     * @param b
     */
    public void setJXADebugEnabled(boolean b) {
        setDebugLevelEnabled(b, jxaDebug);
    }

    /**
     * JXAenvUtils._debugSys level
     *
     * @param b
     */
    public void setJXADebugSysEnabled(boolean b) {
        setDebugLevelEnabled(b, jxaDebugSys);
    }

    /**
     * JXAenvUtils._debug level
     *
     * @return
     */
    public boolean isJXADebugEnabled() {
        return isDebugLevelEnabled(jxaDebug);
    }

    /**
     * JXAenvUtils._debugSys level
     *
     * @return
     */
    public boolean isJXADebugSysEnabled() {
        return isDebugLevelEnabled(jxaDebugSys);
    }

    /**
     * JXAenvUtils._debug level
     *
     * @param d
     * @return
     */
    public boolean isJXADebugEnabled(Class<? extends Debugger> d) {
        return isDebuggerEnabled(d, jxaDebug);
    }

    /**
     * JXAenvUtils._debugSys level
     *
     * @param d
     * @return
     */
    public boolean isJXADebugSysEnabled(Class<? extends Debugger> d) {
        return isDebuggerEnabled(d, jxaDebugSys);
    }

    /**
     * any level
     *
     * @param d
     * @return
     */
    public boolean isDebuggerEnabled(Class<? extends Debugger> d) {
        return isDebuggerEnabled(d, new Level(bits._getAllBitRanges()));
    }

    /**
     * will dis/enable Debugger at JXAenvUtils._debug level it registers the
     * Debugger and links it to the {@linkplain JXAenvUtils#_debug} state
     *
     * @param enable
     * @param d
     * @deprecated #setJXADebugEnabled(boolean, Class)
     */
    public void setJXADebugEnabled(boolean enable, Debugger d) {
        setDebuggerEnabled(enable, d.getClass(), jxaDebug);
    }

    /**
     * will dis/enable Debugger at JXAenvUtils._debugSys level it registers
     * Debugger and links it to the {@linkplain JXAenvUtils#_debugSys} (kernel
     * debug) state
     *
     * @param b
     * @param d
     * @deprecated #setJXADebugSysEnabled(boolean, Class)
     */
    public void setJXADebugSysEnabled(boolean b, Debugger d) {
        setDebuggerEnabled(b, d.getClass(), jxaDebugSys);
    }

    /**
     * @param d
     */
    public void associateJXADebugSys(Class<? extends Debugger> d) {
        associateDebugLevel(d, jxaDebugSys);
    }

    /**
     * @param d
     */
    public void associateJXADebug(Class<? extends Debugger> d) {
        associateDebugLevel(d, jxaDebug);
    }
    private Set<Level> availableBits = Collections.synchronizedSet(new HashSet<Level>());

    /**
     * @return an available level bit or null if none can be found for the level
     * range
     */
    private Level findVacantLevelBits(Level level) {
        synchronized(availableBits) {
                for (Level l : availableBits) {
                        if (level.and(l).equals(level)) {
                                return l;
                        }
                }
                return null;
        }
    }

    /**
     * associate (create) level bits for the debugger
     *
     * @param d
     * @param level
     */
    public void associateDebugLevel(Class<? extends Debugger> d, Level level) {
        Level lvl = Level.NoDebug;
        if (!instancesClass.containsKey(d.getName())) {
            lvl = new Level(bits._newBit(level.n));
        } else {
            lvl = bitMap(d);
            if (lvl.and(level).equals(Level.NoDebug)) { /*
                 * find a new bit if not present
                 */

                Level newLevel = findVacantLevelBits(level);
                lvl = lvl.or(newLevel != null ? newLevel : new Level(bits._newBit(level.n)));
            }
        }
        if (isDebugLevelEnabled(_VOID)) {
            System.out.println("associated " + d.getSimpleName() + " with debuglevel " + lvl.toString());
        }
        instancesClass.put(d.getName(), lvl);
        instances.put(d.getName(), new SoftDebugger(d));
    }

    /**
     * @param d
     */
    public void deassociateJXADebugSys(Class<? extends Debugger> d) {
        deassociateDebugLevel(d, jxaDebugSys);
    }

    /**
     * @param d
     */
    public void deassociateJXADebug(Class<? extends Debugger> d) {
        deassociateDebugLevel(d, jxaDebug);
    }

    /**
     * deassociate (remove) level bits for the debugger
     *
     * @param d
     * @param level
     */
    public void deassociateDebugLevel(Class<? extends Debugger> d, Level level) {
        Level lvl = bitMap(d);
        Level lvlFree = levelBits(d, level);
        availableBits.add(lvlFree);
        instancesClass.put(d.getName(), lvl.andNot(lvlFree));
        instances.put(d.getName(), new SoftDebugger(d));
        if (isDebugLevelEnabled(_VOID)) {
            System.out.println("unassociated " + d.getSimpleName() + " with debuglevel " + lvl.toString());
        }
    }

    /**
     * TICK DEBUG LINES THAT DON'T DISPLAY EVRY FRAME
     */
    /**
     * ticktime
     */
    private long ticker = 0l, ticktime = 1000l;

    /**
     *
     * @return current tick time (delay between each tick)
     */
    public long getTickTime() {
        return ticktime;
    }

    public void setTickTime(long delay) {
        if (delay < 0) {
            throw new JXAException("no negative value please");
        }
        ticktime = delay;
    }

    private boolean print(PrintStream out, boolean newLine, String message, boolean tick) {
        long c = System.currentTimeMillis();
        boolean printed = c - ticker > ticktime;
        if (printed) {
            if (tick) {
                ticker = c;
            }
            if (newLine) {
                out.println(message);
            } else {
                out.print(message);
            }
        }
        return printed;
    }

    /**
     * @param out
     * @return true if it printed something according to the tickTime delay set.
     * @see #setTickTime(long)
     * @see #getTickTime(long)
     * @param tick set true to perform a tick (and bypass next message until it reaches the tick time)
     */
    public boolean tickPrintln(PrintStream out, String message, boolean tick) {
        return print(out, true, message, tick);
    }

    /**
     * @param out
     * @return true if it printed something according to the tickTime delay set.
     * @see #setTickTime(long)
     * @see #getTickTime(long)
     * @param tick set true to perform a tick (and bypass next message until it reaches the tick time)
     */
    public boolean tickPrint(PrintStream out, String message, boolean tick) {
        return print(out, false, message, tick);
    }

}
TOP

Related Classes of net.sf.jiga.xtended.kernel.DebugMap

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.