001: /*
002: * Copyright 2002-2006 the original author or authors.
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:
017: package org.springframework.dao.support;
018:
019: import java.util.Collection;
020:
021: import org.springframework.dao.DataAccessException;
022: import org.springframework.dao.EmptyResultDataAccessException;
023: import org.springframework.dao.IncorrectResultSizeDataAccessException;
024: import org.springframework.dao.TypeMismatchDataAccessException;
025: import org.springframework.util.Assert;
026: import org.springframework.util.CollectionUtils;
027: import org.springframework.util.NumberUtils;
028:
029: /**
030: * Miscellaneous utility methods for DAO implementations.
031: * Useful with any data access technology.
032: *
033: * @author Juergen Hoeller
034: * @since 1.0.2
035: */
036: public abstract class DataAccessUtils {
037:
038: /**
039: * Return a single result object from the given Collection.
040: * <p>Returns <code>null</code> if 0 result objects found;
041: * throws an exception if more than 1 element found.
042: * @param results the result Collection (can be <code>null</code>)
043: * @return the single result object, or <code>null</code> if none
044: * @throws IncorrectResultSizeDataAccessException if more than one
045: * element has been found in the given Collection
046: */
047: public static Object singleResult(Collection results)
048: throws IncorrectResultSizeDataAccessException {
049: int size = (results != null ? results.size() : 0);
050: if (size == 0) {
051: return null;
052: }
053: if (results.size() > 1) {
054: throw new IncorrectResultSizeDataAccessException(1, size);
055: }
056: return results.iterator().next();
057: }
058:
059: /**
060: * Return a single result object from the given Collection.
061: * <p>Throws an exception if 0 or more than 1 element found.
062: * @param results the result Collection (can be <code>null</code>)
063: * @return the single result object
064: * @throws IncorrectResultSizeDataAccessException if more than one
065: * element has been found in the given Collection
066: * @throws EmptyResultDataAccessException if no element at all
067: * has been found in the given Collection
068: */
069: public static Object requiredSingleResult(Collection results)
070: throws IncorrectResultSizeDataAccessException {
071: int size = (results != null ? results.size() : 0);
072: if (size == 0) {
073: throw new EmptyResultDataAccessException(1);
074: }
075: if (results.size() > 1) {
076: throw new IncorrectResultSizeDataAccessException(1, size);
077: }
078: return results.iterator().next();
079: }
080:
081: /**
082: * Return a unique result object from the given Collection.
083: * <p>Returns <code>null</code> if 0 result objects found;
084: * throws an exception if more than 1 instance found.
085: * @param results the result Collection (can be <code>null</code>)
086: * @return the unique result object, or <code>null</code> if none
087: * @throws IncorrectResultSizeDataAccessException if more than one
088: * result object has been found in the given Collection
089: * @see org.springframework.util.CollectionUtils#hasUniqueObject
090: */
091: public static Object uniqueResult(Collection results)
092: throws IncorrectResultSizeDataAccessException {
093: int size = (results != null ? results.size() : 0);
094: if (size == 0) {
095: return null;
096: }
097: if (!CollectionUtils.hasUniqueObject(results)) {
098: throw new IncorrectResultSizeDataAccessException(1, size);
099: }
100: return results.iterator().next();
101: }
102:
103: /**
104: * Return a unique result object from the given Collection.
105: * <p>Throws an exception if 0 or more than 1 instance found.
106: * @param results the result Collection (can be <code>null</code>)
107: * @return the unique result object
108: * @throws IncorrectResultSizeDataAccessException if more than one
109: * result object has been found in the given Collection
110: * @throws EmptyResultDataAccessException if no result object at all
111: * has been found in the given Collection
112: * @see org.springframework.util.CollectionUtils#hasUniqueObject
113: */
114: public static Object requiredUniqueResult(Collection results)
115: throws IncorrectResultSizeDataAccessException {
116: int size = (results != null ? results.size() : 0);
117: if (size == 0) {
118: throw new EmptyResultDataAccessException(1);
119: }
120: if (!CollectionUtils.hasUniqueObject(results)) {
121: throw new IncorrectResultSizeDataAccessException(1, size);
122: }
123: return results.iterator().next();
124: }
125:
126: /**
127: * Return a unique result object from the given Collection.
128: * Throws an exception if 0 or more than 1 result objects found,
129: * of if the unique result object is not convertable to the
130: * specified required type.
131: * @param results the result Collection (can be <code>null</code>)
132: * @return the unique result object
133: * @throws IncorrectResultSizeDataAccessException if more than one
134: * result object has been found in the given Collection
135: * @throws EmptyResultDataAccessException if no result object
136: * at all has been found in the given Collection
137: * @throws TypeMismatchDataAccessException if the unique object does
138: * not match the specified required type
139: */
140: public static Object objectResult(Collection results,
141: Class requiredType)
142: throws IncorrectResultSizeDataAccessException,
143: TypeMismatchDataAccessException {
144:
145: Object result = requiredUniqueResult(results);
146: if (requiredType != null && !requiredType.isInstance(result)) {
147: if (String.class.equals(requiredType)) {
148: result = result.toString();
149: } else if (Number.class.isAssignableFrom(requiredType)
150: && Number.class.isInstance(result)) {
151: try {
152: result = NumberUtils.convertNumberToTargetClass(
153: ((Number) result), requiredType);
154: } catch (IllegalArgumentException ex) {
155: throw new TypeMismatchDataAccessException(ex
156: .getMessage());
157: }
158: } else {
159: throw new TypeMismatchDataAccessException(
160: "Result object is of type ["
161: + result.getClass().getName()
162: + "] and could not be converted to required type ["
163: + requiredType.getName() + "]");
164: }
165: }
166: return result;
167: }
168:
169: /**
170: * Return a unique int result from the given Collection.
171: * Throws an exception if 0 or more than 1 result objects found,
172: * of if the unique result object is not convertable to an int.
173: * @param results the result Collection (can be <code>null</code>)
174: * @return the unique int result
175: * @throws IncorrectResultSizeDataAccessException if more than one
176: * result object has been found in the given Collection
177: * @throws EmptyResultDataAccessException if no result object
178: * at all has been found in the given Collection
179: * @throws TypeMismatchDataAccessException if the unique object
180: * in the collection is not convertable to an int
181: */
182: public static int intResult(Collection results)
183: throws IncorrectResultSizeDataAccessException,
184: TypeMismatchDataAccessException {
185:
186: return ((Number) objectResult(results, Number.class))
187: .intValue();
188: }
189:
190: /**
191: * Return a unique long result from the given Collection.
192: * Throws an exception if 0 or more than 1 result objects found,
193: * of if the unique result object is not convertable to a long.
194: * @param results the result Collection (can be <code>null</code>)
195: * @return the unique long result
196: * @throws IncorrectResultSizeDataAccessException if more than one
197: * result object has been found in the given Collection
198: * @throws EmptyResultDataAccessException if no result object
199: * at all has been found in the given Collection
200: * @throws TypeMismatchDataAccessException if the unique object
201: * in the collection is not convertable to a long
202: */
203: public static long longResult(Collection results)
204: throws IncorrectResultSizeDataAccessException,
205: TypeMismatchDataAccessException {
206:
207: return ((Number) objectResult(results, Number.class))
208: .longValue();
209: }
210:
211: /**
212: * Return a translated exception if this is appropriate,
213: * otherwise return the input exception.
214: * @param rawException exception we may wish to translate
215: * @param pet PersistenceExceptionTranslator to use to perform the translation
216: * @return a translated exception if translation is possible, or
217: * the raw exception if it is not
218: */
219: public static RuntimeException translateIfNecessary(
220: RuntimeException rawException,
221: PersistenceExceptionTranslator pet) {
222:
223: Assert.notNull(pet,
224: "PersistenceExceptionTranslator must not be null");
225: DataAccessException dex = pet
226: .translateExceptionIfPossible(rawException);
227: return (dex != null ? dex : rawException);
228: }
229:
230: }
|