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

com.adobe.xfa.ut.LcText Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright 2002 Adobe Systems Incorporated All Rights Reserved.
 *
 * NOTICE: All information contained herein is, and remains the property of
 * Adobe Systems Incorporated and its suppliers, if any. The intellectual and
 * technical concepts contained herein are proprietary to Adobe Systems
 * Incorporated and its suppliers and may be covered by U.S. and Foreign
 * Patents, patents in process, and are protected by trade secret or copyright
 * law. Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained from
 * Adobe Systems Incorporated.
 */

package com.adobe.xfa.ut;

/**
 * LcText defines objects in support
 * of XFA text picture patterns.
 * 
 * 

Text picture patterns are used to parse and format * text strings. Here are the metasymbols that form valid * text picture patterns: *

*
9
a single numeric character. *
A
a single alphabetic character. *
O
a single alphanumeric character. *
X
a single character. *
*
* * Here's a snippet of code illustrating the use of * {@link LcText} to reformat a text string *

 *      import com.adobe.xfa.ut.LcNum; 
 *      ...
 *      LcText text = new LcText("Agent 007", "'Agent '999");
 *      if (text.isValid())
 *          String s = text.format("999' bottles of beer ...'");
 *      text = new LcText("Ben-Vindo a Cozumel.",
 *                           "'Ben-Vindo a 'AAAAAAA.", "es_MX");
 *      if (text.isValid())
 *          String s = text.format("'Playa ' XXXXXXX");
 * 
* * @author Mike P. Tardif * * @exclude from published api. */ public class LcText { /** * LcText pattern symbols: 9AO0X. */ public static final String TEXT_PICTURE_SYMBOLS = "9AO0Xt"; /** * The text's locale. */ private final LcLocale mLocale; /** * The validity of this text. */ private boolean mbValid; /** * The parsed text. */ private StringBuilder msText; // JavaPort: Never referenced // /** // * The text's locale sensitive symbols. // */ // private Symbols mSymbols = new Symbols(); /** * The parsed number of characters. */ private int mnSignf; // JavaPort: Never referenced // /** // * An inner class to represent locale sensitive // * text symbols. // */ // private static class Symbols { // char zeroDigit; // } /** * Instantiates an LcText object from the given text * and in the locale given. * @param text * a text string. * @param locale * a locale name. When empty, it will default * to the default locale. */ public LcText(String text, String locale) { String sLocale = StringUtils.isEmpty(locale) ? LcLocale.getLocale() : locale; LcLocale lcLocale = new LcLocale(sLocale); mLocale = lcLocale.isValid() ? lcLocale : new LcLocale(LcLocale.DEFAULT_LOCALE); setTextSymbols(mLocale.getIsoName()); msText = new StringBuilder(text != null ? text : ""); mbValid = true; } /** * Instantiates an LcText object from the given text in the pattern * given and in the locale given. * @param text * a text string. * @param pat * a text pattern string used to parse the given text. * @param locale * a locale name. When empty, it will default * to the default locale. */ public LcText(String text, String pat, String locale) { this(text, locale); mbValid = parse(msText.toString(), pat); } /** * Formats this object according to given text pattern string. * @param pat * a text pattern string. * @return * the text string formatted according to the given pattern * string, upon success, and the empty string, upon error. */ public String format(String pat) { if (! mbValid) return ""; StringBuilder sRes = new StringBuilder(); try { char prevChr = 0; int chrCnt = 0; boolean inQuoted = false; boolean inQuoteQuoted = false; // // Foreach each character of the picture Do ... // int picLen = pat.length(); int txtLen = msText.length(); int txtIdx = 0; for (int i = 0; i < picLen; ) { int idx = 0; char chr = pat.charAt(i++); // // If seen a quote within a quoted string ... // if (inQuoteQuoted) { if (chr == '\'') { // cases like '...'' sRes.append(chr); chrCnt = 0; } else { // cases like '...'X inQuoted = false; chrCnt = 1; prevChr = chr; } inQuoteQuoted = false; } // // Elif within a quoted string ... // else if (inQuoted) { if (chr == '\'') { // cases like '...' inQuoteQuoted = true; } else { // cases like '...X sRes.append(chr); } chrCnt++; } // // Elif start of a quoted string ... // else if (chr == '\'') { if (chrCnt > 0) { // cases like ...X' StringBuilder s = new StringBuilder(); idx = subFormat(prevChr, chrCnt, txtIdx, s); if (s.length() == 0) return ""; sRes.append(s); txtIdx = idx; chrCnt = 0; prevChr = 0; } inQuoted = true; } // // Elif start of a metacharacter ... // else if (DateTimeUtil.matchChr(TEXT_PICTURE_SYMBOLS, chr) || ('a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z')) { if (chr != prevChr) { if (chrCnt > 0) { // cases like AAX StringBuilder s = new StringBuilder(); idx = subFormat(prevChr, chrCnt, txtIdx, s); if (s.length() == 0) return ""; sRes.append(s); txtIdx = idx; chrCnt = 0; } prevChr = chr; } chrCnt++; } // // Elif start of a literal ... // else { if (chrCnt > 0) { // cases like AA- StringBuilder s = new StringBuilder(); idx = subFormat(prevChr, chrCnt, txtIdx, s); if (s.length() == 0) return ""; sRes.append(s); txtIdx = idx; chrCnt = 0; } prevChr = 0; if (chr == '?' || chr == '*' || chr == '+') sRes.append(' '); else sRes.append(chr); } } // // Ensure quoted string is terminated. // if (inQuoteQuoted) inQuoted = false; if (inQuoted) return ""; // // Format any remaining items in the picture. // if (prevChr > 0 && chrCnt > 0) { // // Ensure there's enough source to format // Subtract the number of processed characters // from the total number of characters in the // source string. // int numSrcCharsLeft = txtLen - txtIdx; if (numSrcCharsLeft < chrCnt) return ""; StringBuilder s = new StringBuilder(); int idx = subFormat(prevChr, chrCnt, txtIdx, s); if (s.length() == 0) return ""; sRes.append(s); txtIdx = idx; } // // Ensure there's no more source to format. // if (txtIdx != 0 && txtIdx != txtLen) return ""; } catch(ExFull e) { sRes.setLength(0); } return sRes.toString(); } /** * Parse the text picture and return the number of symbols the picture implies. * @param pic - a picture pattern string. */ public static int getSymbolCount(String pic) { String sLoc = LcLocale.English_US; LcText oText = new LcText("", sLoc); oText.xlate(pic); return oText.mnSignf; } /** * Gets this object's parsed text. * @return * the text associated with this object. */ public String getText() { return msText.toString(); } /** * Determines if this object is valid. * @return * boolean true if valid, and false otherwise. */ public boolean isValid() { return mbValid; } /** * Parses the given string according to the text pattern given. * @param str * the text string to parse. * @param pat * a text pattern string. * @return * boolean true if successfully parsed, and false otherwise. */ public boolean parse(String str, String pat) { mbValid = false; int strPos = 0; char prevChr = 0; int chrCnt = 0; boolean inQuoted = false; boolean inQuoteQuoted = false; int strLen = str.length(); int picLen = pat.length(); StringBuilder sRes = new StringBuilder(); int resPos; // // Foreach each character of the picture Do ... // for (int i = 0; i < picLen; ) { char chr = pat.charAt(i++); if (strPos >= strLen) { if (inQuoted && chr == '\'') { inQuoteQuoted = true; break; } return false; } // // If seen a quote within a quoted string ... // if (inQuoteQuoted) { if (chr == '\'') { // cases like '...'' if (! DateTimeUtil.matchChr(str, strPos, chr, false)) return false; strPos += 1; chrCnt = 0; } else { // cases like '...'A inQuoted = false; chrCnt = 1; prevChr = chr; } inQuoteQuoted = false; } // // Elif within a quoted string ... // else if (inQuoted) { if (chr == '\'') { // cases like '...' inQuoteQuoted = true; } else { // cases like '...A if (! DateTimeUtil.matchChr(str, strPos, chr, false)) return false; strPos += 1; } chrCnt++; } // // Elif start of a quoted string ... // else if (chr == '\'') { if (chrCnt > 0) { // cases like AA' resPos = subParse(str, strPos, prevChr, chrCnt); if (resPos < 0) return false; if (DateTimeUtil.matchChr(TEXT_PICTURE_SYMBOLS, prevChr)) sRes.append(getStr(str, strPos, resPos)); strPos = resPos; chrCnt = 0; prevChr = 0; } inQuoted = true; } // // Elif start of a metacharacter ... // else if (DateTimeUtil.matchChr(TEXT_PICTURE_SYMBOLS, chr) || ('a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z')) { if (chr != prevChr) { if (chrCnt > 0) { // cases like AAX resPos = subParse(str, strPos, prevChr, chrCnt); if (resPos < 0) return false; if (DateTimeUtil.matchChr(TEXT_PICTURE_SYMBOLS, prevChr)) sRes.append(getStr(str, strPos, resPos)); strPos = resPos; chrCnt = 0; } prevChr = chr; } chrCnt++; } // // Elif start of a literal ... // else { if (chrCnt > 0) { // cases like AA- resPos = subParse(str, strPos, prevChr, chrCnt); if (resPos < 0) return false; if (DateTimeUtil.matchChr(TEXT_PICTURE_SYMBOLS, prevChr)) sRes.append(getStr(str, strPos, resPos)); strPos = resPos; chrCnt = 0; prevChr = 0; } if (chr == '?') { if (strPos < strLen && Character.isDefined(str.charAt(strPos))) strPos += 1; } else if (chr == '+') { if (strPos >= strLen || ! Character.isWhitespace(str.charAt(strPos))) return false; strPos += 1; while (strPos < strLen && Character.isWhitespace(str.charAt(strPos))) strPos += 1; } else if (chr == '*') { while (strPos < strLen && Character.isWhitespace(str.charAt(strPos))) strPos += 1; } else if (strPos < strLen && str.charAt(strPos) == chr) { strPos += 1; } else { return false; } } } // // Ensure quoted string is terminated. // if (inQuoteQuoted) inQuoted = false; if (inQuoted) return false; // // Parse any remaining items in the picture. // if (prevChr > 0 && chrCnt > 0) { // // Ensure there's enough source to format // Subtract the number of processed characters // from the total number of characters in the // source string. // int numSrcCharsLeft = strLen-strPos; if (numSrcCharsLeft < chrCnt) return false; resPos = subParse(str, strPos, prevChr, chrCnt); if (resPos < 0) return false; if (DateTimeUtil.matchChr(TEXT_PICTURE_SYMBOLS, prevChr)) sRes.append(getStr(str, strPos, resPos)); strPos = resPos; } // // Ensure there's no more source to parse. // if (strPos != strLen) return false; msText = sRes; return true; } /* * Gets a (previously matched) number of characters * from a given start position * to a given end position of the given string. * * @param src * the string to parse. * @param begPos * the beginning parsing position within the string. * @param endPos * the ending parsing position within the string. * @return * the characters matched. */ private String getStr(String src, int begPos, int endPos) { assert(begPos < endPos && endPos <= src.length()); StringBuilder s = new StringBuilder(); while (begPos < endPos) s.append(src.charAt(begPos++)); return s.toString(); } /* * Matches a number of alphabetics from a given start position * to a given end position of the given string. * * @param src * the string to parse. * @param begPos * the beginning parsing position within the string. * @param endPos * the ending parsing position within the string. * @return * the number of alphabetics matched, or -1 otherwise. */ private int matchAlphabetic(String src, int begPos, int endPos) { assert(begPos < endPos && endPos <= src.length()); boolean bAlphasSeen = false; int nAlphasSeen = 0; while (begPos < endPos) { char cUni = src.charAt(begPos++); if (! Character.isLetter(cUni)) break; bAlphasSeen = true; nAlphasSeen++; } return (bAlphasSeen) ? nAlphasSeen : -1; } /* * Matches a number of alphanumerics from a given start position * to a given end position of the given string. * * @param src * the string to parse. * @param begPos * the beginning parsing position within the string. * @param endPos * the ending parsing position within the string. * @return * the number of alphanumerics matched, or -1 otherwise. */ private int matchAlphanumeric(String src, int begPos, int endPos) { assert(begPos < endPos && endPos <= src.length()); boolean bAlphanumsSeen = false; int nAlphanumsSeen = 0; while (begPos < endPos) { char cUni = src.charAt(begPos++); if (! Character.isLetterOrDigit(cUni)) break; bAlphanumsSeen = true; nAlphanumsSeen++; } return (bAlphanumsSeen) ? nAlphanumsSeen : -1; } /* * Matches a number of characters from a given start position * to a given end position of the given string. * * @param src * the string to parse. * @param begPos * the beginning parsing position within the string. * @param endPos * the ending parsing position within the string. * @return * the number of characters matched, or -1 otherwise. */ private int matchCharacter(String src, int begPos, int endPos) { assert(begPos < endPos && endPos <= src.length()); boolean bCharsSeen = false; int nCharsSeen = 0; while (begPos < endPos) { char cUni = src.charAt(begPos++); if (! Character.isDefined(cUni)) break; bCharsSeen = true; nCharsSeen++; } return (bCharsSeen) ? nCharsSeen : -1; } /* * Match a number of numerics from a given start position * to a given end position of the given string. * * @param src * the string to parse. * @param begPos * the beginning parsing position within the string. * @param endPos * the ending parsing position within the string. * @return * the number of digits matched, or -1 otherwise. */ private int matchNumeric(String src, int begPos, int endPos) { assert(begPos < endPos && endPos <= src.length()); boolean bDigitsSeen = false; int nDigitsSeen = 0; while (begPos < endPos) { char cUni = src.charAt(begPos++); if (! Character.isDigit(cUni)) break; bDigitsSeen = true; nDigitsSeen++; } return (bDigitsSeen) ? nDigitsSeen : -1; } /* * Sets locale-specific text symbols for the given locale. * @param locale * a locale name. When empty, it will default * to the default locale. */ private void setTextSymbols(String locale) { //LcData oData = new LcData(locale); //mSymbols.zeroDigit = oData.getZeroSymbol().charAt(0); } /* * Formats a sub-element of a text pattern given the number of * occurances of a text pattern metacharacter. * * @param chr * a text pattern metacharacter. * @param chrCnt * the number of consecutive occurances of the metacharacter. * @param txtIdx * an index into this object's text string. * @param sRes * the formatted sub-element, or the empty upon error. * @return * the index into this object's text string. * @throws * an ExFull if the text value overflowed the field. */ private int subFormat(char chr, int chrCnt, int txtIdx, StringBuilder sRes) { assert(sRes != null); int retIdx = 0; int txtLen = msText.length(); while (chrCnt-- > 0 && txtIdx < txtLen) { char cUni; switch (chr) { case '9': // Numeric cUni = msText.charAt(txtIdx++); if (! Character.isDigit(cUni)) throw new ExFull(); sRes.append(cUni); break; case 'A': // Alphebetic cUni = msText.charAt(txtIdx++); if (! Character.isLetter(cUni)) throw new ExFull(); sRes.append(cUni); break; case 'O': // Alphanumeric case '0': cUni = msText.charAt(txtIdx++); if (! Character.isLetterOrDigit(cUni)) throw new ExFull(); sRes.append(cUni); break; case 'X': // Anything cUni = msText.charAt(txtIdx++); sRes.append(cUni); break; case 't': sRes.append('\t'); break; default: sRes.append(chr); break; } retIdx = txtIdx; } return retIdx; } /* * Parses a sub-element at a given position of the given string, * given the number of occurrences of a text pattern metacharacter. * * @param src * the text string to parse. * @param srcPos * the starting parsing position within the text string. * @param chr * a text pattern metacharacter. * @param chrCnt * the number of consecutive occurances of the metacharacter. * @return * the ending parsing position within the text string * if successfully parsed, and -1 otherwise. */ private int subParse(String src, int srcPos, char chr, int chrCnt) { int len; switch (chr) { case '9': // Numeric len = matchNumeric(src, srcPos, srcPos + chrCnt); if (len != chrCnt) return -1; srcPos = DateTimeUtil.incPos(src, srcPos, len); break; case 'A': // Alphebetic len = matchAlphabetic(src, srcPos, srcPos + chrCnt); if (len != chrCnt) return -1; srcPos = DateTimeUtil.incPos(src, srcPos, len); break; case 'O': // Alphanumeric case '0': len = matchAlphanumeric(src, srcPos, srcPos + chrCnt); if (len != chrCnt) return -1; srcPos = DateTimeUtil.incPos(src, srcPos, len); break; case 'X': // Anything len = matchCharacter(src, srcPos, srcPos + chrCnt); if (len != chrCnt) return -1; srcPos = DateTimeUtil.incPos(src, srcPos, len); break; case 't': // tab while (chrCnt-- > 0) { if (src.charAt(srcPos) != '\t') return -1; srcPos += 1; } break; default: if (src.charAt(srcPos) != chr) return -1; srcPos += 1; break; } return srcPos; } /* * Translate a sub-element of a text pattern given the number of * occurrences of a text pattern meta-character. * * Parameters: * chr -- a text pattern meta-character. * chrCnt -- the number of consecutive occurrences of the meta-character. * * Return Value: * the translated sub-element, or the empty string upon error. * * Exceptions: * jfExFull if sub-elements aren't translated in the proper * sequence. */ private String subXlate(char chr, int chrCnt) { StringBuilder sRes = new StringBuilder(); for (int i = 0; i < chrCnt; i++) sRes.append(chr); // // Re-map any full width meta symbol back to ASCII. // if (0xFF01 <= chr && chr <= 0xFF5E) { chr -= 0xFFE0; chr &= 0x00FF; } if (chr == '9' || chr == 'A' || chr == 'O' || chr == '0' || chr == 'X') { mnSignf += chrCnt; } return sRes.toString(); } /* * Translate a text picture pattern into something else .easily * In the process, flag: * the number of significant digits, * * Parameters: * pic -- a text picture pattern. * * Return Value: * the translated picture. * * Exceptions: * jfExFull if the picture pattern is not valid. */ private String xlate(String pic) { // // Reset the state formatting flags. // mnSignf = 0; // // Initialize finite state scanner. Only operate on previous // character when there's a "state" change triggered by the // current pattern character. // String sRes = null; char prevChr = 0; int chrCnt = 0; boolean inQuoted = false; boolean inQuoteQuoted = false; // // For each character of the pattern Do ... // int picLen = pic.length(); for (int i = 0; i < picLen; ) { char chr = pic.charAt(i++); // // If seen a quote within a quoted string ... // if (inQuoteQuoted) { if (chr == '\'') { // cases like '...'' sRes += chr; chrCnt = 0; } else { // cases like '...'9 inQuoted = false; chrCnt = 1; prevChr = chr; } inQuoteQuoted = false; } // // Else if within a quoted string ... // else if (inQuoted) { if (chr == '\'') // cases like '...' inQuoteQuoted = true; sRes += chr; chrCnt = 0; prevChr = chr; } // // Else if start of a quoted string ... // else if (chr == '\'') { if (chrCnt > 0) { // cases like ...9' sRes += subXlate(prevChr, chrCnt); chrCnt = 0; prevChr = 0; } sRes += chr; inQuoted = true; } // // Else if its a meta-character ... // else if (DateTimeUtil.matchChr(TEXT_PICTURE_SYMBOLS, chr) || ('a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z')) { if (prevChr != chr) { if (chrCnt > 0) { // cases like ZZ9 or :9 sRes += subXlate(prevChr, chrCnt); prevChr = chr; chrCnt = 1; } else { prevChr = chr; chrCnt++; } } else { chrCnt++; } } // // Else if start of a literal ... // else { if (chrCnt > 0) { // cases like 99- sRes += subXlate(prevChr, chrCnt); chrCnt = 0; } prevChr = 0; sRes += chr; } } // // Ensure quoted string is terminated. // if (inQuoteQuoted) inQuoted = false; if (inQuoted) throw new ExFull(); // // Format any remaining items in the pattern. // if (prevChr > 0 && chrCnt > 0) sRes += subXlate(prevChr, chrCnt); return sRes; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy