// Copyright � 2006-2007 ASERT. Released under the Canoo Webtest license. package com.canoo.webtest.extension; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import com.canoo.webtest.steps.AbstractFilter; import com.canoo.webtest.util.ConversionUtil; import com.gargoylesoftware.htmlunit.WebResponse; /** * Removes or keeps lines based on start and stop regular expressions.<p> * * @author Paul King * @webtest.step category="Filter" * name="selectLinesFilter" * description="Removes or keeps lines starting at a <em>start</em> <key>regex</key> until a <em>stop</em> <key>regex</key>. For use with steps which take a <em>ContentFilter</em>." */ public class SelectLinesFilter extends AbstractFilter { private static final String LS = System.getProperty("line.separator"); private static final String LINE_STR = "(^.*$)"; private String fStartRegex; private String fIncludeStart; private String fStopRegex; private String fIncludeStop; private String fRemove; private String fRepeat; private static final Pattern LINE_PATTERN = Pattern.compile(LINE_STR, Pattern.MULTILINE); /** * @param value * @webtest.parameter * required="yes/no" * description="The regex to start selecting from. One of 'startRegex' or 'stopRegex' must be set." */ public void setStartRegex(final String value) { fStartRegex = value; } public String getStartRegex() { return fStartRegex; } /** * @param flag * @webtest.parameter * required="no" * default="true" * description="Whether to include the line the start regex was found on." */ public void setIncludeStart(final String flag) { fIncludeStart = flag; } public String getIncludeStart() { return fIncludeStart; } /** * @param value * @webtest.parameter * required="yes/no" * description="The regex to stop selecting from. One of 'startRegex' or 'stopRegex' must be set." */ public void setStopRegex(final String value) { fStopRegex = value; } public String getStopRegex() { return fStopRegex; } /** * @param flag * @webtest.parameter * required="no" * default="true" * description="Whether to include the line the stop regex was found on." */ public void setIncludeStop(final String flag) { fIncludeStop = flag; } public String getIncludeStop() { return fIncludeStop; } /** * @param flag * @webtest.parameter * required="no" * default="false" * description="Indicates that selected lines will be removed (true) or kept (false)." */ public void setRemove(final String flag) { fRemove = flag; } public String getRemove() { return fRemove; } /** * @param flag * @webtest.parameter * required="no" * default="false" * description="Indicates that the first (false) or all (true) lines between start and stop <key>regex</key> patterns will be selected. Only relevant if the patterns occur multiple times throughout the response." */ public void setRepeat(final String flag) { fRepeat = flag; } public String getRepeat() { return fRepeat; } protected void verifyParameters() { super.verifyParameters(); paramCheck(getStartRegex() == null && getStopRegex() == null, "One of 'startRegex' or 'stopRegex' must be set!"); nullResponseCheck(); } public void doExecute() throws Exception { final WebResponse webResponse = getContext().getCurrentResponse().getWebResponse(); final String orig = webResponse.getContentAsString(); final String origType = webResponse.getContentType(); final boolean remove = ConversionUtil.convertToBoolean(getRemove(), false); final boolean repeat = ConversionUtil.convertToBoolean(getRepeat(), false); final boolean includeStart = ConversionUtil.convertToBoolean(getIncludeStart(), true); final boolean includeStop = ConversionUtil.convertToBoolean(getIncludeStop(), true); final Matcher matcher = LINE_PATTERN.matcher(orig); final StringBuffer buf = new StringBuffer(); boolean selecting = StringUtils.isEmpty(getStartRegex()); boolean done = false; while (matcher.find()) { boolean adding = false; final String line = matcher.group(0); if (selecting && includeStop) { adding = true; } if (selecting && !done && line.matches(getStopRegex())) { selecting = false; if (!repeat) { done = true; } } if (!selecting && !done && line.matches(getStartRegex())) { selecting = true; if (includeStart) { adding = true; } } else if (selecting) { adding = true; } if (adding != remove) { buf.append(line).append(LS); } } defineAsCurrentResponse(buf.toString(), origType); } }