/* * TextToken.java * Copyright 2006 (C) James Dempsey <jdempsey@users.sourceforge.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Created on October 15, 2003, 10:23 PM * * Current Ver: $Revision: 199 $ * */ package plugin.exporttokens; import java.io.BufferedWriter; import java.io.IOException; import java.io.StringWriter; import java.math.BigDecimal; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; import pcgen.core.PlayerCharacter; import pcgen.io.ExportHandler; import pcgen.io.exporttoken.Token; import pcgen.util.Logging; /** * {@code TextToken} produces the output for the output token TEXT. * * Possible tag formats are:<pre> * TEXT.x.y * </pre> * * Where x is the action and y is the export tag to be processed. */ public class TextToken extends Token { /** Token Name */ public static final String TOKENNAME = "TEXT"; /** * @see pcgen.io.exporttoken.Token#getTokenName() */ @Override public String getTokenName() { return TOKENNAME; } /** * @see pcgen.io.exporttoken.Token#getToken(java.lang.String, pcgen.core.PlayerCharacter, pcgen.io.ExportHandler) */ @Override public String getToken(String tokenSource, PlayerCharacter pc, ExportHandler eh) { String retString = ""; StringTokenizer aTok = new StringTokenizer(tokenSource, "."); aTok.nextToken(); //this should be VAR String action = ""; StringBuilder varName = new StringBuilder(); if (aTok.hasMoreElements()) { action = aTok.nextToken(); if (action.startsWith("REPLACE")) { // Make sure that any "." in the token itself stay together while (action.charAt(action.length() - 1) != '}') { action += "." + aTok.nextToken(); } } } if (aTok.hasMoreElements()) { varName.append(aTok.nextToken()); } while (aTok.hasMoreElements()) { varName.append(".").append(aTok.nextToken()); } StringWriter writer = new StringWriter(); BufferedWriter bw = new BufferedWriter(writer); eh.replaceToken(varName.toString(), bw, pc); try { bw.flush(); } catch (IOException e) { e.printStackTrace(); } retString = writer.getBuffer().toString(); if (action.equalsIgnoreCase("UPPER") || action.equalsIgnoreCase("UPPERCASE")) { retString = retString.toUpperCase(); } else if (action.equalsIgnoreCase("LOWER") || action.equalsIgnoreCase("LOWERCASE")) { retString = retString.toLowerCase(); } else if (action.equalsIgnoreCase("SENTENCE") || action.equalsIgnoreCase("SENTENCECASE")) { retString = changeToSentenceCase(retString); } else if (action.equalsIgnoreCase("TITLE") || action.equalsIgnoreCase("TITLECASE")) { retString = changeToTitleCase(retString); } else if (action.equalsIgnoreCase("NUMSUFFIX")) { retString = buildNumSuffix(retString); } else if (action.equalsIgnoreCase("LENGTH")) { retString = String.valueOf(retString.length()); } // TEXT.REPLACEALL{regex,newtext} or // TEXT.REPLACEFIRST{regex,newtext} else if (action.startsWith("REPLACE")) { final String replaceType = action.substring(7, action.indexOf('{')); String args = action.substring(action.indexOf('{') + 1, action.length() - 1); int patternEnd = 0; for (;;) { patternEnd = args.indexOf(',', patternEnd); if (patternEnd <= 0) { break; } if (args.charAt(patternEnd - 1) != '\\') { break; } String temp = args.substring(0, patternEnd - 1); args = temp + args.substring(patternEnd, args.length()); } if (patternEnd <= 0) { Logging.errorPrint("Invalid REPLACE token"); } String pattern = args.substring(0, patternEnd); pattern = pattern.replaceAll("__LP__", "\\(").replaceAll("__RP__", "\\)").replaceAll("__PLUS__", "+"); final String replacement = args.substring(patternEnd + 1).trim().replaceFirst("^\"", "").replaceFirst("\"$", ""); if (replaceType.equalsIgnoreCase("ALL")) { retString = retString.replaceAll(pattern, replacement); } else if (replaceType.equalsIgnoreCase("FIRST")) { retString = retString.replaceFirst(pattern, replacement); } } return retString; } /** * Change the supplied string to sentence case. * * @param value The value to be modified. * @return The value in sentence case. */ private String changeToSentenceCase(String value) { String temp = value.toLowerCase(); String sentence[] = temp.split("\\."); StringBuilder res = new StringBuilder(value.length()); Pattern p = Pattern.compile("\\s*"); for (int i = 0; i < sentence.length; i++) { if (i > 0) { res.append("."); } if (!sentence[i].trim().isEmpty()) { Matcher m = p.matcher(sentence[i]); int pos = 0; if (m.find()) { pos = m.end(); } if (pos > 0) { res.append(sentence[i].substring(0, pos)); } res.append(sentence[i].substring(pos, pos + 1).toUpperCase()); res.append(sentence[i].substring(pos + 1)); } else { res.append(sentence[i]); } } return res.toString(); } /** * Change the supplied string to sentence case. * * @param value The value to be modified. * @return The value in sentence case. */ private String changeToTitleCase(String value) { String temp = value.toLowerCase(); char[] chars = temp.toCharArray(); StringBuilder res = new StringBuilder(value.length()); boolean start = true; for (int i = 0; i < chars.length; i++) { char c = chars[i]; boolean whiteSpace = (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r'); if (start && !whiteSpace) { res.append(Character.toUpperCase(c)); start = false; } else { start = whiteSpace; res.append(c); } } return res.toString(); } /** * Build the suffix for the provided number. * * @param number The number to generate the suffix for. * @return The suffix (or an empty string if not a number) */ private String buildNumSuffix(String number) { String result = ""; int intVal = 0; try { intVal = new BigDecimal(number).intValue(); } catch (Exception e) { // Not a number, so no suffix return ""; } if (intVal % 10 == 1 && intVal % 100 != 11) { result = "st"; } else if (intVal % 10 == 2 && intVal % 100 != 12) { result = "nd"; } else if (intVal % 10 == 3 && intVal % 100 != 13) { result = "rd"; } else { result = "th"; } return result; } /** * Never encode the plain text output * @return false */ @Override public boolean isEncoded() { return false; } }