/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.voice.text;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A helper to parse a sequence of tokens. This class is immutable.
*
* @author Tilman Kamp - Initial contribution and API
*
*/
public class TokenList {
private List<String> list = null;
private int head = 0;
private int tail = 0;
/**
* Constructs a new instance.
*
* @param list of the initial tokens
*/
public TokenList(List<String> list) {
this.list = Collections.unmodifiableList(new ArrayList<String>(list));
this.head = 0;
this.tail = list.size() - 1;
}
private TokenList(List<String> list, int head, int tail) {
this.list = list;
this.head = head;
this.tail = tail;
}
/**
* Gets the first token of the list.
*
* @return the first token of the list
*/
public String head() {
return (list.size() < 1 || head < 0 || head >= list.size()) ? null : list.get(head);
}
/**
* Gets the last token of the list.
*
* @return the last token of the list
*/
public String tail() {
return (list.size() < 1 || tail < 0 || tail >= list.size()) ? null : list.get(tail);
}
/**
* Checks, if the list is empty.
*
* @return if the list is empty
*/
public boolean eof() {
return head > tail;
}
/**
* Retrieves the token count within the list.
*
* @return token count
*/
public int size() {
return tail - head + 1;
}
/**
* Checks for the first token of the list.
* If it is equal to one of the provided alternatives, it will succeed.
*
* @param alternatives Allowed token values for the list's first token.
* If empty, all token values are allowed.
* @return True, if first token is equal to one of the alternatives or if no alternatives were provided.
* False otherwise. Always false, if there is no first token (if the list is empty).
*/
public boolean checkHead(String... alternatives) {
return check(head, alternatives);
}
/**
* Checks for the last token of the list.
* If it is equal to one of the provided alternatives, it will succeed.
*
* @param alternatives Allowed token values for the list's last token.
* If empty, all token values are allowed.
* @return True, if last token is equal to one of the alternatives or if no alternatives were provided.
* False otherwise. Always false, if there is no last token (if the list is empty).
*/
public boolean checkTail(String... alternatives) {
return check(tail, alternatives);
}
/**
* Retrieves the first token of the list, in case it is equal to one of the provided alternatives.
*
* @param alternatives Allowed token values for the list's first token.
* If empty, all token values are allowed.
* @return First token, if it is equal to one of the alternatives or if no alternatives were provided.
* Null otherwise. Always null, if there is no first token (if the list is empty).
*/
public String peekHead(String... alternatives) {
return peek(head, alternatives);
}
/**
* Retrieves the last token of the list, in case it is equal to one of the provided alternatives.
*
* @param alternatives Allowed token values for the list's last token.
* If empty, all token values are allowed.
* @return Last token, if it is equal to one of the alternatives or if no alternatives were provided.
* Null otherwise. Always null, if there is no last token (if the list is empty).
*/
public String peekTail(String... alternatives) {
return peek(tail, alternatives);
}
/**
* Creates a new list without the first token.
*
* @return a new list without the first token
*/
public TokenList skipHead() {
return new TokenList(list, head + 1, tail);
}
/**
* Creates a new list without the last token.
*
* @return a new list without the last token
*/
public TokenList skipTail() {
return new TokenList(list, head, tail - 1);
}
private String peek(int index, String... alternatives) {
return splice(index, alternatives);
}
private boolean check(int index, String... alternatives) {
return splice(index, alternatives) != null;
}
private String splice(int index, String... alternatives) {
if (index < head || index > tail || head > tail) {
return null;
}
String token = list.get(index);
if (alternatives.length == 0) {
return token;
} else {
for (String alt : alternatives) {
if (alt.equals(token)) {
return token;
}
}
return null;
}
}
}