WebObjects 5.4.2

com.webobjects.foundation
Interface NSValidation

All Known Subinterfaces:
EOEnterpriseObject, EOValidation
All Known Implementing Classes:
BASConfirmPage, BASDefaultHeader, BASEditRelationshipPage, BASErrorPage, BASHead, BASInspectPage, BASListPage, BASMasterDetailPage, BASPlainListPage, BASQueryAllEntitiesPage, BASQueryPage, BASSideHeader, BASSidePageWrapper, D2WActions, D2WCollapsibleComponentContent, D2WCompactInspectComponent, D2WComponent, D2WConfirmPage, D2WCustomComponent, D2WCustomQueryComponent, D2WDefaultCustomComponent, D2WDisplayBoolean, D2WDisplayDate, D2WDisplayHyperlink, D2WDisplayImage, D2WDisplayImageFromPath, D2WDisplayLargeString, D2WDisplayMailTo, D2WDisplayNumber, D2WDisplayString, D2WDisplayStyledDate, D2WDisplayStyledNumber, D2WDisplayStyledString, D2WDisplayThresholdColoredNumber, D2WDisplayToMany, D2WDisplayToMany2, D2WDisplayToManyBrowser, D2WDisplayToManyFault, D2WDisplayToManyTable, D2WDisplayToOne, D2WDisplayToOneFault, D2WEdit, D2WEditBoolean, D2WEditDate, D2WEditLargeString, D2WEditNumber, D2WEditRelationshipPage, D2WEditString, D2WEditToManyFault, D2WEditToManyRelationship, D2WEditToOneFault, D2WEditToOneRelationship, D2WEditUneditable, D2WEmbeddedComponent, D2WEmptyWrapper, D2WErrorPage, D2WGenerationWrapper, D2WHead, D2WInspect, D2WInspectPage, D2WKeyPathContainer, D2WList, D2WListPage, D2WMasterDetailPage, D2WPage, D2WPlainListPage, D2WQuery, D2WQueryAllEntitiesPage, D2WQueryAnyField, D2WQueryBoolean, D2WQueryDateOperator, D2WQueryDateRange, D2WQueryNumberOperator, D2WQueryNumberRange, D2WQueryPage, D2WQueryRangeComponent, D2WQueryRelationship, D2WQueryStringComponent, D2WQueryStringOperator, D2WQueryToManyField, D2WQueryToManyRelationship, D2WQueryToOneField, D2WQueryToOneRelationship, D2WQueryUnavailable, D2WRemoteControl, D2WSelect, D2WStandAloneWebAssistantFrame, D2WStatelessComponent, D2WSwitchComponent, D2WTabInspectPage, D2WWebAssistantFrame, D2WWebAssistantPage, DarwinShadow, DefaultHeader, EditComponent, EditRelationship, EOCustomObject, EOGenericRecord, JSAlertPanel, JSComponent, JSConfirmPanel, JSImageFlyover, JSModalWindow, JSTextFlyover, JSValidatedField, NEUCompactInspectComponent, NEUConfirmPage, NEUEditRelationshipPage, NEUErrorPage, NEUHeader, NEUInspectPage, NEUListPage, NEUMasterDetailPage, NEUPlainListPage, NEUQueryAllPage, NEUQueryPage, NEUTabInspectPage, QueryComponent, QueryOperatorComponent, WOAdminAction, WOAggregateEventRow, WOAnyField, WOAssociationEventRow, WOBatchNavigationBar, WOBeginTransactionOperation, WOCheckboxMatrix, WOCollapsibleComponentContent, WOCommitTransactionOperation, WOCompletionBar, WOComponent, WODeleteOperation, WODictionaryRepetition, WODirectAction, WOEventDisplay, WOEventDisplayPage, WOEventPage, WOEventRow, WOEventSetup, WOEventSetupPage, WOExceptionPage, WOFetchSpecSearchOperation, WOIFrame, WOInsertOperation, WOJavaClientApplet, WOJavaClientComponent, WOJavaClientJNLP, WOKeyValueConditional, WOLCompactInspectComponent, WOLConfirmPage, WOLEditRelationshipPage, WOLErrorPage, WOLHeader, WOLInspectPage, WOLListPage, WOLMasterDetailPage, WOLongResponsePage, WOLPlainListPage, WOLQueryAllPage, WOLQueryPage, WOLTabInspectPage, WOMetaRefresh, WOOperation, WOOperationWSDLTemplate, WOPageRestorationError, WOProjectBuilderAction, WORadioButtonMatrix, WORedirect, WORollbackTransactionOperation, WOSearchOperation, WOSessionCreationError, WOSessionRestorationError, WOSimpleArrayDisplay, WOSimpleArrayDisplay2, WOSortOrder, WOSortOrderManyKey, WOStats, WOStatsPage, WOTable, WOTableString, WOTabPanel, WOThresholdColoredNumber, WOToManyRelationship, WOToOneRelationship, WOUpdateOperation, WOWSDLGeneration, WXAccessControl, WXBar, WXOutlineControl, WXOutlineEntry, WXOutlineRepetition, WXSortOrder

