package org.apache.cassandra.stress.settings;
/*
*
* 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.
*
*/
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* For specifying multiple grouped sub-options in the form: group(arg1=,arg2,arg3) etc.
*/
abstract class OptionMulti extends Option
{
private static final Pattern ARGS = Pattern.compile("([^,]+)", Pattern.CASE_INSENSITIVE);
private final class Delegate extends GroupedOptions
{
@Override
public List<? extends Option> options()
{
if (collectAsMap == null)
return OptionMulti.this.options();
List<Option> options = new ArrayList<>(OptionMulti.this.options());
options.add(collectAsMap);
return options;
}
}
protected abstract List<? extends Option> options();
public Map<String, String> extraOptions()
{
return collectAsMap == null ? new HashMap<String, String>() : collectAsMap.options;
}
private final String name;
private final Pattern pattern;
private final String description;
private final Delegate delegate = new Delegate();
private final CollectAsMap collectAsMap;
public OptionMulti(String name, String description, boolean collectExtraOptionsInMap)
{
this.name = name;
pattern = Pattern.compile(name + "\\((.*)\\)", Pattern.CASE_INSENSITIVE);
this.description = description;
this.collectAsMap = collectExtraOptionsInMap ? new CollectAsMap() : null;
}
@Override
public boolean accept(String param)
{
Matcher m = pattern.matcher(param);
if (!m.matches())
return false;
m = ARGS.matcher(m.group(1));
int last = -1;
while (m.find())
{
if (m.start() != last + 1)
throw new IllegalArgumentException("Invalid " + name + " specification: " + param);
last = m.end();
if (!delegate.accept(m.group()))
{
throw new IllegalArgumentException("Invalid " + name + " specification: " + m.group());
}
}
return true;
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(name);
sb.append("(");
for (Option option : delegate.options())
{
sb.append(option);
sb.append(",");
}
sb.append(")");
return sb.toString();
}
@Override
public String shortDisplay()
{
return (happy() ? "[" : "") + name + "(?)" + (happy() ? "]" : "");
}
@Override
public String longDisplay()
{
StringBuilder sb = new StringBuilder();
sb.append(name);
sb.append("(");
for (Option opt : delegate.options())
{
sb.append(opt.shortDisplay());
}
sb.append("): ");
sb.append(description);
return sb.toString();
}
@Override
public List<String> multiLineDisplay()
{
final List<String> r = new ArrayList<>();
for (Option option : options())
r.add(option.longDisplay());
return r;
}
@Override
boolean happy()
{
return delegate.happy();
}
private static final class CollectAsMap extends Option
{
static final String description = "Extra options";
Map<String, String> options = new LinkedHashMap<>();
boolean accept(String param)
{
String[] args = param.split("=");
if (args.length == 2 && args[1].length() > 0 && args[0].length() > 0)
{
if (options.put(args[0], args[1]) != null)
throw new IllegalArgumentException(args[0] + " set twice");
return true;
}
return false;
}
boolean happy()
{
return true;
}
String shortDisplay()
{
return "[<option 1..N>=?]";
}
String longDisplay()
{
return GroupedOptions.formatLong(shortDisplay(), description);
}
List<String> multiLineDisplay()
{
return Collections.emptyList();
}
boolean setByUser()
{
return !options.isEmpty();
}
boolean present()
{
return !options.isEmpty();
}
}
List<Option> optionsSetByUser()
{
List<Option> r = new ArrayList<>();
for (Option option : delegate.options())
if (option.setByUser())
r.add(option);
return r;
}
List<Option> defaultOptions()
{
List<Option> r = new ArrayList<>();
for (Option option : delegate.options())
if (!option.setByUser() && option.present())
r.add(option);
return r;
}
boolean setByUser()
{
for (Option option : delegate.options())
if (option.setByUser())
return true;
return false;
}
boolean present()
{
for (Option option : delegate.options())
if (option.present())
return true;
return false;
}
}