public function is_changed($property = null)
	{
		$properties = static::properties();
		$relations = static::relations();
		$property = (array) $property ?: array_merge(array_keys($properties), array_keys($relations));

		foreach ($property as $p)
		{
			if (isset($properties[$p]))
			{
				if (array_key_exists($p, $this->_original))
				{
					if ((array_key_exists('type', $properties[$p]) and $properties[$p]['type'] == 'int') or
						(array_key_exists('data_type', $properties[$p]) and $properties[$p]['data_type'] == 'int'))
					{
						if ($this->{$p} != $this->_original[$p])
						{
							return true;
						}
					}
					elseif ($this->{$p} !== $this->_original[$p])
					{
						return true;
					}
				}
				else
				{
					if (array_key_exists($p, $this->_data))
					{
						return true;
					}
				}
			}
			elseif (isset($relations[$p]))
			{
				if ($relations[$p]->singular)
				{
					if (empty($this->_original_relations[$p]) !== empty($this->_data_relations[$p])
						or ( ! empty($this->_original_relations[$p])
							and $this->_original_relations[$p] !== $this->_data_relations[$p]->implode_pk($this->{$p})))
					{
						return true;
					}
				}
				else
				{
					if (empty($this->_original_relations[$p]))
					{
						if ( ! empty($this->_data_relations[$p]))
						{
							return true;
						}
						continue;
					}

					$orig_rels = $this->_original_relations[$p];
					foreach ($this->{$p} as $rk => $r)
					{
						if ( ! in_array($r->implode_pk($r), $orig_rels))
						{
							return true;
						}
						unset($orig_rels[array_search($rk, $orig_rels)]);
					}
					if ( ! empty($orig_rels))
					{
						return true;
					}
				}
			}
			else
			{
				throw new \OutOfBoundsException('Unknown property or relation: '.$p);
			}
		}

		return false;
	}