It's taken much longer than I had hoped and I didn't have as much time as I probably needed to rtfm, but here's an answer anyhow...
Am Mittwoch, 19. Mai 2010 10:02:21 schrieb Sam Vilain: > Chris' approach of simply using one set of classes and optional > attributes might be more pragmatic, if it can work out that way. This is > where you just have one super-schema which can parse any version, and > perhaps can write out one version only. Being able to convert between different versions was one of my original intentions. But I might be willing to do without in order to get anything working at all ;-) I really don't feel at home in that meta-programming business yet. > First, I'd probably still keep code that represents the most current > standard hand-written. Then, I'd make a visitor helper, which walks over > the Moose metamodel, and constructs an identical set of classes, but for > the next older version. > > eg say you called one XML::MODS, then the next older version might be > XML::MODS::v3_3; instead of listing all of the properties explicitly, > you use metaprogramming to pull those all from the newer type, but with > changes as appropriate. > > For instance, say you wrote a role which supplied the "clone_mutant" > method. So this would be the "visitor helper" which would be added to all classes of the most current standard by adding something like "with 'XML::MODS::CloneVisitorRole'" to them? Or is that unnecessary, since the role would be applied dynamically and recursivly to the current base when the class for an older standard is loaded? > It is designed to be applied to any PRANG-mixed Moose metaclass, > and what it does is a recursive clone of all the PRANG attributes, but > along the way calls callbacks which are allowed to supply extra > parameters to the eventual ->clone() call, skip objects, etc. > > That might look like this, imagining that there was only one change > between 3.4 and 3.3 of the standard: > > package XML::MODS::v3_3; > use XML::MODS; > use PRANG::Handwave::MutatingCloner; > # apply the MutatingCloner role to the XML::MODS metaclass > PRANG::Handwave::Cloner->setup("XML::MODS"); That should be "PRANG::Handwave::MutatingCloner" in the line above - or is it a different class? Whatever, this "setup" method then would start in XML::MODS, use the method "add_role()" from Moose::Meta::Class to add the role 'PRANG::Handwave::MutatingCloner' to it and then - like PRANG does when serializing to XML - walk recursively over all PRANG attributes and do the same there? Adding the role is effectively the same as adding a method "clone_mutant" (plus it's implementation) to each class? > # do the clone > $newer_meta->clone_mutant( > mutate_class => sub { > my $metaclass = shift; > my $new_name = $metaclass->name; > $new_name =~ s{XML::MODS::}{XML::MODS::v3_3}; > return (name => $new_name); # extra clone args > }, > mutate_attr => sub { > my $metaattr = shift; > if ($meta->name eq "supplied") { > return "SKIP"; # magic return value > } > else { > return (); # pass through as-is > } > }, > ); "$newer_meta" is simply "XML::MODS->meta()"? And the anonymous sub for "mutate_attr" would need to include the code for every change made in the schema to xml elements and attributes (describing different type constraints, manipulating PRANGs "xml_min" or "xml_max" attributes and so on)? Your example is meant to describe the special situation where the (hypothetical) xml element or attribute "supplied" was not present in the previous schema? The injected "clone_mutant" then again walks recursively over every PRANG attribute and uses the callbacks to find out how to modify these, i.e. it should get back from "mutate_attr" a set of parameters for the cloning call? Questions like how to walk over the classes of union typed elements I hope to be able to answer on my own, as soon as I have grokked the general idea. What's missing for that is some knowledge about that "cloning". Does that refer to "Class::MOP::Class::clone_object"? But what is the "instance" to be cloned here? > As new standards are introduced, the transforms layer and layer. You can > also coerce objects between versions by writing rules in each class, > possibly for each direction. I'll postpone thinking about this to a time when I have a few spare brain cells. Right now they seem to be all busy.... > [...] > Anyway, I hope this helps and feel free to ask more questions. Maybe one day you'll regret that ;-) Best, Heiko