## ==========================================================================
## Most objects in flowCore have a name or identifier, most prominently
## filters, flowFrames and flowSets. Please note that these identifiers
## don't necessarily have to be unique. Identifier methods provide a unified
## accessor to these IDs.
## ==========================================================================

#' Retrieve the GUID of flowCore objects
#' 
#' 
#' Retrieve the GUID (globally unique identifier) of a \code{\link{flowFrame}}
#' that was generated by the cytometer or the identifier of a
#' \code{\linkS4class{filter}} or \code{\linkS4class{filterResult}} given by
#' the analyst.
#' 
#' 
#' GUID or Globally Unique Identifier is a pseudo-random number used in
#' software applications. While each generated GUID is not guaranteed to be
#' unique, the total number of unique keys (2\^128) is so large that the
#' probability of the same number being generated twice is very small.
#' 
#' Note that if no GUID has been recorded along with the FCS file, the name of
#' the file is returned.
#' 
#' @name identifier-methods
#' @aliases identifier identifier-methods identifier,filter-method
#' identifier,transform-method identifier,filterReference-method identifier,NULL-method
#' identifier,filterResult-method identifier,flowFrame-method identifier<-
#' identifier<-,flowFrame-method identifier<-,flowFrame,ANY-method
#' @docType methods
#' @usage identifier(object)
#' @param object Object of class \code{\linkS4class{flowFrame}},
#' \code{\linkS4class{filter}} or \code{\linkS4class{filterResult}}.
#' @return
#' 
#' Character vector representing the GUID or the name of the file.
#' @section Methods:
#' 
#' \describe{
#' 
#' \item{identifier(object = "filter")}{Return identifier of a \code{\linkS4class{filter}}
#' object.}
#' 
#' \item{identifier(object = "filterReference")}{Return identifier of a
#' \code{\linkS4class{filterReference}} object.}
#' 
#' \item{identifier(object = "filterResult")}{Return identifier of a
#' \code{\linkS4class{filterResult}} object.}
#' 
#' \item{identifier(object = "transform")}{Return identifier of a
#' \code{\linkS4class{transform}} object.}
#' 
#' \item{identifier(object = "flowFrame")}{Return GUID from the \code{description} slot of
#' a \code{\linkS4class{flowFrame}} object or, alternatively, the name of the
#' input \acronym{FCS} file in case none can be found. For
#' \code{\linkS4class{flowFrame}} objects there also exists a replacement
#' method.}
#' 
#' }
#' @author N. LeMeur
#' @keywords methods
#' @examples
#' 
#'  samp <- read.FCS(system.file("extdata","0877408774.B08", package="flowCore"))
#'  identifier(samp)
#' 
#' 
## ==========================================================================
## Retrieve or set identifier of a flowFrame (normally generated by the
## cytometer and normally unique). There is a hierarchy of places in which
## to look for it: First, the "GUID" keyword, then the "FILENAME" and "$FIL"
## keywords, the fallback is to use the id "aninymous". Replacement will
## always fill the "GUID" keyword.
## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#' @export
setMethod("identifier",
          signature=signature(object="flowFrame"),
          definition=function(object)
      {
          oid <- keyword(object,"GUID")[[1]]
          if(is.null(oid) || is.na(oid))
              oid <- as.vector(keyword(object,"FILENAME")[[1]])
          if(is.null(oid) || is.na(oid))
              oid <- as.vector(keyword(object,"$FIL")[[1]])
          if(is.null(oid) || is.na(oid))
              "anonymous"
          else
              as.vector(oid)
      })

setReplaceMethod("identifier",
                 signature=signature(object="flowFrame",
                                     value="ANY"),
                 definition=function(object, value)
             {
                 object@description[["ORIGINALGUID"]] <- object@description[["GUID"]]
                 object@description[["GUID"]] <- value
#                 tmp <- object@exprs
                 return(object)
             })



## ==========================================================================
## For compensation objects we can get the ID directly from the
## compensationId slot
## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#' @export
setMethod("identifier",
          signature=signature(object="compensation"),
          definition=function(object) object@compensationId)

setReplaceMethod("identifier",
                 signature=signature("compensation","character"),
                 definition=function(object,value)
             {
                 object@compensationId <- value
                 object
             })


## ==========================================================================
## For filterList objects we can get the ID directly from the filterId slot
## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#' @export
setMethod("identifier",
          signature=signature("filterList"),
          definition=function(object) object@filterId)

setReplaceMethod("identifier",
                 signature=signature("filterList","character"),
                 definition=function(object,value)
             {
                 object@filterId <- value
                 object
             })




## ==========================================================================
## For filterReferences we first resolve the reference to a concrete filter
## and use the next available method.
## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#' @export
setMethod("identifier",
          signature=signature(object="filterReference"),
          definition=function(object)
      {
          if(exists(object@name, envir=object@env))
              identifier(as(object, "concreteFilter"))
          else
              object@name
      })



## ==========================================================================
## For all filter objects we can get the ID directly from the filterId slot.
## The setter simply replaces this value.
## --------------------------------------------------------------------------
#' @export
setMethod("identifier",
          signature=signature(object="filter"),
          definition=function(object) object@filterId)

setReplaceMethod("identifier",
                 signature=signature("filter","character"),
                 definition=function(object,value)
             {
                 object@filterId <- value
                 object
             })



## ==========================================================================
## We need this to avoid type-checking
## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#' @export
setMethod("identifier",
          signature=signature(object="NULL"),
          definition=function(object) NULL)


## ==========================================================================
## Transform objects have an ID slot
## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#' @export
setMethod("identifier",
          signature=signature(object="transform"),
          definition=function(object) object@transformationId)



## ==========================================================================
## normalize objects have a normalizationId slot
## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#' @export
setMethod("identifier",
          signature=signature(object="normalization"),
          definition=function(object) object@normalizationId)

setReplaceMethod("identifier",
                 signature=signature("normalization","character"),
                 definition=function(object,value)
             {
                 object@normalizationId <- value
                 object
             })



## ==========================================================================
## transformList objects have a transformationId slot
## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#' @export
setMethod("identifier",
          signature=signature(object="transformList"),
          definition=function(object) object@transformationId)

setReplaceMethod("identifier",
                 signature=signature("transformList","character"),
                 definition=function(object,value)
             {
                 object@transformationId <- value
                 object
             })
