Hi Felix, In this case CAMEL_CASE implementations are wrong. Your conception look indeed closer to what I was usually seeing. Shall I fix it ?
Do you think CAMEL_CASE and CAMEL_CASE_FIRST_LOWER are clear enough ? Or should we name them: - UPPER_CAMEL_CASE - LOWER_CAMEL_CASE As per: https://en.wikipedia.org/wiki/Camel_case Thanks On Tue, Nov 21, 2017 at 9:59 PM, Felix Schumacher <felix.schumacher@ internetallee.de> wrote: > Am 20.11.2017 um 20:50 schrieb [email protected]: > >> Author: pmouawad >> Date: Mon Nov 20 19:50:51 2017 >> New Revision: 1815838 >> >> URL: http://svn.apache.org/viewvc?rev=1815838&view=rev >> Log: >> Bug 61759 - New __changeCase function >> Contributed by Orimarko >> Bugzilla Id: 61759 >> >> Added: >> jmeter/trunk/src/functions/org/apache/jmeter/functions/ChangeCase.java >> (with props) >> jmeter/trunk/test/src/org/apache/jmeter/functions/TestChangeCase.java >> (with props) >> Modified: >> jmeter/trunk/xdocs/changes.xml >> jmeter/trunk/xdocs/usermanual/functions.xml >> >> Added: jmeter/trunk/src/functions/org/apache/jmeter/functions/Chang >> eCase.java >> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/functions/org/ >> apache/jmeter/functions/ChangeCase.java?rev=1815838&view=auto >> ============================================================ >> ================== >> --- jmeter/trunk/src/functions/org/apache/jmeter/functions/ChangeCase.java >> (added) >> +++ jmeter/trunk/src/functions/org/apache/jmeter/functions/ChangeCase.java >> Mon Nov 20 19:50:51 2017 >> @@ -0,0 +1,175 @@ >> +/* >> + * Licensed to the Apache Software Foundation (ASF) under one or more >> + * contributor license agreements. See the NOTICE file distributed with >> + * this work for additional information regarding copyright ownership. >> + * The ASF licenses this file to You under the Apache License, Version >> 2.0 >> + * (the "License"); you may not use this file except in compliance with >> + * the License. You may obtain a copy of the License at >> + * >> + * http://www.apache.org/licenses/LICENSE-2.0 >> + * >> + * Unless required by applicable law or agreed to in writing, software >> + * distributed under the License is distributed on an "AS IS" BASIS, >> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >> implied. >> + * See the License for the specific language governing permissions and >> + * limitations under the License. >> + * >> + */ >> + >> +package org.apache.jmeter.functions; >> + >> +import java.util.Collection; >> +import java.util.EnumSet; >> +import java.util.LinkedList; >> +import java.util.List; >> +import java.util.regex.Pattern; >> + >> +import org.apache.commons.lang3.StringUtils; >> +import org.apache.jmeter.engine.util.CompoundVariable; >> +import org.apache.jmeter.samplers.SampleResult; >> +import org.apache.jmeter.samplers.Sampler; >> +import org.apache.jmeter.util.JMeterUtils; >> +import org.slf4j.Logger; >> +import org.slf4j.LoggerFactory; >> + >> +/** >> + * Change Case Function >> + * >> + * Support String manipulations of: >> + * <ul> >> + * <li>upper case</li> >> + * <li>lower case</li> >> + * <li>capitalize</li> >> + * <li>camel cases</li> >> + * <li></li> >> + * >> + * >> + * @since 4.0 >> + * >> + */ >> +public class ChangeCase extends AbstractFunction { >> + >> + private static final Pattern NOT_ALPHANUMERIC_REGEX = >> + Pattern.compile("[^a-zA-Z]"); >> + private static final Logger LOGGER = LoggerFactory.getLogger(Change >> Case.class); >> + private static final List<String> DESC = new LinkedList<>(); >> + private static final String KEY = "__changeCase"; >> + >> + private static final int MIN_PARAMETER_COUNT = 1; >> + private static final int MAX_PARAMETER_COUNT = 3; >> + >> + static { >> + DESC.add(JMeterUtils.getResString("change_case_string")); >> + DESC.add(JMeterUtils.getResString("change_case_mode")); >> + DESC.add(JMeterUtils.getResString("function_name_paropt")); >> + } >> + >> + private CompoundVariable[] values; >> + >> + @Override >> + public String execute(SampleResult previousResult, Sampler >> currentSampler) throws InvalidVariableException { >> + String originalString = values[0].execute(); >> + String mode = ChangeCaseMode.UPPER.getName(); // default >> + if (values.length > 1) { >> + mode = values[1].execute(); >> + } >> + String targetString = changeCase(originalString, mode); >> + addVariableValue(targetString, values, 2); >> + return targetString; >> + } >> + >> + protected String changeCase(String originalString, String mode) { >> + String targetString = originalString; >> + // mode is case insensitive, allow upper for example >> + ChangeCaseMode changeCaseMode = ChangeCaseMode.typeOf(mode.toU >> pperCase()); >> + if (changeCaseMode != null) { >> + switch (changeCaseMode) { >> + case UPPER: >> + targetString = StringUtils.upperCase(originalString); >> + break; >> + case LOWER: >> + targetString = StringUtils.lowerCase(originalString); >> + break; >> + case CAPITALIZE: >> + targetString = StringUtils.capitalize(originalString); >> + break; >> + case CAMEL_CASE: >> + targetString = camel(originalString, false); >> + break; >> + case CAMEL_CASE_FIRST_LOWER: >> + targetString = camel(originalString, true); >> + break; >> + default: >> + // default not doing nothing to string >> + } >> + } else { >> + LOGGER.error("Unknown mode {}, returning {}Â unchanged", >> mode, targetString); >> + } >> + return targetString; >> + } >> + >> + @Override >> + public void setParameters(Collection<CompoundVariable> parameters) >> throws InvalidVariableException { >> + checkParameterCount(parameters, MIN_PARAMETER_COUNT, >> MAX_PARAMETER_COUNT); >> + values = parameters.toArray(new CompoundVariable[parameters.si >> ze()]); >> + } >> + >> + @Override >> + public String getReferenceKey() { >> + return KEY; >> + } >> + >> + @Override >> + public List<String> getArgumentDesc() { >> + return DESC; >> + } >> + >> + private static String camel(String str, boolean isFirstCapitalized) { >> + StringBuilder builder = new StringBuilder(str.length()); >> + String[] tokens = NOT_ALPHANUMERIC_REGEX.split(str); >> + for (int i = 0; i < tokens.length; i++) { >> + if(i == 0) { >> + builder.append(isFirstCapitalized ? tokens[0]: >> + StringUtils.capitalize(tokens[i])); >> + } else { >> + builder.append(StringUtils.capitalize(tokens[i])); >> + } >> + } >> + return builder.toString(); >> + } >> + >> + /** >> + * ChangeCase Modes >> + * >> + * Modes for different cases >> + * >> + */ >> + public enum ChangeCaseMode { >> + UPPER("UPPER"), LOWER("LOWER"), CAPITALIZE("CAPITALIZE"), >> CAMEL_CASE("CAMEL_CASE"), CAMEL_CASE_FIRST_LOWER( >> + "CAMEL_CASE_FIRST_LOWER"); >> + private String mode; >> + >> + private ChangeCaseMode(String mode) { >> + this.mode = mode; >> + } >> + >> + public String getName() { >> + return this.mode; >> + } >> + >> + /** >> + * Get ChangeCaseMode by mode >> + * >> + * @param mode >> + * @return relevant ChangeCaseMode >> + */ >> + public static ChangeCaseMode typeOf(String mode) { >> + EnumSet<ChangeCaseMode> allOf = >> EnumSet.allOf(ChangeCaseMode.class); >> + for (ChangeCaseMode zs : allOf) { >> + if (zs.getName().equals(mode)) >> + return zs; >> + } >> + return null; >> + } >> + } >> +} >> >> Propchange: jmeter/trunk/src/functions/org/apache/jmeter/functions/Chang >> eCase.java >> ------------------------------------------------------------ >> ------------------ >> svn:eol-style = native >> >> Propchange: jmeter/trunk/src/functions/org/apache/jmeter/functions/Chang >> eCase.java >> ------------------------------------------------------------ >> ------------------ >> svn:mime-type = text/plain >> >> Added: jmeter/trunk/test/src/org/apache/jmeter/functions/TestChange >> Case.java >> URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apach >> e/jmeter/functions/TestChangeCase.java?rev=1815838&view=auto >> ============================================================ >> ================== >> --- jmeter/trunk/test/src/org/apache/jmeter/functions/TestChangeCase.java >> (added) >> +++ jmeter/trunk/test/src/org/apache/jmeter/functions/TestChangeCase.java >> Mon Nov 20 19:50:51 2017 >> @@ -0,0 +1,138 @@ >> +/* >> + * Licensed to the Apache Software Foundation (ASF) under one or more >> + * contributor license agreements. See the NOTICE file distributed with >> + * this work for additional information regarding copyright ownership. >> + * The ASF licenses this file to You under the Apache License, Version >> 2.0 >> + * (the "License"); you may not use this file except in compliance with >> + * the License. You may obtain a copy of the License at >> + * >> + * http://www.apache.org/licenses/LICENSE-2.0 >> + * >> + * Unless required by applicable law or agreed to in writing, software >> + * distributed under the License is distributed on an "AS IS" BASIS, >> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or >> implied. >> + * See the License for the specific language governing permissions and >> + * limitations under the License. >> + * >> + */ >> + >> +package org.apache.jmeter.functions; >> + >> +import static org.junit.Assert.assertEquals; >> + >> +import java.util.Collection; >> +import java.util.LinkedList; >> + >> +import org.apache.jmeter.engine.util.CompoundVariable; >> +import org.apache.jmeter.junit.JMeterTestCase; >> +import org.apache.jmeter.samplers.SampleResult; >> +import org.apache.jmeter.threads.JMeterContext; >> +import org.apache.jmeter.threads.JMeterContextService; >> +import org.apache.jmeter.threads.JMeterVariables; >> +import org.junit.Before; >> +import org.junit.Test; >> + >> +/** >> + * Test{@link ChangeCase} ChangeCase >> + * >> + * @see ChangeCase >> + * @since 4.0 >> + */ >> +public class TestChangeCase extends JMeterTestCase { >> + >> + protected AbstractFunction changeCase; >> + private SampleResult result; >> + >> + private Collection<CompoundVariable> params; >> + >> + private JMeterVariables vars; >> + >> + private JMeterContext jmctx; >> + >> + @Before >> + public void setUp() { >> + changeCase = new ChangeCase(); >> + result = new SampleResult(); >> + jmctx = JMeterContextService.getContext(); >> + String data = "dummy data"; >> + result.setResponseData(data, null); >> + vars = new JMeterVariables(); >> + jmctx.setVariables(vars); >> + jmctx.setPreviousResult(result); >> + params = new LinkedList<>(); >> + } >> + >> + @Test >> + public void testParameterCountIsPropDefined() throws Exception { >> + checkInvalidParameterCounts(changeCase, 1, 3); >> + } >> + >> + @Test >> + public void testChangeCase() throws Exception { >> + params.add(new CompoundVariable("myUpperTest")); >> + changeCase.setParameters(params); >> + String returnValue = changeCase.execute(result, null); >> + assertEquals("MYUPPERTEST", returnValue); >> + } >> + >> + @Test >> + public void testChangeCaseLower() throws Exception { >> + params.add(new CompoundVariable("myUpperTest")); >> + params.add(new CompoundVariable("LOWER")); >> + changeCase.setParameters(params); >> + String returnValue = changeCase.execute(result, null); >> + assertEquals("myuppertest", returnValue); >> + } >> + >> + @Test >> + public void testChangeCaseWrongMode() throws Exception { >> + params.add(new CompoundVariable("myUpperTest")); >> + params.add(new CompoundVariable("Wrong")); >> + changeCase.setParameters(params); >> + String returnValue = changeCase.execute(result, null); >> + assertEquals("myUpperTest", returnValue); >> + } >> + >> + @Test >> + public void testChangeCaseCamelCase() throws Exception { >> + params.add(new CompoundVariable("ab-CD eF")); >> + params.add(new CompoundVariable("CAMEL_CASE")); >> + changeCase.setParameters(params); >> + String returnValue = changeCase.execute(result, null); >> + assertEquals("AbCDEF", returnValue); >> + } >> + >> + @Test >> + public void testChangeCaseCapitalize() throws Exception { >> + params.add(new CompoundVariable("ab-CD eF")); >> + params.add(new CompoundVariable("CAPITALIZE")); >> + changeCase.setParameters(params); >> + String returnValue = changeCase.execute(result, null); >> + assertEquals("Ab-CD eF", returnValue); >> + } >> + >> + @Test >> + public void testChangeCaseCamelCaseFirstLower() throws Exception { >> + params.add(new CompoundVariable("ab-CD eF")); >> + params.add(new CompoundVariable("camel_CASE_FIRST_LOWER")); >> + changeCase.setParameters(params); >> + String returnValue = changeCase.execute(result, null); >> + assertEquals("abCDEF", returnValue); >> + } >> + >> + @Test(expected=InvalidVariableException.class) >> + public void testChangeCaseError() throws Exception { >> + changeCase.setParameters(params); >> + changeCase.execute(result, null); >> + } >> + >> + @Test >> + public void testChangeCaseWrongModeIgnore() throws Exception { >> + params.add(new CompoundVariable("ab-CD eF")); >> + params.add(new CompoundVariable("Wrong")); >> + changeCase.setParameters(params); >> + String returnValue = changeCase.execute(result, null); >> + assertEquals("ab-CD eF", returnValue); >> + } >> + >> +} >> >> Propchange: jmeter/trunk/test/src/org/apache/jmeter/functions/TestChange >> Case.java >> ------------------------------------------------------------ >> ------------------ >> svn:eol-style = native >> >> Propchange: jmeter/trunk/test/src/org/apache/jmeter/functions/TestChange >> Case.java >> ------------------------------------------------------------ >> ------------------ >> svn:mime-type = text/plain >> >> Modified: jmeter/trunk/xdocs/changes.xml >> URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml? >> rev=1815838&r1=1815837&r2=1815838&view=diff >> ============================================================ >> ================== >> --- jmeter/trunk/xdocs/changes.xml [utf-8] (original) >> +++ jmeter/trunk/xdocs/changes.xml [utf-8] Mon Nov 20 19:50:51 2017 >> @@ -136,6 +136,7 @@ Summary >> <li><bug>61724</bug>Add <code>__digest</code> function to provide >> computing of Hashes (SHA-XXX, MDX). Based on a contribution by orimarko at >> gmail.com</li> >> <li><bug>61735</bug>Add <code>__dateTimeConvert</code> function to >> provide date formats conversions. Based on a contribution by orimarko at >> gmail.com</li> >> <li><bug>61760</bug>Add <code>__isPropDefined</code> and >> <code>__isVarDefined</code> functions to know if property or variable >> exist. Contributed by orimarko at gmail.com</li> >> + <li><bug>61759</bug>Add <code>__changeCase</code> function to change >> different cases of a string. Based on a contribution by orimarko at >> gmail.com</li> >> </ul> >> <h3>I18N</h3> >> >> Modified: jmeter/trunk/xdocs/usermanual/functions.xml >> URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/f >> unctions.xml?rev=1815838&r1=1815837&r2=1815838&view=diff >> ============================================================ >> ================== >> --- jmeter/trunk/xdocs/usermanual/functions.xml (original) >> +++ jmeter/trunk/xdocs/usermanual/functions.xml Mon Nov 20 19:50:51 2017 >> @@ -143,13 +143,14 @@ Alternatively, just use <code>/</code> i >> <tr><td>Variables</td><td> <a >> href="#__evalVar">evalVar</a></td><td>evaluate >> an expression stored in a variable</td><td>2.3.1</td></tr> >> <tr><td>Properties</td><td> <a >> href="#__isVarDefined">isVarDefined</a> >> </td><td>Test if a variable exists</td><td>4.0</td></tr> >> <tr><td>Variables</td><td> <a href="#__V">V</a></td><td>evaluate >> a variable name</td><td>2.3RC3</td></tr> >> - <tr><td>String</td><td> <a >> href="#__regexFunction">regexFunction</a></td><td>parse >> previous response using a regular expression</td><td>1.X</td></tr> >> - <tr><td>String</td><td> <a href="#__escapeOroRegexpChars" >> >escapeOroRegexpChars</a></td><td>quote meta chars used by ORO regular >> expression</td><td>2.9</td></tr> >> <tr><td>String</td><td> <a href="#__char">char</a></td><td>generate >> Unicode char values from a list of numbers</td><td>2.3.3</td></tr> >> - <tr><td>String</td><td> <a >> href="#__unescape">unescape</a></td><td>Process >> strings containing Java escapes (e.g. \n & \t)</td><td>2.3.3</td></tr> >> - <tr><td>String</td><td> <a >> href="#__unescapeHtml">unescapeHtml</a></td><td>Decode >> HTML-encoded strings</td><td>2.3.3</td></tr> >> + <tr><td>String</td><td> <a >> href="#__changeCase">changeCase</a></td><td>Change >> case following different modes</td><td>4.0</td></tr> >> <tr><td>String</td><td> <a >> href="#__escapeHtml">escapeHtml</a></td><td>Encode >> strings using HTML encoding</td><td>2.3.3</td></tr> >> + <tr><td>String</td><td> <a href="#__escapeOroRegexpChars" >> >escapeOroRegexpChars</a></td><td>quote meta chars used by ORO regular >> expression</td><td>2.9</td></tr> >> <tr><td>String</td><td> <a >> href="#__escapeXml">escapeXml</a></td><td>Encode >> strings using XMl encoding</td><td>3.2</td></tr> >> + <tr><td>String</td><td> <a >> href="#__regexFunction">regexFunction</a></td><td>parse >> previous response using a regular expression</td><td>1.X</td></tr> >> + <tr><td>String</td><td> <a >> href="#__unescape">unescape</a></td><td>Process >> strings containing Java escapes (e.g. \n & \t)</td><td>2.3.3</td></tr> >> + <tr><td>String</td><td> <a >> href="#__unescapeHtml">unescapeHtml</a></td><td>Decode >> HTML-encoded strings</td><td>2.3.3</td></tr> >> <tr><td>String</td><td> <a >> href="#__urldecode">urldecode</a></td><td>Decode >> a application/x-www-form-urlencoded string</td><td>2.10</td></tr> >> <tr><td>String</td><td> <a >> href="#__urlencode">urlencode</a></td><td>Encode >> a string to a application/x-www-form-urlencoded >> string</td><td>2.10</td></tr> >> <tr><td>String</td><td> <a >> href="#__TestPlanName">TestPlanName</a></td><td>Return >> name of current test plan</td><td>2.6</td></tr> >> @@ -1616,7 +1617,7 @@ becomes: >> <property name="Name of variable" required="No">The name of the >> variable to set.</property> >> </properties> >> </component> >> -<component index="§-num;.5.35" name="__isPropDefined"> >> +<component index="§-num;.5.36" name="__isPropDefined"> >> <description> >> <p>The <code>__isPropDefined</code> function returns true if >> property exists or false if not.</p> >> </description> >> @@ -1626,7 +1627,7 @@ becomes: >> </property> >> </properties> >> </component> >> -<component index="§-num;.5.35" name="__isVarDefined"> >> +<component index="§-num;.5.37" name="__isVarDefined"> >> <description> >> <p>The <code>__isVarDefined</code> function returns true if >> variable exists or false if not.</p> >> </description> >> @@ -1636,6 +1637,30 @@ becomes: >> </property> >> </properties> >> </component> >> +<component index="§-num;.5.38" name="__changeCase"> >> + <description> >> + <p>The change case function returns a string value which >> + case has been changed following a specific mode. >> + Result can optionally be saved in a JMeter variable.</p> >> + </description> >> + <properties> >> + <property name="String to change case" required="Yes">The String >> + which case will be changed</property> >> + <property name="change case mode" required="Yes"> >> + The mode to be used to change case, for example for ab-CD eF: >> + <ul> >> + <li><code>UPPER</code> result as AB-CD EF</li> >> + <li><code>LOWER</code> result as ab-cd ed</li> >> + <li><code>CAPITALIZE</code> result as Ab-CD eF</li> >> + <li><code>CAMEL_CASE</code>result as AbCDEF</li> >> > Shouldn't this be AbCdEf? > >> + <li><code>CAMEL_CASE_FIRST_LOWER</code>result as >> abCDEF</li> >> > and this abCdEf? > > Regards, > Felix > > + </ul> >> + <note>mode is case insensitive</note> >> + </property> >> + <property name="Name of variable" required="No">The name of the >> variable to set.</property> >> + </properties> >> +</component> >> + >> </subsection> >> <subsection name="§-num;.6 Pre-defined Variables" >> anchor="predefinedvars"> >> >> >> > -- Cordialement. Philippe Mouawad.
