arcsfactory.cpp
1 /*
2  name: lib/arcsfactory.cpp
3 
4  This file is part of ARCS - Augmented Reality Component System
5  (version 2-current), written by Jean-Yves Didier
6  for IBISC Laboratory (http://www.ibisc.univ-evry.fr)
7 
8  Copyright (C) 2013 Université d'Evry-Val d'Essonne
9 
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program. If not, see <http://www.gnu.org/licenses/>.
22 
23 
24  Please send bugreports with examples or suggestions to
25  jean-yves.didier__at__ibisc.univ-evry.fr
26 */
27 
28 
29 #include <arcs/arcsfactory.h>
30 #include <arcs/arcsinternalfamily.h>
31 #include <arcs/arcsinternaltypes.h>
32 #include <arcs/arcssensorlogger.h>
33 #include <arcs/arcsgenerallogger.h>
34 #include <arcs/arcsconstantmodifier.h>
35 #include <arcs/arcsapplicationobject.h>
36 #include <QtDebug>
37 #include <QHashIterator>
38 #include <arcs/arcslog.h>
39 
40 
41 QString ARCSAbstractFamily::name() const
42 {
43  return QString("__");
44 }
45 
47 {
48  return false;
49 }
50 
51 
52 
53 ARCSFactory* ARCSFactory::instance = 0;
54 
55 ARCSFactory::ARCSFactory()
56 {
57  /* First create families */
58  nativeFamily = new ARCSNativeFamily();
59  families.insert(nativeFamily->name(), nativeFamily);
60  registerInternalFamily(new ARCSInternalFamily());
61 
62  registerInternalType(new ARCSTypeFactory_void());
63  registerInternalType(new ARCSTypeFactory_bool());
64  registerInternalType(new ARCSTypeFactory_int());
65  registerInternalType(new ARCSTypeFactory_short());
66  registerInternalType(new ARCSTypeFactory_long());
67  registerInternalType(new ARCSTypeFactory_QString());
68  registerInternalType(new ARCSTypeFactory_float());
69  registerInternalType(new ARCSTypeFactory_double());
70  registerInternalType(new ARCSTypeFactory_ARCSConstant());
71  qRegisterMetaType<ARCSConstant>("ARCSConstant");
72  registerInternalType(new ARCSTypeFactory_ARCSComponent());
73  qRegisterMetaType<ARCSComponent>("ARCSComponent");
74  registerInternalType(new ARCSTypeFactory_QSize());
75 
76  registerInternalType(new ARCSTypeFactory_boolArray());
77  qRegisterMetaType<boolArray>("boolArray");
78  registerInternalType(new ARCSTypeFactory_intArray());
79  qRegisterMetaType<intArray>("intArray");
80  registerInternalType(new ARCSTypeFactory_shortArray());
81  qRegisterMetaType<shortArray>("shortArray");
82  registerInternalType(new ARCSTypeFactory_longArray());
83  qRegisterMetaType<longArray>("longArray");
84  registerInternalType(new ARCSTypeFactory_floatArray());
85  qRegisterMetaType<floatArray>("floatArray");
86  registerInternalType(new ARCSTypeFactory_doubleArray());
87  qRegisterMetaType<doubleArray>("doubleArray");
88 
89  nativeFamily->addFactory("ARCSSensorLogger", new ARCSNativeComponentTemplate<ARCSSensorLogger>());
90  nativeFamily->addFactory("ARCSGeneralLogger", new ARCSNativeComponentTemplate<ARCSGeneralLogger>());
91  nativeFamily->addFactory("ARCSConstantModifier", new ARCSNativeComponentTemplate<ARCSConstantModifier>());
92  nativeFamily->addFactory("ARCSApplicationObject", new ARCSNativeComponentTemplate<ARCSApplicationObject>());
93 
94  buildComponentLists();
95 }
96 
97 ARCSFactory::~ARCSFactory()
98 {
99 
100 }
101 
102 
103 
104 
105 void ARCSFactory::registerInternalFamily(ARCSAbstractFamily* family)
106 {
107  families.insert(family->name(), family);
108 }
109 
110 
111 void ARCSFactory::registerInternalType(ARCSTypeFactory* type)
112 {
113  QVariant var = type->parseString(QString::null);
114  QString varName = var.typeName();
115  if ( !variantTypeMap.contains(varName))
116  variantTypeMap.insertMulti(varName, type->getTypeName());
117 
118  types.insert(type->getTypeName(), type);
119 }
120 
122 {
123  if (instance == 0)
124  return (instance = new ARCSFactory());
125  else
126  return instance;
127 }
128 
129 
130 void ARCSFactory::buildComponentLists()
131 {
132  QHashIterator<QString, ARCSAbstractFamily*> i(families);
133  int j;
134 
135  components.clear();
136  componentFamilyMap.clear();
137 
138  while(i.hasNext())
139  {
140  i.next();
141 
142  QStringList flist = (i.value())->factoryList();
143  for (j=0; j < flist.count() ; j++)
144  {
145  if ( components.contains(flist[j]))
146  ;//qCritical() << "[Factory] Component " << flist[j] << "already in components.";
147  else
148  components << flist[j];
149 
150  if (componentFamilyMap.contains(flist[j]))
151  ;//qCritical() << "[Factory] Component " << flist[j] << "already in componentFamilyMap.";
152  else
153  componentFamilyMap.insert(flist[j], i.value()->name());
154 
155  }
156 
157  }
158 
159 }
160 
161 
162 bool ARCSFactory::loadLibrary(QString path)
163 {
164  ARCSLibManager* lib = new ARCSLibManager(path);
165 
166  if ( ! lib->isLoaded())
167  {
168  ARCSLog::logError(ARCS_SOURCE,lib->getError());
169  delete lib;
170  return false;
171  }
172 
173  if ( libraries.contains(path) )
174  {
175  ARCSLog::logWarning(ARCS_SOURCE,"library "+ path+ " already loaded.");
176  delete lib;
177  return true;
178  }
179 
180  ARCSComponentMap acm = lib->getComponentMap();
181  ARCSFamilyMap afm = lib->getFamilyMap();
182  ARCSTypeMap atm = lib->getTypeMap();
183 
184  // parcourir la liste des composants : maj de native
185  QHashIterator<QString, ARCSNativeComponent*> i(acm);
186 
187  while(i.hasNext())
188  {
189  i.next();
190  QString namespaced = path + ":" + i.key();
191 
192  nativeFamily->addFactory(namespaced, i.value());
193  nativeFamily->addFactory(i.key(),i.value());
194 
195  if ( nativeComponentLibraryMap.contains(namespaced) )
196  qCritical() << "[Factory] Native component" << namespaced << "already found !";
197  else
198  nativeComponentLibraryMap.insert(namespaced, path);
199  if ( nativeComponentLibraryMap.contains(i.key()) )
200  qCritical() << "[Factory] Native component" << i.key() << "already found !";
201  else
202  nativeComponentLibraryMap.insert(i.key(), path);
203  }
204 
205 
206  // parcours des familles
207  QHashIterator<QString, ARCSAbstractFamily*> j(afm);
208 
209  while(j.hasNext())
210  {
211  j.next();
212  QString namespaced = path + ":" + j.key();
213 
214 
215  if (families.contains(namespaced))
216  qCritical() << "[Factory] Component family" << namespaced << "already added !";
217  else
218  families.insert(namespaced, j.value());
219 
220  if (families.contains(j.key()))
221  qCritical() << "[Factory] Component family" << j.key() << "already added !";
222  else
223  families.insert(j.key(), j.value());
224 
225  if (familyLibraryMap.contains(namespaced))
226  qCritical() << "[Factory] Component family" << namespaced << "already found !" ;
227  else
228  familyLibraryMap.insert(namespaced, path);
229 
230  if (familyLibraryMap.contains(j.key()))
231  qCritical() << "[Factory] Component family" << j.key() << "already found !" ;
232  else
233  familyLibraryMap.insert(j.key(), path);
234  }
235 
236 
237  // parcours des types
238  QHashIterator<QString, ARCSTypeFactory*> k(atm);
239  while(k.hasNext())
240  {
241  k.next();
242  QString namespaced = path + ":" + k.key();
243 
244  if (typeLibraryMap.contains(namespaced))
245  qCritical() << "[Factory] Type factory" << namespaced << "already found !";
246  else
247  typeLibraryMap.insert(namespaced, path);
248 
249  if (typeLibraryMap.contains(k.key()))
250  qCritical() << "[Factory] Type factory" << k.key() << "already found !" ;
251  else
252  typeLibraryMap.insert(k.key(), path);
253 
254  if( types.contains(namespaced))
255  qCritical() << "[Factory] Type factory" << namespaced << "already added !";
256  else
257  types.insert(namespaced, k.value());
258 
259  if (types.contains(k.key()))
260  qCritical() << "[Factory] Type factory" << namespaced << "already added !";
261  else
262  types.insert(k.key(), k.value());
263 
264  QVariant var = k.value()->parseString(QString::null);
265  QString varName = var.typeName();
266  QString namespacedVarName = path + ":" + k.key();
267  if ( !variantTypeMap.contains(varName))
268  {
269  variantTypeMap.insertMulti(varName, k.key());
270  variantTypeMap.insertMulti(varName, namespacedVarName);
271  }
272  }
273 
274 
275 
276  buildComponentLists();
277  libraries.insert(path,lib);
278  return true;
279 }
280 
281 
282 
283 
284 void ARCSFactory::unLoadLibrary(QString path)
285 {
286  if (!libraries.contains(path))
287  {
288  qCritical() << "[Factory] Attempted to unload an unknown library" << path ;
289  return;
290  }
291 
292  ARCSLibManager* lib = libraries[path];
293 
294  ARCSComponentMap acm = lib->getComponentMap();
295  ARCSFamilyMap afm = lib->getFamilyMap();
296  ARCSTypeMap atm = lib->getTypeMap();
297 
298 
299  // parcourir la liste des composants : maj de native
300  QHashIterator<QString, ARCSNativeComponent*> i(acm);
301 
302  while(i.hasNext())
303  {
304  i.next();
305  QString namespaced = path + ":" + i.key();
306 
307  nativeFamily->removeFactory(namespaced);
308  nativeFamily->removeFactory(i.key());
309 
310  nativeComponentLibraryMap.remove(namespaced);
311  nativeComponentLibraryMap.remove(i.key());
312  }
313 
314  // parcours des familles
315  QHashIterator<QString, ARCSAbstractFamily*> j(afm);
316 
317  while(j.hasNext())
318  {
319  j.next();
320  QString namespaced = path + ":" + j.key();
321  families.remove(namespaced);
322  families.remove(j.key());
323  familyLibraryMap.remove(namespaced);
324  familyLibraryMap.remove(j.key());
325  }
326 
327  // parcours des types
328  QHashIterator<QString, ARCSTypeFactory*> k(atm);
329  while (k.hasNext())
330  {
331  k.next();
332  QString namespaced = path + ":" + k.key();
333  types.remove(namespaced);
334  types.remove(k.key());
335  typeLibraryMap.remove(namespaced);
336  typeLibraryMap.remove(k.key());
337 
338  QVariant var = k.value()->parseString(QString::null);
339  variantTypeMap.remove(var.typeName());
340  }
341 
342  buildComponentLists();
343 }
344 
345 
346 
347 
349 {
350  if (! componentFamilyMap.contains(type))
351  {
352  ARCSLog::logError(ARCS_SOURCE,"component type " + type + " is unknown.");
353  return 0;
354  }
355 
356  QString familyName = componentFamilyMap[type];
357  if (!families.contains(familyName))
358  {
359  ARCSLog::logError(ARCS_SOURCE,"family "+ familyName + " is unkown.");
360  return 0;
361  }
362 
363  ARCSAbstractFamily* aaf = families[familyName];
364 
365 
366  if ( ! aaf->isInternal() )
367  {
368  if (! familyLibraryMap.contains(familyName))
369  {
370  qCritical() << "[Factory] family:" << familyName << "is unkown from family-library map." ;
371  return 0;
372  }
373 
374  QString libraryName = familyLibraryMap[familyName];
375  if (! libraries.contains(libraryName) )
376  {
377  qCritical() << "[Factory] library:" << libraryName << "is not loaded properly." ;
378  return 0;
379  }
380 
381  libraries[libraryName]->ref();
382  }
383 
384  ARCSAbstractComponent* aac = aaf->instanciate(type);
385  if (aac ==0)
386  return 0;
387 
388  aac->setFamily(familyName);
389  aac->setType(type);
390 
391  // un récent pb ici : ce qui était retourné : aaf->instanciate
392  // et non pas aac ?!?
393  return aac;
394 }
395 
396 
398 {
399  QString familyName = aac->getFamily();
400 
401  if (familyName.isEmpty())
402  return ;
403 
404  if (!families.contains(familyName))
405  return ;
406 
407  ARCSAbstractFamily* aaf = families[familyName];
408 
409  if (aaf != 0)
410  aaf->destroy(aac);
411 
412  if (aaf->isInternal())
413  return ;
414 
415  if (! familyLibraryMap.contains(familyName))
416  return ;
417 
418  QString libraryName = familyLibraryMap[familyName];
419  if (! libraries.contains(libraryName) )
420  return ;
421 
422  libraries[libraryName]->unref();
423 }
424 
425 
426 
427 QString ARCSFactory::getVariantType(QVariant var)
428 {
429  QStringList typesList = variantTypeMap.values(var.typeName());
430  QString first,last;
431 
432  if (typesList.count() <=0 )
433  return QString::null;
434 
435  for (int i=0; i < typesList.count() ; i++)
436  {
437  if (typesList[i].contains(":"))
438  last = typesList[i];
439  else
440  first = typesList[i];
441  }
442 
443  if (!first.isEmpty())
444  if (types.count(first) <= 1)
445  return first;
446 
447  if (!last.isEmpty())
448  return last;
449 
450  return QString::null;
451 }
452 
453 
456 {
457  QStringList typesList = variantTypeMap.values(s);
458  QString first,last;
459 
460  if (typesList.count() <= 0)
461  return QString::null;
462 
463  for (int i=0; i < typesList.count() ; i++)
464  {
465  if (typesList[i].contains(":"))
466  last = typesList[i];
467  else
468  first = typesList[i];
469  }
470 
471  if (!first.isEmpty())
472  if (types.count(first) <= 1)
473  return first;
474 
475  if (!last.isEmpty())
476  return last;
477 
478  return QString::null;
479 }
480 
481 
482 
483 
484 QVariant ARCSFactory::dataDeserialize(QString type, QString representation)
485 {
486  if (!types.contains(type))
487  {
488  qCritical() << "[Factory] Type" << type << "is unkown.";
489  return QVariant();
490  }
491 
492  QVariant var = qVariantFromValue(types[type]->parseString(representation));
493 
494  if ( types[type]->isInternal())
495  return var;
496 
497  if (!typeLibraryMap.contains(type))
498  {
499  qCritical() << "[Factory] Type" << type << "is unknown from type-library map.";
500  return var;
501  }
502 
503  QString libraryName = typeLibraryMap[type];
504  if (! libraries.contains(libraryName))
505  return var;
506 
507  libraries[libraryName]->ref();
508  return var;
509 }
510 
511 
512 QString ARCSFactory::dataSerialize(QVariant var)
513 {
514  QString type = getVariantType(var);
515 
516  if (!types.contains(type))
517  {
518  qCritical() << "[Factory] Type" << type << "is unkown.";
519  return QString::null;
520  }
521 
522  return types[type]->toString(var);
523 }
524 
525 
527 {
528  if (nativeComponentLibraryMap.contains(s))
529  return nativeComponentLibraryMap[s];
530 
531  if (componentFamilyMap.contains(s))
532  {
533  QString family = componentFamilyMap[s];
534  if (familyLibraryMap.contains(s))
535  return familyLibraryMap[family];
536  }
537 
538  return QString::null;
539 }
540 
541 QStringList ARCSFactory::getLibraryComponents(QString s)
542 {
543  if (! libraries.contains(s))
544  return QStringList();
545 
546  QStringList res;
547  res += libraries[s]->getComponentMap().keys();
548 
549  ARCSFamilyMap map = libraries[s]->getFamilyMap();
550 
551  QHashIterator<QString,ARCSAbstractFamily*> it(map);
552 
553  while (it.hasNext())
554  {
555  it.next();
556  res += it.value()->factoryList();
557  };
558 
559  return res;
560 }
561 
562 
563 
564 QString ARCSFactory::getTypeLibrary(QString s)
565 {
566  if (typeLibraryMap.contains(s))
567  return typeLibraryMap[s];
568 
569  return QString::null;
570 }
571 
572 
574 {
575  if (familyLibraryMap.contains(s))
576  return familyLibraryMap[s];
577 
578  return QString::null;
579 }
virtual bool isInternal() const
Describes wether the family is internal to ARCS or not.
Definition: arcsfactory.cpp:46
This class is a dynamic library manager.
void destroyComponent(ARCSAbstractComponent *aac)
Destroys a component.
QString getVariantType(QVariant var)
Returns the type of a QVariant.
virtual QString getTypeName() const =0
Should return the name of the type factory.
virtual void removeFactory(QString type)
Removes a component factory to the family.
QString getInternalType(QString s)
QString getTypeLibrary(QString s)
Returns the path of the library associated to a certain kind of type.
QHash< QString, ARCSNativeComponent * > ARCSComponentMap
static ARCSFactory * getInstance()
Returns the instance of the singleton ARCSFactory.
ARCSTypeMap getTypeMap()
QString getError()
ARCSFamilyMap getFamilyMap()
virtual ARCSAbstractComponent * instanciate(QString type)=0
Returns a component.
virtual QString name() const =0
name of the family
Definition: arcsfactory.cpp:41
Class handling the generic description of a component.
virtual void destroy(ARCSAbstractComponent *component)=0
Destroys a component.
A singleton handling all needed factories in ARCS runtime.
Definition: arcsfactory.h:58
This class represents the family that describes several internal component types. ...
void unLoadLibrary(QString path)
Unloads a library given the path to it.
ARCSAbstractComponent * createComponent(QString componentType)
Creates a component given its class name.
QString getFamilyLibrary(QString s)
virtual bool addFactory(QString type, ARCSAbstractComponent *whatever)
Adds a component factory to the family.
QString getComponentLibrary(QString s)
Returns the path of the library associated to a certain kind of component.
virtual QVariant parseString(QString s)=0
Should create data from their string representation.
ARCSComponentMap getComponentMap()
bool loadLibrary(QString path)
Loads a library given the path to it.
Generic class describing how type factories should be implemented.
virtual QString name() const
name of the family
QString dataSerialize(QVariant var)
Serializes data from their QVariant counterpart.
QVariant dataDeserialize(QString type, QString representation)
Deserialize data from their string representation.
QStringList getLibraryComponents(QString s)
Returns the list of components associated to a library.
Native family handling native components inside ARCS runtime.
Generic factories for each new native component type.
Abstract class representing a family of components i.e. a factory of factories of components...