public function assertDevice(WURFL_CustomDevice $device, $response = null)
 {
     if ($this->operator != self::OPERATOR_EQUAL && $this->operator != self::OPERATOR_EQUAL_LOOSE) {
         if (self::compare($this->expected_id, $device->id, $this->operator)) {
             $this->details = "Logical match ({$this->operator}) succeeded";
             return true;
         } else {
             $this->details = "Logical match failed: '{$this->expected_id} {$this->operator} {$device->id}'";
             return false;
         }
     }
     if ($this->expected_id == $device->id) {
         $this->details = 'Exact match succeeded';
         return true;
     } else {
         if ($this->exact_match === true) {
             $this->details = "Exact match required; expected:{$this->expected_id}, got:{$device->id}";
             return false;
         }
     }
     $target_root_device = $device->getActualDeviceRootAncestor();
     // No actual device root means no possible match
     if (!$target_root_device) {
         $this->details = "Exact match not required, but detected device ID has no actual_device_root ancestor; expected:{$this->expected_id}, got:{$device->id}";
         return false;
     }
     // Perform loose comparison
     // Get reference device
     try {
         $reference_device = $this->wurflManager->getDevice($this->expected_id);
         $reference_root_device = $reference_device->getActualDeviceRootAncestor();
     } catch (Exception $e) {
         throw new Exception("The expected WURFL ID ({$this->expected_id}) is not in the loaded WURFL Data!  Detected as: {$device->id}", null, $e);
     }
     if ($reference_root_device->id != $target_root_device->id) {
         $this->details = "Loose match required; expected:{$this->expected_id}, got:{$device->id}";
         return false;
     }
     return true;
 }