~azzar1/unity/scale-left-padding

« back to all changes in this revision

Viewing changes to plugins/unityshell/src/XPathQueryPart.cpp

  • Committer: Andrea Azzarone
  • Date: 2011-12-19 22:18:53 UTC
  • mfrom: (1792 unity)
  • mto: This revision was merged to the branch mainline in revision 1833.
  • Revision ID: azzaronea@gmail.com-20111219221853-wyy8fqwxk78s85ct
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
 
2
/*
 
3
 * Copyright (C) 2010 Canonical Ltd
 
4
 *
 
5
 * This program is free software: you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 3 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 *
 
17
 * Authored by: Thomi Richards <thomi.richards@canonical.com>
 
18
 */
 
19
 
 
20
#include <sstream>
 
21
#include <boost/algorithm/string.hpp>
 
22
#include <boost/algorithm/string/split.hpp>
 
23
#include <boost/algorithm/string/classification.hpp>
 
24
#include <boost/bind.hpp>
 
25
#include <NuxCore/Logger.h>
 
26
#include "XPathQueryPart.h"
 
27
#include "Introspectable.h"
 
28
 
 
29
namespace unity
 
30
{
 
31
 
 
32
namespace debug
 
33
{
 
34
namespace
 
35
{
 
36
  nux::logging::Logger logger("unity.debug.DebugDBusInterface");
 
37
}
 
38
 
 
39
// Stores a part of an XPath query.
 
40
XPathQueryPart::XPathQueryPart(std::string const& query_part)
 
41
{
 
42
  std::vector<std::string> part_pieces;
 
43
  boost::algorithm::split(part_pieces, query_part, boost::algorithm::is_any_of("[]="));
 
44
  // Boost's split() implementation does not match it's documentation! According to the 
 
45
  // docs, it's not supposed to add empty strings, but it does, which is a PITA. This 
 
46
  // next line removes them:
 
47
  part_pieces.erase( std::remove_if( part_pieces.begin(), 
 
48
                                      part_pieces.end(), 
 
49
                                      boost::bind( &std::string::empty, _1 ) ), 
 
50
                    part_pieces.end());
 
51
  if (part_pieces.size() == 1)
 
52
  {
 
53
    node_name_ = part_pieces.at(0);
 
54
  }
 
55
  else if (part_pieces.size() == 3)
 
56
  {
 
57
    node_name_ = part_pieces.at(0);
 
58
    param_name_ = part_pieces.at(1);
 
59
    param_value_ = part_pieces.at(2);
 
60
  }
 
61
  else
 
62
  {
 
63
    LOG_WARNING(logger) << "Malformed query part: " << query_part;
 
64
    // assume it's just a node name:
 
65
    node_name_ = query_part;
 
66
  }
 
67
}
 
68
 
 
69
bool XPathQueryPart::Matches(Introspectable* node) const
 
70
{
 
71
  bool matches = false;
 
72
  if (param_name_ == "")
 
73
  {
 
74
    matches = node->GetName() == node_name_;
 
75
  }
 
76
  else
 
77
  {
 
78
    GVariantBuilder  child_builder;
 
79
    g_variant_builder_init(&child_builder, G_VARIANT_TYPE("a{sv}"));
 
80
    node->AddProperties(&child_builder);
 
81
    GVariant* prop_dict = g_variant_builder_end(&child_builder);
 
82
    GVariant *prop_value = g_variant_lookup_value(prop_dict, param_name_.c_str(), NULL);
 
83
 
 
84
    if (prop_value != NULL)
 
85
    {
 
86
      GVariantClass prop_val_type = g_variant_classify(prop_value);
 
87
      // it'd be nice to be able to do all this with one method. However, the booleans need 
 
88
      // special treatment, and I can't figure out how to group all the integer types together
 
89
      // without resorting to template functions.... and we all know what happens when you 
 
90
      // start doing that...
 
91
      switch (prop_val_type)
 
92
      {
 
93
        case G_VARIANT_CLASS_STRING:
 
94
        {
 
95
          const gchar* prop_val = g_variant_get_string(prop_value, NULL);
 
96
          if (g_strcmp0(prop_val, param_value_.c_str()) == 0)
 
97
          {
 
98
            matches = true;
 
99
          }
 
100
        }
 
101
        break;
 
102
        case G_VARIANT_CLASS_BOOLEAN:
 
103
        {
 
104
          std::string value = boost::to_upper_copy(param_value_);
 
105
          bool p = value == "TRUE" ||
 
106
                    value == "ON" ||
 
107
                    value == "YES" ||
 
108
                    value == "1";
 
109
          matches = (g_variant_get_boolean(prop_value) == p);
 
110
        }
 
111
        break;
 
112
        case G_VARIANT_CLASS_BYTE:
 
113
        {
 
114
          // It would be nice if I could do all the integer types together, but I couldn't see how...
 
115
          std::stringstream stream(param_value_);
 
116
          int val; // changing this to guchar causes problems.
 
117
          stream >> val;
 
118
          matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && 
 
119
                    val == g_variant_get_byte(prop_value);
 
120
        }
 
121
        break;
 
122
        case G_VARIANT_CLASS_INT16:
 
123
        {
 
124
          std::stringstream stream(param_value_);
 
125
          gint16 val;
 
126
          stream >> val;
 
127
          matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && 
 
128
                    val == g_variant_get_int16(prop_value);
 
129
        }
 
130
        break;
 
131
        case G_VARIANT_CLASS_UINT16:
 
132
        {
 
133
          std::stringstream stream(param_value_);
 
134
          guint16 val;
 
135
          stream >> val;
 
136
          matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && 
 
137
                    val == g_variant_get_uint16(prop_value);            
 
138
        }
 
139
        break;
 
140
        case G_VARIANT_CLASS_INT32:
 
141
        {
 
142
          std::stringstream stream(param_value_);
 
143
          gint32 val;
 
144
          stream >> val;
 
145
          matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && 
 
146
                    val == g_variant_get_int32(prop_value);
 
147
        }
 
148
        break;
 
149
        case G_VARIANT_CLASS_UINT32:
 
150
        {
 
151
          std::stringstream stream(param_value_);
 
152
          guint32 val;
 
153
          stream >> val;
 
154
          matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && 
 
155
                    val == g_variant_get_uint32(prop_value);
 
156
        }
 
157
        break;
 
158
        case G_VARIANT_CLASS_INT64:
 
159
        {
 
160
          std::stringstream stream(param_value_);
 
161
          gint64 val;
 
162
          stream >> val;
 
163
          matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && 
 
164
                    val == g_variant_get_int64(prop_value);
 
165
        }
 
166
        break;
 
167
        case G_VARIANT_CLASS_UINT64:
 
168
        {
 
169
          std::stringstream stream(param_value_);
 
170
          guint64 val;
 
171
          stream >> val;
 
172
          matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && 
 
173
                    val == g_variant_get_uint64(prop_value);
 
174
        }
 
175
        break;
 
176
      default:
 
177
        LOG_WARNING(logger) << "Unable to match against property of unknown type.";
 
178
      };
 
179
    }
 
180
    g_variant_unref(prop_value);
 
181
    g_variant_unref(prop_dict);
 
182
  }
 
183
 
 
184
  return matches;
 
185
}
 
186
 
 
187
}
 
188
}