diff --git a/apps/federatedfilesharing/appinfo/app.php b/apps/federatedfilesharing/appinfo/app.php
index f54c47b7829ee7b0984c01661f18675380c92396..7f4e46019777a3a47e3dc588655e37dd767e88e8 100644
--- a/apps/federatedfilesharing/appinfo/app.php
+++ b/apps/federatedfilesharing/appinfo/app.php
@@ -32,7 +32,8 @@ $app->registerSettings();
 $manager = \OC::$server->getNotificationManager();
 $manager->registerNotifier(function() {
 	return new Notifier(
-		\OC::$server->getL10NFactory()
+		\OC::$server->getL10NFactory(),
+		\OC::$server->getContactsManager()
 	);
 }, function() use ($l) {
 	return [
diff --git a/apps/federatedfilesharing/lib/Notifier.php b/apps/federatedfilesharing/lib/Notifier.php
index 62816ee929b7eecdec062e1b04c4ea6589605b57..2cbbea2da427dcc8506dc31c97d21374bea18daa 100644
--- a/apps/federatedfilesharing/lib/Notifier.php
+++ b/apps/federatedfilesharing/lib/Notifier.php
@@ -24,18 +24,28 @@
 namespace OCA\FederatedFileSharing;
 
 
+use OC\HintException;
+use OC\Share\Helper;
+use OCP\Contacts\IManager;
+use OCP\L10N\IFactory;
 use OCP\Notification\INotification;
 use OCP\Notification\INotifier;
 
 class Notifier implements INotifier {
-	/** @var \OCP\L10N\IFactory */
+	/** @var IFactory */
 	protected $factory;
+	/** @var IManager */
+	protected $contactsManager;
+	/** @var array */
+	protected $federatedContacts;
 
 	/**
-	 * @param \OCP\L10N\IFactory $factory
+	 * @param IFactory $factory
+	 * @param IManager $contactsManager
 	 */
-	public function __construct(\OCP\L10N\IFactory $factory) {
+	public function __construct(IFactory $factory, IManager $contactsManager) {
 		$this->factory = $factory;
+		$this->contactsManager = $contactsManager;
 	}
 
 	/**
@@ -58,11 +68,34 @@ class Notifier implements INotifier {
 				$params = $notification->getSubjectParameters();
 				if ($params[0] !== $params[1] && $params[1] !== null) {
 					$notification->setParsedSubject(
-						(string) $l->t('You received "/%3$s" as a remote share from %1$s (on behalf of %2$s)', $params)
+						$l->t('You received "%3$s" as a remote share from %1$s (on behalf of %2$s)', $params)
+					);
+					$notification->setRichSubject(
+						$l->t('You received {share} as a remote share from {user} (on behalf of {behalf})'),
+						[
+							'share' => [
+								'type' => 'pending-federated-share',
+								'id' => $notification->getObjectId(),
+								'name' => $params[2],
+							],
+							'user' => $this->createRemoteUser($params[0]),
+							'behalf' => $this->createRemoteUser($params[1]),
+						]
 					);
 				} else {
 					$notification->setParsedSubject(
-						(string)$l->t('You received "/%3$s" as a remote share from %1$s', $params)
+						$l->t('You received "%3$s" as a remote share from %1$s', $params)
+					);
+					$notification->setRichSubject(
+						$l->t('You received {share} as a remote share from {user}'),
+						[
+							'share' => [
+								'type' => 'pending-federated-share',
+								'id' => $notification->getObjectId(),
+								'name' => $params[2],
+							],
+							'user' => $this->createRemoteUser($params[0]),
+						]
 					);
 				}
 
@@ -92,4 +125,93 @@ class Notifier implements INotifier {
 				throw new \InvalidArgumentException();
 		}
 	}
+
+	/**
+	 * @param string $cloudId
+	 * @return array
+	 */
+	protected function createRemoteUser($cloudId) {
+		$displayName = $cloudId;
+		try {
+			list($user, $server) = Helper::splitUserRemote($cloudId);
+			$displayName = $this->getDisplayName($user, $server);
+		} catch (HintException $e) {
+			$user = $cloudId;
+			$server = '';
+		}
+
+		return [
+			'type' => 'user',
+			'id' => $user,
+			'name' => $displayName,
+			'server' => $server,
+		];
+	}
+
+	/**
+	 * Try to find the user in the contacts
+	 *
+	 * @param string $user
+	 * @param string $server
+	 * @return string
+	 * @throws \OutOfBoundsException when there is no contact for the id
+	 */
+	protected function getDisplayName($user, $server) {
+		$server = strtolower(rtrim($server, '/'));
+
+		if (strpos($server, 'http://') === 0) {
+			$server = substr($server, strlen('http://'));
+		} else if (strpos($server, 'https://') === 0) {
+			$server = substr($server, strlen('https://'));
+		}
+
+		try {
+			return $this->getDisplayNameFromContact($user . '@' . $server);
+		} catch (\OutOfBoundsException $e) {
+		}
+
+		try {
+			$this->getDisplayNameFromContact($user . '@http://' . $server);
+		} catch (\OutOfBoundsException $e) {
+		}
+
+		try {
+			$this->getDisplayNameFromContact($user . '@https://' . $server);
+		} catch (\OutOfBoundsException $e) {
+		}
+
+		return $user . '@' . $server;
+	}
+
+	/**
+	 * Try to find the user in the contacts
+	 *
+	 * @param string $federatedCloudId
+	 * @return string
+	 * @throws \OutOfBoundsException when there is no contact for the id
+	 */
+	protected function getDisplayNameFromContact($federatedCloudId) {
+		if (isset($this->federatedContacts[$federatedCloudId])) {
+			if ($this->federatedContacts[$federatedCloudId] !== '') {
+				return $this->federatedContacts[$federatedCloudId];
+			} else {
+				throw new \OutOfBoundsException('No contact found for federated cloud id');
+			}
+		}
+
+		$addressBookEntries = $this->contactsManager->search($federatedCloudId, ['CLOUD']);
+		foreach ($addressBookEntries as $entry) {
+			if (isset($entry['CLOUD'])) {
+				foreach ($entry['CLOUD'] as $cloudID) {
+					if ($cloudID === $federatedCloudId) {
+						$this->federatedContacts[$federatedCloudId] = $entry['FN'];
+						return $entry['FN'];
+					}
+				}
+			}
+		}
+
+		$this->federatedContacts[$federatedCloudId] = '';
+		throw new \OutOfBoundsException('No contact found for federated cloud id');
+	}
 }
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 1332a570a279dc276a9654276c1c3593ecb7f95a..532a6f39848ef3e080cdd177a1687bb6710e8e8a 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -200,6 +200,8 @@ return array(
     'OCP\\PreConditionNotMetException' => $baseDir . '/lib/public/PreConditionNotMetException.php',
     'OCP\\Preview\\IProvider' => $baseDir . '/lib/public/Preview/IProvider.php',
     'OCP\\Response' => $baseDir . '/lib/public/Response.php',
+    'OCP\\RichObjectStrings\\IValidator' => $baseDir . '/lib/public/RichObjectStrings/IValidator.php',
+    'OCP\\RichObjectStrings\\InvalidObjectExeption' => $baseDir . '/lib/public/RichObjectStrings/InvalidObjectExeption.php',
     'OCP\\Route\\IRoute' => $baseDir . '/lib/public/Route/IRoute.php',
     'OCP\\Route\\IRouter' => $baseDir . '/lib/public/Route/IRouter.php',
     'OCP\\SabrePluginEvent' => $baseDir . '/lib/public/SabrePluginEvent.php',
@@ -663,6 +665,7 @@ return array(
     'OC\\Repair\\SqliteAutoincrement' => $baseDir . '/lib/private/Repair/SqliteAutoincrement.php',
     'OC\\Repair\\UpdateCertificateStore' => $baseDir . '/lib/private/Repair/UpdateCertificateStore.php',
     'OC\\Repair\\UpdateOutdatedOcsIds' => $baseDir . '/lib/private/Repair/UpdateOutdatedOcsIds.php',
+    'OC\\RichObjectStrings\\Validator' => $baseDir . '/lib/private/RichObjectStrings/Validator.php',
     'OC\\Route\\CachingRouter' => $baseDir . '/lib/private/Route/CachingRouter.php',
     'OC\\Route\\Route' => $baseDir . '/lib/private/Route/Route.php',
     'OC\\Route\\Router' => $baseDir . '/lib/private/Route/Router.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index c9bdc5305fead13c8c7ac2476aeef7c8614dbc54..c0a3e9b50c662b58a5f0b4383081a40b5f13fdb5 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -230,6 +230,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
         'OCP\\PreConditionNotMetException' => __DIR__ . '/../../..' . '/lib/public/PreConditionNotMetException.php',
         'OCP\\Preview\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Preview/IProvider.php',
         'OCP\\Response' => __DIR__ . '/../../..' . '/lib/public/Response.php',
+        'OCP\\RichObjectStrings\\IValidator' => __DIR__ . '/../../..' . '/lib/public/RichObjectStrings/IValidator.php',
+        'OCP\\RichObjectStrings\\InvalidObjectExeption' => __DIR__ . '/../../..' . '/lib/public/RichObjectStrings/InvalidObjectExeption.php',
         'OCP\\Route\\IRoute' => __DIR__ . '/../../..' . '/lib/public/Route/IRoute.php',
         'OCP\\Route\\IRouter' => __DIR__ . '/../../..' . '/lib/public/Route/IRouter.php',
         'OCP\\SabrePluginEvent' => __DIR__ . '/../../..' . '/lib/public/SabrePluginEvent.php',
@@ -693,6 +695,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
         'OC\\Repair\\SqliteAutoincrement' => __DIR__ . '/../../..' . '/lib/private/Repair/SqliteAutoincrement.php',
         'OC\\Repair\\UpdateCertificateStore' => __DIR__ . '/../../..' . '/lib/private/Repair/UpdateCertificateStore.php',
         'OC\\Repair\\UpdateOutdatedOcsIds' => __DIR__ . '/../../..' . '/lib/private/Repair/UpdateOutdatedOcsIds.php',
+        'OC\\RichObjectStrings\\Validator' => __DIR__ . '/../../..' . '/lib/private/RichObjectStrings/Validator.php',
         'OC\\Route\\CachingRouter' => __DIR__ . '/../../..' . '/lib/private/Route/CachingRouter.php',
         'OC\\Route\\Route' => __DIR__ . '/../../..' . '/lib/private/Route/Route.php',
         'OC\\Route\\Router' => __DIR__ . '/../../..' . '/lib/private/Route/Router.php',
diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php
index 8fe9b4dca03cdcfb520175512f9fc5916134dbe4..671093ff08bdbcee5c605c613ce36cf389dcb216 100644
--- a/lib/private/AppFramework/DependencyInjection/DIContainer.php
+++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php
@@ -44,10 +44,12 @@ use OC\AppFramework\Middleware\Security\SecurityMiddleware;
 use OC\AppFramework\Middleware\SessionMiddleware;
 use OC\AppFramework\Utility\SimpleContainer;
 use OC\Core\Middleware\TwoFactorMiddleware;
+use OC\RichObjectStrings\Validator;
 use OCP\AppFramework\IApi;
 use OCP\AppFramework\IAppContainer;
 use OCP\Files\IAppData;
 use OCP\Files\Mount\IMountManager;
+use OCP\RichObjectStrings\IValidator;
 
 class DIContainer extends SimpleContainer implements IAppContainer {
 
@@ -330,6 +332,10 @@ class DIContainer extends SimpleContainer implements IAppContainer {
 			return $this->getServer()->getEncryptionManager();
 		});
 
+		$this->registerService(IValidator::class, function($c) {
+			return $c->query(Validator::class);
+		});
+
 
 		/**
 		 * App Framework APIs
diff --git a/lib/private/Notification/Manager.php b/lib/private/Notification/Manager.php
index ec831cf9793b945d64f6e634b693ab35ee57eda9..4b57db4bac9d170a1c7cc41fe673ea3300c85602 100644
--- a/lib/private/Notification/Manager.php
+++ b/lib/private/Notification/Manager.php
@@ -24,6 +24,7 @@
 namespace OC\Notification;
 
 
+use OC\RichObjectStrings\Validator;
 use OCP\Notification\IApp;
 use OCP\Notification\IManager;
 use OCP\Notification\INotification;
@@ -149,7 +150,9 @@ class Manager implements IManager {
 	 * @since 8.2.0
 	 */
 	public function createNotification() {
-		return new Notification();
+		return new Notification(
+			new Validator()
+		);
 	}
 
 	/**
diff --git a/lib/private/Notification/Notification.php b/lib/private/Notification/Notification.php
index 7bf4b9a74cfed588f8af75a0aec6b06bddbfb8df..7346f35f966a11b8aa4d0442ea63089d3017819a 100644
--- a/lib/private/Notification/Notification.php
+++ b/lib/private/Notification/Notification.php
@@ -26,8 +26,14 @@ namespace OC\Notification;
 
 use OCP\Notification\IAction;
 use OCP\Notification\INotification;
+use OCP\RichObjectStrings\InvalidObjectExeption;
+use OCP\RichObjectStrings\IValidator;
 
 class Notification implements INotification {
+
+	/** @var IValidator */
+	protected $richValidator;
+
 	/** @var string */
 	protected $app;
 
@@ -52,6 +58,12 @@ class Notification implements INotification {
 	/** @var string */
 	protected $subjectParsed;
 
+	/** @var string */
+	protected $subjectRich;
+
+	/** @var array */
+	protected $subjectRichParameters;
+
 	/** @var string */
 	protected $message;
 
@@ -81,8 +93,11 @@ class Notification implements INotification {
 
 	/**
 	 * Constructor
+	 *
+	 * @param IValidator $richValidator
 	 */
-	public function __construct() {
+	public function __construct(IValidator $richValidator) {
+		$this->richValidator = $richValidator;
 		$this->app = '';
 		$this->user = '';
 		$this->dateTime = new \DateTime();
@@ -92,6 +107,8 @@ class Notification implements INotification {
 		$this->subject = '';
 		$this->subjectParameters = [];
 		$this->subjectParsed = '';
+		$this->subjectRich = '';
+		$this->subjectRichParameters = [];
 		$this->message = '';
 		$this->messageParameters = [];
 		$this->messageParsed = '';
@@ -261,6 +278,43 @@ class Notification implements INotification {
 		return $this->subjectParsed;
 	}
 
+	/**
+	 * @param string $subject
+	 * @param array $parameters
+	 * @return $this
+	 * @throws \InvalidArgumentException if the subject or parameters are invalid
+	 * @since 9.2.0
+	 */
+	public function setRichSubject($subject, array $parameters = []) {
+		if (!is_string($subject) || $subject === '') {
+			throw new \InvalidArgumentException('The given parsed subject is invalid');
+		}
+		$this->subjectRich = $subject;
+
+		if (!is_array($parameters)) {
+			throw new \InvalidArgumentException('The given subject parameters are invalid');
+		}
+		$this->subjectRichParameters = $parameters;
+
+		return $this;
+	}
+
+	/**
+	 * @return string
+	 * @since 9.2.0
+	 */
+	public function getRichSubject() {
+		return $this->subjectRich;
+	}
+
+	/**
+	 * @return array[]
+	 * @since 9.2.0
+	 */
+	public function getRichSubjectParameters() {
+		return $this->subjectRichParameters;
+	}
+
 	/**
 	 * @param string $message
 	 * @param array $parameters
@@ -454,6 +508,14 @@ class Notification implements INotification {
 	 * @since 8.2.0
 	 */
 	public function isValidParsed() {
+		if ($this->getRichSubject() !== '' || !empty($this->getRichSubjectParameters())) {
+			try {
+				$this->richValidator->validate($this->getRichSubject(), $this->getRichSubjectParameters());
+			} catch (InvalidObjectExeption $e) {
+				return false;
+			}
+		}
+
 		return
 			$this->isValidCommon()
 			&&
diff --git a/lib/private/RichObjectStrings/Validator.php b/lib/private/RichObjectStrings/Validator.php
new file mode 100644
index 0000000000000000000000000000000000000000..2729b4a3f1bcea5a677b78c557e1f830c615116c
--- /dev/null
+++ b/lib/private/RichObjectStrings/Validator.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\RichObjectStrings;
+
+
+use OCP\RichObjectStrings\InvalidObjectExeption;
+use OCP\RichObjectStrings\IValidator;
+
+/**
+ * Class Validator
+ *
+ * @package OCP\RichObjectStrings
+ * @since 9.2.0
+ */
+class Validator implements IValidator  {
+
+	/** @var array[] */
+	protected $definitions;
+
+	/** @var array[] */
+	protected $requiredParameters = [];
+
+	/**
+	 * Constructor
+	 */
+	public function __construct() {
+		$this->definitions = json_decode(file_get_contents(__DIR__ . '/../../public/RichObjectStrings/definitions.json'), true);
+	}
+
+	/**
+	 * @param string $subject
+	 * @param array[] $parameters
+	 * @throws InvalidObjectExeption
+	 * @since 9.2.0
+	 */
+	public function validate($subject, array $parameters) {
+		$matches = [];
+		$result = preg_match_all('/\{([a-z0-9]+)\}/i', $subject, $matches);
+
+		if ($result === false) {
+			throw new InvalidObjectExeption();
+		}
+
+		if (!empty($matches[1])) {
+			foreach ($matches[1] as $parameter) {
+				if (!isset($parameters[$parameter])) {
+					throw new InvalidObjectExeption('Parameter is undefined');
+				} else {
+					$this->validateParameter($parameters[$parameter]);
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param array $parameter
+	 * @throws InvalidObjectExeption
+	 */
+	protected function validateParameter(array $parameter) {
+		if (!isset($parameter['type']) || !isset($this->definitions[$parameter['type']])) {
+			throw new InvalidObjectExeption('Object type is undefined');
+		}
+
+		$requiredParameters = $this->getRequiredParameters($parameter['type']);
+		$missingKeys = array_diff($requiredParameters, array_keys($parameter));
+		if (!empty($missingKeys)) {
+			throw new InvalidObjectExeption('Object is invalid');
+		}
+	}
+
+	/**
+	 * @param string $type
+	 * @return string[]
+	 */
+	protected function getRequiredParameters($type) {
+		if (isset($this->requiredParameters[$type])) {
+			return $this->requiredParameters[$type];
+		}
+
+		$this->requiredParameters[$type] = [];
+		foreach ($this->definitions[$type]['parameters'] as $parameter => $data) {
+			if ($data['required']) {
+				$this->requiredParameters[$type][] = $parameter;
+			}
+		}
+
+		return $this->requiredParameters[$type];
+	}
+}
diff --git a/lib/public/Notification/INotification.php b/lib/public/Notification/INotification.php
index fd16876a666958b2ee21ad40e5f2797db8c4e0c2..3a8bde0a375122f433de35b6138921781e4a58e6 100644
--- a/lib/public/Notification/INotification.php
+++ b/lib/public/Notification/INotification.php
@@ -127,6 +127,27 @@ interface INotification {
 	 */
 	public function getParsedSubject();
 
+	/**
+	 * @param string $subject
+	 * @param array $parameters
+	 * @return $this
+	 * @throws \InvalidArgumentException if the subject or parameters are invalid
+	 * @since 9.2.0
+	 */
+	public function setRichSubject($subject, array $parameters = []);
+
+	/**
+	 * @return string
+	 * @since 9.2.0
+	 */
+	public function getRichSubject();
+
+	/**
+	 * @return array[]
+	 * @since 9.2.0
+	 */
+	public function getRichSubjectParameters();
+
 	/**
 	 * @param string $message
 	 * @param array $parameters
diff --git a/lib/public/RichObjectStrings/IValidator.php b/lib/public/RichObjectStrings/IValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..bba098bdfc13aeb82773ef3bec8edd8f87428ccf
--- /dev/null
+++ b/lib/public/RichObjectStrings/IValidator.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\RichObjectStrings;
+
+/**
+ * Class Validator
+ *
+ * @package OCP\RichObjectStrings
+ * @since 9.2.0
+ */
+interface IValidator {
+
+	/**
+	 * @param string $subject
+	 * @param array[] $parameters
+	 * @throws InvalidObjectExeption
+	 * @since 9.2.0
+	 */
+	public function validate($subject, array $parameters);
+}
diff --git a/lib/public/RichObjectStrings/InvalidObjectExeption.php b/lib/public/RichObjectStrings/InvalidObjectExeption.php
new file mode 100644
index 0000000000000000000000000000000000000000..8bf597ebe9086ccacac29abab1c943becb57e6ee
--- /dev/null
+++ b/lib/public/RichObjectStrings/InvalidObjectExeption.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\RichObjectStrings;
+
+/**
+ * Class InvalidObjectExeption
+ *
+ * @package OCP\RichObjectStrings
+ * @since 9.2.0
+ */
+class InvalidObjectExeption extends \InvalidArgumentException {
+}
diff --git a/lib/public/RichObjectStrings/definitions.json b/lib/public/RichObjectStrings/definitions.json
new file mode 100644
index 0000000000000000000000000000000000000000..222f6615cf48ccc1bed63e7d7faaff4bfb3f4f19
--- /dev/null
+++ b/lib/public/RichObjectStrings/definitions.json
@@ -0,0 +1,228 @@
+{
+  "addressbook": {
+    "author": "Nextcloud",
+    "app": "dav",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the addressbook on the instance",
+        "example": "42"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The display name of the addressbook which should be used in the visual representation",
+        "example": "Contacts"
+      }
+    }
+  },
+  "addressbook-contact": {
+    "author": "Nextcloud",
+    "app": "dav",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the contact on the instance",
+        "example": "42"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The display name of the contact which should be used in the visual representation",
+        "example": "John Doe"
+      }
+    }
+  },
+  "announcement": {
+    "author": "Joas Schilling",
+    "app": "announcementcenter",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the announcement on the instance",
+        "example": "42"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The announcement subject which should be used in the visual representation",
+        "example": "file.txt"
+      },
+      "link": {
+        "since": "9.2.0",
+        "required": false,
+        "description": "The full URL to the file",
+        "example": "http://localhost/index.php/apps/announcements/#23"
+      }
+    }
+  },
+  "calendar": {
+    "author": "Nextcloud",
+    "app": "dav",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the calendar on the instance",
+        "example": "42"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The display name of the calendar which should be used in the visual representation",
+        "example": "Personal"
+      }
+    }
+  },
+  "calendar-event": {
+    "author": "Nextcloud",
+    "app": "dav",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the event on the instance",
+        "example": "42"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The display name of the event which should be used in the visual representation",
+        "example": "Workout"
+      }
+    }
+  },
+  "file": {
+    "author": "Nextcloud",
+    "app": "dav",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the file on the instance",
+        "example": "42"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The file name which should be used in the visual representation",
+        "example": "file.txt"
+      },
+      "path": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The full path of the file for the user",
+        "example": "path/to/file.txt"
+      },
+      "link": {
+        "since": "9.2.0",
+        "required": false,
+        "description": "The full URL to the file",
+        "example": "http://localhost/index.php/f/42"
+      }
+    }
+  },
+  "pending-federated-share": {
+    "author": "Nextcloud",
+    "app": "dav",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the federated share on the instance",
+        "example": "42"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The name of the shared item which should be used in the visual representation",
+        "example": "file.txt"
+      }
+    }
+  },
+  "systemtag": {
+    "author": "Nextcloud",
+    "app": "core",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the systemtag on the instance",
+        "example": "23"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The display name of the systemtag which should be used in the visual representation",
+        "example": "Project 1"
+      },
+      "visibility": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "If the user can see the systemtag",
+        "example": "1"
+      },
+      "assignable": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "If the user can assign the systemtag",
+        "example": "0"
+      }
+    }
+  },
+  "user": {
+    "author": "Nextcloud",
+    "app": "core",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the user on the instance",
+        "example": "johndoe"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The display name of the user which should be used in the visual representation",
+        "example": "John Doe"
+      },
+      "server": {
+        "since": "9.2.0",
+        "required": false,
+        "description": "The URL of the instance the user lives on",
+        "example": "localhost"
+      }
+    }
+  },
+  "user-group": {
+    "author": "Nextcloud",
+    "app": "core",
+    "since": "9.2.0",
+    "parameters": {
+      "id": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The id used to identify the group on the instance",
+        "example": "supportteam"
+      },
+      "name": {
+        "since": "9.2.0",
+        "required": true,
+        "description": "The display name of the group which should be used in the visual representation",
+        "example": "Support Team"
+      }
+    }
+  }
+}
diff --git a/tests/lib/Notification/NotificationTest.php b/tests/lib/Notification/NotificationTest.php
index 77d9e989cf123e3879f1816b04dd74c4e702faa6..eabed2736083a9bb3a5c393c90f314d978e09d36 100644
--- a/tests/lib/Notification/NotificationTest.php
+++ b/tests/lib/Notification/NotificationTest.php
@@ -23,16 +23,21 @@ namespace Test\Notification;
 
 
 use OC\Notification\Notification;
