diff options
-rw-r--r-- | common/clientapi.h | 59 | ||||
-rw-r--r-- | common/domain/applicationdomaintype.h | 7 | ||||
-rw-r--r-- | common/facadeinterface.h | 25 | ||||
-rw-r--r-- | examples/client/main.cpp | 2 | ||||
-rw-r--r-- | tests/clientapitest.cpp | 5 | ||||
-rw-r--r-- | tests/dummyresourcebenchmark.cpp | 4 | ||||
-rw-r--r-- | tests/dummyresourcetest.cpp | 32 |
7 files changed, 82 insertions, 52 deletions
diff --git a/common/clientapi.h b/common/clientapi.h index e467b8f..6237cfb 100644 --- a/common/clientapi.h +++ b/common/clientapi.h | |||
@@ -134,20 +134,25 @@ public: | |||
134 | // { | 134 | // { |
135 | 135 | ||
136 | // } | 136 | // } |
137 | template <class DomainType> | ||
138 | static std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resourceInstanceIdentifier) | ||
139 | { | ||
140 | if (auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceInstanceIdentifier), resourceInstanceIdentifier)) { | ||
141 | return facade; | ||
142 | } | ||
143 | return std::make_shared<NullFacade<DomainType> >(); | ||
144 | } | ||
137 | 145 | ||
138 | /** | 146 | /** |
139 | * Create a new entity. | 147 | * Create a new entity. |
140 | */ | 148 | */ |
141 | template <class DomainType> | 149 | template <class DomainType> |
142 | static KAsync::Job<void> create(const DomainType &domainObject, const QByteArray &resourceIdentifier) { | 150 | static KAsync::Job<void> create(const DomainType &domainObject) { |
143 | //Potentially move to separate thread as well | 151 | //Potentially move to separate thread as well |
144 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceIdentifier), resourceIdentifier); | 152 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); |
145 | if (facade) { | 153 | return facade->create(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { |
146 | return facade->create(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { | 154 | Warning() << "Failed to create"; |
147 | Warning() << "Failed to create"; | 155 | }); |
148 | }); | ||
149 | } | ||
150 | return KAsync::error<void>(-1, "Failed to create a facade"); | ||
151 | } | 156 | } |
152 | 157 | ||
153 | /** | 158 | /** |
@@ -156,30 +161,24 @@ public: | |||
156 | * This includes moving etc. since these are also simple settings on a property. | 161 | * This includes moving etc. since these are also simple settings on a property. |
157 | */ | 162 | */ |
158 | template <class DomainType> | 163 | template <class DomainType> |
159 | static KAsync::Job<void> modify(const DomainType &domainObject, const QByteArray &resourceIdentifier) { | 164 | static KAsync::Job<void> modify(const DomainType &domainObject) { |
160 | //Potentially move to separate thread as well | 165 | //Potentially move to separate thread as well |
161 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceIdentifier), resourceIdentifier); | 166 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); |
162 | if (facade) { | 167 | return facade->modify(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { |
163 | return facade->modify(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { | 168 | Warning() << "Failed to modify"; |
164 | Warning() << "Failed to modify"; | 169 | }); |
165 | }); | ||
166 | } | ||
167 | return KAsync::error<void>(-1, "Failed to create a facade"); | ||
168 | } | 170 | } |
169 | 171 | ||
170 | /** | 172 | /** |
171 | * Remove an entity. | 173 | * Remove an entity. |
172 | */ | 174 | */ |
173 | template <class DomainType> | 175 | template <class DomainType> |
174 | static KAsync::Job<void> remove(const DomainType &domainObject, const QByteArray &resourceIdentifier) { | 176 | static KAsync::Job<void> remove(const DomainType &domainObject) { |
175 | //Potentially move to separate thread as well | 177 | //Potentially move to separate thread as well |
176 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceIdentifier), resourceIdentifier); | 178 | auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier()); |
177 | if (facade) { | 179 | return facade->remove(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { |
178 | return facade->remove(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) { | 180 | Warning() << "Failed to remove"; |
179 | Warning() << "Failed to remove"; | 181 | }); |
180 | }); | ||
181 | } | ||
182 | return KAsync::error<void>(-1, "Failed to create a facade"); | ||
183 | } | 182 | } |
184 | 183 | ||
185 | static void shutdown(const QByteArray &resourceIdentifier); | 184 | static void shutdown(const QByteArray &resourceIdentifier); |
@@ -213,20 +212,20 @@ public: | |||
213 | return ApplicationDomain::AkonadiResource::Ptr::create(); | 212 | return ApplicationDomain::AkonadiResource::Ptr::create(); |
214 | } | 213 | } |
215 | 214 | ||
216 | static void setConfiguration(const ApplicationDomain::AkonadiResource &resource, const QByteArray &resourceIdentifier) | 215 | static void setConfiguration(const ApplicationDomain::AkonadiResource &resource) |
217 | { | 216 | { |
218 | Store::modify<ApplicationDomain::AkonadiResource>(resource, resourceIdentifier); | 217 | Store::modify<ApplicationDomain::AkonadiResource>(resource); |
219 | } | 218 | } |
220 | 219 | ||
221 | static void createResource(const ApplicationDomain::AkonadiResource &resource, const QByteArray &resourceIdentifier) | 220 | static void createResource(const ApplicationDomain::AkonadiResource &resource) |
222 | { | 221 | { |
223 | Store::create<ApplicationDomain::AkonadiResource>(resource, resourceIdentifier); | 222 | Store::create<ApplicationDomain::AkonadiResource>(resource); |
224 | } | 223 | } |
225 | 224 | ||
226 | static void removeResource(const QByteArray &resourceIdentifier) | 225 | static void removeResource(const QByteArray &resourceIdentifier) |
227 | { | 226 | { |
228 | ApplicationDomain::AkonadiResource resource; | 227 | ApplicationDomain::AkonadiResource resource(resourceIdentifier); |
229 | Store::remove<ApplicationDomain::AkonadiResource>(resource, resourceIdentifier); | 228 | Store::remove<ApplicationDomain::AkonadiResource>(resource); |
230 | } | 229 | } |
231 | }; | 230 | }; |
232 | 231 | ||
diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h index 3cc34ec..bd7ff65 100644 --- a/common/domain/applicationdomaintype.h +++ b/common/domain/applicationdomaintype.h | |||
@@ -45,6 +45,13 @@ public: | |||
45 | 45 | ||
46 | } | 46 | } |
47 | 47 | ||
48 | ApplicationDomainType(const QByteArray &resourceInstanceIdentifier) | ||
49 | :mAdaptor(new MemoryBufferAdaptor()), | ||
50 | mResourceInstanceIdentifier(resourceInstanceIdentifier) | ||
51 | { | ||
52 | |||
53 | } | ||
54 | |||
48 | ApplicationDomainType(const QByteArray &resourceInstanceIdentifier, const QByteArray &identifier, qint64 revision, const QSharedPointer<BufferAdaptor> &adaptor) | 55 | ApplicationDomainType(const QByteArray &resourceInstanceIdentifier, const QByteArray &identifier, qint64 revision, const QSharedPointer<BufferAdaptor> &adaptor) |
49 | : mAdaptor(adaptor), | 56 | : mAdaptor(adaptor), |
50 | mResourceInstanceIdentifier(resourceInstanceIdentifier), | 57 | mResourceInstanceIdentifier(resourceInstanceIdentifier), |
diff --git a/common/facadeinterface.h b/common/facadeinterface.h index ac60ae4..cd43fa1 100644 --- a/common/facadeinterface.h +++ b/common/facadeinterface.h | |||
@@ -48,4 +48,29 @@ public: | |||
48 | virtual KAsync::Job<void> load(const Query &query, const QSharedPointer<Akonadi2::ResultProvider<typename DomainType::Ptr> > &resultProvider) = 0; | 48 | virtual KAsync::Job<void> load(const Query &query, const QSharedPointer<Akonadi2::ResultProvider<typename DomainType::Ptr> > &resultProvider) = 0; |
49 | }; | 49 | }; |
50 | 50 | ||
51 | template<class DomainType> | ||
52 | class NullFacade : public StoreFacade<DomainType> { | ||
53 | public: | ||
54 | virtual ~NullFacade(){}; | ||
55 | KAsync::Job<void> create(const DomainType &domainObject) | ||
56 | { | ||
57 | return KAsync::error<void>(-1, "Failed to create a facade"); | ||
58 | } | ||
59 | |||
60 | KAsync::Job<void> modify(const DomainType &domainObject) | ||
61 | { | ||
62 | return KAsync::error<void>(-1, "Failed to create a facade"); | ||
63 | } | ||
64 | |||
65 | KAsync::Job<void> remove(const DomainType &domainObject) | ||
66 | { | ||
67 | return KAsync::error<void>(-1, "Failed to create a facade"); | ||
68 | } | ||
69 | |||
70 | KAsync::Job<void> load(const Query &query, const QSharedPointer<Akonadi2::ResultProvider<typename DomainType::Ptr> > &resultProvider) | ||
71 | { | ||
72 | return KAsync::error<void>(-1, "Failed to create a facade"); | ||
73 | } | ||
74 | }; | ||
75 | |||
51 | } | 76 | } |
diff --git a/examples/client/main.cpp b/examples/client/main.cpp index 269f1aa..6bbec97 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp | |||
@@ -66,7 +66,7 @@ public: | |||
66 | QObject::connect(removeButton, &QPushButton::pressed, [listView]() { | 66 | QObject::connect(removeButton, &QPushButton::pressed, [listView]() { |
67 | for (auto index :listView->selectionModel()->selectedIndexes()) { | 67 | for (auto index :listView->selectionModel()->selectedIndexes()) { |
68 | auto object = index.data(DomainObjectRole).value<typename T::Ptr>(); | 68 | auto object = index.data(DomainObjectRole).value<typename T::Ptr>(); |
69 | Akonadi2::Store::remove(*object, "org.kde.dummy.instance1").exec(); | 69 | Akonadi2::Store::remove(*object).exec(); |
70 | } | 70 | } |
71 | }); | 71 | }); |
72 | 72 | ||
diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp index 03cc732..8779716 100644 --- a/tests/clientapitest.cpp +++ b/tests/clientapitest.cpp | |||
@@ -95,8 +95,7 @@ private Q_SLOTS: | |||
95 | res.setProperty("identifier", "dummyresource.identifier1"); | 95 | res.setProperty("identifier", "dummyresource.identifier1"); |
96 | res.setProperty("type", "dummyresource"); | 96 | res.setProperty("type", "dummyresource"); |
97 | 97 | ||
98 | Akonadi2::Store::create(res, "resourceconfig").exec().waitForFinished(); | 98 | Akonadi2::Store::create(res).exec().waitForFinished(); |
99 | |||
100 | { | 99 | { |
101 | Akonadi2::Query query; | 100 | Akonadi2::Query query; |
102 | query.resources << "resourceconfig"; | 101 | query.resources << "resourceconfig"; |
@@ -106,7 +105,7 @@ private Q_SLOTS: | |||
106 | QCOMPARE(result.size(), 1); | 105 | QCOMPARE(result.size(), 1); |
107 | } | 106 | } |
108 | 107 | ||
109 | Akonadi2::Store::remove(res, "resourceconfig").exec().waitForFinished(); | 108 | Akonadi2::Store::remove(res).exec().waitForFinished(); |
110 | { | 109 | { |
111 | Akonadi2::Query query; | 110 | Akonadi2::Query query; |
112 | query.resources << "resourceconfig"; | 111 | query.resources << "resourceconfig"; |
diff --git a/tests/dummyresourcebenchmark.cpp b/tests/dummyresourcebenchmark.cpp index c020c6b..370acd2 100644 --- a/tests/dummyresourcebenchmark.cpp +++ b/tests/dummyresourcebenchmark.cpp | |||
@@ -72,11 +72,11 @@ private Q_SLOTS: | |||
72 | int num = 100; | 72 | int num = 100; |
73 | QList<KAsync::Future<void> > waitCondition; | 73 | QList<KAsync::Future<void> > waitCondition; |
74 | for (int i = 0; i < num; i++) { | 74 | for (int i = 0; i < num; i++) { |
75 | Akonadi2::ApplicationDomain::Event event; | 75 | Akonadi2::ApplicationDomain::Event event("org.kde.dummy.instance1"); |
76 | event.setProperty("uid", "testuid"); | 76 | event.setProperty("uid", "testuid"); |
77 | QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); | 77 | QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); |
78 | event.setProperty("summary", "summaryValue"); | 78 | event.setProperty("summary", "summaryValue"); |
79 | waitCondition << Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event, "org.kde.dummy.instance1").exec(); | 79 | waitCondition << Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event).exec(); |
80 | } | 80 | } |
81 | waitForCompletion(waitCondition).exec().waitForFinished(); | 81 | waitForCompletion(waitCondition).exec().waitForFinished(); |
82 | auto appendTime = time.elapsed(); | 82 | auto appendTime = time.elapsed(); |
diff --git a/tests/dummyresourcetest.cpp b/tests/dummyresourcetest.cpp index 9d7d092..48bb7b0 100644 --- a/tests/dummyresourcetest.cpp +++ b/tests/dummyresourcetest.cpp | |||
@@ -48,11 +48,11 @@ private Q_SLOTS: | |||
48 | 48 | ||
49 | void testWriteToFacadeAndQueryByUid() | 49 | void testWriteToFacadeAndQueryByUid() |
50 | { | 50 | { |
51 | Akonadi2::ApplicationDomain::Event event; | 51 | Akonadi2::ApplicationDomain::Event event("org.kde.dummy.instance1"); |
52 | event.setProperty("uid", "testuid"); | 52 | event.setProperty("uid", "testuid"); |
53 | QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); | 53 | QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); |
54 | event.setProperty("summary", "summaryValue"); | 54 | event.setProperty("summary", "summaryValue"); |
55 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event, "org.kde.dummy.instance1").exec().waitForFinished(); | 55 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event).exec().waitForFinished(); |
56 | 56 | ||
57 | Akonadi2::Query query; | 57 | Akonadi2::Query query; |
58 | query.resources << "org.kde.dummy.instance1"; | 58 | query.resources << "org.kde.dummy.instance1"; |
@@ -69,14 +69,14 @@ private Q_SLOTS: | |||
69 | 69 | ||
70 | void testWriteToFacadeAndQueryByUid2() | 70 | void testWriteToFacadeAndQueryByUid2() |
71 | { | 71 | { |
72 | Akonadi2::ApplicationDomain::Event event; | 72 | Akonadi2::ApplicationDomain::Event event("org.kde.dummy.instance1"); |
73 | event.setProperty("summary", "summaryValue"); | 73 | event.setProperty("summary", "summaryValue"); |
74 | 74 | ||
75 | event.setProperty("uid", "testuid"); | 75 | event.setProperty("uid", "testuid"); |
76 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event, "org.kde.dummy.instance1").exec().waitForFinished(); | 76 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event).exec().waitForFinished(); |
77 | 77 | ||
78 | event.setProperty("uid", "testuid2"); | 78 | event.setProperty("uid", "testuid2"); |
79 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event, "org.kde.dummy.instance1").exec().waitForFinished(); | 79 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event).exec().waitForFinished(); |
80 | 80 | ||
81 | Akonadi2::Query query; | 81 | Akonadi2::Query query; |
82 | query.resources << "org.kde.dummy.instance1"; | 82 | query.resources << "org.kde.dummy.instance1"; |
@@ -94,15 +94,15 @@ private Q_SLOTS: | |||
94 | 94 | ||
95 | void testWriteToFacadeAndQueryBySummary() | 95 | void testWriteToFacadeAndQueryBySummary() |
96 | { | 96 | { |
97 | Akonadi2::ApplicationDomain::Event event; | 97 | Akonadi2::ApplicationDomain::Event event("org.kde.dummy.instance1"); |
98 | 98 | ||
99 | event.setProperty("uid", "testuid"); | 99 | event.setProperty("uid", "testuid"); |
100 | event.setProperty("summary", "summaryValue1"); | 100 | event.setProperty("summary", "summaryValue1"); |
101 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event, "org.kde.dummy.instance1").exec().waitForFinished(); | 101 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event).exec().waitForFinished(); |
102 | 102 | ||
103 | event.setProperty("uid", "testuid2"); | 103 | event.setProperty("uid", "testuid2"); |
104 | event.setProperty("summary", "summaryValue2"); | 104 | event.setProperty("summary", "summaryValue2"); |
105 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event, "org.kde.dummy.instance1").exec().waitForFinished(); | 105 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event).exec().waitForFinished(); |
106 | 106 | ||
107 | Akonadi2::Query query; | 107 | Akonadi2::Query query; |
108 | query.resources << "org.kde.dummy.instance1"; | 108 | query.resources << "org.kde.dummy.instance1"; |
@@ -165,11 +165,11 @@ private Q_SLOTS: | |||
165 | 165 | ||
166 | void testWriteModifyDelete() | 166 | void testWriteModifyDelete() |
167 | { | 167 | { |
168 | Akonadi2::ApplicationDomain::Event event; | 168 | Akonadi2::ApplicationDomain::Event event("org.kde.dummy.instance1"); |
169 | event.setProperty("uid", "testuid"); | 169 | event.setProperty("uid", "testuid"); |
170 | QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); | 170 | QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); |
171 | event.setProperty("summary", "summaryValue"); | 171 | event.setProperty("summary", "summaryValue"); |
172 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event, "org.kde.dummy.instance1").exec().waitForFinished(); | 172 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event).exec().waitForFinished(); |
173 | 173 | ||
174 | Akonadi2::Query query; | 174 | Akonadi2::Query query; |
175 | query.resources << "org.kde.dummy.instance1"; | 175 | query.resources << "org.kde.dummy.instance1"; |
@@ -191,7 +191,7 @@ private Q_SLOTS: | |||
191 | 191 | ||
192 | event2.setProperty("uid", "testuid"); | 192 | event2.setProperty("uid", "testuid"); |
193 | event2.setProperty("summary", "summaryValue2"); | 193 | event2.setProperty("summary", "summaryValue2"); |
194 | Akonadi2::Store::modify<Akonadi2::ApplicationDomain::Event>(event2, "org.kde.dummy.instance1").exec().waitForFinished(); | 194 | Akonadi2::Store::modify<Akonadi2::ApplicationDomain::Event>(event2).exec().waitForFinished(); |
195 | 195 | ||
196 | //Test modify | 196 | //Test modify |
197 | { | 197 | { |
@@ -203,7 +203,7 @@ private Q_SLOTS: | |||
203 | QCOMPARE(value->getProperty("summary").toByteArray(), QByteArray("summaryValue2")); | 203 | QCOMPARE(value->getProperty("summary").toByteArray(), QByteArray("summaryValue2")); |
204 | } | 204 | } |
205 | 205 | ||
206 | Akonadi2::Store::remove<Akonadi2::ApplicationDomain::Event>(event2, "org.kde.dummy.instance1").exec().waitForFinished(); | 206 | Akonadi2::Store::remove<Akonadi2::ApplicationDomain::Event>(event2).exec().waitForFinished(); |
207 | 207 | ||
208 | //Test remove | 208 | //Test remove |
209 | { | 209 | { |
@@ -227,11 +227,11 @@ private Q_SLOTS: | |||
227 | async::SyncListResult<Akonadi2::ApplicationDomain::Event::Ptr> result(Akonadi2::Store::load<Akonadi2::ApplicationDomain::Event>(query)); | 227 | async::SyncListResult<Akonadi2::ApplicationDomain::Event::Ptr> result(Akonadi2::Store::load<Akonadi2::ApplicationDomain::Event>(query)); |
228 | result.exec(); | 228 | result.exec(); |
229 | 229 | ||
230 | Akonadi2::ApplicationDomain::Event event; | 230 | Akonadi2::ApplicationDomain::Event event("org.kde.dummy.instance1"); |
231 | event.setProperty("uid", "testuid"); | 231 | event.setProperty("uid", "testuid"); |
232 | QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); | 232 | QCOMPARE(event.getProperty("uid").toByteArray(), QByteArray("testuid")); |
233 | event.setProperty("summary", "summaryValue"); | 233 | event.setProperty("summary", "summaryValue"); |
234 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event, "org.kde.dummy.instance1").exec().waitForFinished(); | 234 | Akonadi2::Store::create<Akonadi2::ApplicationDomain::Event>(event).exec().waitForFinished(); |
235 | 235 | ||
236 | //Test create | 236 | //Test create |
237 | Akonadi2::ApplicationDomain::Event event2; | 237 | Akonadi2::ApplicationDomain::Event event2; |
@@ -245,7 +245,7 @@ private Q_SLOTS: | |||
245 | 245 | ||
246 | event2.setProperty("uid", "testuid"); | 246 | event2.setProperty("uid", "testuid"); |
247 | event2.setProperty("summary", "summaryValue2"); | 247 | event2.setProperty("summary", "summaryValue2"); |
248 | Akonadi2::Store::modify<Akonadi2::ApplicationDomain::Event>(event2, "org.kde.dummy.instance1").exec().waitForFinished(); | 248 | Akonadi2::Store::modify<Akonadi2::ApplicationDomain::Event>(event2).exec().waitForFinished(); |
249 | 249 | ||
250 | //Test modify | 250 | //Test modify |
251 | { | 251 | { |
@@ -255,7 +255,7 @@ private Q_SLOTS: | |||
255 | QCOMPARE(value->getProperty("summary").toByteArray(), QByteArray("summaryValue2")); | 255 | QCOMPARE(value->getProperty("summary").toByteArray(), QByteArray("summaryValue2")); |
256 | } | 256 | } |
257 | 257 | ||
258 | Akonadi2::Store::remove<Akonadi2::ApplicationDomain::Event>(event2, "org.kde.dummy.instance1").exec().waitForFinished(); | 258 | Akonadi2::Store::remove<Akonadi2::ApplicationDomain::Event>(event2).exec().waitForFinished(); |
259 | 259 | ||
260 | //Test remove | 260 | //Test remove |
261 | { | 261 | { |