Example usage for org.apache.commons.lang3 StringUtils countMatches

List of usage examples for org.apache.commons.lang3 StringUtils countMatches

Introduction

In this page you can find the example usage for org.apache.commons.lang3 StringUtils countMatches.

Prototype

public static int countMatches(final CharSequence str, final char ch) 

Source Link

Document

Counts how many times the char appears in the given string.

A null or empty ("") String input returns 0 .

 StringUtils.countMatches(null, *)       = 0 StringUtils.countMatches("", *)         = 0 StringUtils.countMatches("abba", 0)  = 0 StringUtils.countMatches("abba", 'a')   = 2 StringUtils.countMatches("abba", 'b')  = 2 StringUtils.countMatches("abba", 'x') = 0 

Usage

From source file:io.sugo.grok.api.Grok.java

/**
 * Compile the {@code Grok} pattern to named regex pattern.
 * // w  ww  .  j a  va  2  s .c o m
 * @param pattern : Grok pattern (ex: %{IP})
 * @param namedOnly : Whether to capture named expressions only or not (i.e. %{IP:ip} but not ${IP})
 * @throws GrokException runtime expt
  */
public void compile(String pattern, boolean namedOnly) throws GrokException {

    if (StringUtils.isBlank(pattern)) {
        throw new GrokException("{pattern} should not be empty or null");
    }

    namedRegex = pattern;
    originalGrokPattern = pattern;
    int index = 0;
    /** flag for infinite recurtion */
    int iterationLeft = 1000;
    Boolean continueIteration = true;

    // Replace %{foo} with the regex (mostly groupname regex)
    // and then compile the regex
    while (continueIteration) {
        continueIteration = false;
        if (iterationLeft <= 0) {
            throw new GrokException("Deep recursion pattern compilation of " + originalGrokPattern);
        }
        iterationLeft--;

        Matcher m = GrokUtils.GROK_PATTERN.matcher(namedRegex);
        // Match %{Foo:bar} -> pattern name and subname
        // Match %{Foo=regex} -> add new regex definition 
        if (m.find()) {
            continueIteration = true;
            Map<String, String> group = GrokUtils.namedGroups(m, m.group());
            if (group.get("definition") != null) {
                try {
                    addPattern(group.get("pattern"), group.get("definition"));
                    group.put("name", group.get("name") + "=" + group.get("definition"));
                } catch (GrokException e) {
                    // Log the exeception
                }
            }
            int count = StringUtils.countMatches(namedRegex, "%{" + group.get("name") + "}");
            for (int i = 0; i < count; i++) {
                String replacement = String.format("(?<name%d>%s)", index,
                        grokPatternDefinition.get(group.get("pattern")));
                if (namedOnly && group.get("subname") == null) {
                    replacement = grokPatternDefinition.get(group.get("pattern"));
                }
                namedRegexCollection.put("name" + index,
                        (group.get("subname") != null ? group.get("subname") : group.get("name")));
                namedRegex = StringUtils.replace(namedRegex, "%{" + group.get("name") + "}", replacement, 1);
                // System.out.println(_expanded_pattern);
                index++;
            }
        }
    }

    if (namedRegex.isEmpty()) {
        throw new GrokException("Pattern not fount");
    }
    // Compile the regex
    compiledNamedRegex = Pattern.compile(namedRegex);
}

From source file:com.seleniumtests.it.reporter.TestSeleniumTestsReporter2.java

/**
 * issue #148: Check that when test is retried and retry is OK, summary is correct
 * @throws Exception// ww  w. jav a 2  s.c  o m
 */
@Test(groups = { "it" })
public void testFailsOnlyOnceAndRetriedOk() throws Exception {

    StubTestClass.failed = false;

    // execute only the test that fails the first time it's executed
    executeSubTest(1, new String[] { "com.seleniumtests.it.stubclasses.StubTestClass" }, ParallelMode.METHODS,
            new String[] { "testWithExceptionOnFirstExec" });

    // check content of summary report file
    String mainReportContent = readSummaryFile();

    // only the last execution (ok) is shown
    Assert.assertEquals(StringUtils.countMatches(mainReportContent, ">testWithExceptionOnFirstExec</a>"), 1);
    Assert.assertFalse(mainReportContent.contains("<i class=\"fa fa-circle circleSkipped\">"));

    // check log contain the 2 executions
    String detailedReportContent1 = readTestMethodResultFile("testWithExceptionOnFirstExec");
    Assert.assertTrue(detailedReportContent1.contains("Test is KO with error: some exception"));
    Assert.assertTrue(detailedReportContent1.contains("Test is OK"));
}

From source file:de.micromata.genome.junittools.wicket.WicketTestBuilder.java

@Deprecated
public T validateLastRenderedResponseOccurrenceOfString(String searchString, int numberOfOccurrence) {
    validateEquals(numberOfOccurrence, StringUtils.countMatches(_getLastResponseAsString(), searchString));
    return (T) this;
}

From source file:com.francetelecom.clara.cloud.scalability.helper.ScalabilityHelper.java

private void logicalModelFactory(ApplicationRelease appRelease, String logicalModelPattern)
        throws ObjectNotFoundException, InvalidMavenReferenceException {
    String releaseName = appRelease.getUID();

    // CREATE SPRINGOO LOGICAL MODEL
    LogicalDeployment ld = manageLogicalDeployment
            .findLogicalDeployment(appRelease.getLogicalDeployment().getId());

    int nbGui = StringUtils.countMatches(logicalModelPattern, LETTER_GUI);
    int nbDB = StringUtils.countMatches(logicalModelPattern, LETTER_DATABASE);
    int nbStore = StringUtils.countMatches(logicalModelPattern, LETTER_STORE);
    int nbNode = StringUtils.countMatches(logicalModelPattern, LETTER_NODE);
    logger.debug("logicalModelFactory {} ", releaseName);
    Collection<LogicalWebGUIService> guis = new ArrayList<LogicalWebGUIService>();
    Collection<LogicalRelationalService> dbs = new ArrayList<LogicalRelationalService>();
    Collection<LogicalOnlineStorageService> stores = new ArrayList<LogicalOnlineStorageService>();
    Collection<ProcessingNode> nodes = new ArrayList<ProcessingNode>();

    for (int g = 0; g < nbGui; g++) {
        LogicalWebGUIService webGuiService = webGuiServiceFactory(releaseName + String.valueOf(g));
        ld.addLogicalService(webGuiService);
        guis.add(webGuiService);//from  ww w  . j a va  2  s  .c  o m
    }
    for (int d = 0; d < nbDB; d++) {
        LogicalRelationalService rdbService = relationalDBServiceFactory(releaseName + String.valueOf(d));
        ld.addLogicalService(rdbService);

        dbs.add(rdbService);
    }
    for (int s = 0; s < nbStore; s++) {
        LogicalOnlineStorageService onlineStorageService = onlineStorageServiceFactory(
                releaseName + String.valueOf(s));
        ld.addLogicalService(onlineStorageService);
        stores.add(onlineStorageService);
    }
    Iterator<LogicalWebGUIService> itGuis = guis.iterator();
    for (int n = 0; n < nbNode; n++) {
        LogicalWebGUIService gui = null;
        if (itGuis.hasNext()) {
            gui = itGuis.next();
        }
        ProcessingNode lenService = cfJavaProcessingFactory(ld, releaseName + "Node." + n, gui, dbs, stores);
        // ld.addExecutionNode(lenService);
        nodes.add(lenService);
    }

    logger.debug("updateLogicalDeployment {}", ld.getName());
    long start = System.currentTimeMillis();

    try {
        ld = manageLogicalDeployment.checkOverallConsistencyAndUpdateLogicalDeployment(ld);
    } catch (BusinessException e) {
        e.printStackTrace(); // To change body of catch statement use File |
                             // Settings | File Templates.
    }

    logger.debug("STATS updateLogicalDeployment duration: " + (System.currentTimeMillis() - start) + "ms");
}

From source file:forge.gui.ImportSourceAnalyzer.java

private void addDefaultPicNames(final PaperCard c, final boolean backFace) {
    final CardRules card = c.getRules();
    final String urls = card.getPictureUrl(backFace);
    if (StringUtils.isEmpty(urls)) {
        return;/* w ww  .j a  v  a2s  .com*/
    }

    final int numPics = 1 + StringUtils.countMatches(urls, "\\");
    if (c.getArtIndex() > numPics) {
        return;
    }

    final String filenameBase = ImageUtil.getImageKey(c, backFace, false);
    final String filename = filenameBase + ".jpg";
    final boolean alreadyHadIt = null != defaultPicNames.put(filename, filename);
    if (alreadyHadIt) {
        return;
    }

    // Do you shift artIndex by one here?
    final String newLastSymbol = 0 == c.getArtIndex() ? "" : String.valueOf(c.getArtIndex() /* + 1 */);
    final String oldFilename = oldCleanString(filenameBase.replaceAll("[0-9]?(\\.full)?$", "")) + newLastSymbol
            + ".jpg";
    //if ( numPics > 1 )
    //System.out.printf("Will move %s -> %s%n", oldFilename, filename);
    defaultPicOldNameToCurrentName.put(oldFilename, filename);
}

From source file:io.thekraken.grok.api.Grok.java

/**
 * Compile the {@code Grok} pattern to named regex pattern.
 * /*from  ww  w  .j a v a  2 s  .co m*/
 * @param pattern : Grok pattern (ex: %{IP})
 * @param namedOnly : Whether to capture named expressions only or not (i.e. %{IP:ip} but not ${IP})
 * @throws GrokException runtime expt
  */
public void compile(String pattern, boolean namedOnly) throws GrokException {

    if (StringUtils.isBlank(pattern)) {
        throw new GrokException("{pattern} should not be empty or null");
    }

    namedRegex = pattern;
    originalGrokPattern = pattern;
    int index = 0;
    /** flag for infinite recurtion */
    int iterationLeft = 1000;
    Boolean continueIteration = true;

    Matcher cm = GrokUtils.CUSTOM_PATTERN.matcher(namedRegex);

    while (cm.find()) {
        Map<String, String> group = GrokUtils.namedGroups(cm, cm.group());
        String customPattern = group.get("grok") == null ? group.get("custompattern")
                : grokPatternDefinition.get(group.get("grokpattern"));
        String replacement = String.format("(?<name%d>%s)", index, customPattern);
        namedRegexCollection.put("name" + index, group.get("customname"));
        namedRegex = StringUtils.replace(namedRegex, group.get("custom"), replacement, 1);
        index++;
    }

    // Replace %{foo} with the regex (mostly groupname regex)
    // and then compile the regex
    while (continueIteration) {
        continueIteration = false;
        if (iterationLeft <= 0) {
            throw new GrokException("Deep recursion pattern compilation of " + originalGrokPattern);
        }
        iterationLeft--;

        Matcher m = GrokUtils.GROK_PATTERN.matcher(namedRegex);
        // Match %{Foo:bar} -> pattern name and subname
        // Match %{Foo=regex} -> add new regex definition 
        if (m.find()) {
            continueIteration = true;
            Map<String, String> group = GrokUtils.namedGroups(m, m.group());
            if (group.get("definition") != null) {
                try {
                    addPattern(group.get("pattern"), group.get("definition"));
                    group.put("name", group.get("name") + "=" + group.get("definition"));
                } catch (GrokException e) {
                    // Log the exeception
                }
            }
            int count = StringUtils.countMatches(namedRegex, "%{" + group.get("name") + "}");
            for (int i = 0; i < count; i++) {
                String replacement = String.format("(?<name%d>%s)", index,
                        grokPatternDefinition.get(group.get("pattern")));
                if (namedOnly && group.get("subname") == null) {
                    replacement = grokPatternDefinition.get(group.get("pattern"));
                }
                namedRegexCollection.put("name" + index,
                        (group.get("subname") != null ? group.get("subname") : group.get("name")));
                namedRegex = StringUtils.replace(namedRegex, "%{" + group.get("name") + "}", replacement, 1);
                // System.out.println(_expanded_pattern);
                index++;
            }
        }
    }

    if (namedRegex.isEmpty()) {
        throw new GrokException("Pattern not fount");
    }
    // Compile the regex
    compiledNamedRegex = Pattern.compile(namedRegex);
}

From source file:info.pancancer.arch3.test.TestWorker.java

@Test
public void testWorker_endless() throws Exception {

    byte[] body = setupMessage();
    Delivery testDelivery = new Delivery(mockEnvelope, mockProperties, body);
    setupMockQueue(testDelivery);//  ww w  .  j  a  va  2  s.c  o m
    Mockito.when(Utilities.parseJSONStr(anyString())).thenCallRealMethod();
    Mockito.when(Utilities.parseConfig(anyString())).thenCallRealMethod();

    //Because the code that does cleanup in calls resultHandler.waitFor(); we need to actually execute something, even if it does nothing.
    Mockito.doNothing().when(mockExecutor).execute(any(CommandLine.class),
            any(DefaultExecuteResultHandler.class));

    // This is to mock the cleanup command - we don't really want to execute the command for deleting contents of /datastore, at least not when unit testing on a workstation!
    PowerMockito.whenNew(DefaultExecutor.class).withNoArguments().thenReturn(mockExecutor);

    Mockito.when(mockExecHandler.hasResult()).thenReturn(true);
    PowerMockito.whenNew(DefaultExecuteResultHandler.class).withNoArguments().thenReturn(mockExecHandler);

    final FutureTask<String> tester = new FutureTask<>(new Callable<String>() {
        @Override
        public String call() {
            LOG.debug("tester thread started");
            try {
                Worker.main(new String[] { "--config", "src/test/resources/workerConfig.ini", "--uuid",
                        "vm123456", "--endless", "--pidFile", "/var/run/arch3_worker.pid" });
            } catch (CancellationException | InterruptedException e) {
                LOG.error("Exception caught: " + e.getMessage());
                return e.getMessage();
            } catch (Exception e) {
                e.printStackTrace();
                fail("Unexpected exception");
                return null;
            } finally {
                Mockito.verify(mockAppender, Mockito.atLeastOnce()).doAppend(argCaptor.capture());
                String s = appendEventsIntoString(argCaptor.getAllValues());
                return s;
            }
        }

    });

    final Thread killer = new Thread(new Runnable() {

        @Override
        public void run() {
            LOG.debug("killer thread started");
            try {
                // The endless worker will not end on its own (because it's endless) so we need to wait a little bit (0.5 seconds) and
                // then kill it as if it were killed by the command-line script (kill_worker_daemon.sh).
                Thread.sleep(2500);
            } catch (InterruptedException e) {
                e.printStackTrace();
                LOG.error(e.getMessage());
            }
            tester.cancel(true);
        }
    });

    ExecutorService es = Executors.newFixedThreadPool(2);
    es.execute(tester);
    es.execute(killer);
    try {
        tester.get();
    } catch (CancellationException e) {
        Mockito.verify(mockAppender, Mockito.atLeastOnce()).doAppend(argCaptor.capture());
        List<LoggingEvent> tmpList = new LinkedList<>(argCaptor.getAllValues());
        String output = this.appendEventsIntoString(tmpList);
        assertTrue(output.contains("The \"--endless\" flag was set, this worker will run endlessly!"));

        int numJobsPulled = StringUtils.countMatches(output, " WORKER IS PREPARING TO PULL JOB FROM QUEUE ");

        LOG.info("Number of jobs attempted: " + numJobsPulled);
        assertTrue("number of jobs attempted > 1", numJobsPulled > 1);
    } catch (Exception e) {
        e.printStackTrace();
        fail();
    }
}

From source file:com.seleniumtests.it.reporter.TestReporterControler.java

/**
 * detailed report should contain only configuration steps corresponding to the test method / test class / test (TestNG test)
 * By default, test context contains all configuration methods. Check we filter them and we have only one configuration step even if it's retried
 * (case where test method fails and is retried, \@BeforeMethod is then called several times
 *///from ww w  . java  2 s. co m
@Test(groups = { "it" })
public void testReportDetailsOnlyTestConfigurationSteps() throws Exception {
    executeSubTest(1, new String[] { "com.seleniumtests.it.stubclasses.StubTestClass" }, ParallelMode.METHODS,
            new String[] { "testAndSubActions", "testInError", "testWithException" });

    String detailedReportContent = FileUtils
            .readFileToString(Paths.get(SeleniumTestsContextManager.getGlobalContext().getOutputDirectory(),
                    "testAndSubActions", "TestReport.html").toFile());
    detailedReportContent = detailedReportContent.replace("\n", "").replace("\r", "").replaceAll(">\\s+<",
            "><");

    Assert.assertEquals(StringUtils.countMatches(detailedReportContent, "</i></button> Pre test step: set -"),
            1);

    String detailedReportContent2 = FileUtils
            .readFileToString(Paths.get(SeleniumTestsContextManager.getGlobalContext().getOutputDirectory(),
                    "testInError", "TestReport.html").toFile());
    detailedReportContent2 = detailedReportContent2.replace("\n", "").replace("\r", "").replaceAll(">\\s+<",
            "><");

    Assert.assertEquals(StringUtils.countMatches(detailedReportContent2, "</i></button> Pre test step: set -"),
            1);

    // check that when test is KO, error cause is displayed
    Assert.assertTrue(detailedReportContent2.contains("[main] TestLogging: Test is KO with error: error"));

    String detailedReportContent3 = FileUtils
            .readFileToString(Paths.get(SeleniumTestsContextManager.getGlobalContext().getOutputDirectory(),
                    "testWithException", "TestReport.html").toFile());
    detailedReportContent3 = detailedReportContent3.replace("\n", "").replace("\r", "").replaceAll(">\\s+<",
            "><");

    Assert.assertEquals(StringUtils.countMatches(detailedReportContent3, "</i></button> Pre test step: set -"),
            1);
    Assert.assertEquals(
            StringUtils.countMatches(detailedReportContent3, "</i></button> Post test step: reset -"), 1);

    // in case of test method error, it is retried so each Before/After method is also replayed. Check it's the last one we have
    Assert.assertTrue(detailedReportContent3.contains("<div class=\"message-info\">before count: 2</div>"));
    Assert.assertTrue(detailedReportContent3.contains("<div class=\"message-info\">after count: 3</div>"));
}

From source file:com.moviejukebox.tools.StringTools.java

/**
 * Trim a string to the 'n'th occurrence of a space.
 *
 * @param sentanceToTrim/*from  ww w.j av a2 s . c  o m*/
 * @param numOfWords
 * @return
 */
public static String getWords(final String sentanceToTrim, int numOfWords) {
    String returnSentance = sentanceToTrim;
    // count the number of spaces in the original string
    int numSpaces = StringUtils.countMatches(sentanceToTrim, " ");
    LOG.trace("Found {} space(s) in '{}', want {} word(s).", numSpaces, sentanceToTrim, numOfWords);

    if (numSpaces > 0 && numSpaces >= numOfWords) {
        // ensure that the number of spaces is no larger than the count
        if (numSpaces > numOfWords) {
            LOG.trace("Number of spaces limited to {}", numOfWords);
            numSpaces = numOfWords;
        }

        int pos = -1;
        for (int i = 1; i <= numSpaces; i++) {
            pos = sentanceToTrim.indexOf(' ', pos + 1);
        }

        returnSentance = sentanceToTrim.substring(0, pos);
        LOG.trace("Final: '{}'", returnSentance);
    }

    return returnSentance;
}

From source file:io.bibleget.HTTPCaller.java

/**
 *
 * @param myQuery/*from w w  w  . j  ava  2  s  .  c  om*/
 * @param selectedVersions
 * @return
 * @throws java.lang.ClassNotFoundException
 * @throws java.io.UnsupportedEncodingException
 */
public boolean integrityCheck(String myQuery, List<String> selectedVersions)
        throws ClassNotFoundException, UnsupportedEncodingException {
    String versionsStr = StringUtils.join(selectedVersions.toArray(), ',');
    //System.out.println("Starting integrity check on query "+myQuery+" for versions: "+versionsStr);
    if (indexes == null) {
        indexes = Indexes.getInstance();
    }
    //build indexes based on versions

    //final result is true until proved false
    //set finFlag to false for non-breaking errors, or simply return false for breaking errors
    boolean finFlag = true;

    errorMessages.removeAll(errorMessages);
    List<String> queries = new ArrayList<>();

    //if english notation is found, translate to european notation
    if (myQuery.contains(":") && myQuery.contains(".")) {
        errorMessages.add(__(
                "Mixed notations have been detected. Please use either english notation or european notation."));
        return false;
    } else if (myQuery.contains(":")) {
        if (myQuery.contains(",")) {
            myQuery = myQuery.replace(",", ".");
        }
        myQuery = myQuery.replace(":", ",");
    }

    if (myQuery.isEmpty() == false) {
        if (myQuery.contains(";")) {
            //System.out.println("We have a semicolon");
            queries.addAll(Arrays.asList(myQuery.split(";")));
            for (Iterator<String> it = queries.iterator(); it.hasNext();) {
                if (it.next().isEmpty()) {
                    it.remove(); // NOTE: Iterator's remove method, not ArrayList's, is used.
                }
            }
        } else {
            //System.out.println("There is no semicolon");
            queries.add(myQuery);
        }
    }

    boolean first = true;
    String currBook = "";

    if (queries.isEmpty()) {
        errorMessages.add(__("You cannot send an empty query."));
        return false;
    }
    for (String querie : queries) {
        //System.out.println(querie);
        querie = toProperCase(querie);
        //System.out.println(querie);

        //RULE 1: at least the first query must have a book indicator
        if (first) {
            if (querie.matches("^[1-3]{0,1}((\\p{L}\\p{M}*)+)(.*)") == false) {
                errorMessages.add(MessageFormat.format(__(
                        "The first query <{0}> in the querystring <{1}> must start with a valid book indicator!"),
                        querie, myQuery));
                finFlag = false;
            }
            first = false;
        }

        //RULE 2: for every query that starts with a book indicator, 
        //        the book indicator must be followed by valid chapter indicator;
        //        else query must start with valid chapter indicator
        int bBooksContains;
        int myidx = -1;
        String tempBook = "";
        if (querie.matches("^[1-3]{0,1}((\\p{L}\\p{M}*)+)(.*)") == true) {
            //while we're at it, let's capture the book value from the query
            Pattern pattern = Pattern.compile("^[1-3]{0,1}((\\p{L}\\p{M}*)+)", Pattern.UNICODE_CHARACTER_CLASS);
            Matcher matcher = pattern.matcher(querie);
            if (matcher.find()) {
                tempBook = matcher.group();
                bBooksContains = isValidBook(tempBook);
                myidx = bBooksContains + 1;
                //if(bBooksContains == false && bBooksAbbrevsContains == false){
                if (bBooksContains == -1) {
                    errorMessages.add(MessageFormat.format(__(
                            "The book indicator <{0}> in the query <{1}> is not valid. Please check the documentation for a list of valid book indicators."),
                            tempBook, querie));
                    finFlag = false;
                } else {
                    //if(bBooksContains)
                    currBook = tempBook;
                    //querie = querie.replace(tempBook,"");
                }
            }

            Pattern pattern1 = Pattern.compile("^[1-3]{0,1}((\\p{L}\\p{M}*)+)",
                    Pattern.UNICODE_CHARACTER_CLASS);
            Pattern pattern2 = Pattern.compile("^[1-3]{0,1}((\\p{L}\\p{M}*)+)[1-9][0-9]{0,2}",
                    Pattern.UNICODE_CHARACTER_CLASS);
            Matcher matcher1 = pattern1.matcher(querie);
            Matcher matcher2 = pattern2.matcher(querie);
            int count1 = 0;
            while (matcher1.find()) {
                count1++;
            }
            int count2 = 0;
            while (matcher2.find()) {
                count2++;
            }
            if (querie.matches("^[1-3]{0,1}((\\p{L}\\p{M}*)+)[1-9][0-9]{0,2}(.*)") == false
                    || count1 != count2) {
                errorMessages.add(__("You must have a valid chapter following the book indicator!"));
                finFlag = false;
            }
            querie = querie.replace(tempBook, "");
        } else {
            if (querie.matches("^[1-9][0-9]{0,2}(.*)") == false) {
                errorMessages.add(__(
                        "A query that doesn't start with a book indicator must however start with a valid chapter indicator!"));
                finFlag = false;
            }
        }

        //RULE 3: Queries with a dot operator must first have a comma operator; and cannot have more commas than dots
        if (querie.contains(".")) {
            Pattern pattern11 = Pattern.compile("[,|\\-|\\.][1-9][0-9]{0,2}\\.");
            Matcher matcher11 = pattern11.matcher(querie);
            if (querie.contains(",") == false || matcher11.find() == false) {
                errorMessages.add(__(
                        "You cannot use a dot without first using a comma or a dash. A dot is a liason between verses, which are separated from the chapter by a comma."));
                finFlag = false;
            }
            Pattern pattern3 = Pattern.compile("(?<![0-9])(?=(([1-9][0-9]{0,2})\\.([1-9][0-9]{0,2})))");
            Matcher matcher3 = pattern3.matcher(querie);
            int count = 0;
            while (matcher3.find()) {
                //RULE 4: verse numbers around dot operators must be sequential
                if (Integer.parseInt(matcher3.group(2)) >= Integer.parseInt(matcher3.group(3))) {
                    errorMessages.add(MessageFormat.format(__(
                            "Verses concatenated by a dot must be consecutive, instead <{0}> is greater than or equal to <{1}> in the expression <{2}> in the query <{3}>"),
                            matcher3.group(2), matcher3.group(3), matcher3.group(1), querie));
                    finFlag = false;
                }
                count++;
            }
            //RULE 5: Dot operators must be preceded and followed by a number from one to three digits, of which the first digit cannot be a 0
            if (count == 0 || count != StringUtils.countMatches(querie, ".")) {
                errorMessages.add(__(
                        "A dot must be preceded and followed by 1 to 3 digits of which the first digit cannot be zero.")
                        + " <" + querie + ">");
                finFlag = false;
            }
        }

        //RULE 6: Comma operators must be preceded and followed by a number from one to three digits, of which the first digit cannot be 0
        if (querie.contains(",")) {

            Pattern pattern4 = Pattern.compile("([1-9][0-9]{0,2})\\,[1-9][0-9]{0,2}");
            Matcher matcher4 = pattern4.matcher(querie);
            int count = 0;
            List<Integer> chapters = new ArrayList<>();
            while (matcher4.find()) {
                //System.out.println("group0="+matcher4.group(0)+", group1="+matcher4.group(1));
                chapters.add(Integer.parseInt(matcher4.group(1)));
                count++;
            }
            if (count == 0 || count != StringUtils.countMatches(querie, ",")) {
                errorMessages.add(__(
                        "A comma must be preceded and followed by 1 to 3 digits of which the first digit cannot be zero.")
                        + " <" + querie + ">" + "(count=" + Integer.toString(count) + ",comma count="
                        + StringUtils.countMatches(querie, ",") + "); chapters=" + chapters.toString());
                finFlag = false;
            } else {
                // let's check the validity of the chapter numbers against the version indexes
                //for each chapter captured in the querystring
                for (int chapter : chapters) {
                    if (indexes.isValidChapter(chapter, myidx, selectedVersions) == false) {
                        int[] chapterLimit = indexes.getChapterLimit(myidx, selectedVersions);
                        errorMessages.add(MessageFormat.format(__(
                                "A chapter in the query is out of bounds: there is no chapter <{0}> in the book <{1}> in the requested version <{2}>, the last possible chapter is <{3}>"),
                                Integer.toString(chapter), currBook, StringUtils.join(selectedVersions, ","),
                                StringUtils.join(chapterLimit, ',')));
                        finFlag = false;
                    }
                }
            }
        }

        if (StringUtils.countMatches(querie, ",") > 1) {
            if (!querie.contains("-")) {
                errorMessages.add(__("You cannot have more than one comma and not have a dash!"));
                finFlag = false;
            }
            String[] parts = StringUtils.split(querie, "-");
            if (parts.length != 2) {
                errorMessages
                        .add(__("You seem to have a malformed querystring, there should be only one dash."));
                finFlag = false;
            }
            for (String p : parts) {
                Integer[] pp = new Integer[2];
                String[] tt = StringUtils.split(p, ",");
                int x = 0;
                for (String t : tt) {
                    pp[x++] = Integer.parseInt(t);
                }
                if (indexes.isValidChapter(pp[0], myidx, selectedVersions) == false) {
                    int[] chapterLimit;
                    chapterLimit = indexes.getChapterLimit(myidx, selectedVersions);
                    //                        System.out.print("chapterLimit = ");
                    //                        System.out.println(Arrays.toString(chapterLimit));
                    errorMessages.add(MessageFormat.format(__(
                            "A chapter in the query is out of bounds: there is no chapter <{0}> in the book <{1}> in the requested version <{2}>, the last possible chapter is <{3}>"),
                            Integer.toString(pp[0]), currBook, StringUtils.join(selectedVersions, ","),
                            StringUtils.join(chapterLimit, ',')));
                    finFlag = false;
                } else {
                    if (indexes.isValidVerse(pp[1], pp[0], myidx, selectedVersions) == false) {
                        int[] verseLimit = indexes.getVerseLimit(pp[0], myidx, selectedVersions);
                        //                            System.out.print("verseLimit = ");
                        //                            System.out.println(Arrays.toString(verseLimit));
                        errorMessages.add(MessageFormat.format(__(
                                "A verse in the query is out of bounds: there is no verse <{0}> in the book <{1}> at chapter <{2}> in the requested version <{3}>, the last possible verse is <{4}>"),
                                Integer.toString(pp[1]), currBook, Integer.toString(pp[0]),
                                StringUtils.join(selectedVersions, ","), StringUtils.join(verseLimit, ',')));
                        finFlag = false;
                    }
                }
            }
        } else if (StringUtils.countMatches(querie, ",") == 1) {
            String[] parts = StringUtils.split(querie, ",");
            //System.out.println(Arrays.toString(parts));
            if (indexes.isValidChapter(Integer.parseInt(parts[0]), myidx, selectedVersions) == false) {
                int[] chapterLimit = indexes.getChapterLimit(myidx, selectedVersions);
                errorMessages.add(MessageFormat.format(__(
                        "A chapter in the query is out of bounds: there is no chapter <{0}> in the book <{1}> in the requested version <{2}>, the last possible chapter is <{3}>"),
                        parts[0], currBook, StringUtils.join(selectedVersions, ","),
                        StringUtils.join(chapterLimit, ',')));
                finFlag = false;
            } else {
                if (parts[1].contains("-")) {
                    Deque<Integer> highverses = new ArrayDeque<>();
                    Pattern pattern11 = Pattern.compile("[,\\.][1-9][0-9]{0,2}\\-([1-9][0-9]{0,2})");
                    Matcher matcher11 = pattern11.matcher(querie);
                    while (matcher11.find()) {
                        highverses.push(Integer.parseInt(matcher11.group(1)));
                    }
                    int highverse = highverses.pop();
                    if (indexes.isValidVerse(highverse, Integer.parseInt(parts[0]), myidx,
                            selectedVersions) == false) {
                        int[] verseLimit = indexes.getVerseLimit(Integer.parseInt(parts[0]), myidx,
                                selectedVersions);
                        errorMessages.add(MessageFormat.format(__(
                                "A verse in the query is out of bounds: there is no verse <{0}> in the book <{1}> at chapter <{2}> in the requested version <{3}>, the last possible verse is <{4}>"),
                                highverse, currBook, parts[0], StringUtils.join(selectedVersions, ","),
                                StringUtils.join(verseLimit, ',')));
                        finFlag = false;
                    }
                } else {
                    Pattern pattern12 = Pattern.compile(",([1-9][0-9]{0,2})");
                    Matcher matcher12 = pattern12.matcher(querie);
                    int highverse = -1;
                    while (matcher12.find()) {
                        highverse = Integer.parseInt(matcher12.group(1));
                        //System.out.println("[line 376]:highverse="+Integer.toString(highverse));
                    }
                    if (highverse != -1) {
                        //System.out.println("Checking verse validity for book "+myidx+" chapter "+parts[0]+"...");
                        if (indexes.isValidVerse(highverse, Integer.parseInt(parts[0]), myidx,
                                selectedVersions) == false) {
                            int[] verseLimit = indexes.getVerseLimit(Integer.parseInt(parts[0]), myidx,
                                    selectedVersions);
                            errorMessages.add(MessageFormat.format(__(
                                    "A verse in the query is out of bounds: there is no verse <{0}> in the book <{1}> at chapter <{2}> in the requested version <{3}>, the last possible verse is <{4}>"),
                                    highverse, currBook, parts[0], StringUtils.join(selectedVersions, ","),
                                    StringUtils.join(verseLimit, ',')));
                            finFlag = false;
                        }
                    }
                }
                Pattern pattern13 = Pattern.compile("\\.([1-9][0-9]{0,2})$");
                Matcher matcher13 = pattern13.matcher(querie);
                int highverse = -1;
                while (matcher13.find()) {
                    highverse = Integer.parseInt(matcher13.group(1));
                }
                if (highverse != -1) {
                    if (indexes.isValidVerse(highverse, Integer.parseInt(parts[0]), myidx,
                            selectedVersions) == false) {
                        int[] verseLimit = indexes.getVerseLimit(Integer.parseInt(parts[0]), myidx,
                                selectedVersions);
                        errorMessages.add(MessageFormat.format(__(
                                "A verse in the query is out of bounds: there is no verse <{0}> in the book <{1}> at chapter <{2}> in the requested version <{3}>, the last possible verse is <{4}>"),
                                highverse, currBook, parts[0], StringUtils.join(selectedVersions, ","),
                                StringUtils.join(verseLimit, ',')));
                        finFlag = false;
                    }
                }
            }
        } else { //if there is no comma, it's either a single chapter or an extension of chapters with a dash
                 //System.out.println("no comma found");
            String[] parts = StringUtils.split(querie, "-");
            //System.out.println(Arrays.toString(parts));
            int highchapter = Integer.parseInt(parts[parts.length - 1]);
            if (indexes.isValidChapter(highchapter, myidx, selectedVersions) == false) {
                int[] chapterLimit = indexes.getChapterLimit(myidx, selectedVersions);
                errorMessages.add(MessageFormat.format(__(
                        "A chapter in the query is out of bounds: there is no chapter <{0}> in the book <{1}> in the requested version <{2}>, the last possible chapter is <{3}>"),
                        Integer.toString(highchapter), currBook, StringUtils.join(selectedVersions, ","),
                        StringUtils.join(chapterLimit, ',')));
                finFlag = false;
            }
        }

        if (querie.contains("-")) {
            //RULE 7: If there are multiple dashes in a query, there cannot be more dashes than there are dots minus 1
            int dashcount = StringUtils.countMatches(querie, "-");
            int dotcount = StringUtils.countMatches(querie, ".");
            if (dashcount > 1) {
                if (dashcount - 1 > dotcount) {
                    errorMessages.add(__(
                            "There are multiple dashes in the query, but there are not enough dots. There can only be one more dash than dots.")
                            + " <" + querie + ">");
                    finFlag = false;
                }
            }

            //RULE 8: Dash operators must be preceded and followed by a number from one to three digits, of which the first digit cannot be 0
            Pattern pattern5 = Pattern.compile("([1-9][0-9]{0,2}\\-[1-9][0-9]{0,2})");
            Matcher matcher5 = pattern5.matcher(querie);
            int count = 0;
            while (matcher5.find()) {
                count++;
            }
            if (count == 0 || count != StringUtils.countMatches(querie, "-")) {
                errorMessages.add(__(
                        "A dash must be preceded and followed by 1 to 3 digits of which the first digit cannot be zero.")
                        + " <" + querie + ">");
                finFlag = false;
            }

            //RULE 9: If a comma construct follows a dash, there must also be a comma construct preceding the dash
            Pattern pattern6 = Pattern.compile("\\-([1-9][0-9]{0,2})\\,");
            Matcher matcher6 = pattern6.matcher(querie);
            if (matcher6.find()) {
                Pattern pattern7 = Pattern.compile("\\,[1-9][0-9]{0,2}\\-");
                Matcher matcher7 = pattern7.matcher(querie);
                if (matcher7.find() == false) {
                    errorMessages.add(__(
                            "If there is a chapter-verse construct following a dash, there must also be a chapter-verse construct preceding the same dash.")
                            + " <" + querie + ">");
                    finFlag = false;
                } else {
                    //RULE 10: Chapters before and after dashes must be sequential
                    int chap1 = -1;
                    int chap2 = -1;

                    Pattern pattern8 = Pattern.compile("([1-9][0-9]{0,2})\\,[1-9][0-9]{0,2}\\-");
                    Matcher matcher8 = pattern8.matcher(querie);
                    if (matcher8.find()) {
                        chap1 = Integer.parseInt(matcher8.group(1));
                    }
                    Pattern pattern9 = Pattern.compile("\\-([1-9][0-9]{0,2})\\,");
                    Matcher matcher9 = pattern9.matcher(querie);
                    if (matcher9.find()) {
                        chap2 = Integer.parseInt(matcher9.group(1));
                    }

                    if (chap1 >= chap2) {
                        errorMessages.add(MessageFormat.format(__(
                                "Chapters must be consecutive. Instead the first chapter indicator <{0}> is greater than or equal to the second chapter indicator <{1}> in the expression <{2}>"),
                                chap1, chap2, querie));
                        finFlag = false;
                    }
                }
            } else {
                //if there are no comma constructs immediately following the dash
                //RULE 11: Verses (or chapters if applicable) around each of the dash operator(s) must be sequential
                Pattern pattern10 = Pattern.compile("([1-9][0-9]{0,2})\\-([1-9][0-9]{0,2})");
                Matcher matcher10 = pattern10.matcher(querie);
                while (matcher10.find()) {
                    int num1 = Integer.parseInt(matcher10.group(1));
                    int num2 = Integer.parseInt(matcher10.group(2));
                    if (num1 >= num2) {
                        errorMessages.add(MessageFormat.format(__(
                                "Verses (or chapters if applicable) around the dash operator must be consecutive. Instead <{0}> is greater than or equal to <{1}> in the expression <{2}>"),
                                num1, num2, querie));
                        finFlag = false;
                    }
                }

            }
        }

    }

    return finFlag;
}