001: /*
002: * Copyright 2003-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.velocity.tools.generic;
017:
018: import java.lang.reflect.Array;
019: import java.util.ArrayList;
020: import java.util.List;
021:
022: /**
023: * Tool for working with arrays in Velocity templates.
024: * It provides a method to get and set specified elements,
025: * retrieve the length, and create clones of an array object.
026: * Also provides a method to convert arrays into java.util.List's.
027: * <p/>
028: * <p><pre>
029: * Example uses:
030: * $primes -> new int[] {2, 3, 5, 7}
031: * $array.length($primes) -> 4
032: * $array.get($primes, 2) -> 5
033: * $array.clone($primes) -> int[] {2, 3, 5, 7}, != $primes
034: * $array.set($primes, 2, 1) -> (primes[2] becomes 1)
035: * $array.get($primes, 2) -> 1
036: * $array.get($clone, 2) -> 5
037: * <p/>
038: * Example toolbox.xml config (if you want to use this with VelocityView):
039: * <tool>
040: * <key>array</key>
041: * <scope>application</scope>
042: * <class>org.apache.velocity.tools.generic.ArrayTool</class>
043: * </tool>
044: * </pre></p>
045: * <p/>
046: * <p>This tool is entirely threadsafe, and has no instance members.
047: * It may be used in any scope (request, session, or application).
048: * </p>
049: *
050: * @author <a href="mailto:shinobu@ieee.org">Shinobu Kawai</a>
051: */
052: public class ArrayTool {
053:
054: /**
055: * Default constructor.
056: */
057: public ArrayTool() {
058: }
059:
060: /**
061: * Converts an array object into a java.util.List.
062: * <ul>
063: * <li>
064: * If the object is an array of an Object,
065: * it will return a java.util.List of the elements.
066: * </li>
067: * <li>
068: * If the object is an array of a primitive type,
069: * it will return a java.util.List of the elements wrapped in their wrapper class.
070: * </li>
071: * <li>
072: * If the object is none of the above, it will return null.
073: * </li>
074: * </ul>
075: *
076: * @param array an array object.
077: * @return the converted java.util.List.
078: */
079: public List list(Object array) {
080: if (!this .isArray(array)) {
081: return null;
082: }
083:
084: // Thanks to Eric Fixler for this refactor.
085: int length = Array.getLength(array);
086: List asList = new ArrayList(length);
087: for (int index = 0; index < length; ++index) {
088: asList.add(Array.get(array, index));
089: }
090: return asList;
091: }
092:
093: /**
094: * Gets the specified element of an array.
095: * It will return null under the following conditions:
096: * <ul>
097: * <li><code>array</code> is null.</li>
098: * <li><code>array</code> is not an array.</li>
099: * <li><code>array</code> doesn't have an <code>index</code>th value.</li>
100: * </ul>
101: *
102: * @param array the array object.
103: * @param index the index of the array to get.
104: * @return the specified element of the array.
105: */
106: public Object get(Object array, int index) {
107: if (!this .isArray(array)) {
108: return null;
109: }
110:
111: try {
112: return Array.get(array, index);
113: } catch (IndexOutOfBoundsException e) {
114: // The index was wrong.
115: return null;
116: }
117: }
118:
119: /**
120: * Sets the specified element of an array.
121: * It will return null under the following conditions:
122: * <ul>
123: * <li><code>array</code> is null.</li>
124: * <li><code>array</code> is not an array.</li>
125: * <li><code>array</code> doesn't have an <code>index</code>th value.</li>
126: * </ul>
127: *
128: * @param array the array object.
129: * @param index the index of the array to set.
130: * @param value the element to set.
131: */
132: public Object set(Object array, int index, Object value) {
133: if (!this .isArray(array)) {
134: return null;
135: }
136:
137: try {
138: Array.set(array, index, value);
139: return "";
140: } catch (IndexOutOfBoundsException e) {
141: // The index was wrong.
142: return null;
143: }
144: }
145:
146: /**
147: * Gets the length of an array.
148: * It will return null under the following conditions:
149: * <ul>
150: * <li><code>array</code> is null.</li>
151: * <li><code>array</code> is not an array.</li>
152: * </ul>
153: *
154: * @param array the array object.
155: * @return the length of the array.
156: */
157: public Integer length(Object array) {
158: if (!this .isArray(array)) {
159: return null;
160: }
161:
162: // Thanks to Eric Fixler for this refactor.
163: return new Integer(Array.getLength(array));
164: }
165:
166: /**
167: * Gets the clone of an array.
168: * It will return null under the following conditions:
169: * <ul>
170: * <li><code>array</code> is null.</li>
171: * <li><code>array</code> is not an array.</li>
172: * </ul>
173: *
174: * @param array the array object.
175: * @return the clone of the array.
176: */
177: public Object clone(Object array) {
178: if (!this .isArray(array)) {
179: return null;
180: }
181:
182: Class type = array.getClass().getComponentType();
183: int length = Array.getLength(array);
184: Object clone = Array.newInstance(type, length);
185: System.arraycopy(array, 0, clone, 0, length);
186: return clone;
187: }
188:
189: /**
190: * Checks if an object is an array.
191: *
192: * @param object the object to check.
193: * @return <code>true</code> if the object is an array.
194: */
195: public boolean isArray(Object object) {
196: if (object == null) {
197: return false;
198: }
199: return object.getClass().isArray();
200: }
201: }
|