//# 3 errors, 116 messages
//#
/*
    //#IgnoreList.java:1:1: class: com.dmdirc.IgnoreList
    //#IgnoreList.java:1:1: method: com.dmdirc.IgnoreList.com.dmdirc.IgnoreList__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.parser.irc.RegexStringList;

import java.util.ArrayList;
import java.util.List;

/**
 * Wraps around a RegexStringList to allow "simple" expressions to be used
 * instead of more complex regular expressions.
 *
 * @author chris
 */
public class IgnoreList extends RegexStringList {

    /**
     * Creates a new instance of IgnoreList.
     */
    public IgnoreList() {
        super();
    //#IgnoreList.java:42: method: void com.dmdirc.IgnoreList.com.dmdirc.IgnoreList()
    //#IgnoreList.java:42: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.parser.irc.RegexStringList()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.IgnoreList
    //#    method: void com.dmdirc.IgnoreList()
    //#    unanalyzed callee: void com.dmdirc.parser.irc.RegexStringList()
    //#input(void com.dmdirc.IgnoreList()): this
    }
    //#IgnoreList.java:43: end of method: void com.dmdirc.IgnoreList.com.dmdirc.IgnoreList()

    /**
     * Creates a new instance of IgnoreList containing the specified items.
     *
     * @param items The items to be added
     */
    public IgnoreList(final List<String> items) {
        super(items);
    //#IgnoreList.java:51: method: void com.dmdirc.IgnoreList.com.dmdirc.IgnoreList(List)
    //#IgnoreList.java:51: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.parser.irc.RegexStringList(List)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.IgnoreList
    //#    method: void com.dmdirc.IgnoreList(List)
    //#    unanalyzed callee: void com.dmdirc.parser.irc.RegexStringList(List)
    //#input(void com.dmdirc.IgnoreList(List)): items
    //#input(void com.dmdirc.IgnoreList(List)): this
    }
    //#IgnoreList.java:52: end of method: void com.dmdirc.IgnoreList.com.dmdirc.IgnoreList(List)

    /**
     * Adds the specified simple pattern to this ignore list.
     *
     * @param pattern The simple pattern to be added
     */
    public void addSimple(final String pattern) {
        add(simpleToRegex(pattern));
    //#IgnoreList.java:60: method: void com.dmdirc.IgnoreList.addSimple(String)
    //#IgnoreList.java:60: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.IgnoreList:add(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.IgnoreList
    //#    method: void addSimple(String)
    //#    unanalyzed callee: void com.dmdirc.IgnoreList:add(String)
    //#input(void addSimple(String)): pattern
    //#input(void addSimple(String)): this
    //#pre[1] (void addSimple(String)): pattern != null
    //#unanalyzed(void addSimple(String)): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void addSimple(String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void addSimple(String)): Effects-of-calling:java.lang.String:toCharArray
    //#unanalyzed(void addSimple(String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void addSimple(String)): Effects-of-calling:java.lang.StringBuilder:toString
    }
    //#IgnoreList.java:61: end of method: void com.dmdirc.IgnoreList.addSimple(String)

    /**
     * Determines if this list can be converted to a simple list.
     *
     * @return True if this list can be converted, false otherwise.
     */
    public boolean canConvert() {
        try {
            getSimpleList();
    //#IgnoreList.java:70: method: bool com.dmdirc.IgnoreList.canConvert()
    //#input(bool canConvert()): "Cannot convert to simple expression: unescaped special char: "._tainted
    //#input(bool canConvert()): __Descendant_Table[com/dmdirc/IgnoreList]
    //#input(bool canConvert()): __Descendant_Table[others]
    //#input(bool canConvert()): __Dispatch_Table.getSimpleList()Ljava/util/List;
    //#input(bool canConvert()): this
    //#input(bool canConvert()): this.__Tag
    //#input(bool canConvert()): this.ignoreInfo
    //#output(bool canConvert()): return_value
    //#pre[2] (bool canConvert()): (soft) this.__Tag == com/dmdirc/IgnoreList
    //#pre[3] (bool canConvert()): (soft) this.ignoreInfo != null
    //#post(bool canConvert()): init'ed(return_value)
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.lang.String:length
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.lang.String:toCharArray
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.lang.UnsupportedOperationException
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(bool canConvert()): Effects-of-calling:java.util.List:add
            return true;
        } catch (UnsupportedOperationException ex) {
            return false;
    //#IgnoreList.java:73: end of method: bool com.dmdirc.IgnoreList.canConvert()
        }
    }

    /**
     * Retrieves a list of regular expressions in this ignore list.
     *
     * @return All expressions in this ignore list
     */
    public List<String> getRegexList() {
        return new ArrayList<String>(ignoreInfo);
    //#IgnoreList.java:83: method: List com.dmdirc.IgnoreList.getRegexList()
    //#input(List getRegexList()): this
    //#input(List getRegexList()): this.ignoreInfo
    //#output(List getRegexList()): new ArrayList(getRegexList#1) num objects
    //#output(List getRegexList()): return_value
    //#new obj(List getRegexList()): new ArrayList(getRegexList#1)
    //#pre[2] (List getRegexList()): init'ed(this.ignoreInfo)
    //#post(List getRegexList()): return_value == &new ArrayList(getRegexList#1)
    //#post(List getRegexList()): new ArrayList(getRegexList#1) num objects == 1
    //#IgnoreList.java:83: end of method: List com.dmdirc.IgnoreList.getRegexList()
    }

