[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:
Matthew Jason Benson 2007-10-29 14:50:23 +00:00
parent 796b898281
commit 013f19fdaf
3 changed files with 293 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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
}
}
}

View File

@ -56,6 +56,7 @@ public static Test suite() {
suite.addTest(StrMatcherTest.suite());
suite.addTest(StrSubstitutorTest.suite());
suite.addTest(StrTokenizerTest.suite());
suite.addTestSuite(MultiFormatTest.class);
return suite;
}