You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mb...@apache.org on 2008/02/25 20:51:26 UTC
svn commit: r630969 - in /commons/proper/lang/trunk/src:
java/org/apache/commons/lang/text/ test/org/apache/commons/lang/text/
Author: mbenson
Date: Mon Feb 25 11:51:18 2008
New Revision: 630969
URL: http://svn.apache.org/viewvc?rev=630969&view=rev
Log:
[LANG-362] simplify ExtendedMessageFormat design; recycle as much of super implementation as possible
Added:
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/FormatFactory.java (with props)
Removed:
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/ChoiceMetaFormat.java
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/DateMetaFormat.java
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/DateMetaFormatSupport.java
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/DefaultMetaFormatFactory.java
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/MetaFormatSupport.java
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/NameKeyedMetaFormat.java
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/NumberMetaFormat.java
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/TimeMetaFormat.java
Modified:
commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/ExtendedMessageFormat.java
commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/ExtendedMessageFormatBaselineTest.java
commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/MessageFormatExtensionTest.java
Modified: commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/ExtendedMessageFormat.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/ExtendedMessageFormat.java?rev=630969&r1=630968&r2=630969&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/ExtendedMessageFormat.java (original)
+++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/ExtendedMessageFormat.java Mon Feb 25 11:51:18 2008
@@ -20,25 +20,19 @@
import java.text.MessageFormat;
import java.text.ParsePosition;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.Locale;
+import java.util.Map;
-import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
/**
* Extends <code>MessageFormat</code> to allow pluggable/additional formatting
- * options for embedded format elements; requires a "meta-format", that is a
- * <code>Format</code> capable of parsing and formatting other
- * <code>Format</code>s.
- *
- * Limitations:
- * <ul>
- * <li><code>toPattern()</code> results are tailored to JDK 1.4+ output and
- * will produce fairly drastically different results on earlier JDKs.</li>
- * <li>Recursive choice formats do not inherit knowledge of the extended
- * formatters and are limited to those available with
- * <code>java.text.MessageFormat</code>.</li>
- * </ul>
+ * options for embedded format elements; requires elaboration.
+ *
+ * Note that the mutator methods for the replacement Formats are to be considered
+ * unnecessary and thus have been disabled (UnsupportedOperationException).
*
* @author Matt Benson
* @since 2.4
@@ -47,389 +41,401 @@
public class ExtendedMessageFormat extends MessageFormat {
private static final long serialVersionUID = -2362048321261811743L;
+ private static final String DUMMY_PATTERN = "";
+ private static final String ESCAPED_QUOTE = "''";
+ private static final char START_FMT = ',';
+ private static final char END_FE = '}';
+ private static final char START_FE = '{';
+ private static final char QUOTE = '\'';
+
+ private String toPattern;
+ private Map registry;
+
/**
- * Get a default meta-format for the default Locale. This will produce
- * behavior identical to a <code>java.lang.MessageFormat</code> using the
- * default locale.
+ * Create a new ExtendedMessageFormat for the default locale.
*
- * @return Format
+ * @param pattern String
+ * @throws IllegalArgumentException in case of a bad pattern.
*/
- public static Format createDefaultMetaFormat() {
- return createDefaultMetaFormat(Locale.getDefault());
+ public ExtendedMessageFormat(String pattern) {
+ this(pattern, Locale.getDefault());
}
/**
- * Get a default meta-format for the specified Locale. This will produce
- * behavior identical to a <code>java.lang.MessageFormat</code> using
- * <code>locale</code>.
+ * Create a new ExtendedMessageFormat.
*
- * @param locale the Locale for the resulting Format instance.
- * @return Format
+ * @param pattern String
+ * @param locale Locale
+ * @throws IllegalArgumentException in case of a bad pattern.
*/
- public static Format createDefaultMetaFormat(Locale locale) {
- return DefaultMetaFormatFactory.getFormat(locale);
+ public ExtendedMessageFormat(String pattern, Locale locale) {
+ this(pattern, locale, null);
}
/**
- * Conceptual demarcation of methods to parse the pattern.
+ * Create a new ExtendedMessageFormat for the default locale.
+ *
+ * @param pattern String
+ * @param registry Registry of format factories: Map<String, FormatFactory>
+ * @throws IllegalArgumentException in case of a bad pattern.
*/
- private static class Parser {
- private static final String ESCAPED_QUOTE = "''";
- private static final char START_FMT = ',';
- private static final char END_FE = '}';
- private static final char START_FE = '{';
- private static final char QUOTE = '\'';
-
- /**
- * Strip all formats from the pattern.
- *
- * @param pattern String to strip
- * @return stripped pattern
- */
- private String stripFormats(String pattern) {
- StringBuffer sb = new StringBuffer(pattern.length());
- ParsePosition pos = new ParsePosition(0);
- char[] c = pattern.toCharArray();
- while (pos.getIndex() < pattern.length()) {
- switch (c[pos.getIndex()]) {
- case QUOTE:
- appendQuotedString(pattern, pos, sb, true);
- break;
- case START_FE:
- int start = pos.getIndex();
- readArgumentIndex(pattern, next(pos));
- sb.append(c, start, pos.getIndex() - start);
- if (c[pos.getIndex()] == START_FMT) {
- eatFormat(pattern, next(pos));
- }
- if (c[pos.getIndex()] != END_FE) {
- throw new IllegalArgumentException(
- "Unreadable format element at position "
- + start);
- }
- // fall through
- default:
- sb.append(c[pos.getIndex()]);
- next(pos);
- }
- }
- return sb.toString();
- }
+ public ExtendedMessageFormat(String pattern, Map registry) {
+ this(pattern, Locale.getDefault(), registry);
+ }
- /**
- * Insert formats back into the pattern for toPattern() support.
- *
- * @param pattern source
- * @param formats the Formats to insert
- * @param metaFormat Format to format the Formats
- * @return full pattern
- */
- private String insertFormats(String pattern, Format[] formats,
- Format metaFormat) {
- if (formats == null || formats.length == 0) {
- return pattern;
- }
- StringBuffer sb = new StringBuffer(pattern.length() * 2);
- ParsePosition pos = new ParsePosition(0);
- int fe = -1;
- while (pos.getIndex() < pattern.length()) {
- char c = pattern.charAt(pos.getIndex());
- switch (c) {
- case QUOTE:
- appendQuotedString(pattern, pos, sb, false);
- break;
- case START_FE:
- fe++;
- sb.append(START_FE).append(
- readArgumentIndex(pattern, next(pos)));
- if (formats[fe] != null) {
- String formatName = metaFormat.format(formats[fe]);
- if (StringUtils.isNotEmpty(formatName)) {
- sb.append(START_FMT).append(formatName);
- }
- }
- break;
- default:
- sb.append(pattern.charAt(pos.getIndex()));
- next(pos);
- }
- }
- return sb.toString();
- }
+ /**
+ * Create a new ExtendedMessageFormat.
+ *
+ * @param pattern String
+ * @param locale Locale
+ * @param registry Registry of format factories: Map<String, FormatFactory>
+ * @throws IllegalArgumentException in case of a bad pattern.
+ */
+ public ExtendedMessageFormat(String pattern, Locale locale, Map registry) {
+ super(DUMMY_PATTERN, locale);
+ this.registry = registry;
+ applyPattern(pattern);
+ }
- /**
- * Parse the formats from the given pattern.
- *
- * @param pattern String to parse
- * @param metaFormat Format to parse the Formats
- * @return array of parsed Formats
- */
- private Format[] parseFormats(String pattern, Format metaFormat) {
- ArrayList result = new ArrayList();
- ParsePosition pos = new ParsePosition(0);
- while (pos.getIndex() < pattern.length()) {
- switch (pattern.charAt(pos.getIndex())) {
- case QUOTE:
- getQuotedString(pattern, next(pos), true);
- break;
- case START_FE:
- int start = pos.getIndex();
- readArgumentIndex(pattern, next(pos));
- if (pattern.charAt(pos.getIndex()) == START_FMT) {
- seekNonWs(pattern, next(pos));
- }
- result.add(metaFormat.parseObject(pattern, pos));
- seekNonWs(pattern, pos);
- if (pattern.charAt(pos.getIndex()) != END_FE) {
- throw new IllegalArgumentException(
- "Unreadable format element at position "
- + start);
- }
- // fall through
- default:
- next(pos);
- }
- }
- return (Format[]) result.toArray(new Format[result.size()]);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public String toPattern() {
+ return toPattern;
+ }
- /**
- * Consume whitespace from the current parse position.
- *
- * @param pattern String to read
- * @param pos current position
- */
- private void seekNonWs(String pattern, ParsePosition pos) {
- int len = 0;
- char[] buffer = pattern.toCharArray();
- do {
- len = StrMatcher.splitMatcher().isMatch(buffer, pos.getIndex());
- pos.setIndex(pos.getIndex() + len);
- } while (len > 0 && pos.getIndex() < pattern.length());
- }
-
- /**
- * Convenience method to advance parse position by 1
- *
- * @param pos ParsePosition
- * @return <code>pos</code>
- */
- private ParsePosition next(ParsePosition pos) {
- pos.setIndex(pos.getIndex() + 1);
- return pos;
- }
-
- /**
- * Read the argument index from the current format element
- *
- * @param pattern pattern to parse
- * @param pos current parse position
- * @return argument index as string
- */
- private String readArgumentIndex(String pattern, ParsePosition pos) {
- int start = pos.getIndex();
- for (; pos.getIndex() < pattern.length(); next(pos)) {
- char c = pattern.charAt(pos.getIndex());
- if (c == START_FMT || c == END_FE) {
- return pattern.substring(start, pos.getIndex());
+ /**
+ * Apply the specified pattern.
+ *
+ * @param pattern String
+ */
+ public final void applyPattern(String pattern) {
+ if (registry == null) {
+ super.applyPattern(pattern);
+ toPattern = super.toPattern();
+ return;
+ }
+ ArrayList foundFormats = new ArrayList();
+ ArrayList foundDescriptions = new ArrayList();
+ StringBuffer stripCustom = new StringBuffer(pattern.length());
+
+ ParsePosition pos = new ParsePosition(0);
+ char[] c = pattern.toCharArray();
+ int fmtCount = 0;
+ while (pos.getIndex() < pattern.length()) {
+ switch (c[pos.getIndex()]) {
+ case QUOTE:
+ appendQuotedString(pattern, pos, stripCustom, true);
+ break;
+ case START_FE:
+ fmtCount++;
+ seekNonWs(pattern, pos);
+ int start = pos.getIndex();
+ int index = readArgumentIndex(pattern, next(pos));
+ stripCustom.append(START_FE).append(index);
+ seekNonWs(pattern, pos);
+ Format format = null;
+ String formatDescription = null;
+ if (c[pos.getIndex()] == START_FMT) {
+ formatDescription = parseFormatDescription(pattern,
+ next(pos));
+ format = getFormat(formatDescription);
+ if (format == null) {
+ stripCustom.append(START_FMT).append(formatDescription);
+ }
}
- if (!Character.isDigit(c)) {
+ foundFormats.add(format);
+ foundDescriptions.add(format == null ? null : formatDescription);
+ Validate.isTrue(foundFormats.size() == fmtCount);
+ Validate.isTrue(foundDescriptions.size() == fmtCount);
+ if (c[pos.getIndex()] != END_FE) {
throw new IllegalArgumentException(
- "Invalid format argument index at position "
- + start);
+ "Unreadable format element at position " + start);
}
+ // fall through
+ default:
+ stripCustom.append(c[pos.getIndex()]);
+ next(pos);
}
- throw new IllegalArgumentException(
- "Unterminated format element at position " + start);
}
-
- /**
- * Consume a quoted string, adding it to <code>appendTo</code> if
- * specified.
- *
- * @param pattern pattern to parse
- * @param pos current parse position
- * @param appendTo optional StringBuffer to append
- * @param escapingOn whether to process escaped quotes
- * @return <code>appendTo</code>
- */
- private StringBuffer appendQuotedString(String pattern,
- ParsePosition pos, StringBuffer appendTo, boolean escapingOn) {
- int start = pos.getIndex();
- char[] c = pattern.toCharArray();
- if (escapingOn && c[start] == QUOTE) {
- return appendTo == null ? null : appendTo.append(QUOTE);
- }
- int lastHold = start;
- for (int i = pos.getIndex(); i < pattern.length(); i++) {
- if (escapingOn
- && pattern.substring(i).startsWith(ESCAPED_QUOTE)) {
- appendTo.append(c, lastHold, pos.getIndex() - lastHold)
- .append(QUOTE);
- pos.setIndex(i + ESCAPED_QUOTE.length());
- lastHold = pos.getIndex();
- continue;
- }
- switch (c[pos.getIndex()]) {
- case QUOTE:
- next(pos);
- return appendTo == null ? null : appendTo.append(c,
- lastHold, pos.getIndex() - lastHold);
- default:
- next(pos);
+ super.applyPattern(stripCustom.toString());
+ toPattern = insertFormats(super.toPattern(), foundDescriptions);
+ if (containsElements(foundFormats)) {
+ Format[] origFormats = getFormats();
+ for (int i = 0; i < origFormats.length; i++) {
+ Format f = (Format) foundFormats.get(i);
+ if (f != null) {
+ origFormats[i] = f;
}
}
- throw new IllegalArgumentException(
- "Unterminated quoted string at position " + start);
+ super.setFormats(origFormats);
}
+ }
- /**
- * Consume quoted string only
- *
- * @param pattern pattern to parse
- * @param pos current parse position
- * @param escapingOn whether to process escaped quotes
- */
- private void getQuotedString(String pattern, ParsePosition pos,
- boolean escapingOn) {
- appendQuotedString(pattern, pos, null, escapingOn);
- }
-
- /**
- * Consume the entire format found at the current position.
- *
- * @param pattern string to parse
- * @param pos current parse position
- */
- private void eatFormat(String pattern, ParsePosition pos) {
- int start = pos.getIndex();
- int depth = 1;
- for (; pos.getIndex() < pattern.length(); next(pos)) {
- switch (pattern.charAt(pos.getIndex())) {
- case START_FE:
- depth++;
- break;
- case END_FE:
- depth--;
- if (depth == 0) {
- return;
- }
- break;
- case QUOTE:
- getQuotedString(pattern, pos, false);
- break;
- }
- }
- throw new IllegalArgumentException(
- "Unterminated format element at position " + start);
- }
+ /**
+ * {@inheritDoc}
+ * UNSUPPORTED
+ */
+ public void setFormat(int formatElementIndex, Format newFormat) {
+ throw new UnsupportedOperationException();
}
- private static final Parser PARSER = new Parser();
+ /**
+ * {@inheritDoc}
+ * UNSUPPORTED
+ */
+ public void setFormatByArgumentIndex(int argumentIndex, Format newFormat) {
+ throw new UnsupportedOperationException();
+ }
- private Format metaFormat;
- private String strippedPattern;
+ /**
+ * {@inheritDoc}
+ * UNSUPPORTED
+ */
+ public void setFormats(Format[] newFormats) {
+ throw new UnsupportedOperationException();
+ }
/**
- * Create a new ExtendedMessageFormat for the default locale.
- *
- * @param pattern String
- * @param metaFormat Format
- * @throws IllegalArgumentException if <code>metaFormat</code> is
- * <code>null</code> or in case of a bad pattern.
+ * {@inheritDoc}
+ * UNSUPPORTED
*/
- public ExtendedMessageFormat(String pattern, Format metaFormat) {
- this(pattern, Locale.getDefault(), metaFormat);
+ public void setFormatsByArgumentIndex(Format[] newFormats) {
+ throw new UnsupportedOperationException();
}
/**
- * Create a new ExtendedMessageFormat.
+ * Get a custom format from a format description.
*
- * @param pattern String
- * @param locale Locale
- * @param metaFormat Format
- * @throws IllegalArgumentException if <code>metaFormat</code> is
- * <code>null</code> or in case of a bad pattern.
- */
- public ExtendedMessageFormat(String pattern, Locale locale,
- Format metaFormat) {
- /*
- * We have to do some acrobatics here: the call to the super constructor
- * will invoke applyPattern(), but we don't want to apply the pattern
- * until we've installed our custom metaformat. So we check for that in
- * our (final) applyPattern implementation, and re-call at the end of
- * this constructor.
- */
- super(pattern);
- setLocale(locale);
- setMetaFormat(metaFormat);
- applyPattern(pattern);
+ * @param desc String
+ * @return Format
+ */
+ private Format getFormat(String desc) {
+ if (registry != null) {
+ String name = desc;
+ String args = null;
+ int i = desc.indexOf(START_FMT);
+ if (i > 0) {
+ name = desc.substring(0, i).trim();
+ args = desc.substring(i + 1).trim();
+ }
+ FormatFactory factory = (FormatFactory) registry.get(name);
+ if (factory != null) {
+ return factory.getFormat(name, args, getLocale());
+ }
+ }
+ return null;
}
/**
- * Apply the specified pattern.
+ * Read the argument index from the current format element
*
- * @param pattern String
- */
- public final void applyPattern(String pattern) {
- if (metaFormat == null) {
- return;
+ * @param pattern pattern to parse
+ * @param pos current parse position
+ * @return argument index
+ */
+ private int readArgumentIndex(String pattern, ParsePosition pos) {
+ int start = pos.getIndex();
+ seekNonWs(pattern, pos);
+ StringBuffer result = new StringBuffer();
+ boolean error = false;
+ for (; !error && pos.getIndex() < pattern.length(); next(pos)) {
+ char c = pattern.charAt(pos.getIndex());
+ if (Character.isWhitespace(c)) {
+ seekNonWs(pattern, pos);
+ c = pattern.charAt(pos.getIndex());
+ if (c != START_FMT && c != END_FE) {
+ error = true;
+ continue;
+ }
+ }
+ if ((c == START_FMT || c == END_FE) && result.length() > 0) {
+ try {
+ return Integer.parseInt(result.toString());
+ } catch (NumberFormatException e) {
+ //we've already ensured only digits, so unless something outlandishly large was specified we should be okay.
+ }
+ }
+ error = !Character.isDigit(c);
+ result.append(c);
}
- applyPatternPre(pattern);
- strippedPattern = PARSER.stripFormats(pattern);
- super.applyPattern(strippedPattern);
- setFormats(PARSER.parseFormats(pattern, metaFormat));
- applyPatternPost(pattern);
+ if (error) {
+ throw new IllegalArgumentException(
+ "Invalid format argument index at position " + start + ": "
+ + pattern.substring(start, pos.getIndex()));
+ }
+ throw new IllegalArgumentException(
+ "Unterminated format element at position " + start);
}
/**
- * Pre-execution hook by means of which a subclass can customize the
- * behavior of the final applyPattern implementation.
+ * Parse the format component of a format element.
*
- * @param pattern String
+ * @param pattern string to parse
+ * @param pos current parse position
+ * @return Format description String
+ */
+ private String parseFormatDescription(String pattern, ParsePosition pos) {
+ int start = pos.getIndex();
+ seekNonWs(pattern, pos);
+ int text = pos.getIndex();
+ int depth = 1;
+ for (; pos.getIndex() < pattern.length(); next(pos)) {
+ switch (pattern.charAt(pos.getIndex())) {
+ case START_FE:
+ depth++;
+ break;
+ case END_FE:
+ depth--;
+ if (depth == 0) {
+ return pattern.substring(text, pos.getIndex());
+ }
+ break;
+ case QUOTE:
+ getQuotedString(pattern, pos, false);
+ break;
+ }
+ }
+ throw new IllegalArgumentException(
+ "Unterminated format element at position " + start);
+ }
+
+ /**
+ * Insert formats back into the pattern for toPattern() support.
+ *
+ * @param pattern source
+ * @param formats the Formats to insert
+ * @param metaFormat Format to format the Formats
+ * @return full pattern
*/
- protected void applyPatternPre(String pattern) {
- // noop
+ private String insertFormats(String pattern, ArrayList customPatterns) {
+ if (!containsElements(customPatterns)) {
+ return pattern;
+ }
+ StringBuffer sb = new StringBuffer(pattern.length() * 2);
+ ParsePosition pos = new ParsePosition(0);
+ int fe = -1;
+ int depth = 0;
+ while (pos.getIndex() < pattern.length()) {
+ char c = pattern.charAt(pos.getIndex());
+ switch (c) {
+ case QUOTE:
+ appendQuotedString(pattern, pos, sb, false);
+ break;
+ case START_FE:
+ depth++;
+ if (depth == 1) {
+ fe++;
+ sb.append(START_FE).append(
+ readArgumentIndex(pattern, next(pos)));
+ String customPattern = (String) customPatterns.get(fe);
+ if (customPattern != null) {
+ sb.append(START_FMT).append(customPattern);
+ }
+ }
+ break;
+ case END_FE:
+ depth--;
+ //fall through:
+ default:
+ sb.append(c);
+ next(pos);
+ }
+ }
+ return sb.toString();
}
/**
- * Post-execution hook by means of which a subclass can customize the
- * behavior of the final applyPattern implementation.
+ * Consume whitespace from the current parse position.
*
- * @param pattern String
+ * @param pattern String to read
+ * @param pos current position
*/
- protected void applyPatternPost(String pattern) {
- // noop
+ private void seekNonWs(String pattern, ParsePosition pos) {
+ int len = 0;
+ char[] buffer = pattern.toCharArray();
+ do {
+ len = StrMatcher.splitMatcher().isMatch(buffer, pos.getIndex());
+ pos.setIndex(pos.getIndex() + len);
+ } while (len > 0 && pos.getIndex() < pattern.length());
}
/**
- * Render the pattern from the current state of the
- * <code>ExtendedMessageFormat</code>.
+ * Convenience method to advance parse position by 1
*
- * @return pattern String
+ * @param pos ParsePosition
+ * @return <code>pos</code>
*/
- public String toPattern() {
- return PARSER.insertFormats(strippedPattern, getFormats(), metaFormat);
+ private ParsePosition next(ParsePosition pos) {
+ pos.setIndex(pos.getIndex() + 1);
+ return pos;
}
/**
- * Get the meta-format currently configured.
+ * Consume a quoted string, adding it to <code>appendTo</code> if
+ * specified.
*
- * @return Format.
- */
- public synchronized Format getMetaFormat() {
- return metaFormat;
+ * @param pattern pattern to parse
+ * @param pos current parse position
+ * @param appendTo optional StringBuffer to append
+ * @param escapingOn whether to process escaped quotes
+ * @return <code>appendTo</code>
+ */
+ private StringBuffer appendQuotedString(String pattern, ParsePosition pos,
+ StringBuffer appendTo, boolean escapingOn) {
+ int start = pos.getIndex();
+ char[] c = pattern.toCharArray();
+ if (escapingOn && c[start] == QUOTE) {
+ return appendTo == null ? null : appendTo.append(QUOTE);
+ }
+ int lastHold = start;
+ for (int i = pos.getIndex(); i < pattern.length(); i++) {
+ if (escapingOn && pattern.substring(i).startsWith(ESCAPED_QUOTE)) {
+ appendTo.append(c, lastHold, pos.getIndex() - lastHold).append(
+ QUOTE);
+ pos.setIndex(i + ESCAPED_QUOTE.length());
+ lastHold = pos.getIndex();
+ continue;
+ }
+ switch (c[pos.getIndex()]) {
+ case QUOTE:
+ next(pos);
+ return appendTo == null ? null : appendTo.append(c, lastHold,
+ pos.getIndex() - lastHold);
+ default:
+ next(pos);
+ }
+ }
+ throw new IllegalArgumentException(
+ "Unterminated quoted string at position " + start);
}
/**
- * Set the meta-format. Has no effect until a subsequent call to
- * {@link #applyPattern(String)}.
+ * Consume quoted string only
*
- * @param metaFormat the Format metaFormat to set.
+ * @param pattern pattern to parse
+ * @param pos current parse position
+ * @param escapingOn whether to process escaped quotes
*/
- public synchronized void setMetaFormat(Format metaFormat) {
- Validate.notNull(metaFormat, "metaFormat is null");
- this.metaFormat = metaFormat;
+ private void getQuotedString(String pattern, ParsePosition pos,
+ boolean escapingOn) {
+ appendQuotedString(pattern, pos, null, escapingOn);
}
+ /**
+ * Learn whether the specified Collection contains non-null elements.
+ * @param coll to check
+ * @return <code>true</code> if some Object was found, <code>false</code> otherwise.
+ */
+ private boolean containsElements(Collection coll) {
+ if (coll == null || coll.size() == 0) {
+ return false;
+ }
+ for (Iterator iter = coll.iterator(); iter.hasNext();) {
+ if (iter.next() != null) {
+ return true;
+ }
+ }
+ return false;
+ }
}
Added: commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/FormatFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/FormatFactory.java?rev=630969&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/FormatFactory.java (added)
+++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/FormatFactory.java Mon Feb 25 11:51:18 2008
@@ -0,0 +1,24 @@
+package org.apache.commons.lang.text;
+
+import java.text.Format;
+import java.util.Locale;
+
+/**
+ * Format factory.
+ * @since 2.4
+ * @author Niall Pemberton
+ * @version $Id$
+ */
+public interface FormatFactory {
+
+ /**
+ * Create or retrieve a format instance.
+ *
+ * @param name The format type name
+ * @param arguments Arguments used to create the format instance
+ * @param locale The locale, may be null
+ * @return The format instance
+ */
+ Format getFormat(String name, String arguments, Locale locale);
+
+}
Propchange: commons/proper/lang/trunk/src/java/org/apache/commons/lang/text/FormatFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/ExtendedMessageFormatBaselineTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/ExtendedMessageFormatBaselineTest.java?rev=630969&r1=630968&r2=630969&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/ExtendedMessageFormatBaselineTest.java (original)
+++ commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/ExtendedMessageFormatBaselineTest.java Mon Feb 25 11:51:18 2008
@@ -173,8 +173,7 @@
* {@inheritDoc}
*/
protected MessageFormat createMessageFormat(String pattern, Locale locale) {
- return new ExtendedMessageFormat(pattern, locale, ExtendedMessageFormat
- .createDefaultMetaFormat(locale));
+ return new ExtendedMessageFormat(pattern, locale);
}
}
Modified: commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/MessageFormatExtensionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/MessageFormatExtensionTest.java?rev=630969&r1=630968&r2=630969&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/MessageFormatExtensionTest.java (original)
+++ commons/proper/lang/trunk/src/test/org/apache/commons/lang/text/MessageFormatExtensionTest.java Mon Feb 25 11:51:18 2008
@@ -24,6 +24,7 @@
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.HashMap;
import java.util.Locale;
/**
@@ -237,13 +238,13 @@
* {@inheritDoc}
*/
protected MessageFormat createMessageFormat(String pattern, Locale locale) {
- return new ExtendedMessageFormat(pattern, locale,
- new MultiFormat.Builder().add(
- new NameKeyedMetaFormat.Builder().put("properName",
- new ProperNameCapitalizationFormat())
- .toNameKeyedMetaFormat()).add(
- ExtendedMessageFormat.createDefaultMetaFormat(locale))
- .toMultiFormat());
+ final ProperNameCapitalizationFormat properNameCapitalizationFormat = new ProperNameCapitalizationFormat();
+ final FormatFactory ff = new FormatFactory() {
+ public Format getFormat(String name, String arguments, Locale locale) {
+ return "properName".equals(name) ? properNameCapitalizationFormat : null;
+ }
+ };
+ return new ExtendedMessageFormat(pattern, locale, new HashMap() { { put("properName", ff); }});
}
public void testProperName() {