1 package org.objectweb.celtix.tools.common.toolspec.parser; 2 3 import java.util.StringTokenizer ; 4 import java.util.logging.Level ; 5 import java.util.logging.Logger ; 6 7 import org.w3c.dom.Element ; 8 import org.w3c.dom.NodeList ; 9 10 import org.objectweb.celtix.common.logging.LogUtils; 11 import org.objectweb.celtix.tools.common.toolspec.Tool; 12 13 public class Option implements TokenConsumer { 14 15 private static final Logger LOG = LogUtils.getL7dLogger(Option.class); 16 private static final String VALUE_ENUM_SEPARATOR = "|"; 17 protected Element argument; 18 protected Element annotation; 19 private final Element element; 20 private Element valueType; 21 22 private int numMatches; 23 24 public Option(Element el) { 25 this.element = el; 26 27 NodeList list = element.getElementsByTagNameNS(Tool.TOOL_SPEC_PUBLIC_ID, "associatedArgument"); 28 29 if (list != null && list.getLength() > 0) { 30 argument = (Element )list.item(0); 31 } 32 33 list = element.getElementsByTagNameNS(Tool.TOOL_SPEC_PUBLIC_ID, "annotation"); 34 if (list != null && list.getLength() > 0) { 35 annotation = (Element )list.item(0); 36 } 37 38 if (annotation == null && argument != null) { 39 list = argument.getElementsByTagNameNS(Tool.TOOL_SPEC_PUBLIC_ID, "annotation"); 40 if (list != null && list.getLength() > 0) { 41 annotation = (Element )list.item(0); 42 } 43 } 44 } 45 46 public boolean hasArgument() { 47 return argument != null; 48 } 49 50 public boolean hasImmediateArgument() { 51 return hasArgument() && "immediate".equals(argument.getAttribute("placement")); 52 } 53 54 57 public boolean accept(TokenInputStream args, Element result, ErrorVisitor errors) { 58 59 if (args.available() == 0) { 60 return false; 61 } 62 String arg = args.peek(); 63 64 if (arg == null) { 65 LOG.severe("ARGUMENT_IS_NULL_MSG"); 66 } 67 68 NodeList switches = element.getElementsByTagNameNS(Tool.TOOL_SPEC_PUBLIC_ID, "switch"); 70 71 boolean accepted = false; 72 73 for (int i = 0; i < switches.getLength(); i++) { 74 75 String switchArg = "-" + switches.item(i).getFirstChild().getNodeValue(); 76 if (LOG.isLoggable(Level.FINE)) { 77 LOG.fine("switchArg is " + switchArg); 78 } 79 if (hasImmediateArgument() ? arg.startsWith(switchArg) : arg.equals(switchArg)) { 80 LOG.fine("Matches a switch!!!"); 81 args.read(); 83 Element optionEl = result.getOwnerDocument() 85 .createElementNS("http://www.xsume.com/Xutil/Command", "option"); 86 87 optionEl.setAttribute("name", getName()); 88 89 if (hasArgument()) { 91 String argValue; 92 if (hasImmediateArgument()) { 93 argValue = arg.substring(switchArg.length()); 94 } else { 95 argValue = readArgumentValue(args, switchArg, errors); 96 } 97 if (argValue != null) { 98 if (LOG.isLoggable(Level.FINE)) { 99 LOG.fine("Setting argument value of option to " + argValue); 100 } 101 optionEl.appendChild(result.getOwnerDocument().createTextNode(argValue)); 102 103 } else { 104 break; 105 } 106 } 107 result.appendChild(optionEl); 108 numMatches++; 109 accepted = true; 110 } 111 } 112 return accepted; 113 } 114 115 private String readArgumentValue(TokenInputStream args, String switchArg, ErrorVisitor errors) { 116 String value = null; 117 if (args.available() > 0) { 118 value = args.read(); 119 if (value.startsWith("-")) { 120 errors.add(new ErrorVisitor.InvalidOption(switchArg)); 121 value = null; 122 } else if (hasInvalidCharacter(value)) { 123 errors.add(new ErrorVisitor.UserError(switchArg + " has invalid character!")); 124 } 125 if (!isInEnumArgumentValue(value)) { 126 errors.add(new ErrorVisitor.UserError(switchArg + " " 127 + value + " not in the enumeration value list!")); 128 } 129 } else { 130 errors.add(new ErrorVisitor.InvalidOption(switchArg)); 131 } 132 return value; 133 } 134 135 private boolean hasInvalidCharacter(String argValue) { 136 NodeList list = argument.getElementsByTagNameNS(Tool.TOOL_SPEC_PUBLIC_ID, "valuetype"); 137 String valuetypeStr = null; 138 139 if (list != null && list.getLength() > 0) { 140 valueType = (Element )list.item(0); 141 valuetypeStr = valueType.getFirstChild().getNodeValue(); 142 143 if ("IdentifyString".equals(valuetypeStr)) { 144 return !isIdentifyString(argValue); 145 } else if ("NamingSpacePackageString".equals(valuetypeStr)) { 146 return !isNamingSpacePackageString(argValue); 147 } else if ("Digital".equals(valuetypeStr)) { 148 for (int i = 0; i < argValue.length(); i++) { 149 if (!Character.isDigit(argValue.charAt(i))) { 150 return true; 151 } 152 } 153 } 154 } 155 return false; 156 } 157 158 private boolean isInEnumArgumentValue(String argValue) { 159 boolean result = true; 160 NodeList list = argument.getElementsByTagNameNS(Tool.TOOL_SPEC_PUBLIC_ID, "valueenum"); 161 if (list != null && list.getLength() == 1) { 162 result = false; 163 String enumValue = list.item(0).getTextContent(); 164 StringTokenizer stk = new StringTokenizer (enumValue, VALUE_ENUM_SEPARATOR); 165 if (stk.countTokens() <= 0) { 166 return result; 167 } 168 while (stk.hasMoreTokens()) { 169 if (argValue.equals(stk.nextToken())) { 170 result = true; 171 } 172 } 173 } 174 return result; 175 } 176 177 private boolean isIdentifyString(String value) { 178 for (int i = 0; i < value.length(); i++) { 179 if (value.charAt(i) == '.') { 180 continue; 181 } else { 182 if (!Character.isJavaIdentifierPart(value.charAt(i))) { 183 return false; 184 } 185 } 186 } 187 return true; 188 } 189 190 private boolean isNamingSpacePackageString(String value) { 191 if (value.indexOf("=") < 0) { 192 return isIdentifyString(value); 193 } else { 194 String packageName = value.substring(value.indexOf("=") + 1, value.length()); 195 return isIdentifyString(packageName); 196 } 197 } 198 199 200 public boolean isSatisfied(ErrorVisitor errors) { 201 if (errors.getErrors().size() > 0) { 202 return false; 203 } 204 if (LOG.isLoggable(Level.FINE)) { 205 LOG.fine("For this option, minOccurs=" + element.getAttribute("minOccurs") + " and maxOccurs=" 206 + element.getAttribute("maxOccurs") + ", numMatches currently " + numMatches); 207 } 208 boolean result = true; 209 210 if (!isAtleastMinimum()) { 211 errors.add(new ErrorVisitor.MissingOption(this)); 212 result = false; 213 } 214 if (result && !isNoGreaterThanMaximum()) { 215 errors.add(new ErrorVisitor.DuplicateOption(getName())); 216 result = false; 217 } 218 if (LOG.isLoggable(Level.FINE)) { 219 LOG.fine("isSatisfied() returning " + result); 220 } 221 return result; 222 } 223 224 private boolean isAtleastMinimum() { 225 boolean result = true; 226 int minOccurs = 0; 227 228 if (!"".equals(element.getAttribute("minOccurs"))) { 229 result = numMatches >= Integer.parseInt(element.getAttribute("minOccurs")); 230 } else { 231 result = numMatches >= minOccurs; 232 } 233 return result; 234 } 235 236 private boolean isNoGreaterThanMaximum() { 237 boolean result = true; 238 int maxOccurs = 1; 239 240 if (!"".equals(element.getAttribute("maxOccurs"))) { 241 result = "unbounded".equals(element.getAttribute("maxOccurs")) 242 || numMatches <= Integer.parseInt(element.getAttribute("maxOccurs")); 243 } else { 244 result = numMatches <= maxOccurs; 245 } 246 return result; 247 } 248 249 public String getName() { 250 return element.getAttribute("id"); 251 } 252 253 public String getAnnotation() { 254 return annotation.getFirstChild().getNodeValue(); 255 } 256 257 public String getPrimarySwitch() { 258 NodeList switches = element.getElementsByTagNameNS(Tool.TOOL_SPEC_PUBLIC_ID, "switch"); 259 260 return switches.item(0).getFirstChild().getNodeValue(); 263 } 264 265 public String toString() { 266 return getName(); 267 } 268 269 } 270 | Popular Tags |