Source Code Cross Referenced for ArrayConverter.java in  » Library » Apache-commons-beanutils-1.8.0-BETA-src » org » apache » commons » beanutils » converters » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache commons beanutils 1.8.0 BETA src » org.apache.commons.beanutils.converters 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.commons.beanutils.converters;
018:
019:        import java.util.Collections;
020:        import java.util.List;
021:        import java.util.ArrayList;
022:        import java.util.Iterator;
023:        import java.util.Collection;
024:        import java.io.StreamTokenizer;
025:        import java.io.StringReader;
026:        import java.io.IOException;
027:        import java.lang.reflect.Array;
028:        import org.apache.commons.beanutils.ConversionException;
029:        import org.apache.commons.beanutils.Converter;
030:
031:        /**
032:         * Generic {@link Converter} implementaion that handles conversion
033:         * to and from <b>array</b> objects.
034:         * <p>
035:         * Can be configured to either return a <i>default value</i> or throw a
036:         * <code>ConversionException</code> if a conversion error occurs.
037:         * <p>
038:         * The main features of this implementation are:
039:         * <ul>
040:         *     <li><b>Element Conversion</b> - delegates to a {@link Converter},
041:         *         appropriate for the type, to convert individual elements
042:         *         of the array. This leverages the power of existing converters
043:         *         without having to replicate their functionality for converting
044:         *         to the element type and removes the need to create a specifc
045:         *         array type converters.</li>
046:         *     <li><b>Arrays or Collections</b> - can convert from either arrays or
047:         *         Collections to an array, limited only by the capability
048:         *         of the delegate {@link Converter}.</li>
049:         *     <li><b>Delimited Lists</b> - can Convert <b>to</b> and <b>from</b> a
050:         *         delimited list in String format.</li>
051:         *     <li><b>Conversion to String</b> - converts an array to a 
052:         *         <code>String</code> in one of two ways: as a <i>delimited list</i>
053:         *         or by converting the first element in the array to a String - this
054:         *         is controlled by the {@link ArrayConverter#setOnlyFirstToString(boolean)}
055:         *         parameter.</li>
056:         *     <li><b>Multi Dimensional Arrays</b> - its possible to convert a <code>String</code>
057:         *         to a multi-dimensional arrays, by embedding {@link ArrayConverter}
058:         *         within each other - see example below.</li>
059:         *     <li><b>Default Value</b></li>
060:         *         <ul>
061:         *             <li><b><i>No Default</b></i> - use the 
062:         *                 {@link ArrayConverter#ArrayConverter(Class, Converter)}
063:         *                 constructor to create a converter which throws a
064:         *                 {@link ConversionException} if the value is missing or
065:         *                 invalid.</li>
066:         *             <li><b><i>Default values</b></i> - use the 
067:         *                 {@link ArrayConverter#ArrayConverter(Class, Converter, int)}
068:         *                 constructor to create a converter which returns a <i>default
069:         *                 value</i>. The <i>defaultSize</i> parameter controls the 
070:         *                 <i>default value</i> in the following way:</li>
071:         *                 <ul>
072:         *                    <li><i>defaultSize &lt; 0</i> - default is <code>null</code></li>
073:         *                    <li><i>defaultSize = 0</i> - default is an array of length zero</li>
074:         *                    <li><i>defaultSize &gt; 0</i> - default is an array with a
075:         *                        length specified by <code>defaultSize</code> (N.B. elements
076:         *                        in the array will be <code>null</code>)</li>
077:         *                 </ul>
078:         *         </ul>
079:         * </ul>
080:         *
081:         * <h3>Parsing Delimited Lists</h3>
082:         * This implementation can convert a delimited list in <code>String</code> format
083:         * into an array of the appropriate type. By default, it uses a comma as the delimiter
084:         * but the following methods can be used to configure parsing:
085:         * <ul>
086:         *     <li><code>setDelimiter(char)</code> - allows the character used as
087:         *         the delimiter to be configured [default is a comma].</li>
088:         *     <li><code>setAllowedChars(char[])</code> - adds additional characters
089:         *         (to the default alphabetic/numeric) to those considered to be
090:         *         valid token characters.
091:         * </ul>
092:         *
093:         * <h3>Multi Dimensional Arrays</h3>
094:         * It is possible to convert a <code>String</code> to mulit-dimensional arrays by using
095:         * {@link ArrayConverter} as the element {@link Converter}
096:         * within another {@link ArrayConverter}.
097:         * <p>
098:         * For example, the following code demonstrates how to construct a {@link Converter}
099:         * to convert a delimited <code>String</code> into a two dimensional integer array:
100:         * <p>
101:         * <pre>
102:         *    // Construct an Integer Converter
103:         *    IntegerConverter integerConverter = new IntegerConverter();
104:         *
105:         *    // Construct an array Converter for an integer array (i.e. int[]) using
106:         *    // an IntegerConverter as the element converter.
107:         *    // N.B. Uses the default comma (i.e. ",") as the delimiter between individual numbers
108:         *    ArrayConverter arrayConverter = new ArrayConverter(int[].class, integerConverter);
109:         *
110:         *    // Construct a "Matrix" Converter which converts arrays of integer arrays using
111:         *    // the pre-ceeding ArrayConverter as the element Converter.
112:         *    // N.B. Uses a semi-colon (i.e. ";") as the delimiter to separate the different sets of numbers.
113:         *    //      Also the delimiter used by the first ArrayConverter needs to be added to the
114:         *    //      "allowed characters" for this one.
115:         *    ArrayConverter matrixConverter = new ArrayConverter(int[][].class, arrayConverter);
116:         *    matrixConverter.setDelimiter(';');
117:         *    matrixConverter.setAllowedChars(new char[] {','});
118:         *
119:         *    // Do the Conversion
120:         *    String matrixString = "11,12,13 ; 21,22,23 ; 31,32,33 ; 41,42,43";
121:         *    int[][] result = (int[][])matrixConverter.convert(int[][].class, matrixString);
122:         * </pre>
123:         *
124:         * @version $Revision: 555824 $ $Date: 2007-07-13 01:27:15 +0100 (Fri, 13 Jul 2007) $
125:         * @since 1.8.0
126:         */
127:        public class ArrayConverter extends AbstractConverter {
128:
129:            private Converter elementConverter;
130:            private int defaultSize;
131:            private char delimiter = ',';
132:            private char[] allowedChars = new char[] { '.', '-' };
133:            private boolean onlyFirstToString = true;
134:
135:            // ----------------------------------------------------------- Constructors
136:
137:            /**
138:             * Construct an <b>array</b> <code>Converter</code> with the specified
139:             * <b>component</b> <code>Converter</code> that throws a
140:             * <code>ConversionException</code> if an error occurs.
141:             *
142:             * @param defaultType The default array type this
143:             *  <code>Converter</code> handles
144:             * @param elementConverter Converter used to convert
145:             *  individual array elements.
146:             */
147:            public ArrayConverter(Class defaultType, Converter elementConverter) {
148:                super (defaultType);
149:                if (!defaultType.isArray()) {
150:                    throw new IllegalArgumentException(
151:                            "Default type must be an array.");
152:                }
153:                if (elementConverter == null) {
154:                    throw new IllegalArgumentException(
155:                            "Component Converter is missing.");
156:                }
157:                this .elementConverter = elementConverter;
158:            }
159:
160:            /**
161:             * Construct an <b>array</b> <code>Converter</code> with the specified
162:             * <b>component</b> <code>Converter</code> that returns a default
163:             * array of the specified size (or <code>null</code>) if an error occurs.
164:             *
165:             * @param defaultType The default array type this
166:             *  <code>Converter</code> handles
167:             * @param elementConverter Converter used to convert
168:             *  individual array elements.
169:             * @param defaultSize Specifies the size of the default array value or if less
170:             *  than zero indicates that a <code>null</code> default value should be used.
171:             */
172:            public ArrayConverter(Class defaultType,
173:                    Converter elementConverter, int defaultSize) {
174:                this (defaultType, elementConverter);
175:                this .defaultSize = defaultSize;
176:                Object defaultValue = null;
177:                if (defaultSize >= 0) {
178:                    defaultValue = Array.newInstance(defaultType
179:                            .getComponentType(), defaultSize);
180:                }
181:                setDefaultValue(defaultValue);
182:            }
183:
184:            /**
185:             * Set the delimiter to be used for parsing a delimited String.
186:             *
187:             * @param delimiter The delimiter [default ',']
188:             */
189:            public void setDelimiter(char delimiter) {
190:                this .delimiter = delimiter;
191:            }
192:
193:            /**
194:             * Set the allowed characters to be used for parsing a delimited String.
195:             *
196:             * @param allowedChars Characters which are to be considered as part of
197:             * the tokens when parsing a delimited String [default is '.' and '-']
198:             */
199:            public void setAllowedChars(char[] allowedChars) {
200:                this .allowedChars = allowedChars;
201:            }
202:
203:            /**
204:             * Indicates whether converting to a String should create
205:             * a delimited list or just convert the first value.
206:             *
207:             * @param onlyFirstToString <code>true</code> converts only
208:             * the first value in the array to a String, <code>false</code>
209:             * converts all values in the array into a delimited list (default
210:             * is <code>true</code> 
211:             */
212:            public void setOnlyFirstToString(boolean onlyFirstToString) {
213:                this .onlyFirstToString = onlyFirstToString;
214:            }
215:
216:            /**
217:             * Handles conversion to a String.
218:             *
219:             * @param value The value to be converted.
220:             * @return the converted String value.
221:             * @throws Throwable if an error occurs converting to a String
222:             */
223:            protected String convertToString(Object value) throws Throwable {
224:
225:                int size = 0;
226:                Iterator iterator = null;
227:                Class type = value.getClass();
228:                if (type.isArray()) {
229:                    size = Array.getLength(value);
230:                } else {
231:                    Collection collection = convertToCollection(type, value);
232:                    size = collection.size();
233:                    iterator = collection.iterator();
234:                }
235:
236:                if (size == 0) {
237:                    return (String) getDefault(String.class);
238:                }
239:
240:                if (onlyFirstToString) {
241:                    size = 1;
242:                }
243:
244:                // Create a StringBuffer containing a delimited list of the values
245:                StringBuffer buffer = new StringBuffer();
246:                for (int i = 0; i < size; i++) {
247:                    if (i > 0) {
248:                        buffer.append(delimiter);
249:                    }
250:                    Object element = iterator == null ? Array.get(value, i)
251:                            : iterator.next();
252:                    element = elementConverter.convert(String.class, element);
253:                    if (element != null) {
254:                        buffer.append(element);
255:                    }
256:                }
257:
258:                return buffer.toString();
259:
260:            }
261:
262:            /**
263:             * Handles conversion to an array of the specified type.
264:             *
265:             * @param type The type to which this value should be converted.
266:             * @param value The input value to be converted.
267:             * @return The converted value.
268:             * @throws Throwable if an error occurs converting to the specified type
269:             */
270:            protected Object convertToType(Class type, Object value)
271:                    throws Throwable {
272:
273:                if (!type.isArray()) {
274:                    throw new ConversionException(toString(getClass())
275:                            + " cannot handle conversion to '" + toString(type)
276:                            + "' (not an array).");
277:                }
278:
279:                // Handle the source
280:                int size = 0;
281:                Iterator iterator = null;
282:                if (value.getClass().isArray()) {
283:                    size = Array.getLength(value);
284:                } else {
285:                    Collection collection = convertToCollection(type, value);
286:                    size = collection.size();
287:                    iterator = collection.iterator();
288:                }
289:
290:                // Allocate a new Array
291:                Class componentType = type.getComponentType();
292:                Object newArray = Array.newInstance(componentType, size);
293:
294:                // Convert and set each element in the new Array
295:                for (int i = 0; i < size; i++) {
296:                    Object element = iterator == null ? Array.get(value, i)
297:                            : iterator.next();
298:                    // TODO - probably should catch conversion errors and throw
299:                    //        new exception providing better info back to the user
300:                    element = elementConverter.convert(componentType, element);
301:                    Array.set(newArray, i, element);
302:                }
303:
304:                return newArray;
305:            }
306:
307:            /**
308:             * Returns the value unchanged.
309:             *
310:             * @param value The value to convert
311:             * @return The value unchanged
312:             */
313:            protected Object convertArray(Object value) {
314:                return value;
315:            }
316:
317:            /**
318:             * Converts non-array values to a Collection prior
319:             * to being converted either to an array or a String.
320:             * </p>
321:             * <ul>
322:             *   <li>{@link Collection} values are returned unchanged</li>
323:             *   <li>{@link Number}, {@link Boolean}  and {@link java.util.Date} 
324:             *       values returned as a the only element in a List.</li>
325:             *   <li>All other types are converted to a String and parsed
326:             *       as a delimited list.</li>
327:             * </ul>
328:             *
329:             * <strong>N.B.</strong> The method is called by both the
330:             * {@link ArrayConverter#convertToType(Class, Object)} and
331:             * {@link ArrayConverter#convertToString(Object)} methods for
332:             * <i>non-array</i> types.
333:             *
334:             * @param type The type to convert the value to
335:             * @param value value to be converted
336:             * @return Collection elements.
337:             */
338:            protected Collection convertToCollection(Class type, Object value) {
339:                if (value instanceof  Collection) {
340:                    return (Collection) value;
341:                }
342:                if (value instanceof  Number || value instanceof  Boolean
343:                        || value instanceof  java.util.Date) {
344:                    List list = new ArrayList(1);
345:                    list.add(value);
346:                    return list;
347:                }
348:
349:                return parseElements(type, value.toString());
350:            }
351:
352:            /**
353:             * Return the default value for conversions to the specified
354:             * type.
355:             * @param type Data type to which this value should be converted.
356:             * @return The default value for the specified type.
357:             */
358:            protected Object getDefault(Class type) {
359:                if (type.equals(String.class)) {
360:                    return null;
361:                }
362:
363:                Object defaultValue = super .getDefault(type);
364:                if (defaultValue == null) {
365:                    return null;
366:                }
367:
368:                if (defaultValue.getClass().equals(type)) {
369:                    return defaultValue;
370:                } else {
371:                    return Array.newInstance(type.getComponentType(),
372:                            defaultSize);
373:                }
374:
375:            }
376:
377:            /**
378:             * Provide a String representation of this array converter.
379:             *
380:             * @return A String representation of this array converter
381:             */
382:            public String toString() {
383:                StringBuffer buffer = new StringBuffer();
384:                buffer.append(toString(getClass()));
385:                buffer.append("[UseDefault=");
386:                buffer.append(isUseDefault());
387:                buffer.append(", ");
388:                buffer.append(elementConverter.toString());
389:                buffer.append(']');
390:                return buffer.toString();
391:            }
392:
393:            /**
394:             * <p>Parse an incoming String of the form similar to an array initializer
395:             * in the Java language into a <code>List</code> individual Strings
396:             * for each element, according to the following rules.</p>
397:             * <ul>
398:             * <li>The string is expected to be a comma-separated list of values.</li>
399:             * <li>The string may optionally have matching '{' and '}' delimiters
400:             *   around the list.</li>
401:             * <li>Whitespace before and after each element is stripped.</li>
402:             * <li>Elements in the list may be delimited by single or double quotes.
403:             *  Within a quoted elements, the normal Java escape sequences are valid.</li>
404:             * </ul>
405:             *
406:             * @param type The type to convert the value to
407:             * @param value String value to be parsed
408:             * @return List of parsed elements.
409:             *
410:             * @throws ConversionException if the syntax of <code>svalue</code>
411:             *  is not syntactically valid
412:             * @throws NullPointerException if <code>svalue</code>
413:             *  is <code>null</code>
414:             */
415:            private List parseElements(Class type, String value) {
416:
417:                if (log().isDebugEnabled()) {
418:                    log().debug(
419:                            "Parsing elements, delimiter=[" + delimiter
420:                                    + "], value=[" + value + "]");
421:                }
422:
423:                // Trim any matching '{' and '}' delimiters
424:                value = value.trim();
425:                if (value.startsWith("{") && value.endsWith("}")) {
426:                    value = value.substring(1, value.length() - 1);
427:                }
428:
429:                try {
430:
431:                    // Set up a StreamTokenizer on the characters in this String
432:                    StreamTokenizer st = new StreamTokenizer(new StringReader(
433:                            value));
434:                    st.whitespaceChars(delimiter, delimiter); // Set the delimiters
435:                    st.ordinaryChars('0', '9'); // Needed to turn off numeric flag
436:                    st.wordChars('0', '9'); // Needed to make part of tokens
437:                    for (int i = 0; i < allowedChars.length; i++) {
438:                        st.ordinaryChars(allowedChars[i], allowedChars[i]);
439:                        st.wordChars(allowedChars[i], allowedChars[i]);
440:                    }
441:
442:                    // Split comma-delimited tokens into a List
443:                    List list = null;
444:                    while (true) {
445:                        int ttype = st.nextToken();
446:                        if ((ttype == StreamTokenizer.TT_WORD) || (ttype > 0)) {
447:                            if (list == null) {
448:                                list = new ArrayList();
449:                            }
450:                            list.add(st.sval.trim());
451:                        } else if (ttype == StreamTokenizer.TT_EOF) {
452:                            break;
453:                        } else {
454:                            throw new ConversionException(
455:                                    "Encountered token of type " + ttype
456:                                            + " parsing elements to '"
457:                                            + toString(type) + ".");
458:                        }
459:                    }
460:
461:                    if (list == null) {
462:                        list = Collections.EMPTY_LIST;
463:                    }
464:                    if (log().isDebugEnabled()) {
465:                        log().debug(list.size() + " elements parsed");
466:                    }
467:
468:                    // Return the completed list
469:                    return (list);
470:
471:                } catch (IOException e) {
472:
473:                    throw new ConversionException(
474:                            "Error converting from String to '"
475:                                    + toString(type) + "': " + e.getMessage(),
476:                            e);
477:
478:                }
479:
480:            }
481:
482:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.