Merge lp:~michihenning/unity-scopes-api/scope-metadata into lp:unity-scopes-api

Proposed by Michi Henning
Status: Merged
Approved by: Michal Hruby
Approved revision: 78
Merged at revision: 75
Proposed branch: lp:~michihenning/unity-scopes-api/scope-metadata
Merge into: lp:unity-scopes-api
Diff against target: 3520 lines (+1636/-438)
91 files modified
STRUCTS (+16/-3)
demo/CMakeLists.txt (+0/-1)
demo/Factory.ini.in (+0/-2)
demo/Zmq.ini.in (+1/-1)
demo/client.cpp (+43/-5)
demo/scopes/scope-A/scope-A.cpp (+0/-1)
demo/scopes/scope-A/scope-A.ini.in (+6/-0)
demo/scopes/scope-B/scope-B.cpp (+4/-4)
demo/scopes/scope-B/scope-B.ini.in (+2/-0)
demo/scopes/scope-C/scope-C.ini.in (+2/-0)
demo/scopes/scope-D/scope-D.ini.in (+2/-0)
demo/scopes/scope-N/scope-N.cpp (+0/-1)
demo/scopes/scope-N/scope-N.ini.in (+2/-0)
demo/scopes/scope-S/scope-S.cpp (+0/-1)
demo/scopes/scope-S/scope-S.ini.in (+2/-0)
include/scopes/ObjectProxy.h (+3/-0)
include/scopes/Registry.h (+19/-12)
include/scopes/ResultItem.h (+1/-1)
include/scopes/Runtime.h (+6/-6)
include/scopes/ScopeMetadata.h (+78/-0)
include/scopes/internal/ConfigBase.h (+2/-0)
include/scopes/internal/MWObjectProxy.h (+3/-2)
include/scopes/internal/MWRegistry.h (+3/-2)
include/scopes/internal/MiddlewareBase.h (+3/-0)
include/scopes/internal/MiddlewareFactory.h (+1/-1)
include/scopes/internal/MiddlewareFactoryConfig.h (+0/-60)
include/scopes/internal/ObjectProxyImpl.h (+6/-3)
include/scopes/internal/RegistryImpl.h (+3/-2)
include/scopes/internal/RegistryObject.h (+7/-9)
include/scopes/internal/RuntimeConfig.h (+1/-1)
include/scopes/internal/RuntimeImpl.h (+1/-1)
include/scopes/internal/ScopeConfig.h (+13/-1)
include/scopes/internal/ScopeMetadataImpl.h (+94/-0)
include/scopes/internal/zmq_middleware/RegistryI.h (+1/-1)
include/scopes/internal/zmq_middleware/RequestType.h (+1/-1)
include/scopes/internal/zmq_middleware/ZmqConfig.h (+1/-4)
include/scopes/internal/zmq_middleware/ZmqMiddleware.h (+2/-0)
include/scopes/internal/zmq_middleware/ZmqObjectProxy.h (+2/-32)
include/scopes/internal/zmq_middleware/ZmqRegistry.h (+2/-2)
scoperegistry/scoperegistry.cpp (+77/-18)
scoperunner/scoperunner.cpp (+1/-6)
src/CMakeLists.txt (+1/-0)
src/ObjectProxy.cpp (+12/-0)
src/ReceiverBase.cpp (+2/-1)
src/Registry.cpp (+8/-3)
src/Runtime.cpp (+0/-2)
src/ScopeMetadata.cpp (+123/-0)
src/internal/CMakeLists.txt (+1/-1)
src/internal/ConfigBase.cpp (+26/-9)
src/internal/MiddlewareFactory.cpp (+1/-12)
src/internal/ObjectProxyImpl.cpp (+10/-0)
src/internal/RegistryImpl.cpp (+17/-3)
src/internal/RegistryObject.cpp (+12/-11)
src/internal/ResultItemImpl.cpp (+3/-7)
src/internal/RuntimeConfig.cpp (+23/-16)
src/internal/RuntimeImpl.cpp (+1/-2)
src/internal/ScopeConfig.cpp (+91/-0)
src/internal/ScopeImpl.cpp (+1/-0)
src/internal/ScopeMetadataImpl.cpp (+325/-0)
src/internal/zmq_middleware/RegistryI.cpp (+18/-23)
src/internal/zmq_middleware/ZmqConfig.cpp (+10/-9)
src/internal/zmq_middleware/ZmqMiddleware.cpp (+14/-0)
src/internal/zmq_middleware/ZmqObject.cpp (+11/-0)
src/internal/zmq_middleware/ZmqRegistry.cpp (+29/-22)
src/internal/zmq_middleware/capnproto/Registry.capnp (+7/-7)
test/gtest/unity/api/scopes/ResultItem/ResultItem_test.cpp (+9/-0)
test/gtest/unity/api/scopes/Runtime/CMakeLists.txt (+0/-1)
test/gtest/unity/api/scopes/Runtime/Factory.ini.in (+0/-2)
test/gtest/unity/api/scopes/Variant/Variant_test.cpp (+3/-0)
test/gtest/unity/api/scopes/internal/CMakeLists.txt (+1/-1)
test/gtest/unity/api/scopes/internal/MiddlewareFactory/CMakeLists.txt (+0/-2)
test/gtest/unity/api/scopes/internal/MiddlewareFactory/Factory.ini.in (+0/-3)
test/gtest/unity/api/scopes/internal/MiddlewareFactory/MiddlewareFactory_test.cpp (+5/-22)
test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/CMakeLists.txt (+0/-6)
test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/Factory.ini.in (+0/-3)
test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/MiddlewareFactoryConfig_test.cpp (+0/-31)
test/gtest/unity/api/scopes/internal/RuntimeConfig/RuntimeConfig_test.cpp (+1/-1)
test/gtest/unity/api/scopes/internal/RuntimeImpl/CMakeLists.txt (+0/-1)
test/gtest/unity/api/scopes/internal/RuntimeImpl/Factory.ini.in (+0/-2)
test/gtest/unity/api/scopes/internal/RuntimeImpl/RuntimeImpl_test.cpp (+0/-6)
test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/CMakeLists.txt (+6/-0)
test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp (+388/-0)
test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/Zmq.ini.in (+3/-0)
test/gtest/unity/api/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini.in (+1/-0)
test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/CMakeLists.txt (+0/-1)
test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Factory.ini.in (+0/-3)
test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp (+58/-41)
test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Zmq.ini.in (+1/-0)
test/gtest/unity/api/scopes/internal/zmq_middleware/ServantBase/Zmq.ini.in (+1/-0)
test/gtest/unity/api/scopes/internal/zmq_middleware/ZmqMiddleware/Zmq.ini.in (+1/-0)
test/gtest/unity/api/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp (+1/-0)
To merge this branch: bzr merge lp:~michihenning/unity-scopes-api/scope-metadata
Reviewer Review Type Date Requested Status
Michal Hruby (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Paweł Stołowski (community) Needs Information
Review via email: mp+197005@code.launchpad.net

Commit message

Added scope metadata to config and registry. Optional fields that are not set throw on an attempt to access them. This allows us to distinguish "not set all" from "set to default value".

Simplified configuration. Factory.ini no longer exists. Client can now run without Runtime.ini, but still needs Registry.ini and Zmq.ini. (It looks for those in the current directory.) Will fix this next.

Various minor clean-up in tests and doc comments.

Description of the change

Added scope metadata to config and registry. Optional fields that are not set throw on an attempt to access them. This allows us to distinguish "not set all" from "set to default value".

Simplified configuration. Factory.ini no longer exists. Client can now run without Runtime.ini, but still needs Registry.ini and Zmq.ini. (It looks for those in the current directory.) Will fix this next.

Various minor clean-up in tests and doc comments.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michal Hruby (mhr3) wrote :

295 + ScopeMetadata find(std::string const& scope_name) const;

As we discussed can we please rename this to get_metadata()? find() throwing an exception if something is not found feels as if a contains() method threw an exception if a container doesn't contain the item.

25 + 'art' : string

I don't think we want "art" in categories too, "art" is called art for results because they can be camera pictures, product images, comic strips... anything. A category should indeed have an "icon", not a picture of your friends.

31 + 'art' : string

For scope metadata, I think we should have both art and icon - art would be used for the branded scope pages, and icons for the navigation bar (both optional I suppose).

review: Needs Fixing
Revision history for this message
Michal Hruby (mhr3) wrote :

2134 +dictionary<string, VariantMap> ScopeMap;

Got me really confused, we do have ScopeMap in the public API, perhaps using a different name would make things clearer.

Revision history for this message
Michal Hruby (mhr3) wrote :

399 +class UNITY_API ScopeMetadata final

No UNITY_DEFINES_PTRS for ScopeMetadata?

Revision history for this message
Michi Henning (michihenning) wrote :

Thanks for the feedback, I agree with all of this. Will change!

Sorry about the "art" thing. I noticed that ResultItem had changed from "icon" to "arg" and figured we had better be consistent. My misunderstanding...

Revision history for this message
Paweł Stołowski (stolowski) wrote :

2857 +TEST(ScopeMetadataImpl, serialize_exceptions)
2858 +{
2859 + ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/unity/api/scopes/internal/ScopeMetadataImpl/Zmq.ini",
2860 + (RuntimeImpl*)0x1);
2861 +
2862 + ScopeMetadataImpl mi(&mw);
2863 + try
2864 + {
2865 + mi.serialize();
2866 + }
2867 + catch (InvalidArgumentException const&e)
2868 + {
2869 + EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadata: required attribute 'scope_name' is empty",
2870 + e.to_string());
2871 + }

Those kind of test should check if the exception was actually thrown.

review: Needs Fixing
Revision history for this message
Paweł Stołowski (stolowski) wrote :

Since ScopeMetadataImpl::serialize() can throw InvalidArgumentException (on empty scope_name or art), is it OK that we don't catch it in RegistryI::find_() and RegistryI::list_()? Also, only for NotFoundException in find_() we set status to (capnproto::ResponseStatus::USER_EXCEPTION), otherwise it is capnproto::ResponseStatus::SUCCESS in both find_() and list_(), is this intended?

I'm sorry, I couldn't easily find out how the exceptions propagate, but from the observation Michal and I have it seems that if "art" attribute of ScopeMetadata is empty (and the assert on that is removed from ctor, which is the case in release code), then the problem is only discovered in deserialize() in the client code, not in the serialize() on registry side, e.g. client gives:

./client A a
unity::api::scopes::MiddlewareException: unity::InvalidArgumentException: ScopeMetadata: required attribute 'art' is empty

review: Needs Information
Revision history for this message
Michi Henning (michihenning) wrote :

> Those kind of test should check if the exception was actually thrown.

Thanks for catching this! I've just added the missing FAIL() statements.

Revision history for this message
Michi Henning (michihenning) wrote :

> Since ScopeMetadataImpl::serialize() can throw InvalidArgumentException (on
> empty scope_name or art), is it OK that we don't catch it in
> RegistryI::find_() and RegistryI::list_()? Also, only for NotFoundException in
> find_() we set status to (capnproto::ResponseStatus::USER_EXCEPTION),
> otherwise it is capnproto::ResponseStatus::SUCCESS in both find_() and
> list_(), is this intended?

Yes, that's OK. Not all exceptions are marshalled as specific exception types over the wire. If the implementation of a method throws something that isn't expected as an exception that is to be marshalled, that is caught in safe_dispatch_() in ServantBase, and the exception response will be UNKNOWN_EXCEPTION over the wire.

> I'm sorry, I couldn't easily find out how the exceptions propagate, but from
> the observation Michal and I have it seems that if "art" attribute of
> ScopeMetadata is empty (and the assert on that is removed from ctor, which is
> the case in release code), then the problem is only discovered in
> deserialize() in the client code, not in the serialize() on registry side,
> e.g. client gives:
>
> ./client A a
> unity::api::scopes::MiddlewareException: unity::InvalidArgumentException:
> ScopeMetadata: required attribute 'art' is empty

From a previous message from Michal, both art and icon should be optional:

> For scope metadata, I think we should have both art and icon - art would be used for the branded > scope pages, and icons for the navigation bar (both optional I suppose).

That's what I implemented (and what I'm about to push).

73. By Michi Henning

Renamed ScopeMap -> MetadataMap

74. By Michi Henning

Added Ptr definitions to ScopeMetadata.

75. By Michi Henning

Renamed find() -> get_metadata()

76. By Michi Henning

Added icon attribute to ScopeMetadata and made art attribute optional.

77. By Michi Henning

Addming missing FAIL() calls for tests that expect an exception when no exception is in fact thrown.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Paweł Stołowski (stolowski) wrote :

1828 + // For optional values, we store them in a unique_ptr so we can distinguish the "not set at all" case
1829 + // from the "explicitly set to empty string" case.
1830 + try
1831 + {
1832 + string art = parser()->get_string(SCOPE_CONFIG_GROUP, art_str);
1833 + art_.reset(new string(art));
1834 + }
1835 + catch (LogicException const&)
1836 + {
1837 + }

Just a small nitpick - can you a add comment saying that these exceptions are ignored deliberately as they are for optional values? Otherwise looking good to me.

Revision history for this message
Michal Hruby (mhr3) wrote :

20 +Category (returned by serialize()):

Missing the new 'art'.

431 + std::string localized_name() const; // localized

Shouldn't this be just "name()"? I don't think we want i18n details to be visible in the API, do we? Also for consistency we'd then want "localized_description()", "locallized_search_hint()" etc. Was the concern that if it was just a "name()", it'd be confusing to have both name() and scope_name()? If so, perhaps we should rename the scope_name() to scope_id()? Afterall it's a unique id, isn't it?

689 + bool add(std::string const& scope_name, ScopeMetadata const scope);

Passing metadata by value? Is that desired?

review: Needs Fixing
Revision history for this message
Michi Henning (michihenning) wrote :

> Just a small nitpick - can you a add comment saying that these exceptions are ignored
> deliberately as they are for optional values? Otherwise looking good to me.

Fixed, thanks!

> 20 +Category (returned by serialize()):
>
> Missing the new 'art'.

Are you sure about this? Categories don't have art, as far as I can see.

> 431 + std::string localized_name() const; // localized
>
> Shouldn't this be just "name()"? I don't think we want i18n details to be
> visible in the API, do we? Also for consistency we'd then want
> "localized_description()", "locallized_search_hint()" etc. Was the concern
> that if it was just a "name()", it'd be confusing to have both name() and
> scope_name()? If so, perhaps we should rename the scope_name() to scope_id()?
> Afterall it's a unique id, isn't it?

Yes. Unfortunately, renaming "scope_name' to "scope_id" would be rather disruptive. It's all through the existing code. How about "display_name" for what is now "localised_name"? That would be much less intrusive a change.

> 689 + bool add(std::string const& scope_name, ScopeMetadata const
> scope);
>
> Passing metadata by value? Is that desired?

Yes, that was intentional. It's a sink function, and the implementation moves the value into place in the map. There are a few corner cases where that avoids a copy. But then, the efficiency gain is minor and basically not noticeable, so I changed it to const reference for consistency.

Please let me know about the "display_name" suggestion.

Revision history for this message
Michi Henning (michihenning) wrote :

Come to think of it, just "name" would work too, I think.

Revision history for this message
Michal Hruby (mhr3) wrote :

> > 20 +Category (returned by serialize()):
> >
> > Missing the new 'art'.
>
> Are you sure about this? Categories don't have art, as far as I can see.

Ah, right, that's for scopes themselves, nevermind then.

> > 431 + std::string localized_name() const; // localized
> >
> > Shouldn't this be just "name()"? I don't think we want i18n details to be
> > visible in the API, do we? Also for consistency we'd then want
> > "localized_description()", "locallized_search_hint()" etc. Was the concern
> > that if it was just a "name()", it'd be confusing to have both name() and
> > scope_name()? If so, perhaps we should rename the scope_name() to
> scope_id()?
> > Afterall it's a unique id, isn't it?
>
> Yes. Unfortunately, renaming "scope_name' to "scope_id" would be rather
> disruptive. It's all through the existing code. How about "display_name" for
> what is now "localised_name"? That would be much less intrusive a change.
>

display_name() works for me.

78. By Michi Henning

Changed localized_name to display_name. Improved comment for catching exceptions for optional attributes.

Revision history for this message
Michal Hruby (mhr3) wrote :

