| 12 | <UL> | <UL> | 
| 13 |  |  | 
| 14 | <LI><A HREF="#name">NAME</A></LI> | <LI><A HREF="#name">NAME</A></LI> | 
| 15 |  | <LI><A HREF="#aims">AIMS</A></LI> | 
| 16 | <LI><A HREF="#synopsis">SYNOPSIS</A></LI> | <LI><A HREF="#synopsis">SYNOPSIS</A></LI> | 
| 17 | <UL> | <UL> | 
| 18 |  |  | 
| 19 |  | <LI><A HREF="#basic access">BASIC ACCESS</A></LI> | 
| 20 |  | <LI><A HREF="#advanced access">ADVANCED ACCESS</A></LI> | 
| 21 |  | <LI><A HREF="#synchronization">SYNCHRONIZATION</A></LI> | 
| 22 | <LI><A HREF="#note">NOTE</A></LI> | <LI><A HREF="#note">NOTE</A></LI> | 
| 23 | </UL> | </UL> | 
| 24 |  |  | 
| 25 |  | <LI><A HREF="#requirements">REQUIREMENTS</A></LI> | 
| 26 | <LI><A HREF="#description">DESCRIPTION</A></LI> | <LI><A HREF="#description">DESCRIPTION</A></LI> | 
| 27 | <LI><A HREF="#authors / copyright">AUTHORS / COPYRIGHT</A></LI> | <LI><A HREF="#authors / copyright">AUTHORS / COPYRIGHT</A></LI> | 
| 28 | <LI><A HREF="#acknowledgements">ACKNOWLEDGEMENTS</A></LI> | <LI><A HREF="#acknowledgements">ACKNOWLEDGEMENTS</A></LI> | 
| 30 | <LI><A HREF="#todo">TODO</A></LI> | <LI><A HREF="#todo">TODO</A></LI> | 
| 31 | <UL> | <UL> | 
| 32 |  |  | 
| 33 | <LI><A HREF="#handle the following errors/cases:">Handle the following errors/cases:</A></LI> | <LI><A HREF="#bugs">BUGS</A></LI> | 
| 34 |  | <LI><A HREF="#features">FEATURES</A></LI> | 
| 35 | <UL> | <UL> | 
| 36 |  |  | 
| 37 | <LI><A HREF="#dbierror [tangram]: dbd::mysql::st execute failed: unknown column 't1.requestdump' in 'field list'">``DBI-Error [Tangram]: DBD::mysql::st execute failed: Unknown column 't1.requestdump' in 'field list'''</A></LI> | <LI><A HREF="#links / references">LINKS / REFERENCES</A></LI> | 
|  | <LI><A HREF="#compare schema (structure diff) with database ...">Compare schema (structure diff) with database ...</A></LI> |  | 
|  | </UL> |  | 
|  |  |  | 
|  | <LI><A HREF="#introduce some features:">Introduce some features:</A></LI> |  | 
|  | <UL> |  | 
|  |  |  | 
|  | <LI><A HREF="#links:">Links:</A></LI> |  | 
| 38 | </UL> | </UL> | 
| 39 |  |  | 
| 40 | </UL> | </UL> | 
| 48 | <P>Data::Storage - Interface for accessing various Storage implementations for Perl in an independent way</P> | <P>Data::Storage - Interface for accessing various Storage implementations for Perl in an independent way</P> | 
| 49 | <P> | <P> | 
| 50 | <HR> | <HR> | 
| 51 | <H1><A NAME="synopsis">SYNOPSIS</A></H1> | <H1><A NAME="aims">AIMS</A></H1> | 
| 52 | <PRE> | <PRE> | 
| 53 | ... the basic way:</PRE> | - should encapsulate Tangram, DBI, DBD::CSV and LWP:: to access them in an unordinary (more convenient) way ;) | 
| 54 |  | - introduce a generic layered structure, refactor *SUBLAYER*-stuff, make (e.g.) this possible: | 
| 55 |  | Perl Data::Storage[DBD::CSV]  ->  Perl LWP::  ->  Internet HTTP/FTP/*  ->  Host Daemon  ->  csv-file | 
| 56 |  | - provide generic synchronization mechanisms across arbitrary/multiple storages based on ident/checksum | 
| 57 |  | maybe it's possible to have schema-, structural- and semantical modifications synchronized???</PRE> | 
| 58 |  | <P> | 
| 59 |  | <HR> | 
| 60 |  | <H1><A NAME="synopsis">SYNOPSIS</A></H1> | 
| 61 |  | <P> | 
| 62 |  | <H2><A NAME="basic access">BASIC ACCESS</A></H2> | 
| 63 |  | <P> | 
| 64 |  | <H2><A NAME="advanced access">ADVANCED ACCESS</A></H2> | 
| 65 | <PRE> | <PRE> | 
| 66 | ... via inheritance: | ... via inheritance: | 
| 67 | </PRE> | </PRE> | 
| 81 | ); | ); | 
| 82 | $self->{storage}->insert($proxyObj);</PRE> | $self->{storage}->insert($proxyObj);</PRE> | 
| 83 | <P> | <P> | 
| 84 |  | <H2><A NAME="synchronization">SYNCHRONIZATION</A></H2> | 
| 85 |  | <PRE> | 
| 86 |  | my $nodemapping = { | 
| 87 |  | 'LangText' => 'langtexts.csv', | 
| 88 |  | 'Currency' => 'currencies.csv', | 
| 89 |  | 'Country'  => 'countries.csv', | 
| 90 |  | };</PRE> | 
| 91 |  | <PRE> | 
| 92 |  | my $propmapping = { | 
| 93 |  | 'LangText' => [ | 
| 94 |  | [ 'source:lcountrykey'  =>  'target:country' ], | 
| 95 |  | [ 'source:lkey'         =>  'target:key' ], | 
| 96 |  | [ 'source:lvalue'       =>  'target:text' ], | 
| 97 |  | ], | 
| 98 |  | 'Currency' => [ | 
| 99 |  | [ 'source:ckey'         =>  'target:key' ], | 
| 100 |  | [ 'source:cname'        =>  'target:text' ], | 
| 101 |  | ], | 
| 102 |  | 'Country' => [ | 
| 103 |  | [ 'source:ckey'         =>  'target:key' ], | 
| 104 |  | [ 'source:cname'        =>  'target:text' ], | 
| 105 |  | ], | 
| 106 |  | };</PRE> | 
| 107 |  | <PRE> | 
| 108 |  | sub syncResource {</PRE> | 
| 109 |  | <PRE> | 
| 110 |  | my $self = shift; | 
| 111 |  | my $node_source = shift; | 
| 112 |  | my $mode = shift; | 
| 113 |  | my $opts = shift; | 
| 114 |  | </PRE> | 
| 115 |  | <PRE> | 
| 116 |  |  | 
| 117 |  | $mode ||= ''; | 
| 118 |  | $opts->{erase} ||= 0;</PRE> | 
| 119 |  | <PRE> | 
| 120 |  |  | 
| 121 |  | $logger->info( __PACKAGE__ . "->syncResource( node_source $node_source mode $mode erase $opts->{erase} )");</PRE> | 
| 122 |  | <PRE> | 
| 123 |  |  | 
| 124 |  | # resolve metadata for syncing requested resource | 
| 125 |  | my $node_target = $nodemapping->{$node_source}; | 
| 126 |  | my $mapping = $propmapping->{$node_source};</PRE> | 
| 127 |  | <PRE> | 
| 128 |  |  | 
| 129 |  | if (!$node_target || !$mapping) { | 
| 130 |  | # loggger.... "no target, sorry!" | 
| 131 |  | print "error while resolving resource metadata", "\n"; | 
| 132 |  | return; | 
| 133 |  | }</PRE> | 
| 134 |  | <PRE> | 
| 135 |  |  | 
| 136 |  | if ($opts->{erase}) { | 
| 137 |  | $self->_erase_all($node_source); | 
| 138 |  | }</PRE> | 
| 139 |  | <PRE> | 
| 140 |  |  | 
| 141 |  | # create new sync object | 
| 142 |  | my $sync = Data::Transfer::Sync->new( | 
| 143 |  | storages => { | 
| 144 |  | L => $self->{bizWorks}->{backend}, | 
| 145 |  | R => $self->{bizWorks}->{resources}, | 
| 146 |  | }, | 
| 147 |  | id_authorities        =>  [qw( L ) ], | 
| 148 |  | checksum_authorities  =>  [qw( L ) ], | 
| 149 |  | write_protected       =>  [qw( R ) ], | 
| 150 |  | verbose               =>  1, | 
| 151 |  | );</PRE> | 
| 152 |  | <PRE> | 
| 153 |  |  | 
| 154 |  | # sync | 
| 155 |  | # todo: filter!? | 
| 156 |  | $sync->syncNodes( { | 
| 157 |  | direction       =>  $mode,                 # | +PUSH | +PULL | -FULL | +IMPORT | -EXPORT | 
| 158 |  | method          =>  'checksum',            # | -timestamp | -manual | 
| 159 |  | source          =>  "L:$node_source", | 
| 160 |  | source_ident    =>  'storage_method:id', | 
| 161 |  | source_exclude  =>  [qw( id cs )], | 
| 162 |  | target          =>  "R:$node_target", | 
| 163 |  | target_ident    =>  'property:oid', | 
| 164 |  | mapping         =>  $mapping, | 
| 165 |  | } );</PRE> | 
| 166 |  | <PRE> | 
| 167 |  | }</PRE> | 
| 168 |  | <P> | 
| 169 | <H2><A NAME="note">NOTE</A></H2> | <H2><A NAME="note">NOTE</A></H2> | 
| 170 | <P>This module heavily relies on DBI and Tangram, but adds a lot of additional bugs and quirks. | <P>This module heavily relies on DBI and Tangram, but adds a lot of additional bugs and quirks. | 
| 171 | Please look at their documentation and this code for additional information.</P> | Please look at their documentation and/or this code for additional information.</P> | 
| 172 |  | <P> | 
| 173 |  | <HR> | 
| 174 |  | <H1><A NAME="requirements">REQUIREMENTS</A></H1> | 
| 175 |  | <PRE> | 
| 176 |  | For full functionality: | 
| 177 |  | DBI              from CPAN | 
| 178 |  | DBD::mysql       from CPAN | 
| 179 |  | Tangram 2.04     from CPAN         (hmmm, 2.04 won't do in some cases) | 
| 180 |  | Tangram 2.05     from <A HREF="http://">http://</A>...   (2.05 seems okay but there are also additional patches from our side) | 
| 181 |  | Class::Tangram   from CPAN | 
| 182 |  | DBD::CSV         from CPAN | 
| 183 |  | MySQL::Diff      from <A HREF="http://adamspiers.org/computing/mysqldiff/">http://adamspiers.org/computing/mysqldiff/</A> | 
| 184 |  | ... and all their dependencies</PRE> | 
| 185 | <P> | <P> | 
| 186 | <HR> | <HR> | 
| 187 | <H1><A NAME="description">DESCRIPTION</A></H1> | <H1><A NAME="description">DESCRIPTION</A></H1> | 
| 188 | <P>Data::Storage is module for a accessing various ``data structures'' stored inside | <P>Data::Storage is a module for accessing various ``data structures'' stored inside | 
| 189 | various ``data containers''. It sits on top of DBI and/or Tangram.</P> | various ``data containers''. It sits on top of DBI and/or Tangram.</P> | 
| 190 | <P> | <P> | 
| 191 | <HR> | <HR> | 
| 197 | <P> | <P> | 
| 198 | <HR> | <HR> | 
| 199 | <H1><A NAME="acknowledgements">ACKNOWLEDGEMENTS</A></H1> | <H1><A NAME="acknowledgements">ACKNOWLEDGEMENTS</A></H1> | 
| 200 | <P>Larry Wall and the <CODE>perl5-porters</CODE> for Perl, | <P>Larry Wall for Perl, Tim Bunce for DBI, Jean-Louis Leroy for Tangram and Set::Object, | 
| 201 | Tim Bunce for DBI, Jean-Louis Leroy for Tangram and Set::Object, | Sam Vilain for Class::Tangram, Jochen Wiedmann and Jeff Zucker for DBD::CSV and related, | 
| 202 | Sam Vilain for Class::Tangram.</P> | Adam Spiers for MySQL::Diff and all contributors.</P> | 
| 203 | <P> | <P> | 
| 204 | <HR> | <HR> | 
| 205 | <H1><A NAME="support / warranty">SUPPORT / WARRANTY</A></H1> | <H1><A NAME="support / warranty">SUPPORT / WARRANTY</A></H1> | 
| 208 | <HR> | <HR> | 
| 209 | <H1><A NAME="todo">TODO</A></H1> | <H1><A NAME="todo">TODO</A></H1> | 
| 210 | <P> | <P> | 
| 211 | <H2><A NAME="handle the following errors/cases:">Handle the following errors/cases:</A></H2> | <H2><A NAME="bugs">BUGS</A></H2> | 
| 212 | <P> | <P>``DBI-Error [Tangram]: DBD::mysql::st execute failed: Unknown column 't1.requestdump' in 'field list'''</P> | 
|  | <H3><A NAME="dbierror [tangram]: dbd::mysql::st execute failed: unknown column 't1.requestdump' in 'field list'">``DBI-Error [Tangram]: DBD::mysql::st execute failed: Unknown column 't1.requestdump' in 'field list'''</A></H3> |  | 
| 213 | <PRE> | <PRE> | 
| 214 | ... occours when operating on object-attributes not introduced yet: | ... occours when operating on object-attributes not introduced yet: | 
| 215 | this should be detected and appended/replaced through: | this should be detected and appended/replaced through: | 
| 216 | "Schema-Error detected, maybe (just) an inconsistency. | "Schema-Error detected, maybe (just) an inconsistency. | 
| 217 | Please check if your declaration in schema-module "a" matches structure in database "b" or try to run" | Please check if your declaration in schema-module "a" matches structure in database "b" or try to run" | 
| 218 | db_setup.pl --dbkey=import --action=deploy</PRE> | db_setup.pl --dbkey=import --action=deploy</PRE> | 
| 219 | <P> | <P>Compare schema (structure diff) with database ...</P> | 
|  | <H3><A NAME="compare schema (structure diff) with database ...">Compare schema (structure diff) with database ...</A></H3> |  | 
| 220 | <PRE> | <PRE> | 
| 221 | ... when issuing "db_setup.pl --dbkey=import --action=deploy" | ... when issuing "db_setup.pl --dbkey=import --action=deploy" | 
| 222 | on a database with an already deployed schema, use an additional "--update" then | on a database with an already deployed schema, use an additional "--update" then | 
| 247 | As we can see, creations of Classes and new Class variables is handled | As we can see, creations of Classes and new Class variables is handled | 
| 248 | automatically and this is believed to be the most common case under normal circumstances.</PRE> | automatically and this is believed to be the most common case under normal circumstances.</PRE> | 
| 249 | <P> | <P> | 
| 250 | <H2><A NAME="introduce some features:">Introduce some features:</A></H2> | <H2><A NAME="features">FEATURES</A></H2> | 
| 251 | <PRE> | <PRE> | 
| 252 | - Get this stuff together with UML (Unified Modeling Language) and/or standards from ODMG. | - Get this stuff together with UML (Unified Modeling Language) and/or standards from ODMG. | 
| 253 | - Make it possible to load/save schemas in XMI (XML Metadata Interchange), | - Make it possible to load/save schemas in XMI (XML Metadata Interchange), | 
| 255 | Integrate/bundle this with a web-/html-based UML modeling tool or | Integrate/bundle this with a web-/html-based UML modeling tool or | 
| 256 | some other interesting stuff like the "Co-operative UML Editor" from Uni Darmstadt. (web-/java-based) | some other interesting stuff like the "Co-operative UML Editor" from Uni Darmstadt. (web-/java-based) | 
| 257 | - Enable Round Trip Engineering. Keep code and diagrams in sync. Don't annoy/bother the programmers. | - Enable Round Trip Engineering. Keep code and diagrams in sync. Don't annoy/bother the programmers. | 
| 258 | - Add some more handlers: | - Add support for some more handlers/locators to be able to | 
| 259 | - look at DBD::CSV, Text::CSV, XML::CSV, XML::Excel | access the following standards/protocols/interfaces/programs/apis transparently: | 
| 260 | - Add some more locations/locators: | +  DBD::CSV (via Data::Storage::Handler::DBI) | 
| 261 | - PerlDAV: <A HREF="http://www.webdav.org/perldav/">http://www.webdav.org/perldav/</A> | (-) Text::CSV, XML::CSV, XML::Excel | 
| 262 | - Move to t3, use InCASE</PRE> | -  MAPI | 
| 263 |  | -  LDAP | 
| 264 |  | -  DAV (look at PerlDAV: <A HREF="http://www.webdav.org/perldav/">http://www.webdav.org/perldav/</A>) | 
| 265 |  | -  Mbox (use formail for seperating/splitting entries/nodes) | 
| 266 |  | -  Cyrus (cyrdeliver - what about cyrretrieve (export)???) | 
| 267 |  | -  use File::DiffTree, use File::Compare | 
| 268 |  | -  Hibernate | 
| 269 |  | -  "Win32::UserAccountDb" | 
| 270 |  | -  "*nix::UserAccountDb" | 
| 271 |  | -  .wab - files (Windows Address Book) | 
| 272 |  | -  .pst - files (Outlook Post Storage?) | 
| 273 |  | -  XML (e.g. via XML::Simple?) | 
| 274 |  | - Move to t3, look at InCASE</PRE> | 
| 275 | <P> | <P> | 
| 276 | <H3><A NAME="links:">Links:</A></H3> | <H3><A NAME="links / references">LINKS / REFERENCES</A></H3> | 
| 277 | <PRE> | <PRE> | 
| 278 | Specs: | Specs: | 
| 279 | UML 1.3 Spec: <A HREF="http://cgi.omg.org/cgi-bin/doc?ad/99-06-08.pdf">http://cgi.omg.org/cgi-bin/doc?ad/99-06-08.pdf</A> | UML 1.3 Spec: <A HREF="http://cgi.omg.org/cgi-bin/doc?ad/99-06-08.pdf">http://cgi.omg.org/cgi-bin/doc?ad/99-06-08.pdf</A> | 
| 300 | PyUt (free): <A HREF="http://pyut.sourceforge.net/">http://pyut.sourceforge.net/</A> | PyUt (free): <A HREF="http://pyut.sourceforge.net/">http://pyut.sourceforge.net/</A> | 
| 301 | (Dia (free): <A HREF="http://www.lysator.liu.se/~alla/dia/">http://www.lysator.liu.se/~alla/dia/</A>) | (Dia (free): <A HREF="http://www.lysator.liu.se/~alla/dia/">http://www.lysator.liu.se/~alla/dia/</A>) | 
| 302 | UMLet (free, university): <A HREF="http://www.swt.tuwien.ac.at/umlet/index.html">http://www.swt.tuwien.ac.at/umlet/index.html</A> | UMLet (free, university): <A HREF="http://www.swt.tuwien.ac.at/umlet/index.html">http://www.swt.tuwien.ac.at/umlet/index.html</A> | 
| 303 | Voodoo (free): <A HREF="http://voodoo.sourceforge.net/">http://voodoo.sourceforge.net/</A></PRE> | Voodoo (free): <A HREF="http://voodoo.sourceforge.net/">http://voodoo.sourceforge.net/</A> | 
| 304 |  | Umbrello UML Modeller: <A HREF="http://uml.sourceforge.net/">http://uml.sourceforge.net/</A></PRE> | 
| 305 | <PRE> | <PRE> | 
| 306 | UML Tools: | UML Tools: | 
| 307 | <A HREF="http://www.objectsbydesign.com/tools/umltools_byPrice.html">http://www.objectsbydesign.com/tools/umltools_byPrice.html</A></PRE> | <A HREF="http://www.objectsbydesign.com/tools/umltools_byPrice.html">http://www.objectsbydesign.com/tools/umltools_byPrice.html</A></PRE> |