//# 0 errors, 108 messages
//#
/*
    //#ServerStatus.java:1:1: class: com.dmdirc.ServerStatus
    //#ServerStatus.java:1:1: method: com.dmdirc.ServerStatus.com.dmdirc.ServerStatus__static_init
 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.dmdirc;

import com.dmdirc.util.RollingList;

/**
 * Describes the status of a server and manages transitions between different
 * states.
 *
 * @since 0.6.3m1
 * @author chris
 */
public class ServerStatus {
    //#ServerStatus.java:34: method: void com.dmdirc.ServerStatus.com.dmdirc.ServerStatus()
    //#input(void com.dmdirc.ServerStatus()): com/dmdirc/ServerState.DISCONNECTED
    //#input(void com.dmdirc.ServerStatus()): this
    //#output(void com.dmdirc.ServerStatus()): new RollingList(ServerStatus#1) num objects
    //#output(void com.dmdirc.ServerStatus()): this.history
    //#output(void com.dmdirc.ServerStatus()): this.state
    //#new obj(void com.dmdirc.ServerStatus()): new RollingList(ServerStatus#1)
    //#post(void com.dmdirc.ServerStatus()): this.history == &new RollingList(ServerStatus#1)
    //#post(void com.dmdirc.ServerStatus()): this.state == &com.dmdirc.ServerState__static_init.new ServerState(ServerState__static_init#7)
    //#post(void com.dmdirc.ServerStatus()): new RollingList(ServerStatus#1) num objects == 1

    /** The current state of the server. */
    protected ServerState state = ServerState.DISCONNECTED;

    /** A history of transactions for debugging purposes. */
    protected RollingList<String> history = new RollingList<String>(10);
    //#ServerStatus.java:40: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.RollingList(int)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ServerStatus
    //#    method: void com.dmdirc.ServerStatus()
    //#    unanalyzed callee: void com.dmdirc.util.RollingList(int)
    //#ServerStatus.java:40: end of method: void com.dmdirc.ServerStatus.com.dmdirc.ServerStatus()

    /**
     * Transitions the status of this object to the specified state.
     *
     * @param newState The state to transition to
     */
    public synchronized void transition(final ServerState newState) {
        addHistoryEntry(state, newState);
    //#ServerStatus.java:48: method: void com.dmdirc.ServerStatus.transition(ServerState)
    //#input(void transition(ServerState)): " ["._tainted
    //#input(void transition(ServerState)): "->"._tainted
    //#input(void transition(ServerState)): "Illegal server state transition&#10;&#10;"._tainted
    //#input(void transition(ServerState)): __Descendant_Table[com/dmdirc/ServerStatus]
    //#input(void transition(ServerState)): __Descendant_Table[others]
    //#input(void transition(ServerState)): __Dispatch_Table.addHistoryEntry(Lcom/dmdirc/ServerState;Lcom/dmdirc/ServerState;)V
    //#input(void transition(ServerState)): __Dispatch_Table.getTransitionHistory()Ljava/lang/String;
    //#input(void transition(ServerState)): newState
    //#input(void transition(ServerState)): newState.transitions
    //#input(void transition(ServerState)): this
    //#input(void transition(ServerState)): this.__Tag
    //#input(void transition(ServerState)): this.history
    //#input(void transition(ServerState)): this.state
    //#input(void transition(ServerState)): this.state.transitions
    //#output(void transition(ServerState)): this.state
    //#pre[1] (void transition(ServerState)): newState != null
    //#pre[4] (void transition(ServerState)): this.state != null
    //#pre[7] (void transition(ServerState)): this.__Tag == com/dmdirc/ServerStatus
    //#pre[8] (void transition(ServerState)): this.history != null
    //#pre[9] (void transition(ServerState)): this.state.transitions != null
    //#presumption(void transition(ServerState)): java.util.List:contains(...)@101 == 1
    //#post(void transition(ServerState)): this.state == newState
    //#post(void transition(ServerState)): this.state != null
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:com.dmdirc.util.RollingList:getList
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.lang.StringBuilder:length
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:com.dmdirc.ServerState:name
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.lang.Thread:currentThread
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.lang.Thread:getStackTrace
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.lang.StackTraceElement:toString
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.lang.Thread:getName
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:com.dmdirc.util.RollingList:add
    //#unanalyzed(void transition(ServerState)): Effects-of-calling:java.util.List:contains

        if (state.canTransitionTo(newState)) {
            state = newState;

            synchronized (this) {
                notifyAll();
            }
        } else {
            throw new IllegalArgumentException("Illegal server state "
                    + "transition\n\n" + getTransitionHistory());
        }
    }
    //#ServerStatus.java:60: end of method: void com.dmdirc.ServerStatus.transition(ServerState)

