/[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.5 - (show annotations)
Tue Mar 11 00:12:49 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.4: +8 -5 lines
+ fixed metadata for phpDocumentor

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

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