    /**
     * Retrieves a list of simple expressions in this ignore list.
     *
     * @return All expressions in this ignore list, converted to simple expressions
     * @throws UnsupportedOperationException if an expression can't be converted
     */
    public List<String> getSimpleList() throws UnsupportedOperationException {
        final List<String> res = new ArrayList<String>();
    //#IgnoreList.java:93: method: List com.dmdirc.IgnoreList.getSimpleList()
    //#input(List getSimpleList()): "Cannot convert to simple expression: unescaped special char: "._tainted
    //#input(List getSimpleList()): this
    //#input(List getSimpleList()): this.ignoreInfo
    //#output(List getSimpleList()): new ArrayList(getSimpleList#1) num objects
    //#output(List getSimpleList()): return_value
    //#new obj(List getSimpleList()): new ArrayList(getSimpleList#1)
    //#pre[2] (List getSimpleList()): this.ignoreInfo != null
    //#presumption(List getSimpleList()): java.util.Iterator:next(...)@95 != null
    //#post(List getSimpleList()): return_value == &new ArrayList(getSimpleList#1)
    //#post(List getSimpleList()): new ArrayList(getSimpleList#1) num objects == 1
    //#unanalyzed(List getSimpleList()): Effects-of-calling:java.lang.String:length
    //#unanalyzed(List getSimpleList()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(List getSimpleList()): Effects-of-calling:java.lang.String:toCharArray
    //#unanalyzed(List getSimpleList()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(List getSimpleList()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(List getSimpleList()): Effects-of-calling:java.lang.UnsupportedOperationException
    //#test_vector(List getSimpleList()): java.util.Iterator:hasNext(...)@95: {0}, {1}

        for (String regex : ignoreInfo) {
            res.add(regexToSimple(regex));
        }

        return res;
    //#IgnoreList.java:99: end of method: List com.dmdirc.IgnoreList.getSimpleList()
    }

    /**
     * Converts a regular expression into a simple expression.
     *
     * @param regex The regular expression to be converted
     * @return A simple expression corresponding to the regex
     * @throws UnsupportedOperationException if the regex cannot be converted
     */
    protected static String regexToSimple(final String regex)
            throws UnsupportedOperationException {
        final StringBuilder res = new StringBuilder(regex.length());
    //#IgnoreList.java:111: method: String com.dmdirc.IgnoreList.regexToSimple(String)
    //#input(String regexToSimple(String)): "Cannot convert to simple expression: unescaped special char: "._tainted
    //#input(String regexToSimple(String)): regex
    //#output(String regexToSimple(String)): java.lang.StringBuilder:toString(...)._tainted
    //#output(String regexToSimple(String)): return_value
    //#new obj(String regexToSimple(String)): java.lang.StringBuilder:toString(...)
    //#pre[1] (String regexToSimple(String)): regex != null
    //#presumption(String regexToSimple(String)): arr$.length@115 <= 4_294_967_295
    //#presumption(String regexToSimple(String)): arr$[i$]@115 not in {36, 40,41, 43, 63, 91, 93,94, 123..125}
    //#presumption(String regexToSimple(String)): arr$[i$]@115 not in {36, 40..43, 46, 63, 91..94, 123..125}
    //#presumption(String regexToSimple(String)): arr$[i$]@115 not in {36, 40..43, 46, 63, 91..94, 123..125}
    //#post(String regexToSimple(String)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(String regexToSimple(String)): return_value == &java.lang.StringBuilder:toString(...)
    //#test_vector(String regexToSimple(String)): arr$[i$]@115: {92}, {42}, {46}, {0..35, 37..39, 44,45, 47..62, 64..90, 95..122, 126..65_535}
        boolean escaped = false;
        boolean inchar = false;

        for (char part : regex.toCharArray()) {
            if (inchar) {
                inchar = false;

                if (part == '*') {
                    res.append(part);
                    continue;
                } else {
                    res.append('?');
                }
            }

            if (escaped) {
                if (part == '?' || part == '*') {
    //#IgnoreList.java:128: ?UnsupportedOperationException check
    //#    part != 42
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.IgnoreList
    //#    method: String regexToSimple(String)
    //#    basic block: bb_8
    //#    assertion: part != 42
    //#    VN: arr$[i$]@115 - 42
    //#    Expected: {-Inf..-1, 1..+Inf}
    //#    Bad: {0}
    //#    Attribs:  Int  Bad singleton  Bad overlaps +/-1000  Bad > Exp  Uncertain
                    throw new UnsupportedOperationException("Cannot convert to"
                            + " simple expression: ? or * is escaped.");
                }

                res.append(part);
                escaped = false;
            }  else if (part == '\\') {
                escaped = true;
            } else if (part == '.') {
                inchar = true;
            } else if (part == '.' || part == '^' || part == '$' || part == '['
                    || part == ']' || part == '\\' || part == '(' || part == ')'
                    || part == '{' || part == '}' || part == '|' || part == '+'
                    || part == '*' || part == '?') {
                throw new UnsupportedOperationException("Cannot convert to"
    //#IgnoreList.java:143: ?conditional throw
    //#    part != 42
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.IgnoreList
    //#    method: String regexToSimple(String)
    //#    basic block: bb_25
    //#    assertion: part != 42
    //#    VN: arr$[i$]@115 - 42
    //#    Expected: {-Inf..-1, 1..+Inf}
    //#    Bad: {0}
    //#    Attribs:  Int  Bad singleton  Bad overlaps +/-1000  Bad > Exp  Uncertain
                        + " simple expression: unescaped special char: " + part);
            } else {
                res.append(part);
            }
        }

        if (escaped) {
    //#IgnoreList.java:150: ?UnsupportedOperationException check
    //#    escaped == 0
    //#    severity: LOW
    //#    class: com.dmdirc.IgnoreList
    //#    method: String regexToSimple(String)
    //#    basic block: bb_30
    //#    assertion: escaped == 0
    //#    VN: escaped
    //#    Expected: {0}
    //#    Bad: {1}
    //#    Attribs:  Int  Exp in +/-1000  Exp singleton  Bad singleton  Bad overlaps +/-1000  Bad > Exp
            throw new UnsupportedOperationException("Cannot convert to "
                    + "simple expression: trailing backslash");
        } else if (inchar) {
            res.append('?');
        }

        return res.toString();
    //#IgnoreList.java:157: end of method: String com.dmdirc.IgnoreList.regexToSimple(String)
    }

    /**
     * Converts a simple expression to a regular expression.
     *
     * @param regex The simple expression to be converted
     * @return A corresponding regular expression
     */
    @SuppressWarnings("fallthrough")
    protected static String simpleToRegex(final String regex) {
        final StringBuilder res = new StringBuilder(regex.length());
    //#IgnoreList.java:168: method: String com.dmdirc.IgnoreList.simpleToRegex(String)
    //#input(String simpleToRegex(String)): regex
    //#output(String simpleToRegex(String)): java.lang.StringBuilder:toString(...)._tainted
    //#output(String simpleToRegex(String)): return_value
    //#new obj(String simpleToRegex(String)): java.lang.StringBuilder:toString(...)
    //#pre[1] (String simpleToRegex(String)): regex != null
    //#presumption(String simpleToRegex(String)): arr$.length@170 <= 4_294_967_295
    //#post(String simpleToRegex(String)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(String simpleToRegex(String)): return_value == &java.lang.StringBuilder:toString(...)
    //#test_vector(String simpleToRegex(String)): arr$[i$]@170: {36, 40,41, 43, 46, 91..94, 123..125}, {42}, {63}, {0..35, 37..39, 44,45, 47..62, 64..90, 95..122, 126..65_535}

        for (char part : regex.toCharArray()) {
            switch (part) {
            case '.': case '^': case '$': case '[': case ']': case '\\':
            case '(': case ')': case '{': case '}': case '|': case '+':
                res.append('\\');
                res.append(part);
                break;
            case '?':
                res.append('.');
                break;
            case '*':
                res.append('.');
            default:
                res.append(part);
                break;
            }
        }

        return res.toString();
    //#IgnoreList.java:188: end of method: String com.dmdirc.IgnoreList.simpleToRegex(String)
    }

}
    //#output(com.dmdirc.IgnoreList__static_init): __Descendant_Table[com/dmdirc/IgnoreList]
    //#output(com.dmdirc.IgnoreList__static_init): __Dispatch_Table.addSimple(Ljava/lang/String;)V
    //#output(com.dmdirc.IgnoreList__static_init): __Dispatch_Table.canConvert()Z
    //#output(com.dmdirc.IgnoreList__static_init): __Dispatch_Table.getRegexList()Ljava/util/List;
    //#output(com.dmdirc.IgnoreList__static_init): __Dispatch_Table.getSimpleList()Ljava/util/List;
    //#post(com.dmdirc.IgnoreList__static_init): __Descendant_Table[com/dmdirc/IgnoreList] == &__Dispatch_Table
    //#post(com.dmdirc.IgnoreList__static_init): __Dispatch_Table.addSimple(Ljava/lang/String;)V == &addSimple
    //#post(com.dmdirc.IgnoreList__static_init): __Dispatch_Table.canConvert()Z == &canConvert
    //#post(com.dmdirc.IgnoreList__static_init): __Dispatch_Table.getRegexList()Ljava/util/List; == &getRegexList
    //#post(com.dmdirc.IgnoreList__static_init): __Dispatch_Table.getSimpleList()Ljava/util/List; == &getSimpleList
    //#IgnoreList.java:: end of method: com.dmdirc.IgnoreList.com.dmdirc.IgnoreList__static_init
    //#IgnoreList.java:: end of class: com.dmdirc.IgnoreList
