public function __construct(array $params, $mainEntity)
 {
     $this->at = RestUrlParams::parseTimestamp(RestUrlParams::extractValue($params, RestUrlParams::AT));
     if ($this->at == RestUrlParams::ALL_TIMES) {
         $this->at = self::ALL_TIMES;
     }
     $this->published = RestUrlParams::parseBoolean(RestUrlParams::extractValue($params, RestUrlParams::PUBLISHED));
     $this->queryParamsMap = array();
     $this->scopeMap = array();
     if ($mainEntity != NULL) {
         foreach ($params as $paramName => $paramValue) {
             // Parameters can be specified with or without entity-prefix, e.g. 'entity/property=value' or just
             // 'property=value'. Check if an entity-prefix is provided.
             $entityName = NULL;
             $propertyName = NULL;
             $paramNameParts = explode(RestUrlParams::ENTITY_SEPARATOR, $paramName);
             if (count($paramNameParts) == 1) {
                 // It's like 'property=value'.
                 $entityName = $mainEntity->getName();
                 $propertyName = $paramName;
             } else {
                 if (count($paramNameParts) == 2) {
                     // It's like 'entity/property=value'.
                     $entityName = $paramNameParts[0];
                     $propertyName = $paramNameParts[1];
                 } else {
                     throw new Exception("Illegal query parameter '{$paramName}'.");
                 }
             }
             // If it's a scope parameter...
             if (strcasecmp($propertyName, RestUrlParams::SCOPE) == 0) {
                 // ...then parse it.
                 $this->scopeMap[$entityName] = Scope::parseValue($paramValue);
             } else {
                 // ...else add the value to the map at the correct entity-entry.
                 if (!array_key_exists($entityName, $this->queryParamsMap)) {
                     $this->queryParamsMap[$entityName] = array();
                 }
                 // If $paramName is 'id'...
                 if (strcasecmp($propertyName, RestUrlParams::ID) == 0) {
                     // ...then check if this is allowed for the given entity...
                     if (!$mainEntity->isObjectEntity()) {
                         throw new Exception("Cannot fetch entity '" . $mainEntity->getName() . "' by id.");
                     }
                     // ...and apply the correct property name and value.
                     $propertyName = $mainEntity->getObjectIdColumnName();
                     $paramValue = explode(RestUrlParams::ID_SEPARATOR, $paramValue);
                 }
                 $this->queryParamsMap[$entityName][$propertyName] = $paramValue;
             }
         }
     }
 }
 /**
  * Fetches a single object of the given entity and id, applying the query parameters to limit the resultset.
  * The fetched data is added as the root element of the given XML document.
  * 
  * @param Entity $entity
  * @param type $id
  * @param array $params
  * @params Scope $scope
  * @params DOMDocument $domDoc
  * @params $skipBinaries
  * @return DOMElement with requested data or NULL if not found
  */
 public function getObjectTree(Entity $entity, $id, array $params, DOMDocument $domDoc)
 {
     $scope = Scope::parseValue(RestUrlParams::extractValue($params, RestUrlParams::SCOPE));
     $skipBinaries = RestUrlParams::parseBoolean(RestUrlParams::extractValue($params, RestUrlParams::SKIP_BINARIES));
     $queryContext = new QueryContext($params, $entity);
     $xmlElementsWithState = array();
     $this->fetchObjects($entity, $id, $queryContext, $scope, $skipBinaries, $domDoc, $domDoc, $xmlElementsWithState);
     $xmlResult = $domDoc->documentElement;
     if ($xmlResult != NULL) {
         $this->setLifecycleTimestamps($xmlElementsWithState);
         $this->setTimestamp($xmlResult, XmlConstants::AT, $queryContext->getParameterAt());
     }
     return $xmlResult;
 }