Package com.instantiations.pde.build.preprocessor

Source Code of com.instantiations.pde.build.preprocessor.PropertiesFilePreprocessor

package com.instantiations.pde.build.preprocessor;

import java.io.PrintWriter;
import java.util.HashMap;
import java.util.regex.Pattern;

import com.instantiations.pde.build.util.BuildProperties;
import com.instantiations.pde.build.util.OemVersion;
import com.instantiations.pde.build.util.Version;
import com.objfac.prebop.Expression;
import com.objfac.prebop.PreprocessorError;

/**
* A preprocessor for *.properties files such as feature.properties and plugin.properties.
*/
public class PropertiesFilePreprocessor extends VariableReplacementPreprocessor
{
  private static final Pattern EXPRESSION_PATTERN = Pattern.compile("\\s*#\\s*\\$\\s*(if|elseif|else|endif)\\s+");

  private final HashMap<String, String> vars;

  protected PropertiesFilePreprocessor(OemVersion targetVersion, BuildProperties prop) {
    super(targetVersion.getVersion(), prop);
    this.vars = new HashMap<String, String>();
    this.vars.put("eclipse.version", targetVersion.getVersion().toString());
    this.vars.put("oem.name", targetVersion.getOemName() != null ? targetVersion.getOemName() : "none");
    lineProcessors.add(new ExpressionProcessor());
  }
 
  protected void endProcess(PrintWriter writer) {

    // Append the "build" property
    writer.println();
    writer.println("build = " + prop.getBuildNum());
   
    super.endProcess(writer);
  }

  private enum ExpressionState {
    NORMAL, // processing outside any expression
    INCLUDE, // in expression that evaluates true
    INCLUDE_ELSE, // in ELSE expression that should be uncommented
    EXCLUDE, // in expression but have not found a true expression yet
    EXCLUDE_ELSE, // in ELSE expression that should be commented
    EXCLUDE_REMAINING, // in expression but after block that evaluated true
  };
  private enum ExpressionType {
    IF, ELSEIF, ELSE, ENDIF
  }

