Clover coverage report - JGAP 3.1
Coverage timestamp: Mo Dez 11 2006 21:16:18 CET
file stats: LOC: 282   Methods: 12
NCLOC: 151   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
MetaConfig.java 78,6% 90,3% 100% 87,3%
coverage coverage
 1    /*
 2    * This file is part of JGAP.
 3    *
 4    * JGAP offers a dual license model containing the LGPL as well as the MPL.
 5    *
 6    * For licencing information please see the file license.txt included with JGAP
 7    * or have a look at the top of class org.jgap.Chromosome which representatively
 8    * includes the JGAP license policy applicable for any file delivered with JGAP.
 9    */
 10    package org.jgap.data.config;
 11   
 12    import java.util.*;
 13    import java.io.*;
 14   
 15    /**
 16    * This class provides an interface to the configuration information to create
 17    * a JGAP Configuration GUI.
 18    * @author Siddhartha Azad
 19    * @since 2.4
 20    *
 21    */
 22    public class MetaConfig {
 23    // file to read the GUI Configuration information from
 24    private static final String METACON_FILENAME = "jgap-meta.con";
 25   
 26    private static final String CN = "MetaConfig";
 27   
 28    // singleton instance
 29    private static MetaConfig instance;
 30   
 31    // ClassName-ConfigProperty mapping
 32    private Hashtable m_metaMap = new Hashtable();
 33   
 34    // state for the parser
 35    private int m_state;
 36   
 37    private static final int INIT = 0;
 38   
 39    private static final int CLASS = 1;
 40   
 41    private static final int PROPERTY = 2;
 42   
 43    private static final int VALUES = 3;
 44   
 45    // class name currently being handled
 46    private String m_currName;
 47   
 48    private ConfigProperty m_currProperty;
 49   
 50  4 public static MetaConfig getInstance()
 51    throws MetaConfigException, IOException {
 52  4 if (null == instance) {
 53  1 instance = new MetaConfig();
 54    }
 55  4 return instance;
 56    }
 57   
 58  1 private MetaConfig()
 59    throws MetaConfigException, IOException {
 60  1 m_state = MetaConfig.INIT;
 61  1 init();
 62    }
 63   
 64    // public interface
 65   
 66    /**
 67    * Read the meta-config file and load it in memory.
 68    * @param className the name of the class of which the properties are
 69    * required
 70    * @return the list of properties for this class, if class is registered,
 71    * otherwise null
 72    *
 73    * @author Siddhartha Azad
 74    * @since 2.4
 75    * */
 76  2 public List getConfigProperty(String className) {
 77  2 return (List)m_metaMap.get(className);
 78    }
 79   
 80    /**
 81    * Read the meta-config file and load it in memory.
 82    * Having to read my own property file without using the Java Property
 83    * class since I need to preserve the order of these properties, plus
 84    * I have duplicate labels.
 85    * @throws MetaConfigException
 86    * @throws IOException
 87    *
 88    * @author Siddhartha Azad
 89    * @since 2.4
 90    */
 91  1 protected void init()
 92    throws MetaConfigException, IOException {
 93  1 Reader fr = getReader(METACON_FILENAME);
 94  1 LineNumberReader lr = new LineNumberReader(fr);
 95  1 String line = lr.readLine();
 96  1 while (line != null) {
 97  11 if (!this.isComment(line)) {
 98  10 parseLine(line);
 99    }
 100  11 line = lr.readLine();
 101    }
 102  1 endState();
 103  1 lr.close();
 104    }
 105   
 106    /**
 107    * Returns a reader to a file
 108    * @param a_filename the file to retrieve a reader for
 109    * @throws IOException
 110    * @return the Reader
 111    *
 112    * @author Klaus Meffert
 113    * @since 3.0
 114    */
 115  1 public Reader getReader(String a_filename) throws IOException {
 116  1 File metaFile = new File(a_filename);
 117  1 FileReader fr = new FileReader(metaFile);
 118  1 return fr;
 119    }
 120   
 121    /**
 122    * Check whether a line is a comment. Any line starting with a '#' is a
 123    * comment.
 124    * @return true if a line is a comment, false if it is not
 125    *
 126    * @author Siddhartha Azad
 127    * @since 2.4
 128    * */
 129  11 private boolean isComment(String line) {
 130  11 String tmpLine = line.trim();
 131  11 StringBuffer sb = new StringBuffer(tmpLine);
 132  11 if (sb.charAt(0) == '#') {
 133  1 return true;
 134    }
 135  10 return false;
 136    }
 137   
 138    /**
 139    * Parse a line. This method is dispatches lines to other methods, hence
 140    * acting like a state machine.
 141    * @throws MetaConfigException
 142    *
 143    * @author Siddhartha Azad
 144    * @since 2.4
 145    * */
 146  10 private void parseLine(String a_line)
 147    throws MetaConfigException {
 148  10 String[] tokens = a_line.split("=");
 149  10 if (tokens == null || tokens.length != 2)
 150  0 throw new MetaConfigException(CN + ".parseLine():Exception while " +
 151    "parsing " + METACON_FILENAME + " line " +
 152    a_line + " is invalid");
 153  10 if (m_state == MetaConfig.INIT && tokens[0].equals("class")) {
 154  1 handleClass(tokens[1]);
 155    }
 156  9 else if (m_state == MetaConfig.CLASS && tokens[0].equals("property")) {
 157  2 handleProperty(tokens[1]);
 158    }
 159  7 else if (m_state == MetaConfig.PROPERTY && tokens[0].equals("values")) {
 160  3 handleValues(tokens[1]);
 161    }
 162  4 else if (m_state == MetaConfig.PROPERTY && tokens[0].equals("class")) {
 163  1 handleClass(tokens[1]);
 164    }
 165  3 else if (m_state == MetaConfig.VALUES && tokens[0].equals("class")) {
 166  0 handleClass(tokens[1]);
 167    }
 168  3 else if (m_state == MetaConfig.VALUES && tokens[0].equals("property")) {
 169  3 handleProperty(tokens[1]);
 170    }
 171    else {
 172  0 throw new MetaConfigException(CN + ".parseLine():Exception while "
 173    + "parsing " + METACON_FILENAME + " state "
 174    + m_state
 175    + " incompatible with line " + a_line);
 176    }
 177    }
 178   
 179    /**
 180    * Handle the state when a 'class' tag is found.
 181    * @author Siddhartha Azad
 182    * @since 2.4
 183    * */
 184  2 private void handleClass(final String a_token) {
 185  2 m_state = MetaConfig.CLASS;
 186  2 if (m_currProperty != null) {
 187  1 add(m_currName, m_currProperty);
 188    }
 189  2 m_currProperty = new ConfigProperty();
 190  2 m_currName = a_token;
 191    }
 192   
 193    /**
 194    * Handle the state when a 'property' tag is found.
 195    * @throws MetaConfigException
 196    *
 197    * @author Siddhartha Azad
 198    * @since 2.4
 199    * */
 200  5 private void handleProperty(final String a_token)
 201    throws MetaConfigException {
 202  5 int prevState = m_state;
 203  5 if (prevState == MetaConfig.VALUES) {
 204  3 if (m_currProperty != null) {
 205  3 add(m_currName, m_currProperty);
 206    }
 207    }
 208  5 m_currProperty = new ConfigProperty();
 209  5 m_state = MetaConfig.PROPERTY;
 210  5 String[] tokens = a_token.split(",");
 211  5 if (tokens.length < 2 || tokens.length > 3) {
 212  0 throw new MetaConfigException("Invalid format of property line: " +
 213    a_token);
 214    }
 215  5 m_currProperty.setName(tokens[0].trim());
 216  5 m_currProperty.setWidget(tokens[1].trim());
 217  5 if (tokens.length == 3) {
 218  0 m_currProperty.setLabel(tokens[2]);
 219    }
 220    }
 221   
 222    /**
 223    * Handle the state when a 'values' tag is found.
 224    * @param a_token the rhs of the values property
 225    * @throws MetaConfigException
 226    *
 227    * @author Siddhartha Azad
 228    * @since 2.4
 229    *
 230    * */
 231  3 private void handleValues(final String a_token)
 232    throws MetaConfigException {
 233  3 m_state = MetaConfig.VALUES;
 234  3 String[] tokens = a_token.split(",");
 235  3 if (tokens.length == 0) {
 236  0 throw new MetaConfigException("Invalid format of property line: " +
 237    a_token);
 238    }
 239  3 for (int i = 0; i < tokens.length; i++) {
 240  6 m_currProperty.addValue(tokens[i].trim());
 241    }
 242    }
 243   
 244    /**
 245    * Called once the EOF is encountered while parsing the file.
 246    *
 247    * @throws MetaConfigException if parsing ends in an invalid state
 248    *
 249    * @author Siddhartha Azad
 250    * @since 2.4
 251    * */
 252  1 private void endState()
 253    throws MetaConfigException {
 254  1 if (m_state != MetaConfig.PROPERTY && m_state != MetaConfig.VALUES) {
 255  0 throw new MetaConfigException("Invalid format of JGAP MetaConfig "
 256    + "file: " + METACON_FILENAME
 257    + "Ending in Invalid state : "
 258    + m_state);
 259    }
 260  1 if (m_currProperty != null) {
 261  1 add(m_currName, m_currProperty);
 262    }
 263    }
 264   
 265    /**
 266    * Add a new ConfigProperty for a certain class to the hashtable of
 267    * properties.
 268    * @param currName name of the class to which the property belongs
 269    * @param a_cp the ConfigProperty to be added to the class
 270    *
 271    * @author Siddhartha Azad
 272    * @since 2.4
 273    * */
 274  5 private void add(final String currName, ConfigProperty a_cp) {
 275  5 List props = (List) m_metaMap.get(currName);
 276  5 if (null == props) {
 277  2 props = Collections.synchronizedList(new ArrayList());
 278  2 m_metaMap.put(currName, props);
 279    }
 280  5 props.add(a_cp);
 281    }
 282    }