summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-25 18:52:37 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-25 18:52:37 +0100
commit9436db19a79fab0cad1c3b9dbc2628e1d4ed6e51 (patch)
tree6664d13d7b22da8dca414d73f76f8e3c307c1856
parentbe66642ba83c1e238ba89d8cb562eb0e4b5c280c (diff)
Replaced stupid static ResourceUtils class with shiny new ResourceRequest class and corresponding (unfinished) test
-rw-r--r--src/core/resource/ResourceRequest.cpp238
-rw-r--r--src/core/resource/ResourceRequest.hpp197
-rw-r--r--src/core/resource/ResourceUtils.cpp138
-rw-r--r--src/core/resource/ResourceUtils.hpp128
-rw-r--r--test/core/resource/ResourceRequestTest.cpp149
5 files changed, 584 insertions, 266 deletions
diff --git a/src/core/resource/ResourceRequest.cpp b/src/core/resource/ResourceRequest.cpp
new file mode 100644
index 0000000..b047082
--- /dev/null
+++ b/src/core/resource/ResourceRequest.cpp
@@ -0,0 +1,238 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <string>
+
+#include <core/common/Logger.hpp>
+#include <core/common/Rtti.hpp>
+#include <core/common/Utils.hpp>
+#include <core/resource/Resource.hpp>
+#include <core/resource/Resource.hpp>
+#include <core/Registry.hpp>
+
+#include "ResourceRequest.hpp"
+
+namespace ousia {
+
+namespace RttiTypes {
+extern const Rtti Document;
+extern const Rtti Domain;
+extern const Rtti Node;
+extern const Rtti Typesystem;
+}
+
+/**
+ * Map mapping from Rtti pointers to the corresponding ResourceType.
+ */
+static const std::unordered_map<const Rtti *, ResourceType>
+ RTTI_RESOURCE_TYPE_MAP{{&RttiTypes::Document, ResourceType::DOCUMENT},
+ {&RttiTypes::Domain, ResourceType::DOMAIN_DESC},
+ {&RttiTypes::Typesystem, ResourceType::TYPESYSTEM}};
+
+/**
+ * Function used internally to build a set with all currently supported
+ * ResourceType instances.
+ *
+ * @param supportedTypes are all supported types.
+ * @return a set containing all ResourceTypes that can be used for these
+ * RTTI descriptors.
+ */
+static const std::unordered_set<ResourceType, Utils::EnumHash>
+supportedResourceTypes(const RttiSet &supportedTypes)
+{
+ std::unordered_set<ResourceType, Utils::EnumHash> res;
+ for (const Rtti *supportedType : supportedTypes) {
+ auto it = RTTI_RESOURCE_TYPE_MAP.find(supportedType);
+ if (it != RTTI_RESOURCE_TYPE_MAP.end()) {
+ res.insert(it->second);
+ }
+ }
+ return res;
+}
+
+/**
+ * Converts a set of supported RTTI descriptors to a string describing the
+ * corresponding ResourceTypes.
+ *
+ * @param supportedTypes are all supported types.
+ * @return a string containing all corresponding resource types.
+ */
+static std::string supportedResourceTypesString(const RttiSet &supportedTypes)
+{
+ return Utils::join(supportedResourceTypes(supportedTypes), ", ", "{", "}");
+}
+
+/**
+ * Tries to deduce the resource type from the given set of supported types.
+ * Returns ResourceType::UNKNOWN if there are ambiguities.
+ *
+ * @param supportedTypes are all supported types.
+ * @return the deduced ResourceType or ResourceType::UNKNOWN if there was an
+ * ambiguity.
+ */
+static ResourceType deduceResourceType(const RttiSet &supportedTypes)
+{
+ ResourceType resourceType = ResourceType::UNKNOWN;
+ for (const Rtti *supportedType : supportedTypes) {
+ auto it = RTTI_RESOURCE_TYPE_MAP.find(supportedType);
+ if (it != RTTI_RESOURCE_TYPE_MAP.end()) {
+ // Preven ambiguity
+ if (resourceType != ResourceType::UNKNOWN &&
+ resourceType != it->second) {
+ resourceType = ResourceType::UNKNOWN;
+ break;
+ }
+ resourceType = it->second;
+ }
+ }
+ return resourceType;
+}
+
+/**
+ * Function used to limit the supportedTypes to those that correspond to the
+ * ResourceType.
+ *
+ * @param resourceType is the type of the resource type that is going to be
+ * included.
+ * @param supportedTypes are all supported types.
+ * @return a restricted set of supportedTypes that correspond to the
+ * resourceType.
+ */
+static RttiSet limitSupportedTypes(ResourceType resourceType,
+ const RttiSet &supportedTypes)
+{
+ // Calculate the expected types
+ RttiSet expectedTypes;
+ for (auto entry : RTTI_RESOURCE_TYPE_MAP) {
+ if (entry.second == resourceType) {
+ expectedTypes.insert(entry.first);
+ }
+ }
+
+ // Restrict the supported types to the expected types
+ return Rtti::setIntersection(supportedTypes, expectedTypes);
+}
+
+/* Class ResourceRequest */
+
+ResourceRequest::ResourceRequest(const std::string &path,
+ const std::string &mimetype,
+ const std::string &rel,
+ const RttiSet &supportedTypes)
+ : path(path),
+ mimetype(mimetype),
+ rel(rel),
+ supportedTypes(supportedTypes),
+ resourceType(ResourceType::UNKNOWN),
+ parser(nullptr)
+{
+}
+
+bool ResourceRequest::deduce(Registry &registry, Logger &logger)
+{
+ bool ok = true;
+
+ // Try to deduce the mimetype if none was given
+ if (mimetype.empty()) {
+ mimetype = registry.getMimetypeForFilename(path);
+ if (mimetype.empty()) {
+ logger.error(std::string("Filename \"") + path +
+ std::string(
+ "\" has an unknown file extension. Explicitly "
+ "specify a mimetype."));
+ ok = false;
+ }
+ }
+
+ // Find a parser for the mimetype
+ if (!mimetype.empty()) {
+ auto parserDescr = registry.getParserForMimetype(mimetype);
+ parser = parserDescr.first;
+ parserTypes = parserDescr.second;
+
+ // Make sure a valid parser was returned, and if yes, whether the
+ // parser is allows to run here
+ if (!parser) {
+ logger.error(std::string("Cannot parse files of type \"") +
+ mimetype + std::string("\""));
+ ok = false;
+ } else if (!Rtti::setIsOneOf(parserTypes, supportedTypes)) {
+ logger.error(std::string("Resource of type \"") + mimetype +
+ std::string("\" cannot be included here!"));
+ ok = false;
+ }
+ }
+
+ // Limit the supportedTypes to those returned by the parser
+ supportedTypes = Rtti::setIntersection(supportedTypes, parserTypes);
+ if (supportedTypes.empty()) {
+ logger.error(std::string("Cannot include or link a file of type \"") +
+ mimetype + std::string("\" here!"));
+ ok = false;
+ }
+
+ // Try to deduce the ResourceType from the "rel" string
+ if (!rel.empty()) {
+ resourceType = Resource::getResourceTypeByName(rel);
+ if (resourceType == ResourceType::UNKNOWN) {
+ logger.error(std::string("Unknown relation \"") + rel +
+ std::string("\", expected one of ") +
+ supportedResourceTypesString(supportedTypes));
+ ok = false;
+ }
+ }
+
+ // Try to deduce the ResourceType from the supportedTypes
+ if (resourceType == ResourceType::UNKNOWN) {
+ resourceType = deduceResourceType(supportedTypes);
+ }
+
+ // Further limit the supportedTypes to those types that correspond to the
+ // specified resource type.
+ if (resourceType != ResourceType::UNKNOWN) {
+ supportedTypes = limitSupportedTypes(resourceType, supportedTypes);
+ if (supportedTypes.empty()) {
+ logger.error(
+ std::string("File of type \"") + mimetype +
+ std::string("\" cannot be included with relationship ") +
+ Resource::getResourceTypeName(resourceType));
+ ok = false;
+ }
+ } else {
+ // Issue a warning if the resource type is unknown
+ logger.warning(std::string(
+ "Ambiguous resource relationship, consider "
+ "specifying one of ") +
+ supportedResourceTypesString(supportedTypes) +
+ std::string(" as \"rel\" attribute"));
+ }
+
+ return ok;
+}
+
+bool ResourceRequest::locate(Registry &registry, Logger &logger,
+ Resource &resource,
+ const Resource &relativeTo) const
+{
+ if (!registry.locateResource(resource, path, resourceType, relativeTo)) {
+ logger.error(std::string("File not found: ") + path);
+ return false;
+ }
+ return true;
+}
+}
+
diff --git a/src/core/resource/ResourceRequest.hpp b/src/core/resource/ResourceRequest.hpp
new file mode 100644
index 0000000..9d5728f
--- /dev/null
+++ b/src/core/resource/ResourceRequest.hpp
@@ -0,0 +1,197 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ResourceRequest.hpp
+ *
+ * Defines the ResourceRequest class used by the ResourceManager to deduce as
+ * much information as possible about a resource that was included by the user.
+ *
+ * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
+ */
+
+#ifndef _OUSIA_RESOURCE_REQUEST_HPP_
+#define _OUSIA_RESOURCE_REQUEST_HPP_
+
+#include <string>
+
+#include <core/common/Rtti.hpp>
+#include <core/resource/Resource.hpp>
+
+namespace ousia {
+
+// Forward declarations
+class Logger;
+class Parser;
+class Registry;
+
+/**
+ * The ResourceRequest class contains user provided data about a Resource that
+ * should be opened and parsed. The ResourceRequest class can then be used to
+ * deduce missing information about the resource and finally to locate the
+ * Resource in the filesystem and to find a parser that is capable of parsing
+ * the Resource.
+ */
+class ResourceRequest {
+private:
+ /**
+ * Requested path of the file that should be included.
+ */
+ std::string path;
+
+ /**
+ * Mimetype of the resource that should be parsed.
+ */
+ std::string mimetype;
+
+ /**
+ * Relation string specifing the relationship of the resource within the
+ * document it is included in.
+ */
+ std::string rel;
+
+ /**
+ * Specifies the types of the Node that may result from the resource once it
+ * has been parsed.
+ */
+ RttiSet supportedTypes;
+
+ /**
+ * Types the parser is expected to return.
+ */
+ RttiSet parserTypes;
+
+ /**
+ * ResourceType as deduced from the user provided values.
+ */
+ ResourceType resourceType;
+
+ /**
+ * Pointer at the Parser instance that may be used to parse the resource.
+ */
+ Parser *parser;
+
+public:
+ /**
+ * Constructor of the ResourceRequest class. Takes the user provided data
+ * about the resource request.
+ *
+ * @param path is the requested path of the file that should be included.
+ * @param mimetype is the mimetype of the resource that should be parsed
+ * (may be empty, in which case the mimetype is deduced from the file
+ * extension)
+ * @param rel is a "relation string" supplied by the user which specifies
+ * the relationship of the specified resource within the document it is
+ * included in.
+ * @param supportedTypes specifies the types of the Node that may result
+ * from the resource once it has been parsed. This value is not directly
+ * provided by the user, but by the calling code.
+ */
+ ResourceRequest(const std::string &path, const std::string &mimetype,
+ const std::string &rel, const RttiSet &supportedTypes);
+
+ /**
+ * Tries to deduce all possible information and produces log messages for
+ * the user.
+ *
+ * @param registry from which registered parsers, mimetypes and file
+ * extensions are looked up.
+ * @param logger is the logger instance to which errors or warnings are
+ * logged.
+ * @return true if a parser has been found that could potentially be used to
+ * parse the file.
+ */
+ bool deduce(Registry &registry, Logger &logger);
+
+ /**
+ * Tries to locate the specified resource.
+ *
+ * @param registry from which registered parsers, mimetypes and file
+ * extensions are looked up.
+ * @param logger is the logger instance to which errors or warnings are
+ * logged.
+ * @param resource is the Resource descriptor that should be filled with the
+ * actual location.
+ * @param relativeTo is another resource relative to which the Resource
+ * should be looked up.
+ * @return true if a resource was found, false otherwise. Equivalent to
+ * the value of resource.isValid().
+ */
+ bool locate(Registry &registry, Logger &logger, Resource &resource,
+ const Resource &relativeTo = NullResource) const;
+
+ /**
+ * Returns the requested path of the file that should be included.
+ *
+ * @param path given by the user (not the location of an actually found
+ * resource).
+ */
+ const std::string &getPath() const { return path; }
+
+ /**
+ * Returns the mimetype of the resource that should be parsed.
+ *
+ * @return the deduced mimetype.
+ */
+ const std::string &getMimetype() const { return mimetype; }
+
+ /**
+ * Returns the relation string which specifies the relationship of the
+ * resource within the document it is included in.
+ *
+ * @return the deduced relation string.
+ */
+ const std::string &getRel() const { return rel; }
+
+ /**
+ * Returns the types of the Node that may result from the resource once it
+ * has been parsed. Restricted to the types that may actually returned by
+ * the parser.
+ *
+ * @return the deduced supported types.
+ */
+ const RttiSet &getSupportedTypes() const { return supportedTypes; }
+
+ /**
+ * Returns the ResourceType as deduced from the user provided values.
+ *
+ * @return deduced ResourceType or ResourceType::UNKNOWN if none could be
+ * deduced.
+ */
+ ResourceType getResourceType() const { return resourceType; }
+
+ /**
+ * Returns the parser that was deduced according to the given resource
+ * descriptors.
+ *
+ * @return the pointer at the parser instance or nullptr if none was found.
+ */
+ Parser *getParser() const { return parser; }
+
+ /**
+ * Returns the types the parser may return or an empty set if no parser was
+ * found.
+ *
+ * @return the types the parser may return.
+ */
+ RttiSet getParserTypes() const { return parserTypes; }
+};
+}
+
+#endif /* _OUSIA_RESOURCE_REQUEST_HPP_ */
+
diff --git a/src/core/resource/ResourceUtils.cpp b/src/core/resource/ResourceUtils.cpp
deleted file mode 100644
index 7c42716..0000000
--- a/src/core/resource/ResourceUtils.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- Ousía
- Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <core/common/Logger.hpp>
-#include <core/common/Rtti.hpp>
-#include <core/common/Utils.hpp>
-
-#include "ResourceUtils.hpp"
-
-namespace ousia {
-
-namespace RttiTypes {
-extern const Rtti Document;
-extern const Rtti Domain;
-extern const Rtti Node;
-extern const Rtti Typesystem;
-}
-
-/**
- * Map mapping from relations (the "rel" attribute in includes) to the
- * corresponding ResourceType.
- */
-static const std::unordered_map<std::string, ResourceType> RelResourceTypeMap{
- {"document", ResourceType::DOCUMENT},
- {"domain", ResourceType::DOMAIN_DESC},
- {"typesystem", ResourceType::TYPESYSTEM}};
-
-/**
- * Map mapping from relations to the corresponding Rtti descriptor.
- */
-static const std::unordered_map<std::string, const Rtti *> RelRttiTypeMap{
- {"document", &RttiTypes::Document},
- {"domain", &RttiTypes::Domain},
- {"typesystem", &RttiTypes::Typesystem}};
-
-/**
- * Map mapping from Rtti pointers to the corresponding ResourceType.
- */
-static const std::unordered_map<const Rtti *, ResourceType> RttiResourceTypeMap{
- {&RttiTypes::Document, ResourceType::DOCUMENT},
- {&RttiTypes::Domain, ResourceType::DOMAIN_DESC},
- {&RttiTypes::Typesystem, ResourceType::TYPESYSTEM}};
-
-ResourceType ResourceUtils::deduceResourceType(const std::string &rel,
- const RttiSet &supportedTypes,
- Logger &logger)
-{
- ResourceType res;
-
- // Try to deduce the ResourceType from the "rel" attribute
- res = deduceResourceType(rel, logger);
-
- // If this did not work, try to deduce the ResourceType from the
- // supportedTypes supplied by the Parser instance.
- if (res == ResourceType::UNKNOWN) {
- res = deduceResourceType(supportedTypes, logger);
- }
- if (res == ResourceType::UNKNOWN) {
- logger.note(
- "Ambigous resource type, consider specifying the \"rel\" "
- "attribute");
- }
- return res;
-}
-
-ResourceType ResourceUtils::deduceResourceType(const std::string &rel,
- Logger &logger)
-{
- std::string s = Utils::toLower(rel);
- if (!s.empty()) {
- auto it = RelResourceTypeMap.find(s);
- if (it != RelResourceTypeMap.end()) {
- return it->second;
- } else {
- logger.error(std::string("Unknown relation \"") + rel +
- std::string("\""));
- }
- }
- return ResourceType::UNKNOWN;
-}
-
-ResourceType ResourceUtils::deduceResourceType(const RttiSet &supportedTypes,
- Logger &logger)
-{
- if (supportedTypes.size() == 1U) {
- auto it = RttiResourceTypeMap.find(*supportedTypes.begin());
- if (it != RttiResourceTypeMap.end()) {
- return it->second;
- }
- }
- return ResourceType::UNKNOWN;
-}
-
-const Rtti *ResourceUtils::deduceRttiType(const std::string &rel)
-{
- std::string s = Utils::toLower(rel);
- if (!s.empty()) {
- auto it = RelRttiTypeMap.find(s);
- if (it != RelRttiTypeMap.end()) {
- return it->second;
- }
- }
- return &RttiTypes::Node;
-}
-
-RttiSet ResourceUtils::limitRttiTypes(const RttiSet &supportedTypes,
- const std::string &rel)
-{
- return limitRttiTypes(supportedTypes, deduceRttiType(rel));
-}
-
-RttiSet ResourceUtils::limitRttiTypes(const RttiSet &supportedTypes,
- const Rtti *type)
-{
- RttiSet res;
- for (const Rtti *supportedType : supportedTypes) {
- if (supportedType->isa(*type)) {
- res.insert(supportedType);
- }
- }
- return res;
-}
-}
diff --git a/src/core/resource/ResourceUtils.hpp b/src/core/resource/ResourceUtils.hpp
deleted file mode 100644
index 13f9251..0000000
--- a/src/core/resource/ResourceUtils.hpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- Ousía
- Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file ResourceUtils.hpp
- *
- * Contains the ResourceUtils class which defines a set of static utility
- * functions for dealing with Resources and ResourceTypes.
- *
- * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
- */
-
-#ifndef _OUSIA_RESOURCE_UTILS_HPP_
-#define _OUSIA_RESOURCE_UTILS_HPP_
-
-#include <string>
-
-#include <core/common/Rtti.hpp>
-
-#include "Resource.hpp"
-
-namespace ousia {
-
-/**
- * Class containing static utility functions for dealing with Resources and
- * ResourceTypes.
- */
-class ResourceUtils {
-public:
- /**
- * Function used to deduce the resource type from a given "relation" string
- * and a set of RTTI types into which the resource should be converted by a
- * parser.
- *
- * @param rel is a relation string which specifies the type of the resource.
- * May be empty.
- * @param supportedTypes is a set of RTTI types into which the resource
- * should be converted by a parser. Set may be empty.
- * @param logger is the Logger instance to which errors should be logged.
- * @return a ResourceType specifier.
- */
- static ResourceType deduceResourceType(const std::string &rel,
- const RttiSet &supportedTypes,
- Logger &logger);
-
- /**
- * Function used to deduce the resource type from a given "relation" string.
- *
- * @param rel is a relation string which specifies the type of the resource.
- * May be empty.
- * @param logger is the Logger instance to which errors should be logged
- * (e.g. if the relation string is invalid).
- * @return a ResourceType specifier.
- */
- static ResourceType deduceResourceType(const std::string &rel,
- Logger &logger);
-
- /**
- * Function used to deduce the resource type from a set of RTTI types into
- * which the resource should be converted by a parser.
- *
- * @param supportedTypes is a set of RTTI types into which the resource
- * should be converted by a parser. Set may be empty.
- * @param logger is the Logger instance to which errors should be logged.
- * @return a ResourceType specifier.
- */
- static ResourceType deduceResourceType(const RttiSet &supportedTypes,
- Logger &logger);
-
- /**
- * Transforms the given relation string to the corresponding RttiType.
- *
- * @param rel is a relation string which specifies the type of the resource.
- * May be empty.
- * @return a pointer at the corresponding Rtti instance or a pointer at the
- * Rtti descriptor of the Node class (the most general Node type) if the
- * given relation type is unknown.
- */
- static const Rtti *deduceRttiType(const std::string &rel);
-
- /**
- * Reduces the number of types supported by a parser as the type of a
- * resource to the intersection of the given supported types and the RTTI
- * type associated with the given relation string.
- *
- * @param supportedTypes is a set of RTTI types into which the resource
- * should be converted by a parser. Set may be empty.
- * @param rel is a relation string which specifies the type of the resource.
- * @return the supported type set limited to those types that can actually
- * be returned according to the given relation string.
- */
- static RttiSet limitRttiTypes(const RttiSet &supportedTypes,
- const std::string &rel);
-
- /**
- * Reduces the number of types supported by a parser as the type of a
- * resource to the intersection of the given supported types and the RTTI
- * type associated with the given relation string.
- *
- * @param supportedTypes is a set of RTTI types into which the resource
- * should be converted by a parser. Set may be empty.
- * @param type is the type that is to be expected from the parser.
- * @return the supported type set limited to those types that can actually
- * be returned according to the given relation string (form an isa
- * relationship with the given type).
- */
- static RttiSet limitRttiTypes(const RttiSet &supportedTypes,
- const Rtti *type);
-};
-}
-
-#endif /* _OUSIA_RESOURCE_UTILS_HPP_ */
-
diff --git a/test/core/resource/ResourceRequestTest.cpp b/test/core/resource/ResourceRequestTest.cpp
new file mode 100644
index 0000000..0bb34be
--- /dev/null
+++ b/test/core/resource/ResourceRequestTest.cpp
@@ -0,0 +1,149 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <gtest/gtest.h>
+
+#include <iostream>
+
+#include <core/common/Logger.hpp>
+#include <core/common/Rtti.hpp>
+#include <core/frontend/TerminalLogger.hpp>
+#include <core/parser/Parser.hpp>
+#include <core/resource/ResourceRequest.hpp>
+#include <core/Registry.hpp>
+
+namespace ousia {
+
+namespace RttiTypes {
+extern const Rtti Document;
+extern const Rtti Domain;
+extern const Rtti Typesystem;
+}
+
+static TerminalLogger logger(std::cerr, true);
+// static ConcreteLogger logger;
+
+namespace {
+class ModuleParser : public Parser {
+protected:
+ Rooted<Node> doParse(CharReader &reader, ParserContext &ctx) override
+ {
+ return nullptr; // Stub
+ }
+};
+
+class DocumentParser : public Parser {
+protected:
+ Rooted<Node> doParse(CharReader &reader, ParserContext &ctx) override
+ {
+ return nullptr; // Stub
+ }
+};
+
+struct TestSetup {
+ ModuleParser pModule;
+ DocumentParser pDocument;
+ Registry registry;
+
+ TestSetup()
+ {
+ registry.registerExtension("domain", "application/domain");
+ registry.registerExtension("typesystem", "application/typesystem");
+ registry.registerExtension("document", "application/document");
+ registry.registerParser(
+ {"application/domain", "application/typesystem"},
+ {&RttiTypes::Domain, &RttiTypes::Typesystem}, &pModule);
+ registry.registerParser({"application/document"},
+ {&RttiTypes::Document}, &pDocument);
+ }
+};
+}
+
+TEST(ResourceRequest, deduction)
+{
+ TestSetup t;
+
+ ResourceRequest req("test.domain", "", "", {&RttiTypes::Domain});
+
+ ASSERT_TRUE(req.deduce(t.registry, logger));
+
+ ASSERT_EQ("test.domain", req.getPath());
+ ASSERT_EQ("application/domain", req.getMimetype());
+ ASSERT_EQ(RttiSet({&RttiTypes::Domain}), req.getSupportedTypes());
+ ASSERT_EQ(ResourceType::DOMAIN_DESC, req.getResourceType());
+ ASSERT_EQ(&t.pModule, req.getParser());
+ ASSERT_EQ(RttiSet({&RttiTypes::Domain, &RttiTypes::Typesystem}),
+ req.getParserTypes());
+}
+
+TEST(ResourceRequest, deductionWithMimetype)
+{
+ TestSetup t;
+
+ ResourceRequest req("test.domain", "application/typesystem", "",
+ {&RttiTypes::Typesystem});
+
+ ASSERT_TRUE(req.deduce(t.registry, logger));
+
+ ASSERT_EQ("test.domain", req.getPath());
+ ASSERT_EQ("application/typesystem", req.getMimetype());
+ ASSERT_EQ(RttiSet({&RttiTypes::Typesystem}), req.getSupportedTypes());
+ ASSERT_EQ(ResourceType::TYPESYSTEM, req.getResourceType());
+ ASSERT_EQ(&t.pModule, req.getParser());
+ ASSERT_EQ(RttiSet({&RttiTypes::Domain, &RttiTypes::Typesystem}),
+ req.getParserTypes());
+}
+
+TEST(ResourceRequest, deductionWithUnknownResourceType)
+{
+ TestSetup t;
+
+ ResourceRequest req("test.domain", "", "",
+ {&RttiTypes::Domain, &RttiTypes::Typesystem});
+
+ ASSERT_TRUE(req.deduce(t.registry, logger));
+
+ ASSERT_EQ("test.domain", req.getPath());
+ ASSERT_EQ("application/domain", req.getMimetype());
+ ASSERT_EQ(RttiSet({&RttiTypes::Domain, &RttiTypes::Typesystem}),
+ req.getSupportedTypes());
+ ASSERT_EQ(ResourceType::UNKNOWN, req.getResourceType());
+ ASSERT_EQ(&t.pModule, req.getParser());
+ ASSERT_EQ(RttiSet({&RttiTypes::Domain, &RttiTypes::Typesystem}),
+ req.getParserTypes());
+}
+
+TEST(ResourceRequest, deductionWithRel)
+{
+ TestSetup t;
+
+ ResourceRequest req("test.domain", "", "domain",
+ {&RttiTypes::Domain, &RttiTypes::Typesystem});
+
+ ASSERT_TRUE(req.deduce(t.registry, logger));
+
+ ASSERT_EQ("test.domain", req.getPath());
+ ASSERT_EQ("application/domain", req.getMimetype());
+ ASSERT_EQ(RttiSet({&RttiTypes::Domain}), req.getSupportedTypes());
+ ASSERT_EQ(ResourceType::DOMAIN_DESC, req.getResourceType());
+ ASSERT_EQ(&t.pModule, req.getParser());
+ ASSERT_EQ(RttiSet({&RttiTypes::Domain, &RttiTypes::Typesystem}),
+ req.getParserTypes());
+}
+}
+