001: package org.apache.velocity.tools.generic;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.lang.reflect.Array;
023: import java.util.List;
024:
025: /**
026: * Tool for working with Lists and arrays in Velocity templates.
027: * It provides a method to get and set specified elements.
028: * Also provides methods to perform the following actions to Lists and arrays:
029: * <ul>
030: * <li>Check if it is empty.</li>
031: * <li>Check if it contains a certain element.</li>
032: * </ul>
033: *
034: * <p><pre>
035: * Example uses:
036: * $primes -> new int[] {2, 3, 5, 7}
037: * $list.size($primes) -> 4
038: * $list.get($primes, 2) -> 5
039: * $list.set($primes, 2, 1) -> (primes[2] becomes 1)
040: * $list.get($primes, 2) -> 1
041: * $list.isEmpty($primes) -> false
042: * $list.contains($primes, 7) -> true
043: *
044: * Example toolbox.xml config (if you want to use this with VelocityView):
045: * <tool>
046: * <key>list</key>
047: * <scope>application</scope>
048: * <class>org.apache.velocity.tools.generic.ListTool</class>
049: * </tool>
050: * </pre></p>
051: *
052: * <p>This tool is entirely threadsafe, and has no instance members.
053: * It may be used in any scope (request, session, or application).
054: * </p>
055: *
056: * @author <a href="mailto:shinobu@ieee.org">Shinobu Kawai</a>
057: * @version $Id: $
058: * @since VelocityTools 1.2
059: */
060: public class ListTool {
061:
062: /**
063: * Default constructor.
064: */
065: public ListTool() {
066: }
067:
068: /**
069: * Gets the specified element of a List/array.
070: * It will return null under the following conditions:
071: * <ul>
072: * <li><code>list</code> is null.</li>
073: * <li><code>list</code> is not a List/array.</li>
074: * <li><code>list</code> doesn't have an <code>index</code>th value.</li>
075: * </ul>
076: * @param list the List/array object.
077: * @param index the index of the List/array to get.
078: * @return the specified element of the List/array.
079: */
080: public Object get(Object list, int index) {
081: if (isArray(list)) {
082: return getFromArray(list, index);
083: }
084: if (!isList(list)) {
085: return null;
086: }
087:
088: try {
089: return ((List) list).get(index);
090: } catch (IndexOutOfBoundsException e) {
091: // The index was wrong.
092: return null;
093: }
094: }
095:
096: /**
097: * Gets the specified element of an array.
098: * @param array the array object.
099: * @param index the index of the array to get.
100: * @return the specified element of the array.
101: */
102: private Object getFromArray(Object array, int index) {
103: try {
104: return Array.get(array, index);
105: } catch (IndexOutOfBoundsException e) {
106: // The index was wrong.
107: return null;
108: }
109: }
110:
111: /**
112: * Sets the specified element of a List/array.
113: * It will return null under the following conditions:
114: * <ul>
115: * <li><code>list</code> is null.</li>
116: * <li><code>list</code> is not a List/array.</li>
117: * <li><code>list</code> doesn't have an <code>index</code>th value.</li>
118: * </ul>
119: * @param list the List/array object.
120: * @param index the index of the List/array to set.
121: * @param value the element to set.
122: * @return blank if set, null if not set.
123: */
124: public Object set(Object list, int index, Object value) {
125: if (isArray(list)) {
126: return setToArray(list, index, value);
127: }
128: if (!isList(list)) {
129: return null;
130: }
131:
132: try {
133: ((List) list).set(index, value);
134: return "";
135: } catch (IndexOutOfBoundsException e) {
136: // The index was wrong.
137: return null;
138: }
139: }
140:
141: /**
142: * Sets the specified element of an array.
143: * @param array the array object.
144: * @param index the index of the array to set.
145: * @param value the element to set.
146: * @return blank if set, null if not set.
147: */
148: private Object setToArray(Object array, int index, Object value) {
149: try {
150: Array.set(array, index, value);
151: return "";
152: } catch (IndexOutOfBoundsException e) {
153: // The index was wrong.
154: return null;
155: }
156: }
157:
158: /**
159: * Gets the size of a List/array.
160: * It will return null under the following conditions:
161: * <ul>
162: * <li><code>list</code> is null.</li>
163: * <li><code>list</code> is not a List/array.</li>
164: * </ul>
165: * @param list the List object.
166: * @return the size of the List.
167: */
168: public Integer size(Object list) {
169: if (isArray(list)) {
170: // Thanks to Eric Fixler for this refactor.
171: return new Integer(Array.getLength(list));
172: }
173: if (!isList(list)) {
174: return null;
175: }
176:
177: return new Integer(((List) list).size());
178: }
179:
180: /**
181: * Checks if an object is an array.
182: * @param object the object to check.
183: * @return <code>true</code> if the object is an array.
184: */
185: public boolean isArray(Object object) {
186: if (object == null) {
187: return false;
188: }
189: return object.getClass().isArray();
190: }
191:
192: /**
193: * Checks if an object is a List.
194: * @param object the object to check.
195: * @return <code>true</code> if the object is a List.
196: */
197: public boolean isList(Object object) {
198: return object instanceof List;
199: }
200:
201: /**
202: * Checks if a List/array is empty.
203: * @param list the List/array to check.
204: * @return <code>true</code> if the List/array is empty.
205: */
206: public Boolean isEmpty(Object list) {
207: Integer size = size(list);
208: if (size == null) {
209: return null;
210: }
211:
212: return new Boolean(size.intValue() == 0);
213: }
214:
215: /**
216: * Checks if a List/array contains a certain element.
217: * @param list the List/array to check.
218: * @param element the element to check.
219: * @return <code>true</code> if the List/array contains the element.
220: */
221: public Boolean contains(Object list, Object element) {
222: if (isArray(list)) {
223: return arrayContains(list, element);
224: }
225: if (!isList(list)) {
226: return null;
227: }
228:
229: return new Boolean(((List) list).contains(element));
230: }
231:
232: /**
233: * Checks if an array contains a certain element.
234: * @param array the array to check.
235: * @param element the element to check.
236: * @return <code>true</code> if the array contains the element.
237: */
238: private Boolean arrayContains(Object array, Object element) {
239: int size = size(array).intValue();
240:
241: for (int index = 0; index < size; ++index) {
242: if (equals(element, getFromArray(array, index))) {
243: return Boolean.TRUE;
244: }
245: }
246: return Boolean.FALSE;
247: }
248:
249: /**
250: * Check if two objects are equal.
251: * @param what an object
252: * @param with another object.
253: * @return <code>true</code> if the two objects are equal.
254: */
255: private boolean equals(Object what, Object with) {
256: if (what == null) {
257: return with == null;
258: }
259:
260: return what.equals(with);
261: }
262:
263: }
|