    /**
     * Retrieves the current state of this status object.
     *
     * @return This object's current state
     */
    public synchronized ServerState getState() {
        return state;
    //#ServerStatus.java:68: method: ServerState com.dmdirc.ServerStatus.getState()
    //#input(ServerState getState()): this
    //#input(ServerState getState()): this.__Lock
    //#input(ServerState getState()): this.state
    //#output(ServerState getState()): return_value
    //#pre[2] (ServerState getState()): init'ed(this.state)
    //#post(ServerState getState()): return_value == this.state
    //#post(ServerState getState()): init'ed(return_value)
    //#ServerStatus.java:68: end of method: ServerState com.dmdirc.ServerStatus.getState()
    }

    /**
     * Adds a history entry to this status object. The history entry contains
     * the name of the states being transitioned between, the details of the
     * method (and class and line) which initiated the transition, and the
     * name of the thread in which the transition is occuring.
     *
     * @param fromState The state which is being transitioned from
     * @param toState The state which is being transitioned to
     */
    protected void addHistoryEntry(final ServerState fromState, final ServerState toState) {
        final StringBuilder builder = new StringBuilder();
    //#ServerStatus.java:81: method: void com.dmdirc.ServerStatus.addHistoryEntry(ServerState, ServerState)
    //#input(void addHistoryEntry(ServerState, ServerState)): " ["._tainted
    //#input(void addHistoryEntry(ServerState, ServerState)): "->"._tainted
    //#input(void addHistoryEntry(ServerState, ServerState)): fromState
    //#input(void addHistoryEntry(ServerState, ServerState)): this
    //#input(void addHistoryEntry(ServerState, ServerState)): this.history
    //#input(void addHistoryEntry(ServerState, ServerState)): toState
    //#pre[1] (void addHistoryEntry(ServerState, ServerState)): fromState != null
    //#pre[3] (void addHistoryEntry(ServerState, ServerState)): this.history != null
    //#pre[4] (void addHistoryEntry(ServerState, ServerState)): toState != null
    //#presumption(void addHistoryEntry(ServerState, ServerState)): java.lang.Thread:currentThread(...)@86 != null
    //#presumption(void addHistoryEntry(ServerState, ServerState)): java.lang.Thread:currentThread(...)@88 != null
    //#presumption(void addHistoryEntry(ServerState, ServerState)): java.lang.Thread:getStackTrace(...).length@86 >= 4
    //#presumption(void addHistoryEntry(ServerState, ServerState)): java.lang.Thread:getStackTrace(...)@86 != null
    //#presumption(void addHistoryEntry(ServerState, ServerState)): java.lang.Thread:getStackTrace(...)[3]@86 != null
        builder.append(fromState.name());
    //#ServerStatus.java:82: Warning: method not available - call not analyzed
    //#    call on String com.dmdirc.ServerState:name()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ServerStatus
    //#    method: void addHistoryEntry(ServerState, ServerState)
    //#    unanalyzed callee: String com.dmdirc.ServerState:name()
        builder.append("->");
        builder.append(toState.name());
    //#ServerStatus.java:84: Warning: method not available - call not analyzed
    //#    call on String com.dmdirc.ServerState:name()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ServerStatus
    //#    method: void addHistoryEntry(ServerState, ServerState)
    //#    unanalyzed callee: String com.dmdirc.ServerState:name()
        builder.append(' ');
        builder.append(Thread.currentThread().getStackTrace()[3].toString());
        builder.append(" [");
        builder.append(Thread.currentThread().getName());
        builder.append(']');

        history.add(builder.toString());
    //#ServerStatus.java:91: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.RollingList:add(Object)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ServerStatus
    //#    method: void addHistoryEntry(ServerState, ServerState)
    //#    unanalyzed callee: bool com.dmdirc.util.RollingList:add(Object)
    }
    //#ServerStatus.java:92: end of method: void com.dmdirc.ServerStatus.addHistoryEntry(ServerState, ServerState)

