1dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/*
2dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Licensed to the Apache Software Foundation (ASF) under one or more
3dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * contributor license agreements.  See the NOTICE file distributed with
4dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this work for additional information regarding copyright ownership.
5dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ASF licenses this file to You under the Apache License, Version 2.0
6dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (the "License"); you may not use this file except in compliance with
7dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the License.  You may obtain a copy of the License at
8dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
9dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *      http://www.apache.org/licenses/LICENSE-2.0
10dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
11dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Unless required by applicable law or agreed to in writing, software
12dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * distributed under the License is distributed on an "AS IS" BASIS,
13dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See the License for the specific language governing permissions and
15dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * limitations under the License.
16dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.geometry;
19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.text.FieldPosition;
21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.text.NumberFormat;
22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.text.ParseException;
23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.text.ParsePosition;
24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.util.Locale;
25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.MathRuntimeException;
27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.exception.util.LocalizedFormats;
28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.util.CompositeFormat;
29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/**
31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Formats a 3D vector in components list format "{x; y; z}".
32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>The prefix and suffix "{" and "}" and the separator "; " can be replaced by
33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * any user-defined strings. The number format for components can be configured.</p>
34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>White space is ignored at parse time, even if it is in the prefix, suffix
35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * or separator specifications. So even if the default separator does include a space
36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * character that is used at format time, both input string "{1;1;1}" and
37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * " { 1 ; 1 ; 1 } " will be parsed without error and the same vector will be
38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * returned. In the second case, however, the parse position after parsing will be
39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * just after the closing curly brace, i.e. just before the trailing space.</p>
40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1003886 $ $Date: 2010-10-02 23:04:44 +0200 (sam. 02 oct. 2010) $
42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class Vector3DFormat extends CompositeFormat {
44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Serializable version identifier */
46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final long serialVersionUID = -5447606608652576301L;
47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** The default prefix: "{". */
49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final String DEFAULT_PREFIX = "{";
50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** The default suffix: "}". */
52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final String DEFAULT_SUFFIX = "}";
53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** The default separator: ", ". */
55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final String DEFAULT_SEPARATOR = "; ";
56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Prefix. */
58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final String prefix;
59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Suffix. */
61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final String suffix;
62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Separator. */
64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final String separator;
65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Trimmed prefix. */
67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final String trimmedPrefix;
68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Trimmed suffix. */
70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final String trimmedSuffix;
71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Trimmed separator. */
73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final String trimmedSeparator;
74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** The format used for components. */
76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final NumberFormat format;
77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create an instance with default settings.
80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>The instance uses the default prefix, suffix and separator:
81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * "{", "}", and "; " and the default number format for components.</p>
82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public Vector3DFormat() {
84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, getDefaultNumberFormat());
85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create an instance with a custom number format for components.
89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param format the custom format for components.
90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public Vector3DFormat(final NumberFormat format) {
92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, format);
93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create an instance with custom prefix, suffix and separator.
97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param prefix prefix to use instead of the default "{"
98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param suffix suffix to use instead of the default "}"
99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param separator separator to use instead of the default "; "
100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public Vector3DFormat(final String prefix, final String suffix,
102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                          final String separator) {
103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this(prefix, suffix, separator, getDefaultNumberFormat());
104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create an instance with custom prefix, suffix, separator and format
108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * for components.
109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param prefix prefix to use instead of the default "{"
110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param suffix suffix to use instead of the default "}"
111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param separator separator to use instead of the default "; "
112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param format the custom format for components.
113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public Vector3DFormat(final String prefix, final String suffix,
115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                          final String separator, final NumberFormat format) {
116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.prefix      = prefix;
117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.suffix      = suffix;
118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.separator   = separator;
119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        trimmedPrefix    = prefix.trim();
120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        trimmedSuffix    = suffix.trim();
121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        trimmedSeparator = separator.trim();
122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.format      = format;
123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Get the set of locales for which 3D vectors formats are available.
127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>This is the same set as the {@link NumberFormat} set.</p>
128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return available 3D vector format locales.
129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static Locale[] getAvailableLocales() {
131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return NumberFormat.getAvailableLocales();
132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Get the format prefix.
136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return format prefix.
137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public String getPrefix() {
139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return prefix;
140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Get the format suffix.
144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return format suffix.
145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public String getSuffix() {
147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return suffix;
148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Get the format separator between components.
152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return format separator.
153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public String getSeparator() {
155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return separator;
156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Get the components format.
160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return components format.
161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public NumberFormat getFormat() {
163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return format;
164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the default 3D vector format for the current locale.
168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the default 3D vector format.
169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static Vector3DFormat getInstance() {
171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return getInstance(Locale.getDefault());
172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the default 3D vector format for the given locale.
176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param locale the specific locale used by the format.
177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the 3D vector format specific to the given locale.
178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static Vector3DFormat getInstance(final Locale locale) {
180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return new Vector3DFormat(getDefaultNumberFormat(locale));
181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * This static method calls {@link #format(Object)} on a default instance of
185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Vector3DFormat.
186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param v Vector3D object to format
188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return A formatted vector
189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static String formatVector3D(Vector3D v) {
191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return getInstance().format(v);
192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Formats a {@link Vector3D} object to produce a string.
196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param vector the object to format.
197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param toAppendTo where the text is to be appended
198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param pos On input: an alignment field, if desired. On output: the
199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *            offsets of the alignment field
200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the value passed in as toAppendTo.
201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public StringBuffer format(Vector3D vector, StringBuffer toAppendTo,
203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                               FieldPosition pos) {
204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        pos.setBeginIndex(0);
206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        pos.setEndIndex(0);
207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // format prefix
209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        toAppendTo.append(prefix);
210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // format components
212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        formatDouble(vector.getX(), format, toAppendTo, pos);
213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        toAppendTo.append(separator);
214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        formatDouble(vector.getY(), format, toAppendTo, pos);
215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        toAppendTo.append(separator);
216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        formatDouble(vector.getZ(), format, toAppendTo, pos);
217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // format suffix
219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        toAppendTo.append(suffix);
220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return toAppendTo;
222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Formats a object to produce a string.
227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p><code>obj</code> must be a  {@link Vector3D} object. Any other type of
228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * object will result in an {@link IllegalArgumentException} being thrown.</p>
229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param obj the object to format.
230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param toAppendTo where the text is to be appended
231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param pos On input: an alignment field, if desired. On output: the
232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *            offsets of the alignment field
233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the value passed in as toAppendTo.
234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException is <code>obj</code> is not a valid type.
236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public StringBuffer format(Object obj, StringBuffer toAppendTo,
239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                               FieldPosition pos) {
240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (obj instanceof Vector3D) {
242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return format( (Vector3D)obj, toAppendTo, pos);
243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.CANNOT_FORMAT_INSTANCE_AS_3D_VECTOR,
246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                                                  obj.getClass().getName());
247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Parses a string to produce a {@link Vector3D} object.
252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param source the string to parse
253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the parsed {@link Vector3D} object.
254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @exception ParseException if the beginning of the specified string
255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *            cannot be parsed.
256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public Vector3D parse(String source) throws ParseException {
258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ParsePosition parsePosition = new ParsePosition(0);
259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        Vector3D result = parse(source, parsePosition);
260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (parsePosition.getIndex() == 0) {
261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createParseException(
262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    parsePosition.getErrorIndex(),
263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.UNPARSEABLE_3D_VECTOR, source);
264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Parses a string to produce a {@link Vector3D} object.
270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param source the string to parse
271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param pos input/ouput parsing parameter.
272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the parsed {@link Vector3D} object.
273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public Vector3D parse(String source, ParsePosition pos) {
275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int initialIndex = pos.getIndex();
276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // parse prefix
278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        parseAndIgnoreWhitespace(source, pos);
279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (!parseFixedstring(source, trimmedPrefix, pos)) {
280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return null;
281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // parse X component
284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        parseAndIgnoreWhitespace(source, pos);
285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        Number x = parseNumber(source, format, pos);
286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x == null) {
287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // invalid abscissa
288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // set index back to initial, error index should already be set
289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            pos.setIndex(initialIndex);
290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return null;
291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // parse Y component
294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        parseAndIgnoreWhitespace(source, pos);
295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (!parseFixedstring(source, trimmedSeparator, pos)) {
296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return null;
297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        parseAndIgnoreWhitespace(source, pos);
299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        Number y = parseNumber(source, format, pos);
300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == null) {
301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // invalid ordinate
302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // set index back to initial, error index should already be set
303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            pos.setIndex(initialIndex);
304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return null;
305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // parse Z component
308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        parseAndIgnoreWhitespace(source, pos);
309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (!parseFixedstring(source, trimmedSeparator, pos)) {
310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return null;
311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        parseAndIgnoreWhitespace(source, pos);
313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        Number z = parseNumber(source, format, pos);
314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (z == null) {
315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // invalid height
316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // set index back to initial, error index should already be set
317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            pos.setIndex(initialIndex);
318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return null;
319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // parse suffix
322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        parseAndIgnoreWhitespace(source, pos);
323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (!parseFixedstring(source, trimmedSuffix, pos)) {
324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return null;
325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return new Vector3D(x.doubleValue(), y.doubleValue(), z.doubleValue());
328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Parses a string to produce a object.
333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param source the string to parse
334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param pos input/ouput parsing parameter.
335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the parsed object.
336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public Object parseObject(String source, ParsePosition pos) {
340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return parse(source, pos);
341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond}
344