Task: Update a configuration file





Java: import java.io.*;
import java.util.*;
import java.util.regex.*;

public class UpdateConfig {

    public static void main(String[] args) {
        if (args[0] == null) {
            System.out.println("filename required");

        } else if (readConfig(args[0])) {
            enableOption("seedsremoved");
            disableOption("needspeeling");
            setOption("numberofbananas", "1024");
            addOption("numberofstrawberries", "62000");
            store();
        }
    }

    private enum EntryType {
        EMPTY, ENABLED, DISABLED, COMMENT
    }

    private static class Entry {
        EntryType type;
        String name, value;

        Entry(EntryType t, String n, String v) {
            type = t;
            name = n;
            value = v;
        }
    }

    private static Map<String, Entry> entries = new LinkedHashMap<>();
    private static String path;

    private static boolean readConfig(String p) {
        path = p;

        File f = new File(path);
        if (!f.exists() || f.isDirectory())
            return false;

        String regexString = "^(;*)\\s*([A-Za-z0-9]+)\\s*([A-Za-z0-9]*)";
        Pattern regex = Pattern.compile(regexString);

        try (Scanner sc = new Scanner(new FileReader(f))){
            int emptyLines = 0;
            String line;
            while (sc.hasNext()) {
                line = sc.nextLine().trim();

                if (line.isEmpty()) {
                    addOption("" + emptyLines++, null, EntryType.EMPTY);

                } else if (line.charAt(0) == '#') {
                    entries.put(line, new Entry(EntryType.COMMENT, line, null));

                } else {
                    line = line.replaceAll("[^a-zA-Z0-9\\x20;]", "");
                    Matcher m = regex.matcher(line);

                    if (m.find() && !m.group(2).isEmpty()) {

                        EntryType t = EntryType.ENABLED;
                        if (!m.group(1).isEmpty())
                            t = EntryType.DISABLED;

                        addOption(m.group(2), m.group(3), t);
                    }
                }
            }
        } catch (IOException e) {
            System.out.println(e);
        }
        return true;
    }

    private static void addOption(String name, String value) {
        addOption(name, value, EntryType.ENABLED);
    }

    private static void addOption(String name, String value, EntryType t) {
        name = name.toUpperCase();
        entries.put(name, new Entry(t, name, value));
    }

    private static void enableOption(String name) {
        Entry e = entries.get(name.toUpperCase());
        if (e != null)
            e.type = EntryType.ENABLED;
    }

    private static void disableOption(String name) {
        Entry e = entries.get(name.toUpperCase());
        if (e != null)
            e.type = EntryType.DISABLED;
    }

    private static void setOption(String name, String value) {
        Entry e = entries.get(name.toUpperCase());
        if (e != null)
            e.value = value;
    }

    private static void store() {
        try (PrintWriter pw = new PrintWriter(path)) {
            for (Entry e : entries.values()) {
                switch (e.type) {
                    case EMPTY:
                        pw.println();
                        break;
                    case ENABLED:
                        pw.format("%s %s%n", e.name, e.value);
                        break;
                    case DISABLED:
                        pw.format("; %s %s%n", e.name, e.value);
                        break;
                    case COMMENT:
                        pw.println(e.name);
                        break;
                    default:
                        break;
                }
            }
            if (pw.checkError()) {
                throw new IOException("writing to file failed");
            }
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}



Python: 




import re
import string





DISABLED_PREFIX = ';'





class Option(object):
    

    
    def __init__(self, name, value=None, disabled=False,
                 disabled_prefix=DISABLED_PREFIX):
        
        self.name = str(name)
        self.value = value
        self.disabled = bool(disabled)
        self.disabled_prefix = disabled_prefix

    
    def __str__(self):
        
        disabled = ('', '%s ' % self.disabled_prefix)[self.disabled]
        value = (' %s' % self.value, '')[self.value is None]
        return ''.join((disabled, self.name, value))

    
    def get(self):
        
        enabled = not bool(self.disabled)
        if self.value is None:
            value = enabled
        else:
            value = enabled and self.value
        return value

    



class Config(object):
    
    
    reOPTION = r'^\s*(?P<disabled>%s*)\s*(?P<name>\w+)(?:\s+(?P<value>.+?))?\s*$'

    
    def __init__(self, fname=None, disabled_prefix=DISABLED_PREFIX):
        
        self.disabled_prefix = disabled_prefix
        self.contents = []          
        self.options = {}           
        self.creOPTION = re.compile(self.reOPTION % self.disabled_prefix)
        if fname:
            self.parse_file(fname)

    
    def __str__(self):
        
        return '\n'.join(map(str, self.contents))

    
    def parse_file(self, fname):
        
        with open(fname) as f:
            self.parse_lines(f)
        return self

    
    def parse_lines(self, lines):
        
        for line in lines:
            self.parse_line(line)
        return self

    
    def parse_line(self, line):
        
        s = ''.join(c for c in line.strip() if c in string.printable) 
        moOPTION = self.creOPTION.match(s)
        if moOPTION:
            name = moOPTION.group('name').upper()
            if not name in self.options:
                self.add_option(name, moOPTION.group('value'),
                                moOPTION.group('disabled'))
        else:
            if not s.startswith(self.disabled_prefix):
                self.contents.append(line.rstrip())
        return self

    
    def add_option(self, name, value=None, disabled=False):
        
        name = name.upper()
        opt = Option(name, value, disabled)
        self.options[name] = opt
        self.contents.append(opt)
        return opt

    
    def set_option(self, name, value=None, disabled=False):
        
        name = name.upper()
        opt = self.options.get(name)
        if opt:
            opt.value = value
            opt.disabled = disabled
        else:
            opt = self.add_option(name, value, disabled)
        return opt

    
    def enable_option(self, name, value=None):
        
        return self.set_option(name, value, False)

    
    def disable_option(self, name, value=None):
        
        return self.set_option(name, value, True)

    
    def get_option(self, name):
        
        opt = self.options.get(name.upper())
        value = opt.get() if opt else None
        return value





if __name__ == '__main__':
    import sys
    cfg = Config(sys.argv[1] if len(sys.argv) > 1 else None)
    cfg.disable_option('needspeeling')
    cfg.enable_option('seedsremoved')
    cfg.enable_option('numberofbananas', 1024)
    cfg.enable_option('numberofstrawberries', 62000)
    print cfg