/[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.1 - (show annotations)
Wed Mar 5 12:04:00 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
+ initial commit, from GenericDataSource

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

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