Started the rearrangements for constraints, but I've decided not to go "all the way" with them. This is basically because the poor design of constraints is too endemic to fix in only a few days.
The problem is clearly evident in
ConstraintImpl. This class both extends the abstract class
AbstractConstraintExpression and implements the
AbstractConstraintExpression implements (partially) the
Constraint extends the
ConstraintImpl class is getting declarations of methods from one parent (
Constraint), and implementations of those methods from another parent (
ConstraintExpressions were once distinct, with
Constraint being the class that
ConstraintImpl now holds the position of. Fortunately AN has already changed that, but it's a shame that it didn't end up as a parent of
AbstractConstraintExpression, as this would solve a few problems by creating a single inheritance path. It's a little problematic to do this, as the methods declared by
ConstraintExpression are unrelated, and some classes implement
ConstraintExpression without implementing
For the moment I've create a new
ConstraintFactory class. This can be used by
ConstraintExpressionBuilder instead of directly creating a new
ConstraintImpl object. The point of this modification is to automatically create a different kind of constraint object when a magic predicate is used. By using different constraint object types, the constraint code can avoid the use of numerous "
Magic predicates are described in
AbstractDatabase. This class declares methods for getting the node numbers for each of the predicates, such as "KOWARI_IS". However, these do not describe the URI used for any of the predicates. Currently this is done in
XADatabaseImpl, and would be duplicated in any "implementing" database.
XADatabaseImpl actually creates nodes in the datastore for each magic predicate. The generated node numbers appear to have no use except to recognize when a magic predicate is being used. This generation is done during the
init() method, and it defines the string for the predicate inline. An example is:
KOWARI_IS = initSession.preallocate(new URIReferenceImpl(new URI(Tucana.NAMESPACE + "is")));This has the undesirable effect of tying the URI of the predicate directly to this particular implementation of the code. The only reason a query can be made which matches this predicate is because of user documentation. There is no connection at all between iTQL and these predicates. It's just asking for one of the predicates to start failing due to a typo when a change is made. To make things worse, these predicate URIs are duplicated in
As a first priority, I've started moving these URI definitions to a new class called
SpecialPredicates. From here they can be accessed by any class which wants to refer to the URI of the predicate, making them consistent across the system. This can also be used by the iTQL parser to recognize when one of these predicates is used, so that an appropriate kind of constraint object can be created.
Once these new constraint objects are created, there should be no need for node numbers to be created. The only reason I could see to keep them might be to prevent a magic predicate from being explicitly added to the database. I should ask AN about this and see what he thinks.
Well, I'm getting used to the new interface. It has its strong points, but also a lot of weaknesses.
As a Java editor, it seems to be somewhat lacking. For a start, the only awareness of code in the editor is a selection widget which lets you navigate to any method in the current class. While this is nice, there is no list of member variables, nor is there any code checking for declared members, methods, or any other context relevant information. More annoyingly, comments are not detected during paste operations, meaning that when I paste a header into a new file, it thinks it is seeing tags which need special indenting treatment.
Another feature I was looking for was a hierachical class viewer. Xcode has one, but interfaces are kept separate from classes. This made it useless for tracking the genealogy of classes like
ConstraintImpl, with its combination of interface and abstract class parents. I found it was faster and much easier to just look at the source code.
One useful feature I've found is CVS support, though it took me a little while to work out how to turn it on. It seems pretty good, but it appears to be a relatively simple wrapper around the "cvs" command.
I'm still discovering features, and I'm still struggling against my natural tendency to use vi commands, so I'll be giving it a bit longer yet. At this stage it looks like Xcode is really better for C and C++ development, and that I might want to consider something else for Java. KA has been using Eclipse, and I might give that a go shortly.
I wrote this a day late as Brisbane is having a public holiday for the Brisbane Exhibition, and I decided to have a restful night. I was happy to be home today, because I discovered Luc's first tooth has poked through. So all that lack of sleep has been worth it... I guess. Ask me again when he's two. :-)