View Javadoc
1   /*
2    * Redistribution and use of this software and associated documentation ("Software"), with or
3    * without modification, are permitted provided that the following conditions are met:
4    *
5    * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6    * must also contain a copy of this document.
7    *
8    * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9    * conditions and the following disclaimer in the documentation and/or other materials provided with
10   * the distribution.
11   *
12   * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13   * without prior written permission of Intalio, Inc. For written permission, please contact
14   * info@exolab.org.
15   *
16   * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17   * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18   * Intalio, Inc.
19   *
20   * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21   *
22   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29   * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * Copyright 1999-2002 (C) Intalio, Inc. All Rights Reserved.
32   *
33   * This file was originally developed by Keith Visco during the course of employment at Intalio Inc.
34   * All portions of this file developed by Keith Visco after Jan 19 2005 are Copyright (C) 2005 Keith
35   * Visco. All Rights Reserved.
36   *
37   * $Id$
38   */
39  package org.exolab.castor.xml;
40  
41  import java.text.MessageFormat;
42  import java.util.Locale;
43  import java.util.ResourceBundle;
44  
45  import org.apache.commons.logging.Log;
46  import org.apache.commons.logging.LogFactory;
47  import org.castor.xml.BackwardCompatibilityContext;
48  import org.castor.xml.InternalContext;
49  import org.exolab.castor.mapping.FieldDescriptor;
50  import org.exolab.castor.xml.location.XPathLocation;
51  import org.exolab.castor.xml.validators.ClassValidator;
52  
53  /**
54   * A class which can perform Validation on an Object model. This class uses the ClassDescriptors and
55   * FieldDescriptors to perform the validation.
56   *
57   * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
58   * @version $Revision$ $Date: 2005-02-28 17:43:25 -0700 (Mon, 28 Feb 2005) $
59   */
60  public class Validator implements ClassValidator {
61    private static final Log LOG = LogFactory.getLog(Validator.class);
62  
63    /** resource bundle */
64    protected static ResourceBundle resourceBundle;
65  
66    static {
67      resourceBundle = ResourceBundle.getBundle("ValidationMessages", Locale.getDefault());
68    }
69  
70    /**
71     * Creates a new Validator.
72     */
73    public Validator() {
74      super();
75      // usage
76      // MessageFormat.format(rbm.getString(validator.cannot.validate.null.object), new Object[]
77      // {"Yes!!!", "is"});
78    } // -- Validator
79  
80    /**
81     * Validates the given Object.
82     *
83     * @param object the Object to validate
84     * @throws ValidationException if validation fails.
85     */
86    public void validate(final Object object) throws ValidationException {
87      validate(object, (ValidationContext) null);
88    }
89  
90    /**
91     * Validates the given Object.
92     *
93     * @param object the Object to validate
94     * @param context the ValidationContext to use during validation.
95     * @throws ValidationException if validation fails.
96     */
97    public void validate(final Object object, final ValidationContext context)
98        throws ValidationException {
99      if (object == null) {
100       throw new ValidationException(
101           resourceBundle.getString("validator.error.cannot.validate.null.object"));
102     }
103 
104     if (context == null) {
105       ValidationContext v2 = new ValidationContext();
106       InternalContext ic = new BackwardCompatibilityContext();
107       ic.setClassLoader(object.getClass().getClassLoader());
108       v2.setInternalContext(ic);
109       validate(object, v2);
110       return;
111     }
112 
113     if (context.getClassDescriptorResolver() == null) {
114       String message = resourceBundle.getString("validator.error.class.descriptor.resolver.null");
115       throw new IllegalStateException(message);
116     }
117 
118     XMLClassDescriptor classDesc = null;
119 
120     if (!MarshalFramework.isPrimitive(object.getClass())) {
121       try {
122         classDesc =
123             (XMLClassDescriptor) context.getClassDescriptorResolver().resolve(object.getClass());
124       } catch (ResolverException rx) {
125         throw new ValidationException(rx);
126       }
127     }
128 
129     // -- we cannot validate an object if ClassDescriptor is null
130     if (classDesc == null) {
131       return;
132     }
133 
134     XMLFieldDescriptor fieldDesc = null;
135 
136     try {
137       TypeValidator validator = classDesc.getValidator();
138       if (validator != null) {
139         validator.validate(object, context);
140       } else {
141         // Default validation -- just validate each field
142         FieldDescriptor[] fields = classDesc.getFields();
143         if (fields != null) {
144           for (int i = 0; i < fields.length; i++) {
145             fieldDesc = (XMLFieldDescriptor) fields[i];
146             if (fieldDesc == null) {
147               continue;
148             }
149             FieldValidator fieldValidator = fieldDesc.getValidator();
150             if (fieldValidator != null) {
151               fieldValidator.validate(object, context);
152             }
153           }
154         }
155       }
156     } catch (ValidationException vx) {
157       // -- add location information
158       XPathLocation loc = (XPathLocation) vx.getLocation();
159       if (loc == null) {
160         loc = new XPathLocation();
161         vx.setLocation(loc);
162         if (fieldDesc != null) {
163           if (fieldDesc.getNodeType() == NodeType.Attribute) {
164             loc.addAttribute(fieldDesc.getXMLName());
165           } else {
166             loc.addChild(fieldDesc.getXMLName());
167           }
168         }
169       }
170       if (classDesc.getXMLName() != null) {
171         loc.addParent(classDesc.getXMLName());
172       }
173       throw vx;
174     }
175 
176     // checkUnresolvedIdrefs(context);
177 
178   }
179 
180   public void checkUnresolvedIdrefs(ValidationContext context) throws ValidationException {
181     if (!context.getUnresolvedIdRefs().isEmpty()) {
182       String err = MessageFormat.format(
183           resourceBundle.getString("validator.error.class.descriptor.resolver.null"),
184           new Object[] {context.getUnresolvedIdRefs().toString()});
185       throw new ValidationException(err);
186     }
187   }
188 
189   // TODO: add cleanup life-cycle method to be called from outside
190 
191 }