From 0f08bd630209714e8264ecbdb2e1ec2f37e55cfe Mon Sep 17 00:00:00 2001 From: Xavier Hanin Date: Wed, 2 Nov 2005 13:53:50 +0000 Subject: [PATCH] IMPROVE: allow optional parts in the patterns (IVY-102) (thanks to Maarten Coene) git-svn-id: https://svn.apache.org/repos/asf/incubator/ivy/trunk@484069 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 1 + .../jayasoft/ivy/util/IvyPatternHelper.java | 95 ++++++++++++++++--- .../ivy/util/IvyPatternHelperTest.java | 9 ++ 3 files changed, 92 insertions(+), 13 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 4fd80c71..b9df473c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,7 @@ - NEW: ability to output a path of dependencies in cache from the standalone mode (IVY-92) - NEW: it is now possible to reference existing resolver in resolver containers (IVY-35) - NEW: overwrite attribute in the publish task now let force overwrite of read only files (IVY-83) +- IMPROVE: allow optional parts in the patterns (IVY-102) (thanks to Maarten Coene) - IMPROVE: ability to define variable directly in ivyconf.xml (IVY-100) - IMPROVE: ability to use no revision in pattern with latest.integration dependency, artifacts being updated according to revision change in ivy file (if checkmodified is set to true) (IVY-95) - IMPROVE: ability to specify a root module in buildlist to filter out unnecessary build files (IVY-93) (thanks to Kristian Cibulskis) diff --git a/src/java/fr/jayasoft/ivy/util/IvyPatternHelper.java b/src/java/fr/jayasoft/ivy/util/IvyPatternHelper.java index 66ce9b32..760950f3 100644 --- a/src/java/fr/jayasoft/ivy/util/IvyPatternHelper.java +++ b/src/java/fr/jayasoft/ivy/util/IvyPatternHelper.java @@ -18,7 +18,7 @@ import fr.jayasoft.ivy.ModuleRevisionId; /** * @author x.hanin - * + * @author Maarten Coene (for the optional part management) */ public class IvyPatternHelper { public static final String CONF_KEY = "conf"; @@ -123,20 +123,89 @@ public class IvyPatternHelper { } public static String substituteTokens(String pattern, Map tokens) { - Matcher m = TOKEN_PATTERN.matcher(pattern); + StringBuffer buffer = new StringBuffer(); - StringBuffer sb = new StringBuffer(); - while (m.find()) { - String var = m.group(1); - String val = (String)tokens.get(var); - if (val == null) { - val = m.group(); - } - m.appendReplacement(sb, val.replaceAll("\\\\", "\\\\\\\\").replaceAll("\\$", "\\\\\\$")); - } - m.appendTail(sb); + char[] chars = pattern.toCharArray(); + + StringBuffer optionalPart = null; + StringBuffer tokenBuffer = null; + boolean insideOptionalPart = false; + boolean insideToken = false; + boolean tokenHadValue = false; + + for (int i = 0; i < chars.length; i++) { + switch (chars[i]) { + case '(': + if (insideOptionalPart) { + throw new IllegalArgumentException("invalid start of optional part at position " + i + " in pattern " + pattern); + } - return sb.toString(); + optionalPart = new StringBuffer(); + insideOptionalPart = true; + tokenHadValue = false; + break; + + case ')': + if (!insideOptionalPart || insideToken) { + throw new IllegalArgumentException("invalid end of optional part at position " + i + " in pattern " + pattern); + } + + if (tokenHadValue) { + buffer.append(optionalPart.toString()); + } + + insideOptionalPart = false; + break; + + case '[': + if (insideToken) { + throw new IllegalArgumentException("invalid start of token at position " + i + " in pattern " + pattern); + } + + tokenBuffer = new StringBuffer(); + insideToken = true; + break; + + case ']': + if (!insideToken) { + throw new IllegalArgumentException("invalid end of token at position " + i + " in pattern " + pattern); + } + + String token = tokenBuffer.toString(); + String value = (String) tokens.get(token); + + if (insideOptionalPart) { + tokenHadValue = (value != null) && (value.length() > 0); + optionalPart.append(value); + } else { + buffer.append(value); + } + + insideToken = false; + break; + + default: + if (insideToken) { + tokenBuffer.append(chars[i]); + } else if (insideOptionalPart) { + optionalPart.append(chars[i]); + } else { + buffer.append(chars[i]); + } + + break; + } + } + + if (insideToken) { + throw new IllegalArgumentException("last token hasn't been closed in pattern " + pattern); + } + + if (insideOptionalPart) { + throw new IllegalArgumentException("optional part hasn't been closed in pattern " + pattern); + } + + return buffer.toString(); } public static String substituteVariable(String pattern, String variable, String value) { diff --git a/test/java/fr/jayasoft/ivy/util/IvyPatternHelperTest.java b/test/java/fr/jayasoft/ivy/util/IvyPatternHelperTest.java index 4b2f1291..42b058e8 100644 --- a/test/java/fr/jayasoft/ivy/util/IvyPatternHelperTest.java +++ b/test/java/fr/jayasoft/ivy/util/IvyPatternHelperTest.java @@ -34,6 +34,15 @@ public class IvyPatternHelperTest extends TestCase { } } + public void testOptionalSubstitute() { + Map tokens = new HashMap(); + tokens.put("token", ""); + tokens.put("othertoken", "myval"); + assertEquals("test-myval", IvyPatternHelper.substituteTokens("test(-[token])(-[othertoken])", tokens)); + tokens.put("token", "val"); + assertEquals("test-val-myval", IvyPatternHelper.substituteTokens("test(-[token])(-[othertoken])", tokens)); + } + public void testOrganization() { String pattern = "[organization]/[module]/build/archives/[type]s/[artifact]-[revision].[ext]"; assertEquals(