net.sf.jett.parser.MetadataParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jett-core Show documentation
Show all versions of jett-core Show documentation
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.
The 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 exhausted 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;
}
}