[LANG-366] Add MultiFormat
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@589646 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
796b898281
commit
013f19fdaf
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.text;
|
||||||
|
|
||||||
|
import java.text.FieldPosition;
|
||||||
|
import java.text.Format;
|
||||||
|
import java.text.ParsePosition;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format that tries a number of delegates in turn until one is successful.
|
||||||
|
* Contrast to {@link CompositeFormat}.
|
||||||
|
*
|
||||||
|
* @author Matt Benson
|
||||||
|
* @since 2.4
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class MultiFormat extends Format {
|
||||||
|
private static final long serialVersionUID = -6128683973856547540L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a builder with a fluent interface. Example:
|
||||||
|
* <p>
|
||||||
|
* <code>
|
||||||
|
* <pre>
|
||||||
|
* MultiFormat mf = new MultiFormat.Builder().add(new FooFormat()).add(
|
||||||
|
* new BarFormat()).add(new BazFormat()).toMultiFormat();
|
||||||
|
* </pre></code>
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public static class Builder {
|
||||||
|
private ArrayList delegates = new ArrayList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a delegate format.
|
||||||
|
*
|
||||||
|
* @param delegate
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public Builder add(Format delegate) {
|
||||||
|
Validate.notNull(delegate, "delegate format is null");
|
||||||
|
delegates.add(delegate);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the {@link MultiFormat} instance from this Builder.
|
||||||
|
*
|
||||||
|
* @return MultiFormat
|
||||||
|
*/
|
||||||
|
public MultiFormat toMultiFormat() {
|
||||||
|
return new MultiFormat((Format[]) delegates
|
||||||
|
.toArray(new Format[delegates.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Format[] delegates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MultiFormat.
|
||||||
|
*/
|
||||||
|
public MultiFormat() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MultiFormat.
|
||||||
|
*
|
||||||
|
* @param delegates
|
||||||
|
*/
|
||||||
|
public MultiFormat(Format[] delegates) {
|
||||||
|
setDelegates(delegates);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer,
|
||||||
|
* java.text.FieldPosition)
|
||||||
|
*/
|
||||||
|
public StringBuffer format(Object obj, StringBuffer toAppendTo,
|
||||||
|
FieldPosition pos) {
|
||||||
|
Format[] d = getValidDelegates();
|
||||||
|
for (int i = 0; i < d.length; i++) {
|
||||||
|
try {
|
||||||
|
return d[i].format(obj, toAppendTo, pos);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("No delegate Format can parse "
|
||||||
|
+ obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.text.Format#parseObject(java.lang.String,
|
||||||
|
* java.text.ParsePosition)
|
||||||
|
*/
|
||||||
|
public Object parseObject(String source, ParsePosition pos) {
|
||||||
|
int start = pos.getIndex();
|
||||||
|
Format[] d = getDelegates();
|
||||||
|
for (int i = 0; i < d.length; i++) {
|
||||||
|
Object o = d[i].parseObject(source, pos);
|
||||||
|
if (pos.getErrorIndex() < 0) {
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
// set up for next attempt:
|
||||||
|
pos.setIndex(start);
|
||||||
|
pos.setErrorIndex(-1);
|
||||||
|
}
|
||||||
|
pos.setErrorIndex(start);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the delegates.
|
||||||
|
*
|
||||||
|
* @param delegates
|
||||||
|
* the Format[] delegates to set.
|
||||||
|
*/
|
||||||
|
public void setDelegates(Format[] delegates) {
|
||||||
|
Validate.noNullElements(delegates,
|
||||||
|
"Null elements present in delegates Format[]");
|
||||||
|
this.delegates = delegates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the delegates.
|
||||||
|
*
|
||||||
|
* @return Format[].
|
||||||
|
*/
|
||||||
|
public Format[] getDelegates() {
|
||||||
|
return delegates;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Format[] getValidDelegates() {
|
||||||
|
Format[] result = getDelegates();
|
||||||
|
Validate.notEmpty(result, "No delegate Formats configured");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang.text;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.FieldPosition;
|
||||||
|
import java.text.Format;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.ParsePosition;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.ClassUtils;
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test MultiFormat
|
||||||
|
*
|
||||||
|
* @author Matt Benson
|
||||||
|
* @since 2.4
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class MultiFormatTest extends TestCase {
|
||||||
|
private class GuardedFormat extends Format {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
Format delegate;
|
||||||
|
Class[] allowableTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MultiFormatTest.GuardedFormat.
|
||||||
|
*/
|
||||||
|
public GuardedFormat(Format delegate, Class[] allowableTypes) {
|
||||||
|
Validate.notNull(delegate);
|
||||||
|
this.delegate = delegate;
|
||||||
|
Validate.notNull(allowableTypes);
|
||||||
|
this.allowableTypes = allowableTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuffer format(Object obj, StringBuffer toAppendTo,
|
||||||
|
FieldPosition pos) {
|
||||||
|
Class c = obj == null ? null : obj.getClass();
|
||||||
|
for (int i = 0; i < allowableTypes.length; i++) {
|
||||||
|
if (ClassUtils.isAssignable(c, allowableTypes[i])) {
|
||||||
|
return delegate.format(obj, toAppendTo, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object parseObject(String source, ParsePosition pos) {
|
||||||
|
return delegate.parseObject(source, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Format format;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see junit.framework.TestCase#setUp()
|
||||||
|
*/
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
// silliness to avoid the DateFormat grabbing the Integer, or the
|
||||||
|
// integer parsing the first (month) date component:
|
||||||
|
format = new MultiFormat.Builder().add(
|
||||||
|
new GuardedFormat(DateFormat.getDateInstance(DateFormat.SHORT,
|
||||||
|
Locale.US), new Class[] { Date.class })).add(
|
||||||
|
NumberFormat.getIntegerInstance(Locale.US)).toMultiFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWTF() {
|
||||||
|
System.out.println(DateFormat.getDateInstance(DateFormat.SHORT,
|
||||||
|
Locale.US).format(new Integer(1000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFormatNumber() {
|
||||||
|
assertEquals("1,000", format.format(new Integer(1000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testParseNumber() throws ParseException {
|
||||||
|
assertEquals(new Integer(-1000).intValue(), ((Number) format
|
||||||
|
.parseObject("-1,000")).intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFormatDate() {
|
||||||
|
assertEquals("1/1/70", format.format(new GregorianCalendar(1970,
|
||||||
|
Calendar.JANUARY, 01).getTime()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testParseDate() throws ParseException {
|
||||||
|
assertEquals(new GregorianCalendar(1970, Calendar.JANUARY, 01)
|
||||||
|
.getTime(), format.parseObject("1/1/70"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFormatObject() {
|
||||||
|
try {
|
||||||
|
format.format(new Object());
|
||||||
|
fail("expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// okay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testParseGarbage() {
|
||||||
|
try {
|
||||||
|
format.parseObject("garbage");
|
||||||
|
fail("expected ParseException");
|
||||||
|
} catch (ParseException e) {
|
||||||
|
//okay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,6 +56,7 @@ public static Test suite() {
|
||||||
suite.addTest(StrMatcherTest.suite());
|
suite.addTest(StrMatcherTest.suite());
|
||||||
suite.addTest(StrSubstitutorTest.suite());
|
suite.addTest(StrSubstitutorTest.suite());
|
||||||
suite.addTest(StrTokenizerTest.suite());
|
suite.addTest(StrTokenizerTest.suite());
|
||||||
|
suite.addTestSuite(MultiFormatTest.class);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue