When you need to, you can combine simple search elements in a variety of ways with BBQ. We'll examine how one particular search is constructed from simpler elements in some detail. Although it might seem daunting at first, the hope is that with familiarity constructing similar queries will become almost effortless, second-nature. Eventually you may come to see more and more development tasks in terms of BBQ queries.
If you have a class that implements java.io.Serializable
,
it's a good idea to to have the class include a version identifier in the form
of a static long field named serialVersionUID
. This
query will identify such classes.
First, let's find the classes that implement java.io.Serializable
.
Start with the class
set expression,
and apply the recursive derived classes of
transform.
recursive derived classes of class "java.io.Serializable"
Now, we'll refine the query to include only those classes that do not
have the version marker.
"Does not have" in BBQ generally translates to the exists
filter modified by the not
operator; exists
takes a transform argument
that should produce whatever we are testing the existence of.
In this case we are testing for a field with a certain name; we'll specify the name
with the matching
filter.
So the transform that finds the appropriate field in the class is:
matching "serialVersionUID" fields in ...
We use that transform with the exists
filter
to get the more specific set expression:
not exists ( matching "serialVersionUID" fields in ) recursive derived classes of class "java.io.Serializable"
Straightforward enough, I hope, and in fact the Eclipse IDE duplicates this functionality and by default will flag such classes in your project.
The problem with the output of the query as written is that it might return a number of classes
that are serializable only incidentally; for these classes you don't care if there is a serialVersionUID
field. For example (making some quick use to the count
expression) the Eclipse 3.1 code base has 368 Serializable
classes; only 169 of these
have a serialVersionUID field. Presumably, for the remaining 199 classes, it's not that important.
One of the advantages of BBQ is that it lets you focus quickly on what you do
think is important. Suppose you were not interested in all classes that implement Serializable
,
but only those that are derived from Persistent
.
You can readily modify the query and get exactly the list of classes that you want:
not exists ( matching "serialVersionUID" fields in ) recursive derived classes of class "Persistent"
Alternatively, you might be interested in any Serializable
class within a certain package tree.
You can do that by applying the transform that looks for the missing field
not exists ( matching "serialVersionUID" fields in ) ...
to the intersection of the two sets of classes: classes derived from java.io.Serializable
and classes within a package tree.
recursive derived classes of class "java.io.Serializable" intersection classes in recursive ( packages in ) package "com.antlersoft"
When we construct the full expression we have to use parentheses to group the set expression because the intersection operator has low precedence:
not exists ( matching "serialVersionUID" fields in ) ( ( recursive derived classes of class "java.io.Serializable" ) intersection classes in recursive ( packages in ) package "com.antlersoft" )
When we deal with longer examples, it can help to use line breaks and indenting to see the structure of the query. A good rule is to break and indent at parentheses, and break lines before and after and back indent set operators.
not exists ( matching "serialVersionUID" fields in ) ( ( recursive derived classes of class "java.io.Serializable" ) intersection classes in recursive ( packages in ) package "com.antlersoft" )
browse-by-query home | antlersoft free software | sourceforge project page |