DynamicSpec { public static DynamicSpec[] parseRules(final String rule) { final String[] rules = rule.trim().split(";"); final DynamicSpec[] specs = new DynamicSpec[rules.length]; for (int i = 0; i < rules.length; ++i) { final String[] classNameMethodSpec = rules[i].split("#"); if (classNameMethodSpec.length != 2) throw error(rules[i]); final boolean polymorphic = classNameMethodSpec[0].startsWith("^"); if (polymorphic) classNameMethodSpec[0] = classNameMethodSpec[0].substring(1).trim(); trim(classNameMethodSpec); final String className = classNameMethodSpec[0]; if (className.isEmpty()) throw error(rules[i]); final String returning; final int col = classNameMethodSpec[1].indexOf(':'); if (col == -1) { returning = null; } else { if (classNameMethodSpec[1].endsWith(":")) throw error(rules[i]); returning = classNameMethodSpec[1].substring(col + 1).trim(); if (returning.isEmpty() || returning.contains(":")) throw error(rules[i]); classNameMethodSpec[1] = classNameMethodSpec[1].substring(0, col).trim(); } final String methodName; final String[] args; final int start = classNameMethodSpec[1].indexOf('('); if (start == -1) { methodName = classNameMethodSpec[1]; args = null; } else { final int end = classNameMethodSpec[1].indexOf(')', start + 1); if (end == -1) throw error(rules[i]); args = start + 1 == end ? empty : classNameMethodSpec[1].substring(start + 1, end).split(","); trim(args); methodName = classNameMethodSpec[1].substring(0, start).trim(); } if (methodName.isEmpty() || ("<init>".equals(methodName) && returning != null) || ("<clinit>".equals(methodName) && (args != null || returning != null))) throw error(rules[i]); specs[i] = new DynamicSpec(polymorphic, className, methodName, args, returning); } return specs; } private  DynamicSpec(final boolean polymorphic, final String className, final String methodName, final String[] args, final String returning); static DynamicSpec[] parseRules(final String rule); final boolean polymorphic; final String className; final String methodName; final String[] args; final String returning; }
@Test public void testErrors() { try { DynamicSpec.parseRules(null); fail("Expected NullPointerException"); } catch (final NullPointerException e) { } try { DynamicSpec.parseRules(""); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("#toString:java.lang.String"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object#"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object#:java.lang.String"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object#toString()::"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object#():java.lang.String"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object#toString():java.lang.String:"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object#wait():<void>:~java.lang.Exception"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object#<init>():<void>"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object#<clinit>():<void>"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } try { DynamicSpec.parseRules("java.lang.Object#<clinit>()"); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { } }