001/*
002 * Copyright 2002-2012 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 *      https://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
017package org.springframework.beans;
018
019import java.io.PrintStream;
020import java.io.PrintWriter;
021
022import org.springframework.util.Assert;
023import org.springframework.util.ObjectUtils;
024
025/**
026 * Combined exception, composed of individual PropertyAccessException instances.
027 * An object of this class is created at the beginning of the binding
028 * process, and errors added to it as necessary.
029 *
030 * <p>The binding process continues when it encounters application-level
031 * PropertyAccessExceptions, applying those changes that can be applied
032 * and storing rejected changes in an object of this class.
033 *
034 * @author Rod Johnson
035 * @author Juergen Hoeller
036 * @since 18 April 2001
037 */
038@SuppressWarnings("serial")
039public class PropertyBatchUpdateException extends BeansException {
040
041        /** List of PropertyAccessException objects */
042        private PropertyAccessException[] propertyAccessExceptions;
043
044
045        /**
046         * Create a new PropertyBatchUpdateException.
047         * @param propertyAccessExceptions the List of PropertyAccessExceptions
048         */
049        public PropertyBatchUpdateException(PropertyAccessException[] propertyAccessExceptions) {
050                super(null);
051                Assert.notEmpty(propertyAccessExceptions, "At least 1 PropertyAccessException required");
052                this.propertyAccessExceptions = propertyAccessExceptions;
053        }
054
055
056        /**
057         * If this returns 0, no errors were encountered during binding.
058         */
059        public final int getExceptionCount() {
060                return this.propertyAccessExceptions.length;
061        }
062
063        /**
064         * Return an array of the propertyAccessExceptions stored in this object.
065         * <p>Will return the empty array (not {@code null}) if there were no errors.
066         */
067        public final PropertyAccessException[] getPropertyAccessExceptions() {
068                return this.propertyAccessExceptions;
069        }
070
071        /**
072         * Return the exception for this field, or {@code null} if there isn't any.
073         */
074        public PropertyAccessException getPropertyAccessException(String propertyName) {
075                for (PropertyAccessException pae : this.propertyAccessExceptions) {
076                        if (ObjectUtils.nullSafeEquals(propertyName, pae.getPropertyName())) {
077                                return pae;
078                        }
079                }
080                return null;
081        }
082
083
084        @Override
085        public String getMessage() {
086                StringBuilder sb = new StringBuilder("Failed properties: ");
087                for (int i = 0; i < this.propertyAccessExceptions.length; i++) {
088                        sb.append(this.propertyAccessExceptions[i].getMessage());
089                        if (i < this.propertyAccessExceptions.length - 1) {
090                                sb.append("; ");
091                        }
092                }
093                return sb.toString();
094        }
095
096        @Override
097        public String toString() {
098                StringBuilder sb = new StringBuilder();
099                sb.append(getClass().getName()).append("; nested PropertyAccessExceptions (");
100                sb.append(getExceptionCount()).append(") are:");
101                for (int i = 0; i < this.propertyAccessExceptions.length; i++) {
102                        sb.append('\n').append("PropertyAccessException ").append(i + 1).append(": ");
103                        sb.append(this.propertyAccessExceptions[i]);
104                }
105                return sb.toString();
106        }
107
108        @Override
109        public void printStackTrace(PrintStream ps) {
110                synchronized (ps) {
111                        ps.println(getClass().getName() + "; nested PropertyAccessException details (" +
112                                        getExceptionCount() + ") are:");
113                        for (int i = 0; i < this.propertyAccessExceptions.length; i++) {
114                                ps.println("PropertyAccessException " + (i + 1) + ":");
115                                this.propertyAccessExceptions[i].printStackTrace(ps);
116                        }
117                }
118        }
119
120        @Override
121        public void printStackTrace(PrintWriter pw) {
122                synchronized (pw) {
123                        pw.println(getClass().getName() + "; nested PropertyAccessException details (" +
124                                        getExceptionCount() + ") are:");
125                        for (int i = 0; i < this.propertyAccessExceptions.length; i++) {
126                                pw.println("PropertyAccessException " + (i + 1) + ":");
127                                this.propertyAccessExceptions[i].printStackTrace(pw);
128                        }
129                }
130        }
131
132        @Override
133        public boolean contains(Class<?> exType) {
134                if (exType == null) {
135                        return false;
136                }
137                if (exType.isInstance(this)) {
138                        return true;
139                }
140                for (PropertyAccessException pae : this.propertyAccessExceptions) {
141                        if (pae.contains(exType)) {
142                                return true;
143                        }
144                }
145                return false;
146        }
147
148}