View Javadoc
1   /*******************************************************************************
2    * Portions created by Sebastian Thomschke are copyright (c) 2005-2013 Sebastian
3    * Thomschke.
4    *
5    * All Rights Reserved. This program and the accompanying materials
6    * are made available under the terms of the Eclipse Public License v1.0
7    * which accompanies this distribution, and is available at
8    * http://www.eclipse.org/legal/epl-v10.html
9    *
10   * Contributors:
11   *     Sebastian Thomschke - initial implementation.
12   *******************************************************************************/
13  package net.sf.oval;
14  
15  import java.io.IOException;
16  import java.io.Serializable;
17  import java.util.List;
18  import java.util.Map;
19  
20  import net.sf.oval.context.OValContext;
21  import net.sf.oval.internal.Log;
22  
23  /**
24   * An instance of this class provides detailed information about a single constraint
25   * violation that occurred during validation.
26   *
27   * @author Sebastian Thomschke
28   */
29  public class ConstraintViolation implements Serializable
30  {
31  	private static final Log LOG = Log.getLog(ConstraintViolation.class);
32  
33  	private static final long serialVersionUID = 1L;
34  
35  	private final ConstraintViolation[] causes;
36  	private final OValContext checkDeclaringContext;
37  	private final String checkName;
38  	private final OValContext context;
39  	private final String errorCode;
40  	private transient Object invalidValue;
41  	private final String message;
42  	private final String messageTemplate;
43  	private final Map<String, ? extends Serializable> messageVariables;
44  
45  	private final int severity;
46  	private transient Object validatedObject;
47  
48  	public ConstraintViolation(final Check check, final String message, final Object validatedObject, final Object invalidValue,
49  			final OValContext context)
50  	{
51  		this(check, message, validatedObject, invalidValue, context, (ConstraintViolation[]) null);
52  	}
53  
54  	public ConstraintViolation(final Check check, final String message, final Object validatedObject, final Object invalidValue,
55  			final OValContext context, final ConstraintViolation... causes)
56  	{
57  		checkName = check.getClass().getName();
58  		checkDeclaringContext = check.getContext();
59  		errorCode = check.getErrorCode();
60  		this.message = message;
61  		messageTemplate = check.getMessage();
62  		messageVariables = check.getMessageVariables();
63  		severity = check.getSeverity();
64  		this.validatedObject = validatedObject;
65  		this.invalidValue = invalidValue;
66  		this.context = context;
67  		this.causes = causes != null && causes.length == 0 ? null : causes;
68  	}
69  
70  	public ConstraintViolation(final Check check, final String message, final Object validatedObject, final Object invalidValue,
71  			final OValContext context, final List<ConstraintViolation> causes)
72  	{
73  		checkName = check.getClass().getName();
74  		checkDeclaringContext = check.getContext();
75  		errorCode = check.getErrorCode();
76  		this.message = message;
77  		messageTemplate = check.getMessage();
78  		messageVariables = check.getMessageVariables();
79  		severity = check.getSeverity();
80  		this.validatedObject = validatedObject;
81  		this.invalidValue = invalidValue;
82  		this.context = context;
83  		this.causes = causes == null || causes.size() == 0 ? null : causes.toArray(new ConstraintViolation[causes.size()]);
84  	}
85  
86  	/**
87  	 * @return the causes or null of no causes exists
88  	 */
89  	public ConstraintViolation[] getCauses()
90  	{
91  		return causes == null ? null : (ConstraintViolation[]) causes.clone();
92  	}
93  
94  	/**
95  	 * @return Returns the context where the constraint was declared.
96  	 *
97  	 * @see net.sf.oval.context.ClassContext
98  	 * @see net.sf.oval.context.FieldContext
99  	 * @see net.sf.oval.context.MethodEntryContext
100 	 * @see net.sf.oval.context.MethodExitContext
101 	 * @see net.sf.oval.context.MethodParameterContext
102 	 * @see net.sf.oval.context.MethodReturnValueContext
103 	 */
104 	public OValContext getCheckDeclaringContext()
105 	{
106 		return checkDeclaringContext;
107 	}
108 
109 	/**
110 	 * @return the fully qualified class name of the corresponding check
111 	 */
112 	public String getCheckName()
113 	{
114 		return checkName;
115 	}
116 
117 	/**
118 	 * @return Returns the context where the constraint violation occurred.
119 	 *
120 	 * @see net.sf.oval.context.ClassContext
121 	 * @see net.sf.oval.context.FieldContext
122 	 * @see net.sf.oval.context.MethodEntryContext
123 	 * @see net.sf.oval.context.MethodExitContext
124 	 * @see net.sf.oval.context.MethodParameterContext
125 	 * @see net.sf.oval.context.MethodReturnValueContext
126 	 */
127 	public OValContext getContext()
128 	{
129 		return context;
130 	}
131 
132 	/**
133 	 * @return the error code
134 	 */
135 	public String getErrorCode()
136 	{
137 		return errorCode;
138 	}
139 
140 	/**
141 	 * @return Returns the value that was validated.
142 	 */
143 	public Object getInvalidValue()
144 	{
145 		return invalidValue;
146 	}
147 
148 	/**
149 	 * @return the localized and rendered message
150 	 */
151 	public String getMessage()
152 	{
153 		return message;
154 	}
155 
156 	/**
157 	 * @return the raw message specified for the constraint without variable resolution and localization
158 	 */
159 	public String getMessageTemplate()
160 	{
161 		return messageTemplate;
162 	}
163 
164 	/**
165 	 * Returns the message variables provided by the corresponding check.
166 	 * @return an unmodifiable map holding the message variables provided by the corresponding check.
167 	 */
168 	public Map<String, ? extends Serializable> getMessageVariables()
169 	{
170 		return messageVariables;
171 	}
172 
173 	/**
174 	 * @return the severity
175 	 */
176 	public int getSeverity()
177 	{
178 		return severity;
179 	}
180 
181 	/**
182 	 * @return the validatedObject
183 	 */
184 	public Object getValidatedObject()
185 	{
186 		return validatedObject;
187 	}
188 
189 	/**
190 	 * see http://java.sun.com/developer/technicalArticles/ALT/serialization/
191 	 *
192 	 * @param in
193 	 * @throws IOException
194 	 * @throws ClassNotFoundException
195 	 */
196 	private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
197 	{
198 		in.defaultReadObject();
199 		if (in.readBoolean()) validatedObject = in.readObject();
200 		if (in.readBoolean()) invalidValue = in.readObject();
201 	}
202 
203 	/**
204 	 * {@inheritDoc}
205 	 */
206 	@Override
207 	public String toString()
208 	{
209 		return getClass().getName() + ": " + message;
210 	}
211 
212 	/**
213 	 * see http://java.sun.com/developer/technicalArticles/ALT/serialization/
214 	 *
215 	 * @param out
216 	 * @throws IOException
217 	 */
218 	private void writeObject(final java.io.ObjectOutputStream out) throws IOException
219 	{
220 		out.defaultWriteObject();
221 		if (validatedObject instanceof Serializable)
222 		{
223 			// indicate validatedObject implements Serializable
224 			out.writeBoolean(true);
225 			out.writeObject(validatedObject);
226 		}
227 		else
228 		{
229 			LOG.warn("Field 'validatedObject' not serialized because the field value object " + validatedObject + " of type "
230 					+ invalidValue.getClass() + " does not implement " + Serializable.class.getName());
231 
232 			// indicate validatedObject does not implement Serializable
233 			out.writeBoolean(false);
234 		}
235 
236 		if (invalidValue instanceof Serializable)
237 		{
238 			// indicate value implements Serializable
239 			out.writeBoolean(true);
240 			out.writeObject(invalidValue);
241 		}
242 		else
243 		{
244 			final String warning = //
245 			"Field 'invalidValue' could not be serialized because the field value object {1} does not implement java.io.Serializable.";
246 			LOG.warn(warning, invalidValue);
247 			// indicate value does not implement Serializable
248 			out.writeBoolean(false);
249 		}
250 	}
251 }