/*
* Copyright (C) 2014 Facebook, Inc.
*
* 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.facebook.tools.parser;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
class ArgumentList {
private final int originalSize;
private final List<Argument> arguments;
ArgumentList(List<String> arguments) {
this.originalSize = arguments.size();
this.arguments = new ArrayList<>(arguments.size());
for (String argument : arguments) {
this.arguments.add(new Argument(this.arguments.size(), argument));
}
}
public List<Map.Entry<String, String>> removeSwitchValues(String switchName) {
return removeSwitchValues(switchName, false);
}
public List<Map.Entry<String, String>> removeFlag(String flagName) {
return removeSwitchValues(flagName, true);
}
public Iterator<String> trailing() {
int trailingIndex = arguments.size() - 1;
int expectedIndex = originalSize - 1;
if (arguments.isEmpty() || arguments.get(trailingIndex).index != expectedIndex) {
// either no unconsumed arguments, or they are not trailing
return Collections.emptyIterator();
}
// scan backwards for the longest contiguous block of trailing arguments
while (trailingIndex > 0 && arguments.get(trailingIndex).index == expectedIndex) {
--trailingIndex;
--expectedIndex;
}
return new TrailingIterator(arguments.subList(trailingIndex, arguments.size()).iterator());
}
public Iterator<String> remaining() {
return new TrailingIterator(arguments.iterator());
}
private List<Map.Entry<String, String>> removeSwitchValues(String switchName, boolean flag) {
Iterator<Argument> iterator = arguments.iterator();
List<Map.Entry<String, String>> values = new ArrayList<>();
while (iterator.hasNext()) {
String argument = iterator.next().value;
String value = null;
if (flag) {
if (switchName.equals(argument)) {
iterator.remove(); // remove flag
value = "true";
}
} else {
if (argument.startsWith(switchName + "=")) {
value = argument.substring((switchName + "=").length());
iterator.remove(); // remove switch=value
}
if (switchName.equals(argument) && iterator.hasNext()) {
iterator.remove(); // remove switch
value = iterator.next().value;
iterator.remove(); // remove value
}
}
if (value != null) {
values.add(new AbstractMap.SimpleImmutableEntry<>(switchName, value));
}
}
return values;
}
private static class Argument {
private final int index;
private final String value;
private Argument(int index, String value) {
this.index = index;
this.value = value;
}
}
private static class TrailingIterator implements Iterator<String> {
private final Iterator<Argument> delegate;
private TrailingIterator(Iterator<Argument> delegate) {
this.delegate = delegate;
}
@Override
public boolean hasNext() {
return delegate.hasNext();
}
@Override
public String next() {
return delegate.next().value;
}
@Override
public void remove() {
delegate.remove();
}
}
}