r2599 - in trunk/src: main/java/org/nuiton/decorator test/java/org/nuiton/decorator
Author: tchemit Date: 2013-09-28 16:27:50 +0200 (Sat, 28 Sep 2013) New Revision: 2599 Url: http://nuiton.org/projects/nuiton-decorator/repository/revisions/2599 Log: fixes #2858: Add a way in MultiJxPath to keep the order of context, when changing it Modified: trunk/src/main/java/org/nuiton/decorator/DecoratorUtil.java trunk/src/test/java/org/nuiton/decorator/MultiJXPathDecoratorTest.java Modified: trunk/src/main/java/org/nuiton/decorator/DecoratorUtil.java =================================================================== --- trunk/src/main/java/org/nuiton/decorator/DecoratorUtil.java 2013-08-09 09:04:09 UTC (rev 2598) +++ trunk/src/main/java/org/nuiton/decorator/DecoratorUtil.java 2013-09-28 14:27:50 UTC (rev 2599) @@ -124,6 +124,25 @@ return decorator; } + /** + * Build a new multi jx path decorator which uise a cycling order while changing the context index. + * <p/> + * For example, having a initial expression: + * <pre>A - B - C</pre> + * <p/> + * When setting conext index to 1, then we will us this expression: + * <pre>B - C - A</pre> + * + * @param type type of bean + * @param expression initial expression + * @param separator expression context separator + * @param separatorReplacement context separator replacement in decorator + * @param <O> type of bean + * @return the new decorator + * @throws IllegalArgumentException ... + * @throws NullPointerException ... + * @since 3.0 + */ public static <O> MultiJXPathDecorator<O> newMultiJXPathDecorator( Class<O> type, String expression, @@ -145,6 +164,45 @@ } /** + * Build a new multi jx path decorator which keep order of incoming expression while changing the context index. + * <p/> + * For example, having a initial expression: + * <pre>A - B - C</pre> + * <p/> + * When setting conext index to 1, then we will us this expression: + * <pre>B - A - C</pre> + * + * @param type type of bean + * @param expression initial expression + * @param separator expression context separator + * @param separatorReplacement context separator replacement in decorator + * @param <O> type of bean + * @return the new decorator + * @throws IllegalArgumentException ... + * @throws NullPointerException ... + * @since 3.0 + */ + public static <O> MultiJXPathDecorator<O> newMultiJXPathDecoratorKeepingOrder( + Class<O> type, + String expression, + String separator, + String separatorReplacement) + throws IllegalArgumentException, NullPointerException { + + Context<O>[] contexts = createMultiJXPathContextKeepingOrder( + expression, + separator, + separatorReplacement); + + return new MultiJXPathDecorator<O>( + type, + expression, + separator, + separatorReplacement, + contexts); + } + + /** * Sort a list of data based on the first token property of a given context * in a given decorator. * @@ -291,6 +349,81 @@ return contexts; } + public static <O> Context<O>[] createMultiJXPathContextKeepingOrder( + String expression, + String separator, + String separatorReplacement) { + int sep = expression.indexOf(separator); + if (sep == -1) { + Context<O>[] result = newInstance(1); + result[0] = createJXPathContext(expression); + return result; + } + + List<String> tokens = new ArrayList<String>(); + StringTokenizer stk = new StringTokenizer(expression, separator); + while (stk.hasMoreTokens()) { + tokens.add(stk.nextToken()); + } + + int nbTokens = tokens.size(); + Context<O>[] contexts = newInstance(nbTokens); + if (log.isDebugEnabled()) { + log.debug("Will prepare " + nbTokens + " contexts from [" + expression + "]"); + } + for (int i = 0; i < nbTokens; i++) { + StringBuilder buffer = new StringBuilder(expression.length()); + + { + // first set the i context, then keep context in order + int index = i; + String str = tokens.get(index); + + //replace all '%(index+1)$' pattern with '%(1)$' + Pattern p = Pattern.compile("\\%(" + (index + 1) + ")\\$"); + Matcher matcher = p.matcher(str); + String safeStr = matcher.replaceAll("\\%" + (1) + "\\$"); + + if (log.isDebugEnabled()) { + log.debug("[" + (index + 1) + "-->" + (1) + "] " + str + + " transformed to " + safeStr); + } + buffer.append(separatorReplacement).append(safeStr); + } + for (int j = 0; j < nbTokens; j++) { + if (j == i) { + + // already done + continue; + } + + int index = j; + + String str = tokens.get(index); + + int againstIndex = j < i ? j + 1 : j; + + //replace all '%(index+1)$' pattern with '%(againstIndex+1)$' + Pattern p = Pattern.compile("\\%(" + (index + 1) + ")\\$"); + Matcher matcher = p.matcher(str); + String safeStr = matcher.replaceAll("\\%" + (againstIndex + 1) + "\\$"); + + if (log.isDebugEnabled()) { + log.debug("[" + (index + 1) + "-->" + (againstIndex + 1) + "] " + str + + " transformed to " + safeStr); + } + buffer.append(separatorReplacement).append(safeStr); + } + String expr = buffer.substring(separatorReplacement.length()); + if (log.isDebugEnabled()) { + log.debug("context [" + i + "] : " + expr); + } + contexts[i] = createJXPathContext( + expr); + } + return contexts; + } + @SuppressWarnings("unchecked") protected static <O> Context<O>[] newInstance(int size) { // fixme how to instanciate a typed array with no checking warning ? Modified: trunk/src/test/java/org/nuiton/decorator/MultiJXPathDecoratorTest.java =================================================================== --- trunk/src/test/java/org/nuiton/decorator/MultiJXPathDecoratorTest.java 2013-08-09 09:04:09 UTC (rev 2598) +++ trunk/src/test/java/org/nuiton/decorator/MultiJXPathDecoratorTest.java 2013-09-28 14:27:50 UTC (rev 2599) @@ -198,6 +198,35 @@ } @Test + public void testMultiDecoratorWithMultiRefKeepingOrder() throws Exception { + + decorator = DecoratorUtil.newMultiJXPathDecoratorKeepingOrder(JXPathDecorator.class, "${expression}$s#${nbToken}$d#${separator}$s %3$s", "#", " - "); + + assertEquals("%1$s - %2$d - %3$s %3$s", decorator.getExpression()); + assertTokens("expression", "nbToken", "separator"); + assertEquals(3, decorator.contexts.length); + + expected = String.format(decorator.getExpression(), decorator.getExpression(), decorator.getNbToken(), decorator.getSeparator()); + result = decorator.toString(decorator); + assertEquals(expected, result); + + decorator.setContextIndex(1); + assertEquals("%1$d - %2$s - %3$s %3$s", decorator.getExpression()); + assertTokens("nbToken", "expression", "separator"); + expected = String.format(decorator.getExpression(), decorator.getNbToken(), decorator.getExpression(), decorator.getSeparator()); + result = decorator.toString(decorator); + assertEquals(expected, result); + + decorator.setContextIndex(2); + assertEquals("%1$s %1$s - %2$s - %3$d", decorator.getExpression()); + assertTokens("separator", "expression", "nbToken"); + + expected = String.format(decorator.getExpression(), decorator.getSeparator(), decorator.getExpression(), decorator.getNbToken()); + result = decorator.toString(decorator); + assertEquals(expected, result); + } + + @Test public void testSort() throws Exception { List<Data> datas = Data.generate(10);
participants (1)
-
tchemit@users.nuiton.org