public interface NSValidation

The NSValidation interface defines a validation mechanism in which the properties of an object are validated indirectly by name (or key), rather than directly through invocation of an specific validation method. Thus, all of an object's properties can be validated in a consistent manner. The validateValueForKey method confirms that a value is legal for a particular property, and validateTakeValueForKeyPath performs the validation and assigns the value if it's legal and different from the current value.

The NSValidation interface contains two inner classes, NSValidation.DefaultImplementation and NSValidation.Utility. The former provides a default implementation of the interface, making it easy to implement custom classes. The latter is a convenience class that allows you to access the properties of NSValidation objects and non-NSValidation objects using the same code.

NSValidation

Default Implementation

The methods in the NSValidation.DefaultImplementation class are just like the methods defined by the NSValidation interface, except they are static methods and they take an extra argument -- the object on which the default implementation should operate.

For example, suppose you want to implement an Employee class that implements NSValidation using NSValidation.DefaultImplementation. Employee's validateValueForKey method would then look like this:

 <blockquote>
 public Object validateValueForKey(Object value, String key) {
 return NSValidation.DefaultImplementation.validateValueForKey(this,
 value, key);
 }
 </blockquote>
 

The NSValidation.DefaultImplementation methods search for property- specific methods of the form validateKey and invoke them if they exist. Thus an NSValidation class should implement a validate method for each property that has associated validation logic. For example, a validateAge method could check that the value a user enters as an age is within acceptable limits and throw an NSValidation.ValidationException if it finds an unacceptable value.

Because custom validation logic is implements in the validateKey methods, you rarely need to implement the NSValidation methods from scratch. Rather, the default implementation provided by NSValidation.DefaultImplementation is generally sufficient.

Note:The default implementations have significant performance optimizations. To benefit from them, implement NSValidation on a custom class as shown above by using the methods in NSValidation.DefaultImplementation, or if the class inherits from a WebObjects class that implements NSValidation, don't override the inherited implementation. Using a custom implementation incurs significant performance penalties.

Utility

Recall that the NSValidation.Utility class is a convenience class that allows you to access the properties of NSValidation objects and non-NSValidation objects using the same code.

Utility's methods are similar to DefaultImplementation's methods in that they are static methods and they take an extra argument -- the object on which the method should operate. However, Utility's methods simply check to see if the object on which they operate is an NSValidation object and invoke the corresponding NSValidation method on the object if it is. Otherwise, they invoke the corresponding DefaultImplementation method, passing the object on which to operate.

For example, suppose that you want to access an object with the NSValidation API but doesn't know if the object is an NSValidation object. To do so, you simply use the corresponding Utility API, as in the following line of code:

 <blockquote>
 theValue = NSValidation.Utility.validateValueForKey(object, value, key);
 </blockquote>
 

The above line of code is simply a short-cut for the following:

 <blockquote>
 if (object instanceof NSValidation) {
 theValue = ((NSValidation)object).validateValueForKey(key);
 } else {
 theValue = validateValueForKey.DefaultImplementation.validateValueForKey(
 object, value, key);
 }
 </blockquote>
 

Writing validateKey Methods

To implement validation logic in an NSValidation class, a validateKey method is created for each property needing validation. The default implementations of NSValidation's methods look for these validateKey methods and use them to perform the actual validation.

A class's validateKey methods should have the following form:

 <blockquote>
 public Object validateKey(Object aValue) throws
 NSValidation.ValidationException
 </blockquote>
 

The implementation should confirm that the value passed in is legal and throw an NSValidation.ValidationException if it's not. It should also coerce the argument to the proper type, if necessary. Note that a validateKey method's argument type is Object, and not specifically the class of the corresponding property (String, Integer, or NSTimestamp, for example). Thus, a validateKey method needs to check the type of the argument and convert it to a different type if necessary. The return type of a validateKey method doesn't have to be Object. In fact, it's a good idea to specify the class of the value the method returns, which is generally the class of the corresponding property. The argument type, on the other hand, should generally be Object.

The following validateAge method is an example that validates values for a property named age that's stored as an Integer. The method handles arguments of type String and Number. If the argument is an instance of any other class, the method throws a NSValidation.ValidationException.

 <blockquote>
 public Number validateAge(Object aValue) throws
 NSValidation.ValidationException
 {
     Integer numberValue;
     int age;
     if (aValue instanceof String) {
     // Convert the String to an Integer.
        try {
          numberValue = new Integer((String)aValue);
        } catch (NumberFormatException numberFormatException) {
           throw new NSValidation.ValidationException("Validation exception: Unable to convert the String " + aValue + " to an Integer");
        }
      } else if (aValue instanceof Number) {
         numberValue = new Integer(((Number)aValue).intValue());
      } else {
          throw new NSValidation.ValidationException("Validation exception: Unable to convert the Object " + aValue + " to an Integer");
      }
   age = numberValue.intValue();
   if (age < 16) {
      throw new NSValidation.ValidationException("Age of " + age + " is below minimum.", this, "age");
   }
  return numberValue;
 }
 </blockquote>
 

The validateAge method checks the argument's class. If the argument is a String or Number, it creates an Integer from the argument and validates it. If the Integer fails the validation test (if the value is less than 16), the method throws an NSValidation.ValidationException inserting the NSValidation object and the key into the exception's userInfo dictionary by providing them to the constructor. On the other hand, if the Integer passes the validation test, the method returns the Integer.

The code that invokes the validation process is expected to use the value returned from the validateKey method instead of the original value it provided. Thus, a validateKey method has an opportunity to coerce a value into a type it prefers. As another example of coercion, a validateKey method can return null. A method might do this, for example, if it is invoked with the empty string as the argument.

The validateKey Argument Type

The argument type of a validateKey method doesn't have to be specifically Object; it can be Object or any subclass. However, generally Object is the most appropriate type for a validateKey method's argument (the one exception is described later in this section). As explained in "Writing validateKey Methods", a validateKey method should be able to handle any reasonable argument type. You can type the argument to the common superclass of all reasonable arguments, but this is frequently Object.

You should not overload a validateKey method for a particular property, creating different validateKey methods for each argument type. Instead you should create one version of the validateKey method for the property that takes Object as its argument (or at least a superclass of all the possible argument types). The method's implementation should test the argument's type and coerce it appropriately.

There's one situation in which the argument type should be more specific than Object. If the property corresponding to the validateKey method is a to-one relationship to an enterprise object, the argument's type should be EOEnterpriseObject.

See Also:
NSValidation.validateValueForKey(java.lang.Object, java.lang.String), NSValidation.validateTakeValueForKeyPath(java.lang.Object, java.lang.String), NSValidation.DefaultImplementation, NSValidation.Utility, NSKeyValueCoding

Nested Class Summary
static class NSValidation.DefaultImplementation
          The methods in the NSValidation.DefaultImplementation class are just like the methods defined by the NSValidation interface, except they are static methods and they take an additional argument, which is the object on which the default implementation should operate.
static class NSValidation.Utility
          This class is a convenience that allows you to access the properties of NSValidation objects and non-NSValidation objects using the same code.
static class NSValidation.ValidationException
          Instances of the NSValidation.ValidationException class are created and thrown when an error condition is encountered during the validation of an object that implements NSValidation.
 
Method Summary
 Object validateTakeValueForKeyPath(Object value, String keyPath)
          Confirms that value is legal for the object's property named by keyPath and then assigns it to the property.
 Object validateValueForKey(Object value, String key)
          Confirms that value is legal for the object's property named by key.
 

Method Detail

validateValueForKey

Object validateValueForKey(Object value,
                           String key)
                           throws NSValidation.ValidationException
Confirms that value is legal for the object's property named by key.

It returns the validated value if it's legal, or throws an NSValidation.ValidationException. Custom implementations may return something other than value, including a coerced value or a substitution.

The default implementation of this method (provided by NSValidation.DefaultImplementation) checks for a method of the form validateKey (for example, validateBudget for a key of "budget"). If such a method exists, it invokes it and returns the result. Thus, NSValidation objects can implement individual validateKey methods to check limits, test for nonsense values, and coerce values (convert strings to dates or numbers, for example). If no such method exists, it simply returns value

Parameters:
value - the value to be examined for validity
key - the key for the property corresponding to value
Returns:
either value, value coerced to a different type or precision, or an entirely different substitution
Throws:
NSValidation.ValidationException - value is invalid
See Also:
NSKeyValueCoding.valueForKey(java.lang.String), NSValidation.DefaultImplementation

validateTakeValueForKeyPath

Object validateTakeValueForKeyPath(Object value,
                                   String keyPath)
                                   throws NSValidation.ValidationException
Confirms that value is legal for the object's property named by keyPath and then assigns it to the property.

If value is valid, this method then assigns a new value to the property. The new value may be different than value if a custom validation method performed any coercions or substitutions. Finally, this method returns the Object actually assigned to the property. By default, this is value If value is an invalid value for this property, this method throws an NSValidation.ValidationException

A keyPath has the form relationship.property (with one or more relationships); for example "movieRole.roleName" or "movieRole.talent.lastName".

The default implementation of this method (provided by NSValidation.DefaultImplementation) gets the destination object for each relationship using valueForKey, and sends the final object a validateValueForKey message with value and property.

Parameters:
value - the value to be examined for validity, and then assigned to the property at keyPath
keyPath - the key path describing the property to operate upon
Returns:
either value, value coerced to a different type or precision, or an entirely different substitution
Throws:
NSValidation.ValidationException - if value is invalid
See Also:
NSKeyValueCoding.takeValueForKey(java.lang.Object, java.lang.String), NSKeyValueCoding.valueForKey(java.lang.String), NSValidation.validateValueForKey(java.lang.Object, java.lang.String), NSValidation.DefaultImplementation

Last updated June 2008

Copyright © 2000-2008 Apple Inc.