All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgap.data.config.MetaConfig Maven / Gradle / Ivy

/*
 * This file is part of JGAP.
 *
 * JGAP offers a dual license model containing the LGPL as well as the MPL.
 *
 * For licensing information please see the file license.txt included with JGAP
 * or have a look at the top of class org.jgap.Chromosome which representatively
 * includes the JGAP license policy applicable for any file delivered with JGAP.
 */
package org.jgap.data.config;

import java.util.*;
import java.io.*;

/**
 * This class provides an interface to the configuration information to create
 * a JGAP Configuration GUI.
 *
 * @author Siddhartha Azad
 * @since 2.4
 *
 */
public class MetaConfig {
  // file to read the GUI Configuration information from
  private static final String METACON_FILENAME = "jgap-meta.con";

  private static final String CN = "MetaConfig";

  // singleton instance
  private static MetaConfig instance;

  // ClassName-ConfigProperty mapping
  private Hashtable m_metaMap = new Hashtable();

  // state for the parser
  private int m_state;

  private static final int INIT = 0;

  private static final int CLASS = 1;

  private static final int PROPERTY = 2;

  private static final int VALUES = 3;

  // class name currently being handled
  private String m_currName;

  private ConfigProperty m_currProperty;

  public static MetaConfig getInstance()
      throws MetaConfigException, IOException {
    if (null == instance) {
      instance = new MetaConfig();
    }
    return instance;
  }

  private MetaConfig()
      throws MetaConfigException, IOException {
    m_state = MetaConfig.INIT;
    init();
  }

  // public interface

  /**
   * Read the meta-config file and load it in memory.
   * @param className the name of the class of which the properties are
   * required
   * @return the list of properties for this class, if class is registered,
   * otherwise null
   *
   * @author Siddhartha Azad
   * @since 2.4
   * */
  public List getConfigProperty(String className) {
    return (List)m_metaMap.get(className);
  }

  /**
   * Read the meta-config file and load it in memory.
   * Having to read my own property file without using the Java Property
   * class since I need to preserve the order of these properties, plus
   * I have duplicate labels.
   * @throws MetaConfigException
   * @throws IOException
   *
   * @author Siddhartha Azad
   * @since 2.4
   */
  protected void init()
      throws MetaConfigException, IOException {
    Reader fr = getReader(METACON_FILENAME);
    LineNumberReader lr = new LineNumberReader(fr);
    String line = lr.readLine();
    while (line != null) {
      if (!this.isComment(line)) {
        parseLine(line);
      }
      line = lr.readLine();
    }
    endState();
    lr.close();
  }

  /**
   * Returns a reader to a file
   * @param a_filename the file to retrieve a reader for
   * @throws IOException
   * @return the Reader
   *
   * @author Klaus Meffert
   * @since 3.0
   */
  public Reader getReader(String a_filename) throws IOException {
    File metaFile = new File(a_filename);
    FileReader fr = new FileReader(metaFile);
    return fr;
  }

  /**
   * Check whether a line is a comment. Any line starting with a '#' is a
   * comment.
   * @return true if a line is a comment, false if it is not
   *
   * @author Siddhartha Azad
   * @since 2.4
   * */
  private boolean isComment(String line) {
    String tmpLine = line.trim();
    StringBuffer sb = new StringBuffer(tmpLine);
    if (sb.charAt(0) == '#') {
      return true;
    }
    return false;
  }

