From: Rib R. <ri...@gm...> - 2006-03-07 20:21:11
|
Okay. Let me explain a little about how the XML parser I built works. The basic idea is that has a list of element names which can have child elements. When it encounters the start tag for one of these elements, it starts building an object. So if there was an xml file like this: <patchbasket> <patch> <author>foo</author> </patch> </patchbasket> The parser would: 1) Create a patchbasket object 2) create a patch object 3) Use introspection to find (and call) a setter (in the patch) setAuthor(String) or addAuthor(String) 4) Use introspection to find (and call) a setter in the basket class setPatch or addPatch which will accept the created patch 5) Return the patchbasket object So to set up the parser we need to tell it: 1) Which element should cause it to start building an object 2) How to create those objects With that foundation, my recommendation (which I explained terribly in my last email) is to allow two generating elements: patchbasket and patch. Any other element would be treated as a string property by the parser. Then each IPatch implementation has to have some sort of a write method, plus matching setters. We should probably have some sort of helper for binary data. The implementation would look somthing like this: void write(XMLWriter xml) { xml.writeProperty("author", self.author); xml.writeBinaryProperty("data", self.sysex); } void setAuthor(String author) { /* ... */ } void setData(String data) { self.sysex =3D XMLTools.decodeBinary(data); } On 3/7/06, Joe Emenaker <jo...@em...> wrote: > Rib Rdb wrote: > > I just glanced at the code. It looks like you're casting everything > > in the PatchBasket to Patch. > That was before I realized that SceneLibrary was also saving through the > same code. So, at the very least, I have to check if it's an instance of > a Patch or a Scene. > > That won't work with the XML driver (or > > any other custom Patch classes). It looks like a simple solution for > > doing the output would be to make IPatch extend > > org.jsynthlib.utils.Writable, and use org.jsynthlib.utils.XMLWriter > > instead of the JDOM XMLOutputter. Then each patch implementation only > > needs to add a write method. > > > > Reading the XML files back in is more complicated, because the parser > > needs to know what it should do with the elements it gets > This was my first misgiving about having each patch implementation > define a write method. Your options for reading are: > 1 - Have the code for reading the XML be in different classes from the > code for writing them (very, very bad form, in my opinion), or > 2 - Have each patch implementation define a read method as well. > > The problem I have with #2 is that it seems like we'd end up using it > much like we find the driver for a sysex. We just give it to each driver > and ask it if it recognizes it. I'd like to avoid that for patch > implementations. > > (either call > > a setter method with the string contents, or build an object, then > > call a setter). This probably means we need to decide on some > > restrictions on how patches can store themselves. > Well, here's another thought I had. Right now, Patch has some fields > named Author and Date, I think. However, they're no longer used to hold > author and date. They're called "Field 1" and "Field 2" in the > LibraryFrame. We *could* just allow any number of name/value pairs (ie > "String getValue(String name)" and "void setValue(String name, String > value)"), and then the XML code would have no trouble at all retrieving > them and setting them. How the individual classes chose to use them > would be up to them. If we wanted some tighter controls, we could allow > Patch subclasses to define an array of allowed value names (ie > "allowedNames =3D new String[] {'Author', 'Date', 'Comment', 'FromPatch', > 'FromBank' ") and we could trigger an ErrMsg if the XML file contained a > non-allowed value name. > > To downside to all of this is that it would be a burden for the Patch > subclasses to access their own data, since they'd probably always have > to use their own getValue and setValue methods. Also, dealing with any > data other than String would be a bother. > > An alternative would be to have the XML code use inspection to find all > matched getter/setters, discover the data type, and magically > save/restore them. The downsides to this would be: > 1 - The XML code becomes significantly more complex and error-prone > 2 - We would have to decide on how to have the XML code cope if it > encounters a getter/setter that it doesn't know how to save (like if a > getter returns a Vector, or Hashtable, say). > 3 - Anybody who subclasses Patch would have to remember to make public > getter *and* setter methods for any new data elements that they want > saved. If they *forget* to do so, this could lead to a "why isn't my > field getting saved?" problem that is tough to track down. > > - Joe > > > |