aboutsummaryrefslogtreecommitdiff
path: root/libcontextsubscriber/src/contexttyperegistryinfo.cpp
blob: 912aeab69214fd204cff184630b6645e784a8a44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * Copyright (C) 2008 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include "contexttyperegistryinfo.h"
#include "logging.h"
#include "loggingfeatures.h"
#include <QMutex>
#include <QMutexLocker>
#include <QCoreApplication>
#include "nanoxml.h"

/*!
    \class ContextTypeRegistryInfo

    \brief A class to access the type registry.

    This is a singelton class used to obtain information about the core types defined
    in the type registry. Information is provided as type definitions returned as
    AssocTree instances. Each type definition is a QVariant tree wrapped in AssocTree
    for easy helper key accessors.

    \section Usage

    To obtain a type definition for a given type:

    \code
    AssocTree typeDefinition = ContextTypeRegistryInfo::instance()->typeDefinitionForName("string-enum");
    \endcode

    Unless you're building a dedicated type-introspection application, you don't
    want to deal with ContextTypeRegistryInfo directly. Instead, you can use the ContextTypeInfo
    class to fetch concrete types and use the easy accessors provided there.
*/

ContextTypeRegistryInfo* ContextTypeRegistryInfo::registryInstance = NULL;

/* Public */

/// Returns the singleton instance of the ContextTypeRegistryInfo. The object
/// is constructed automaticall on first access.
ContextTypeRegistryInfo* ContextTypeRegistryInfo::instance()
{
    static QMutex mutex;
    QMutexLocker locker(&mutex);
    if (! registryInstance) {
        contextDebug() << F_TYPES << "Creating ContextTypeRegistryInfo instance";
        registryInstance = new ContextTypeRegistryInfo;

        // Move the backend to the main thread
        registryInstance->moveToThread(QCoreApplication::instance()->thread());
    }

    return registryInstance;
}

/// Returns the full path to the registry directory. Takes the
/// \c CONTEXT_TYPES env variable into account.
QString ContextTypeRegistryInfo::registryPath()
{
    const char *regpath = getenv("CONTEXT_TYPES");
    if (! regpath)
        regpath = DEFAULT_CONTEXT_TYPES;

    return QString(regpath);
}

/// Returns the full path to the core property declaration file. Takes
/// the \c CONTEXT_CORE_TYPES env variable into account.
QString ContextTypeRegistryInfo::coreTypesPath()
{
    const char *corepath = getenv("CONTEXT_CORE_TYPES");
    if (! corepath)
        corepath = DEFAULT_CONTEXT_CORE_TYPES;

    return QString(corepath);
}

/// Returns a type definition for the type with the given name. The type
/// is being fetched from the registry.
AssocTree ContextTypeRegistryInfo::typeDefinitionForName(QString name)
{
    // Support for the old types
    if (name == "TRUTH")
        name = "bool";
    else if (name == "STRING")
        name = "string";
    else if (name == "INT")
        name = "integer";
    else if (name == "INTEGER")
        name = "integer";
    else if (name == "DOUBLE")
        name = "double";

    // Try using the cache first
    if (typeCache.contains(name))
        return typeCache.value(name);

    // No type in cache? Find it in the assoc tree and put in cache.
    Q_FOREACH (AssocTree typeTree, coreTree.nodes()) {
        if (typeTree.name() == "type" && typeTree.value("name") == name) {
            typeCache.insert(name, typeTree);
            return typeTree;
        }
    }

    // Not found. Return blank null type.
    return AssocTree();
}

/* Private */

/// Private constructor. Do not use.
ContextTypeRegistryInfo::ContextTypeRegistryInfo()
{
    if (QFile(ContextTypeRegistryInfo::coreTypesPath()).exists()) {
        contextDebug() << F_TYPES << "Reading core types from:" << ContextTypeRegistryInfo::coreTypesPath();

        NanoXml parser(ContextTypeRegistryInfo::coreTypesPath());
        if (parser.didFail())
            contextWarning() << F_TYPES << "Reading core types from" << ContextTypeRegistryInfo::coreTypesPath() << "failed, parsing error";
        else
            coreTree = parser.result();
    } else
        contextDebug() << F_TYPES << "Core types at" << ContextTypeRegistryInfo::coreTypesPath() << "missing.";
}