LGTM.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'STRUCTS'
2--- STRUCTS 2013-11-18 11:32:10 +0000
3+++ STRUCTS 2013-12-03 14:09:20 +0000
4@@ -19,22 +19,35 @@
5 middleware.
6 -----------------------------------------------------------------------------
7
8-ResultItem (returned by variant_map()):
9+ResultItem (returned by serialize()):
10 =======================================
11 'uri' : string
12 'title' : string
13- 'icon' : string
14+ 'art' : string
15 'dnd_uri' : string
16 'cat_id' : string
17 + any custom key-value attribute added by scope author.
18
19-Category (returned by variant_map()):
20+Category (returned by serialize()):
21 =====================================
22 'id' : string
23 'title' : string
24 'icon' : string
25 'renderer_template' : string
26
27+ScopeMetadata (returned by serialize()):
28+=====================================
29+ 'scope_name' : string
30+ 'proxy' : dictionary
31+ 'identity' : string
32+ 'endpoint' : string
33+ 'display_name' : string
34+ 'description' : string
35+ 'art' : string, optional
36+ 'icon' : string, optional
37+ 'search_hint' : string, optional
38+ 'hot_key' : string, optional
39+
40 PushRequest (capnproto structure)
41 =================================
42 result : ValueDict with "category" and/or "result" key and serialized Category / ResultItem respectively.
43
44=== modified file 'demo/CMakeLists.txt'
45--- demo/CMakeLists.txt 2013-11-19 02:51:46 +0000
46+++ demo/CMakeLists.txt 2013-12-03 14:09:20 +0000
47@@ -1,7 +1,6 @@
48 add_subdirectory(scopes)
49 add_subdirectory(scope-groups)
50
51-configure_file(Factory.ini.in Factory.ini)
52 configure_file(Runtime.ini.in Runtime.ini)
53 configure_file(Registry.ini.in Registry.ini)
54 configure_file(Zmq.ini.in Zmq.ini)
55
56=== removed file 'demo/Factory.ini.in'
57--- demo/Factory.ini.in 2013-11-19 02:51:46 +0000
58+++ demo/Factory.ini.in 1970-01-01 00:00:00 +0000
59@@ -1,2 +0,0 @@
60-[MiddlewareFactory]
61-Zmq.Configfile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini
62
63=== modified file 'demo/Zmq.ini.in'
64--- demo/Zmq.ini.in 2013-11-19 02:51:46 +0000
65+++ demo/Zmq.ini.in 2013-12-03 14:09:20 +0000
66@@ -1,3 +1,3 @@
67 [Zmq]
68 EndpointDir.Public = /tmp
69-EndpointDir.Private = @CMAKE_CURRENT_BINARY_DIR@
70+EndpointDir.Private = /tmp
71
72=== modified file 'demo/client.cpp'
73--- demo/client.cpp 2013-11-26 16:08:29 +0000
74+++ demo/client.cpp 2013-12-03 14:09:20 +0000
75@@ -16,12 +16,13 @@
76 * Authored by: Michi Henning <michi.henning@canonical.com>
77 */
78
79+#include <scopes/CategoryRenderer.h>
80 #include <scopes/QueryCtrl.h>
81 #include <scopes/Registry.h>
82 #include <scopes/ReceiverBase.h>
83 #include <scopes/Runtime.h>
84 #include <scopes/ResultItem.h>
85-#include <scopes/CategoryRenderer.h>
86+#include <scopes/ScopeExceptions.h>
87 #include <unity/UnityExceptions.h>
88
89 #include <condition_variable>
90@@ -91,15 +92,52 @@
91 Runtime::UPtr rt = Runtime::create("dash");
92
93 RegistryProxy r = rt->registry();
94- ScopeProxy s = r->find(scope_name);
95+ auto meta = r->get_metadata(scope_name);
96+ cout << "Scope metadata: " << endl;
97+ cout << "\tscope_name: " << meta.scope_name() << endl;
98+ cout << "\tdisplay_name: " << meta.display_name() << endl;
99+ cout << "\tdescription: " << meta.description() << endl;
100+ string tmp;
101+ try
102+ {
103+ tmp = meta.art();
104+ cout << "\tart: " << meta.art() << endl;
105+ }
106+ catch (NotFoundException const& e)
107+ {
108+ }
109+ try
110+ {
111+ tmp = meta.icon();
112+ cout << "\ticon: " << meta.icon() << endl;
113+ }
114+ catch (NotFoundException const& e)
115+ {
116+ }
117+ try
118+ {
119+ tmp = meta.search_hint();
120+ cout << "\tsearch_hint: " << meta.search_hint() << endl;
121+ }
122+ catch (NotFoundException const& e)
123+ {
124+ }
125+ try
126+ {
127+ tmp = meta.hot_key();
128+ cout << "\thot_key: " << meta.hot_key() << endl;
129+ }
130+ catch (NotFoundException const& e)
131+ {
132+ }
133 shared_ptr<Receiver> reply(new Receiver);
134 VariantMap vm;
135 vm["cardinality"] = 10;
136 vm["locale"] = "C";
137- auto ctrl = s->create_query(search_string, vm, reply); // Returns (almost) immediately
138- cerr << "client: created query" << endl;
139+ auto ctrl = meta.proxy()->create_query(search_string, vm, reply); // Returns (almost) immediately
140+ cout << "client: created query" << endl;
141 reply->wait_until_finished();
142- cerr << "client: wait returned" << endl;
143+ cout << "client: wait returned" << endl;
144 }
145
146 catch (unity::Exception const& e)
147
148=== modified file 'demo/scopes/scope-A/scope-A.cpp'
149--- demo/scopes/scope-A/scope-A.cpp 2013-11-26 16:08:29 +0000
150+++ demo/scopes/scope-A/scope-A.cpp 2013-12-03 14:09:20 +0000
151@@ -73,7 +73,6 @@
152 }
153
154 virtual void stop() override {}
155- virtual void run() override {}
156
157 virtual QueryBase::UPtr create_query(string const& q, VariantMap const&) override
158 {
159
160=== modified file 'demo/scopes/scope-A/scope-A.ini.in'
161--- demo/scopes/scope-A/scope-A.ini.in 2013-11-19 02:51:46 +0000
162+++ demo/scopes/scope-A/scope-A.ini.in 2013-12-03 14:09:20 +0000
163@@ -1,1 +1,7 @@
164 [ScopeConfig]
165+DisplayName = scope-A.DisplayName
166+Description = scope-A.Description
167+Art = scope-A.Art
168+Icon = scope-A.Icon
169+SearchHint = scope-A.SearchHint
170+HotKey = scope-A.HotKey
171
172=== modified file 'demo/scopes/scope-B/scope-B.cpp'
173--- demo/scopes/scope-B/scope-B.cpp 2013-11-26 16:08:29 +0000
174+++ demo/scopes/scope-B/scope-B.cpp 2013-12-03 14:09:20 +0000
175@@ -128,16 +128,16 @@
176 scope_name_ = scope_name;
177
178 // Lock up scopes C and D in the registry and remember their proxies.
179- scope_c_ = registry->find("scope-C");
180- scope_d_ = registry->find("scope-D");
181+ auto meta_c = registry->get_metadata("scope-C");
182+ scope_c_ = meta_c.proxy();
183+ auto meta_d = registry->get_metadata("scope-D");
184+ scope_d_ = meta_d.proxy();
185
186 return VERSION;
187 }
188
189 virtual void stop() override {}
190
191- virtual void run() override {}
192-
193 virtual QueryBase::UPtr create_query(string const& q, VariantMap const&) override
194 {
195 QueryBase::UPtr query(new MyQuery(scope_name_, q, scope_c_, scope_d_));
196
197=== modified file 'demo/scopes/scope-B/scope-B.ini.in'
198--- demo/scopes/scope-B/scope-B.ini.in 2013-11-19 02:51:46 +0000
199+++ demo/scopes/scope-B/scope-B.ini.in 2013-12-03 14:09:20 +0000
200@@ -1,1 +1,3 @@
201 [ScopeConfig]
202+DisplayName = scope-B.DisplayName
203+Description = scope-B.Description
204
205=== modified file 'demo/scopes/scope-C/scope-C.ini.in'
206--- demo/scopes/scope-C/scope-C.ini.in 2013-11-19 02:51:46 +0000
207+++ demo/scopes/scope-C/scope-C.ini.in 2013-12-03 14:09:20 +0000
208@@ -1,1 +1,3 @@
209 [ScopeConfig]
210+DisplayName = scope-C.DisplayName
211+Description = scope-C.Description
212
213=== modified file 'demo/scopes/scope-D/scope-D.ini.in'
214--- demo/scopes/scope-D/scope-D.ini.in 2013-11-19 02:51:46 +0000
215+++ demo/scopes/scope-D/scope-D.ini.in 2013-12-03 14:09:20 +0000
216@@ -1,1 +1,3 @@
217 [ScopeConfig]
218+DisplayName = scope-D.DisplayName
219+Description = scope-D.Description
220
221=== modified file 'demo/scopes/scope-N/scope-N.cpp'
222--- demo/scopes/scope-N/scope-N.cpp 2013-11-21 21:44:00 +0000
223+++ demo/scopes/scope-N/scope-N.cpp 2013-12-03 14:09:20 +0000
224@@ -62,7 +62,6 @@
225 }
226
227 virtual void stop() override {}
228- virtual void run() override {}
229
230 virtual QueryBase::UPtr create_query(string const&, VariantMap const&) override
231 {
232
233=== modified file 'demo/scopes/scope-N/scope-N.ini.in'
234--- demo/scopes/scope-N/scope-N.ini.in 2013-11-19 02:51:46 +0000
235+++ demo/scopes/scope-N/scope-N.ini.in 2013-12-03 14:09:20 +0000
236@@ -1,1 +1,3 @@
237 [ScopeConfig]
238+DisplayName = scope-N.DisplayName
239+Description = scope-N.Description
240
241=== modified file 'demo/scopes/scope-S/scope-S.cpp'
242--- demo/scopes/scope-S/scope-S.cpp 2013-11-26 16:08:29 +0000
243+++ demo/scopes/scope-S/scope-S.cpp 2013-12-03 14:09:20 +0000
244@@ -77,7 +77,6 @@
245 }
246
247 virtual void stop() override {}
248- virtual void run() override {}
249
250 virtual QueryBase::UPtr create_query(string const& q, VariantMap const& hints) override
251 {
252
253=== modified file 'demo/scopes/scope-S/scope-S.ini.in'
254--- demo/scopes/scope-S/scope-S.ini.in 2013-11-19 02:51:46 +0000
255+++ demo/scopes/scope-S/scope-S.ini.in 2013-12-03 14:09:20 +0000
256@@ -1,1 +1,3 @@
257 [ScopeConfig]
258+DisplayName = scope-S.DisplayName
259+Description = scope-S.Description
260
261=== modified file 'include/scopes/ObjectProxy.h'
262--- include/scopes/ObjectProxy.h 2013-11-25 19:05:41 +0000
263+++ include/scopes/ObjectProxy.h 2013-12-03 14:09:20 +0000
264@@ -42,6 +42,9 @@
265 ObjectProxy();
266 virtual ~ObjectProxy() noexcept;
267
268+ std::string endpoint() const;
269+ std::string identity() const;
270+
271 protected:
272 internal::ObjectProxyImpl* pimpl() const noexcept; // Non-virtual because we can't use covariance with incomplete types
273 // Each derived proxy type implements a non-virtual fwd() method
274
275=== modified file 'include/scopes/Registry.h'
276--- include/scopes/Registry.h 2013-11-25 19:05:41 +0000
277+++ include/scopes/Registry.h 2013-12-03 14:09:20 +0000
278@@ -21,7 +21,7 @@
279
280 #include <scopes/ObjectProxy.h>
281 #include <scopes/RegistryProxyFwd.h>
282-#include <scopes/Scope.h>
283+#include <scopes/ScopeMetadata.h>
284
285 #include <map>
286
287@@ -40,9 +40,9 @@
288 }
289
290 /**
291-\brief Map for scope name and proxy pairs.
292+\brief Map for scope name and metadata pairs.
293 */
294-typedef std::map<std::string, ScopeProxy> ScopeMap;
295+typedef std::map<std::string, ScopeMetadata> MetadataMap;
296
297 /**
298 \brief RegistryProxy provides access to the available scopes.
299@@ -57,15 +57,22 @@
300 /// @endcond
301
302 /**
303- \brief Returns a ScopeProxy for the scope with the given name.
304- @return If no scope with the given name exists, find() throws NotFoundException.
305- */
306- ScopeProxy find(std::string const& scope_name) const;
307-
308- /**
309- \brief Returns a map containing the name/proxy pairs for all available scopes.
310- */
311- ScopeMap list() const;
312+ \brief Returns the metadata for the scope with the given name.
313+ @return The metadata for the scope. If no scope with the given name exists, get_metadata() throws NotFoundException.
314+ */
315+ ScopeMetadata get_metadata(std::string const& scope_name) const;
316+
317+ /**
318+ \brief Returns a map containing the metadata for all scopes.
319+ */
320+ MetadataMap list() const;
321+
322+ /**
323+ \brief Returns a map containing only those scopes for which predicate returns true.
324+ \param predicate a function object the must return true for each metadata item to be include in the map.
325+ \return The metadata items for which the predicate returned true.
326+ */
327+ MetadataMap list_if(std::function<bool(ScopeMetadata const& item)> predicate) const;
328
329 protected:
330 Registry(internal::RegistryImpl* impl); // Instantiated only by RegistryImpl
331
332=== modified file 'include/scopes/ResultItem.h'
333--- include/scopes/ResultItem.h 2013-11-27 02:08:11 +0000
334+++ include/scopes/ResultItem.h 2013-12-03 14:09:20 +0000
335@@ -87,7 +87,7 @@
336
337 /**
338 \brief Returns a dictionary of all attributes of this ResultItem instance.
339- \return dictionary of all base attributes and custom attributes set with add_metadata call.
340+ \return Dictionary of all base attributes and custom attributes set with add_metadata call.
341 */
342 VariantMap serialize() const;
343
344
345=== modified file 'include/scopes/Runtime.h'
346--- include/scopes/Runtime.h 2013-11-25 16:22:12 +0000
347+++ include/scopes/Runtime.h 2013-12-03 14:09:20 +0000
348@@ -58,11 +58,6 @@
349 /// @endcond
350
351 /**
352- \brief The default configuration file (relative to the current directory) if none is passed to create().
353- */
354- static constexpr char const* DFLT_CONFIGFILE = "Runtime.ini";
355-
356- /**
357 \brief Instantiates the scopes run time for the scope with the given name and (optional) configuration file.
358
359 The life time of the run time is under control of the caller. Letting the returned `unique_ptr` go out
360@@ -71,8 +66,13 @@
361 You _must not_ create a Runtime instance until after `main()` is entered, and you _must_ destroy it
362 before leaving `main()` (either by explicitly calling destroy(), or by letting the returned
363 `unique_ptr` go out of scope). Failure to do so causes undefined behavior.
364+
365+ \param configfile The path name of the configuration file to use.
366+
367+ If configfile is the empty string, a default configuration is used.
368 */
369- static UPtr create(std::string const& scope_name, std::string const& configfile = DFLT_CONFIGFILE);
370+ // TODO: Update above to state what the default configuration is exactly
371+ static UPtr create(std::string const& scope_name, std::string const& configfile = "");
372
373 /**
374 \brief Shuts down the run time, reclaiming all associated resources.
375
376=== added file 'include/scopes/ScopeMetadata.h'
377--- include/scopes/ScopeMetadata.h 1970-01-01 00:00:00 +0000
378+++ include/scopes/ScopeMetadata.h 2013-12-03 14:09:20 +0000
379@@ -0,0 +1,78 @@
380+/*
381+ * Copyright (C) 2013 Canonical Ltd
382+ *
383+ * This program is free software: you can redistribute it and/or modify
384+ * it under the terms of the Lesser GNU General Public License version 3 as
385+ * published by the Free Software Foundation.
386+ *
387+ * This program is distributed in the hope that it will be useful,
388+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
389+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
390+ * GNU Lesser General Public License for more details.
391+ *
392+ * You should have received a copy of the GNU Lesser General Public License
393+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
394+ *
395+ * Authored by: Michi Henning <michi.henning@canonical.com>
396+ */
397+
398+#ifndef UNITY_API_SCOPES_SCOPEMETADATA_H
399+#define UNITY_API_SCOPES_SCOPEMETADATA_H
400+
401+#include <scopes/Scope.h>
402+
403+namespace unity
404+{
405+
406+namespace api
407+{
408+
409+namespace scopes
410+{
411+
412+namespace internal
413+{
414+class ScopeMetadataImpl;
415+} // namespace internal
416+
417+class UNITY_API ScopeMetadata final
418+{
419+public:
420+ UNITY_DEFINES_PTRS(ScopeMetadata);
421+
422+ ScopeMetadata(ScopeMetadata const& other);
423+ ScopeMetadata(ScopeMetadata&&);
424+ ~ScopeMetadata();
425+
426+ ScopeMetadata& operator=(ScopeMetadata const& other);
427+ ScopeMetadata& operator=(ScopeMetadata&&);
428+
429+ std::string scope_name() const;
430+ ScopeProxy proxy() const;
431+ std::string display_name() const; // localized
432+ std::string description() const; // localized
433+ std::string art() const; // optional
434+ std::string icon() const; // optional
435+ std::string search_hint() const; // localized, optional
436+ std::string hot_key() const; // localized, optional
437+
438+ /**
439+ \brief Returns a dictionary of all attributes of this ScopeMetadata instance.
440+ \return Dictionary of all metadata attributes.
441+ */
442+ VariantMap serialize() const;
443+
444+private:
445+ ScopeMetadata(std::unique_ptr<internal::ScopeMetadataImpl>); // Instantiable only by ScopeMetadataImpl
446+ std::unique_ptr<internal::ScopeMetadataImpl> p;
447+
448+ friend class internal::ScopeMetadataImpl;
449+};
450+
451+} // namespace scopes
452+
453+} // namespace api
454+
455+} // namespace unity
456+
457+#endif
458
459=== modified file 'include/scopes/internal/ConfigBase.h'
460--- include/scopes/internal/ConfigBase.h 2013-11-21 21:44:00 +0000
461+++ include/scopes/internal/ConfigBase.h 2013-12-03 14:09:20 +0000
462@@ -41,6 +41,7 @@
463 class ConfigBase
464 {
465 public:
466+ ConfigBase();
467 ConfigBase(std::string const& configfile);
468 virtual ~ConfigBase() noexcept;
469
470@@ -53,6 +54,7 @@
471 virtual void throw_ex(::std::string const& reason) const;
472
473 private:
474+ unity::util::IniParser::SPtr p() const;
475 unity::util::IniParser::SPtr parser_;
476 std::string configfile_;
477 };
478
479=== modified file 'include/scopes/internal/MWObjectProxy.h'
480--- include/scopes/internal/MWObjectProxy.h 2013-11-21 21:44:00 +0000
481+++ include/scopes/internal/MWObjectProxy.h 2013-12-03 14:09:20 +0000
482@@ -37,8 +37,6 @@
483
484 // Base class for the MW<something>Proxy hierarchy. We store the pointer to the middleware here,
485 // which is needed to, for example, register callback objects (such as a Reply object) with the middleware.
486-// We also keep a pointer to the run time, so we can get at other relevant deatils, such as a scope name,
487-// reply object reaper, etc.
488
489 class MWObjectProxy
490 {
491@@ -47,6 +45,9 @@
492
493 virtual MiddlewareBase* mw_base() const noexcept = 0;
494
495+ virtual std::string identity() const = 0;
496+ virtual std::string endpoint() const = 0;
497+
498 protected:
499 MWObjectProxy(MiddlewareBase* mw_base);
500
501
502=== modified file 'include/scopes/internal/MWRegistry.h'
503--- include/scopes/internal/MWRegistry.h 2013-11-25 16:22:12 +0000
504+++ include/scopes/internal/MWRegistry.h 2013-12-03 14:09:20 +0000
505@@ -21,6 +21,7 @@
506
507 #include <scopes/internal/MWObjectProxy.h>
508 #include <scopes/Registry.h>
509+#include <scopes/ScopeMetadata.h>
510
511 namespace unity
512 {
513@@ -38,8 +39,8 @@
514 {
515 public:
516 // Remote operation implementation
517- virtual ScopeProxy find(std::string const& scope_name) = 0;
518- virtual ScopeMap list() = 0;
519+ virtual ScopeMetadata get_metadata(std::string const& scope_name) = 0;
520+ virtual MetadataMap list() = 0;
521
522 virtual ~MWRegistry() noexcept;
523
524
525=== modified file 'include/scopes/internal/MiddlewareBase.h'
526--- include/scopes/internal/MiddlewareBase.h 2013-11-21 21:44:00 +0000
527+++ include/scopes/internal/MiddlewareBase.h 2013-12-03 14:09:20 +0000
528@@ -19,6 +19,7 @@
529 #ifndef UNITY_API_SCOPES_INTERNAL_MIDDLEWAREBASE_H
530 #define UNITY_API_SCOPES_INTERNAL_MIDDLEWAREBASE_H
531
532+#include <scopes/internal/MWObjectProxyFwd.h>
533 #include <scopes/internal/MWQueryCtrlProxyFwd.h>
534 #include <scopes/internal/MWQueryProxyFwd.h>
535 #include <scopes/internal/MWRegistryProxyFwd.h>
536@@ -61,6 +62,8 @@
537 virtual void stop() = 0;
538 virtual void wait_for_shutdown() = 0;
539
540+ virtual MWProxy create_proxy(std::string const& identity, std::string const& endpoint) = 0;
541+
542 virtual MWRegistryProxy create_registry_proxy(std::string const& identity, std::string const& endpoint) = 0;
543 virtual MWScopeProxy create_scope_proxy(std::string const& identity) = 0;
544 virtual MWScopeProxy create_scope_proxy(std::string const& identity, std::string const& endpoint) = 0;
545
546=== modified file 'include/scopes/internal/MiddlewareFactory.h'
547--- include/scopes/internal/MiddlewareFactory.h 2013-11-21 21:44:00 +0000
548+++ include/scopes/internal/MiddlewareFactory.h 2013-12-03 14:09:20 +0000
549@@ -44,7 +44,7 @@
550 public:
551 UNITY_DEFINES_PTRS(MiddlewareFactory);
552
553- MiddlewareFactory(std::string const& configfile, RuntimeImpl* runtime);
554+ MiddlewareFactory(RuntimeImpl* runtime);
555 ~MiddlewareFactory() noexcept;
556
557 // Returns the middleware with the given name and kind. If that middleware hasn't been created yet,
558
559=== removed file 'include/scopes/internal/MiddlewareFactoryConfig.h'
560--- include/scopes/internal/MiddlewareFactoryConfig.h 2013-11-21 21:44:00 +0000
561+++ include/scopes/internal/MiddlewareFactoryConfig.h 1970-01-01 00:00:00 +0000
562@@ -1,60 +0,0 @@
563-/*
564- * Copyright (C) 2013 Canonical Ltd
565- *
566- * This program is free software: you can redistribute it and/or modify
567- * it under the terms of the GNU Lesser General Public License version 3 as
568- * published by the Free Software Foundation.
569- *
570- * This program is distributed in the hope that it will be useful,
571- * but WITHOUT ANY WARRANTY; without even the implied warranty of
572- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
573- * GNU Lesser General Public License for more details.
574- *
575- * You should have received a copy of the GNU Lesser General Public License
576- * along with this program. If not, see <http://www.gnu.org/licenses/>.
577- *
578- * Authored by: Michi Henning <michi.henning@canonical.com>
579- */
580-
581-#ifndef UNITY_API_SCOPES_INTERNAL_MIDDLEWAREFACTORYCONFIG_H
582-#define UNITY_API_SCOPES_INTERNAL_MIDDLEWAREFACTORYCONFIG_H
583-
584-#include <scopes/internal/ConfigBase.h>
585-
586-namespace unity
587-{
588-
589-namespace api
590-{
591-
592-namespace scopes
593-{
594-
595-namespace internal
596-{
597-
598-class MiddlewareFactoryConfig : public ConfigBase
599-{
600-public:
601- static const char* MIDDLEWARE_FACTORY_CONFIG_GROUP;
602-
603- MiddlewareFactoryConfig(std::string const& configfile);
604- ~MiddlewareFactoryConfig() noexcept;
605-
606- std::string zmq_configfile() const;
607- std::string rest_configfile() const;
608-
609-private:
610- std::string zmq_configfile_;
611- std::string rest_configfile_;
612-};
613-
614-} // namespace internal
615-
616-} // namespace scopes
617-
618-} // namespace api
619-
620-} // namespace unity
621-
622-#endif
623
624=== modified file 'include/scopes/internal/ObjectProxyImpl.h'
625--- include/scopes/internal/ObjectProxyImpl.h 2013-11-25 19:05:41 +0000
626+++ include/scopes/internal/ObjectProxyImpl.h 2013-12-03 14:09:20 +0000
627@@ -40,10 +40,13 @@
628 ObjectProxyImpl(MWProxy const& mw_proxy);
629 virtual ~ObjectProxyImpl() noexcept;
630
631+ virtual std::string identity() const;
632+ virtual std::string endpoint() const;
633+
634 protected:
635- MWProxy proxy() const; // Non-virtual because we cannot use covariance with incomplete types.
636- // Each derived proxy implements a non-virtual fwd() method
637- // that is called from within each operation to down-cast the MWProxy.
638+ MWProxy proxy() const; // Non-virtual because we cannot use covariance with incomplete types.
639+ // Each derived proxy implements a non-virtual fwd() method
640+ // that is called from within each operation to down-cast the MWProxy.
641
642 private:
643 static Proxy create(MWProxy const& mw_proxy);
644
645=== modified file 'include/scopes/internal/RegistryImpl.h'
646--- include/scopes/internal/RegistryImpl.h 2013-11-25 19:05:41 +0000
647+++ include/scopes/internal/RegistryImpl.h 2013-12-03 14:09:20 +0000
648@@ -43,8 +43,9 @@
649 RegistryImpl(MWRegistryProxy const& mw_proxy, RuntimeImpl* runtime);
650 ~RegistryImpl() noexcept;
651
652- ScopeProxy find(std::string const& scope_name);
653- ScopeMap list();
654+ ScopeMetadata get_metadata(std::string const& scope_name);
655+ MetadataMap list();
656+ MetadataMap list_if(std::function<bool(ScopeMetadata const& item)> predicate);
657
658 static RegistryProxy create(MWRegistryProxy const& mw_proxy, RuntimeImpl* runtime);
659
660
661=== modified file 'include/scopes/internal/RegistryObject.h'
662--- include/scopes/internal/RegistryObject.h 2013-11-21 21:44:00 +0000
663+++ include/scopes/internal/RegistryObject.h 2013-12-03 14:09:20 +0000
664@@ -20,9 +20,8 @@
665 #define UNITY_API_SCOPES_INTERNAL_REGISTRYOBJECT_H
666
667 #include <scopes/internal/AbstractObject.h>
668-#include <scopes/internal/MWScope.h>
669+#include <scopes/Registry.h>
670
671-#include <map>
672 #include <mutex>
673
674 namespace unity
675@@ -48,16 +47,15 @@
676 virtual ~RegistryObject() noexcept;
677
678 // Remote operation implementations
679- MWScopeProxy find(std::string const& scope_name);
680-
681- typedef std::map<std::string, MWScopeProxy> MWScopeMap;
682- MWScopeMap list();
683-
684- bool add(std::string const& scope_name, MWScopeProxy const& scope);
685+ ScopeMetadata get_metadata(std::string const& scope_name);
686+
687+ MetadataMap list();
688+
689+ bool add(std::string const& scope_name, ScopeMetadata const& scope);
690 bool remove(std::string const& scope_name);
691
692 private:
693- mutable MWScopeMap scopes_;
694+ mutable MetadataMap scopes_;
695 mutable std::mutex mutex_;
696 };
697
698
699=== modified file 'include/scopes/internal/RuntimeConfig.h'
700--- include/scopes/internal/RuntimeConfig.h 2013-11-21 21:44:00 +0000
701+++ include/scopes/internal/RuntimeConfig.h 2013-12-03 14:09:20 +0000
702@@ -39,7 +39,7 @@
703 public:
704 static const char* RUNTIME_CONFIG_GROUP;
705
706- RuntimeConfig(std::string const& configfile = Runtime::DFLT_CONFIGFILE);
707+ RuntimeConfig(std::string const& configfile);
708 ~RuntimeConfig() noexcept;
709
710 std::string registry_identity() const;
711
712=== modified file 'include/scopes/internal/RuntimeImpl.h'
713--- include/scopes/internal/RuntimeImpl.h 2013-11-21 21:44:00 +0000
714+++ include/scopes/internal/RuntimeImpl.h 2013-12-03 14:09:20 +0000
715@@ -43,7 +43,7 @@
716 public:
717 UNITY_DEFINES_PTRS(RuntimeImpl);
718
719- static UPtr create(std::string const& scope_name, std::string const& configfile = Runtime::DFLT_CONFIGFILE);
720+ static UPtr create(std::string const& scope_name, std::string const& configfile = "");
721 void destroy();
722
723 std::string scope_name() const;
724
725=== modified file 'include/scopes/internal/ScopeConfig.h'
726--- include/scopes/internal/ScopeConfig.h 2013-11-21 21:44:00 +0000
727+++ include/scopes/internal/ScopeConfig.h 2013-12-03 14:09:20 +0000
728@@ -41,10 +41,22 @@
729 ScopeConfig(std::string const& configfile);
730 ~ScopeConfig() noexcept;
731
732- bool overrideable() const;
733+ bool overrideable() const; // Optional, returns false if not present
734+ std::string display_name() const;
735+ std::string description() const;
736+ std::string art() const; // Optional, throws NotFoundException if not present
737+ std::string icon() const; // Optional, throws NotFoundException if not present
738+ std::string search_hint() const; // Optional, throws NotFoundException if not present
739+ std::string hot_key() const; // Optional, throws NotFoundException if not present
740
741 private:
742 bool overrideable_;
743+ std::string display_name_;
744+ std::string description_;
745+ std::unique_ptr<std::string> art_;
746+ std::unique_ptr<std::string> icon_;
747+ std::unique_ptr<std::string> search_hint_;
748+ std::unique_ptr<std::string> hot_key_;
749 };
750
751 } // namespace internal
752
753=== added file 'include/scopes/internal/ScopeMetadataImpl.h'
754--- include/scopes/internal/ScopeMetadataImpl.h 1970-01-01 00:00:00 +0000
755+++ include/scopes/internal/ScopeMetadataImpl.h 2013-12-03 14:09:20 +0000
756@@ -0,0 +1,94 @@
757+/*
758+ * Copyright (C) 2013 Canonical Ltd
759+ *
760+ * This program is free software: you can redistribute it and/or modify
761+ * it under the terms of the Lesser GNU General Public License version 3 as
762+ * published by the Free Software Foundation.
763+ *
764+ * This program is distributed in the hope that it will be useful,
765+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
766+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
767+ * GNU Lesser General Public License for more details.
768+ *
769+ * You should have received a copy of the Lesser GNU General Public License
770+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
771+ *
772+ * Authored by: Michi Henning <michi.henning@canonical.com>
773+ */
774+
775+#ifndef UNITY_API_SCOPES_INTERNAL_SCOPEMETADATAIMPL_H
776+#define UNITY_API_SCOPES_INTERNAL_SCOPEMETADATAIMPL_H
777+
778+#include <scopes/internal/MWScope.h>
779+#include <scopes/ScopeMetadata.h>
780+
781+#include <unordered_set>
782+
783+namespace unity
784+{
785+
786+namespace api
787+{
788+
789+namespace scopes
790+{
791+
792+namespace internal
793+{
794+
795+class ScopeMetadataImpl
796+{
797+public:
798+ ScopeMetadataImpl(MiddlewareBase* mw);
799+ ScopeMetadataImpl(VariantMap const& variant_map, MiddlewareBase* mw);
800+ ScopeMetadataImpl(ScopeMetadataImpl const&);
801+ ScopeMetadataImpl(ScopeMetadataImpl&&) = default;
802+ ScopeMetadataImpl& operator=(ScopeMetadataImpl const&);
803+ ScopeMetadataImpl& operator=(ScopeMetadataImpl&&) = default;
804+
805+ std::string scope_name() const;
806+ ScopeProxy proxy() const;
807+ std::string display_name() const; // localized
808+ std::string description() const; // localized
809+ std::string art() const; // optional
810+ std::string icon() const; // optional
811+ std::string search_hint() const; // localized, optional
812+ std::string hot_key() const; // localized, optional
813+
814+ void set_scope_name(std::string const& scope_name);
815+ void set_proxy(ScopeProxy const& proxy);
816+ void set_display_name(std::string const& display_name);
817+ void set_description(std::string const& description);
818+ void set_art(std::string const& art);
819+ void set_icon(std::string const& icon);
820+ void set_search_hint(std::string const& search_hint);
821+ void set_hot_key(std::string const& hot_key);
822+
823+ VariantMap serialize() const;
824+ void deserialize(VariantMap const& var);
825+
826+ static ScopeMetadata create(std::unique_ptr<ScopeMetadataImpl> impl);
827+
828+private:
829+
830+ MiddlewareBase* mw_;
831+ std::string scope_name_;
832+ ScopeProxy proxy_;
833+ std::string display_name_;
834+ std::string description_;
835+ std::unique_ptr<std::string> art_; // Optional, hence a pointer
836+ std::unique_ptr<std::string> icon_; // Optional, hence a pointer
837+ std::unique_ptr<std::string> search_hint_; // Optional, hence a pointer
838+ std::unique_ptr<std::string> hot_key_; // Optional, hence a pointer
839+};
840+
841+} // namespace internal
842+
843+} // namespace scopes
844+
845+} // namespace api
846+
847+} // namespace unity
848+
849+
850+#endif
851
852=== modified file 'include/scopes/internal/zmq_middleware/RegistryI.h'
853--- include/scopes/internal/zmq_middleware/RegistryI.h 2013-11-21 21:46:36 +0000
854+++ include/scopes/internal/zmq_middleware/RegistryI.h 2013-12-03 14:09:20 +0000
855@@ -51,7 +51,7 @@
856 virtual ~RegistryI() noexcept;
857
858 private:
859- virtual void find_(Current const& current,
860+ virtual void get_metadata_(Current const& current,
861 capnp::ObjectPointer::Reader& in_params,
862 capnproto::Response::Builder& r);
863
864
865=== modified file 'include/scopes/internal/zmq_middleware/RequestType.h'
866--- include/scopes/internal/zmq_middleware/RequestType.h 2013-11-21 21:44:00 +0000
867+++ include/scopes/internal/zmq_middleware/RequestType.h 2013-12-03 14:09:20 +0000
868@@ -36,7 +36,7 @@
869 namespace zmq_middleware
870 {
871
872-enum RequestType { Oneway, Twoway };
873+enum RequestType { Unknown, Oneway, Twoway };
874
875 std::string to_string(RequestType);
876
877
878=== modified file 'include/scopes/internal/zmq_middleware/ZmqConfig.h'
879--- include/scopes/internal/zmq_middleware/ZmqConfig.h 2013-11-21 21:44:00 +0000
880+++ include/scopes/internal/zmq_middleware/ZmqConfig.h 2013-12-03 14:09:20 +0000
881@@ -21,8 +21,6 @@
882
883 #include <scopes/internal/ConfigBase.h>
884
885-#include <mutex>
886-
887 namespace unity
888 {
889
890@@ -48,8 +46,7 @@
891
892 private:
893 std::string public_dir_;
894- mutable std::string private_dir_;
895- mutable std::mutex mutex_;
896+ std::string private_dir_;
897 };
898
899 } // namespace internal
900
901=== modified file 'include/scopes/internal/zmq_middleware/ZmqMiddleware.h'
902--- include/scopes/internal/zmq_middleware/ZmqMiddleware.h 2013-11-21 21:44:00 +0000
903+++ include/scopes/internal/zmq_middleware/ZmqMiddleware.h 2013-12-03 14:09:20 +0000
904@@ -61,6 +61,8 @@
905 virtual void stop() override;
906 virtual void wait_for_shutdown() override;
907
908+ virtual MWProxy create_proxy(std::string const& identity, std::string const& endpoint) override;
909+
910 virtual MWRegistryProxy create_registry_proxy(std::string const& identity, std::string const& endpoint) override;
911 virtual MWScopeProxy create_scope_proxy(std::string const& identity) override;
912 virtual MWScopeProxy create_scope_proxy(std::string const& identity, std::string const& endpoint) override;
913
914=== modified file 'include/scopes/internal/zmq_middleware/ZmqObjectProxy.h'
915--- include/scopes/internal/zmq_middleware/ZmqObjectProxy.h 2013-11-25 16:22:12 +0000
916+++ include/scopes/internal/zmq_middleware/ZmqObjectProxy.h 2013-12-03 14:09:20 +0000
917@@ -45,11 +45,12 @@
918
919 class ZmqReceiver;
920
921-// An Zmq proxy that points at some Zmq object, but without a specific type.
922+// A Zmq proxy that points at some Zmq object, but without a specific type.
923
924 class ZmqObjectProxy : public virtual MWObjectProxy
925 {
926 public:
927+ ZmqObjectProxy(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity);
928 ZmqObjectProxy(ZmqMiddleware* mw_base, std::string const& endpoint, std::string const& identity, RequestType t);
929 virtual ~ZmqObjectProxy() noexcept;
930
931@@ -63,43 +64,12 @@
932 capnproto::Request::Builder make_request_(capnp::MessageBuilder& b, std::string const& operation_name) const;
933 std::unique_ptr<ZmqReceiver> invoke_(capnp::MessageBuilder& out_params);
934
935- // TODO: commented out for now (see below)
936-#if 0
937- template<typename F>
938- std::unique_ptr<capnp::SegmentArrayMessageReader> submit_request_(F f);
939-#endif
940-
941 private:
942 std::string endpoint_;
943 std::string identity_;
944 RequestType type_;
945 };
946
947-// TODO: Ideally, we would use this template because this is type-independent work, instead of having the
948-// body of this method repeated in each operation of the derived proxy. But, for some reason, the getRoot
949-// call below causes a syntax error. Need to try with clang to see whether there is a better error message.
950-// Or maybe it's a gcc bug...
951-
952-#if 0
953-template<typename F>
954-std::unique_ptr<capnp::SegmentArrayMessageReader> ZmqObjectProxy::submit_request_(F f)
955-{
956- try
957- {
958- auto future = mw_base()->invoke_pool()->submit(f);
959- future.wait();
960- auto reader = future.get();
961- auto response = reader->getRoot<capnproto::Response>();
962- throw_if_runtime_exception(response);
963- return reader;
964- }
965- catch (...)
966- {
967- throw; // TODO: what to do here?
968- }
969-}
970-#endif
971-
972 } // namespace zmq_middleware
973
974 } // namespace internal
975
976=== modified file 'include/scopes/internal/zmq_middleware/ZmqRegistry.h'
977--- include/scopes/internal/zmq_middleware/ZmqRegistry.h 2013-11-25 16:22:12 +0000
978+++ include/scopes/internal/zmq_middleware/ZmqRegistry.h 2013-12-03 14:09:20 +0000
979@@ -48,8 +48,8 @@
980 virtual ~ZmqRegistry() noexcept;
981
982 // Remote operations.
983- virtual ScopeProxy find(std::string const& scope_name) override;
984- virtual ScopeMap list() override;
985+ virtual ScopeMetadata get_metadata(std::string const& scope_name) override;
986+ virtual MetadataMap list() override;
987 };
988
989 } // namespace zmq_middleware
990
991=== modified file 'scoperegistry/scoperegistry.cpp'
992--- scoperegistry/scoperegistry.cpp 2013-11-21 21:44:00 +0000
993+++ scoperegistry/scoperegistry.cpp 2013-12-03 14:09:20 +0000
994@@ -25,6 +25,9 @@
995 #include <scopes/internal/RuntimeConfig.h>
996 #include <scopes/internal/RuntimeImpl.h>
997 #include <scopes/internal/ScopeConfig.h>
998+#include <scopes/internal/ScopeMetadataImpl.h>
999+#include <scopes/internal/ScopeImpl.h>
1000+#include <scopes/ScopeExceptions.h>
1001 #include <unity/UnityExceptions.h>
1002 #include <unity/util/ResourcePtr.h>
1003
1004@@ -94,7 +97,7 @@
1005 }
1006 catch (FileException const& e)
1007 {
1008- error(e.to_string() + ": scope group file ignored");
1009+ error("scope group config file ignored:\n" + e.to_string());
1010 continue;
1011 }
1012
1013@@ -105,7 +108,7 @@
1014 }
1015 catch (LogicException const& e)
1016 {
1017- error("group file \"" + file + ": file ignored: " + e.to_string());
1018+ error("group file \"" + file + ": file ignored:\n" + e.to_string());
1019 continue;
1020 }
1021
1022@@ -148,6 +151,62 @@
1023 return scope_groups;
1024 }
1025
1026+// For each scope, open the config file for each scope, create the metadata info from the config,
1027+// and add an entry to the RegistryObject.
1028+
1029+void add_metadata(RegistryObject::SPtr const& registry,
1030+ map<string, string> const& all_scopes,
1031+ MiddlewareBase::SPtr const& mw)
1032+{
1033+ for (auto pair : all_scopes)
1034+ {
1035+ try
1036+ {
1037+ unique_ptr<ScopeMetadataImpl> mi(new ScopeMetadataImpl(mw.get()));
1038+ ScopeConfig sc(pair.second);
1039+ mi->set_scope_name(pair.first);
1040+ mi->set_display_name(sc.display_name());
1041+ mi->set_description(sc.description());
1042+ try
1043+ {
1044+ mi->set_art(sc.art());
1045+ }
1046+ catch (NotFoundException const&)
1047+ {
1048+ }
1049+ try
1050+ {
1051+ mi->set_icon(sc.icon());
1052+ }
1053+ catch (NotFoundException const&)
1054+ {
1055+ }
1056+ try
1057+ {
1058+ mi->set_search_hint(sc.search_hint());
1059+ }
1060+ catch (NotFoundException const&)
1061+ {
1062+ }
1063+ try
1064+ {
1065+ mi->set_hot_key(sc.hot_key());
1066+ }
1067+ catch (NotFoundException const&)
1068+ {
1069+ }
1070+ ScopeProxy proxy = ScopeImpl::create(mw->create_scope_proxy(pair.first), mw->runtime());
1071+ mi->set_proxy(proxy);
1072+ auto meta = ScopeMetadataImpl::create(move(mi));
1073+ registry->add(pair.first, move(meta));
1074+ }
1075+ catch (unity::Exception const& e)
1076+ {
1077+ error("ignoring scope \"" + pair.first + "\": cannot create metadata: " + e.to_string());
1078+ }
1079+ }
1080+}
1081+
1082 void run_scopes(SignalThread& sigthread,
1083 string const& scoperunner_path,
1084 string const& config_file,
1085@@ -200,7 +259,7 @@
1086 }
1087 char const* const config_file = argv[1];
1088
1089- int exit_status = 0;
1090+ int exit_status = 1;
1091
1092 // Run a separate thread to deal with SIGCHLD. This allows us to report when a scope process exits abnormally.
1093 SignalThread signal_thread;
1094@@ -246,14 +305,21 @@
1095 {
1096 string file_name = basename(const_cast<char*>(string(path).c_str())); // basename() modifies its argument
1097 string scope_name = strip_suffix(file_name, ".ini");
1098- ScopeConfig config(path);
1099- if (config.overrideable())
1100+ try
1101 {
1102- overrideable_scopes[scope_name] = path;
1103+ ScopeConfig config(path);
1104+ if (config.overrideable())
1105+ {
1106+ overrideable_scopes[scope_name] = path;
1107+ }
1108+ else
1109+ {
1110+ fixed_scopes[scope_name] = path;
1111+ }
1112 }
1113- else
1114+ catch (unity::Exception const& e)
1115 {
1116- fixed_scopes[scope_name] = path;
1117+ error("ignoring scope \"" + scope_name + "\": configuration error:\n" + e.to_string());
1118 }
1119 }
1120
1121@@ -297,13 +363,10 @@
1122 RegistryObject::SPtr registry(new RegistryObject);
1123 middleware->add_registry_object(runtime->registry_identity(), registry);
1124
1125- // Add a proxy for each scope to the lookup table.
1126+ // Add the metadata for each scope to the lookup table.
1127 // We do this before starting any of the scopes, so aggregating scopes don't get a lookup failure if
1128 // they look for another scope in the registry.
1129- for (auto pair : all_scopes)
1130- {
1131- registry->add(pair.first, middleware->create_scope_proxy(pair.first));
1132- }
1133+ add_metadata(registry, all_scopes, middleware);
1134
1135 // Start a scoperunner for each Canonical scope group and add the corresponding proxies to the registry
1136 run_scopes(signal_thread, scoperunner_path, config_file, canonical_groups);
1137@@ -313,31 +376,27 @@
1138
1139 // Wait until we are done.
1140 middleware->wait_for_shutdown();
1141+ exit_status = 0;
1142 }
1143 catch (unity::Exception const& e)
1144 {
1145 error(e.to_string());
1146- exit_status = 1;
1147 }
1148 catch (std::exception const& e)
1149 {
1150 error(e.what());
1151- exit_status = 1;
1152 }
1153 catch (string const& e)
1154 {
1155 error("fatal error: " + e);
1156- exit_status = 1;
1157 }
1158 catch (char const* e)
1159 {
1160 error(string("fatal error: ") + e);
1161- exit_status = 1;
1162 }
1163 catch (...)
1164 {
1165 error("terminated due to unknown exception");
1166- exit_status = 1;
1167 }
1168
1169 return exit_status;
1170
1171=== modified file 'scoperunner/scoperunner.cpp'
1172--- scoperunner/scoperunner.cpp 2013-11-21 21:44:00 +0000
1173+++ scoperunner/scoperunner.cpp 2013-12-03 14:09:20 +0000
1174@@ -200,7 +200,7 @@
1175 }
1176 char const* const runtime_config = argv[1];
1177
1178- int exit_status = 0;
1179+ int exit_status = 1;
1180 try
1181 {
1182 vector<string> config_files;
1183@@ -218,27 +218,22 @@
1184 catch (unity::Exception const& e)
1185 {
1186 error(e.to_string());
1187- exit_status = 1;
1188 }
1189 catch (std::exception const& e)
1190 {
1191 error(e.what());
1192- exit_status = 1;
1193 }
1194 catch (string const& e)
1195 {
1196 error("fatal error: " + e);
1197- exit_status = 1;
1198 }
1199 catch (char const* e)
1200 {
1201 error(string("fatal error: ") + e);
1202- exit_status = 1;
1203 }
1204 catch (...)
1205 {
1206 error("terminated due to unknown exception");
1207- exit_status = 1;
1208 }
1209
1210 return exit_status;
1211
1212=== modified file 'src/CMakeLists.txt'
1213--- src/CMakeLists.txt 2013-11-26 15:35:46 +0000
1214+++ src/CMakeLists.txt 2013-12-03 14:09:20 +0000
1215@@ -16,6 +16,7 @@
1216 ${CMAKE_CURRENT_SOURCE_DIR}/Scope.cpp
1217 ${CMAKE_CURRENT_SOURCE_DIR}/ScopeBase.cpp
1218 ${CMAKE_CURRENT_SOURCE_DIR}/ScopeExceptions.cpp
1219+ ${CMAKE_CURRENT_SOURCE_DIR}/ScopeMetadata.cpp
1220 ${CMAKE_CURRENT_SOURCE_DIR}/Variant.cpp
1221 ${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp
1222 )
1223
1224=== modified file 'src/ObjectProxy.cpp'
1225--- src/ObjectProxy.cpp 2013-11-25 19:05:41 +0000
1226+++ src/ObjectProxy.cpp 2013-12-03 14:09:20 +0000
1227@@ -20,6 +20,8 @@
1228
1229 #include <scopes/internal/ObjectProxyImpl.h>
1230
1231+using namespace std;
1232+
1233 namespace unity
1234 {
1235
1236@@ -51,6 +53,16 @@
1237 {
1238 }
1239
1240+string ObjectProxy::identity() const
1241+{
1242+ return p->identity();
1243+}
1244+
1245+string ObjectProxy::endpoint() const
1246+{
1247+ return p->endpoint();
1248+}
1249+
1250 internal::ObjectProxyImpl* ObjectProxy::pimpl() const noexcept
1251 {
1252 return p.get();
1253
1254=== modified file 'src/ReceiverBase.cpp'
1255--- src/ReceiverBase.cpp 2013-11-25 19:05:41 +0000
1256+++ src/ReceiverBase.cpp 2013-12-03 14:09:20 +0000
1257@@ -42,8 +42,9 @@
1258 {
1259 }
1260
1261-void ReceiverBase::push(Category::SCPtr category)
1262+void ReceiverBase::push(Category::SCPtr /* category */)
1263 {
1264+ // Intentionally empty: "do nothing" default implementation.
1265 }
1266
1267 // Possibly overkill, but safer than using the enum as the index into an array,
1268
1269=== modified file 'src/Registry.cpp'
1270--- src/Registry.cpp 2013-11-25 19:05:41 +0000
1271+++ src/Registry.cpp 2013-12-03 14:09:20 +0000
1272@@ -42,16 +42,21 @@
1273
1274 //! @endcond
1275
1276-ScopeProxy Registry::find(std::string const& scope_name) const
1277+ScopeMetadata Registry::get_metadata(std::string const& scope_name) const
1278 {
1279- return fwd()->find(scope_name);
1280+ return fwd()->get_metadata(scope_name);
1281 }
1282
1283-ScopeMap Registry::list() const
1284+MetadataMap Registry::list() const
1285 {
1286 return fwd()->list();
1287 }
1288
1289+MetadataMap Registry::list_if(std::function<bool(ScopeMetadata const& item)> predicate) const
1290+{
1291+ return fwd()->list_if(predicate);
1292+}
1293+
1294 internal::RegistryImpl* Registry::fwd() const
1295 {
1296 return dynamic_cast<internal::RegistryImpl*>(pimpl());
1297
1298=== modified file 'src/Runtime.cpp'
1299--- src/Runtime.cpp 2013-11-25 16:22:12 +0000
1300+++ src/Runtime.cpp 2013-12-03 14:09:20 +0000
1301@@ -31,8 +31,6 @@
1302 namespace scopes
1303 {
1304
1305-constexpr char const* Runtime::DFLT_CONFIGFILE;
1306-
1307 //! @cond
1308
1309 Runtime::Runtime(string const& scope_name, string const& configfile) :
1310
1311=== added file 'src/ScopeMetadata.cpp'
1312--- src/ScopeMetadata.cpp 1970-01-01 00:00:00 +0000
1313+++ src/ScopeMetadata.cpp 2013-12-03 14:09:20 +0000
1314@@ -0,0 +1,123 @@
1315+/*
1316+ * Copyright (C) 2013 Canonical Ltd
1317+ *
1318+ * This program is free software: you can redistribute it and/or modify
1319+ * it under the terms of the Lesser GNU General Public License version 3 as
1320+ * published by the Free Software Foundation.
1321+ *
1322+ * This program is distributed in the hope that it will be useful,
1323+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1324+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1325+ * GNU Lesser General Public License for more details.
1326+ *
1327+ * You should have received a copy of the GNU Lesser General Public License
1328+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1329+ *
1330+ * Authored by: Michi Henning <michi.henning@canonical.com>
1331+ */
1332+
1333+#include <scopes/ScopeMetadata.h>
1334+#include <scopes/internal/ScopeMetadataImpl.h>
1335+
1336+#include <cassert>
1337+
1338+using namespace std;
1339+
1340+namespace unity
1341+{
1342+
1343+namespace api
1344+{
1345+
1346+namespace scopes
1347+{
1348+
1349+//! @cond
1350+
1351+ScopeMetadata::ScopeMetadata(unique_ptr<internal::ScopeMetadataImpl> impl) :
1352+ p(move(impl))
1353+{
1354+ // The only way to create a ScopeMetadata instance is to first intialize
1355+ // a ScopeMetadataImpl, fill it in, and then call this constructor.
1356+ // We check here that all mandatory fields are present. If not
1357+ // we have an internal logic error.
1358+ assert(!p->scope_name().empty());
1359+ assert(p->proxy());
1360+ assert(!p->display_name().empty());
1361+ assert(!p->description().empty());
1362+}
1363+
1364+ScopeMetadata::ScopeMetadata(ScopeMetadata const& other) :
1365+ p(new internal::ScopeMetadataImpl(*(other.p)))
1366+{
1367+}
1368+
1369+ScopeMetadata::ScopeMetadata(ScopeMetadata&&) = default;
1370+
1371+ScopeMetadata::~ScopeMetadata()
1372+{
1373+}
1374+
1375+ScopeMetadata& ScopeMetadata::operator=(ScopeMetadata const& other)
1376+{
1377+ if (this != &other)
1378+ {
1379+ p.reset(new internal::ScopeMetadataImpl(*(other.p)));
1380+ }
1381+ return *this;
1382+}
1383+
1384+ScopeMetadata& ScopeMetadata::operator=(ScopeMetadata&&) = default;
1385+
1386+string ScopeMetadata::scope_name() const
1387+{
1388+ return p->scope_name();
1389+}
1390+
1391+ScopeProxy ScopeMetadata::proxy() const
1392+{
1393+ return p->proxy();
1394+}
1395+
1396+string ScopeMetadata::display_name() const
1397+{
1398+ return p->display_name();
1399+}
1400+
1401+string ScopeMetadata::description() const
1402+{
1403+ return p->description();
1404+}
1405+
1406+string ScopeMetadata::art() const
1407+{
1408+ return p->art();
1409+}
1410+
1411+string ScopeMetadata::icon() const
1412+{
1413+ return p->icon();
1414+}
1415+
1416+string ScopeMetadata::search_hint() const
1417+{
1418+ return p->search_hint();
1419+}
1420+
1421+string ScopeMetadata::hot_key() const
1422+{
1423+ return p->hot_key();
1424+}
1425+
1426+VariantMap ScopeMetadata::serialize() const
1427+{
1428+ return p->serialize();
1429+}
1430+
1431+//! @endcond
1432+
1433+} // namespace scopes
1434+
1435+} // namespace api
1436+
1437+} // namespace unity
1438
1439=== modified file 'src/internal/CMakeLists.txt'
1440--- src/internal/CMakeLists.txt 2013-11-26 15:35:46 +0000
1441+++ src/internal/CMakeLists.txt 2013-12-03 14:09:20 +0000
1442@@ -11,7 +11,6 @@
1443 ${CMAKE_CURRENT_SOURCE_DIR}/DynamicLoader.cpp
1444 ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareBase.cpp
1445 ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareFactory.cpp
1446- ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareFactoryConfig.cpp
1447 ${CMAKE_CURRENT_SOURCE_DIR}/MWObject.cpp
1448 ${CMAKE_CURRENT_SOURCE_DIR}/MWQuery.cpp
1449 ${CMAKE_CURRENT_SOURCE_DIR}/MWQueryCtrl.cpp
1450@@ -35,6 +34,7 @@
1451 ${CMAKE_CURRENT_SOURCE_DIR}/ScopeConfig.cpp
1452 ${CMAKE_CURRENT_SOURCE_DIR}/ScopeImpl.cpp
1453 ${CMAKE_CURRENT_SOURCE_DIR}/ScopeLoader.cpp
1454+ ${CMAKE_CURRENT_SOURCE_DIR}/ScopeMetadataImpl.cpp
1455 ${CMAKE_CURRENT_SOURCE_DIR}/ScopeObject.cpp
1456 ${CMAKE_CURRENT_SOURCE_DIR}/ThreadPool.cpp
1457 ${CMAKE_CURRENT_SOURCE_DIR}/UniqueID.cpp
1458
1459=== modified file 'src/internal/ConfigBase.cpp'
1460--- src/internal/ConfigBase.cpp 2013-11-21 21:44:00 +0000
1461+++ src/internal/ConfigBase.cpp 2013-12-03 14:09:20 +0000
1462@@ -22,7 +22,6 @@
1463 #include <unity/UnityExceptions.h>
1464 #include <unity/util/IniParser.h>
1465
1466-#include <sstream>
1467
1468 using namespace std;
1469
1470@@ -38,24 +37,30 @@
1471 namespace internal
1472 {
1473
1474+// If configfile is the empty string, we create a default instance that returns "Zmq" for the middleware
1475+// and throws for the other methods.
1476+
1477 ConfigBase::ConfigBase(string const& configfile) :
1478- parser_(make_shared<util::IniParser>(configfile.c_str())),
1479 configfile_(configfile)
1480 {
1481+ if (!configfile.empty())
1482+ {
1483+ parser_ = make_shared<util::IniParser>(configfile.c_str());
1484+ }
1485 }
1486
1487 ConfigBase::~ConfigBase() noexcept
1488 {
1489 }
1490
1491-shared_ptr<util::IniParser> ConfigBase::parser() const noexcept
1492+util::IniParser::SPtr ConfigBase::parser() const noexcept
1493 {
1494- return parser_;
1495+ return p();
1496 }
1497
1498 string ConfigBase::get_string(string const& group, string const& key) const
1499 {
1500- string val = parser_->get_string(group, key);
1501+ string val = p()->get_string(group, key);
1502 if (val.empty())
1503 {
1504 throw_ex("Illegal empty value for " + key);
1505@@ -67,7 +72,7 @@
1506 {
1507 try
1508 {
1509- return parser_->get_string(group, key);
1510+ return p()->get_string(group, key);
1511 }
1512 catch (unity::LogicException const&)
1513 {
1514@@ -77,6 +82,10 @@
1515
1516 string ConfigBase::get_middleware(string const& group, string const& key) const
1517 {
1518+ if (!parser_)
1519+ {
1520+ return "Zmq";
1521+ }
1522 string val = get_string(group, key);
1523 if (val != "Zmq" && val != "REST")
1524 {
1525@@ -88,9 +97,17 @@
1526
1527 void ConfigBase::throw_ex(string const& reason) const
1528 {
1529- ostringstream s;
1530- s << "\"" << configfile_ << "\": " << reason;
1531- throw ConfigException(s.str());
1532+ string s = "\"" + configfile_ + "\": " + reason;
1533+ throw ConfigException(s);
1534+}
1535+
1536+util::IniParser::SPtr ConfigBase::p() const
1537+{
1538+ if (!parser_)
1539+ {
1540+ throw LogicException("ConfigBase: no parser available with default config");
1541+ }
1542+ return parser_;
1543 }
1544
1545 } // namespace internal
1546
1547=== modified file 'src/internal/MiddlewareFactory.cpp'
1548--- src/internal/MiddlewareFactory.cpp 2013-11-21 21:44:00 +0000
1549+++ src/internal/MiddlewareFactory.cpp 2013-12-03 14:09:20 +0000
1550@@ -18,8 +18,6 @@
1551
1552 #include <scopes/internal/MiddlewareFactory.h>
1553
1554-// #include <scopes/internal/ice_middleware/IceMiddleware.h>
1555-#include <scopes/internal/MiddlewareFactoryConfig.h>
1556 #include <scopes/internal/zmq_middleware/ZmqMiddleware.h>
1557 #include <scopes/ScopeExceptions.h>
1558
1559@@ -40,19 +38,10 @@
1560 namespace internal
1561 {
1562
1563-MiddlewareFactory::MiddlewareFactory(string const& configfile, RuntimeImpl* runtime) :
1564+MiddlewareFactory::MiddlewareFactory(RuntimeImpl* runtime) :
1565 runtime_(runtime)
1566 {
1567 assert(runtime);
1568-
1569- try
1570- {
1571- MiddlewareFactoryConfig config(configfile);
1572- }
1573- catch (unity::Exception const& e)
1574- {
1575- throw ConfigException("cannot instantiate MiddlewareFactory: config file: " + configfile);
1576- }
1577 }
1578
1579 MiddlewareFactory::~MiddlewareFactory() noexcept
1580
1581=== modified file 'src/internal/ObjectProxyImpl.cpp'
1582--- src/internal/ObjectProxyImpl.cpp 2013-11-25 19:05:41 +0000
1583+++ src/internal/ObjectProxyImpl.cpp 2013-12-03 14:09:20 +0000
1584@@ -49,6 +49,16 @@
1585 return make_shared<ObjectProxy>();
1586 }
1587
1588+string ObjectProxyImpl::identity() const
1589+{
1590+ return mw_proxy_->identity();
1591+}
1592+
1593+string ObjectProxyImpl::endpoint() const
1594+{
1595+ return mw_proxy_->endpoint();
1596+}
1597+
1598 MWProxy ObjectProxyImpl::proxy() const
1599 {
1600 return mw_proxy_;
1601
1602=== modified file 'src/internal/RegistryImpl.cpp'
1603--- src/internal/RegistryImpl.cpp 2013-11-25 19:05:41 +0000
1604+++ src/internal/RegistryImpl.cpp 2013-12-03 14:09:20 +0000
1605@@ -45,16 +45,30 @@
1606 {
1607 }
1608
1609-ScopeProxy RegistryImpl::find(std::string const& scope_name)
1610+ScopeMetadata RegistryImpl::get_metadata(std::string const& scope_name)
1611 {
1612- return fwd()->find(scope_name);
1613+ return fwd()->get_metadata(scope_name);
1614 }
1615
1616-ScopeMap RegistryImpl::list()
1617+MetadataMap RegistryImpl::list()
1618 {
1619 return fwd()->list();
1620 }
1621
1622+MetadataMap RegistryImpl::list_if(std::function<bool(ScopeMetadata const& item)> predicate)
1623+{
1624+ auto scope_map = list();
1625+ MetadataMap matching_entries;
1626+ for (auto& pair : scope_map)
1627+ {
1628+ if (predicate(pair.second))
1629+ {
1630+ matching_entries.emplace(pair);
1631+ }
1632+ }
1633+ return matching_entries;
1634+}
1635+
1636 RegistryProxy RegistryImpl::create(MWRegistryProxy const& mw_proxy, RuntimeImpl* runtime)
1637 {
1638 return RegistryProxy(new Registry(new RegistryImpl(mw_proxy, runtime)));
1639
1640=== modified file 'src/internal/RegistryObject.cpp'
1641--- src/internal/RegistryObject.cpp 2013-11-21 21:44:00 +0000
1642+++ src/internal/RegistryObject.cpp 2013-12-03 14:09:20 +0000
1643@@ -43,7 +43,7 @@
1644 {
1645 }
1646
1647-MWScopeProxy RegistryObject::find(std::string const& scope_name)
1648+ScopeMetadata RegistryObject::get_metadata(std::string const& scope_name)
1649 {
1650 // If the name is empty, it was sent as empty by the remote client.
1651 if (scope_name.empty())
1652@@ -56,33 +56,34 @@
1653 auto const& it = scopes_.find(scope_name);
1654 if (it == scopes_.end())
1655 {
1656- throw NotFoundException("Registry::find(): no such scope", scope_name);
1657+ throw NotFoundException("Registry::get_metadata(): no such scope", scope_name);
1658 }
1659 return it->second;
1660 }
1661
1662-RegistryObject::MWScopeMap RegistryObject::list()
1663+MetadataMap RegistryObject::list()
1664 {
1665 lock_guard<decltype(mutex_)> lock(mutex_);
1666 return scopes_;
1667 }
1668
1669-bool RegistryObject::add(std::string const& scope_name, MWScopeProxy const& scope)
1670+bool RegistryObject::add(std::string const& scope_name, ScopeMetadata const& metadata)
1671 {
1672- // TODO: also check for names containing a slash, because that won't work if we use
1673+ if (scope_name.empty())
1674+ {
1675+ throw unity::InvalidArgumentException("Registry: Cannot add scope with empty name");
1676+ }
1677+ // TODO: check for names containing a slash, because that won't work if we use
1678 // the name for a socket in the file system.
1679- if (scope_name.empty())
1680- {
1681- throw unity::InvalidArgumentException("Registry: Cannot add scope with empty name");
1682- }
1683
1684 lock_guard<decltype(mutex_)> lock(mutex_);
1685
1686- auto const& pair = scopes_.insert(make_pair(scope_name, scope));
1687+ auto const& pair = scopes_.insert(make_pair(scope_name, metadata));
1688 if (!pair.second)
1689 {
1690+ // Replace already existing entry with this one
1691 scopes_.erase(pair.first);
1692- scopes_.insert(make_pair(scope_name, scope));
1693+ scopes_.insert(make_pair(scope_name, metadata));
1694 return false;
1695 }
1696 return true;
1697
1698=== modified file 'src/internal/ResultItemImpl.cpp'
1699--- src/internal/ResultItemImpl.cpp 2013-11-27 02:08:11 +0000
1700+++ src/internal/ResultItemImpl.cpp 2013-12-03 14:09:20 +0000
1701@@ -19,7 +19,6 @@
1702 #include <scopes/internal/ResultItemImpl.h>
1703 #include <unity/UnityExceptions.h>
1704 #include <scopes/Category.h>
1705-#include <sstream>
1706
1707 namespace unity
1708 {
1709@@ -113,9 +112,7 @@
1710 {
1711 if (value.empty())
1712 {
1713- std::ostringstream s;
1714- s << "Required attribute " << name << " is empty";
1715- throw InvalidArgumentException(s.str());
1716+ throw InvalidArgumentException("ResultItem: invalid empty attribute: " + name);
1717 }
1718 }
1719
1720@@ -139,9 +136,8 @@
1721 {
1722 if (var.find(kv.first) != var.end())
1723 {
1724- std::ostringstream s;
1725- s << "Can't overwrite internal attribute: " << kv.first;
1726- throw InvalidArgumentException(s.str());
1727+ throw InvalidArgumentException("ResultItemImpl::serialize(): Can't overwrite internal attribute: "
1728+ + kv.first);
1729 }
1730 var[kv.first] = kv.second;
1731 }
1732
1733=== modified file 'src/internal/RuntimeConfig.cpp'
1734--- src/internal/RuntimeConfig.cpp 2013-11-21 21:44:00 +0000
1735+++ src/internal/RuntimeConfig.cpp 2013-12-03 14:09:20 +0000
1736@@ -46,22 +46,29 @@
1737 RuntimeConfig::RuntimeConfig(string const& configfile) :
1738 ConfigBase(configfile)
1739 {
1740- registry_identity_ = get_string(RUNTIME_CONFIG_GROUP, registry_identity_str);
1741- auto pos = registry_identity_.find_first_of("@:/");
1742- if (pos != string::npos)
1743- {
1744- throw_ex("Illegal character in value for " + registry_identity_str + ": \"" + registry_identity_ +
1745- "\": identity cannot contain '" + registry_identity_[pos] + "'");
1746- }
1747-
1748- registry_configfile_ = get_string(RUNTIME_CONFIG_GROUP, registry_configfile_str);
1749-
1750- default_middleware_ = get_middleware(RUNTIME_CONFIG_GROUP, default_middleware_str);
1751-
1752- default_middleware_configfile_ = get_string(RUNTIME_CONFIG_GROUP,
1753- default_middleware_ + "." + default_middleware_configfile_str);
1754-
1755- factory_configfile_ = get_string(RUNTIME_CONFIG_GROUP, factory_configfile_str);
1756+ if (configfile.empty()) // Default config
1757+ {
1758+ registry_identity_ = "Registry";
1759+ registry_configfile_ = "Registry.ini";
1760+ default_middleware_ = "Zmq";
1761+ default_middleware_configfile_ = "";
1762+ factory_configfile_ = "Factory.ini";
1763+ }
1764+ else
1765+ {
1766+ registry_identity_ = get_string(RUNTIME_CONFIG_GROUP, registry_identity_str);
1767+ auto pos = registry_identity_.find_first_of("@:/");
1768+ if (pos != string::npos)
1769+ {
1770+ throw_ex("Illegal character in value for " + registry_identity_str + ": \"" + registry_identity_ +
1771+ "\": identity cannot contain '" + registry_identity_[pos] + "'");
1772+ }
1773+ registry_configfile_ = get_string(RUNTIME_CONFIG_GROUP, registry_configfile_str);
1774+ default_middleware_ = get_middleware(RUNTIME_CONFIG_GROUP, default_middleware_str);
1775+ default_middleware_configfile_ = get_string(RUNTIME_CONFIG_GROUP,
1776+ default_middleware_ + "." + default_middleware_configfile_str);
1777+ factory_configfile_ = get_string(RUNTIME_CONFIG_GROUP, factory_configfile_str);
1778+ }
1779 }
1780
1781 RuntimeConfig::~RuntimeConfig() noexcept
1782
1783=== modified file 'src/internal/RuntimeImpl.cpp'
1784--- src/internal/RuntimeImpl.cpp 2013-11-21 21:44:00 +0000
1785+++ src/internal/RuntimeImpl.cpp 2013-12-03 14:09:20 +0000
1786@@ -56,8 +56,7 @@
1787 RuntimeConfig config(configfile);
1788 string default_middleware = config.default_middleware();
1789 string middleware_configfile = config.default_middleware_configfile();
1790- string factory_configfile = config.factory_configfile();
1791- middleware_factory_.reset(new MiddlewareFactory(factory_configfile, this));
1792+ middleware_factory_.reset(new MiddlewareFactory(this));
1793 registry_configfile_ = config.registry_configfile();
1794 registry_identity_ = config.registry_identity();
1795 assert(!registry_identity_.empty());
1796
1797=== modified file 'src/internal/ScopeConfig.cpp'
1798--- src/internal/ScopeConfig.cpp 2013-11-21 21:44:00 +0000
1799+++ src/internal/ScopeConfig.cpp 2013-12-03 14:09:20 +0000
1800@@ -18,6 +18,7 @@
1801
1802 #include <scopes/internal/ScopeConfig.h>
1803
1804+#include <scopes/ScopeExceptions.h>
1805 #include <unity/UnityExceptions.h>
1806
1807 using namespace std;
1808@@ -37,6 +38,12 @@
1809 namespace
1810 {
1811 const string overrideable_str = "Override";
1812+ const string scope_name_str = "DisplayName";
1813+ const string description_str = "Description";
1814+ const string art_str = "Art";
1815+ const string icon_str = "Icon";
1816+ const string search_hint_str = "SearchHint";
1817+ const string hot_key_str = "HotKey";
1818 }
1819
1820 ScopeConfig::ScopeConfig(string const& configfile) :
1821@@ -50,6 +57,44 @@
1822 {
1823 overrideable_ = false;
1824 }
1825+ display_name_ = parser()->get_string(SCOPE_CONFIG_GROUP, scope_name_str);
1826+ description_ = parser()->get_string(SCOPE_CONFIG_GROUP, description_str);
1827+
1828+ // For optional values, we store them in a unique_ptr so we can distinguish the "not set at all" case
1829+ // from the "explicitly set to empty string" case. parser()->get_string throws LogicException if
1830+ // the key is not present, so we ignore the exception for optional values.
1831+ try
1832+ {
1833+ string art = parser()->get_string(SCOPE_CONFIG_GROUP, art_str);
1834+ art_.reset(new string(art));
1835+ }
1836+ catch (LogicException const&)
1837+ {
1838+ }
1839+ try
1840+ {
1841+ string icon = parser()->get_string(SCOPE_CONFIG_GROUP, icon_str);
1842+ icon_.reset(new string(icon));
1843+ }
1844+ catch (LogicException const&)
1845+ {
1846+ }
1847+ try
1848+ {
1849+ string hint = parser()->get_string(SCOPE_CONFIG_GROUP, search_hint_str);
1850+ search_hint_.reset(new string(hint));
1851+ }
1852+ catch (LogicException const&)
1853+ {
1854+ }
1855+ try
1856+ {
1857+ string key = parser()->get_string(SCOPE_CONFIG_GROUP, hot_key_str);
1858+ hot_key_.reset(new string(key));
1859+ }
1860+ catch (LogicException const&)
1861+ {
1862+ }
1863 }
1864
1865 ScopeConfig::~ScopeConfig() noexcept
1866@@ -61,6 +106,52 @@
1867 return overrideable_;
1868 }
1869
1870+string ScopeConfig::display_name() const
1871+{
1872+ return display_name_;
1873+}
1874+
1875+string ScopeConfig::description() const
1876+{
1877+ return description_;
1878+}
1879+
1880+string ScopeConfig::art() const
1881+{
1882+ if (!art_)
1883+ {
1884+ throw NotFoundException("Art not set", art_str);
1885+ }
1886+ return *art_;
1887+}
1888+
1889+string ScopeConfig::icon() const
1890+{
1891+ if (!icon_)
1892+ {
1893+ throw NotFoundException("Icon not set", icon_str);
1894+ }
1895+ return *icon_;
1896+}
1897+
1898+string ScopeConfig::search_hint() const
1899+{
1900+ if (!search_hint_)
1901+ {
1902+ throw NotFoundException("Hint not set", search_hint_str);
1903+ }
1904+ return *search_hint_;
1905+}
1906+
1907+string ScopeConfig::hot_key() const
1908+{
1909+ if (!hot_key_)
1910+ {
1911+ throw NotFoundException("Key not set", hot_key_str);
1912+ }
1913+ return *hot_key_;
1914+}
1915+
1916 } // namespace internal
1917
1918 } // namespace scopes
1919
1920=== modified file 'src/internal/ScopeImpl.cpp'
1921--- src/internal/ScopeImpl.cpp 2013-11-25 19:05:41 +0000
1922+++ src/internal/ScopeImpl.cpp 2013-12-03 14:09:20 +0000
1923@@ -19,6 +19,7 @@
1924 #include <scopes/internal/ScopeImpl.h>
1925
1926 #include <scopes/internal/MiddlewareBase.h>
1927+#include <scopes/internal/MWScope.h>
1928 #include <scopes/internal/QueryCtrlImpl.h>
1929 #include <scopes/Scope.h>
1930 #include <unity/Exception.h>
1931
1932=== added file 'src/internal/ScopeMetadataImpl.cpp'
1933--- src/internal/ScopeMetadataImpl.cpp 1970-01-01 00:00:00 +0000
1934+++ src/internal/ScopeMetadataImpl.cpp 2013-12-03 14:09:20 +0000
1935@@ -0,0 +1,325 @@
1936+/*
1937+ * Copyright (C) 2013 Canonical Ltd
1938+ *
1939+ * This program is free software: you can redistribute it and/or modify
1940+ * it under the terms of the Lesser GNU General Public License version 3 as
1941+ * published by the Free Software Foundation.
1942+ *
1943+ * This program is distributed in the hope that it will be useful,
1944+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1945+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1946+ * GNU Lesser General Public License for more details.
1947+ *
1948+ * You should have received a copy of the Lesser GNU General Public License
1949+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1950+ *
1951+ * Authored by: Michi Henning <michi.henning@canonical.com>
1952+ */
1953+
1954+#include <scopes/internal/ScopeMetadataImpl.h>
1955+
1956+#include <scopes/internal/MiddlewareBase.h>
1957+#include <scopes/internal/ScopeImpl.h>
1958+#include <scopes/ScopeExceptions.h>
1959+#include <unity/UnityExceptions.h>
1960+
1961+using namespace std;
1962+using namespace unity;
1963+
1964+namespace unity
1965+{
1966+
1967+namespace api
1968+{
1969+
1970+namespace scopes
1971+{
1972+
1973+namespace internal
1974+{
1975+
1976+ScopeMetadataImpl::ScopeMetadataImpl(MiddlewareBase* mw) :
1977+ mw_(mw)
1978+{
1979+}
1980+
1981+ScopeMetadataImpl::ScopeMetadataImpl(const VariantMap& variant_map, MiddlewareBase* mw) :
1982+ mw_(mw)
1983+{
1984+ deserialize(variant_map);
1985+}
1986+
1987+ScopeMetadataImpl::ScopeMetadataImpl(ScopeMetadataImpl const& other) :
1988+ scope_name_(other.scope_name_),
1989+ proxy_(other.proxy_),
1990+ display_name_(other.display_name_),
1991+ description_(other.description_)
1992+{
1993+ if (other.art_)
1994+ {
1995+ art_.reset(new string(*other.art_));
1996+ }
1997+ if (other.icon_)
1998+ {
1999+ icon_.reset(new string(*other.icon_));
2000+ }
2001+ if (other.search_hint_)
2002+ {
2003+ search_hint_.reset(new string(*other.search_hint_));
2004+ }
2005+ if (other.hot_key_)
2006+ {
2007+ hot_key_.reset(new string(*other.hot_key_));
2008+ }
2009+}
2010+
2011+ScopeMetadataImpl& ScopeMetadataImpl::operator=(ScopeMetadataImpl const& rhs)
2012+{
2013+ if (this != &rhs)
2014+ {
2015+ scope_name_ = rhs.scope_name_;
2016+ proxy_ = rhs.proxy_;
2017+ display_name_ = rhs.display_name_;
2018+ description_ = rhs.description_;
2019+ art_.reset(rhs.art_ ? new string(*rhs.art_) : nullptr);
2020+ icon_.reset(rhs.icon_ ? new string(*rhs.icon_) : nullptr);
2021+ search_hint_.reset(rhs.search_hint_ ? new string(*rhs.search_hint_) : nullptr);
2022+ hot_key_.reset(rhs.hot_key_ ? new string(*rhs.hot_key_) : nullptr);
2023+ }
2024+ return *this;
2025+}
2026+
2027+std::string ScopeMetadataImpl::scope_name() const
2028+{
2029+ return scope_name_;
2030+}
2031+
2032+ScopeProxy ScopeMetadataImpl::proxy() const
2033+{
2034+ return proxy_;
2035+}
2036+
2037+std::string ScopeMetadataImpl::display_name() const
2038+{
2039+ return display_name_;
2040+}
2041+
2042+std::string ScopeMetadataImpl::description() const
2043+{
2044+ return description_;
2045+}
2046+
2047+std::string ScopeMetadataImpl::art() const
2048+{
2049+ if (art_)
2050+ {
2051+ return *art_;
2052+ }
2053+ throw NotFoundException("attribute not set", "art");
2054+}
2055+
2056+std::string ScopeMetadataImpl::icon() const
2057+{
2058+ if (icon_)
2059+ {
2060+ return *icon_;
2061+ }
2062+ throw NotFoundException("attribute not set", "icon");
2063+}
2064+
2065+std::string ScopeMetadataImpl::search_hint() const
2066+{
2067+ if (search_hint_)
2068+ {
2069+ return *search_hint_;
2070+ }
2071+ throw NotFoundException("attribute not set", "search_hint");
2072+}
2073+
2074+std::string ScopeMetadataImpl::hot_key() const
2075+{
2076+ if (hot_key_)
2077+ {
2078+ return *hot_key_;
2079+ }
2080+ throw NotFoundException("attribute not set", "hot_key");
2081+}
2082+
2083+void ScopeMetadataImpl::set_scope_name(std::string const& scope_name)
2084+{
2085+ scope_name_ = scope_name;
2086+}
2087+
2088+void ScopeMetadataImpl::set_proxy(ScopeProxy const& proxy)
2089+{
2090+ proxy_ = proxy;
2091+}
2092+
2093+void ScopeMetadataImpl::set_display_name(std::string const& display_name)
2094+{
2095+ display_name_ = display_name;
2096+}
2097+
2098+void ScopeMetadataImpl::set_description(std::string const& description)
2099+{
2100+ description_ = description;
2101+}
2102+
2103+void ScopeMetadataImpl::set_art(std::string const& art)
2104+{
2105+ art_.reset(new string(art));
2106+}
2107+
2108+void ScopeMetadataImpl::set_icon(std::string const& icon)
2109+{
2110+ icon_.reset(new string(icon));
2111+}
2112+
2113+void ScopeMetadataImpl::set_search_hint(std::string const& search_hint)
2114+{
2115+ search_hint_.reset(new string(search_hint));
2116+}
2117+
2118+void ScopeMetadataImpl::set_hot_key(std::string const& hot_key)
2119+{
2120+ hot_key_.reset(new string(hot_key));
2121+}
2122+
2123+namespace
2124+{
2125+
2126+void throw_on_empty(std::string const& name, std::string const& value)
2127+{
2128+ if (value.empty())
2129+ {
2130+ throw InvalidArgumentException("ScopeMetadata: required attribute '" + name + "' is empty");
2131+ }
2132+}
2133+
2134+} // namespace
2135+
2136+VariantMap ScopeMetadataImpl::serialize() const
2137+{
2138+ throw_on_empty("scope_name", scope_name_);
2139+ if (!proxy_)
2140+ {
2141+ throw InvalidArgumentException("ScopeMetadataImpl::serialize(): required attribute 'proxy' is null");
2142+ }
2143+ throw_on_empty("display_name", display_name_);
2144+ throw_on_empty("description", description_);
2145+
2146+ VariantMap var;
2147+ var["scope_name"] = scope_name_;
2148+ VariantMap proxy;
2149+ proxy["identity"] = proxy_->identity();
2150+ proxy["endpoint"] = proxy_->endpoint();
2151+ var["proxy"] = proxy;
2152+ var["display_name"] = display_name_;
2153+ var["description"] = description_;
2154+
2155+ // Optional fields
2156+ if (art_)
2157+ {
2158+ var["art"] = *art_;
2159+ }
2160+ if (icon_)
2161+ {
2162+ var["icon"] = *icon_;
2163+ }
2164+ if (search_hint_)
2165+ {
2166+ var["search_hint"] = *search_hint_;
2167+ }
2168+ if (hot_key_)
2169+ {
2170+ var["hot_key"] = *hot_key_;
2171+ }
2172+
2173+ return var;
2174+}
2175+
2176+namespace
2177+{
2178+
2179+VariantMap::const_iterator find_or_throw(VariantMap const& var, std::string const& name)
2180+{
2181+ auto it = var.find(name);
2182+ if (it == var.end())
2183+ {
2184+ throw InvalidArgumentException("ScopeMetadata::deserialize(): required attribute '" + name + "' is missing");
2185+ }
2186+ return it;
2187+}
2188+
2189+} // namespace
2190+
2191+void ScopeMetadataImpl::deserialize(VariantMap const& var)
2192+{
2193+ auto it = find_or_throw(var, "scope_name");
2194+ scope_name_ = it->second.get_string();
2195+ throw_on_empty("scope_name", scope_name_);
2196+
2197+ it = find_or_throw(var, "proxy");
2198+ auto proxy = it->second.get_dict();
2199+ auto it2 = proxy.find("identity");
2200+ if (it2 == proxy.end())
2201+ {
2202+ throw InvalidArgumentException("ScopeMetadataImpl::deserialize(): missing 'proxy.identity'");
2203+ }
2204+ auto identity = it2->second.get_string();
2205+ throw_on_empty("proxy.identity", identity);
2206+ it2 = proxy.find("endpoint");
2207+ if (it2 == proxy.end())
2208+ {
2209+ throw InvalidArgumentException("ScopeMetadataImpl::deserialize(): missing 'proxy.endpoint'");
2210+ }
2211+ auto endpoint = it2->second.get_string();
2212+ throw_on_empty("proxy.endpoint", endpoint);
2213+ auto mw_proxy = mw_->create_scope_proxy(identity, endpoint);
2214+ proxy_ = ScopeImpl::create(mw_proxy, mw_->runtime());
2215+
2216+ it = find_or_throw(var, "display_name");
2217+ display_name_ = it->second.get_string();
2218+
2219+ it = find_or_throw(var, "description");
2220+ description_ = it->second.get_string();
2221+
2222+ // Optional fields
2223+
2224+ it = var.find("art");
2225+ if (it != var.end())
2226+ {
2227+ art_.reset(new string(it->second.get_string()));
2228+ }
2229+
2230+ it = var.find("icon");
2231+ if (it != var.end())
2232+ {
2233+ icon_.reset(new string(it->second.get_string()));
2234+ }
2235+
2236+ it = var.find("search_hint");
2237+ if (it != var.end())
2238+ {
2239+ search_hint_.reset(new string(it->second.get_string()));
2240+ }
2241+
2242+ it = var.find("hot_key");
2243+ if (it != var.end())
2244+ {
2245+ hot_key_.reset(new string(it->second.get_string()));
2246+ }
2247+}
2248+
2249+ScopeMetadata ScopeMetadataImpl::create(unique_ptr<ScopeMetadataImpl> impl)
2250+{
2251+ return ScopeMetadata(move(impl));
2252+}
2253+
2254+} // namespace internal
2255+
2256+} // namespace scopes
2257+
2258+} // namespace api
2259+
2260+} // namespace unity
2261
2262=== modified file 'src/internal/zmq_middleware/RegistryI.cpp'
2263--- src/internal/zmq_middleware/RegistryI.cpp 2013-11-21 21:44:00 +0000
2264+++ src/internal/zmq_middleware/RegistryI.cpp 2013-12-03 14:09:20 +0000
2265@@ -21,6 +21,7 @@
2266 #include <internal/zmq_middleware/capnproto/Registry.capnp.h>
2267 #include <internal/zmq_middleware/capnproto/Scope.capnp.h>
2268 #include <scopes/internal/zmq_middleware/ObjectAdapter.h>
2269+#include <scopes/internal/zmq_middleware/VariantConverter.h>
2270 #include <scopes/internal/zmq_middleware/ZmqScope.h>
2271 #include <scopes/internal/RegistryObject.h>
2272 #include <scopes/ScopeExceptions.h>
2273@@ -48,7 +49,7 @@
2274
2275 interface Scope;
2276
2277-dictionary<string, Scope*> ScopeDictMap;
2278+dictionary<string, VariantMap> MetadataMap;
2279
2280 exception NotFoundException
2281 {
2282@@ -57,8 +58,8 @@
2283
2284 interface Registry
2285 {
2286- Scope* find(string name) throws NotFoundException;
2287- ScopeDict list();
2288+ Scope* get_metadata(string name) throws NotFoundException;
2289+ ScopeMap list();
2290 };
2291
2292 */
2293@@ -66,7 +67,7 @@
2294 using namespace std::placeholders;
2295
2296 RegistryI::RegistryI(RegistryObject::SPtr const& ro) :
2297- ServantBase(ro, { { "find", bind(&RegistryI::find_, this, _1, _2, _3) },
2298+ ServantBase(ro, { { "get_metadata", bind(&RegistryI::get_metadata_, this, _1, _2, _3) },
2299 { "list", bind(&RegistryI::list_, this, _1, _2, _3) } })
2300
2301 {
2302@@ -76,28 +77,26 @@
2303 {
2304 }
2305
2306-void RegistryI::find_(Current const&,
2307+void RegistryI::get_metadata_(Current const&,
2308 capnp::ObjectPointer::Reader& in_params,
2309 capnproto::Response::Builder& r)
2310 {
2311- auto req = in_params.getAs<capnproto::Registry::FindRequest>();
2312+ auto req = in_params.getAs<capnproto::Registry::GetMetadataRequest>();
2313 string name = req.getName().cStr();
2314 auto delegate = dynamic_pointer_cast<RegistryObject>(del());
2315 try
2316 {
2317- auto proxy = dynamic_pointer_cast<ZmqObjectProxy>(delegate->find(name));
2318- assert(proxy);
2319+ auto meta = delegate->get_metadata(name);
2320 r.setStatus(capnproto::ResponseStatus::SUCCESS);
2321- auto find_response = r.initPayload().getAs<capnproto::Registry::FindResponse>().initResponse();
2322- auto p = find_response.initReturnValue();
2323- p.setEndpoint(proxy->endpoint().c_str());
2324- p.setIdentity(proxy->identity().c_str());
2325+ auto get_metadata_response = r.initPayload().getAs<capnproto::Registry::GetMetadataResponse>().initResponse();
2326+ auto dict = get_metadata_response.initReturnValue();
2327+ to_value_dict(meta.serialize(), dict);
2328 }
2329 catch (NotFoundException const& e)
2330 {
2331 r.setStatus(capnproto::ResponseStatus::USER_EXCEPTION);
2332- auto find_response = r.initPayload().getAs<capnproto::Registry::FindResponse>().initResponse();
2333- find_response.initNotFoundException().setName(e.name().c_str());
2334+ auto get_metadata_response = r.initPayload().getAs<capnproto::Registry::GetMetadataResponse>().initResponse();
2335+ get_metadata_response.initNotFoundException().setName(e.name().c_str());
2336 }
2337 }
2338
2339@@ -106,18 +105,14 @@
2340 capnproto::Response::Builder& r)
2341 {
2342 auto delegate = dynamic_pointer_cast<RegistryObject>(del());
2343- auto scope_map = delegate->list();
2344+ auto metadata_map = delegate->list();
2345 r.setStatus(capnproto::ResponseStatus::SUCCESS);
2346- auto rv = r.initPayload().getAs<capnproto::Registry::ListResponse>().initReturnValue();
2347- auto list = rv.initPairs(scope_map.size());
2348+ auto rv = r.initPayload().getAs<capnproto::Registry::ListResponse>().initReturnValue(metadata_map.size());
2349 int i = 0;
2350- for (auto const& pair : scope_map)
2351+ for (auto& pair : metadata_map)
2352 {
2353- list[i].setName(pair.first.c_str());
2354- auto p = list[i].initScopeProxy();
2355- auto sp = dynamic_pointer_cast<ZmqScope>(pair.second);
2356- p.setEndpoint(sp->endpoint().c_str());
2357- p.setIdentity(sp->identity().c_str());
2358+ auto dict = rv[i];
2359+ to_value_dict(pair.second.serialize(), dict);
2360 ++i;
2361 }
2362 }
2363
2364=== modified file 'src/internal/zmq_middleware/ZmqConfig.cpp'
2365--- src/internal/zmq_middleware/ZmqConfig.cpp 2013-11-21 21:44:00 +0000
2366+++ src/internal/zmq_middleware/ZmqConfig.cpp 2013-12-03 14:09:20 +0000
2367@@ -43,10 +43,16 @@
2368 ZmqConfig::ZmqConfig(string const& configfile) :
2369 ConfigBase(configfile)
2370 {
2371- public_dir_ = get_string(ZMQ_CONFIG_GROUP, public_dir_str);
2372-
2373- // Private directory is not needed by all processes. It is retrieved
2374- // on demand during adapter creation.
2375+ if (configfile.empty())
2376+ {
2377+ public_dir_ = "/tmp";
2378+ private_dir_ = "/tmp";
2379+ }
2380+ else
2381+ {
2382+ public_dir_ = get_string(ZMQ_CONFIG_GROUP, public_dir_str);
2383+ private_dir_ = get_string(ZMQ_CONFIG_GROUP, private_dir_str);
2384+ }
2385 }
2386
2387 ZmqConfig::~ZmqConfig() noexcept
2388@@ -60,11 +66,6 @@
2389
2390 string ZmqConfig::private_dir() const
2391 {
2392- lock_guard<mutex> lock(mutex_);
2393- if (private_dir_.empty()) // Initialize first time only
2394- {
2395- private_dir_ = get_string(ZMQ_CONFIG_GROUP, private_dir_str);
2396- }
2397 return private_dir_;
2398 }
2399
2400
2401=== modified file 'src/internal/zmq_middleware/ZmqMiddleware.cpp'
2402--- src/internal/zmq_middleware/ZmqMiddleware.cpp 2013-11-21 21:44:00 +0000
2403+++ src/internal/zmq_middleware/ZmqMiddleware.cpp 2013-12-03 14:09:20 +0000
2404@@ -164,6 +164,20 @@
2405 state_changed_.wait(lock, [this] { return state_ == Stopped; }); // LCOV_EXCL_LINE
2406 }
2407
2408+MWProxy ZmqMiddleware::create_proxy(string const& identity, string const& endpoint)
2409+{
2410+ MWProxy proxy;
2411+ try
2412+ {
2413+ proxy.reset(new ZmqObjectProxy(this, endpoint, identity));
2414+ }
2415+ catch (zmqpp::exception const& e)
2416+ {
2417+ rethrow_zmq_ex(e);
2418+ }
2419+ return proxy;
2420+}
2421+
2422 MWRegistryProxy ZmqMiddleware::create_registry_proxy(string const& identity, string const& endpoint)
2423 {
2424 MWRegistryProxy proxy;
2425
2426=== modified file 'src/internal/zmq_middleware/ZmqObject.cpp'
2427--- src/internal/zmq_middleware/ZmqObject.cpp 2013-11-21 21:44:00 +0000
2428+++ src/internal/zmq_middleware/ZmqObject.cpp 2013-12-03 14:09:20 +0000
2429@@ -44,6 +44,16 @@
2430
2431 #define MONITOR_ENDPOINT "ipc:///tmp/scopes-monitor"
2432
2433+ZmqObjectProxy::ZmqObjectProxy(ZmqMiddleware* mw_base, string const& endpoint, string const& identity) :
2434+ MWObjectProxy(mw_base),
2435+ endpoint_(endpoint),
2436+ identity_(identity),
2437+ type_(Unknown)
2438+{
2439+ assert(!endpoint.empty());
2440+ assert(!identity.empty());
2441+}
2442+
2443 ZmqObjectProxy::ZmqObjectProxy(ZmqMiddleware* mw_base, string const& endpoint, string const& identity, RequestType t) :
2444 MWObjectProxy(mw_base),
2445 endpoint_(endpoint),
2446@@ -52,6 +62,7 @@
2447 {
2448 assert(!endpoint.empty());
2449 assert(!identity.empty());
2450+ assert(t != Unknown);
2451 }
2452
2453 ZmqObjectProxy::~ZmqObjectProxy() noexcept
2454
2455=== modified file 'src/internal/zmq_middleware/ZmqRegistry.cpp'
2456--- src/internal/zmq_middleware/ZmqRegistry.cpp 2013-11-21 21:44:00 +0000
2457+++ src/internal/zmq_middleware/ZmqRegistry.cpp 2013-12-03 14:09:20 +0000
2458@@ -19,9 +19,11 @@
2459 #include <scopes/internal/zmq_middleware/ZmqRegistry.h>
2460
2461 #include <internal/zmq_middleware/capnproto/Registry.capnp.h>
2462+#include <scopes/internal/zmq_middleware/VariantConverter.h>
2463 #include <scopes/internal/zmq_middleware/ZmqException.h>
2464 #include <scopes/internal/zmq_middleware/ZmqScope.h>
2465 #include <scopes/internal/ScopeImpl.h>
2466+#include <scopes/internal/ScopeMetadataImpl.h>
2467 #include <scopes/ScopeExceptions.h>
2468
2469 #include <capnp/message.h>
2470@@ -47,7 +49,7 @@
2471
2472 interface Scope;
2473
2474-dictionary<string, Scope*> ScopeDictMap;
2475+dictionary<string, ScopeMetadata> MetadataMap;
2476
2477 exception NotFoundException
2478 {
2479@@ -56,7 +58,7 @@
2480
2481 interface Registry
2482 {
2483- Scope* find(string name) throws NotFoundException;
2484+ ScopeMetadata get_metadata(string name) throws NotFoundException;
2485 ScopeDict list();
2486 };
2487
2488@@ -73,11 +75,11 @@
2489 {
2490 }
2491
2492-ScopeProxy ZmqRegistry::find(std::string const& scope_name)
2493+ScopeMetadata ZmqRegistry::get_metadata(std::string const& scope_name)
2494 {
2495 capnp::MallocMessageBuilder request_builder;
2496- auto request = make_request_(request_builder, "find");
2497- auto in_params = request.initInParams().getAs<capnproto::Registry::FindRequest>();
2498+ auto request = make_request_(request_builder, "get_metadata");
2499+ auto in_params = request.initInParams().getAs<capnproto::Registry::GetMetadataRequest>();
2500 in_params.setName(scope_name.c_str());
2501
2502 auto future = mw_base()->invoke_pool()->submit([&] { return this->invoke_(request_builder); });
2503@@ -88,28 +90,30 @@
2504 auto response = reader.getRoot<capnproto::Response>();
2505 throw_if_runtime_exception(response);
2506
2507- auto find_response = response.getPayload().getAs<capnproto::Registry::FindResponse>().getResponse();
2508- switch (find_response.which())
2509+ auto get_metadata_response = response.getPayload().getAs<capnproto::Registry::GetMetadataResponse>().getResponse();
2510+ switch (get_metadata_response.which())
2511 {
2512- case capnproto::Registry::FindResponse::Response::RETURN_VALUE:
2513+ case capnproto::Registry::GetMetadataResponse::Response::RETURN_VALUE:
2514 {
2515- auto proxy = find_response.getReturnValue();
2516- ZmqScopeProxy p(new ZmqScope(mw_base(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr()));
2517- return ScopeImpl::create(p, mw_base()->runtime());
2518+ auto md = get_metadata_response.getReturnValue();
2519+ VariantMap m = to_variant_map(md);
2520+ unique_ptr<ScopeMetadataImpl> smdi(new ScopeMetadataImpl(mw_base()));
2521+ smdi->deserialize(m);
2522+ return ScopeMetadata(ScopeMetadataImpl::create(move(smdi)));
2523 }
2524- case capnproto::Registry::FindResponse::Response::NOT_FOUND_EXCEPTION:
2525+ case capnproto::Registry::GetMetadataResponse::Response::NOT_FOUND_EXCEPTION:
2526 {
2527- auto ex = find_response.getNotFoundException();
2528- throw NotFoundException("Registry::find(): no such scope", ex.getName().cStr());
2529+ auto ex = get_metadata_response.getNotFoundException();
2530+ throw NotFoundException("Registry::get_metadata(): no such scope", ex.getName().cStr());
2531 }
2532 default:
2533 {
2534- throw MiddlewareException("Registry::find(): unknown user exception");
2535+ throw MiddlewareException("Registry::get_metadata(): unknown user exception");
2536 }
2537 }
2538 }
2539
2540-ScopeMap ZmqRegistry::list()
2541+MetadataMap ZmqRegistry::list()
2542 {
2543 capnp::MallocMessageBuilder request_builder;
2544 make_request_(request_builder, "list");
2545@@ -123,13 +127,16 @@
2546 throw_if_runtime_exception(response);
2547
2548 auto list_response = response.getPayload().getAs<capnproto::Registry::ListResponse>();
2549- auto pairs = list_response.getReturnValue().getPairs();
2550- ScopeMap sm;
2551- for (size_t i = 0; i < pairs.size(); ++i)
2552+ auto list = list_response.getReturnValue();
2553+ MetadataMap sm;
2554+ for (size_t i = 0; i < list.size(); ++i)
2555 {
2556- auto proxy = pairs[i].getScopeProxy();
2557- ZmqScopeProxy p(new ZmqScope(mw_base(), proxy.getEndpoint().cStr(), proxy.getIdentity().cStr()));
2558- sm[pairs[i].getName().cStr()] = ScopeImpl::create(p, mw_base()->runtime());
2559+ VariantMap m = to_variant_map(list[i]);
2560+ string scope_name = m["scope_name"].get_string();
2561+ unique_ptr<ScopeMetadataImpl> smdi(new ScopeMetadataImpl(mw_base()));
2562+ smdi->deserialize(m);
2563+ ScopeMetadata d(ScopeMetadataImpl::create(move(smdi)));
2564+ sm.emplace(make_pair(move(scope_name), move(d)));
2565 }
2566 return sm;
2567 }
2568
2569=== modified file 'src/internal/zmq_middleware/capnproto/Registry.capnp'
2570--- src/internal/zmq_middleware/capnproto/Registry.capnp 2013-09-17 08:02:23 +0000
2571+++ src/internal/zmq_middleware/capnproto/Registry.capnp 2013-12-03 14:09:20 +0000
2572@@ -22,31 +22,31 @@
2573
2574 $Cxx.namespace("unity::api::scopes::internal::zmq_middleware::capnproto::Registry");
2575
2576-using ScopeDict = import "ScopeDict.capnp";
2577+using ValueDict = import "ValueDict.capnp";
2578 using Proxy = import "Proxy.capnp";
2579
2580 # Registry interface
2581 #
2582 # Operations:
2583 #
2584-# Proxy find(string name) throws NotFoundException;
2585-# ScopeDict list();
2586+# ValueDict get_metadata(string name) throws NotFoundException;
2587+# map<string, ScopeMetadata> list();
2588
2589 struct NotFoundException
2590 {
2591 name @0 : Text;
2592 }
2593
2594-struct FindRequest
2595+struct GetMetadataRequest
2596 {
2597 name @0 : Text;
2598 }
2599
2600-struct FindResponse
2601+struct GetMetadataResponse
2602 {
2603 response : union
2604 {
2605- returnValue @0 : Proxy.Proxy;
2606+ returnValue @0 : ValueDict.ValueDict;
2607 notFoundException @1 : NotFoundException;
2608 }
2609 }
2610@@ -57,5 +57,5 @@
2611
2612 struct ListResponse
2613 {
2614- returnValue @0 : ScopeDict.ScopeDict;
2615+ returnValue @0 : List(ValueDict.ValueDict);
2616 }
2617
2618=== modified file 'test/gtest/unity/api/scopes/ResultItem/ResultItem_test.cpp'
2619--- test/gtest/unity/api/scopes/ResultItem/ResultItem_test.cpp 2013-11-27 10:44:35 +0000
2620+++ test/gtest/unity/api/scopes/ResultItem/ResultItem_test.cpp 2013-12-03 14:09:20 +0000
2621@@ -116,6 +116,15 @@
2622 EXPECT_EQ("dnd_uri b", copy.dnd_uri());
2623 EXPECT_EQ("xyz", copy.serialize()["foo"].get_string());
2624 EXPECT_EQ("1", copy.category()->id());
2625+
2626+ ResultItem copy2(cat);
2627+ copy2 = copy;
2628+ EXPECT_EQ("uri b", copy2.uri());
2629+ EXPECT_EQ("title b", copy2.title());
2630+ EXPECT_EQ("icon b", copy2.art());
2631+ EXPECT_EQ("dnd_uri b", copy2.dnd_uri());
2632+ EXPECT_EQ("xyz", copy2.serialize()["foo"].get_string());
2633+ EXPECT_EQ("1", copy2.category()->id());
2634 }
2635 }
2636
2637
2638=== modified file 'test/gtest/unity/api/scopes/Runtime/CMakeLists.txt'
2639--- test/gtest/unity/api/scopes/Runtime/CMakeLists.txt 2013-11-19 02:51:46 +0000
2640+++ test/gtest/unity/api/scopes/Runtime/CMakeLists.txt 2013-12-03 14:09:20 +0000
2641@@ -1,4 +1,3 @@
2642-configure_file(Factory.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Factory.ini)
2643 configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini)
2644 configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini)
2645 configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini)
2646
2647=== removed file 'test/gtest/unity/api/scopes/Runtime/Factory.ini.in'
2648--- test/gtest/unity/api/scopes/Runtime/Factory.ini.in 2013-09-17 08:02:23 +0000
2649+++ test/gtest/unity/api/scopes/Runtime/Factory.ini.in 1970-01-01 00:00:00 +0000
2650@@ -1,2 +0,0 @@
2651-[MiddlewareFactory]
2652-Zmq.Configfile =
2653
2654=== modified file 'test/gtest/unity/api/scopes/Variant/Variant_test.cpp'
2655--- test/gtest/unity/api/scopes/Variant/Variant_test.cpp 2013-11-19 15:35:07 +0000
2656+++ test/gtest/unity/api/scopes/Variant/Variant_test.cpp 2013-12-03 14:09:20 +0000
2657@@ -106,6 +106,9 @@
2658 v = 99;
2659 EXPECT_EQ(99, v.get_int());
2660
2661+ v = 10.5f;
2662+ EXPECT_TRUE(v.get_double() - 10.5f < 0.00001f);
2663+
2664 v = false;
2665 EXPECT_FALSE(v.get_bool());
2666
2667
2668=== modified file 'test/gtest/unity/api/scopes/internal/CMakeLists.txt'
2669--- test/gtest/unity/api/scopes/internal/CMakeLists.txt 2013-11-18 08:14:46 +0000
2670+++ test/gtest/unity/api/scopes/internal/CMakeLists.txt 2013-12-03 14:09:20 +0000
2671@@ -3,12 +3,12 @@
2672 add_subdirectory(DynamicLoader)
2673 add_subdirectory(lttng)
2674 add_subdirectory(MiddlewareFactory)
2675-add_subdirectory(MiddlewareFactoryConfig)
2676 add_subdirectory(Reaper)
2677 add_subdirectory(RegistryConfig)
2678 add_subdirectory(RuntimeConfig)
2679 add_subdirectory(RuntimeImpl)
2680 add_subdirectory(ScopeLoader)
2681+add_subdirectory(ScopeMetadataImpl)
2682 add_subdirectory(ThreadPool)
2683 add_subdirectory(ThreadSafeQueue)
2684 add_subdirectory(UniqueID)
2685
2686=== modified file 'test/gtest/unity/api/scopes/internal/MiddlewareFactory/CMakeLists.txt'
2687--- test/gtest/unity/api/scopes/internal/MiddlewareFactory/CMakeLists.txt 2013-09-23 06:13:06 +0000
2688+++ test/gtest/unity/api/scopes/internal/MiddlewareFactory/CMakeLists.txt 2013-12-03 14:09:20 +0000
2689@@ -1,5 +1,3 @@
2690-configure_file(Factory.ini.in Factory.ini)
2691-
2692 add_executable(MiddlewareFactory_test MiddlewareFactory_test.cpp)
2693 target_link_libraries(MiddlewareFactory_test ${TESTLIBS})
2694
2695
2696=== removed file 'test/gtest/unity/api/scopes/internal/MiddlewareFactory/Factory.ini.in'
2697--- test/gtest/unity/api/scopes/internal/MiddlewareFactory/Factory.ini.in 2013-08-06 01:51:26 +0000
2698+++ test/gtest/unity/api/scopes/internal/MiddlewareFactory/Factory.ini.in 1970-01-01 00:00:00 +0000
2699@@ -1,3 +0,0 @@
2700-[MiddlewareFactory]
2701-Ice.Configfile = Ice.Config
2702-REST.Configfile = REST.Config
2703
2704=== modified file 'test/gtest/unity/api/scopes/internal/MiddlewareFactory/MiddlewareFactory_test.cpp'
2705--- test/gtest/unity/api/scopes/internal/MiddlewareFactory/MiddlewareFactory_test.cpp 2013-11-01 12:44:48 +0000
2706+++ test/gtest/unity/api/scopes/internal/MiddlewareFactory/MiddlewareFactory_test.cpp 2013-12-03 14:09:20 +0000
2707@@ -27,10 +27,10 @@
2708
2709 TEST(MiddlewareFactory, basic)
2710 {
2711- MiddlewareFactory f("Factory.ini", (RuntimeImpl*)0x1);
2712- EXPECT_EQ(nullptr, f.find("nosuchscope", "Ice"));
2713+ MiddlewareFactory f((RuntimeImpl*)0x1);
2714+ EXPECT_EQ(nullptr, f.find("nosuchscope", "Zmq"));
2715 MiddlewareBase::SPtr not_found;
2716- MiddlewareBase::SPtr mw = f.find("testscope", "Ice");
2717+ MiddlewareBase::SPtr mw = f.find("testscope", "Zmq");
2718 EXPECT_EQ(not_found, mw);
2719 mw = f.find("testscope", "NoSuchMiddleware");
2720 EXPECT_EQ(not_found, mw);
2721@@ -40,8 +40,8 @@
2722 {
2723 try
2724 {
2725- MiddlewareFactory f("Factory.ini", (RuntimeImpl*)0x1);
2726- f.create("somescope", "NoSuchMiddleware", "Ice.Config");
2727+ MiddlewareFactory f((RuntimeImpl*)0x1);
2728+ f.create("somescope", "NoSuchMiddleware", "Zmq.ini");
2729 FAIL();
2730 }
2731 catch (ConfigException const& e)
2732@@ -49,20 +49,3 @@
2733 EXPECT_EQ("unity::api::scopes::ConfigException: Invalid middleware kind: NoSuchMiddleware", e.to_string());
2734 }
2735 }
2736-
2737-TEST(MiddlewareFactory, BadIniFile)
2738-{
2739- try
2740- {
2741- MiddlewareFactory f("NoSuchFile.ini", (RuntimeImpl*)0x1);
2742- FAIL();
2743- }
2744- catch (ConfigException const& e)
2745- {
2746- EXPECT_EQ("unity::api::scopes::ConfigException: cannot instantiate MiddlewareFactory: "
2747- "config file: NoSuchFile.ini:\n"
2748- " unity::FileException: Could not load ini file NoSuchFile.ini: "
2749- "No such file or directory (errno = 4)",
2750- e.to_string());
2751- }
2752-}
2753
2754=== removed directory 'test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig'
2755=== removed file 'test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/CMakeLists.txt'
2756--- test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/CMakeLists.txt 2013-08-06 01:51:26 +0000
2757+++ test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/CMakeLists.txt 1970-01-01 00:00:00 +0000
2758@@ -1,6 +0,0 @@
2759-configure_file(Factory.ini.in Factory.ini)
2760-
2761-add_executable(MiddlewareFactoryConfig_test MiddlewareFactoryConfig_test.cpp)
2762-target_link_libraries(MiddlewareFactoryConfig_test ${TESTLIBS})
2763-
2764-add_test(MiddlewareFactoryConfig MiddlewareFactoryConfig_test)
2765
2766=== removed file 'test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/Factory.ini.in'
2767--- test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/Factory.ini.in 2013-11-19 02:51:46 +0000
2768+++ test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/Factory.ini.in 1970-01-01 00:00:00 +0000
2769@@ -1,3 +0,0 @@
2770-[MiddlewareFactory]
2771-Zmq.ConfigFile = Zmq.ini
2772-REST.ConfigFile = REST.ini
2773
2774=== removed file 'test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/MiddlewareFactoryConfig_test.cpp'
2775--- test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/MiddlewareFactoryConfig_test.cpp 2013-11-19 02:51:46 +0000
2776+++ test/gtest/unity/api/scopes/internal/MiddlewareFactoryConfig/MiddlewareFactoryConfig_test.cpp 1970-01-01 00:00:00 +0000
2777@@ -1,31 +0,0 @@
2778-/*
2779- * Copyright (C) 2013 Canonical Ltd
2780- *
2781- * This program is free software: you can redistribute it and/or modify
2782- * it under the terms of the GNU Lesser General Public License version 3 as
2783- * published by the Free Software Foundation.
2784- *
2785- * This program is distributed in the hope that it will be useful,
2786- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2787- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2788- * GNU Lesser General Public License for more details.
2789- *
2790- * You should have received a copy of the GNU Lesser General Public License
2791- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2792- *
2793- * Authored by: Michi Henning <michi.henning@canonical.com>
2794- */
2795-
2796-#include <scopes/internal/MiddlewareFactoryConfig.h>
2797-
2798-#include <gtest/gtest.h>
2799-
2800-using namespace std;
2801-using namespace unity::api::scopes::internal;
2802-
2803-TEST(MiddlewareFactoryConfig, basic)
2804-{
2805- MiddlewareFactoryConfig c("Factory.ini");
2806- EXPECT_EQ("Zmq.ini", c.zmq_configfile());
2807- EXPECT_EQ("REST.ini", c.rest_configfile());
2808-}
2809
2810=== modified file 'test/gtest/unity/api/scopes/internal/RuntimeConfig/RuntimeConfig_test.cpp'
2811--- test/gtest/unity/api/scopes/internal/RuntimeConfig/RuntimeConfig_test.cpp 2013-11-19 02:51:46 +0000
2812+++ test/gtest/unity/api/scopes/internal/RuntimeConfig/RuntimeConfig_test.cpp 2013-12-03 14:09:20 +0000
2813@@ -27,7 +27,7 @@
2814
2815 TEST(RuntimeConfig, basic)
2816 {
2817- RuntimeConfig c;
2818+ RuntimeConfig c("");
2819 EXPECT_EQ("Registry", c.registry_identity());
2820 EXPECT_EQ("Registry.ini", c.registry_configfile());
2821 EXPECT_EQ("Zmq", c.default_middleware());
2822
2823=== modified file 'test/gtest/unity/api/scopes/internal/RuntimeImpl/CMakeLists.txt'
2824--- test/gtest/unity/api/scopes/internal/RuntimeImpl/CMakeLists.txt 2013-11-19 02:51:46 +0000
2825+++ test/gtest/unity/api/scopes/internal/RuntimeImpl/CMakeLists.txt 2013-12-03 14:09:20 +0000
2826@@ -1,4 +1,3 @@
2827-configure_file(Factory.ini.in Factory.ini)
2828 configure_file(Zmq.ini.in Zmq.ini)
2829 configure_file(Registry.ini.in Registry.ini)
2830 configure_file(Runtime.ini.in Runtime.ini)
2831
2832=== removed file 'test/gtest/unity/api/scopes/internal/RuntimeImpl/Factory.ini.in'
2833--- test/gtest/unity/api/scopes/internal/RuntimeImpl/Factory.ini.in 2013-08-05 06:02:03 +0000
2834+++ test/gtest/unity/api/scopes/internal/RuntimeImpl/Factory.ini.in 1970-01-01 00:00:00 +0000
2835@@ -1,2 +0,0 @@
2836-[MiddlewareFactory]
2837-Ice.Configfile =
2838
2839=== modified file 'test/gtest/unity/api/scopes/internal/RuntimeImpl/RuntimeImpl_test.cpp'
2840--- test/gtest/unity/api/scopes/internal/RuntimeImpl/RuntimeImpl_test.cpp 2013-11-19 02:51:46 +0000
2841+++ test/gtest/unity/api/scopes/internal/RuntimeImpl/RuntimeImpl_test.cpp 2013-12-03 14:09:20 +0000
2842@@ -29,7 +29,6 @@
2843
2844 TEST(RuntimeImpl, basic)
2845 {
2846-try{
2847 RuntimeImpl::UPtr rt = RuntimeImpl::create("testscope");
2848
2849 EXPECT_TRUE(rt->registry().get() != nullptr);
2850@@ -61,11 +60,6 @@
2851 e.to_string());
2852 }
2853 }
2854-catch(unity::Exception const& e)
2855-{
2856- cout << e.to_string() << endl;
2857-}
2858-}
2859
2860 TEST(RuntimeImpl, error)
2861 {
2862
2863=== added directory 'test/gtest/unity/api/scopes/internal/ScopeMetadataImpl'
2864=== added file 'test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/CMakeLists.txt'
2865--- test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/CMakeLists.txt 1970-01-01 00:00:00 +0000
2866+++ test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/CMakeLists.txt 2013-12-03 14:09:20 +0000
2867@@ -0,0 +1,6 @@
2868+configure_file(Zmq.ini.in Zmq.ini)
2869+
2870+add_executable(ScopeMetadataImpl_test ScopeMetadataImpl_test.cpp)
2871+target_link_libraries(ScopeMetadataImpl_test ${TESTLIBS})
2872+
2873+add_test(ScopeMetadataImpl ScopeMetadataImpl_test)
2874
2875=== added file 'test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp'
2876--- test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp 1970-01-01 00:00:00 +0000
2877+++ test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp 2013-12-03 14:09:20 +0000
2878@@ -0,0 +1,388 @@
2879+/*
2880+ * Copyright (C) 2013 Canonical Ltd
2881+ *
2882+ * This program is free software: you can redistribute it and/or modify
2883+ * it under the terms of the GNU Lesser General Public License version 3 as
2884+ * published by the Free Software Foundation.
2885+ *
2886+ * This program is distributed in the hope that it will be useful,
2887+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2888+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2889+ * GNU Lesser General Public License for more details.
2890+ *
2891+ * You should have received a copy of the GNU Lesser General Public License
2892+ * along with this program. If not, see <http://www.gnu.org/lzmqnses/>.
2893+ *
2894+ * Authored by: Michi Henning <michi.henning@canonical.com>
2895+ */
2896+
2897+#include <scopes/internal/ScopeMetadataImpl.h>
2898+
2899+#include <scopes/internal/ScopeImpl.h>
2900+#include <scopes/internal/zmq_middleware/ZmqMiddleware.h>
2901+#include <scopes/ScopeExceptions.h>
2902+#include <unity/UnityExceptions.h>
2903+
2904+#include <boost/regex.hpp> // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed.
2905+#include <gtest/gtest.h>
2906+#include <scope-api-testconfig.h>
2907+
2908+using namespace std;
2909+using namespace unity;
2910+using namespace unity::api::scopes;
2911+using namespace unity::api::scopes::internal;
2912+using namespace unity::api::scopes::internal::zmq_middleware;
2913+
2914+TEST(ScopeMetadataImpl, basic)
2915+{
2916+ ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/unity/api/scopes/internal/ScopeMetadataImpl/Zmq.ini",
2917+ (RuntimeImpl*)0x1);
2918+
2919+ unique_ptr<ScopeMetadataImpl> mi(new ScopeMetadataImpl(&mw));
2920+ mi->set_scope_name("scope_name");
2921+ auto mw_proxy = mw.create_scope_proxy("identity", "endpoint");
2922+ mi->set_proxy(ScopeImpl::create(mw_proxy, mw.runtime()));
2923+ mi->set_display_name("display_name");
2924+ mi->set_description("description");
2925+
2926+ // Keep a copy for tests below
2927+ unique_ptr<ScopeMetadataImpl> mi2(new ScopeMetadataImpl(*mi));
2928+
2929+ // Create the public instance and check that the values match
2930+ auto m = ScopeMetadataImpl::create(move(mi));
2931+ EXPECT_EQ("scope_name", m.scope_name());
2932+ EXPECT_EQ("identity", m.proxy()->identity());
2933+ EXPECT_EQ("endpoint", m.proxy()->endpoint());
2934+ EXPECT_EQ("display_name", m.display_name());
2935+ EXPECT_EQ("description", m.description());
2936+
2937+ // Check that optional fields that are not set throw
2938+ try
2939+ {
2940+ m.art();
2941+ FAIL();
2942+ }
2943+ catch (NotFoundException const& e)
2944+ {
2945+ EXPECT_EQ("unity::api::scopes::NotFoundException: attribute not set (name = art)", e.to_string());
2946+ }
2947+
2948+ try
2949+ {
2950+ m.icon();
2951+ FAIL();
2952+ }
2953+ catch (NotFoundException const& e)
2954+ {
2955+ EXPECT_EQ("unity::api::scopes::NotFoundException: attribute not set (name = icon)", e.to_string());
2956+ }
2957+
2958+ try
2959+ {
2960+ m.search_hint();
2961+ FAIL();
2962+ }
2963+ catch (NotFoundException const& e)
2964+ {
2965+ EXPECT_EQ("unity::api::scopes::NotFoundException: attribute not set (name = search_hint)", e.to_string());
2966+ }
2967+
2968+ try
2969+ {
2970+ m.hot_key();
2971+ FAIL();
2972+ }
2973+ catch (NotFoundException const& e)
2974+ {
2975+ EXPECT_EQ("unity::api::scopes::NotFoundException: attribute not set (name = hot_key)", e.to_string());
2976+ }
2977+
2978+ // Check that the copy has the same values as the original
2979+ EXPECT_EQ("scope_name", mi2->scope_name());
2980+ EXPECT_EQ("identity", mi2->proxy()->identity());
2981+ EXPECT_EQ("endpoint", mi2->proxy()->endpoint());
2982+ EXPECT_EQ("display_name", mi2->display_name());
2983+ EXPECT_EQ("description", mi2->description());
2984+
2985+ // Set optional fields on copy.
2986+ mi2->set_art("art");
2987+ mi2->set_icon("icon");
2988+ mi2->set_search_hint("search_hint");
2989+ mi2->set_hot_key("hot_key");
2990+
2991+ // Make another copy, so we get coverage on the entire copy constructor
2992+ unique_ptr<ScopeMetadataImpl> mi3(new ScopeMetadataImpl(*mi2));
2993+
2994+ // Check that optional fields are set correctly
2995+ m = ScopeMetadataImpl::create(move(mi2));
2996+ EXPECT_EQ("search_hint", m.search_hint());
2997+ EXPECT_EQ("hot_key", m.hot_key());
2998+
2999+ // Make another value
3000+ unique_ptr<ScopeMetadataImpl> ti(new ScopeMetadataImpl(&mw));
3001+ ti->set_scope_name("tmp scope_name");
3002+ mw_proxy = mw.create_scope_proxy("tmp identity", "tmp endpoint");
3003+ ti->set_proxy(ScopeImpl::create(mw_proxy, mw.runtime()));
3004+ ti->set_display_name("tmp display_name");
3005+ ti->set_description("tmp description");
3006+ ti->set_art("tmp art");
3007+ ti->set_icon("tmp icon");
3008+ ti->set_search_hint("tmp search_hint");
3009+ ti->set_hot_key("tmp hot_key");
3010+
3011+ // Check impl assignment operator
3012+ ScopeMetadataImpl ci(&mw);
3013+ ci = *ti;
3014+ EXPECT_EQ("tmp scope_name", ci.scope_name());
3015+ EXPECT_EQ("tmp identity", ci.proxy()->identity());
3016+ EXPECT_EQ("tmp endpoint", ci.proxy()->endpoint());
3017+ EXPECT_EQ("tmp display_name", ci.display_name());
3018+ EXPECT_EQ("tmp description", ci.description());
3019+ EXPECT_EQ("tmp art", ci.art());
3020+ EXPECT_EQ("tmp icon", ci.icon());
3021+ EXPECT_EQ("tmp search_hint", ci.search_hint());
3022+ EXPECT_EQ("tmp hot_key", ci.hot_key());
3023+
3024+ // Check public assignment operator
3025+ auto tmp = ScopeMetadataImpl::create(move(ti));
3026+ m = tmp;
3027+ EXPECT_EQ("tmp scope_name", m.scope_name());
3028+ EXPECT_EQ("tmp identity", m.proxy()->identity());
3029+ EXPECT_EQ("tmp endpoint", m.proxy()->endpoint());
3030+ EXPECT_EQ("tmp display_name", m.display_name());
3031+ EXPECT_EQ("tmp description", m.description());
3032+ EXPECT_EQ("tmp art", m.art());
3033+ EXPECT_EQ("tmp icon", m.icon());
3034+ EXPECT_EQ("tmp search_hint", m.search_hint());
3035+ EXPECT_EQ("tmp hot_key", m.hot_key());
3036+
3037+ // Self-assignment
3038+ tmp = tmp;
3039+ EXPECT_EQ("tmp scope_name", tmp.scope_name());
3040+ EXPECT_EQ("tmp identity", tmp.proxy()->identity());
3041+ EXPECT_EQ("tmp endpoint", tmp.proxy()->endpoint());
3042+ EXPECT_EQ("tmp display_name", tmp.display_name());
3043+ EXPECT_EQ("tmp description", tmp.description());
3044+ EXPECT_EQ("tmp art", tmp.art());
3045+ EXPECT_EQ("tmp icon", tmp.icon());
3046+ EXPECT_EQ("tmp search_hint", tmp.search_hint());
3047+ EXPECT_EQ("tmp hot_key", tmp.hot_key());
3048+
3049+ // Copy constructor
3050+ ScopeMetadata tmp2(tmp);
3051+ EXPECT_EQ("tmp scope_name", tmp2.scope_name());
3052+ EXPECT_EQ("tmp identity", tmp2.proxy()->identity());
3053+ EXPECT_EQ("tmp endpoint", tmp2.proxy()->endpoint());
3054+ EXPECT_EQ("tmp display_name", tmp2.display_name());
3055+ EXPECT_EQ("tmp description", tmp2.description());
3056+ EXPECT_EQ("tmp art", tmp2.art());
3057+ EXPECT_EQ("tmp icon", tmp2.icon());
3058+ EXPECT_EQ("tmp search_hint", tmp2.search_hint());
3059+ EXPECT_EQ("tmp hot_key", tmp2.hot_key());
3060+}
3061+
3062+TEST(ScopeMetadataImpl, serialize)
3063+{
3064+ ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/unity/api/scopes/internal/ScopeMetadataImpl/Zmq.ini",
3065+ (RuntimeImpl*)0x1);
3066+
3067+ unique_ptr<ScopeMetadataImpl> mi(new ScopeMetadataImpl(&mw));
3068+ mi->set_scope_name("scope_name");
3069+ auto mw_proxy = mw.create_scope_proxy("identity", "endpoint");
3070+ mi->set_proxy(ScopeImpl::create(mw_proxy, mw.runtime()));
3071+ mi->set_display_name("display_name");
3072+ mi->set_description("description");
3073+ mi->set_art("art");
3074+ mi->set_icon("icon");
3075+ mi->set_search_hint("search_hint");
3076+ mi->set_hot_key("hot_key");
3077+
3078+ // Check that serialize() sets the map values correctly
3079+ auto m = ScopeMetadataImpl::create(move(mi));
3080+ auto var = m.serialize();
3081+ EXPECT_EQ(8, var.size());
3082+ EXPECT_EQ("scope_name", var["scope_name"].get_string());
3083+ EXPECT_EQ("display_name", var["display_name"].get_string());
3084+ EXPECT_EQ("description", var["description"].get_string());
3085+ EXPECT_EQ("art", var["art"].get_string());
3086+ EXPECT_EQ("icon", var["icon"].get_string());
3087+ EXPECT_EQ("search_hint", var["search_hint"].get_string());
3088+ EXPECT_EQ("hot_key", var["hot_key"].get_string());
3089+
3090+ // Make another instance from the VariantMap and check its fields
3091+ ScopeMetadataImpl c(var, &mw);
3092+ EXPECT_EQ("scope_name", c.scope_name());
3093+ EXPECT_EQ("identity", c.proxy()->identity());
3094+ EXPECT_EQ("endpoint", c.proxy()->endpoint());
3095+ EXPECT_EQ("display_name", c.display_name());
3096+ EXPECT_EQ("description", c.description());
3097+ EXPECT_EQ("art", c.art());
3098+ EXPECT_EQ("icon", c.icon());
3099+ EXPECT_EQ("search_hint", c.search_hint());
3100+ EXPECT_EQ("hot_key", c.hot_key());
3101+}
3102+
3103+TEST(ScopeMetadataImpl, serialize_exceptions)
3104+{
3105+ ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/unity/api/scopes/internal/ScopeMetadataImpl/Zmq.ini",
3106+ (RuntimeImpl*)0x1);
3107+
3108+ ScopeMetadataImpl mi(&mw);
3109+ try
3110+ {
3111+ mi.serialize();
3112+ FAIL();
3113+ }
3114+ catch (InvalidArgumentException const&e)
3115+ {
3116+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadata: required attribute 'scope_name' is empty",
3117+ e.to_string());
3118+ }
3119+
3120+ try
3121+ {
3122+ mi.set_scope_name("scope_name");
3123+ mi.serialize();
3124+ FAIL();
3125+ }
3126+ catch (InvalidArgumentException const&e)
3127+ {
3128+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadataImpl::serialize(): required attribute 'proxy' is null",
3129+ e.to_string());
3130+ }
3131+
3132+ try
3133+ {
3134+ auto mw_proxy = mw.create_scope_proxy("identity", "endpoint");
3135+ mi.set_proxy(ScopeImpl::create(mw_proxy, mw.runtime()));
3136+ mi.serialize();
3137+ FAIL();
3138+ }
3139+ catch (InvalidArgumentException const&e)
3140+ {
3141+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadata: required attribute 'display_name' is empty",
3142+ e.to_string());
3143+ }
3144+
3145+ try
3146+ {
3147+ mi.set_display_name("display_name");
3148+ mi.serialize();
3149+ FAIL();
3150+ }
3151+ catch (InvalidArgumentException const&e)
3152+ {
3153+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadata: required attribute 'description' is empty",
3154+ e.to_string());
3155+ }
3156+}
3157+
3158+TEST(ScopeMetadataImpl, deserialize_exceptions)
3159+{
3160+ ZmqMiddleware mw("testscope", TEST_BUILD_ROOT "/gtest/unity/api/scopes/internal/ScopeMetadataImpl/Zmq.ini",
3161+ (RuntimeImpl*)0x1);
3162+
3163+ VariantMap m;
3164+ try
3165+ {
3166+ ScopeMetadataImpl mi(m, &mw);
3167+ mi.deserialize(m);
3168+ FAIL();
3169+ }
3170+ catch (InvalidArgumentException const&e)
3171+ {
3172+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadata::deserialize(): required attribute "
3173+ "'scope_name' is missing",
3174+ e.to_string());
3175+ }
3176+
3177+ m["scope_name"] = "scope_name";
3178+ try
3179+ {
3180+ ScopeMetadataImpl mi(m, &mw);
3181+ mi.deserialize(m);
3182+ FAIL();
3183+ }
3184+ catch (InvalidArgumentException const&e)
3185+ {
3186+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadata::deserialize(): required attribute "
3187+ "'proxy' is missing",
3188+ e.to_string());
3189+ }
3190+
3191+ VariantMap proxy;
3192+ m["proxy"] = proxy;
3193+ try
3194+ {
3195+ ScopeMetadataImpl mi(m, &mw);
3196+ mi.deserialize(m);
3197+ FAIL();
3198+ }
3199+ catch (InvalidArgumentException const&e)
3200+ {
3201+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadataImpl::deserialize(): missing 'proxy.identity'",
3202+ e.to_string());
3203+ }
3204+
3205+ proxy["identity"] = "identity";
3206+ m["proxy"] = proxy;
3207+ try
3208+ {
3209+ ScopeMetadataImpl mi(m, &mw);
3210+ mi.deserialize(m);
3211+ FAIL();
3212+ }
3213+ catch (InvalidArgumentException const&e)
3214+ {
3215+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadataImpl::deserialize(): missing 'proxy.endpoint'",
3216+ e.to_string());
3217+ }
3218+
3219+ proxy["endpoint"] = "endpoint";
3220+ m["proxy"] = proxy;
3221+ try
3222+ {
3223+ ScopeMetadataImpl mi(m, &mw);
3224+ mi.deserialize(m);
3225+ FAIL();
3226+ }
3227+ catch (InvalidArgumentException const&e)
3228+ {
3229+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadata::deserialize(): required attribute "
3230+ "'display_name' is missing",
3231+ e.to_string());
3232+ }
3233+
3234+ m["display_name"] = "display_name";
3235+ try
3236+ {
3237+ ScopeMetadataImpl mi(m, &mw);
3238+ mi.deserialize(m);
3239+ FAIL();
3240+ }
3241+ catch (InvalidArgumentException const&e)
3242+ {
3243+ EXPECT_EQ("unity::InvalidArgumentException: ScopeMetadata::deserialize(): required attribute "
3244+ "'description' is missing",
3245+ e.to_string());
3246+ }
3247+ m["description"] = "description";
3248+
3249+ // Optional attributes
3250+ m["art"] = "art";
3251+ m["icon"] = "icon";
3252+ m["search_hint"] = "search_hint";
3253+ m["hot_key"] = "hot_key";
3254+
3255+ ScopeMetadataImpl mi(m, &mw);
3256+ mi.deserialize(m);
3257+ EXPECT_EQ("scope_name", mi.scope_name());
3258+ EXPECT_EQ("identity", mi.proxy()->identity());
3259+ EXPECT_EQ("endpoint", mi.proxy()->endpoint());
3260+ EXPECT_EQ("display_name", mi.display_name());
3261+ EXPECT_EQ("description", mi.description());
3262+ EXPECT_EQ("art", mi.art());
3263+ EXPECT_EQ("icon", mi.icon());
3264+ EXPECT_EQ("search_hint", mi.search_hint());
3265+ EXPECT_EQ("hot_key", mi.hot_key());
3266+}
3267
3268=== added file 'test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/Zmq.ini.in'
3269--- test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/Zmq.ini.in 1970-01-01 00:00:00 +0000
3270+++ test/gtest/unity/api/scopes/internal/ScopeMetadataImpl/Zmq.ini.in 2013-12-03 14:09:20 +0000
3271@@ -0,0 +1,3 @@
3272+[Zmq]
3273+EndpointDir.Public = /tmp
3274+EndpointDir.Private = /tmp
3275
3276=== modified file 'test/gtest/unity/api/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini.in'
3277--- test/gtest/unity/api/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini.in 2013-11-19 02:51:46 +0000
3278+++ test/gtest/unity/api/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini.in 2013-12-03 14:09:20 +0000
3279@@ -1,2 +1,3 @@
3280 [Zmq]
3281 EndpointDir.Public = /tmp
3282+EndpointDir.Private = /tmp
3283
3284=== modified file 'test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/CMakeLists.txt'
3285--- test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/CMakeLists.txt 2013-11-19 02:51:46 +0000
3286+++ test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/CMakeLists.txt 2013-12-03 14:09:20 +0000
3287@@ -1,4 +1,3 @@
3288-configure_file(Factory.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Factory.ini)
3289 configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini)
3290 configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini)
3291 configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini)
3292
3293=== removed file 'test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Factory.ini.in'
3294--- test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Factory.ini.in 2013-09-23 06:13:06 +0000
3295+++ test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Factory.ini.in 1970-01-01 00:00:00 +0000
3296@@ -1,3 +0,0 @@
3297-[MiddlewareFactory]
3298-Zmq.Configfile = Zmq.ini
3299-REST.Configfile = REST.ini
3300
3301=== modified file 'test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp'
3302--- test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp 2013-11-21 21:46:36 +0000
3303+++ test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp 2013-12-03 14:09:20 +0000
3304@@ -20,6 +20,8 @@
3305
3306 #include <scopes/internal/RegistryConfig.h>
3307 #include <scopes/internal/RuntimeImpl.h>
3308+#include <scopes/internal/ScopeMetadataImpl.h>
3309+#include <scopes/internal/ScopeImpl.h>
3310 #include <scopes/internal/UniqueID.h>
3311 #include <internal/zmq_middleware/capnproto/Message.capnp.h>
3312 #include <scopes/ScopeExceptions.h>
3313@@ -37,33 +39,48 @@
3314 using namespace unity::api::scopes::internal;
3315 using namespace unity::api::scopes::internal::zmq_middleware;
3316
3317-TEST(RegistryI, find)
3318-{
3319-try
3320-{
3321- RuntimeImpl::UPtr runtime = RuntimeImpl::create(
3322- "Registry", TEST_BUILD_ROOT "/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Runtime.ini");
3323-
3324- string identity = runtime->registry_identity();
3325- RegistryConfig c(identity, runtime->registry_configfile());
3326- string mw_kind = c.mw_kind();
3327- string mw_endpoint = c.endpoint();
3328- string mw_configfile = c.mw_configfile();
3329-
3330- MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile);
3331- RegistryObject::SPtr ro(make_shared<RegistryObject>());
3332- auto registry = middleware->add_registry_object(identity, ro);
3333- auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1");
3334- EXPECT_TRUE(ro->add("scope1", proxy));
3335-
3336- auto r = runtime->registry();
3337- auto scope = r->find("scope1");
3338- EXPECT_TRUE(scope.get());
3339-}
3340-catch(unity::Exception const& e)
3341-{
3342- cout << e.to_string() << endl;
3343-}
3344+ScopeMetadata make_meta(const string& name, MWScopeProxy const& proxy, MiddlewareBase::SPtr const& mw)
3345+{
3346+ unique_ptr<ScopeMetadataImpl> mi(new ScopeMetadataImpl(mw.get()));
3347+ mi->set_scope_name(name);
3348+ mi->set_art("art " + name);
3349+ mi->set_display_name("display name " + name);
3350+ mi->set_description("description " + name);
3351+ mi->set_search_hint("search hint " + name);
3352+ mi->set_hot_key("hot key " + name);
3353+ ScopeProxy p = ScopeImpl::create(proxy, mw->runtime());
3354+ mi->set_proxy(p);
3355+ return ScopeMetadataImpl::create(move(mi));
3356+}
3357+
3358+TEST(RegistryI, get_metadata)
3359+{
3360+ try
3361+ {
3362+ RuntimeImpl::UPtr runtime = RuntimeImpl::create(
3363+ "Registry", TEST_BUILD_ROOT "/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Runtime.ini");
3364+
3365+ string identity = runtime->registry_identity();
3366+ RegistryConfig c(identity, runtime->registry_configfile());
3367+ string mw_kind = c.mw_kind();
3368+ string mw_endpoint = c.endpoint();
3369+ string mw_configfile = c.mw_configfile();
3370+
3371+ MiddlewareBase::SPtr middleware = runtime->factory()->create(identity, mw_kind, mw_configfile);
3372+ RegistryObject::SPtr ro(make_shared<RegistryObject>());
3373+ auto registry = middleware->add_registry_object(identity, ro);
3374+ auto p = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1");
3375+ EXPECT_TRUE(ro->add("scope1", move(make_meta("scope1", p, middleware))));
3376+
3377+ auto r = runtime->registry();
3378+ auto scope = r->get_metadata("scope1");
3379+ EXPECT_EQ("scope1", scope.scope_name());
3380+ }
3381+ catch (unity::Exception const& e)
3382+ {
3383+ cerr << e.to_string() << endl;
3384+ FAIL();
3385+ }
3386 }
3387
3388 TEST(RegistryI, list)
3389@@ -86,7 +103,7 @@
3390 EXPECT_TRUE(scopes.empty());
3391
3392 auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1");
3393- EXPECT_TRUE(ro->add("scope1", proxy));
3394+ EXPECT_TRUE(ro->add("scope1", move(make_meta("scope1", proxy, middleware))));
3395 scopes = r->list();
3396 EXPECT_EQ(1, scopes.size());
3397 EXPECT_NE(scopes.end(), scopes.find("scope1"));
3398@@ -96,14 +113,14 @@
3399 EXPECT_EQ(0, scopes.size());
3400
3401 set<string> ids;
3402- for (int i = 0; i < 1000; ++i)
3403+ for (int i = 0; i < 10; ++i)
3404 {
3405 string long_id = "0000000000000000000000000000000000000000000000" + to_string(i);
3406- EXPECT_TRUE(ro->add(long_id, proxy));
3407+ EXPECT_TRUE(ro->add(long_id, move(make_meta(long_id, proxy, middleware))));
3408 ids.insert(long_id);
3409 }
3410 scopes = r->list();
3411- EXPECT_EQ(1000, scopes.size());
3412+ EXPECT_EQ(10, scopes.size());
3413 for (auto& id : ids)
3414 {
3415 auto it = scopes.find(id);
3416@@ -132,11 +149,11 @@
3417 EXPECT_TRUE(scopes.empty());
3418
3419 auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1");
3420- EXPECT_TRUE(ro->add("scope1", proxy));
3421+ EXPECT_TRUE(ro->add("scope1", move(make_meta("scope1", proxy, middleware))));
3422 scopes = r->list();
3423 EXPECT_EQ(1, scopes.size());
3424 EXPECT_NE(scopes.end(), scopes.find("scope1"));
3425- EXPECT_FALSE(ro->add("scope1", proxy));
3426+ EXPECT_FALSE(ro->add("scope1", move(make_meta("scope1", proxy, middleware))));
3427
3428 EXPECT_TRUE(ro->remove("scope1"));
3429 scopes = r->list();
3430@@ -144,14 +161,14 @@
3431 EXPECT_FALSE(ro->remove("scope1"));
3432
3433 set<string> ids;
3434- for (int i = 0; i < 1000; ++i)
3435+ for (int i = 0; i < 10; ++i)
3436 {
3437 string long_id = "0000000000000000000000000000000000000000000000" + to_string(i);
3438- ro->add(long_id, proxy);
3439+ ro->add(long_id, move(make_meta(long_id, proxy, middleware)));
3440 ids.insert(long_id);
3441 }
3442 scopes = r->list();
3443- EXPECT_EQ(1000, scopes.size());
3444+ EXPECT_EQ(10, scopes.size());
3445 for (auto& id : ids)
3446 {
3447 auto it = scopes.find(id);
3448@@ -175,24 +192,24 @@
3449 RegistryObject::SPtr ro(make_shared<RegistryObject>());
3450 auto registry = middleware->add_registry_object(identity, ro);
3451 auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1");
3452- ro->add("scope1", proxy);
3453+ ro->add("scope1", move(make_meta("scope1", proxy, middleware)));
3454
3455 auto r = runtime->registry();
3456
3457 try
3458 {
3459- r->find("fred");
3460+ r->get_metadata("fred");
3461 FAIL();
3462 }
3463 catch (NotFoundException const& e)
3464 {
3465- EXPECT_EQ("unity::api::scopes::NotFoundException: Registry::find(): no such scope (name = fred)",
3466+ EXPECT_EQ("unity::api::scopes::NotFoundException: Registry::get_metadata(): no such scope (name = fred)",
3467 e.to_string());
3468 }
3469
3470 try
3471 {
3472- r->find("");
3473+ r->get_metadata("");
3474 FAIL();
3475 }
3476 catch (MiddlewareException const& e)
3477@@ -205,7 +222,7 @@
3478 try
3479 {
3480 auto proxy = middleware->create_scope_proxy("scope1", "ipc:///tmp/scope1");
3481- ro->add("", proxy);
3482+ ro->add("", move(make_meta("blah", proxy, middleware)));
3483 FAIL();
3484 }
3485 catch (InvalidArgumentException const& e)
3486
3487=== modified file 'test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Zmq.ini.in'
3488--- test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Zmq.ini.in 2013-11-19 21:12:39 +0000
3489+++ test/gtest/unity/api/scopes/internal/zmq_middleware/RegistryI/Zmq.ini.in 2013-12-03 14:09:20 +0000
3490@@ -1,2 +1,3 @@
3491 [Zmq]
3492 EndpointDir.Public = /tmp
3493+EndpointDir.Private = /tmp
3494
3495=== modified file 'test/gtest/unity/api/scopes/internal/zmq_middleware/ServantBase/Zmq.ini.in'
3496--- test/gtest/unity/api/scopes/internal/zmq_middleware/ServantBase/Zmq.ini.in 2013-11-19 21:12:39 +0000
3497+++ test/gtest/unity/api/scopes/internal/zmq_middleware/ServantBase/Zmq.ini.in 2013-12-03 14:09:20 +0000
3498@@ -1,2 +1,3 @@
3499 [Zmq]
3500 EndpointDir.Public = /tmp
3501+EndpointDir.Private = /tmp
3502
3503=== modified file 'test/gtest/unity/api/scopes/internal/zmq_middleware/ZmqMiddleware/Zmq.ini.in'
3504--- test/gtest/unity/api/scopes/internal/zmq_middleware/ZmqMiddleware/Zmq.ini.in 2013-11-19 21:12:39 +0000
3505+++ test/gtest/unity/api/scopes/internal/zmq_middleware/ZmqMiddleware/Zmq.ini.in 2013-12-03 14:09:20 +0000
3506@@ -1,2 +1,3 @@
3507 [Zmq]
3508 EndpointDir.Public = /tmp
3509+EndpointDir.Private = /tmp
3510
3511=== modified file 'test/gtest/unity/api/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp'
3512--- test/gtest/unity/api/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp 2013-11-21 21:46:36 +0000
3513+++ test/gtest/unity/api/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp 2013-12-03 14:09:20 +0000
3514@@ -21,6 +21,7 @@
3515 #include <gtest/gtest.h>
3516 #include <scope-api-testconfig.h>
3517
3518+using namespace std;
3519 using namespace unity::api::scopes::internal;
3520 using namespace unity::api::scopes::internal::zmq_middleware;
3521

Subscribers

People subscribed via source and target branches

to all changes: