% File src/library/methods/man/validObject.Rd
% Part of the R package, http://www.R-project.org
% Copyright 1995-2007 R Core Team
% Distributed under GPL 2 or later

\name{validObject}
\alias{validObject}
\alias{getValidity}
\alias{setValidity}
\title{ Test the Validity of an Object }
\description{
  The validity of \code{object} related to its class definition is
  tested.  If the object is valid, \code{TRUE} is returned; otherwise,
  either a vector of strings describing validity failures is returned,
  or an error is generated (according to whether \code{test} is
  \code{TRUE}).  Optionally, all slots in the object can also be validated.

  The function \code{setValidity} sets the validity method of a class
  (but more normally, this method will be supplied as the
  \code{validity} argument to \code{\link{setClass}}).  The method
  should be a function of one object that returns \code{TRUE} or a
  description of the non-validity.
}
\usage{
validObject(object, test = FALSE, complete = FALSE)

setValidity(Class, method, where = topenv(parent.frame()) )

getValidity(ClassDef)
}
\arguments{
  \item{object}{ any object, but not much will happen unless the
    object's class has a formal definition.}
  \item{test}{logical; if \code{TRUE} and validity fails, the
    function returns a vector of strings describing the problems.  If
    \code{test} is \code{FALSE} (the default) validity failure generates
    an error.}
  \item{complete}{logical; if \code{TRUE}, validity methods will be
    applied recursively to any of the slots that have such methods.}
  \item{Class}{the name or class definition of the class whose validity
    method is to be set.}
  \item{ClassDef}{a class definition object, as from
    \code{\link{getClassDef}}.}
  \item{method}{a validity method;  that is, either \code{NULL} or a
    function of one argument (\code{object}).  Like
    \code{validObject}, the function should return \code{TRUE} if the
    object is valid, and one or more descriptive strings if any problems
    are found.  Unlike \code{validObject}, it should never generate an
    error.
  }
  \item{where}{the modified class definition will be stored in this
    environment.}

  Note that validity methods do not have to check validity of
  superclasses: the logic of \code{validObject} ensures these tests are
  done once only.  As a consequence, if one validity method wants to use
  another, it should extract and call the method from the other
  definition of the other class by calling \code{getValidity()}: it
  should \emph{not} call \code{validObject}.
}
\details{
  Validity testing takes place \sQuote{bottom up}: Optionally, if
  \code{complete=TRUE}, the validity of the object's slots, if any, is
  tested.  Then, in all cases, for each of the classes that this class
  extends (the \sQuote{superclasses}), the explicit validity method of
  that class is called, if one exists.  Finally, the validity method of
  \code{object}'s class is called, if there is one.

  Testing generally stops at the first stage of finding an error, except
  that all the slots will be examined even if a slot has failed its
  validity test.

  The standard validity test (with \code{complete=FALSE}) is applied
  when an object is created via \code{\link{new}} with any optional
  arguments (without the extra arguments the result is just the class
  prototype object).

  An attempt is made to fix up the definition of a validity method if
  its argument is not \code{object}.
}
\value{
  \code{validObject} returns \code{TRUE} if the object is valid.
  Otherwise a vector of strings describing problems found, except that
  if \code{test} is \code{FALSE}, validity failure generates an error,
  with the corresponding strings in the error message.
}
\references{
 Chambers, John M. (2008)
 \emph{Software for Data Analysis: Programming with R}
  Springer.  (For the R version.)

 Chambers, John M. (1998)
 \emph{Programming with Data}
 Springer (For the original S4 version.) 
}
\seealso{\code{\link{setClass}};
  class \code{\linkS4class{classRepresentation}}.
}
\examples{
setClass("track",
          representation(x="numeric", y = "numeric"))
t1 <- new("track", x=1:10, y=sort(stats::rnorm(10)))
## A valid "track" object has the same number of x, y values
validTrackObject <- function(object) {
    if(length(object@x) == length(object@y)) TRUE
    else paste("Unequal x,y lengths: ", length(object@x), ", ",
               length(object@y), sep="")
}
## assign the function as the validity method for the class
setValidity("track", validTrackObject)
## t1 should be a valid "track" object
validObject(t1)
## Now we do something bad
t2 <- t1
t2@x <- 1:20
## This should generate an error
\dontrun{try(validObject(t2))}
\dontshow{stopifnot(is(try(validObject(t2)), "try-error"))}

setClass("trackCurve",
         representation("track", smooth = "numeric"))

## all superclass validity methods are used when validObject
## is called from initialize() with arguments, so this fails
\dontrun{trynew("trackCurve", t2)}
\dontshow{stopifnot(is(try(new("trackCurve", t2)), "try-error"))}

setClass("twoTrack", representation(tr1 = "track", tr2 ="track"))

## validity tests are not applied recursively by default,
## so this object is created (invalidly)
tT  <- new("twoTrack", tr2 = t2)

## A stricter test detects the problem
\dontrun{try(validObject(tT, complete = TRUE))}
\dontshow{stopifnot(is(try(validObject(tT, complete = TRUE)), "try-error"))}
}
\keyword{programming}
\keyword{classes}
