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

net.sf.jett.parser.MetadataParser Maven / Gradle / Ivy

Go to download

JETT is a Java API that reads an Excel spreadsheet as a template, takes your data, and creates a new Excel spreadsheet that contains your data, formatted as in the template. It works with .xls and .xlsx template spreadsheets.

There is a newer version: 0.11.0
Show newest version
package net.sf.jett.parser;

import java.util.Map;

import org.apache.poi.ss.usermodel.Cell;

import net.sf.jett.exception.MetadataParseException;
import net.sf.jett.util.SheetUtil;

/**
 * A MetadataParser parses metadata at the end of cell text.
 *
 * @author Randy Gettman
 */
public class MetadataParser
{
   /**
    * Metadata variable name for extra rows in the Block.
    */
   public static final String VAR_NAME_EXTRA_ROWS = "extraRows";
   /**
    * Metadata variable name for additional columns to the left in the Block.
    */
   public static final String VAR_NAME_LEFT = "left";
   /**
    * Metadata variable name for additional columns to the right in the Block.
    */
   public static final String VAR_NAME_RIGHT = "right";
   /**
    * Metadata variable name for copying right instead of down.  This is
    * ignored if neither "left" nor "right" is specified.
    */
   public static final String VAR_NAME_COPY_RIGHT = "copyRight";
   /**
    * Metadata variable name for not shifting other content out of the way of a
    * looping block.  This turns on the implicit version of the "fixed"
    * attribute of looping tags.
    */
   public static final String VAR_NAME_FIXED = "fixed";
   /**
    * Metadata variable name specifying the "past end action" to take whenever
    * a Collection is exhausted before the end of iteration.
    * @since 0.2.0
    */
   public static final String VAR_NAME_PAST_END_ACTION = "pastEndAction";
   /**
    * Metadata variable name specifying the value with which to replace any
    * expression that refers to a Collection that is exhausted
    * before the end of iteration.  This defaults to an empty string
    * "".  This is only relevant if the past end action is to
    * replace expressions.
    * @since 0.7.0
    */
   public static final String VAR_NAME_REPLACE_VALUE = "replaceValue";
   /**
    * Metadata variable name specifying to create an Excel grouping for rows,
    * columns, or no grouping.
    * @since 0.2.0
    */
   public static final String VAR_NAME_GROUP_DIR = "groupDir";
   /**
    * Metadata variable name specifying whether any Excel grouping created
    * should be collapsed, defaulting to false.
    * @since 0.2.0
    */
   public static final String VAR_NAME_COLLAPSE = "collapse";
   /**
    * Metadata variable name specifying a TagLoopListener to
    * listen for TagLoopEvents.
    * @since 0.3.0
    */
   public static final String VAR_NAME_ON_LOOP_PROCESSED = "onLoopProcessed";
   /**
    * Metadata variable name specifying a TagListener to listen
    * for TagEvents.
    * @since 0.3.0
    */
   public static final String VAR_NAME_ON_PROCESSED = "onProcessed";
   /**
    * Metadata variable name specifying the name of the zero-based "looping"
    * variable.
    * @since 0.3.0
    */
   public static final String VAR_NAME_INDEXVAR = "indexVar";
   /**
    * Metadata variable name specifying a limit to the number of iterations
    * processed.
    * @since 0.3.0
    */
   public static final String VAR_NAME_LIMIT = "limit";
   /**
    * Metadata variable name specifying the name of the
    * {@link net.sf.jett.model.LoopTagStatus} variable.
    * @since 0.9.1
    */
   public static final String VAR_NAME_VAR_STATUS = "varStatus";

   private Cell myCell;
   private boolean amIExpectingAValue;
   private String myMetadataText;
   private String myExtraRows;
   private String myColsLeft;
   private String myColsRight;
   private boolean amIDefiningCols;
   private String myCopyingRight;
   private String myFixed;
   private String myPastEndActionValue;
   private String myReplacementValue;
   private String myGroupDir;
   private String myCollapsingGroup;
   private String myTagLoopListener;
   private String myTagListener;
   private String myIndexVarName;
   private String myLimit;
   private String myVarStatusName;

   /**
    * Create a MetadataParser.
    */
   public MetadataParser()
   {
      setMetadataText("");
   }

   /**
    * Create a MetadataParser object that will parse the given
    * metadata text.
    * @param metadataText The text of the metadata.
    */
   public MetadataParser(String metadataText)
   {
      setMetadataText(metadataText);
   }

   /**
    * Sets the Cell that contains the formula to be parsed.
    * @param cell The Cell.
    * @since 0.7.0
    */
   public void setCell(Cell cell)
   {
      myCell = cell;
   }

   /**
    * Sets the metadata text to the given metadata text and resets the parser.
    * @param metadataText The new metadata text.
    */
   public void setMetadataText(String metadataText)
   {
      myMetadataText = metadataText;
      reset();
   }

   /**
    * Resets this MetadataParser, usually at creation time and
    * when new input arrives.
    */
   private void reset()
   {
      amIExpectingAValue = false;
      myExtraRows = null;
      myColsLeft = null;
      myColsRight = null;
      amIDefiningCols = false;
      myCopyingRight = null;
      myFixed = null;
      myPastEndActionValue = null;
      myReplacementValue = "";  // default to empty string
      myGroupDir = null;
      myCollapsingGroup = null;
      myTagLoopListener = null;
      myTagListener = null;
      myIndexVarName = null;
      myLimit = null;
   }

   /**
    * Parses the metadata text.
    */
   public void parse()
   {
      MetadataScanner scanner = new MetadataScanner(myMetadataText);
      Map abbr = getAbbreviations();

      MetadataScanner.Token token = scanner.getNextToken();
      if (token == MetadataScanner.Token.TOKEN_WHITESPACE)
         token = scanner.getNextToken();

      // Parse any metadata variable name/value pairs: varName=value.
      String varName = null;
      while (token.getCode() >= 0 && token != MetadataScanner.Token.TOKEN_EOI)
      {
         switch(token)
         {
         case TOKEN_WHITESPACE:
            // Ignore.
            break;
         case TOKEN_STRING:
            if (amIExpectingAValue)
            {
               String lexeme = scanner.getCurrLexeme();
               if (abbr != null && abbr.containsKey(varName))
               {
                  varName = abbr.get(varName);
               }

               // Add newly complete variable name/value pair.
               if (VAR_NAME_EXTRA_ROWS.equals(varName))
               {
                  myExtraRows = lexeme;
               }
               else if (VAR_NAME_LEFT.equals(varName))
               {
                  myColsLeft = lexeme;
                  amIDefiningCols = true;
               }
               else if (VAR_NAME_RIGHT.equals(varName))
               {
                  myColsRight = lexeme;
                  amIDefiningCols = true;
               }
               else if (VAR_NAME_COPY_RIGHT.equals(varName))
               {
                  myCopyingRight = lexeme;
               }
               else if (VAR_NAME_FIXED.equals(varName))
               {
                  myFixed = lexeme;
               }
               else if (VAR_NAME_PAST_END_ACTION.equals(varName))
               {
                  myPastEndActionValue = lexeme;
               }
               else if (VAR_NAME_REPLACE_VALUE.equals(varName))
               {
                  myReplacementValue = lexeme;
               }
               else if (VAR_NAME_GROUP_DIR.equals(varName))
               {
                  myGroupDir = lexeme;
               }
               else if (VAR_NAME_COLLAPSE.equals(varName))
               {
                  myCollapsingGroup = lexeme;
               }
               else if (VAR_NAME_ON_LOOP_PROCESSED.equals(varName))
               {
                  myTagLoopListener = lexeme;
               }
               else if (VAR_NAME_ON_PROCESSED.equals(varName))
               {
                  myTagListener = lexeme;
               }
               else if (VAR_NAME_INDEXVAR.equals(varName))
               {
                  myIndexVarName = lexeme;
               }
               else if (VAR_NAME_LIMIT.equals(varName))
               {
                  myLimit = lexeme;
               }
               else if (VAR_NAME_VAR_STATUS.equals(varName))
               {
                  myVarStatusName = lexeme;
               }
               else
               {
                  throw new MetadataParseException("Unrecognized variable name: \"" +
                     varName + "\"." + SheetUtil.getCellLocation(myCell));
               }
               if (isRestricted(varName))
               {
                  throw new MetadataParseException("Variable name \"" + varName +
                          "\" is restricted in this context.");
               }
               varName = null;
               amIExpectingAValue = false;
            }
            else
               varName = scanner.getCurrLexeme();
            break;
         case TOKEN_EQUALS:
            if (varName == null)
               throw new MetadataParseException("Variable name missing before \"=\": " + myMetadataText +
                       SheetUtil.getCellLocation(myCell));
            amIExpectingAValue = true;
            break;
         case TOKEN_SEMICOLON:
            // Just a delimiter between var/value pairs.
            break;
         case TOKEN_DOUBLE_QUOTE:
         case TOKEN_SINGLE_QUOTE:
            // These just delimit Strings.
            break;
         default:
            throw new MetadataParseException("Parse error occurred: " + myMetadataText + SheetUtil.getCellLocation(myCell));
         }
         token = scanner.getNextToken();
      }
      // Found end of input before attribute value found.
      if (varName != null)
         throw new MetadataParseException("Found end of metadata before equals sign at \"" +
            varName + "\": " + myMetadataText);
      if (amIExpectingAValue)
         throw new MetadataParseException("Found end of metadata before variable value: " + myMetadataText +
                 SheetUtil.getCellLocation(myCell));
      if (token.getCode() < 0)
         throw new MetadataParseException("Found end of input while scanning metadata value: " + myMetadataText +
                SheetUtil.getCellLocation(myCell));
   }

