com.xceptance.xlt.nocoding.parser.csv.CsvParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xlt-nocoding Show documentation
Show all versions of xlt-nocoding Show documentation
A library based on XLT to run Web test cases that are written in either YAML or CSV format.
The newest version!
/*
* Copyright (c) 2013-2023 Xceptance Software Technologies GmbH
*
* Licensed 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 com.xceptance.xlt.nocoding.parser.csv;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.apache.commons.csv.CSVParser;
import com.xceptance.xlt.nocoding.command.Command;
import com.xceptance.xlt.nocoding.command.action.Action;
import com.xceptance.xlt.nocoding.command.action.subrequest.StaticSubrequest;
import com.xceptance.xlt.nocoding.parser.Parser;
import com.xceptance.xlt.nocoding.parser.csv.command.ActionParser;
import com.xceptance.xlt.nocoding.parser.csv.command.StaticSubrequestParser;
import com.xceptance.xlt.nocoding.parser.csv.command.XhrSubrequestParser;
/**
* Reads a CSV file, and generates a list filled with {@link Command}s out of the CSV file.
*
* @author ckeiner
*/
public class CsvParser implements Parser
{
/**
* Parses the content of the Reader reader
to a list of {@link Command}s
*
* @param reader
* The Reader that contains {@link Command}s in a parser dependent format
* @return A list of {@link Command}s
* @throws IOException
* if an I/O error occurs during creating the reader, parsing the file or closing the parser
*/
@Override
public List parse(final Reader reader) throws IOException
{
// Initialize variables
final List scriptItems = new ArrayList<>();
final ActionWrapper lastAction = new ActionWrapper();
final StaticSubrequestWrapper lastStatic = new StaticSubrequestWrapper();
// Create a CSVParser based on the Reader
final CSVParser parser = new CSVParser(reader, CsvConstants.CSV_FORMAT);
try
{
validateHeader(parser.getHeaderMap().keySet());
parser.forEach(record -> {
// If the record is consistent, which means that all headers have a value
if (record.isConsistent())
{
// Get the type of the record
String type = CsvConstants.TYPE_DEFAULT;
if (record.isMapped(CsvConstants.TYPE))
{
type = record.get(CsvConstants.TYPE);
}
// Differentiate between Action, Static and Xhr Requests
switch (type)
{
case CsvConstants.TYPE_ACTION:
// Reset the last static subrequest
lastStatic.setStaticSubrequest(null);
// Set the new action as last action
lastAction.setAction(new ActionParser().parse(record));
// And add it to the scriptItems
scriptItems.add(lastAction.getAction());
break;
case CsvConstants.TYPE_STATIC:
// If there was no lastAction, throw an exception
if (lastAction.getAction() == null)
{
throw new IllegalArgumentException("Static Type must be defined after an Action Type");
}
// If there wasn't a last static request
if (lastStatic.getStaticSubrequest() == null)
{
// Read the static request and assign it to lastStatic
lastStatic.setStaticSubrequest(new StaticSubrequestParser().parse(record));
// Assign last static as actionItem of the lastAction
lastAction.getAction().getActionItems().add(lastStatic.getStaticSubrequest());
}
// If there was a last static request
else
{
// Simply add the url of the current static request to the lastStatic request, so they
// can
// be executed parallel
lastStatic.getStaticSubrequest().getUrls().addAll(new StaticSubrequestParser().parse(record).getUrls());
}
break;
case CsvConstants.TYPE_XHR_ACTION:
// Reset the last static subrequest
lastStatic.setStaticSubrequest(null);
// If there was no lastAction, throw an exception
if (lastAction.getAction() == null)
{
throw new IllegalArgumentException("Xhr Action Type must be defined after an Action Type");
}
// Add the Xhr Subrequest to the action items of the lastAction
lastAction.getAction().getActionItems().add(new XhrSubrequestParser().parse(record));
break;
default:
// If the type is unknown, throw an error
throw new IllegalArgumentException("The record has an unknown type: " + type);
}
}
else
{
throw new IllegalStateException("The record does not contain an entry for each header!");
}
});
}
catch (final Throwable e)
{
throw new IllegalStateException("CSV Parsing failed in line " + parser.getCurrentLineNumber() + ": " + e.getMessage(), e);
}
finally
{
parser.close();
}
// Return the scriptItems
return scriptItems;
}
/**
* Validates the headers are permitted
*
* @param headers
*/
private void validateHeader(final Set headers)
{
// for each header
for (final String header : headers)
{
// If the header is not in the permitted list
if (!CsvConstants.isPermittedHeaderField(header))
{
// Verify the header either starts with the Regexp or Xpath getter prefix
if (!(header.startsWith(CsvConstants.REGEXP_GETTER_PREFIX) || header.startsWith(CsvConstants.XPATH_GETTER_PREFIX)))
{
throw new IllegalArgumentException(header + "isn't an allowed header!");
}
}
}
}
@Override
public List getExtensions()
{
return Arrays.asList("csv");
}
public class ActionWrapper
{
public Action getAction()
{
return action;
}
public void setAction(final Action action)
{
this.action = action;
}
Action action;
}
public class StaticSubrequestWrapper
{
public StaticSubrequest getStaticSubrequest()
{
return staticSubrequest;
}
public void setStaticSubrequest(final StaticSubrequest staticSubrequest)
{
this.staticSubrequest = staticSubrequest;
}
StaticSubrequest staticSubrequest;
}
}