SLING-3709 improve exception handling by using dedicated exception classes instead of the one global result object

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1680581 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/models/factory/MissingElementException.java b/src/main/java/org/apache/sling/models/factory/MissingElementException.java
new file mode 100644
index 0000000..09195aa
--- /dev/null
+++ b/src/main/java/org/apache/sling/models/factory/MissingElementException.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.models.factory;
+
+import java.lang.reflect.AnnotatedElement;
+
+/**
+ * Exception which is used whenever one element (field, method or constructor) could not be set.
+ * @see MissingElementsException
+ */
+public class MissingElementException extends RuntimeException {
+
+    private static final long serialVersionUID = 5782291184414886658L;
+    private final AnnotatedElement element;
+
+    public MissingElementException(AnnotatedElement element, Throwable cause) {
+        super("Could not inject " + element, cause);
+        this.element = element;
+    }
+
+    public AnnotatedElement getElement() {
+        return element;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/models/factory/MissingElementsException.java b/src/main/java/org/apache/sling/models/factory/MissingElementsException.java
index f8377fd..7c02dbe 100644
--- a/src/main/java/org/apache/sling/models/factory/MissingElementsException.java
+++ b/src/main/java/org/apache/sling/models/factory/MissingElementsException.java
@@ -18,13 +18,14 @@
  */
 package org.apache.sling.models.factory;
 
-import java.lang.reflect.AnnotatedElement;
+import java.util.ArrayList;
 import java.util.Collection;
 
 /**
  * Exception which is triggered whenever a Sling Model cannot be instantiated
- * due to some missing elements (i.e. required fields/methods/constructor params
+ * due to some missing elements (i.e. required fields/methods/constructor parameters
  * could not be injected).
+ * Contains a number of {@link MissingElementException}s.
  * 
  * @see ModelFactory
  *
@@ -32,29 +33,37 @@
 public final class MissingElementsException extends RuntimeException {
     private static final long serialVersionUID = 7870762030809272254L;
 
-    private final Collection<? extends AnnotatedElement> missingElements;
+    private Collection<MissingElementException> missingElements;
 
-    private String formatString;
-
-    private Class<?> type;
-
-    public MissingElementsException(String format, Collection<? extends AnnotatedElement> elements, Class<?> type) {
-        super();
-        this.formatString = format;
-        this.missingElements = elements;
-        this.type = type;
+    
+    public MissingElementsException(String message) {
+        super(message);
+        missingElements = new ArrayList<MissingElementException>();
     }
 
     @Override
     public String getMessage() {
-        return String.format(formatString, missingElements, type);
+        StringBuilder message = new StringBuilder(super.getMessage());
+        for (MissingElementException e : missingElements) {
+            message.append('\n');
+            message.append(e.getMessage());
+            if (e.getCause() != null) {
+                message.append(" caused by ");
+                message.append(e.getCause().getMessage());
+            }
+        }
+        return message.toString();
     }
 
-    public Class<?> getType() {
-        return type;
+    public void addMissingElementExceptions(MissingElementException e) {
+        missingElements.add(e);
     }
-
-    public Collection<? extends AnnotatedElement> getMissingElements() {
+    
+    public boolean isEmpty() {
+        return missingElements.isEmpty();
+    }
+    
+    public Collection<MissingElementException> getMissingElements() {
         return missingElements;
     }
 }
diff --git a/src/main/java/org/apache/sling/models/factory/ModelClassException.java b/src/main/java/org/apache/sling/models/factory/ModelClassException.java
index 7718dd6..6ef5118 100644
--- a/src/main/java/org/apache/sling/models/factory/ModelClassException.java
+++ b/src/main/java/org/apache/sling/models/factory/ModelClassException.java
@@ -32,4 +32,8 @@
     public ModelClassException(String message) {
         super(message);
     }
+    
+    public ModelClassException(String message, Throwable e) {
+        super(message, e);
+    }
 }