Ilwis-Objects  1.0
GIS and Remote Sensing framework for data access and processing
 All Classes Functions Enumerations Pages
ilwisdata.h
1 #ifndef ILWISDATA_H
2 #define ILWISDATA_H
3 
4 #include <QUrl>
5 #include <QStringList>
6 #include <typeinfo>
7 #include <mutex>
8 //#include "ilwis.h"
9 #include "errorobject.h"
10 #include "prepareoptions.h"
11 #include "ilwisobject.h"
12 #include "resource.h"
13 #include "mastercatalog.h"
14 
15 
16 namespace Ilwis {
17 typedef std::shared_ptr<IlwisObject> ESPIlwisObject;
18 
29 template<class T> class IlwisData {
30 public:
31  template<class C> friend class IlwisData;
32 
33  IlwisData() {}
34  IlwisData(const QString& name, IlwisTypes tp=itANY, const PrepareOptions& options=PrepareOptions()){
35  prepare(name, tp, options);
36  }
37  IlwisData(const Resource& resource1,const PrepareOptions& options=PrepareOptions()){
38  prepare(resource1, options);
39  }
40 
41 
42  IlwisData(T *data) {
43  set(data);
44  }
45 
46  IlwisData(const ESPIlwisObject& impl) {
47  _implementation = impl;
48  }
49 
50  template<typename K> IlwisData(const IlwisData<K>& obj) {
51  _implementation = std::dynamic_pointer_cast<T>(obj._implementation);
52  }
53 
54  IlwisData(const IlwisData& obj) {
55  _implementation = obj._implementation;
56  }
57 
58 
59 
60  ~IlwisData() {
61  if (_implementation.get()!= 0 ) // there is always one extra reference in the registerd objects, so 2 means last object will disappear
62  if ( _implementation.use_count() == 2)
63  mastercatalog()->unregister(_implementation.get()->id());
64  }
65 
66  void set(T *data) {
67  removeCurrent();
68  if ( data != nullptr) {
69  if (!mastercatalog()->isRegistered(data->id())) {
70  _implementation.reset(data);
71  mastercatalog()->registerObject(_implementation);
72  }
73  else {
74  _implementation = mastercatalog()->get(data->id());
75  }
76  }else {
77  _implementation.reset();
78  }
79  }
80 
81  template<typename K> IlwisData<T>& assign(const IlwisData<K>& obj) {
82  if ( _implementation && obj->ilwisType() == _implementation->ilwisType())
83  set(static_cast<T *>(obj._implementation.get())) ;
84  else
85  set(dynamic_cast<T *>(obj._implementation.get())) ;
86  return *this;
87  }
88 
89  template<typename K> IlwisData<T>& operator=(const IlwisData<K>& obj) {
90  return assign(obj);
91  }
92 
93  IlwisData& operator=(const IlwisData& obj) {
94  return assign(obj);
95  }
96 
97  T *operator->() {
98  T* p = static_cast<T *>(_implementation.get());
99  if (!p)
100  throw ErrorObject(TR("Using unitialized object"));
101  return p;
102  }
103 
104  T *operator->() const{
105  T* p = static_cast<T *>(_implementation.get());
106  if (!p)
107  throw ErrorObject(TR("Using unitialized object"));
108  return p;
109  }
110 
111  T *ptr() const {
112  return operator->();
113  }
114 
125  template<class C=IlwisObject> IlwisData<C> get() const {
126  if (_implementation.get() == 0)
127  throw ErrorObject(TR("Using unitialized object"));
128  if ( hasType(_implementation->ilwisType(),itILWISOBJECT)) {
129  IlwisData<C> obj;
130  obj._implementation = std::static_pointer_cast<C>(_implementation);
131  return obj;
132  }
133  return IlwisData<C>();
134  }
140  bool prepare() {
141  removeCurrent();
142  auto type = kernel()->demangle(typeid(T).name());
143 
144  IlwisTypes tp = IlwisObject::name2Type(type);
145  Resource res;
146  res.prepare();
147  res.setIlwisType(tp);
148  tp = IlwisObject::name2ExtendedType(type);
149  if ( tp != itUNKNOWN)
150  res.setExtendedType(tp);
151  QString name = QString("%1%2").arg(ANONYMOUS_PREFIX).arg(res.id());
152  QUrl url(QString("ilwis://internalcatalog/%1").arg(name));
153  res.setName(name);
154  res.setUrl(url);
155  return prepare(res);
156 
157  }
158 
168  bool prepare(const QString& name, IlwisTypes tp=itANY,const PrepareOptions& options=PrepareOptions()){
169  if ( name.left(11) == ANONYMOUS_PREFIX) { // internal objects are not in the catalog
170  QString sid = name.mid(11);
171  bool ok;
172  quint64 id = sid.toLongLong(&ok);
173  if (ok){
174  ESPIlwisObject data = mastercatalog()->get(id);
175  if ( data.get() != 0) {
176  removeCurrent();
177  _implementation = data;
178  return true;
179  }
180 
181  }
182  return ERROR1(ERR_COULDNT_CREATE_OBJECT_FOR_1,name);
183 
184  }
185  if ( name.indexOf(NAME_ALIAS) == 0) {
186  QString sid = name.mid(SZ_NAME_ALIAS);
187  bool ok;
188  quint64 id = sid.toLongLong(&ok);
189  if (ok){
190  ESPIlwisObject data = mastercatalog()->get(id);
191  if ( data.get() != 0) {
192  removeCurrent();
193  _implementation = data;
194  return true;
195  }
196 
197  }
198  return ERROR1(ERR_COULDNT_CREATE_OBJECT_FOR_1,name);
199 
200  }
201  if ( tp == itANY) {
202  auto type = kernel()->demangle(typeid(T).name());
203  tp = IlwisObject::name2Type(type);
204  }
205  auto resource = mastercatalog()->name2Resource(name,tp );
206  if (resource.isValid()) {
207  if (!mastercatalog()->isRegistered(resource.id())) {
208  T *data = static_cast<T *>(IlwisObject::create(resource, options));
209  if ( data == 0) {
210  _implementation.reset((T*)0);
211  removeCurrent();
212  return ERROR1("Couldnt create ilwisobject %1",name);
213  }
214  bool ok = data->prepare();
215  if ( !ok){
216  delete data;
217  return false;
218  }
219 
220  data->changed(false);
221  removeCurrent();
222  _implementation = ESPIlwisObject(data);
223  mastercatalog()->registerObject(_implementation);
224  } else {
225  _implementation = mastercatalog()->get(resource.id());
226  }
227  return true;
228  } else {
229  if(tp != itUNKNOWN && prepare(Resource(name, tp)))
230  return true;
231  }
232  return ERROR1(ERR_COULDNT_CREATE_OBJECT_FOR_1,name);
233 
234  }
235 
236  bool prepare(const Resource& resource1,const PrepareOptions& options=PrepareOptions()){
237  if (resource1.isValid()) {
238  quint64 id = iUNDEF;
239  if ( mastercatalog()->usesContainers(resource1.url())) // containers dont make sense for services
240  mastercatalog()->addContainer(resource1.container());
241  id = mastercatalog()->url2id(resource1.url(), resource1.ilwisType());
242  Resource resource = mastercatalog()->id2Resource(id);
243  if (!resource.isValid())
244  resource = resource1;
245  if (!mastercatalog()->isRegistered(resource.id())) {
246  T *data = static_cast<T *>(IlwisObject::create(resource, options));
247  if ( data == 0) {
248  _implementation.reset((T*)0);
249  removeCurrent();
250  return ERROR1("Couldnt create ilwisobject %1",resource.name());
251  }
252  bool ok = data->prepare();
253  if ( !ok){
254  delete data;
255  return false;
256  }
257  data->changed(false);
258  removeCurrent();
259  _implementation = ESPIlwisObject(data);
260  mastercatalog()->registerObject(_implementation);
261  } else {
262  _implementation = mastercatalog()->get(resource.id());
263  }
264  return true;
265  } else {
266  ERROR1(ERR_COULDNT_CREATE_OBJECT_FOR_1,resource1.name());
267  }
268  return false;
269 
270  }
271 
282  bool prepare(const quint64& iid,const PrepareOptions& options=PrepareOptions()){
283  Resource resource = mastercatalog()->id2Resource(iid);
284  if (!mastercatalog()->isRegistered(iid)) {
285  T *data = static_cast<T *>(IlwisObject::create(resource, options));
286  if ( data != 0)
287  data->prepare();
288  else {
289  _implementation.reset((T*)0);
290  removeCurrent();
291  return ERROR1("Couldnt create ilwisobject %1",resource.name());
292  }
293  removeCurrent();
294  _implementation = ESPIlwisObject(data);
295  } else
296  _implementation = mastercatalog()->get(iid);
297  if ( _implementation.get() == 0) {
298  return ERROR0("Corrupted object registration");
299  }
300  mastercatalog()->registerObject(_implementation);
301  return true;
302 
303  }
304 
305 
311  bool isValid() const {
312  return _implementation.get() != 0;
313  }
314 
315 
316 private:
317  void removeCurrent() {
318  if ( _implementation && _implementation->id() != i64UNDEF) {
319  ESPIlwisObject obj= mastercatalog()->get( _implementation->id() );
320  if(obj.use_count() <= 3) { // current _impl + one in the lookup + the one just created
321  mastercatalog()->unregister(_implementation->id());
322  }
323  }
324  }
325 
326  ESPIlwisObject _implementation;
327 };
328 
329 template<class T> bool operator==(const IlwisData<T>& d1, const IlwisData<T>& d2) {
330  return d1->id() == d2->id();
331 }
332 
333 template<class T> bool operator!=(const IlwisData<T>& d1, const IlwisData<T>& d2) {
334  return d1->id() != d2->id();
335 }
336 
337 typedef Ilwis::IlwisData<Ilwis::IlwisObject> IIlwisObject;
338 
339 }
340 
341 Q_DECLARE_METATYPE(Ilwis::IIlwisObject)
342 
343 template<class C> QDataStream & operator << ( QDataStream & s, const Ilwis::IlwisData<C> & obj ){
344  if ( obj.isValid() == false)
345  return s;
346 
347  obj->store(s, obj->serializationOptions());
348 
349  return s;
350 }
351 
352 template<class C> QDataStream & operator >> ( QDataStream & s, Ilwis::IlwisData<C> & obj ){
353  if ( obj.isValid() == false)
354  obj.prepare();
355  obj->load(s);
356 
357  return s;
358 }
359 
360 
361 #endif // ILWISDATA_H
362