package net.sf.expectit; /* * #%L * ExpectIt * %% * Copyright (C) 2014 - 2015 Alexey Gavrilov and contributors * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import static net.sf.expectit.matcher.Matchers.anyOf; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import net.sf.expectit.interact.Action; import net.sf.expectit.interact.InteractBuilder; import net.sf.expectit.interact.OngoingResult; import net.sf.expectit.matcher.Matcher; import net.sf.expectit.matcher.SimpleResult; class InteractBuilderImpl implements InteractBuilder { private static final Logger LOG = Logger.getLogger(SingleInputExpect.class.getName()); private final AbstractExpectImpl expect; private final int input; private final List<Matcher<?>> matchers = new ArrayList<Matcher<?>>(); private final List<Action> actions = new ArrayList<Action>(); public InteractBuilderImpl(final AbstractExpectImpl expect, final int input) { this.expect = expect; this.input = input; } @Override public <R extends Result> OngoingResult<R> when(final Matcher<R> matcher) { return new OngoingResult<R>() { @Override public InteractBuilder then(final Action action) { if (action == null) { throw new NullPointerException("Action cannot be null"); } matchers.add(matcher); actions.add(action); return InteractBuilderImpl.this; } }; } @SuppressWarnings("unchecked") @Override public <R extends Result> R until(final Matcher<R> matcher) throws IOException { final Matcher<?>[] array = new Matcher[matchers.size() + 1]; for (int i = 0; i < matchers.size(); i++) { array[i + 1] = matchers.get(i); } array[0] = new ResultMatcher((Matcher<Result>) matcher); while (true) { final long time = System.currentTimeMillis(); final MultiResult multiResult = expect.expectIn(input, anyOf(array)); final String inputBuffer = expect.getInputs()[this.input].getBuffer().toString(); if (System.currentTimeMillis() - time > expect.getTimeout()) { LOG.fine("Until matching operation timeout"); return (R) SimpleResult.failure(inputBuffer, true); } final InternalResult untilResult = (InternalResult) multiResult.getResults().get(0); boolean matched = false; for (int i = 0; i < multiResult.getResults().size() - 1; i++) { final Result result = multiResult.getResults().get(i + 1); if (result.isSuccessful() && (!untilResult.isSuccessful() || untilResult.getResult().end() > result.end())) { matched = true; LOG.fine("Condition #" + i + " matched: " + result); actions.get(i).apply(result); } } if (!matched && untilResult.isSuccessful()) { LOG.fine("Until condition is successful"); return (R) untilResult.getResult(); } } } private static class InternalResult extends SimpleResult { private final Result result; public InternalResult(final Result result, final String input) { super( result.isSuccessful(), input, "", "", result.canStopMatching()); this.result = result; } public Result getResult() { return result; } } private static class ResultMatcher implements Matcher<Result> { private final Matcher<Result> matcher; public ResultMatcher(final Matcher<Result> matcher) { this.matcher = matcher; } @Override public Result matches(final String input, final boolean isEof) { final Result result = matcher.matches(input, isEof); return new InternalResult(result, input); } @Override public String toString() { return matcher.toString(); } } }