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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Wed Mar 5 12:04:00 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
+ initial commit, from GenericDataSource

1 joko 1.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