Checks the syntax of the specified command. Returns an error with the expected syntax if the check fails. The passed on strings describe the arguments of a command. They may be: attribute names labels for text nodes if prefixed with "#" labels for text or descenda
(final XNode root, final String... checks)
| 252 | * @throws QueryException query exception |
| 253 | */ |
| 254 | private boolean check(final XNode root, final String... checks) throws QueryException { |
| 255 | // prepare validating query |
| 256 | final TokenList mand = new TokenList(), opt = new TokenList(); |
| 257 | String t = null; |
| 258 | boolean ot = true; |
| 259 | boolean n = false; |
| 260 | for(String check : checks) { |
| 261 | final boolean o = Strings.endsWith(check, '?'); |
| 262 | check = check.replace("?", ""); |
| 263 | if(!check.isEmpty() && !Character.isLetter(check.charAt(0))) { |
| 264 | // textual contents |
| 265 | t = check.substring(1); |
| 266 | ot = o; |
| 267 | n = check.charAt(0) == '<'; |
| 268 | } else { |
| 269 | (o ? opt : mand).add(check); |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | // build validating query |
| 274 | final TokenBuilder tb = new TokenBuilder(); |
| 275 | tb.add("declare variable $A external;"); |
| 276 | tb.add("declare variable $O external;"); |
| 277 | tb.add("."); |
| 278 | // check existence of mandatory attributes |
| 279 | tb.add("[every $e in $A satisfies @*/name() = $e]"); |
| 280 | // check existence of unknown attributes |
| 281 | tb.add("[every $e in @* satisfies $e/name() = ($A, $O)]"); |
| 282 | // ensure that all values are non-empty |
| 283 | tb.add("[every $e in @* satisfies data($e)]"); |
| 284 | if(t == null) { |
| 285 | // ensure that no children exist |
| 286 | tb.add("[not(node())]"); |
| 287 | } else if(!ot) { |
| 288 | // ensure that children exist |
| 289 | tb.add("[node()]"); |
| 290 | if(!n) tb.add("[not(*)]"); |
| 291 | } |
| 292 | |
| 293 | // run query |
| 294 | try(QueryProcessor qp = new QueryProcessor(tb.toString(), ctx).context(root)) { |
| 295 | qp.variable("A", StrSeq.get(mand.toArray())).variable("O", StrSeq.get(opt.toArray())); |
| 296 | if(!qp.value().isEmpty()) return true; |
| 297 | } |
| 298 | // build error string |
| 299 | final TokenBuilder syntax = new TokenBuilder(); |
| 300 | final byte[] nm = root.qname().string(); |
| 301 | syntax.reset().add('<').add(nm); |
| 302 | for(final byte[] m : mand) syntax.add(' ').add(m).add("=\"...\""); |
| 303 | for(final byte[] o : opt) syntax.add(" (").add(o).add("=\"...\")"); |
| 304 | if(t != null) { |
| 305 | syntax.add('>'); |
| 306 | if(ot) syntax.add('('); |
| 307 | syntax.add('[').add(t).add(']'); |
| 308 | if(ot) syntax.add(')'); |
| 309 | syntax.add("</").add(nm).add('>'); |
| 310 | } else { |
| 311 | syntax.add("/>"); |
no test coverage detected