tikhomirov@331: /* tikhomirov@331: * Copyright (c) 2011 TMate Software Ltd tikhomirov@331: * tikhomirov@331: * This program is free software; you can redistribute it and/or modify tikhomirov@331: * it under the terms of the GNU General Public License as published by tikhomirov@331: * the Free Software Foundation; version 2 of the License. tikhomirov@331: * tikhomirov@331: * This program is distributed in the hope that it will be useful, tikhomirov@331: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@331: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@331: * GNU General Public License for more details. tikhomirov@331: * tikhomirov@331: * For information on how to redistribute this software under tikhomirov@331: * the terms of a license other than GNU General Public License tikhomirov@331: * contact TMate Software at support@hg4j.com tikhomirov@331: */ tikhomirov@331: package org.tmatesoft.hg.repo; tikhomirov@331: tikhomirov@331: import java.util.ArrayList; tikhomirov@331: import java.util.Collections; tikhomirov@331: import java.util.Iterator; tikhomirov@331: import java.util.List; tikhomirov@331: import java.util.Map; tikhomirov@331: tikhomirov@331: import org.tmatesoft.hg.internal.ConfigFile; tikhomirov@331: import org.tmatesoft.hg.internal.Experimental; tikhomirov@331: import org.tmatesoft.hg.util.Pair; tikhomirov@331: tikhomirov@331: /** tikhomirov@331: * WORK IN PROGRESS tikhomirov@331: * tikhomirov@331: * Repository-specific configuration. tikhomirov@331: * tikhomirov@331: * @author Artem Tikhomirov tikhomirov@331: * @author TMate Software Ltd. tikhomirov@331: */ tikhomirov@331: @Experimental(reason="WORK IN PROGRESS") tikhomirov@331: public final class HgRepoConfig /*implements RepoChangeListener, perhaps, also RepoChangeNotifier? */{ tikhomirov@331: /*ease access for inner classes*/ final ConfigFile config; tikhomirov@331: tikhomirov@331: /*package-local*/HgRepoConfig(ConfigFile configFile) { tikhomirov@331: config = configFile; tikhomirov@331: } tikhomirov@331: tikhomirov@331: public Section getSection(String name) { tikhomirov@331: if (name == null) { tikhomirov@331: throw new IllegalArgumentException(); tikhomirov@331: } tikhomirov@331: if ("paths".equals(name)) { tikhomirov@331: return new PathsSection(); tikhomirov@331: } tikhomirov@331: if ("extensions".equals(name)) { tikhomirov@331: return new ExtensionsSection(); tikhomirov@331: } tikhomirov@331: return new Section(name); tikhomirov@331: } tikhomirov@331: tikhomirov@331: public boolean hasSection(String name) { tikhomirov@331: return config.hasSection(name); tikhomirov@331: } tikhomirov@331: tikhomirov@331: public boolean getBooleanValue(String section, String key, boolean defaultValue) { tikhomirov@331: return config.getBoolean(section, key, defaultValue); tikhomirov@331: } tikhomirov@331: tikhomirov@331: public String getStringValue(String section, String key, String defaultValue) { tikhomirov@331: return config.getString(section, key, defaultValue); tikhomirov@331: } tikhomirov@331: tikhomirov@331: // tikhomirov@331: // tikhomirov@331: tikhomirov@331: public PathsSection getPaths() { tikhomirov@331: Section s = getSection("paths"); tikhomirov@331: if (s.exists()) { tikhomirov@331: return (PathsSection) s; tikhomirov@331: } tikhomirov@331: return new PathsSection(); tikhomirov@331: } tikhomirov@331: tikhomirov@331: public ExtensionsSection getExtensions() { tikhomirov@331: Section s = getSection("extensions"); tikhomirov@331: if (s.exists()) { tikhomirov@331: return (ExtensionsSection) s; tikhomirov@331: } tikhomirov@331: return new ExtensionsSection(); tikhomirov@331: } tikhomirov@331: tikhomirov@331: /* tikhomirov@331: * IMPLEMENTATION NOTE: Section is merely a view to configuration file, without any state. tikhomirov@331: * In case I need to sync access to config (i.e. write) or refresh it later - can be easily done tikhomirov@331: */ tikhomirov@331: tikhomirov@331: public class Section implements Iterable> { tikhomirov@331: tikhomirov@331: protected final String section; tikhomirov@331: tikhomirov@331: /*package-local*/Section(String sectionName) { tikhomirov@331: section = sectionName; tikhomirov@331: } tikhomirov@331: tikhomirov@331: public String getName() { tikhomirov@331: return section; tikhomirov@331: } tikhomirov@331: tikhomirov@331: /** tikhomirov@331: * Whether this is real section or a bare non-null instance tikhomirov@331: */ tikhomirov@331: public boolean exists() { tikhomirov@331: return hasSection(section); tikhomirov@331: } tikhomirov@331: tikhomirov@331: /** tikhomirov@331: * @return defined keys, in the order they appear in the section tikhomirov@331: */ tikhomirov@331: public List getKeys() { tikhomirov@333: // PathsSection depends on return value being modifiable tikhomirov@331: return new ArrayList(config.getSection(section).keySet()); tikhomirov@331: } tikhomirov@331: tikhomirov@331: /** tikhomirov@331: * Find out whether key is present and got any value tikhomirov@331: * @param key identifies an entry to look up tikhomirov@331: * @return true if key is present in the section and has non-empty value tikhomirov@331: */ tikhomirov@331: public boolean isKeySet(String key) { tikhomirov@331: String value = getStringValue(section, key, null); tikhomirov@331: return value != null && value.length() > 0; tikhomirov@331: } tikhomirov@331: tikhomirov@331: /** tikhomirov@331: * Value of a key as boolean tikhomirov@331: * @param key identifies an entry to look up tikhomirov@331: * @param defaultValue optional value to return if no entry for the key found in this section tikhomirov@331: * @return value corresponding to the key, or defaultValue if key not found tikhomirov@331: */ tikhomirov@331: public boolean getBoolean(String key, boolean defaultValue) { tikhomirov@331: return getBooleanValue(section, key, defaultValue); tikhomirov@331: } tikhomirov@331: tikhomirov@331: /** tikhomirov@331: * Value of a key as regular string tikhomirov@331: * @param key identifies entry to look up tikhomirov@331: * @param defaultValue optional value to return if no entry for the key found in this section tikhomirov@331: * @return value corresponding to the key, or defaultValue if key not found tikhomirov@331: */ tikhomirov@331: public String getString(String key, String defaultValue) { tikhomirov@331: return getStringValue(section, key, defaultValue); tikhomirov@331: } tikhomirov@331: tikhomirov@331: public Iterator> iterator() { tikhomirov@331: final Map m = config.getSection(section); tikhomirov@331: if (m.isEmpty()) { tikhomirov@331: return Collections.>emptyList().iterator(); tikhomirov@331: } tikhomirov@331: ArrayList> rv = new ArrayList>(m.size()); tikhomirov@331: for (Map.Entry e : m.entrySet()) { tikhomirov@331: rv.add(new Pair(e.getKey(), e.getValue())); tikhomirov@331: } tikhomirov@331: return rv.iterator(); tikhomirov@331: } tikhomirov@331: } tikhomirov@331: tikhomirov@331: /* tikhomirov@331: * Few well-known sections may get their specific subclasses tikhomirov@331: */ tikhomirov@331: tikhomirov@331: /** tikhomirov@331: * Section [paths] tikhomirov@331: */ tikhomirov@331: public class PathsSection extends Section { tikhomirov@331: PathsSection() { tikhomirov@331: super("paths"); tikhomirov@331: } tikhomirov@333: tikhomirov@333: /** tikhomirov@333: * Similar to {@link #getKeys()}, but without entries for default and default-push paths tikhomirov@333: * @return list of path symbolic names tikhomirov@333: */ tikhomirov@333: public List getPathSymbolicNames() { tikhomirov@333: final List rv = getKeys(); tikhomirov@333: rv.remove("default"); tikhomirov@333: rv.remove("default-push"); tikhomirov@333: return rv; tikhomirov@333: } tikhomirov@331: tikhomirov@331: public boolean hasDefault() { tikhomirov@331: return isKeySet("default"); tikhomirov@331: } tikhomirov@331: public String getDefault() { tikhomirov@331: return super.getString("default", null); tikhomirov@331: } tikhomirov@331: public boolean hasDefaultPush() { tikhomirov@331: return isKeySet("default-push"); tikhomirov@331: } tikhomirov@331: public String getDefaultPush() { tikhomirov@331: return super.getString("default-push", null); tikhomirov@331: } tikhomirov@331: } tikhomirov@331: tikhomirov@331: /** tikhomirov@331: * Section [extensions] tikhomirov@331: * tikhomirov@331: * @author Artem Tikhomirov tikhomirov@331: * @author TMate Software Ltd. tikhomirov@331: */ tikhomirov@331: public class ExtensionsSection extends Section { tikhomirov@331: ExtensionsSection() { tikhomirov@331: super("extensions"); tikhomirov@331: } tikhomirov@331: tikhomirov@331: public boolean isEnabled(String extensionName) { tikhomirov@331: String value = config.getSection(section).get(extensionName); tikhomirov@349: // empty line, just "extension =" is valid way to enable it tikhomirov@349: return value != null && (value.length() == 0 || '!' != value.charAt(0)); tikhomirov@331: } tikhomirov@331: } tikhomirov@331: }