Note: the code/queries below have NOT been tested or compiled, it is there for illustration purposes only, please don't complain at me if it doesn't compile (or even work, I'm not here to do your work for you)!
Finding Files
A pretty simple example would be if you wanted to find some files in a directory(ies) that have a specific file extension or have been updated since a certain date, or are between certain size criteria, or just a mix of them all.Example query, return all .html files that have been updated since 01/Jan/2006, are readable, are between 10K and 20K in size. Order the results by the last modified date (more recently modified first) and then by size (greatest first).
SELECT * FROM java.io.File WHERE lower (name) LIKE '%.html' AND length BETWEEN (10 * 1024) + (20 * 1024) ORDER BY lastModified DESC, length DESC
File d = new File (dirName); Query q = new Query (); q.parse (queryText); QueryResults qr = q.execute (new ArrayList (d.listFiles ()));
Augmenting Google API Search Results
Let's try something a little more interesting ;) Now, Google has made their Web Search API available, so that you can perform Google searches from your Java code. Now whilst Google is very powerful, it does have some limitations. For example, let's say you want to find out want to find out all the pages that mention JoSQL on the SourceForge and freshmeat sites. Easy enough to do, just perform this query. So far so good, but we've got about 440 results that are ordered by Google's relevance criteria, pretty useless if you want to get details about each site!So the following query will tell you some aggregate information about the query AND will group the results for you by site making life much easier ;)
SELECT * result FROM GoogleSearchResultWrapper GROUP BY urlObj.host GROUP BY ORDER :_allobjs.size DESC EXECUTE ON GROUP_BY_RESULTS avg (cachedSizeAsInt) cachedAvgSize
com.google.soap.search.GoogleSearchResultElement
class and create a java.net.URL
object for the URL returned by the getURL
call and return an int via the getCachedSizeAsInt
class:GoogleSearch search = new GoogleSearch(); // Set mandatory attributes. search.setKey("000000000000000000000000"); // Set the query string. search.setQueryString("josql+site%3Asourceforge.net+OR+site%3Afreshmeat.net"); // Invoke the actual search GoogleSearchResult result = search.doSearch(); // Get the result. GoogleSearchResultElement[] els = result.getResultElements (); List l = new ArrayList (); // Convert to our wrapper object and prepare for JoSQL call. for (int i = 0; i < els.length i++) { l.add (new GoogleSearchResultWrapper (els[i])); } Query q = new Query (); q.parse (queryText); QueryResults qr = q.execute (l); // Now iterate over the results. List josqlRes = qr.getResults (); // Note: here we are iterating over the group by results, so each list // here will contain a single column that is the "host". for (int i = 0; i < josqlRes.size (); i++) { List h = josqlRes.get (i); String host = h.get (0); // Get the results associated with this host. List hostResults = (Map) qr.getGroupByResults ().get (h); // Get the save values associated with this host. Map saveValues = qr.getGroupBySaveValues (h); // Get the average cache size. double avgCacheSize = ((Number) saveValues.get ("avgCacheSize")).doubleValue (); // Now do something with the results! }
SELECT DISTINCT urlObj.host FROM GoogleSearchResultWrapper
Trimming Exception traces to items you are interested in
If you've ever used a framework or plugin manager then you'll have sometimes have got a scary looking exception trace when something goes wrong. Often times the stack trace generated contains about 20-30 elements that you aren't really interested in because they relate to the internals of the framework/plugin manager, sometimes the elements you are interested in are the top 2-3. Wouldn't it be nice to be able to remove all that fluff?Note: you don't actually have to implement this yourself, see org.josql.filters.StackTraceElementFilter for details of a filter that will handle the nasty bits for you!
Example query, return limit the elements to those within the org.josql package.
SELECT * FROM java.lang.StackTraceElement WHERE className LIKE 'org.josql.%'
public static Exception filterAndRethrow (Exception e) { // Assume that the query has been parsed already when the class was inited. try { QueryResult qr = stackTraceFilterQuery.execute (Arrays.asList (e.getStackTrace ())); // Note: this line probably won't work, for some reason I haven't been // able to cast to a "StackTracElement[]", if anyone can explain // why please let me know! e.setStackTrace ((StackTraceElement[]) qr.getResults ().toArray ()); } catch (Exception ex) { // Just throw the exception we have been unable to filter and // we are already (probably) in an error chain so it's not wise to // "lose" this exception by throwing a JoSQL problem which should // be handled by another mechanism. } throw e; }
A Rule-based Event dispatcher
The Java standard event listener event architecture is fine and dandy but it generally provides a very broad mechanism of "tell me about all events". This is ok, but it is then down to the listener to determine whether it's interested in the event after all. It would be useful to put this logic into the event dispatcher. Well using a JoSQL WHERE clause this is possible (note: for convenience here we use a org.josql.filters.DefaultObjectFilter instance to do the heavy lifting for us). For example:/** * Note: we assume here that the listener interface is called: ObjectListener * and events of type: ObjectEvent will be dispatched to the listener via a: * handleEvent method. * * The mechanism would be the same for ANY type of object used to capture * details about an "event". * * It is also possible (of course) to create a configurable dispatcher that allows * configuration of the specific event method to be fired, but that is beyond the * scope of this discussion! */ public class RuleEventDispatcher { private Map listeners = new LinkedHashMap (); /** * The method needs to be synchronized because JoSQL query objects are * NOT thread-safe. * * @param o The event object. * @throws JoSQLExecutionException If the where clause cannot be evaluated against * the event object. */ public synchronized void fireEvent (ObjectEvent o) throws JoSQLExecutionException { Iterator iter = this.listeners.keySet ().iterator (); while (iter.hasNext ()) { ObjectListener ol = (ObjectListener) iter.next (); DefaultObjectFilter dof = (DefaultObjectFilter) this.listeners.get (ol); // See if the listener is interested in this event. if (dof.accept (o)) { // Yes they are, send them the event. ol.handleEvent (o); } else { // See if an exception has occurred. if (dof.getException () != null) { // Wrap the exception to provide more details. JoSQLExecutionException ee = new JoSQLExecutionException ("Unable to execute WHERE clause for listener: " + ol.getClass ().getName () + " against event: " + o.getClass ().getName () + " using statement: " + dof.getQuery (), dof.getException ()); // Reset the exception. dof.clearException (); throw ee; } } } } public synchronized void addListener (ObjectListener o, String whereClause) throws JoSQLParseException { DefaultObjectFilter f = new DefaultObjectFilter (whereClause, ObjectEvent.class); this.listeners.put (o, f); } public synchronized void removeListener (ObjectListener o) { this.listeners.remove (o); } }
java.util.EventObject
instead and have an extra parm on the addListener
method which specifies the specific sub-class of EventObject
that will be used, or even just leave it at EventObject
if that would be enough!