CharacterFormatter.java
/*
** Module : CharacterFormatter.java
** Abstract : Implements the Progress STRING(value, format) function for characters.
**
** Copyright (c) 2019-2023, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------Description---------------------------------
** 001 VVT 20210408 Created initial version.
** VVT 20210427 API changed: the format is now passed to class constructor.
** Method parse() renamed to format()
** 002 GBB 20230512 Logging methods replaced by CentralLogger/ConversionStatus.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.util;
import com.goldencode.p2j.util.logging.*;
import java.io.*;
/**
* Implements the Progress <code>STRING(value, format)</code> function
* for characters.
* <p>
* Example:
* <p>
* <pre>
* CharacterFormatter formatter = new CharacterFormatter("String to format", "x(8)");
* formatter.parse();
* String formatted = formatter.getValue(); // "String t"
* </pre>
*
*/
public class CharacterFormatter extends CharacterFormatParser
{
/** Logger */
private static final CentralLogger LOG = CentralLogger.get(CharacterFormatter.class);
/** The input format specification */
protected final String format;
/** The collector for the output formatted value */
private final StringBuilder out = new StringBuilder();
/** Reader on the input formatted string */
private final Reader in;
/**
* The constructor.
*
* @param format
* the format string
* @param value
* the value to format
*/
public CharacterFormatter(final String format, final String value)
{
this.format = format;
in = new StringReader(value);
}
/**
* Get the formatted value.
*
* @return see above
*/
public String getValue()
{
return out.toString();
}
/**
* Do the formatting.
*
* @return the formatted string.
*/
public String format()
{
parse(format);
return out.toString();
}
/**
* This method is called by {@link #format()} for each occurrence of
* a non-special character in format string.
*
* @param ch
* the format character
*/
@Override
protected void visitFillChar(final char ch)
{
out.append(ch);
}
/**
* This method is called by {@link #format()} for each occurrence of
* the 'a' (letter) special character in format string.
*
* @param repeatCount
* the special character repeat count
*/
@Override
protected void visitLetter(final int repeatCount)
{
processCharactersAsIs(repeatCount);
}
/**
* This method is called by {@link #format()} for each occurrence of
* the 'n' (alphanumeric) special character in format string.
*
* @param repeatCount
* the special character repeat count
*/
@Override
protected void visitAlphanum(final int repeatCount)
{
processCharactersAsIs(repeatCount);
}
/**
* This method is called by {@link #format()} for each occurrence of
* the 'x' (any character) special character in format string.
*
* @param repeatCount
* the special character repeat count
*/
@Override
protected void visitAnyChar(final int repeatCount)
{
processCharactersAsIs(repeatCount);
}
/**
* This method is called by {@link #format()} for each occurrence of
* the '9' (the digit) special character in format string.
*
* @param repeatCount
* the special character repeat count
*/
@Override
protected void visitDigit(final int repeatCount)
{
processCharactersAsIs(repeatCount);
}
/**
* This method is called by {@link #format()} for each occurrence of
* the '!' (upcase) special character in format string.
*
* @param repeatCount
* the special character repeat count
*/
@Override
protected void visitUpperLetter(final int repeatCount)
{
processCharacters(Character::toUpperCase, repeatCount);
}
/**
* Process characters with no conversion helper method.
*
* @param repeatCount
* the character repeat count
*/
private final void processCharactersAsIs(int repeatCount)
{
processCharacters(c -> c, repeatCount);
}
/**
* Process the action associated with a special formatting character.
*
* @param converter
* the character converter
* @param repeatCount
* the number of times the operation should repeat
*/
private final void processCharacters(final Convert converter, final int repeatCount)
{
try
{
for (int i = 0; i < repeatCount; i++)
{
final int read = in.read();
if (read == -1)
{
// No more input characters, pad with spaces
out.append(' ');
continue;
}
out.append(converter.convert((char) read));
}
}
catch (IOException e)
{
// Should never happen when reading from a string
LOG.severe("", e);
}
}
/**
* Helper method for character testers.
*
*/
private static interface Convert
{
/**
* Convert a character.
*
* @param c
* the character to test
*
* @return the result of conversion
*/
char convert(char c);
}
}