  /**
   * Parse a line. This method is dispatches lines to other methods, hence
   * acting like a state machine.
   * @throws MetaConfigException
   *
   * @author Siddhartha Azad
   * @since 2.4
   * */
  private void parseLine(String a_line)
      throws MetaConfigException {
    String[] tokens = a_line.split("=");
    if (tokens == null || tokens.length != 2)
      throw new MetaConfigException(CN + ".parseLine():Exception while " +
                                    "parsing " + METACON_FILENAME + " line " +
                                    a_line + " is invalid");
    if (m_state == MetaConfig.INIT && tokens[0].equals("class")) {
      handleClass(tokens[1]);
    }
    else if (m_state == MetaConfig.CLASS && tokens[0].equals("property")) {
      handleProperty(tokens[1]);
    }
    else if (m_state == MetaConfig.PROPERTY && tokens[0].equals("values")) {
      handleValues(tokens[1]);
    }
    else if (m_state == MetaConfig.PROPERTY && tokens[0].equals("class")) {
      handleClass(tokens[1]);
    }
    else if (m_state == MetaConfig.VALUES && tokens[0].equals("class")) {
      handleClass(tokens[1]);
    }
    else if (m_state == MetaConfig.VALUES && tokens[0].equals("property")) {
      handleProperty(tokens[1]);
    }
    else {
      throw new MetaConfigException(CN + ".parseLine():Exception while "
                                    + "parsing " + METACON_FILENAME + " state "
                                    + m_state
                                    + " incompatible with line " + a_line);
    }
  }

  /**
   * Handle the state when a 'class' tag is found.
   * @author Siddhartha Azad
   * @since 2.4
   * */
  private void handleClass(final String a_token) {
    m_state = MetaConfig.CLASS;
    if (m_currProperty != null) {
      add(m_currName, m_currProperty);
    }
    m_currProperty = new ConfigProperty();
    m_currName = a_token;
  }

  /**
   * Handle the state when a 'property' tag is found.
   * @throws MetaConfigException
   *
   * @author Siddhartha Azad
   * @since 2.4
   * */
  private void handleProperty(final String a_token)
      throws MetaConfigException {
    int prevState = m_state;
    if (prevState == MetaConfig.VALUES) {
      if (m_currProperty != null) {
        add(m_currName, m_currProperty);
      }
    }
    m_currProperty = new ConfigProperty();
    m_state = MetaConfig.PROPERTY;
    String[] tokens = a_token.split(",");
    if (tokens.length < 2 || tokens.length > 3) {
      throw new MetaConfigException("Invalid format of property line: " +
                                    a_token);
    }
    m_currProperty.setName(tokens[0].trim());
    m_currProperty.setWidget(tokens[1].trim());
    if (tokens.length == 3) {
      m_currProperty.setLabel(tokens[2]);
    }
  }

  /**
   * Handle the state when a 'values' tag is found.
   * @param a_token the rhs of the values property
   * @throws MetaConfigException
   *
   * @author Siddhartha Azad
   * @since 2.4
   *
   * */
  private void handleValues(final String a_token)
      throws MetaConfigException {
    m_state = MetaConfig.VALUES;
    String[] tokens = a_token.split(",");
    if (tokens.length == 0) {
      throw new MetaConfigException("Invalid format of property line: " +
                                    a_token);
    }
    for (int i = 0; i < tokens.length; i++) {
      m_currProperty.addValue(tokens[i].trim());
    }
  }

  /**
   * Called once the EOF is encountered while parsing the file.
   *
   * @throws MetaConfigException if parsing ends in an invalid state
   *
   * @author Siddhartha Azad
   * @since 2.4
   * */
  private void endState()
      throws MetaConfigException {
    if (m_state != MetaConfig.PROPERTY && m_state != MetaConfig.VALUES) {
      throw new MetaConfigException("Invalid format of JGAP MetaConfig "
                                    + "file: " + METACON_FILENAME
                                    + "Ending in Invalid state : "
                                    + m_state);
    }
    if (m_currProperty != null) {
      add(m_currName, m_currProperty);
    }
  }

  /**
   * Add a new ConfigProperty for a certain class to the hashtable of
   * properties.
   * @param currName name of the class to which the property belongs
   * @param a_cp the ConfigProperty to be added to the class
   *
   * @author Siddhartha Azad
   * @since 2.4
   * */
  private void add(final String currName, ConfigProperty a_cp) {
    List props = (List) m_metaMap.get(currName);
    if (null == props) {
      props = Collections.synchronizedList(new ArrayList());
      m_metaMap.put(currName, props);
    }
    props.add(a_cp);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy