### Question:
Rule { public boolean hasOptionals() { for(String item: rhs) if(isOptional(item)) return true; return false; } Rule(String lhs, StringTuple rhs);  Rule(String lhs, String rhs);  Rule(String lhs, String rhs, SemanticFunction semantics);  Rule(String lhs, StringTuple rhs, SemanticFunction semantics);  Rule(String lhs, String rhs, Map<String, Object> semantics);  Rule(String lhs, String rhs, String semantics); String getLHS(); StringTuple getRHS(); SemanticFunction getSemantics(); boolean isLexical(); boolean isUnary(); boolean isBinary(); boolean isCategorial(); boolean hasOptionals(); void validate(); boolean isCat(String label); boolean isOptional(String label); @Override String toString(); @Override boolean equals(Object o); @Override int hashCode();  }### Answer:
@Test void hasOptionals() { Rule r1 = new Rule("$A", "?B C"); Rule r2 = new Rule("$A", "B C ?$D"); Rule r3 = new Rule("$A", "?B"); Rule r4 = new Rule("$A", "$B $D"); assertTrue(r1.hasOptionals()); assertTrue(r2.hasOptionals()); assertTrue(r3.hasOptionals()); assertFalse(r4.hasOptionals()); }