summaryrefslogtreecommitdiff
path: root/src/main/java/org/apache/commons/math/util/CompositeFormat.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/apache/commons/math/util/CompositeFormat.java')
-rw-r--r--src/main/java/org/apache/commons/math/util/CompositeFormat.java220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/main/java/org/apache/commons/math/util/CompositeFormat.java b/src/main/java/org/apache/commons/math/util/CompositeFormat.java
new file mode 100644
index 0000000..99d18ab
--- /dev/null
+++ b/src/main/java/org/apache/commons/math/util/CompositeFormat.java
@@ -0,0 +1,220 @@
+/*
+ * 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.math.util;
+
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.NumberFormat;
+import java.text.ParsePosition;
+import java.util.Locale;
+
+/**
+ * Base class for formatters of composite objects (complex numbers, vectors ...).
+ *
+ * @version $Revision: 1042376 $ $Date: 2010-12-05 16:54:55 +0100 (dim. 05 déc. 2010) $
+ */
+public abstract class CompositeFormat extends Format {
+
+ /** Serializable version identifier. */
+ private static final long serialVersionUID = 5358685519349262494L;
+
+ /**
+ * Create a default number format. The default number format is based on
+ * {@link NumberFormat#getInstance()} with the only customizing that the
+ * maximum number of fraction digits is set to 2.
+ * @return the default number format.
+ */
+ protected static NumberFormat getDefaultNumberFormat() {
+ return getDefaultNumberFormat(Locale.getDefault());
+ }
+
+ /**
+ * Create a default number format. The default number format is based on
+ * {@link NumberFormat#getInstance(java.util.Locale)} with the only
+ * customizing that the maximum number of fraction digits is set to 2.
+ * @param locale the specific locale used by the format.
+ * @return the default number format specific to the given locale.
+ */
+ protected static NumberFormat getDefaultNumberFormat(final Locale locale) {
+ final NumberFormat nf = NumberFormat.getInstance(locale);
+ nf.setMaximumFractionDigits(2);
+ return nf;
+ }
+
+ /**
+ * Parses <code>source</code> until a non-whitespace character is found.
+ *
+ * @param source the string to parse
+ * @param pos input/ouput parsing parameter. On output, <code>pos</code>
+ * holds the index of the next non-whitespace character.
+ */
+ protected void parseAndIgnoreWhitespace(final String source,
+ final ParsePosition pos) {
+ parseNextCharacter(source, pos);
+ pos.setIndex(pos.getIndex() - 1);
+ }
+
+ /**
+ * Parses <code>source</code> until a non-whitespace character is found.
+ *
+ * @param source the string to parse
+ * @param pos input/ouput parsing parameter.
+ * @return the first non-whitespace character.
+ */
+ protected char parseNextCharacter(final String source,
+ final ParsePosition pos) {
+ int index = pos.getIndex();
+ final int n = source.length();
+ char ret = 0;
+
+ if (index < n) {
+ char c;
+ do {
+ c = source.charAt(index++);
+ } while (Character.isWhitespace(c) && index < n);
+ pos.setIndex(index);
+
+ if (index < n) {
+ ret = c;
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Parses <code>source</code> for special double values. These values
+ * include Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY.
+ *
+ * @param source the string to parse
+ * @param value the special value to parse.
+ * @param pos input/ouput parsing parameter.
+ * @return the special number.
+ */
+ private Number parseNumber(final String source, final double value,
+ final ParsePosition pos) {
+ Number ret = null;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append('(');
+ sb.append(value);
+ sb.append(')');
+
+ final int n = sb.length();
+ final int startIndex = pos.getIndex();
+ final int endIndex = startIndex + n;
+ if (endIndex < source.length()) {
+ if (source.substring(startIndex, endIndex).compareTo(sb.toString()) == 0) {
+ ret = Double.valueOf(value);
+ pos.setIndex(endIndex);
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Parses <code>source</code> for a number. This method can parse normal,
+ * numeric values as well as special values. These special values include
+ * Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY.
+ *
+ * @param source the string to parse
+ * @param format the number format used to parse normal, numeric values.
+ * @param pos input/ouput parsing parameter.
+ * @return the parsed number.
+ */
+ protected Number parseNumber(final String source, final NumberFormat format,
+ final ParsePosition pos) {
+ final int startIndex = pos.getIndex();
+ Number number = format.parse(source, pos);
+ final int endIndex = pos.getIndex();
+
+ // check for error parsing number
+ if (startIndex == endIndex) {
+ // try parsing special numbers
+ final double[] special = {
+ Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY
+ };
+ for (int i = 0; i < special.length; ++i) {
+ number = parseNumber(source, special[i], pos);
+ if (number != null) {
+ break;
+ }
+ }
+ }
+
+ return number;
+ }
+
+ /**
+ * Parse <code>source</code> for an expected fixed string.
+ * @param source the string to parse
+ * @param expected expected string
+ * @param pos input/ouput parsing parameter.
+ * @return true if the expected string was there
+ */
+ protected boolean parseFixedstring(final String source, final String expected,
+ final ParsePosition pos) {
+
+ final int startIndex = pos.getIndex();
+ final int endIndex = startIndex + expected.length();
+ if ((startIndex >= source.length()) ||
+ (endIndex > source.length()) ||
+ (source.substring(startIndex, endIndex).compareTo(expected) != 0)) {
+ // set index back to start, error index should be the start index
+ pos.setIndex(startIndex);
+ pos.setErrorIndex(startIndex);
+ return false;
+ }
+
+ // the string was here
+ pos.setIndex(endIndex);
+ return true;
+
+ }
+
+ /**
+ * Formats a double value to produce a string. In general, the value is
+ * formatted using the formatting rules of <code>format</code>. There are
+ * three exceptions to this:
+ * <ol>
+ * <li>NaN is formatted as '(NaN)'</li>
+ * <li>Positive infinity is formatted as '(Infinity)'</li>
+ * <li>Negative infinity is formatted as '(-Infinity)'</li>
+ * </ol>
+ *
+ * @param value the double to format.
+ * @param format the format used.
+ * @param toAppendTo where the text is to be appended
+ * @param pos On input: an alignment field, if desired. On output: the
+ * offsets of the alignment field
+ * @return the value passed in as toAppendTo.
+ */
+ protected StringBuffer formatDouble(final double value, final NumberFormat format,
+ final StringBuffer toAppendTo,
+ final FieldPosition pos) {
+ if( Double.isNaN(value) || Double.isInfinite(value) ) {
+ toAppendTo.append('(');
+ toAppendTo.append(value);
+ toAppendTo.append(')');
+ } else {
+ format.format(value, toAppendTo, pos);
+ }
+ return toAppendTo;
+ }
+
+}