001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 The ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.lib.commons.options; 018 019import java.util.LinkedList; 020import java.util.Queue; 021 022/** 023 * This class preprocesses the command line arguments by splitting them into 024 * several tokens. It supports the GNU style syntax as described in 025 * {@link org.conqat.lib.commons.options.CommandLine}. 026 */ 027public class CommandLineTokenStream { 028 029 /** Queue storing remaining short options (results from option chaining). */ 030 private final Queue<Character> shortOptionQueue = new LinkedList<Character>(); 031 032 /** 033 * Pending parameter (possibly remaining from the last long option read). 034 */ 035 private String pendingParam = null; 036 037 /** Queue storing all remaining arguments. */ 038 private final Queue<String> argQueue = new LinkedList<String>(); 039 040 /** Constructs a new CommandLineTokenStream on the given arguments. */ 041 public CommandLineTokenStream(String[] args) { 042 for (String a : args) { 043 argQueue.add(a); 044 } 045 } 046 047 /** Returns whether a further token is available. */ 048 public boolean hasNext() { 049 return !argQueue.isEmpty() || !shortOptionQueue.isEmpty() || pendingParam != null; 050 } 051 052 /** Returns whether the next token is the argument separator "--". */ 053 public boolean nextIsSeparator() { 054 if (!shortOptionQueue.isEmpty() || pendingParam != null || argQueue.isEmpty()) { 055 return false; 056 } 057 return argQueue.peek().equals("--"); 058 } 059 060 /** Returns whether the next token is available and is a short option. */ 061 public boolean nextIsShortOption() { 062 if (!shortOptionQueue.isEmpty()) { 063 return true; 064 } 065 if (pendingParam != null || argQueue.isEmpty()) { 066 return false; 067 } 068 String next = argQueue.peek(); 069 return next.length() >= 2 && next.charAt(0) == '-' && next.charAt(1) != '-'; 070 } 071 072 /** Returns whether the next token is available and is a long option. */ 073 public boolean nextIsLongOption() { 074 if (!shortOptionQueue.isEmpty() || pendingParam != null || argQueue.isEmpty()) { 075 return false; 076 } 077 return argQueue.peek().startsWith("--") && argQueue.peek().length() > 2; 078 } 079 080 /** 081 * Returns whether the next token is available and can be used as a file 082 * argument. 083 */ 084 public boolean nextIsFileArgument() { 085 if (!shortOptionQueue.isEmpty() || pendingParam != null || argQueue.isEmpty()) { 086 return false; 087 } 088 return !argQueue.peek().startsWith("-"); 089 } 090 091 /** 092 * Returns whether the next token is available and can be used as a 093 * parameter to an option. 094 */ 095 public boolean nextIsParameter() { 096 if (!shortOptionQueue.isEmpty()) { 097 return false; 098 } 099 if (pendingParam != null) { 100 return true; 101 } 102 return !argQueue.isEmpty(); 103 } 104 105 /** Returns the next token as a plain string. */ 106 public String next() { 107 if (!shortOptionQueue.isEmpty()) { 108 return "-" + shortOptionQueue.poll(); 109 } 110 if (pendingParam != null) { 111 String result = pendingParam; 112 pendingParam = null; 113 return result; 114 } 115 return argQueue.poll(); 116 } 117 118 /** Returns the next token as a short option. */ 119 public char nextShortOption() { 120 if (!nextIsShortOption()) { 121 throw new IllegalStateException("No short option available!"); 122 } 123 if (shortOptionQueue.isEmpty()) { 124 String arg = argQueue.poll(); 125 for (int i = 1; i < arg.length(); ++i) { 126 shortOptionQueue.add(arg.charAt(i)); 127 } 128 } 129 return shortOptionQueue.poll(); 130 } 131 132 /** Returns the next token as a long option. */ 133 public String nextLongOption() { 134 if (!nextIsLongOption()) { 135 throw new IllegalStateException("No long option available!"); 136 } 137 String res = argQueue.poll().substring(2); 138 if (res.contains("=")) { 139 String[] parts = res.split("=", 2); 140 res = parts[0]; 141 pendingParam = parts[1]; 142 } 143 return res; 144 } 145}