//# 1 errors, 262 messages
//#
/*
    //#ThemeManager.java:1:1: class: com.dmdirc.ui.themes.ThemeManager$1
    //#ThemeManager.java:1:1: method: com.dmdirc.ui.themes.ThemeManager$1.com.dmdirc.ui.themes.ThemeManager$1__static_init
    //#ThemeManager.java:1:1: class: com.dmdirc.ui.themes.ThemeManager
 * 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.ui.themes;

import com.dmdirc.Main;
import com.dmdirc.config.IdentityManager;
import com.dmdirc.interfaces.ConfigChangeListener;
import com.dmdirc.logger.ErrorLevel;
import com.dmdirc.logger.Logger;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Manages available themes.
 *
 * @author Chris
 */
public final class ThemeManager {
    
    /** The directory to look for themes in. */
    private static final String THEME_DIR = Main.getConfigDir() + "themes/";
    //#ThemeManager.java:44: method: com.dmdirc.ui.themes.ThemeManager.com.dmdirc.ui.themes.ThemeManager__static_init
    //#ThemeManager.java:44: Warning: method not available - call not analyzed
    //#    call on String com.dmdirc.Main:getConfigDir()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.themes.ThemeManager
    //#    method: com.dmdirc.ui.themes.ThemeManager__static_init
    //#    unanalyzed callee: String com.dmdirc.Main:getConfigDir()
    //#output(com.dmdirc.ui.themes.ThemeManager__static_init): "themes."._tainted
    //#output(com.dmdirc.ui.themes.ThemeManager__static_init): THEMES
    //#output(com.dmdirc.ui.themes.ThemeManager__static_init): THEME_DIR
    //#output(com.dmdirc.ui.themes.ThemeManager__static_init): __Descendant_Table[com/dmdirc/ui/themes/ThemeManager]
    //#output(com.dmdirc.ui.themes.ThemeManager__static_init): java.lang.StringBuilder:toString(...)._tainted
    //#output(com.dmdirc.ui.themes.ThemeManager__static_init): new HashMap(ThemeManager__static_init#2) num objects
    //#new obj(com.dmdirc.ui.themes.ThemeManager__static_init): java.lang.StringBuilder:toString(...)
    //#new obj(com.dmdirc.ui.themes.ThemeManager__static_init): new HashMap(ThemeManager__static_init#2)
    //#presumption(com.dmdirc.ui.themes.ThemeManager__static_init): com.dmdirc.config.IdentityManager:getGlobalConfig(...)@50 != null
    //#post(com.dmdirc.ui.themes.ThemeManager__static_init): "themes."._tainted == 0
    //#post(com.dmdirc.ui.themes.ThemeManager__static_init): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(com.dmdirc.ui.themes.ThemeManager__static_init): THEMES == &new HashMap(ThemeManager__static_init#2)
    //#post(com.dmdirc.ui.themes.ThemeManager__static_init): THEME_DIR == &java.lang.StringBuilder:toString(...)
    //#post(com.dmdirc.ui.themes.ThemeManager__static_init): __Descendant_Table[com/dmdirc/ui/themes/ThemeManager] == &__Dispatch_Table
    //#post(com.dmdirc.ui.themes.ThemeManager__static_init): new HashMap(ThemeManager__static_init#2) num objects == 1
    
    /** Available themes. */
    private static final Map<String, Theme> THEMES = new HashMap<String, Theme>();
    
    static {
        IdentityManager.getGlobalConfig().addChangeListener("themes", "enabled",
    //#ThemeManager.java:50: Warning: method not available - call not analyzed
    //#    call on ConfigManager com.dmdirc.config.IdentityManager:getGlobalConfig()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.themes.ThemeManager
    //#    method: com.dmdirc.ui.themes.ThemeManager__static_init
    //#    unanalyzed callee: ConfigManager com.dmdirc.config.IdentityManager:getGlobalConfig()
    //#ThemeManager.java:50: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.config.ConfigManager:addChangeListener(String, String, ConfigChangeListener)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.themes.ThemeManager
    //#    method: com.dmdirc.ui.themes.ThemeManager__static_init
    //#    unanalyzed callee: void com.dmdirc.config.ConfigManager:addChangeListener(String, String, ConfigChangeListener)
                new ConfigChangeListener() {
    //#ThemeManager.java:51: method: void com.dmdirc.ui.themes.ThemeManager$1.com.dmdirc.ui.themes.ThemeManager$1()
    //#ThemeManager.java:51: end of method: void com.dmdirc.ui.themes.ThemeManager$1.com.dmdirc.ui.themes.ThemeManager$1()
            /** {@inheritDoc} */
            @Override
            public void configChanged(final String domain, final String key) {
                loadThemes();
    //#ThemeManager.java:55: method: void com.dmdirc.ui.themes.ThemeManager$1.configChanged(String, String)
            }
    //#ThemeManager.java:56: end of method: void com.dmdirc.ui.themes.ThemeManager$1.configChanged(String, String)
        });
    }
    //#ThemeManager.java:58: end of method: com.dmdirc.ui.themes.ThemeManager.com.dmdirc.ui.themes.ThemeManager__static_init
    
    /**
     * Creates a new instance of theme manager.
     */
    private ThemeManager() {
    //#ThemeManager.java:63: method: void com.dmdirc.ui.themes.ThemeManager.com.dmdirc.ui.themes.ThemeManager()
        // Do nothing
    }
    //#ThemeManager.java:65: end of method: void com.dmdirc.ui.themes.ThemeManager.com.dmdirc.ui.themes.ThemeManager()
    
    /**
     * Scans for available themes and loads any themes that the user has enabled.
     */
    public static void loadThemes() {
        final File dir = new File(THEME_DIR);
    //#ThemeManager.java:71: method: void com.dmdirc.ui.themes.ThemeManager.loadThemes()
    //#input(void loadThemes()): THEMES
    //#input(void loadThemes()): THEME_DIR
    //#input(void loadThemes()): com.dmdirc.logger.ErrorLevel.HIGH
    //#input(void loadThemes()): com.dmdirc.logger.ErrorLevel.MEDIUM
    //#input(void loadThemes()): THEMES.__Lock
    //#presumption(void loadThemes()): arr$.length@86 <= 4_294_967_295
    //#presumption(void loadThemes()): arr$[i$]@86 != null
    //#presumption(void loadThemes()): com.dmdirc.config.ConfigManager:getOptionList(...)@77 != null
    //#presumption(void loadThemes()): com.dmdirc.config.IdentityManager:getGlobalConfig(...)@77 != null
    //#presumption(void loadThemes()): init'ed(com.dmdirc.logger.ErrorLevel.HIGH)
    //#presumption(void loadThemes()): init'ed(com.dmdirc.logger.ErrorLevel.MEDIUM)
    //#presumption(void loadThemes()): java.io.File:listFiles(...)@86 != null
    //#test_vector(void loadThemes()): java.io.File:exists(...)@73: {1}, {0}
    //#test_vector(void loadThemes()): java.io.File:listFiles(...)@80: Inverse{null}, Addr_Set{null}
    //#test_vector(void loadThemes()): java.io.File:mkdirs(...)@73: {1}, {0}

        if (!dir.exists() && !dir.mkdirs()) {
            Logger.userError(ErrorLevel.HIGH, "Could not create themes directory");
    //#ThemeManager.java:74: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.themes.ThemeManager
    //#    method: void loadThemes()
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
        }
        
        final List<String> enabled
    //#ThemeManager.java:77: Warning: method not available - call not analyzed
    //#    call on ConfigManager com.dmdirc.config.IdentityManager:getGlobalConfig()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.themes.ThemeManager
    //#    method: void loadThemes()
    //#    unanalyzed callee: ConfigManager com.dmdirc.config.IdentityManager:getGlobalConfig()
    //#ThemeManager.java:77: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.config.ConfigManager:getOptionList(String, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.themes.ThemeManager
    //#    method: void loadThemes()
    //#    unanalyzed callee: List com.dmdirc.config.ConfigManager:getOptionList(String, String)
                = IdentityManager.getGlobalConfig().getOptionList("themes", "enabled");
            
        if (dir.listFiles() == null) {
            Logger.userError(ErrorLevel.MEDIUM, "Unable to load themes");
    //#ThemeManager.java:81: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.themes.ThemeManager
    //#    method: void loadThemes()
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
            return;
        }
        
        synchronized (THEMES) {
            for (File file : dir.listFiles()) {
                if (file.isDirectory()) {
                    continue;
                }

                loadTheme(file, enabled.contains(file.getName()));
    //#ThemeManager.java:91: Warning: call too complex - analysis skipped
    //#    call on void loadTheme(File, bool)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.themes.ThemeManager
    //#    method: void loadThemes()
    //#    unanalyzed callee: void loadTheme(File, bool)
            }
        }            
    }
    //#ThemeManager.java:94: end of method: void com.dmdirc.ui.themes.ThemeManager.loadThemes()
    
    /**
     * Attempts to load the theme from the specified file. If the enabled 
     * argument is true, the theme will be applied automatically. If it
     * has been previously applied and is no longer enabled, it will be 
     * unapplied.
     * 
     * @param file The file pointing to the theme to be loaded
     * @param enabled Whether this theme is enabled or not
     */
    private static void loadTheme(final File file, final boolean enabled) {
        Theme theme;

        if (THEMES.containsKey(file.getName())) {
    //#ThemeManager.java:108: method: void com.dmdirc.ui.themes.ThemeManager.loadTheme(File, bool)
    //#input(void loadTheme(File, bool)): ": "._tainted
    //#input(void loadTheme(File, bool)): "Error loading theme identity file: "._tainted
    //#input(void loadTheme(File, bool)): "I.O error when loading theme: "._tainted
    //#input(void loadTheme(File, bool)): "Unknown or unexpected line encountered: "._tainted
    //#input(void loadTheme(File, bool)): THEMES
    //#input(void loadTheme(File, bool)): com/dmdirc/ui/themes/Theme.__Descendant_Table[com/dmdirc/ui/themes/Theme]
    //#input(void loadTheme(File, bool)): com/dmdirc/ui/themes/Theme.__Descendant_Table[others]
    //#input(void loadTheme(File, bool)): com/dmdirc/ui/themes/Theme.__Dispatch_Table.applyTheme()V
    //#input(void loadTheme(File, bool)): com/dmdirc/ui/themes/Theme.__Dispatch_Table.isEnabled()Z
    //#input(void loadTheme(File, bool)): com/dmdirc/ui/themes/Theme.__Dispatch_Table.isValidTheme()Z
    //#input(void loadTheme(File, bool)): com/dmdirc/ui/themes/Theme.__Dispatch_Table.removeTheme()V
    //#input(void loadTheme(File, bool)): com/dmdirc/ui/themes/Theme.com.dmdirc.logger.ErrorLevel.MEDIUM
    //#input(void loadTheme(File, bool)): com/dmdirc/util/ConfigFile.__Descendant_Table[com/dmdirc/util/ConfigFile]
    //#input(void loadTheme(File, bool)): com/dmdirc/util/ConfigFile.__Descendant_Table[others]
    //#input(void loadTheme(File, bool)): com/dmdirc/util/ConfigFile.__Dispatch_Table.getLines()Ljava/util/List;
    //#input(void loadTheme(File, bool)): com/dmdirc/util/ConfigFile.__Dispatch_Table.read()V
    //#input(void loadTheme(File, bool)): com/dmdirc/util/ConfigFile.__Dispatch_Table.readLines()V
    //#input(void loadTheme(File, bool)): com/dmdirc/util/MapList.__Descendant_Table[com/dmdirc/util/MapList]
    //#input(void loadTheme(File, bool)): com/dmdirc/util/MapList.__Descendant_Table[com/dmdirc/util/WeakMapList]
    //#input(void loadTheme(File, bool)): com/dmdirc/util/MapList.__Descendant_Table[others]
    //#input(void loadTheme(File, bool)): com/dmdirc/util/MapList.__Dispatch_Table.add(Ljava/lang/Object;)V
    //#input(void loadTheme(File, bool)): com/dmdirc/util/MapList.__Dispatch_Table.add(Ljava/lang/Object;Ljava/lang/Object;)V
    //#input(void loadTheme(File, bool)): com/dmdirc/util/MapList.__Dispatch_Table.clear()V
    //#input(void loadTheme(File, bool)): com/dmdirc/util/MapList.__Dispatch_Table.containsKey(Ljava/lang/Object;)Z
    //#input(void loadTheme(File, bool)): com/dmdirc/util/MapList.__Dispatch_Table.containsValue(Ljava/lang/Object;Ljava/lang/Object;)Z
    //#input(void loadTheme(File, bool)): com/dmdirc/util/MapList.__Dispatch_Table.safeGet(Ljava/lang/Object;)Ljava/util/List;
    //#input(void loadTheme(File, bool)): com/dmdirc/util/TextFile.__Descendant_Table[com/dmdirc/util/ConfigFile]
    //#input(void loadTheme(File, bool)): com/dmdirc/util/TextFile.__Descendant_Table[com/dmdirc/util/TextFile]
    //#input(void loadTheme(File, bool)): com/dmdirc/util/TextFile.__Descendant_Table[others]
    //#input(void loadTheme(File, bool)): com/dmdirc/util/TextFile.__Dispatch_Table.readLines()V
    //#input(void loadTheme(File, bool)): com/dmdirc/util/WeakMapList.__Dispatch_Table.add(Ljava/lang/Object;)V
    //#input(void loadTheme(File, bool)): com/dmdirc/util/WeakMapList.__Dispatch_Table.add(Ljava/lang/Object;Ljava/lang/Object;)V
    //#input(void loadTheme(File, bool)): com/dmdirc/util/WeakMapList.__Dispatch_Table.clear()V
    //#input(void loadTheme(File, bool)): com/dmdirc/util/WeakMapList.__Dispatch_Table.containsKey(Ljava/lang/Object;)Z
    //#input(void loadTheme(File, bool)): com/dmdirc/util/WeakMapList.__Dispatch_Table.containsValue(Ljava/lang/Object;Ljava/lang/Object;)Z
    //#input(void loadTheme(File, bool)): com/dmdirc/util/WeakMapList.__Dispatch_Table.safeGet(Ljava/lang/Object;)Ljava/util/List;
    //#input(void loadTheme(File, bool)): com/dmdirc/util/resourcemanager/ZipResourceManager.__Class_Obj.__Lock
    //#input(void loadTheme(File, bool)): enabled
    //#input(void loadTheme(File, bool)): file
    //#output(void loadTheme(File, bool)): new ArrayList(ConfigFile#1) num objects
    //#output(void loadTheme(File, bool)): new ArrayList(ZipResourceManager#2) num objects
    //#output(void loadTheme(File, bool)): new ArrayList(readLines#4) num objects
    //#output(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2) num objects
    //#output(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2).__Tag
    //#output(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2).charset
    //#output(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2).domains
    //#output(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2).file
    //#output(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2).flatdomains
    //#output(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2).is
    //#output(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2).keydomains
    //#output(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2).lines
    //#output(void loadTheme(File, bool)): new HashMap(ConfigFile#3) num objects
    //#output(void loadTheme(File, bool)): new HashMap(MapList#1) num objects
    //#output(void loadTheme(File, bool)): new MapList(ConfigFile#2) num objects
    //#output(void loadTheme(File, bool)): new MapList(ConfigFile#2).__Tag
    //#output(void loadTheme(File, bool)): new MapList(ConfigFile#2).map
    //#output(void loadTheme(File, bool)): new Theme(loadTheme#1) num objects
    //#output(void loadTheme(File, bool)): new Theme(loadTheme#1).__Tag
    //#output(void loadTheme(File, bool)): new Theme(loadTheme#1).enabled
    //#output(void loadTheme(File, bool)): new Theme(loadTheme#1).file
    //#output(void loadTheme(File, bool)): new Theme(loadTheme#1).identity
    //#output(void loadTheme(File, bool)): new Theme(loadTheme#1).metadata
    //#output(void loadTheme(File, bool)): new Theme(loadTheme#1).rm
    //#output(void loadTheme(File, bool)): new ThemeIdentity(applyTheme#1) num objects
    //#output(void loadTheme(File, bool)): new ThemeIdentity(applyTheme#1).__Tag
    //#output(void loadTheme(File, bool)): new ThemeIdentity(applyTheme#1).myTarget
    //#output(void loadTheme(File, bool)): new ThemeIdentity(applyTheme#1).theme
    //#output(void loadTheme(File, bool)): new ZipFile(ZipResourceManager#1) num objects
    //#output(void loadTheme(File, bool)): new ZipResourceManager(getInstance#1) num objects
    //#output(void loadTheme(File, bool)): new ZipResourceManager(getInstance#1).__Tag
    //#output(void loadTheme(File, bool)): new ZipResourceManager(getInstance#1).entries
    //#output(void loadTheme(File, bool)): new ZipResourceManager(getInstance#1).zipFile
    //#new obj(void loadTheme(File, bool)): new ArrayList(ConfigFile#1)
    //#new obj(void loadTheme(File, bool)): new ArrayList(ZipResourceManager#2)
    //#new obj(void loadTheme(File, bool)): new ArrayList(readLines#4)
    //#new obj(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2)
    //#new obj(void loadTheme(File, bool)): new HashMap(ConfigFile#3)
    //#new obj(void loadTheme(File, bool)): new HashMap(MapList#1)
    //#new obj(void loadTheme(File, bool)): new MapList(ConfigFile#2)
    //#new obj(void loadTheme(File, bool)): new Theme(loadTheme#1)
    //#new obj(void loadTheme(File, bool)): new ThemeIdentity(applyTheme#1)
    //#new obj(void loadTheme(File, bool)): new ZipFile(ZipResourceManager#1)
    //#new obj(void loadTheme(File, bool)): new ZipResourceManager(getInstance#1)
    //#pre[2] (void loadTheme(File, bool)): file != null
    //#presumption(void loadTheme(File, bool)): java.util.Map:get(...).__Tag@109 == com/dmdirc/ui/themes/Theme
    //#presumption(void loadTheme(File, bool)): java.util.Map:get(...)@109 != null
    //#presumption(void loadTheme(File, bool)): theme.file@109 != null
    //#presumption(void loadTheme(File, bool)): theme.rm.zipFile@109 != null
    //#presumption(void loadTheme(File, bool)): theme.rm.zipFile@114 != null
    //#post(void loadTheme(File, bool)): new ArrayList(ConfigFile#1) num objects <= 1
    //#post(void loadTheme(File, bool)): new ArrayList(ZipResourceManager#2) num objects <= 1
    //#post(void loadTheme(File, bool)): new ArrayList(readLines#4) num objects == 0
    //#post(void loadTheme(File, bool)): new ConfigFile(isValidTheme#2) num objects <= 1
    //#post(void loadTheme(File, bool)): init'ed(new ConfigFile(isValidTheme#2).__Tag)
    //#post(void loadTheme(File, bool)): init'ed(new ConfigFile(isValidTheme#2).charset)
    //#post(void loadTheme(File, bool)): init'ed(new ConfigFile(isValidTheme#2).domains)
    //#post(void loadTheme(File, bool)): init'ed(new ConfigFile(isValidTheme#2).file)
    //#post(void loadTheme(File, bool)): init'ed(new ConfigFile(isValidTheme#2).flatdomains)
    //#post(void loadTheme(File, bool)): init'ed(new ConfigFile(isValidTheme#2).is)
    //#post(void loadTheme(File, bool)): init'ed(new ConfigFile(isValidTheme#2).keydomains)
    //#post(void loadTheme(File, bool)): init'ed(new ConfigFile(isValidTheme#2).lines)
    //#post(void loadTheme(File, bool)): new HashMap(ConfigFile#3) num objects <= 1
    //#post(void loadTheme(File, bool)): new HashMap(MapList#1) num objects <= 1
    //#post(void loadTheme(File, bool)): new MapList(ConfigFile#2) num objects <= 1
    //#post(void loadTheme(File, bool)): init'ed(new MapList(ConfigFile#2).__Tag)
    //#post(void loadTheme(File, bool)): init'ed(new MapList(ConfigFile#2).map)
    //#post(void loadTheme(File, bool)): new Theme(loadTheme#1) num objects <= 1
    //#post(void loadTheme(File, bool)): init'ed(new Theme(loadTheme#1).__Tag)
    //#post(void loadTheme(File, bool)): init'ed(new Theme(loadTheme#1).enabled)
    //#post(void loadTheme(File, bool)): init'ed(new Theme(loadTheme#1).file)
    //#post(void loadTheme(File, bool)): init'ed(new Theme(loadTheme#1).identity)
    //#post(void loadTheme(File, bool)): possibly_updated(new Theme(loadTheme#1).metadata)
    //#post(void loadTheme(File, bool)): possibly_updated(new Theme(loadTheme#1).rm)
    //#post(void loadTheme(File, bool)): new ThemeIdentity(applyTheme#1) num objects <= 1
    //#post(void loadTheme(File, bool)): init'ed(new ThemeIdentity(applyTheme#1).__Tag)
    //#post(void loadTheme(File, bool)): init'ed(new ThemeIdentity(applyTheme#1).myTarget)
    //#post(void loadTheme(File, bool)): init'ed(new ThemeIdentity(applyTheme#1).theme)
    //#post(void loadTheme(File, bool)): new ZipFile(ZipResourceManager#1) num objects <= 1
    //#post(void loadTheme(File, bool)): new ZipResourceManager(getInstance#1) num objects <= 1
    //#post(void loadTheme(File, bool)): init'ed(new ZipResourceManager(getInstance#1).__Tag)
    //#post(void loadTheme(File, bool)): init'ed(new ZipResourceManager(getInstance#1).entries)
    //#post(void loadTheme(File, bool)): init'ed(new ZipResourceManager(getInstance#1).zipFile)
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.HashMap
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.List:add
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.zip.ZipFile:getEntry
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.zip.ZipFile:getInputStream
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:com.dmdirc.logger.Logger:userError
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.io.IOException:getMessage
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.io.File:getCanonicalPath
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.zip.ZipFile
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.zip.ZipFile:entries
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.Enumeration:hasMoreElements
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.Enumeration:nextElement
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.zip.ZipEntry:getName
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.zip.ZipEntry:isDirectory
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.nio.charset.Charset:forName
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.String:charAt
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.Map:clear
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.List:clear
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.io.FileInputStream
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.io.InputStreamReader
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.io.BufferedReader
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.io.BufferedReader:readLine
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.io.BufferedReader:close
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.String:indexOf
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.String:endsWith
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.lang.Exception
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:java.io.File:getAbsolutePath
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:isValidTheme
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:com.dmdirc.config.Identity
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:com.dmdirc.config.ConfigTarget:setTheme
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:com.dmdirc.config.IdentityManager:addIdentity
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:com.dmdirc.config.InvalidIdentityFileException:getMessage
    //#unanalyzed(void loadTheme(File, bool)): Effects-of-calling:com.dmdirc.config.IdentityManager:removeIdentity
    //#test_vector(void loadTheme(File, bool)): enabled: {0}, {1}
    //#test_vector(void loadTheme(File, bool)): java.util.Map:containsKey(...)@108: {0}, {1}
            theme = THEMES.get(file.getName());
        } else {
            theme = new Theme(file);

            if (theme.isValidTheme()) {
    //#ThemeManager.java:113: ?precondition failure
    //#    com/dmdirc/ui/themes/Theme.isValidTheme: init'ed(this.rm)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.ui.themes.ThemeManager
    //#    method: void loadTheme(File, bool)
    //#    basic block: bb_3
    //#    assertion: init'ed(undefined)
    //#    callee: bool com/dmdirc/ui/themes/Theme.isValidTheme()
    //#    callee assertion: init'ed(this.rm)
    //#    callee file: Theme.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 75
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
                THEMES.put(file.getName(), theme);
            } else {
                return;
            }
        }

        if (enabled && !theme.isEnabled()) {
            theme.applyTheme();
        } else if (theme.isEnabled() && !enabled) {
            theme.removeTheme();
        }        
    }
    //#ThemeManager.java:125: end of method: void com.dmdirc.ui.themes.ThemeManager.loadTheme(File, bool)
    
    /**
     * Retrieves a list of available themes.
     *
     * @return A list of available themes
     */    
    public static Map<String, Theme> getAvailableThemes() {
        loadThemes();
    //#ThemeManager.java:133: method: Map com.dmdirc.ui.themes.ThemeManager.getAvailableThemes()
    //#input(Map getAvailableThemes()): THEMES
    //#input(Map getAvailableThemes()): THEME_DIR
    //#input(Map getAvailableThemes()): com.dmdirc.logger.ErrorLevel.HIGH
    //#input(Map getAvailableThemes()): com.dmdirc.logger.ErrorLevel.MEDIUM
    //#output(Map getAvailableThemes()): new HashMap(getAvailableThemes#1) num objects
    //#output(Map getAvailableThemes()): return_value
    //#new obj(Map getAvailableThemes()): new HashMap(getAvailableThemes#1)
    //#post(Map getAvailableThemes()): return_value == &new HashMap(getAvailableThemes#1)
    //#post(Map getAvailableThemes()): new HashMap(getAvailableThemes#1) num objects == 1
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:com.dmdirc.config.IdentityManager:getGlobalConfig
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:java.io.File:getName
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:java.io.File
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:java.io.File:exists
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:java.io.File:mkdirs
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:com.dmdirc.logger.Logger:userError
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:com.dmdirc.config.ConfigManager:getOptionList
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:java.util.List:contains
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:loadTheme
    //#unanalyzed(Map getAvailableThemes()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
        
        synchronized (THEMES) {
            return new HashMap<String, Theme>(THEMES);
        }
    //#ThemeManager.java:137: end of method: Map com.dmdirc.ui.themes.ThemeManager.getAvailableThemes()
    }
    
    /**
     * Retrieves the directory used for storing themes.
     * 
     * @return The directory used for storing themes
     */
    public static String getThemeDirectory() {
        return THEME_DIR;
    //#ThemeManager.java:146: method: String com.dmdirc.ui.themes.ThemeManager.getThemeDirectory()
    //#input(String getThemeDirectory()): THEME_DIR
    //#output(String getThemeDirectory()): java.lang.StringBuilder:toString(...)
    //#output(String getThemeDirectory()): return_value
    //#new obj(String getThemeDirectory()): java.lang.StringBuilder:toString(...)
    //#post(String getThemeDirectory()): return_value == &java.lang.StringBuilder:toString(...)
    //#ThemeManager.java:146: end of method: String com.dmdirc.ui.themes.ThemeManager.getThemeDirectory()
    }

}
    //#output(com.dmdirc.ui.themes.ThemeManager$1__static_init): __Descendant_Table[com/dmdirc/ui/themes/ThemeManager$1]
    //#output(com.dmdirc.ui.themes.ThemeManager$1__static_init): __Dispatch_Table.configChanged(Ljava/lang/String;Ljava/lang/String;)V
    //#post(com.dmdirc.ui.themes.ThemeManager$1__static_init): __Descendant_Table[com/dmdirc/ui/themes/ThemeManager$1] == &__Dispatch_Table
    //#post(com.dmdirc.ui.themes.ThemeManager$1__static_init): __Dispatch_Table.configChanged(Ljava/lang/String;Ljava/lang/String;)V == &configChanged
    //#ThemeManager.java:: end of method: com.dmdirc.ui.themes.ThemeManager$1.com.dmdirc.ui.themes.ThemeManager$1__static_init
    //#ThemeManager.java:: end of class: com.dmdirc.ui.themes.ThemeManager$1
    //#ThemeManager.java:: end of class: com.dmdirc.ui.themes.ThemeManager