   /**
    * Determines whether the given metadata key is restricted -- not
    * allowed in this context.  Subclasses can override this method to
    * implement their own restricted lists.  This implementation doesn't
    * restrict anything - it always returns false.
    * @param metadataKey The metadata key.
    * @return true if it's restricted, else false.
    * @since 0.9.1
    */
   protected boolean isRestricted(String metadataKey)
   {
      return false;
   }

   /**
    * Returns a Map of abbreviations.  The map's keys are the
    * abbreviations, and the values are the metadata keys.
    * @return A Map of abbreviations, null means no
    *    abbreviations are permitted.
    * @since 0.9.1
    */
   protected Map getAbbreviations()
   {
      return null;
   }

   /**
    * Returns the "extra rows" lexeme.
    * @return The "extra rows" lexeme.
    */
   public String getExtraRows()
   {
      return myExtraRows;
   }

   /**
    * Returns the "columns left" lexeme.
    * @return The "columns left" lexeme.
    */
   public String getColsLeft()
   {
      return myColsLeft;
   }

   /**
    * Returns the "columns right" lexeme.
    * @return The "columns right" lexeme.
    */
   public String getColsRight()
   {
      return myColsRight;
   }

   /**
    * Returns whether column definitions are present.
    * @return Whether column definitions are present.
    */
   public boolean isDefiningCols()
   {
      return amIDefiningCols;
   }

   /**
    * Returns the "copy right" lexeme.
    * @return The "copy right" lexeme.
    */
   public String getCopyingRight()
   {
      return myCopyingRight;
   }

   /**
    * Returns the "fixed" lexeme.
    * @return The "fixed" lexeme.
    */
   public String getFixed()
   {
      return myFixed;
   }

   /**
    * Returns the "past end action" lexeme.
    * @return The "past end action" lexeme.
    * @since 0.2.0
    */
   public String getPastEndAction()
   {
      return myPastEndActionValue;
   }

   /**
    * Returns the replacement value, which is used to replace expressions that
    * have been exhaused prior to the end of iteration, if the past end action
    * is to replace expressions.
    * @return The replacement value, which defaults to an empty string
    *    "".
    * @since 0.7.0
    */
   public String getReplacementValue()
   {
      return myReplacementValue;
   }

   /**
    * Returns the "group dir" lexeme.
    * @return The "group dir" lexeme.
    * @since 0.2.0
    */
   public String getGroupDir()
   {
      return myGroupDir;
   }

   /**
    * Returns the "collapse" lexeme.
    * @return The "collapse" lexeme.
    * @since 0.2.0
    */
   public String getCollapsingGroup()
   {
      return myCollapsingGroup;
   }

   /**
    * Returns the "tag loop listener" lexeme.
    * @return The "tag loop listener" lexeme.
    * @since 0.3.0
    */
   public String getTagLoopListener()
   {
      return myTagLoopListener;
   }

   /**
    * Returns the "tag listener" lexeme.
    * @return The "tag listener" lexeme.
    * @since 0.3.0
    */
   public String getTagListener()
   {
      return myTagListener;
   }

   /**
    * Returns the "looping" variable name.
    * @return The "looping" variable name.
    * @since 0.3.0
    */
   public String getIndexVarName()
   {
      return myIndexVarName;
   }

   /**
    * Returns the "limit" lexeme.
    * @return The "limit" lexeme.
    * @since 0.3.0
    */
   public String getLimit()
   {
      return myLimit;
   }

   /**
    * Returns the "varStatus" lexeme.
    * @return The "varStatus" lexeme.
    * @since 0.9.1
    */
   public String getVarStatusName()
   {
      return myVarStatusName;
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy