@SuppressWarnings("unchecked")
@Test
public void testExec() throws Exception {

    addSchematron("iso19139");
    addSchematron("dublin-core");
    ServiceContext context = createServiceContext();
    loginAsAdmin(context);
    Element params = createParams();
    final SchematronCriteriaTypeService service = new SchematronCriteriaTypeService();
    Element results = service.exec(params, context);
    Element schemas = results.getChild("schemas");
    Element requirements = results.getChild("requirements");
    assertEquals(SchematronRequirement.values().length, requirements.getChildren().size());
    String json = Xml.getJSON(schemas);
    new JSON().parse(json);
    // no exception ??? good
    assertEqualsText("iso19139", schemas, "iso19139/name");
    String resultAsString = Xml.getString(schemas);
    // the number 4 can change depending on the definition of the iso19139 criteria definition.
    // It should normally be [the number of criteria in criteria-type.xml] + 2(ALL ways true and XPATH)
    assertEquals(resultAsString, 5, Xml.selectNumber(schemas, "count(iso19139/criteriaTypes/type)").intValue());
    assertEqualsText(XPATH.toString(), schemas, "iso19139/criteriaTypes/type[1]/type");
    assertEqualsText("Keyword", schemas, "iso19139/criteriaTypes/type[1]/name");
    assertEquals(resultAsString, 1, Xml.selectNumber(schemas, "count(iso19139/criteriaTypes/type[type = '" +
        ALWAYS_ACCEPT.name() + "'])").intValue());
    assertEquals(resultAsString, 0, Xml.selectNumber(schemas, "count(iso19139/criteriaTypes/type[type = '" +
        ALWAYS_ACCEPT.name() + "']/value)").intValue());
    assertTrue(resultAsString, 0 < Xml.selectNumber(schemas, "count(iso19139/criteriaTypes/type[type = '" +
        GROUP.name() + "'])").intValue());
    assertEquals(resultAsString, 1, Xml.selectNumber(schemas, "count(iso19139/criteriaTypes/type[upper-case(name) = '" +
        XPATH.name() + "'])").intValue());
    assertTrue(resultAsString, 0 < Xml.selectNumber(schemas, "count(iso19139/schematron)").intValue());
    assertEquals(resultAsString, 1, Xml.selectNumber(schemas, "count(iso19139/schematron[1]/file)").intValue());
    assertEquals(resultAsString, 1, Xml.selectNumber(schemas, "count(iso19139/schematron[1]/id)").intValue());
    assertEquals(resultAsString,
        Xml.selectNumber(schemas, "count(iso19139/schematron)").intValue(),
        Xml.selectNumber(schemas, "count(iso19139/schematron/title)").intValue());
    assertEquals(resultAsString, 1, Xml.selectNumber(schemas, "count(iso19139/schematron[1]/rulename)").intValue());
    assertTrue(resultAsString, 0 < Xml.selectNumber(schemas, "count(iso19139/schematron[1]/label)").intValue());
    assertEquals(resultAsString, 1, Xml.selectNumber(schemas, "count(iso19139/schematron[1]/schemaname)").intValue());
    assertEquals(resultAsString, 1, Xml.selectNumber(schemas, "count(iso19139/schematron[1]/groupCount)").intValue());
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    final List<Element> types = (List<Element>) Xml.selectNodes(schemas, "iso19139/criteriaTypes/type");
    for (Element type : types) {
        final Element typeahead = type.getChild("typeahead");
        if (typeahead != null) {
            final Element remote = typeahead.getChild("remote");
            if (remote != null) {
                checkForJSFunction(engine, remote, "selectRecordArray");
                checkForJSFunction(engine, remote, "selectLabelFunction");
                if (typeahead.getChild("selectTokensFunction") != null) {
                    checkForJSFunction(engine, remote, "selectTokensFunction");
                }
                checkForJSFunction(engine, remote, "selectValueFunction");
            } else {
                final Element values = typeahead.getChild("local");
                assertNotNull(values);
                assertTrue(values.getChildren().size() > 0);
                for (Object o : values.getChildren()) {
                    Element element = (Element) o;
                    assertNotNull(element.getChild("value"));
                    final Element tokens = element.getChild("tokens");
                    assertNotNull(tokens);
                }
            }
        }
    }
}