+use OCP\Notification\IAction;
 use OCP\Notification\INotification;
+use OCP\RichObjectStrings\IValidator;
 use Test\TestCase;
 
 class NotificationTest extends TestCase {
 	/** @var INotification */
 	protected $notification;
+	/** @var IValidator|\PHPUnit_Framework_MockObject_MockObject */
+	protected $validator;
 
 	public function setUp() {
 		parent::setUp();
-		$this->notification = new Notification();
+		$this->validator = $this->createMock(IValidator::class);
+		$this->notification = new Notification($this->validator);
 	}
 
 	protected function dataValidString($maxLength) {
@@ -416,14 +421,12 @@ class NotificationTest extends TestCase {
 
 	public function testCreateAction() {
 		$action = $this->notification->createAction();
-		$this->assertInstanceOf('OCP\Notification\IAction', $action);
+		$this->assertInstanceOf(IAction::class, $action);
 	}
 
 	public function testAddAction() {
 		/** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
-		$action = $this->getMockBuilder('OCP\Notification\IAction')
-			->disableOriginalConstructor()
-			->getMock();
+		$action = $this->createMock(IAction::class);
 		$action->expects($this->once())
 			->method('isValid')
 			->willReturn(true);
@@ -441,9 +444,7 @@ class NotificationTest extends TestCase {
 	 */
 	public function testAddActionInvalid() {
 		/** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
-		$action = $this->getMockBuilder('OCP\Notification\IAction')
-			->disableOriginalConstructor()
-			->getMock();
+		$action = $this->createMock(IAction::class);
 		$action->expects($this->once())
 			->method('isValid')
 			->willReturn(false);
@@ -455,9 +456,7 @@ class NotificationTest extends TestCase {
 
 	public function testAddActionSecondPrimary() {
 		/** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
-		$action = $this->getMockBuilder('OCP\Notification\IAction')
-			->disableOriginalConstructor()
-			->getMock();
+		$action = $this->createMock(IAction::class);
 		$action->expects($this->exactly(2))
 			->method('isValid')
 			->willReturn(true);
@@ -473,9 +472,7 @@ class NotificationTest extends TestCase {
 
 	public function testAddParsedAction() {
 		/** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
-		$action = $this->getMockBuilder('OCP\Notification\IAction')
-			->disableOriginalConstructor()
-			->getMock();
+		$action = $this->createMock(IAction::class);
 		$action->expects($this->once())
 			->method('isValidParsed')
 			->willReturn(true);
@@ -493,9 +490,7 @@ class NotificationTest extends TestCase {
 	 */
 	public function testAddParsedActionInvalid() {
 		/** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
-		$action = $this->getMockBuilder('OCP\Notification\IAction')
-			->disableOriginalConstructor()
-			->getMock();
+		$action = $this->createMock(IAction::class);
 		$action->expects($this->once())
 			->method('isValidParsed')
 			->willReturn(false);
@@ -507,9 +502,7 @@ class NotificationTest extends TestCase {
 
 	public function testAddActionSecondParsedPrimary() {
 		/** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
-		$action = $this->getMockBuilder('OCP\Notification\IAction')
-			->disableOriginalConstructor()
-			->getMock();
+		$action = $this->createMock(IAction::class);
 		$action->expects($this->exactly(2))
 			->method('isValidParsed')
 			->willReturn(true);
@@ -525,9 +518,7 @@ class NotificationTest extends TestCase {
 
 	public function testAddActionParsedPrimaryEnd() {
 		/** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
-		$action1 = $this->getMockBuilder('OCP\Notification\IAction')
-			->disableOriginalConstructor()
-			->getMock();
+		$action1 = $this->createMock(IAction::class);
 		$action1->expects($this->exactly(2))
 			->method('isValidParsed')
 			->willReturn(true);
@@ -535,9 +526,7 @@ class NotificationTest extends TestCase {
 			->method('isPrimary')
 			->willReturn(false);
 		/** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
-		$action2 = $this->getMockBuilder('OCP\Notification\IAction')
-			->disableOriginalConstructor()
-			->getMock();
+		$action2 = $this->createMock(IAction::class);
 		$action2->expects($this->once())
 			->method('isValidParsed')
 			->willReturn(true);
@@ -570,12 +559,13 @@ class NotificationTest extends TestCase {
 	 */
 	public function testIsValid($isValidCommon, $subject, $expected) {
 		/** @var \OCP\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
-		$notification = $this->getMockBuilder('\OC\Notification\Notification')
+		$notification = $this->getMockBuilder(Notification::class)
 			->setMethods([
 				'isValidCommon',
 				'getSubject',
 				'getParsedSubject',
 			])
+			->setConstructorArgs([$this->validator])
 			->getMock();
 
 		$notification->expects($this->once())
@@ -602,12 +592,13 @@ class NotificationTest extends TestCase {
 	 */
 	public function testIsParsedValid($isValidCommon, $subject, $expected) {
 		/** @var \OCP\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
-		$notification = $this->getMockBuilder('\OC\Notification\Notification')
+		$notification = $this->getMockBuilder(Notification::class)
 			->setMethods([
 				'isValidCommon',
 				'getParsedSubject',
 				'getSubject',
 			])
+			->setConstructorArgs([$this->validator])
 			->getMock();
 
 		$notification->expects($this->once())
@@ -648,7 +639,7 @@ class NotificationTest extends TestCase {
 	 */
 	public function testIsValidCommon($app, $user, $timestamp, $objectType, $objectId, $expected) {
 		/** @var \OCP\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
-		$notification = $this->getMockBuilder('\OC\Notification\Notification')
+		$notification = $this->getMockBuilder(Notification::class)
 			->setMethods([
 				'getApp',
 				'getUser',
@@ -656,6 +647,7 @@ class NotificationTest extends TestCase {
 				'getObjectType',
 				'getObjectId',
 			])
+			->setConstructorArgs([$this->validator])
 			->getMock();
 
 		$notification->expects($this->any())
diff --git a/tests/lib/RichObjectStrings/ValidatorTest.php b/tests/lib/RichObjectStrings/ValidatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b97388ab8e013e6217a30fafacdf074a60816f80
--- /dev/null
+++ b/tests/lib/RichObjectStrings/ValidatorTest.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\RichObjectStrings;
+
+
+use OC\RichObjectStrings\Validator;
+use Test\TestCase;
+
+class ValidatorTest extends TestCase {
+
+	public function test() {
+		$v = new Validator();
+		$v->validate('test', []);
+		$v->validate('test {string1} test {foo} test {bar}.', [
+			'string1' => [
+				'type' => 'user',
+				'id' => 'johndoe',
+				'name' => 'John Doe',
+			],
+			'foo' => [
+				'type' => 'user-group',
+				'id' => 'sample',
+				'name' => 'Sample Group',
+			],
+			'bar' => [
+				'type' => 'file',
+				'id' => '42',
+				'name' => 'test.txt',
+				'path' => 'path/to/test.txt',
+			],
+		]);
+	}
+
+}