public function executeNotifyUpdate() {
		$page_id = $this->m_title->getArticleID();
		if ( ( $page_id == 0 ) || ( $this->m_title->getNamespace() != NS_MAIN ) ) {
			return;
		}
		$sStore = NMStorage::getDatabase();

		$info = $this->getSemanticInfo( $this->m_title );
		// get different
		$tmp_info = array(); // type : category 0, property 2; name; sem action : del 0, modify 1, add 2; val action : del 0, add 1
		foreach ( $this->m_info as $key => $value ) {
			$i = SMWNotifyProcessor::getInfoFromId( $key );
			$updated = false;
			if ( !isset( $info[$key] ) ) {
				if ( $i[type] == 0 ) {
					$tmp_info[$key] = array( 'sem_act' => 0, 'name' => $value[0][name] );
				} else {
					$tmp_info[$key] = array( 'sem_act' => 0, 'name' => $value[0][name], 'del_vals' => array(), 'new_vals' => array() );
					foreach ( $value as $v ) {
						$tmp_info[$key][del_vals][] = array( 'plain' => $v[value]->getWikiValue(), 'html' => $this->getFullLink( $v[value] ) );
					}
				}
			} elseif ( $i[type] == 2 ) {
				$mvalue = $info[$key];
				foreach ( $value as $v1 ) {
					$found = false;
					foreach ( $mvalue as $v2 ) {
						if ( $this->isEqual( $v1, $v2 ) ) {
							$found = true;
							break;
						}
					}
					if ( !$found ) {
						if ( !$updated ) {
							$updated = true;
							$tmp_info[$key] = array( 'sem_act' => 1, 'name' => $value[0][name], 'del_vals' => array(), 'new_vals' => array() );
						}
						$tmp_info[$key][del_vals][] = array( 'plain' => $v1[value]->getWikiValue(), 'html' => $this->getFullLink( $v1[value] ) );
					}
				}
				foreach ( $mvalue as $v1 ) {
					$found = false;
					foreach ( $value as $v2 ) {
						if ( $this->isEqual( $v1, $v2 ) ) {
							$found = true;
							break;
						}
					}
					if ( !$found ) {
						if ( !$updated ) {
							$updated = true;
							$tmp_info[$key] = array( 'sem_act' => 1, 'name' => $value[0][name], 'del_vals' => array(), 'new_vals' => array() );
						}
						$tmp_info[$key][new_vals][] = array( 'plain' => $v1[value]->getWikiValue(), 'html' => $this->getFullLink( $v1[value] ) );
					}
				}
			}
		}
		foreach ( $info as $key => $value ) {
			$i = SMWNotifyProcessor::getInfoFromId( $key );
			if ( !isset( $this->m_info[$key] ) ) {
				if ( $i[type] == 0 ) {
					$tmp_info[$key] = array( 'sem_act' => 2, 'name' => $value[0][name] );
				} else {
					$tmp_info[$key] = array( 'sem_act' => 2, 'name' => $value[0][name], 'del_vals' => array(), 'new_vals' => array() );
					foreach ( $value as $v ) {
						$tmp_info[$key][new_vals][] = array( 'plain' => $v[value]->getWikiValue(), 'html' => $this->getFullLink( $v[value] ) );
					}
				}
			}
		}

		$notifications = $sStore->getMonitoredNotificationsDetail( $page_id );
		// add semantic info to report all NM
		foreach ( $notifications as $user_id => $notifies ) {
			foreach ( $notifies['rep_all'] as $notify_id => $notify_name ) {
				foreach ( array_keys( $tmp_info ) as $key ) {
					$notifications[$user_id]['semantic'][$key][$notify_id] = $notify_name;
				}
			}
		}
		$page_name = $this->m_title->getText() . ' (' . $this->m_title->getFullUrl() . ')';

		$notifyMsgAdded = array();
		foreach ( $notifications as $user_id => $notifies ) {
			if ( !isset( $notifies['semantic'] ) ) continue;
			foreach ( $notifies['semantic'] as $key => $notify ) {
				if ( isset( $tmp_info[$key] ) ) {
					$hint = "";
					if ( !isset( $this->m_userMsgs[$user_id] ) ) {
						$this->m_userMsgs[$user_id] = wfMsg( 'smw_nm_hint_change', $page_name );
						$hint = wfMsg( 'smw_nm_hint_change_html', $this->m_title->getFullUrl(), htmlspecialchars( $this->m_title->getText() ) );
						$this->m_userHtmlNMMsgs[$user_id] .= $hint;
					}

					$this->m_userMsgs[$user_id] .= $this->getNotifyPlain( $tmp_info[$key], $key ) . ' ( NM: ';
					$propHint = $this->getNotifyHtml( $tmp_info[$key], $key );
					$this->m_userHtmlPropMsgs[$user_id] .= $propHint . "<tr><td colspan='5'>" . wfMsg( 'smw_notifyme' ) . ": ";
					$first = true;
					foreach ( $notify as $notify_id => $notify_name ) {
						if ( !$first ) {
							$this->m_userMsgs[$user_id] .= ', ';
							$this->m_userHtmlPropMsgs[$user_id] .= ', ';
						} else {
							$first = false;
						}
						$this->m_userMsgs[$user_id] .= $notify_name;
						$this->m_userHtmlPropMsgs[$user_id] .= '<b>' . htmlspecialchars( $notify_name ) . '</b>';

						if ( !isset( $notifyMsgAdded[$notify_id] ) ) {
							$this->m_notifyHtmlMsgs[$notify_id] .= $hint;
						}
						if ( !isset( $notifyMsgAdded[$notify_id][$key] ) ) {
							$this->m_notifyHtmlPropMsgs[$notify_id] .= $propHint;
							$notifyMsgAdded[$notify_id][$key] = true;
						}

						$this->m_userNMs[$user_id][] = $notify_id;
					}
					$this->m_userMsgs[$user_id] .= ' ).';
					$this->m_userHtmlPropMsgs[$user_id] .= "</td></tr>";
				}
			}
		}
		// get possible subquery
		$this->m_subQueryNotify = array();
		$queries = $sStore->getPossibleQuery( $this->m_info );
		if ( is_array( $queries ) ) {
			foreach ( $queries[1] as $notify_id => $notify ) {
				$this->m_subQueryNotify[$notify_id] = $notify;
			}
		}

		$this->m_info = $info;
	}
	public function getPossibleQuery( $info ) {
		$cnt = count( $info );
		if ( $cnt == 0 ) {
			return null;
		}
		$fname = 'NotifyMe::getPossibleQuery';
		wfProfileIn( $fname );

		$first = true;
		foreach ( $info as $key => $value ) {
			if ( $first ) {
				$first = false;
			} else {
				$cond .= "OR ";
			}
			$i = SMWNotifyProcessor::getInfoFromId( $key );
			$cond .= "(smw_id=$i[attr_id] AND type=$i[type]) ";
		}

		$db = wfGetDB( DB_SLAVE );
		$result = array( 0 => array(), 1 => array() );
		extract( $db->tableNames( 'smw_nm_query', 'smw_nm_relations' ) );
		$res = $db->query( "SELECT q.notify_id, q.name, q.user_id, q.delegate, q.nm_sql, q.nm_hierarchy, c1.subquery FROM (" .
			"SELECT count(*) cnt, notify_id, subquery FROM $smw_nm_relations " .
					"WHERE $cond GROUP BY notify_id, subquery" .
			") c1 INNER JOIN (" .
				"SELECT count(*) cnt, notify_id, subquery FROM $smw_nm_relations " .
					"WHERE type<>1 GROUP BY notify_id, subquery" .
			") c2 ON c1.notify_id=c2.notify_id AND c1.subquery=c2.subquery AND c1.cnt=c2.cnt " .
			"LEFT JOIN $smw_nm_query q ON q.notify_id = c1.notify_id WHERE c1.cnt<=$cnt", $fname );
		if ( $db->numRows( $res ) > 0 ) {
			while ( $row = $db->fetchObject( $res ) ) {
				$ds = explode( ',', $row->delegate );
				$uids = array();
				foreach ( $ds as $delegate ) {
					$u = User::newFromName( trim( $delegate ) );
					if ( $u == null ) continue;
					$id = $u->getId();
					if ( $id > 0 ) {
						$uids[] = $id;
					}
				}
				if ( count( $uids ) == 0 ) {
					$uids[] = $row->user_id;
				}
				$result[$row->subquery > 0 ? 1:0][$row->notify_id] = array( 'user_ids' => $uids, 'name' => $row->name, 'sql' => $row->nm_sql, 'hierarchy' => $row->nm_hierarchy );
			}
		}
		$db->freeResult( $res );
		wfProfileOut( $fname );
		return $result;
	}