From: <jma...@rh...> - 2008-12-25 09:27:44
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg DL { border : 1px #006 solid; background-color : #369; padding : 6px; color : #fff; } #msg DT { float : left; width : 6em; font-weight : bold; } #msg DL, #msg DT, #msg UL, #msg LI { font-family : arial,helvetica,sans-serif; font-size : 10pt; } h3 { font-family : arial,helvetica,sans-serif; font-size : 10pt; font-weight : bold; } #msg PRE { overflow : auto; white-space : normal; background-color : #ffc; border : 1px #fc0 solid; padding : 6px; } #msg UL, PRE, .diff { overflow : auto; } #patch h4 { font-family : arial,helvetica,sans-serif; font-size : 10pt; } #patch h4 { padding: 8px; background : #369; color : #fff; margin : 0; } #patch .propset h4, #patch .binary h4 {margin: 0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {background:#eeeeee;padding: 0 0 10px 0;} #patch .propset .diff, #patch .binary .diff {padding: 10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch .add {background:#ddffdd;} #patch .rem {background:#ffdddd;} #patch .lines, .info {color:#888888;background:#ffffff;} .diff { width : 100%; } #msg DL { border : 1px #006 solid; background-color : #369; padding : 6px; color : #fff; } #msg DT { float : left; width : 6em; font-weight : bold; } #msg DL, #msg DT, #msg UL, #msg LI { font-family : arial,helvetica,sans-serif; font-size : 10pt; } h3 { font-family : arial,helvetica,sans-serif; font-size : 10pt; font-weight : bold; } #msg PRE { overflow : auto; white-space : normal; background-color : #ffc; border : 1px #fc0 solid; padding : 6px; } #msg UL, PRE, .diff { overflow : auto; } #patch h4 { font-family : arial,helvetica,sans-serif; font-size : 10pt; } #patch h4 { padding: 8px; background : #369; color : #fff; margin : 0; } #patch .propset h4, #patch .binary h4 {margin: 0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {background:#eeeeee;padding: 0 0 10px 0;} #patch .propset .diff, #patch .binary .diff {padding: 10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch .add {background:#ddffdd;} #patch .rem {background:#ffdddd;} #patch .lines, .info {color:#888888;background:#ffffff;} .diff { width : 100%; } --></style> <title>[rhq-project.org rhq] [2542] RHQ-493 - support pivoting on unset/null plugin/resource configuration properties; </title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>2542</dd> <dt>Author</dt> <dd>jmarques</dd> <dt>Date</dt> <dd>2008-12-25 03:27:41 -0600 (Thu, 25 Dec 2008)</dd> </dl> <h3>Log Message</h3> <pre>RHQ-493 - support pivoting on unset/null plugin/resource configuration properties; in fact, this commit supports the general nullabllity of any condition that dynagroups supports; </pre> <h3>Modified Paths</h3> <ul> <li><a href="#rhqtrunkmodulesenterpriseserverjarsrcmainjavaorgrhqenterpriseserverresourcegroupdefinitionframeworkExpressionEvaluatorjava">rhq/trunk/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="rhqtrunkmodulesenterpriseserverjarsrcmainjavaorgrhqenterpriseserverresourcegroupdefinitionframeworkExpressionEvaluatorjava"></a> <div class="modfile"><h4>Modified: rhq/trunk/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java (2541 => 2542)</h4> <pre class="diff"> <span class="info">--- rhq/trunk/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java 2008-12-25 08:56:22 UTC (rev 2541) +++ rhq/trunk/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java 2008-12-25 09:27:41 UTC (rev 2542) </span><span class="lines">@@ -28,6 +28,8 @@ </span><span class="cx"> import java.util.List; import java.util.Map; import java.util.Set; </span><span class="add">+import java.util.regex.Matcher; +import java.util.regex.Pattern; </span><span class="cx"> import javax.persistence.Query; </span><span class="lines">@@ -759,6 +761,19 @@ </span><span class="cx"> * they were added to the predicate list groupByElements */ private class MultipleQueryIterator implements Iterator<ExpressionEvaluator.Result> { </span><span class="add">+ /* + * support multi-layer capture groups for flexibility, today they resolve to: + * group(0) = "token operator :argX" // where operator is '=' or 'LIKE' + * group(1) = "operator :argX" + * group(2) = "operator" + * group(3) = ":argX" + */ + private final static String nullHandlerPattern = "" + // the 'token' will go in front + "\\s+" + // followed by some whitespace + "((\\=|LIKE)" + // and either an '=' or the word 'like' + "\\s+" + // followed by more whitespace + "(:arg[0-9]*))"; // ending in ':argX' where X is some integer + </span><span class="cx"> @SuppressWarnings("unchecked") List uniqueTuples; int index; </span><span class="lines">@@ -778,24 +793,15 @@ </span><span class="cx"> int i = 0; Object nextResult = uniqueTuples.get(index++); </span><span class="add">+ Object[] groupByExpression; </span><span class="cx"> if (nextResult == null) { </span><span class="rem">- return null; - } - - Object[] groupByExpression; - if (nextResult.getClass().isArray()) { </span><span class="add">+ groupByExpression = new Object[] { null }; + } else if (nextResult.getClass().isArray()) { </span><span class="cx"> groupByExpression = (Object[]) nextResult; } else { groupByExpression = new Object[] { nextResult }; } </span><span class="rem">- // RHQ-1115 - filter out results with NULL elements - for (Object next : groupByExpression) { - if (next == null) { - return null; - } - } - </span><span class="cx"> /* * we built the basic structure earlier, now all we have to do is iterate over the unique N-tuples and set * the bind variables; conveniently, map semantics will, for each named group element, eject the current </span><span class="lines">@@ -803,10 +809,39 @@ </span><span class="cx"> */ for (String groupedElement : groupByElements) { String bindArgumentName = whereConditions.get(groupedElement); </span><span class="rem">- whereReplacements.put(bindArgumentName, groupByExpression[i++]); - whereReplacementTypes.put(bindArgumentName, String.class); </span><span class="add">+ Object groupByExpressionElement = groupByExpression[i++]; + if (groupByExpressionElement == null) { + whereReplacements.remove(bindArgumentName); + String patternWtihArgument = "\\Q" + groupedElement + "\\E" + nullHandlerPattern; + Pattern nullHandler = Pattern.compile(patternWtihArgument); + Matcher nullMatcher = nullHandler.matcher(computedJPQLGroupStatement); + if (nullMatcher.find() == false) { + log.warn("Did not match for pivoted NULL result"); + log.warn("Handler pattern was: " + patternWtihArgument); + log.warn("Computed statement was: " + computedJPQLGroupStatement); + return null; // default to classic, non-null-supported handling + } + log.info("Dynamic replacement made for pivoted NULL result on subexpression bind argument '" + + bindArgumentName + "'"); + log.info("Orginal query: " + computedJPQLGroupStatement); + computedJPQLGroupStatement = nullMatcher.replaceFirst(groupedElement + " IS NULL "); + log.info("Updated query: " + computedJPQLGroupStatement); + } else { + whereReplacements.put(bindArgumentName, groupByExpression[i++]); + whereReplacementTypes.put(bindArgumentName, String.class); + } </span><span class="cx"> } </span><span class="add">+ /* + Object bindValue = whereReplacements.get(whereCondition.getValue()); + if (bindValue == Literal.NOTNULL) { + result += whereCondition.getKey() + " IS NOT NULL "; + whereReplacements.remove(whereCondition.getValue()); // no longer needed, literal rendered here + } else if (bindValue == Literal.NULL) { + result += whereCondition.getKey() + " IS NULL "; + whereReplacements.remove(whereCondition.getValue()); // no longer needed, literal rendered here + */ + </span><span class="cx"> log.debug("MultipleQueryIterator: '" + computedJPQLGroupStatement + "'"); List<Integer> results = getSingleResultList(computedJPQLGroupStatement); </span><span class="lines">@@ -1068,7 +1103,12 @@ </span><span class="cx"> builder.append(delimiter); } </span><span class="rem">- builder.append(tokens[j].toString()); </span><span class="add">+ Object token = tokens[j]; + if (token == null) { + builder.append("empty"); + } else { + builder.append(token.toString()); + } </span><span class="cx"> } return builder.toString(); </span> </pre> </div> </div> </body> </html> |