    /**
     * Retrieves the transition history of this status object as a string.
     *
     * @see #addHistoryEntry(com.dmdirc.ServerState, com.dmdirc.ServerState)
     * @return A line feed ('\n') delimited string containing one entry for
     * each of the entries in this status's transition history.
     */
    public String getTransitionHistory() {
        final StringBuilder builder = new StringBuilder();
    //#ServerStatus.java:102: method: String com.dmdirc.ServerStatus.getTransitionHistory()
    //#input(String getTransitionHistory()): this
    //#input(String getTransitionHistory()): this.history
    //#output(String getTransitionHistory()): java.lang.StringBuilder:toString(...)._tainted
    //#output(String getTransitionHistory()): return_value
    //#new obj(String getTransitionHistory()): java.lang.StringBuilder:toString(...)
    //#pre[2] (String getTransitionHistory()): this.history != null
    //#presumption(String getTransitionHistory()): com.dmdirc.util.RollingList:getList(...)@104 != null
    //#post(String getTransitionHistory()): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(String getTransitionHistory()): return_value == &java.lang.StringBuilder:toString(...)
    //#test_vector(String getTransitionHistory()): java.lang.StringBuilder:length(...)@105: {-2_147_483_648..0}, {1..4_294_967_295}
    //#test_vector(String getTransitionHistory()): java.util.Iterator:hasNext(...)@104: {0}, {1}

        for (String line : history.getList()) {
    //#ServerStatus.java:104: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.RollingList:getList()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ServerStatus
    //#    method: String getTransitionHistory()
    //#    unanalyzed callee: List com.dmdirc.util.RollingList:getList()
            if (builder.length() > 0) {
                builder.append('\n');
            }

            builder.append(line);
        }

        return builder.toString();
    //#ServerStatus.java:112: end of method: String com.dmdirc.ServerStatus.getTransitionHistory()
    }

}
    //#output(com.dmdirc.ServerStatus__static_init): __Descendant_Table[com/dmdirc/ServerStatus]
    //#output(com.dmdirc.ServerStatus__static_init): __Dispatch_Table.addHistoryEntry(Lcom/dmdirc/ServerState;Lcom/dmdirc/ServerState;)V
    //#output(com.dmdirc.ServerStatus__static_init): __Dispatch_Table.getState()Lcom/dmdirc/ServerState;
    //#output(com.dmdirc.ServerStatus__static_init): __Dispatch_Table.getTransitionHistory()Ljava/lang/String;
    //#output(com.dmdirc.ServerStatus__static_init): __Dispatch_Table.transition(Lcom/dmdirc/ServerState;)V
    //#post(com.dmdirc.ServerStatus__static_init): __Descendant_Table[com/dmdirc/ServerStatus] == &__Dispatch_Table
    //#post(com.dmdirc.ServerStatus__static_init): __Dispatch_Table.addHistoryEntry(Lcom/dmdirc/ServerState;Lcom/dmdirc/ServerState;)V == &addHistoryEntry
    //#post(com.dmdirc.ServerStatus__static_init): __Dispatch_Table.getState()Lcom/dmdirc/ServerState; == &getState
    //#post(com.dmdirc.ServerStatus__static_init): __Dispatch_Table.getTransitionHistory()Ljava/lang/String; == &getTransitionHistory
    //#post(com.dmdirc.ServerStatus__static_init): __Dispatch_Table.transition(Lcom/dmdirc/ServerState;)V == &transition
    //#ServerStatus.java:: end of method: com.dmdirc.ServerStatus.com.dmdirc.ServerStatus__static_init
    //#ServerStatus.java:: end of class: com.dmdirc.ServerStatus
