1
0
Fork 0
arangodb/arangod/Documentation/user-manual.dox

745 lines
28 KiB
Plaintext

////////////////////////////////////////////////////////////////////////////////
/// @brief user guide guide
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- USER MANUAL
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @page UserManual ArangoDB's User Manual (@VERSION)
///
/// @if LATEX
/// <ul>
/// <li>@ref UserManualBasics</li>
/// <li>@ref FirstStepsArangoDB</li>
/// <li>@ref UserManualArangosh</li>
/// <li>@ref ShellCollection</li>
/// <li>@ref ShellDocument</li>
/// <li>@ref ShellEdge</li>
/// <li>@ref SimpleQueries</li>
/// <li>@ref Aql</li>
/// <li>@ref UserManualActions</li>
///
/// @latexonly\appendix@endlatexonly
/// <li>@ref CommandLine</li>
/// <li>@ref Glossary</li>
/// </ul>
/// @else
/// @copydetails UserManualBasicsTOC
/// @copydetails FirstStepsArangoDBTOC
/// @copydetails UserManualArangoshTOC
/// @copydetails ShellCollectionTOC
/// @copydetails ShellDocumentTOC
/// @copydetails ShellEdgeTOC
/// @copydetails SimpleQueriesTOC
/// @copydetails AqlTOC
/// @copydetails UserManualActionsTOC
/// @copydetails CommandLineTOC
/// @endif
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- USER MANUAL BASICS
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @page UserManualBasicsTOC
///
/// <ul>
/// <li>@ref UserManualBasics
/// <ul>
/// <li>@ref UserManualServerStartStop
/// <ul>
/// <li>@ref UserManualServerStartStopOptions</li>
/// </ul>
/// </li>
/// <li>@ref UserManualServerFE</li>
/// <li>@ref UserManualShellStartStop
/// <ul>
/// <li>@ref UserManualShellStartStopOptions</li>
/// </ul>
/// </li>
/// </li>
/// <li>@ref UserManualServerStartStopDebug
/// </li>
/// </ul>
/// </li>
/// </ul>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @page UserManualBasics About ArangoDB
///
/// We recently started a new open source project - a universal nosql database
/// called AvocadoDB which became ArangoDB in May 2012.
///
/// Key features include:
///
/// <ul>
/// <li> Schema-free schemata let you combine the space efficiency of MySQL with
/// the performance power of NoSQL</li>
/// <li> Use ArangoDB as an application server and fuse your application and
/// database together for maximal throughput</li>
/// <li> JavaScript for all: no language zoo, you can use one language from your
/// browser to your back-end</li>
/// <li> ArangoDB is multi-threaded - exploit the power of all your cores</li>
/// <li> Flexible data modeling: model your data as combination of key-value pairs,
/// documents or graphs - perfect for social relations</li>
/// <li> Free index choice: use the correct index for your problem, be it a skip
/// list or a n-gram search</li>
/// <li> Configurable durability: let the application decide if it needs more
/// durability or more performance</li>
/// <li> No-nonsense storage: ArangoDB uses all of the power of modern storage
/// hardware, like SSD and large caches</li>
/// <li> It is open source (Apache Licence 2.0)</li>
/// </ul>
///
/// For more in-depth information
///
/// <ul>
/// <li> read more on the @EXTRES{http://www.arangodb.org/2012/03/07/avocadodbs-design-objectives,design goals of ArangoDB}</li>
/// <li> @EXTREF{http://vimeo.com/36411892,watch the video}@SPC- Martin Schoenert,
/// architect of ArangoDB, gives an introduction of what the ArangoDB project
/// is about.</li>
/// <li> or give it a @EXTRES{http://www.arangodb.org/try,try}.</li>
/// </ul>
///
/// The ArangoDB database groups documents into collections. Collections and
/// documents can be accessed using queries. For simple queries involving just
/// one collection and one search criteria, you can use a simple interface from
/// within JavaScript code or other languages supported by an API. This
/// interface allows you to select documents from one collection based on just
/// one search criteria. For more complex queries, you can use the Arango Query
/// Language (AQL), which is an evolution of SQL resp. UNQL for the NoSQL
/// world. AQL allows you to use more then one collection, similar to joins from
/// SQL, while still retaining the document and list structures like UNQL.
///
/// The ArangoDB database packages comes with various programs:
///
/// - @LIT{arangod}: The ArangoDB database daemon. This server program is
/// intended to run as daemon process and to server the various clients
/// connection to the server via TCP / HTTP. See @ref
/// UserManualServerStartStop.
/// - @LIT{arangosh}: The ArangoDB shell. A client that implements a
/// read-eval-print loop (REPL) and provides functions to access and
/// administrate the ArangoDB server. See @ref UserManualShellStartStop.
/// - @LIT{arangoimp}: A bulk importer for the ArangoDB server.
/// See @ref ImpManual
///
/// @EMBEDTOC{UserManualBasicsTOC}
///
/// @section UserManualServerStartStop Starting the ArangoDB Server
///////////////////////////////////////////////////////////////////
///
/// The ArangoDB database server has two modes of operation: as server, where it
/// will answer to client requests and an emergency console, in which you can
/// access the database directly. The latter - as the name suggests - should
/// only be used in case of an emergency, for example, a corrupted
/// collection. Using the emergency console allows you to issue all commands
/// normally available in actions and transactions.
///
/// You should never start more than one server for the same database,
/// independent from the mode of operation.
///
/// The following command starts the ArangoDB database in server mode. You will
/// be able to access the server using HTTP requests on port 8529. See @ref
/// UserManualServerStartStopOptions "below" for a list of frequently used
/// options, see @ref CommandLine "here" for a complete list.
///
/// @TINYEXAMPLE{option-database-directory,starting the server}
///
/// After starting the server, point your favorite browser to:
///
/// @LIT{http://localhost:8529/}
///
/// to access the administration front-end.
///
/// @subsection UserManualServerStartStopOptions Frequently Used Options
////////////////////////////////////////////////////////////////////////
///
/// The following command-line options are frequently used. For a full
/// list of options see @ref CommandLine "here".
///
/// @CMDOPT{@CA{database-directory}}
////////////////////////////////////
///
/// Uses the @CA{database-directory} as base directory. There is an alternative
/// version available for use in configuration files, see @ref
/// CommandLineArango "here".
///
/// @copydetails triagens::rest::ApplicationServer::_options
////////////////////////////////////////////////////////////
///
/// @CMDOPT{--log @CA{level}}
/////////////////////////////
///
/// Allows the user to choose the level of information which is logged by the
/// server. The @CA{level} is specified as a string and can be one of the
/// following values: fatal, error, warning, info, debug, trace. For more
/// information see @ref CommandLineLogging "here".
///
/// @copydetails triagens::arango::ArangoServer::_httpPort
//////////////////////////////////////////////////////////
///
/// @CMDOPT{--daemon}
/////////////////////
///
/// Runs the server as a daemon (as a background process).
///
/// @section UserManualServerFE ArangoDB's Front-End
////////////////////////////////////////////////////
///
/// The ArangoDB server has a graphical front-end, which allows you to inspect
/// the current state of the server. You can read the front-end using the
/// following URL:
///
/// @LIT{http://localhost:8529/_admin}
///
/// Unless you have loaded an application into the ArangoDB server, which remaps
/// the paths, the front-end will also be available under
///
/// @LIT{http://localhost:8529/}.
///
/// @htmlonly <img src="images/fe1.png" alt="ArangoDB Front-End">@endhtmlonly
/// @latexonly\includegraphics[width=12cm]{images/fe1.png}@endlatexonly
///
/// The front-end allows you the browser through the collections and
/// documents. If you need to administrate the database, please use
/// the ArgangoDB shell described in the next section.
///
/// @section UserManualShellStartStop Starting the ArangoDB Shell
/////////////////////////////////////////////////////////////////
///
/// After the server has been @ref UserManualServerStartStop "started",
/// you can use the ArangoDB shell to administrate the server. Without
/// any arguments, the ArangoDB shell will try to contact the server
/// on port 8529 on the localhost. For more information see @ref
/// UserManualArangosh.
///
/// @TINYEXAMPLE{arangosh-start,starting the shell}
///
/// The shell will print its own version number and, if successfully connected
/// to a server, the version number of the ArangoDB server.
///
/// @subsection UserManualShellStartStopOptions Command-Line Options
////////////////////////////////////////////////////////////////////
///
/// Use @LIT{--help} to get a list of command-line options:
///
/// @TINYEXAMPLE{arangosh-options,shell options}
///
/// @section UserManualServerStartStopDebug Starting the ArangoDB Emergency Console
///////////////////////////////////////////////////////////////////////////////////
///
/// The following command starts a emergency console. See below for a list of
/// frequently used options, see @ref CommandLine "here" for a complete list.
///
/// @note Never start the emergency console for a database which also has a
/// server attached to it. In general the ArangoDB shell is what you want.
///
/// @EXAMPLE{start-emergency-console,emergency console}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- USER MANUAL ARANGOSH
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @page UserManualArangoshTOC
///
/// <ul>
/// <li>@ref UserManualArangosh
/// </li>
/// </ul>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @page UserManualArangosh The Arango Shell
///
/// @EMBEDTOC{UserManualArangoshTOC}
///
/// @section UserManualArangoshOutput Arango Shell Output
/////////////////////////////////////////////////////////
///
/// In general the Arango Shells prints its as output to standard output channel
/// using the JSON stringifier.
///
/// @code
/// arangosh> db.five.all().toArray();
/// [{ _id : "2223655/3665447", _rev : 3665447, name : "one" },
/// { _id : "2223655/3730983", _rev : 3730983, name : "two" },
/// { _id : "2223655/3862055", _rev : 3862055, name : "four" },
/// { _id : "2223655/3993127", _rev : 3993127, name : "three" }]
/// @endcode
///
/// @CLEARPAGE
/// @FUN{start_pretty_print()}
///
/// While the standard JSON stringifier is very concise it is hard to read.
/// Calling the function @FN{start_pretty_print} will enable the pretty printer
/// which formats the output in a human readable way.
///
/// @code
/// arangosh> start_pretty_print();
/// using pretty printing
/// arangosh> db.five.all().toArray();
/// [
/// {
/// _id : "2223655/3665447",
/// _rev : 3665447,
/// name : "one"
/// },
/// {
/// _id : "2223655/3730983",
/// _rev : 3730983,
/// name : "two"
/// },
/// {
/// _id : "2223655/3862055",
/// _rev : 3862055,
/// name : "four"
/// },
/// {
/// _id : "2223655/3993127",
/// _rev : 3993127,
/// name : "three"
/// }
/// ]
/// @endcode
///
/// @CLEARPAGE
/// @FUN{stop_pretty_print()}
///
/// The functions disable the pretty printer, switching back to the standard
/// JSON output format.
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- USER MANUAL ACTIONS
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @page UserManualActionsTOC
///
/// <ul>
/// <li>@ref UserManualActions
/// <ul>
/// <li>@ref UserManualActionsIntro</li>
/// <li>@ref UserManualActionsHelloWorld</li>
/// <li>@ref UserManualActionsHelloJson</li>
/// <li>@ref UserManualActionsEcho</li>
/// <li>@ref UserManualActionsDYO</li>
/// <li>@ref UserManualActionsAdvanced</li>
/// </ul>
/// </li>
/// </ul>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @page UserManualActions Arango Actions
///
/// Please note, that user Actions in ArangoDB are still preliminary and details
/// are subject to change.
///
/// @EMBEDTOC{UserManualActionsTOC}
///
/// @section UserManualActionsIntro Introduction to User Actions
////////////////////////////////////////////////////////////////
///
/// In some ways the communication layer of the ArangoDB server behaves like a
/// Web server. Unlike a Web server, it normally responses to HTTP requests by
/// delivering JSON objects. Remember, documents in the database are just JSON
/// objects. So, most of the time the HTTP response will contain a JSON document
/// from the database as body. You can extract the documents stored in the
/// database using HTTP @LIT{GET}. You can store documents using HTTP
/// @LIT{POST}.
///
/// However, there is something more. You can write small sniplets - so called
/// actions - to extend the database. The idea of actions is that sometimes it
/// is better to store parts of the business logic within AnrangoDB.
///
/// The simplest example is the age of a person. Assume you store information
/// about people in your database. It is an anti-pattern to store the age,
/// because it changes every now and then. Therefore, you normally store the
/// birthday and let the client decide what to do with it. However, if you have
/// many different clients, it might be easier to enrich the person document
/// with the age using actions once on the server side.
///
/// Or, for instance, if you want to apply some statistics to large data-sets
/// and you cannot easily express this as query. You can define a action instead
/// of transferring the whole data to the client and do the computation on the
/// client.
///
/// Actions are also useful if you want to restrict and filter data according to
/// some complex permission system.
///
/// The ArangoDB server can deliver all kinds of information, JSON being only
/// one possible format. You can also generate HTML or images. However, a Web
/// server is normally better suited for the task as it also implements various
/// caching strategies, language selection, compression and so on. Having said
/// that, there are still situations where it might be suitable to use the
/// ArangoDB to deliver HTML pages - static or dynamic. An simple example is the
/// built-in administration interface. You can access it using any modern
/// browser and there is no need for a separate Apache or IIS.
///
/// The following sections will explain actions within ArangoDB and show how to
/// define them. The examples start with delivering static HTML pages - even if
/// this is not the primary use-case for actions. The later sections will then
/// show you, how to code some pieces of your business logic and return JSON
/// objects.
///
/// The interface is loosely modelled after the JavaScript classes for HTTP
/// request and responses found in node.js and the middleware/routing aspects
/// of connect.js and express.js.
///
/// Note that unlike node.js, ArangoDB is multi-threaded and there is no easy
/// way to share state between queries inside the JavaScript engine. If such
/// state information is required, you need to use the database itself.
///
/// @section UserManualActionsHelloWorld A Hello World Example
//////////////////////////////////////////////////////////////
///
/// The client API or browser sends a HTTP request to the ArangoDB server and
/// the server returns a HTTP response to the client. A HTTP requests consists
/// of a method, normally @LIT{GET} or @LIT{POST} when using a browser, and a
/// request path like @LIT{/hello/world}. For a real Web server there are a zillion
/// of other thing to consider, we will ignore this for the moment. The HTTP
/// response contains a content type, describing how to interpret the returned
/// data, and the data itself.
///
/// In the following example, we want to define action in ArangoDB, so that the
/// server returns the HTML document
///
/// @code
/// <html>
/// <body>
/// Hello World
/// </body>
/// </html>
/// @endcode
///
/// if asked @LIT{GET /hello/world}.
///
/// The server needs to know what function to call or what document to deliver
/// if it receives a request. This is called routing. All the routing information
/// of ArangoDB is stored in a collection @LIT{_routing}. Each entry in this
/// collections describes how to deal with a particular request path.
///
/// For the above example, add the following document to the @{_routing}
/// collection:
///
/// @code
/// arangosh> db._routing.save({
/// ........> path: "/hello/world",
/// ........> callback: {
/// ........> contentType: "text/html",
/// ........> body: "<html><body>Hello World</body></html>" }});
/// @endcode
///
/// In order to activate the new routing, you must either restart the server
/// or call the internal reload function.
///
/// @code
/// arangosh> require("internal").reloadRouting()
/// @endcode
///
/// Now use the browser and access
///
/// @LIT{http://localhost:8529/hello/world}
///
/// @section UserManualActionsHelloJson A Hello World Example for JSON
//////////////////////////////////////////////////////////////////////
///
/// If you change the example slightly, then a JSON object will be delivered.
///
/// @code
/// arangosh> db._routing.save({
/// ........> path: "/hello/json",
/// ........> callback: {
/// ........> contentType: "application/json",
/// ........> body: "{ \"hello\" : \"world\" }" }});
/// arangosh> require("internal").reloadRouting()
/// @endcode
///
/// Again check with your browser
///
/// @LIT{http://localhost:8529/hello/json}
///
/// Depending on your browser and installed add-ons you will either see the
/// JSON object or a download dialog. If your browser wants to open an external
/// application to display the JSON object, you can change the @LIT{contentType}
/// to @LIT{"text/plain"} for the example. This makes it easier to check the
/// example using a browser. Or use @LIT{curl} to access the server.
///
/// @code
/// bash> curl "http://127.0.0.1:8529/hello/json" && echo
/// { "hello" : "world" }
/// @endcode
///
/// @section UserManualActionsEcho A Dynamic Example
////////////////////////////////////////////////////
///
/// The above examples deliver static content, which is fine for an example.
/// But the real power of actions lies in dynamic actions which use JavaScript
/// to construct the result.
///
/// A very simple example is the function @LIT{echoRequest} defined in
/// the module @LIT{org/arangodb/actions}.
///
/// @code
/// function (req, res, next, options) {
/// var result;
///
/// result = { request: req, options: options };
///
/// res.responseCode = exports.HTTP_OK;
/// res.contentType = "application/json";
/// res.body = JSON.stringify(result);
/// }
/// @endcode
///
/// That functions accepts a request and returns this request as JSON object.
///
/// It is not possible to store functions directly in the routing table, but you
/// can call functions defined in modules. In the above example the function can
/// be accessed from JavaScript as:
///
/// @LIT{require("org/arangodb/actions").echoRequest}
///
/// You can use it in the routing collection by specifying the name
/// @LIT{"org/arangodb/actions/echoRequest"}.
///
/// @code
/// arangosh> db._routing.save({
/// ........> path: "/hello/echo",
/// ........> callback: "org/arangodb/actions/echoRequest" });
/// @endcode
///
/// Reload the routing and check
///
/// @LIT{http://127.0.0.1:8529/hello/echo}
///
/// You should see something like
///
/// @code
/// {
/// "request": {
/// "prefix": "/hello/echo",
/// "suffix": [
/// "hello",
/// "echo"
/// ],
/// "path": "/hello/echo",
/// "headers": {
/// "accept-encoding": "gzip, deflate",
/// "accept-language": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3",
/// "connection": "keep-alive",
/// "content-length": "0",
/// "host": "localhost:8529",
/// "user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0"
/// },
/// "requestType": "GET",
/// "parameters": { }
/// },
/// "options": { }
/// }
/// @endcode
///
/// Please note that
///
/// @code
/// arangosh> db._routing.save({
/// ........> path: "/hello/echo",
/// ........> callback: "org/arangodb/actions/echoRequest" });
/// @endcode
///
/// is a short-cut for
///
/// @code
/// arangosh> db._routing.save({
/// ........> path: "/hello/echo-long",
/// ........> callback: {
/// ........> for: "org/arangodb/actions",
/// ........> do: "echoRequest" }});
/// @endcode
///
/// The verbose form allows you to pass options to the called function:
///
/// @code
/// arangosh> a = db._routing.firstExample({path: "/hello/echo-long"});
/// arangosh> a.callback.options = { option: "my option1" };
/// arangosh> db._replace(a, a);
/// @endcode
///
/// You should now see the options in the result.
///
/// @code
/// {
/// "request": {
/// "prefix": "/hello/echo-long",
/// ...
/// },
/// "options": {
/// "option": "my option1"
/// }
/// }
/// @endcode
///
/// @section UserManualActionsDYO Define Your Own Callback
//////////////////////////////////////////////////////////
///
/// You can define your own callbacks by adding a new module to ArangoDB. In
/// order to avoid name clashes modules should be named
///
/// @LIT{tld/domain/modulename}
///
/// where @LIT{domain.tld} is your domain name. For development you can store
/// your code in files in the filesystem, see @ref MODULES_PATH and
/// @ref MODULES.
///
/// However, when you are finished with the development, you can rollout the
/// module code by storing it inside the @LIT{_modules} collection.
///
/// Create a file @LIT{hello-world.js} with the following content:
///
/// @code
/// var actions = require("org/arangodb/actions");
///
/// exports.helloWorld = function (req, res) {
/// res.contentType = "text/html";
/// res.responseCode = actions.HTTP_OK;
/// res.body = "<html><body>Hello World!</body></html>";
/// };
/// @endcode
///
/// Load this file as new module @LIT{de/celler/hello-world} into the database
///
/// @code
/// arangosh> require("internal").defineModule("de/celler/hello-world", "hello-world.js");
/// @endcode
///
/// Define a corresponding routing
///
/// @code
/// arangosh> db._routing.save({
/// ........> path: "/my/echo",
/// ........> callback: "de/celler/hello-world/helloWorld" });
/// arangosh> require("internal").reloadRouting()
/// @endcode
///
/// and check it
///
/// @LIT{http://localhost:8529/my/echo}
///
/// @section UserManualActionsAdvanced Advanced Usages
//////////////////////////////////////////////////////
///
/// For detailed information see the reference manual.
///
/// @subsection UserManualActionsAdvancedPrefix Using Prefixes
//////////////////////////////////////////////////////////////
///
/// All the above definitions require an exact match. If you set the
/// @LIT{prefix} attribute to @LIT{true}, additional paths are ignored and the
/// URL also results in a match.
///
/// @code
/// arangosh> db._routing.save({
/// ........> path: "/hello",
/// ........> prefix: true,
/// ........> callback: "org/arangodb/actions/echoRequest" });
/// @endcode
///
/// Now try
///
/// @LIT{http://localhost:8529/hello/this/is/ignored/but/available/in/path}
///
/// The complete path is available in the @LIT{path} attribute, while the
/// matched prefix is available in the @LIT{prefix} attribute.
///
/// @code
/// {
/// "request": {
/// "prefix": "/hello",
/// "path": "/hello/this/is/ignored/but/available/in/path",
/// ...
/// },
/// "options": { }
/// }
/// @endcode
///
/// @subsection UserManualActionsAdvancedMiddleware Writing Middleware
//////////////////////////////////////////////////////////////////////
///
/// Assume, you want to log every request. In this case you can easily define
/// an action for the whole url-space @LIT{/}. This action simply logs
/// the requests, calls the next in line, and logs the response.
///
/// @code
/// exports.logRequest = function (req, res, next, options) {
/// console.log("received request: %s", JSON.stringify(req));
/// next();
/// console.log("produced response: %s", JSON.stringify(res));
/// };
/// @endcode
///
/// This functions is available as @LIT{org/arangodb/actions/logRequest}.
/// You need to tell ArangoDB that it is should use a prefix match and
/// that the shortest match should win in this case:
///
/// @code
/// arangosh> db._routing.save({
/// ........> path: "/",
/// ........> topdown: true,
/// ........> prefix: true,
/// ........> callback: "org/arangodb/actions/logRequest" });
/// @endcode
///
/// @subsection UserManualActionsAdvancedeRedirect Redirects
////////////////////////////////////////////////////////////
///
/// Use the following for a permanent redirect:
///
/// @code
/// arangosh> db._routing.save({
/// ........> path: "/",
/// ........> topdown: true,
/// ........> prefix: true,
/// ........> callback: { redirect: "http://somewhere.else.org/hallo" });
/// @endcode
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: c++
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @\\}\\)"
// End: