factory._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2006 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: factory.pike,v 1.2 2009/08/07 15:22:36 nicke Exp $
18  */
19 inherit "/classes/Object";
20 #include <macros.h>
21 #include <roles.h>
22 #include <assert.h>
23 #include <attributes.h>
24 #include <classes.h>
25 #include <access.h>
26 #include <database.h>
27 #include <types.h>
28 #include <events.h>
29 #include <exception.h>
30 //! This is the factory class - other factories are derived from this one.
31 //! See the factory pattern for factories in general.
32 //! A factory is used by calling the execute() function and passing a mapping
33 //! of params. Each factory used the param "name" for execution in order to
34 //! give a new object a name. The factory for a class is retrieved by calling
35 //! the globally available function "get_factory(int classbit)", for example
36 //! get_factory(CLASS_USER).
37 class factory : public Object{
38 public:
39 
40 
41 
42 
43 
44 import Attributes;
45 
46 
47  Thread.Queue updateQueue = Thread.Queue();
48  mapping mRegAttributes =([ ]); // "attribute-name":Attribute
49  mapping mUpdAttributes=([ ]);
50  int modeRegister = 0;
51 
52 bool check_swap() { return false; }
53 bool check_upgrade() { return false; }
54 
55 
56 /**
57  * Init callback function sets a data storage.
58  *
59  */
60 protected:
61  void
62 init()
63 {
64  ::init();
65 private:
66  add_data_storage(STORE_ATTREG, retrieve_attr_registration,
67  restore_attr_registration);
68 }
69 
70 private:
71  void init_factory()
72 {
73  register_class_attribute(UserAttribute(OBJ_NAME, "object name", CMD_TYPE_STRING,""));
74  register_class_attribute(UserAttribute(OBJ_DESC, "description", CMD_TYPE_STRING,""));
75  register_class_attribute(UserAttribute(OBJ_ICON, "icon", CMD_TYPE_OBJECT, 0));
76  register_class_attribute(UserAttribute(OBJ_LINK_ICON,"link icon",CMD_TYPE_OBJECT,0));
77  register_class_attribute(Attribute(OBJ_URL,"url", CMD_TYPE_STRING, 0,
78  get_module("filepath:url")));
79  register_class_attribute(UserAttribute(OBJ_KEYWORDS,"keywords",CMD_TYPE_ARRAY,({})));
80  register_class_attribute
81  (PositionAttribute(OBJ_POSITION_X, "x-position", CMD_TYPE_FLOAT, 0.0));
82  register_class_attribute
83  (PositionAttribute(OBJ_POSITION_Y, "y-position", CMD_TYPE_FLOAT, 0.0));
84  register_class_attribute
85  (PositionAttribute(OBJ_POSITION_Z, "z-position", CMD_TYPE_FLOAT, 0.0));
86  register_class_attribute
87  (PositionAttribute(OBJ_WIDTH, "width of object", CMD_TYPE_FLOAT, 0.0));
88  register_class_attribute
89  (PositionAttribute(OBJ_HEIGHT, "height of object", CMD_TYPE_FLOAT, 0.0));
90 
91  register_class_attribute(UserAttribute(OBJ_LANGUAGE,"language",CMD_TYPE_STRING,"de"));
92  register_class_attribute(Attribute(OBJ_ANNO_MESSAGE_IDS,
93  "maps message ids to annotations",
94  CMD_TYPE_MAPPING,
95  ([]),
96  0,
97  CONTROL_ATTR_SERVER));
98  register_class_attribute(Attribute(OBJ_ANNO_MISSING_IDS,
99  "stores message ids which were missing for annotations",
100  CMD_TYPE_MAPPING,
101  ([]),
102  0,
103  CONTROL_ATTR_SERVER));
104  register_class_attribute(Attribute(OBJ_ONTHOLOGY,
105  "Onthology of the object.",
106  CMD_TYPE_OBJECT,
107  0,
108  0,
109  CONTROL_ATTR_USER));
110 
111  register_class_attribute(Attribute(OBJ_VERSIONOF,
112  "points to the current version",
113  CMD_TYPE_OBJECT,
114  0));
115  register_class_attribute(Attribute(OBJ_LINKS,
116  "all links of this object",
117  CMD_TYPE_ARRAY,
118  ({ })));
119  register_class_attribute(Attribute(OBJ_PATH,
120  "the path of this object",
121  CMD_TYPE_STRING,
122  ""));
123 }
124 
125 public:
126 
127 /**
128  * A factory calls initialization of factory when it is loaded.
129  *
130  */
131 protected:
132  void load_object()
133 {
134  if ( !mappingp(mRegAttributes) )
135  mRegAttributes = ([]);
136  mUpdAttributes = ([ ]);
137 
138  if ( sizeof(mUpdAttributes) > 0 ) {
139  MESSAGE("Updating Instances after loading factory !");
140  update_instances(mUpdAttributes);
141  }
142 
143  mUpdAttributes = ([ ]);
144 }
145 
146 public:
147 
148 /**
149  * Object constructor. Here the Attribute registration mapping is initialized.
150  *
151  */
152 protected:
153  void create_object()
154 {
155  mRegAttributes = ([]);
156  init_factory();
157  require_save(STORE_ATTREG);
158 }
159 
160 public:
161 
162 /**
163  * See if a given name is valid for objects created by this factory.
164  *
165  * @param string name - the name of the object
166  */
167 void valid_name(string name)
168 {
169  if ( !stringp(name) )
170  steam_user_error("The name of an object must be a string !");
171  if ( search(name, "/") >= 0 )
172  steam_user_error("/ is not allowed in Object Names...(%O)", name);
173  if ( !xml.utf8_check(name) )
174  steam_user_error("Name %O of object is not utf-8 !", name);
175 }
176 
177 
178 /**
179  * create a new object of 'doc_class'
180  *
181  * @param string name - the name of the new object
182  * @param string doc_class - the class of the new object
183  * @param object env - the env the object should be moved to
184  * @param mapping|int attr - attribute mapping for initial attribute settings
185  * @param void|mapping attrAcq - acquired attributes
186  * @param void|mapping attrLocked - locked attributes initialization
187  * @param void|mapping sanction - sanction initialization
188  * @param void|mapping sanctionMeta - meta sanction initialization
189  * @return pointer to the new object
190  */
191 protected:
192  object
193 object_create(string name, string doc_class, object env, int|mapping attr,
194  void|mapping attrAcq, void|mapping attrLocked,
195  void|mapping sanction, void|mapping sanctionMeta)
196 {
197  object obj, user;
198 
199  user = geteuid() || this_user();
200 
201  doc_class = CLASS_PATH + doc_class + ".pike";
202  SECURITY_LOG("New object of class:" + doc_class + " at " + ctime(time()));
203 
204  valid_name(name);
205 
206  if ( mappingp(attr) ) {
207  foreach(values(attr), mixed v) {
208  if ( stringp(v) && !xml.utf8_check(v) )
209  error("Create: Invalid Attribute found (utf-8 check failed).");
210  }
211  }
212 
213  if ( objectp(env) && !(env->get_object_class() & CLASS_CONTAINER) )
214  steam_error("Failed to move object to " + env->get_object_id() +
215  " : object is no container !");
216 
217  obj = new(doc_class, name, attr);
218  if ( !objectp(obj) )
219  THROW("Failed to create object !", E_ERROR);
220 
221  function obj_set_attribute = obj->get_function("do_set_attribute");
222  function obj_acquire_attribute = obj->get_function("do_set_acquire_attribute");
223  function obj_lock_attribute = obj->get_function("do_lock_attribute");
224  function obj_sanction_object = obj->get_function("do_sanction_object");
225  function obj_sanction_object_meta =obj->get_function("do_sanction_object_meta");
226 
227  obj_set_attribute,
228  obj_acquire_attribute);
229 
230  if ( !stringp(name) || name == "" )
231  THROW("No name set for object !", E_ERROR);
232 
233  obj_set_attribute(OBJ_NAME, name);
234  obj_set_attribute(OBJ_CREATION_TIME, time());
235 
236  if ( !mappingp(attr) || !objectp(attr[OBJ_ICON]) )
237  obj_acquire_attribute(OBJ_ICON, _Server->get_module("icons"));
238 
239  if ( !stringp(obj->query_attribute(OBJ_NAME)) ||
240  obj->query_attribute(OBJ_NAME) == "" )
241  THROW("Strange error - attribute name setting failed !", E_ERROR);
242 
243  SECURITY_LOG("Object " + obj->get_object_id() + " name set on " +
244  ctime(time()));
245 
246  if ( !objectp(user) )
247  user = MODULE_USERS->lookup("root");
248  obj->set_creator(user);
249 
250  if ( user != MODULE_USERS->lookup("root") &&
251  user != MODULE_USERS->lookup("guest") )
252  {
253  obj_sanction_object(user, SANCTION_ALL);
254  obj_sanction_object_meta(user, SANCTION_ALL);
255  }
256  obj->set_acquire(obj->get_environment);
257  ASSERTINFO(obj->get_acquire() == obj->get_environment,
258  "Acquire not on environment, huh?");
259 
260  foreach(indices(attrAcq||([])), string acqi) {
261  obj_acquire_attribute(acqi, attrAcq[acqi]);
262  }
263  foreach(indices(attrLocked||([])), string locki) {
264  obj_lock_attribute(locki);
265  }
266  foreach(indices(sanction||([])), object sanctioni) {
267  if ( objectp(sanctioni) )
268  obj_sanction_object(sanctioni, sanction[sanctioni]);
269  }
270  foreach(indices(sanctionMeta||([])), object sanctionmi) {
271  if ( objectp(sanctionmi) )
272  obj_sanction_object_meta(sanctionmi, sanctionMeta[sanctionmi]);
273  }
274 
275  obj->created();
276 
277  if ( objectp(env) ) {
278  }
279 }
280 
281 public:
282 
283 protected:
284  bool install_attribute(Attribute attr,
285  object obj,
286  void|mixed val,
287  void|function obj_set_attribute,
288  void|function obj_acquire_attribute)
289 {
290  if ( !objectp(obj) || obj->status() < 0 )
291  return true;
292 
293  if ( !functionp(obj_set_attribute) )
294  obj_set_attribute = obj->get_function("do_set_attribute");
295  if ( !functionp(obj_acquire_attribute))
296  obj_acquire_attribute = obj->get_function("do_set_acquire_attribute");
297 
298  mixed err = catch {
299  mixed key = attr->get_key();
300  mixed def = attr->get_default_value();
301  string|object acq = attr->get_acquire();
302 
303  if ( obj->is_locked(key) )
304  return true;
305 
306  if ( !zero_type(def) ) {
307  obj_set_attribute(key, copy_value(def));
308  }
309 
310  // do not acquire attributes for the default objects set
311  if ( !objectp(acq) || acq != obj )
312  {
313  if ( stringp(acq) )
314  obj_acquire_attribute(key, obj->find_function(acq));
315  else
316  obj_acquire_attribute(key, acq);
317  }
318  if ( !zero_type(val) ) {
319  obj_set_attribute(key, val);
320  }
321  return true;
322  };
323  FATAL("Error registering attribute: %s\n%s",
324  err[0],
325  describe_backtrace(err[1]));
326 }
327 
328 public:
329 
330 array get_inherited_factories()
331 {
332  array factories = _Server->get_factories();
333  array depFactories = ({ });
334  array myPrograms = Program.all_inherits(object_program(this_object()));
335  foreach ( factories, object factory ) {
336  if ( search(myPrograms, object_program(factory->get_object())) >= 0 ) {
337  depFactories += ({ factory });
338  }
339  }
340  return depFactories;
341 }
342 
343 array get_derived_factories()
344 {
345  array factories = _Server->get_factories();
346  array depFactories = ({ });
347  foreach ( factories, object factory ) {
348  array facPrograms = Program.all_inherits(object_program(factory->get_object()));
349  if ( search(facPrograms, object_program(this_object())) >= 0 ) {
350  depFactories += ({ factory });
351  }
352  }
353  return depFactories;
354 }
355 
356 /**
357  * register all attributes for an object
358  *
359  * @param obj - the object to register attributes
360  * @see register_class_attribute
361  */
362 protected:
363  void install_attributes(object obj,
364  void|mapping mAttr,
365  string|void key,
366  void|function obj_set_attribute,
367  void|function obj_acquire_attribute)
368 {
369  Attribute attr;
370 
371  if ( !functionp(obj_set_attribute) )
372  obj_set_attribute = obj->get_function("do_set_attribute");
373  if ( !functionp(obj_acquire_attribute) )
374  obj_acquire_attribute = obj->get_function("do_set_acquire_attribute");
375 
376  if ( !mappingp(mAttr) )
377  mAttr = ([ ]);
378 
379  if ( stringp(key) ) {
380  attr = mRegAttributes[key];
381  if ( objectp(attr) )
382  obj_set_attribute,
383  obj_acquire_attribute);
384  }
385  else {
386  foreach (indices(mRegAttributes), key) {
387  attr = mRegAttributes[key];
388  obj_set_attribute,
389  obj_acquire_attribute);
390  }
391  }
392 }
393 
394 public:
395 
396 /**
397  * register attributes for the class(es) this factory creates.
398  * each newly created object will have the attributes registered here.
399  *
400  * @param Attribute attr - the new attribute to register.
401  * @param void|function conversion - conversion function for all objects
402  *
403  * @see classes/Object.set_attribute
404  * @see libraries/Attributes.pmod.Attribute
405  */
406 void
407 register_attribute(Attribute attr, void|object conversion)
408 {
409  try_event(EVENT_REGISTER_ATTRIBUTE, CALLER, attr);
410 
411  if ( register_class_attribute(attr, conversion) == 0 )
412  return;
413 
414  // register on all dependent factories too
415  array factories = values(_Server->get_classes());
416  foreach ( factories, object factory ) {
417  factory = factory->get_object();
418  if ( factory->get_object_id() == get_object_id() )
419  continue;
420  if ( search(Program.all_inherits(object_program(factory)),
421  object_program(this_object())) >= 0 )
422  factory->register_attribute(copy_value(attr), conversion);
423  }
424 
425  update_instances(attr->get_key());
426 
427  run_event(EVENT_REGISTER_ATTRIBUTE, CALLER, attr);
428 }
429 
430 void unregister_attribute(string key)
431 {
432  Attribute attr = mRegAttributes[key];
433  if ( !objectp(attr) )
434  return;
435 
436  try_event(EVENT_REGISTER_ATTRIBUTE, CALLER, attr);
437  if ( unregister_class_attribute(attr) == 0 )
438  return;
439  array factories = values(_Server->get_classes());
440  foreach ( factories, object factory ) {
441  factory = factory->get_object();
442  if ( factory->get_object_id() == get_object_id() )
443  continue;
444  if ( search(Program.all_inherits(object_program(factory)),
445  object_program(this_object())) >= 0 )
446  factory->unregister_attribute(copy_value(attr));
447  }
448 
449  run_event(EVENT_REGISTER_ATTRIBUTE, CALLER, attr);
450 }
451 
452 /**
453  * Update instances of objects created by this factory when a new
454  * attribute is registered. This sets the new default value for the attribute
455  * and the basic acquiring.
456  *
457  * @param mixed key - the attribute key.
458  * @param function|void conv - the conversion function.
459  */
460 void update_instances(mixed key)
461 {
462  Attribute attr;
463  if ( !mappingp(key) ) {
464  attr = mRegAttributes[key];
465  if ( !objectp(attr) )
466  THROW("Unregistered Attribute !", E_ERROR);
467  }
468  else {
469  if ( sizeof(key) == 0 ) {
470  MESSAGE("(%s) Nothing to update !", get_identifier());
471  return;
472  }
473  }
474 
475  array instances = get_all_objects();
476  int cnt = 0;
477  int csz = sizeof(instances);
478  foreach(instances, object instance) {
479  cnt++;
480  if ( cnt % 10000 == 0 ) {
481  MESSAGE("Registering attribute %O : %d of %d objects done.",
482  key, cnt, csz);
483  }
484  if ( !objectp(instance) || instance->status() < 0 )
485  continue;
486 
487 
488  // object is saved and can be updated later !
489  if ( instance->status() == PSTAT_DISK )
490  continue;
491 
492  // this should not happen anymore!!!
493  if ( !functionp(instance->get_object_class) ||
494  !(instance->get_object_class() & get_class_id()) ) {
495  FATAL("Got wrong instance %O in %s\n", instance, get_identifier());
496  continue;
497  }
498  if ( mappingp(key) ) {
499  function obj_set_attribute = instance->get_function("do_set_attribute");
500  function obj_acquire_attribute = instance->get_function("do_set_acquire_attribute");
501  foreach( indices(key), mixed k) {
502  attr = mRegAttributes[k];
503  if ( !attr->check_convert(instance) &&
504  !check_attribute_registration(instance, attr) )
505  install_attribute(attr, instance, UNDEFINED,
506  obj_set_attribute,
507  obj_acquire_attribute);
508  }
509  }
510  else {
511  if ( !attr->check_convert(instance) &&
512  !check_attribute_registration(instance, attr) ) {
513  install_attribute(attr, instance);
514  }
515  }
516  }
517 }
518 
519 
520 /**
521  * Register_class_attribute is called by register_attribute,
522  * this function is local and does no security checks. All instances
523  * of this class are set to the default value and acquiring settings.
524  *
525  * @param Attribute attr - the Attribute to register for this factories class
526  * @see register_attribute
527  */
528 protected:
529  int register_class_attribute(Attribute attr, void|object conv)
530 {
531  string|int key = attr->get_key();
532  Attribute pattr = mRegAttributes[key];
533  if ( pattr == attr )
534  return 0;
535 
536  modeRegister = 1;
537 
538  do_set_attribute(FACTORY_LAST_REGISTER, time());
539  if ( objectp(conv) )
540  attr->set_converter(conv);
541  mRegAttributes[key] = attr;
542  require_save(STORE_ATTREG);
543 
544  modeRegister = 0;
545 
546  foreach( get_inherited_factories(), object factory ) {
547  if ( factory->is_attribute(key) )
548  return 1;
549  }
550 
551  mUpdAttributes[key] = 1;
552  return 1;
553 }
554 
555 public:
556 
557 protected:
558  int unregister_class_attribute(Attribute attr)
559 {
560  m_delete(mRegAttributes, attr->get_key());
561  require_save(STORE_ATTREG);
562  return 1;
563 }
564 
565 public:
566 
567 
568 /*
569  * Init an attribute of this class calls registration function.
570  *
571  * @see register_class_attribute
572  */
573 protected:
574  void
575 private:
576 init_class_attribute(mixed key, int type, string desc,
577  int event_read, int event_write,
578  object|int acq, int cntrl, mixed def)
579 {
580  Attribute attr = Attribute(key, desc, type, def, acq,
581  cntrl, event_read, event_write);
582  if ( !objectp(mRegAttributes[key]) )
583  register_class_attribute(attr);
584 }
585 
586 public:
587 
588 /**
589  * Check if an attributes value is going to be set correctly.
590  * An objects set_attribute function calls this check and
591  * throws an error if the value is incorrect.
592  *
593  * @param mixed key - the attributes key.
594  * @param mixed data - the new value of the attribute.
595  * @param int|void regType - registration data to check, if void use factories.
596  * @return true or false.
597  */
598 bool check_attribute(mixed key, mixed data, int|void regType)
599 {
600  object caller = CALLER;
601 
602  if ( !objectp(mRegAttributes[key]) )
603  return true;
604 
605  // see if our factory has something about this attribute
606  // if previous attribute in zero
607  // this will end up in loop when installing attributes
608  if ( zero_type(caller->query_attribute(key)) )
609  install_attributes(CALLER, ([ ]), key);
610 
611 
612  // value 0 should be ok
613  if ( data == 0 ) return true;
614  if ( key == "OBJ_NAME" )
615  valid_name(data);
616 
617  return mRegAttributes[key]->check_attribute(data);
618 }
619 
620 
621 /**
622  * check the registration of an attribute
623  *
624  * @param object obj - the object to check the attribute
625  * @param Attribute attr - the new registered attribute
626  * @return if the attribute is ok
627  */
628 bool check_attribute_registration(object obj, Attribute attr)
629 {
630  string key = attr->get_key();
631  mixed val = obj->query_attribute(key);
632  if ( zero_type(val) )
633  return false;
634 
635  if ( val == attr->get_default_value() )
636  return true;
637  switch(attr->get_type()) {
638  case CMD_TYPE_INT: if ( !intp(val) ) return false; break;
639  case CMD_TYPE_FLOAT: if ( !floatp(val) ) return false; break;
640  case CMD_TYPE_STRING: if ( !stringp(val) ) return false; break;
641  case CMD_TYPE_OBJECT: if ( !objectp(val) ) return false; break;
642  case CMD_TYPE_ARRAY: if ( !arrayp(val) ) return false; break;
643  case CMD_TYPE_MAPPING: if ( !mappingp(val) ) return false; break;
644  case CMD_TYPE_PROGRAM: if ( !programp(val) ) return false; break;
645  case CMD_TYPE_FUNCTION: if ( !functionp(val) ) return false; break;
646  }
647  return true;
648 }
649 
650 /**
651  * check all attributes of an object
652  *
653  * @param object obj - the object to check
654  * @return true or false (attributes changed)
655  * @see check_attribute
656  */
657 bool check_attributes(object obj)
658 {
659  int last_change = obj->query_attribute(OBJ_LAST_CHANGED);
660  if ( last_change <= do_query_attribute(FACTORY_LAST_REGISTER) ) {
661 
662  if ( modeRegister ) {
663  FATAL("checking object %O while registering .... !\n", obj);
664  steam_error("registration failed due to loading objects ...");
665  }
666  function obj_set_attribute=obj->get_function("do_set_attribute");
667  function obj_acquire_attribute=obj->get_function("do_set_acquire_attribute");
668 
669  foreach ( indices(mRegAttributes), string key ) {
670  Attribute a = mRegAttributes[key];
671  if ( !a->check_convert(obj) &&
672  !check_attribute_registration(obj, a) )
673  install_attribute(a, obj, UNDEFINED,
674  obj_set_attribute,
675  obj_acquire_attribute);
676 
677  }
678  obj_set_attribute(OBJ_LAST_CHANGED, time());
679  return true;
680  }
681  return false;
682 }
683 
684 
685 /**
686  * Get the registration information for one attribute of this class.
687  *
688  * @param mixed key the attributes key.
689  * @return The array of registered data.
690  */
691 Attribute describe_attribute(mixed key)
692 {
693  return copy_value(mRegAttributes[key]);
694 }
695 
696 /**
697  * Get all registered attributes for this class.
698  *
699  * @return the mapping of registered attributes for this class
700  * @see register_class_attribute
701  */
702 mapping get_attributes()
703 {
704  return copy_value(mRegAttributes);
705 }
706 
707 bool is_attribute(string key)
708 {
709  if ( mRegAttributes[key] )
710  return true;
711  return false;
712 }
713 
714 /**
715  * Get the event to fire upon reading the attribute.
716  *
717  * @param mixed key - the attributes key.
718  * @return read event or zero.
719  * @see get_attribute_change_event
720  */
721 int get_attributes_read_event(mixed key)
722 {
723  if ( !arrayp(mRegAttributes[key]) )
724  return 0;
725  return mRegAttributes[key]->get_read_event();
726 }
727 
728 /**
729  * Get the event to fire upon changing an attribute.
730  *
731  * @param mixed key - the attributes key.
732  * @return change event or zero.
733  * @see get_attributes_read_event
734  */
735 int get_attributes_change_event(mixed key)
736 {
737  if ( !mappingp(mRegAttributes) || !objectp(mRegAttributes[key]) )
738  return EVENT_ATTRIBUTES_CHANGE;
739  return mRegAttributes[key]->get_write_event();
740 }
741 
742 /**
743  * Get an attributes default value and acquiring.
744  *
745  * @param mixed key - the attributes key.
746  * @return array of default value and acquiring setting.
747  */
748 array get_attribute_default(mixed key)
749 {
750  return ({ mRegAttributes[key]->get_default_value(),
751  mRegAttributes[key]->get_acquire() });
752 }
753 
754 /**
755  * Called by the _Database to get the registered attributes (saved data)
756  * for this factory.
757  *
758  * @return mapping of registered attributes.
759  */
760 final mapping
761 private:
762 retrieve_attr_registration()
763 {
764  if ( CALLER != _Database )
765  THROW("Invalid call to retrieve_data()", E_ACCESS);
766  return ([
767  "RegAttributes":map(mRegAttributes, save_attribute),
768  ]);
769 }
770 
771 public:
772 
773 protected:
774  mapping save_attribute(Attribute attr)
775 {
776  return attr->save();
777 }
778 
779 public:
780 
781 /**
782  * Called by _Database to restore the registered attributes data.
783  *
784  * @param mixed data - restore data.
785  */
786 final void
787 private:
788 restore_attr_registration(mixed data)
789 {
790  if ( CALLER != _Database )
791  THROW("Invalid call to restore_data()", E_ACCESS);
792  foreach(indices(data->RegAttributes), mixed key) {
793  if ( !stringp(key) )
794  continue;
795  mixed v = data->RegAttributes[key];
796  if ( arrayp(v) ) {
797  mixed acq = v[4];
798  if ( intp(acq) && acq == 1 )
799  acq = REG_ACQ_ENVIRONMENT;
800  Attribute a = Attribute(key,v[1],v[0],v[6],acq,v[5],v[2],v[3]);
801  mRegAttributes[key] = a;
802  }
803  else {
804  Attribute a = Attribute(v->key,v->desc,v->type,v->def,v->acquire,
805  v->control, v->event_read, v->event_write);
806  if ( v->converter )
807  a->set_converter(v->converter);
808  mRegAttributes[key] = a;
809  }
810  }
811 }
812 
813 public:
814 
815 array get_all_objects()
816 {
817  return _Database->get_objects_by_class("/classes/"+get_class_name());
818 }
819 
820 string get_identifier() { return "factory"; }
821 int get_object_class() { return ::get_object_class() | CLASS_FACTORY; }
822 string get_class_name() { return "undefined"; }
823 int get_class_id() { return CLASS_OBJECT; }
824 
825 
826 };