Hello Brendan,
The DDMSVersion _currentVersion singleton should be the only part of the library where state is handled in a thread-unsafe manner. Class immutability trumped thread safety in my original design: I wanted the versioning mechanism to be as unobtrusive as possible to library users, while maintaining the immutability of each component class. Maintaining the current version in a non-static way would have added additional required parameters to all component constructors and builders, and at the time, I felt that many of the constructors were already too verbose. So, this approach is more about simplicity and usability than performance or other technical reasons.
Here are the technical details of the specific workflows where this might get complicated in a multithreaded environment:
1) Reading DDMS metacards from an input stream via DDMSReader
Current Impact: Because each DDMSReader is instantiated with a specific DDMSVersion, and because you can have multiple readers active at the same time, reading metacards should always be thread-safe. You should not need to worry unless you take a successfully-read metacard and drop it into a Component Builder for transformation / manipulation (see #4 below).
2) Building components with XML-based constructors ("bottoms-up")
Current Impact: Because these constructors use the XML namespace of the XML elements to determine the correct version, these constructors should be thread-safe.
3) Building components with data-based constructors ("bottoms-up")
Current Impact: Each constructor that builds a DDMS component from basic Java data types relies upon the _currentVersion singleton at the moment of instantiation. When child components are added into parent components later, they must share the same version, according to the XML namespace that was assigned at instantiation. However, changing the _currentVersion after a component has been instantiated will not harm or change that component.
Thread Safe Approach: Each DDMS component would need to accept a current version variable in its data-based constructors rather than checking the singleton.
4) Using Component Builders ("top-down")
Current Impact: Each builder class relies upon the _currentVersion singleton at the moment that commit() is called to create an immutable component from the mutable builder. Generally, commit would be called one time at the Resource level, and convert the entire tree of child components at the same time. Changing the _currentVersion after a builder has been committed will not harm or change that component.
Thread Safe Approach: Each builder class would need to accept a current version variable as a set() accessor on the builder rather than checking the singleton.
Off the top of my head, a potential workaround that might satisfy your requirements with the existing library code would be this:
1) Employ Component Builders to do the transformations.
2) Minimize dependent code to call commit() just once per metacard, at the Resource.Builder level.
3) Set up a thread monitor / lock around the two lines of code that (a) set the DDMS Version and (b) commit the metacard.
If the above workaround is insufficient, please provide me with additional detail about your workflow and I'll see what I can come up with. If there are details that cannot be publicly shared, you can reach me privately at ddmsence AT
urizone.net. I admit that I'm not a multithreaded expert, but would be willing to work with you to satisfy your specific case. I would also be willing to make changes to the library itself too, provided that I can balance a multithreaded solution with the intuitiveness of the existing single-threaded solution in a single new library version. (I would prefer to have a single latest release that handles all cases, rather than maintain separate multithreaded vs. single-threaded release lines).
Happy Thanksgiving,
BU