I ran into a few separate issues. Since they concentrate on the same piece of code, I address them simultaneously. In my program I have the following method:
private void processEventTriggers() { try { ByteArrayOutputStream stream = new ByteArrayOutputStream(); String inQuery = "collection()/event/@in/string()"; XQuery inputQuery = new XQuery(inQuery); inputQuery.execute(_context,stream); String input = stream.toString();
String processQuery = "collection()/trigger_set/trigger[@name='"+_currentTrigger+"']/matches"; System.out.println("Process Event: "+processQuery); QueryProcessor processor = new QueryProcessor(processQuery, _context); Iter iterator = processor.iter(); Item item; while ((item=iterator.next())!=null) { BXNode node = (BXNode)item.toJava();
String pattern = node.getAttributes().getNamedItem("pattern").getNodeValue(); // Pattern regexp = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); // Matcher regexpMatcher = regexp.matcher(input); // System.out.print("'"+input+"' matches '"+pattern+"'"); // if (regexpMatcher.matches()) // System.out.println(" = true"); // else // System.out.println(" = false"); String matchQueryString = "matches('"+input+"','"+pattern+"','i')"; System.out.print("Match Query: "+matchQueryString); XQuery matchQuery = new XQuery(matchQueryString); stream.reset(); matchQuery.execute(_context,stream); if (stream.toString().equals("true")) { System.out.println(" = true"); if (executeCommands(node)) break; } else System.out.println(" = false"); } } catch (BaseXException exception) { exception.printStackTrace(); } catch (QueryException exception) { exception.printStackTrace(); } }
What this does is it queries the database for an input item and then matches this input to a set of 'matches' nodes. When a node matches it starts executing a series of commands, which are mostly XQuery commands themselves.
The first issue I have is that it seemed a bit inefficient to use an XQuery to match a regular expression. The section commented out matches the same regular expression. Unfortunately, I bumped into a few cases where the Java implementation mistakenly returns 'false' whereas the BaseX implementation returns 'true'. I can't complain really about BaseX here. Actually, kudos for providing a proper implementation, because I had assumed it would simply delegate this functionality to the Java regexp API. But I was a bit surprised to find that the Java regular expressions implementation seems to be broken. My question now is, can I call the BaseX 'matches()' function directly? Because I think that would be much more efficient.
A more serious issue I have is that the XQueries that are executed in the 'executeCommand()' call occasionally insert and delete nodes into collection()/memory sub-elements. And it also can recursively call processEventTriggers() again. Most of the time this works fine, but occasionally I get the following error:
Exception in thread "main" java.lang.RuntimeException: Possible bug? Feedback is welcome: basex-talk@mailman.uni-konstanz.de BaseX 6.3.2: Data Access out of bounds [pre:403, indexSize:4, access:4 > 3]
at org.basex.util.Util.notexpected(Util.java:46) at org.basex.io.TableDiskAccess.cursor(TableDiskAccess.java:323) at org.basex.io.TableDiskAccess.read1(TableDiskAccess.java:92) at org.basex.data.Data.kind(Data.java:324) at org.basex.query.item.DBNode$4.next(DBNode.java:272) at org.basex.query.path.IterStep$1.next(IterStep.java:45) at org.basex.query.iter.NodeIter.next(NodeIter.java:1) at org.basex.query.path.IterPath$1.next(IterPath.java:66) at org.basex.query.path.IterPath$1.next(IterPath.java:1) at BotCommandProcessor.processEventTriggers(BotCommandProcessor.java:285) at BotCommandProcessor.processEvent(BotCommandProcessor.java:262) at BotCommandProcessor.executeCommands(BotCommandProcessor.java:364) at BotCommandProcessor.processEventTriggers(BotCommandProcessor.java:305) at BotCommandProcessor.processEvent(BotCommandProcessor.java:262) at BotCommandProcessor.main(BotCommandProcessor.java:442)
Now I'm not entirely sure, but I suspect that the iterator is affected either by the insert/delete operations or by the nesting of the iterator process. Or a combination of the two. I could somehow understand this if the queries that are being executed would affect the set of triggers it's looping over, but that is not the case.
I did find an ugly way around this problem but I'm afraid it could get me into trouble later. So any feed-back about what might be the best way to fix this would be appreciated.
Mark Boon