  /**
   * Processor for $if, $elseif, $else, $endif expressions
   */
  private class ExpressionProcessor
    implements LineProcessor
  {
    ExpressionState state = ExpressionState.NORMAL;

    public void reset() {
      state = ExpressionState.NORMAL;
    }

    /**
     * Process the specified line
     */
    public String process(String line) {

      // If this is not a comment containing $if, $elseif, $else, $endif
      // then comment or uncomment the line as appropriate

      if (!EXPRESSION_PATTERN.matcher(line).find()) {
        switch (state) {
          case NORMAL :
            return line;
          case INCLUDE :
          case INCLUDE_ELSE :
            return uncommentLine(line);
          case EXCLUDE :
          case EXCLUDE_ELSE :
          case EXCLUDE_REMAINING :
            return commentLine(line);
          default :
            throw new IllegalStateException("Unexpected state " + state);
        }
      }

      // Determine the type of control statement: $if, $elseif, $else, $endif
      // and adjust the state accordingly
     
      ExpressionType expType = getExpType(line);
      switch (state) {

        case NORMAL :
          switch (expType) {
            case IF :
              state = evaluate(line) ? ExpressionState.INCLUDE : ExpressionState.EXCLUDE;
              return line;
            case ELSEIF :
            case ELSE :
            case ENDIF :
              throw new IllegalStateException("Expected \"if\", but found:\n" + line);
            default :
              throw new IllegalStateException("Unexpected Expression Type: " + expType);
          }

        case INCLUDE :
          switch (expType) {
            case IF :
              throw new IllegalStateException("Expected \"elseif\", \"else\", or \"endif\", but found:\n"
                + line);
            case ELSEIF :
              state = ExpressionState.EXCLUDE_REMAINING;
              return line;
            case ELSE :
              state = ExpressionState.EXCLUDE_ELSE;
              return line;
            case ENDIF :
              state = ExpressionState.NORMAL;
              return line;
            default :
              throw new IllegalStateException("Unexpected Expression Type: " + expType);
          }

        case EXCLUDE :
          switch (expType) {
            case IF :
              throw new IllegalStateException("Expected \"elseif\", \"else\", or \"endif\", but found:\n"
                + line);
            case ELSEIF :
              state = (evaluate(line) ? ExpressionState.INCLUDE : ExpressionState.EXCLUDE);
              return line;
            case ELSE :
              state = ExpressionState.INCLUDE_ELSE;
              return line;
            case ENDIF :
              state = ExpressionState.NORMAL;
              return line;
            default :
              throw new IllegalStateException("Unexpected Expression Type: " + expType);
          }

        case INCLUDE_ELSE :
        case EXCLUDE_ELSE :
          switch (expType) {
            case IF :
            case ELSEIF :
            case ELSE :
              throw new IllegalStateException("Expected \"endif\", but found:\n" + line);
            case ENDIF :
              state = ExpressionState.NORMAL;
              return line;
            default :
              throw new IllegalStateException("Unexpected Expression Type: " + expType);
          }

        case EXCLUDE_REMAINING :
          switch (expType) {
            case IF :
              throw new IllegalStateException("Expected \"elseif\", \"else\", or \"endif\", but found:\n"
                + line);
            case ELSEIF :
              state = ExpressionState.EXCLUDE_REMAINING;
              return line;
            case ELSE :
              state = ExpressionState.EXCLUDE_ELSE;
              return line;
            case ENDIF :
              state = ExpressionState.NORMAL;
              return line;
            default :
              throw new IllegalStateException("Unexpected Expression Type: " + expType);
          }

        default :
          throw new IllegalStateException("Unexpected state " + state);
      }
    }

    /**
     * Evaluate the expression
     *
     * @param line the line containing the expression
     * @return <code>true</code> if the expression evaluates <code>true</code>, else
     *         <code>false</code>
     */
    private boolean evaluate(String line) {
      Expression exp;
      try {
        exp = new Expression(line.getBytes(), line.indexOf("if") + 2, vars);
      }
      catch (PreprocessorError e) {
        throw new RuntimeException("Failed to contruct expression: " + line, e);
      }
      try {
        return exp.eval();
      }
      catch (PreprocessorError e) {
        throw new RuntimeException("Failed to process expression: " + line, e);
      }
    }

    /**
     * Answer an uncommented line
     *
     * @param line the original line
     * @return the original line uncommented
     */
    private String uncommentLine(String line) {
      if (line == null)
        return null;
      for (int i = 0; i < line.length(); i++) {
        char ch = line.charAt(i);
        if (ch == '#')
          return line.substring(i + 1);
        if (!Character.isWhitespace(ch))
          break;
      }
      return line;
    }

    /**
     * Answer a commented line
     *
     * @param line the original line
     * @return the original line commented
     */
    private String commentLine(String line) {
      if (line == null)
        return null;
      for (int i = 0; i < line.length(); i++) {
        char ch = line.charAt(i);
        if (ch == '#')
          return line;
        if (!Character.isWhitespace(ch))
          break;
      }
      return "# " + line;
    }

    /**
     * Determine if this is an $if, $elseif, or $endif
     *
     * @param line the line containing the expression
     * @return IF, ELSEIF, or ENDIF
     */
    private ExpressionType getExpType(String line) {
      int i = 0;
      while (!Character.isLetter(line.charAt(i)))
        i++;
      if (line.charAt(i) == 'i')
        return ExpressionType.IF;
      if (line.charAt(i) == 'e') {
        if (line.charAt(i + 1) == 'n')
          return ExpressionType.ENDIF;
        if (i + 4 < line.length() && line.charAt(i + 4) == 'i')
          return ExpressionType.ELSEIF;
        return ExpressionType.ELSE;
      }
      throw new IllegalStateException("Expected if, elseif, else, or endif in " + line);
    }
  }
}
TOP

Related Classes of com.instantiations.pde.build.preprocessor.PropertiesFilePreprocessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.