/[cvs]/nfo/php/libs/org.netfrag.glib/DataSource/Generic.php
ViewVC logotype

Contents of /nfo/php/libs/org.netfrag.glib/DataSource/Generic.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations)
Sun Mar 9 15:50:36 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.2: +28 -3 lines
+ additional metadata for Autodia

1 <?php
2 /**
3 * This file contains the GenericDataSource child class
4 *
5 * @author Andreas Motl <andreas.motl@ilo.de>
6 * @package org.netfrag.glib
7 * @name DataSource::Generic
8 *
9 */
10
11 /**
12 * $Id: Generic.php,v 1.2 2003/03/05 17:28:43 joko Exp $
13 *
14 * $Log: Generic.php,v $
15 * Revision 1.2 2003/03/05 17:28:43 joko
16 * updated docu (phpDocumentor testing....)
17 *
18 * Revision 1.1 2003/03/05 12:04:00 joko
19 * + initial commit, from GenericDataSource
20 *
21 * Revision 1.3 2003/03/03 21:24:18 joko
22 * now based on DesignPattern::RemoteProxy
23 *
24 * Revision 1.2 2003/03/02 01:05:13 joko
25 * - purged old code
26 *
27 * Revision 1.1 2003/03/01 21:47:15 joko
28 * renamed from AbstractDataSource.inc
29 *
30 * Revision 1.1 2003/03/01 20:17:15 joko
31 * renamed from GenericDataSource.inc
32 * replaced '_proxy' through '_handler' to better associate the ability to act as a generic dispatcher handler
33 *
34 * Revision 1.3 2003/03/01 15:36:11 joko
35 * + debugging
36 * + renamed some methods regarding new proposal (build_handler_options, fetch_result, etc.)
37 *
38 * Revision 1.2 2003/03/01 04:50:27 joko
39 * encapsulated all output into tracing mode
40 * disabled tracing
41 *
42 * Revision 1.1 2003/03/01 03:10:40 joko
43 * + initial commit
44 *
45 *
46 */
47
48 /**
49 * This requires the MemoryDataSource base class
50 *
51 */
52
53 // V1: compile-time-include, stable since years ;-)
54 //include_once($phphtmllib."/widgets/data_source/MemoryDataSource.inc");
55
56 // V2: runtime-load proposal, more flexible
57 // loadModule('MemoryDataSource', 'inc'); // doesn't work (would do if basepath of module is in libpath)
58 // loadModule($phphtmllib . '::widgets::data_source::MemoryDataSource', 'inc'); // works (by accident)
59 // loadModule($phphtmllib . "/widgets/data_source/MemoryDataSource", "inc"); // works (should be stable)
60 // loadModule($phphtmllib . "/widgets/data_source/MemoryDataSource.inc", null); // works (should be stable)
61
62
63
64 /**
65 * Have to have PEAR and DB included
66 * the pear dir must be in the
67 * include path.
68 */
69 // require_once("PEAR.php"); // FIXME: what about PEAR::XML::RPC?
70 // require_once("DB.php");
71
72
73 loadModule('DesignPattern::Proxy');
74 loadModule('DesignPattern::TransparentProxy');
75 loadModule('DesignPattern::RemoteProxy');
76
77 //class GenericDataSource extends MemoryDataSource {
78 //class GenericDataSource extends DesignPattern_Proxy {
79 //class GenericDataSource extends DesignPattern_RemoteProxy {
80 //class GenericDataSource extends DesignPattern_TransparentProxy {
81
82 //class GenericDataSource extends MemoryDataSource {
83 //loadModule("DataSource::Proxy::Memory");
84 //class GenericDataSource extends DataSource_Proxy_Memory {
85 //class DataSource_GenericDataSource extends DataSource_Proxy_Memory {
86 //class DataSource_GenericDataSource extends DesignPattern_Proxy {
87 //class DataSource_GenericDataSource extends DataSource_Proxy_Memory {
88
89 // now independent!!! new class-inheritance-tree possible now!
90 // solved by having an Adapter *and* a Proxy here!
91 //class GenericDataSource {
92
93 loadModule('DesignPattern::AdapterProxy');
94
95
96
97 /**
98 * This GenericDataSource child class is *completely* independent
99 * of a specific storage implementation and intended to be a wrapper
100 * class on the way from phpHtmlLib to Xyz. <br>
101 * ("Yyz" gets represented by Data::Storage by now.....)
102 *
103 * GenericDataSource interacts with an intermediate "proxy" object
104 * (e.g. Data::Driver::Proxy) when doing queries. <br>
105 * <pre>
106 * Don't mix this up with a persistent database handle which gets
107 * reused each and every time for different queries.
108 * Here *is* a new instance of Data::Driver::Proxy for *each* query.
109 * </pre>
110 *
111 * But the point is: Caching! The actual *data* isn't read redundant!
112 *
113 * <pre>
114 * --- snipped into here from above ---
115 * that may use arbitrary code modules as database handlers.
116 * It's aims are to get together:
117 * o phpHtmlLibs "source-handlers"
118 * o PEAR's database handlers
119 * o custom ones (e.g. Data::Driver::Proxy object, which talks to a remote rpc server)
120 * --- snipped into here from above ---
121 * </pre>
122 *
123 *
124 * !!!!!! refactor this to Data::Driver::Proxy !!!!!! <-----------------
125 *
126 * Data::Driver::Proxy instantiates "handlers" below itself
127 * which act as encapsulated workers to actually do the stuff to do.
128 * It can cache data for "disconnected mode" using the
129 * php PEAR DB abstraction objects.
130 * One worker already implemented is Data::Driver::RPC::Remote, which
131 * talks to a RPC::XML server (todo: talk SOAP!) using PEAR::XML::RPC.
132 *
133 * <pre>
134 * --- refactored here, but: redundant somehow ---
135 * Data::Driver::Proxy uses a PEAR XML::RPC object to actually
136 * talk HTTP and serialize data chunks to and from XML,
137 * but adds some caching to this "process of fetching data from a remote side".
138 * It "proxies" arbitrary data chunks a) inside a native php4 session,
139 * b) by talking to a rdbms (single proxy-table) or c) [TODO] using PEAR::Cache.
140 * --- refactored here, but: redundant somehow ---
141 * </pre>
142 *
143 * !!!!!! refactor this to Data::Driver::Proxy !!!!!! <-----------------
144 *
145 *
146 * <b>How to use?</b>
147 *
148 * Pass an array holding "locator metadata" to the constructor.
149 * GenericDataSource takes care of the rest.
150 *
151 * Pass an array to the constructor: (e.g.)
152 *
153 * 1. doing rpc-calls....
154 * <code>
155 * $locator = array(
156 * type => 'rpc',
157 * metadata => array( Host => 'localhost', Port => '8765' ),
158 * );
159 * $source = ne w GenericDataSource($locator);
160 * $this->set_data_source( &$source );
161 * </code>
162 *
163 * 2. [proposal] common datahandles....
164 * <code>
165 * $locator = array(
166 * type => 'mysql',
167 * dsn => 'known dsn markup',
168 * );
169 * $source = ne w GenericDataSource($locator);
170 * $this->set_data_source( &$source );
171 * </code>
172 *
173 * @link http://www.netfrag.org/~joko/
174 * @author Andreas Motl <andreas.motl@ilo.de>
175 *
176 * @link http://www.netfrag.org/~jonen/
177 * @author Sebastian Utz <seut@tunemedia.de>
178 *
179 * @copyright (c) 2003 - All Rights reserved.
180 *
181 * @link http://www.gnu.org/licenses/lgpl.txt
182 * @license GNU LGPL (GNU Lesser General Public License)
183 *
184 *
185 * @package org.netfrag.glib
186 * @subpackage DataSource
187 * @name DataSource::Generic
188 *
189 * @todo
190 * <ul>
191 * o mungle this to be able to be wrapped around phpHtmlLib's own storage-handles
192 * o implement another Data::Driver::Proxy container
193 * </ul>
194 *
195
196 // !!!!!!!! THIS IS THE PROBLEM !!!!!!!!
197 // !!!!!!!! here is it where we have to break inheritance again !!!!!!!!
198 //
199 // THE CONFLICT: Beeing in phpHtmlLib *and* DesignPattern::TransparentProxy
200 // inheritance trees at the same time, which is *not* possible at
201 // declare-time. We *do* need some runtime-infrastructure to solve this!
202 //
203 // TODO: move build- and check-locator stuff from ObjectList to this place!!!
204 //
205 // ABOUT:
206 // 1. otherwhere: WebApp - scope:
207 // x handles page vs. block vs. widget; dispatches MVC-View
208 // 2. here: DataSource - scope:
209 // x handles bridge to frameworks (e.g. phpHtmlLib) vs. actual data driver libs (PEAR, etc.))
210 // o clean implementation using a DesignPattern::AdapterProxy
211 //
212
213 */
214 class DataSource_Generic extends DesignPattern_AdapterProxy {
215
216 // !!!!!!!! here is it where we have to break inheritance again !!!!!!!!
217 // !!!!!!!! THIS IS THE PROBLEM !!!!!!!!
218
219
220
221 /**
222 * This var holds the locator metadata hash
223 * that is used to feed metadata to a per-query-instance
224 * of an Adapter object.
225 *
226 */
227 //var $_locator = NULL;
228
229 /**
230 * This var holds the locator metadata hash
231 * which is built from some predefined rules
232 * using metadata from $_options and some
233 * other presets.
234 *
235 * See '_buildLocator' which acts as a dispatcher
236 * depending on $_options[datasource].
237 * (main dispatching level)
238 *
239 * The structure of a full blown locator looks like this:
240 *
241 * $locator = array(
242 * type => '<your type specifying the datasource-type>',
243 * metadata => array(
244 * ... your arbitrary deep metadata structure ...
245 * ),
246 * [dsn => '<your dsn markup>'],
247 * );
248 *
249 * Example 1 - data is inside a rdbms, using a dsn to connect to it:
250 * $locator = array(
251 * type => 'sql',
252 * dsn => 'mysql://username:password@localhost/database',
253 * );
254 *
255 * Example 2 - data is inside an odbms, reachable by doing remote procedure calls (rpc):
256 * $locator = array(
257 * type => 'rpc',
258 * metadata => array(
259 * package => 'Data::Driver::Proxy',
260 * Host => 'localhost',
261 * Port => '8765',
262 * )
263 * );
264 *
265 */
266 var $_locator = NULL;
267
268
269 /**
270 * This var holds the module information required to
271 * create instances of a Proxy and an Adapter.
272 * Information might get extracted from a
273 * DataSource::Locator instance.
274 *
275 * --- A skeleton:
276 *
277 * $this->_modules = array(
278 * _proxy => array( _id => '', _module => '', _options = array(), _instance => &$obj),
279 * _adapter => array( _id => '', _module => '', _options = array(), _instance => &$obj),
280 * );
281 *
282 *
283 * --- An example:
284 *
285 * $this->_modules = array(
286 * _proxy => array( _id => 'rpc', _module => 'DesignPattern::RemoteProxy', _instance => &$obj),
287 * _adapter => array( _id => 'phpHtmlLib', _module => 'DataSource::Adapter::phpHtmlLib::DataListSource', _instance => &$obj),
288 * );
289 *
290 *
291 */
292 //var $_modules = NULL;
293
294
295 /**
296 * This var holds the query hash
297 * that is used to feed as query to a per-query-instance
298 * of a Data::Driver::Proxy object.
299 *
300 */
301 var $_query = NULL;
302
303
304 /**
305 * this holds the query result from the
306 * Data::Driver::Proxy->queryXyz() call
307 *
308 */
309 var $_result = NULL;
310
311
312
313 /**
314 * The constructor is used to pass in the
315 * locator metadata hash.
316 *
317 * @param LocatorMetadataHash array - layout: array( type => '', metadata => '', dsn => '' )
318 * @param Query array - layout: array( type => '', metadata => '', dsn => '' )
319 */
320
321
322 function DataSource_Generic( &$locator, $query ) {
323
324 // copy parameter from query to locator
325 //$this->_locator->merge_to($this->_locator, array( datasource_type => $query[datasource] ), '_');
326 //$this->_locator->_datasource_type = $query[datasource];
327 //$locator[_datasource_type] = $query[datasource];
328
329 /**
330 * <!-- Autodia -->
331 * can do: (this is metadata supplied for Autodia, don't delete!)
332 * $this->_locator = new DataSource_Locator()
333 *
334 */
335
336 // build master locator
337 $this->_locator = php::mkComponent('DataSource::Locator', $locator, array( datasource_type => $query[datasource] ) );
338 //exit;
339 //$this->_locator = php::mkComponent('DataSource::Locator');
340
341 $this->_locator->check();
342
343 // trace
344 //print "locator-obj: " . Dumper($this->_locator);
345 //print "locator-data: " . Dumper($locator_data);
346 //exit;
347
348
349
350 /*
351 $this->_modules = array(
352 _proxy => array( _id => $locator->_datasource_type ),
353 _adapter => array( _id => $locator->_adapter_type ),
354 );
355 */
356
357 //$this->set_locator( $locator );
358 $this->set_query( $query );
359
360
361
362 /*
363 // V1:
364 // pre-flight: establish and check locator metadata
365 $this->_buildLocator();
366 $this->_checkLocator();
367 */
368
369
370
371 // pre-flight: check locator metadata
372 //$locator->build();
373 if (!$this->_locator->check()) {
374 user_error("locator-check failed.");
375 exit;
376 //return;
377 }
378
379 //exit;
380
381
382 /**
383 * <!-- Autodia -->
384 * can do: (this is metadata supplied for Autodia, don't delete!)
385 * $proxy = new DesignPattern_RemoteProxy()
386 *
387 */
388
389
390 // --- Proxy selector/dispatcher ...
391
392 switch ($this->_locator->_datasource_type) {
393 case 'rpc':
394 //$locator_data = $this->_locator->get_metadata();
395 //$this->_modules[_proxy][_options] = array( locator => $this->_locator, query => $query );
396 //$this->_modules[_proxy][_module] = 'DataSource::Proxy::XMLRPC';
397
398 //$this->_modules[_proxy][_module] = 'DesignPattern::RemoteProxy';
399 //$this->_modules[_proxy][_options] = $locator_data;
400
401 //$this->set_component_name('DesignPattern::RemoteProxy');
402 //$this->set_component_options($locator_data);
403
404 $this->set_component_name('DesignPattern::RemoteProxy');
405
406 break;
407 default:
408 user_error("Site::GenericPage: no Proxy could be selected!");
409 break;
410 }
411
412
413
414 /*
415 // V1:
416 // make up dummy args by now
417 $args = array(
418 adapter => 'phpHtmlLib',
419 );
420 */
421
422 // V2: now propagated from caller!
423
424 //print Dumper(array( locator => $locator, query => $query ));
425 //exit;
426
427 //$this->create_adapter($this->module, $this->function, $this->arguments);
428 //$this->set_handler( $this->get_adapter() );
429
430
431 // --- Adapter selector/dispatcher ...
432 // ... resolves this._modules.adapter._id to this._modules.adapter._module
433
434 switch ($locator->_adapter_type) {
435 case 'phpHtmlLib':
436 //$adapter_arguments = $args[title];
437
438 $this->set_adapter_module('DataSource::Adapter::phpHtmlLib::DataListSource');
439
440 // in order to let the Adapter communicate with the Proxy,
441 // instantiate a wrapper method in a third namespace via
442 // Exporter::export_symbol(from, to)
443 $this->set_adapter_options($this);
444
445
446 break;
447 default:
448 user_error("DataSource::GenericDataSource: no Adapter could be selected!");
449 break;
450 }
451
452
453
454 // --- module instantiation - Proxy and Adapter
455
456 //user_error("handle proxy here!");
457 //$this->create_proxy();
458
459 //print Dumper($this);
460
461 //print "this: " . Dumper($this);
462
463 // V1:
464 /*
465 $proxy = php::mkComponent($this->_modules[_proxy][_module], $this->_modules[_proxy][_options]);
466 print "proxy: " . Dumper($proxy);
467 //exit;
468 */
469
470 // V2:
471 /*
472 $resultHandle = mkObject('DesignPattern::RemoteProxy', $cache_key, array( key => 1, command => $command, query => $query, remote => 1, rpcinfo => $rpcinfo, cache => array( db => 0, session => 1 ) ) );
473 $result = $resultHandle->getAttributes();
474 return $result;
475 */
476
477 // V3:
478 // $this->set_handler( $proxy );
479
480 // V4: use _component_name & _component_options (proposal from GenericPage)
481 // $this->_component_name = ...
482 // $this->create_handler();
483
484
485 /**
486 * <!-- Autodia -->
487 * can do: (this is metadata supplied for Autodia, don't delete!)
488 * $adapter = new DataSource_Adapter_phpHtmlLib_DataListSource()
489 *
490 */
491
492 // V1:
493 //$this->create_adapter($adapter_module, $this->function, $this->arguments);
494
495 // V2: FIXME - better use V1?
496 $adapter = php::mkComponent($this->get_adapter_module(), $this->get_adapter_options());
497 $this->set_adapter($adapter);
498
499
500
501
502 }
503
504 function make_adapter_transparent() {
505
506 // ... known from Site::Adapter::php::Class:
507
508 // At this place the Adapter becomes a Proxy.
509 // This functionality currently correlates to the
510 // name of our ancestor, DesignPattern::AdapterProxy.
511 // FIXME: move this code to its namespace!!!
512 // FIXME: rename to set_proxy...
513
514 // The reason this has to occour here is required
515 // by the TransparentProxy to actually make the
516 // _handler (_proxy) transparent later....
517 //$this->set_proxy( $this->get_adapter() );
518 }
519
520 /**
521 * Set the metadata information
522 * (a DataSource::Locator) we will use
523 * to build encapsulated instances
524 * of both a Proxy and an Adapter.
525 *
526 * @param LocatorMetadataHash array -
527 *
528 */
529 function set_metadata( &$locator ) {
530 $this->_locator = &$locator;
531 }
532
533 function &get_metadata() {
534 return $this->_locator;
535 }
536
537
538 /**
539 * Set the query metadata hash we will feed *completely*
540 * to an encapsulated Proxy instance.
541 *
542 * @param QueryDeclaration array -
543 *
544 */
545 function set_query( $query ) {
546 $this->_query = $query;
547 }
548
549 /**
550 * Issue remote/proxy call
551 * Stolen from Application_AbstractBackend::_remote_method (RefactoringProposal?)
552 * Tweaked a bit: proxy package now taken from $this->_handler_name
553 *
554 * Create a new instance of a proxy and store it for later reuse.
555 * Read the locator metadata hash and create
556 * the proxy handler instance using passed-in name.
557 *
558 * @param string - $proxy_name (namespaced classname - perl syntax - e.g.: Data::Driver::Proxy)
559 *
560 */
561 function datasource_handler_call() {
562
563
564 // 1. read args and build cache key
565
566 $arg_list = func_get_args();
567 $command = array_shift($arg_list);
568 $cache_key = join("-", array(session_id(), $command, join('_', $arg_list) ));
569 //print "cache_key: $cache_key<br>";
570
571 // FIXME: what if arg_list still contains more elements after doing this?
572 $query = array_shift($arg_list);
573
574 // 2. prepare proxy-options (read from locator)
575
576 //print "this: " . Dumper($this);
577 //exit;
578
579 // read from locator metadata
580 //$proxy_name = $this->_locator[metadata][package];
581
582 // V1:
583 //$rpcinfo = array( Host => $this->_locator[metadata][Host], Port => $this->_locator[metadata][Port] );
584
585 // V2:
586 $rpcinfo = $this->_locator->get_metadata();
587
588 // FIXME! implement this into Data::Driver::RPC::Remote!
589 //$rpcinfo[to_latin] = 1;
590
591 // FIXME! patch query
592 if (sizeof($query) == 1) {
593 $query = $query[0];
594 }
595
596 //print "query: " . Dumper($query);
597
598 // !!! use DesignPattern::Proxy here !!!
599 // $proxy = new DesignPattern_Proxy($proxy_name, ...)
600 // or:
601 // $proxy = mkObject('DesignPattern::Proxy');
602 // $this->set_handler( $proxy );
603 // or:
604 // $proxy = mkObject('DesignPattern::Proxy');
605 // $proxy->
606 // $this->set_handler( $proxy );
607
608
609
610 //$this->set_component_name( $proxy_name );
611 $this->set_component_options( $cache_key, array( key => 1, command => $command, query => $query, remote => 1, rpcinfo => $rpcinfo, cache => array( db => 0, session => 1 ) ) );
612 //print Dumper($this);
613 //exit;
614
615 $this->create_proxy();
616
617 //print Dumper($this);
618 //exit;
619
620 /*
621 // -------------------- clone this & modify ----------
622 $proxy = mkObject($proxy_name, $cache_key, array( key => 1, command => $command, query => $query, remote => 1, rpcinfo => $rpcinfo, cache => array( db => 0, session => 1 ) ) );
623 $this->set_handler( $proxy );
624 //$result = $resultHandle->getAttributes();
625 //return $result;
626 //$this->_result = $resultHandle->getAttributes();
627 //$this->_result = $this->_handler->getAttributes();
628 // -------------------- clone this & modify ----------
629 */
630
631 }
632
633
634 function datasource_handler_buildoptions() {
635
636 //print Dumper($this->_query);
637 //exit;
638
639 // make up a command from metadata
640 // FIXME: abstract this some more (e.g. via a CommandMapper|Registry)
641 switch ($this->_query[metatype]) {
642 case 'data':
643 //$command = 'queryData';
644 $command = 'getObjects'; // FIXME!!!
645 //$this->_locator->set_option('metadata.command', $command);
646 $args = array();
647 switch ($this->_query[vartype]) {
648 case 'object':
649 if (!$this->_query[classname]) {
650 $msg = "_query[vartype] == 'object' requires _query[classname]";
651 user_error("GenericDataSource::query_data() - failed: " . $msg);
652 }
653 array_push($args, $this->_query[classname]);
654 break;
655 }
656 break;
657 case 'schema':
658 $command = 'querySchema';
659 break;
660 }
661
662
663 /*
664 $this->_query[rpc_command] = $command;
665 $this->_query[rpc_args] = $command;
666 */
667
668 // methods!!!
669 $this->_locator->_call[_method] = $command;
670 $this->_locator->_call[_arguments] = $args;
671
672 //$adapter = $this->get_adapter();
673
674 // trace
675 /*
676 print Dumper(null, '<b>= = = = = = = = = = = = = = = = = = = = = =</b>');
677 print Dumper('datasource_handler_buildoptions', array(
678 "_locator" => $this->_locator,
679 "_query" => $this->_query,
680 "command" => '<b>' . $command . "</b>",
681 "args" => $args
682 ));
683 */
684
685 /*
686 $this->_handler_options = array(
687 method => $command,
688 args => $args,
689 );
690 */
691
692 }
693
694 function &fetch_result() {
695
696 $this->datasource_handler_buildoptions();
697
698 $method = $this->_locator->_call[_method];
699 $args = $this->_locator->_call[_arguments];
700
701 // pre-flight checks
702 if (!$method) {
703 $msg = "Remote command could not be resolved, please pass in or check configuration.";
704 user_error("GenericDataSource::query_data() - failed: " . $msg);
705 return;
706 }
707
708 //print "fetch_result: this->_handler=" . Dumper($this->_handler);
709
710 // do remote call here and get result
711 // FIXME: handle synchronous/asynchronous mode here!!!
712 $this->datasource_handler_call($method, $args);
713
714
715 // TODO: ... = $this->poll_handler_result and $this->get_handler_result
716 $proxy = $this->get_proxy();
717 $this->_result = $proxy->getResult();
718 //print "result: " . Dumper($this->_result); exit;
719
720 $this->_result_count = sizeof($this->_result);
721
722 // trace
723 if ($this->_debug[notice]) {
724 //print "_result = " . Dumper($this->_result);
725 print "DataSource::Generic->_result_count = " . $this->_result_count . "<br/>";
726 }
727
728 return $this->_result;
729
730 }
731
732
733 function &query_data() {
734 //print "query!<br/>";
735 return $this->fetch_result();
736 //$this->handle_result();
737 }
738
739 function query_schema() {
740 user_error("FIXME: query_schema");
741 // $this->datasource_handler_call( ... );
742 }
743
744 function &get_result() {
745 return $this->_result;
746 }
747
748 }
749
750 ?>

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed