<commit_before>/**
 * Copyright (C) 2015 TeeTime (http://teetime.sourceforge.net)
 *
 * 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.
 */
package teetime.framework;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import teetime.framework.exceptionHandling.IgnoringStageListener;
import teetime.framework.exceptionHandling.StageExceptionHandler;
import teetime.framework.signal.ValidatingSignal;
import teetime.framework.validation.AnalysisNotValidException;
import teetime.util.Pair;

/**
 * Represents an Analysis to which stages can be added and executed later.
 * This needs a {@link AnalysisConfiguration},
 * in which the adding and configuring of stages takes place.
 * To start the analysis {@link #execute()} needs to be executed.
 * This class will automatically create threads and join them without any further commitment.
 */
public final class Analysis implements UncaughtExceptionHandler {

	private static final Logger LOGGER = LoggerFactory.getLogger(Analysis.class);

	private final AnalysisConfiguration configuration;

	private final Class<? extends teetime.framework.exceptionHandling.StageExceptionHandler> listener;

	private boolean executionInterrupted = false;

	private final List<Thread> consumerThreads = new LinkedList<Thread>();
	private final List<Thread> finiteProducerThreads = new LinkedList<Thread>();
	private final List<Thread> infiniteProducerThreads = new LinkedList<Thread>();

	private final Collection<Pair<Thread, Throwable>> exceptions = new ConcurrentLinkedQueue<Pair<Thread, Throwable>>();

	private boolean initialized;

	/**
	 * Creates a new {@link Analysis} that skips validating the port connections and uses the default listener.
	 *
	 * @param configuration
	 *            to be used for the analysis
	 */
	public Analysis(final AnalysisConfiguration configuration) {
		this(configuration, false, IgnoringStageListener.class);
	}

	@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
	// TODO remove @SuppressWarnings if init is no longer deprecated
	public Analysis(final AnalysisConfiguration configuration, final boolean validationEnabled) {
		this(configuration, validationEnabled, IgnoringStageListener.class);
	}

	/**
	 * Creates a new {@link Analysis} that skips validating the port connections and uses a specific listener.
	 *
	 * @param configuration
	 *            to be used for the analysis
	 * @param listener
	 *            specific listener for the exception handling
	 */
	public Analysis(final AnalysisConfiguration configuration, final Class<? extends StageExceptionHandler> listener) {
		this(configuration, false, listener);
	}

	public Analysis(final AnalysisConfiguration configuration, final boolean validationEnabled, final Class<? extends StageExceptionHandler> listener) {
		this.configuration = configuration;
		this.listener = listener;
		if (validationEnabled) {
			validateStages();
		}
		init();
	}

	private void validateStages() {
		// BETTER validate concurrently
		final List<Stage> threadableStageJobs = this.configuration.getThreadableStageJobs();
		for (Stage stage : threadableStageJobs) {
			// // portConnectionValidator.validate(stage);
			// }

			final ValidatingSignal validatingSignal = new ValidatingSignal();
			stage.onSignal(validatingSignal, null);
			if (validatingSignal.getInvalidPortConnections().size() > 0) {
				throw new AnalysisNotValidException(validatingSignal.getInvalidPortConnections());
			}
		}
	}

	/**
	 * This initializes Analysis and needs to be run right before starting it.
	 *
	 * @deprecated since 1.1
	 */
	@Deprecated
	public final void init() {
		if (initialized) {
			return;
		}
		initialized = true;

		final List<Stage> threadableStageJobs = this.configuration.getThreadableStageJobs();
		for (Stage stage : threadableStageJobs) {
			StageExceptionHandler newListener;
			try {
				newListener = listener.newInstance();
			} catch (InstantiationException e) {
				throw new IllegalStateException(e);
			} catch (IllegalAccessException e) {
				throw new IllegalStateException(e);
			}
			switch (stage.getTerminationStrategy()) {
			case BY_SIGNAL: {
				final Thread thread = new Thread(new RunnableConsumerStage(stage, newListener));
				stage.setOwningThread(thread);
				this.consumerThreads.add(thread);
				break;
			}<commit_msg>added exception, if there are no threadable stages<commit_after>/**
 * Copyright (C) 2015 TeeTime (http://teetime.sourceforge.net)
 *
 * 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.
 */
package teetime.framework;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import teetime.framework.exceptionHandling.IgnoringStageListener;
import teetime.framework.exceptionHandling.StageExceptionHandler;
import teetime.framework.signal.ValidatingSignal;
import teetime.framework.validation.AnalysisNotValidException;
import teetime.util.Pair;

/**
 * Represents an Analysis to which stages can be added and executed later.
 * This needs a {@link AnalysisConfiguration},
 * in which the adding and configuring of stages takes place.
 * To start the analysis {@link #execute()} needs to be executed.
 * This class will automatically create threads and join them without any further commitment.
 */
public final class Analysis implements UncaughtExceptionHandler {

	private static final Logger LOGGER = LoggerFactory.getLogger(Analysis.class);

	private final AnalysisConfiguration configuration;

	private final Class<? extends teetime.framework.exceptionHandling.StageExceptionHandler> listener;

	private boolean executionInterrupted = false;

	private final List<Thread> consumerThreads = new LinkedList<Thread>();
	private final List<Thread> finiteProducerThreads = new LinkedList<Thread>();
	private final List<Thread> infiniteProducerThreads = new LinkedList<Thread>();

	private final Collection<Pair<Thread, Throwable>> exceptions = new ConcurrentLinkedQueue<Pair<Thread, Throwable>>();

	private boolean initialized;

	/**
	 * Creates a new {@link Analysis} that skips validating the port connections and uses the default listener.
	 *
	 * @param configuration
	 *            to be used for the analysis
	 */
	public Analysis(final AnalysisConfiguration configuration) {
		this(configuration, false, IgnoringStageListener.class);
	}

	@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
	// TODO remove @SuppressWarnings if init is no longer deprecated
	public Analysis(final AnalysisConfiguration configuration, final boolean validationEnabled) {
		this(configuration, validationEnabled, IgnoringStageListener.class);
	}

	/**
	 * Creates a new {@link Analysis} that skips validating the port connections and uses a specific listener.
	 *
	 * @param configuration
	 *            to be used for the analysis
	 * @param listener
	 *            specific listener for the exception handling
	 */
	public Analysis(final AnalysisConfiguration configuration, final Class<? extends StageExceptionHandler> listener) {
		this(configuration, false, listener);
	}

	public Analysis(final AnalysisConfiguration configuration, final boolean validationEnabled, final Class<? extends StageExceptionHandler> listener) {
		this.configuration = configuration;
		this.listener = listener;
		if (validationEnabled) {
			validateStages();
		}
		init();
	}

	private void validateStages() {
		// BETTER validate concurrently
		final List<Stage> threadableStageJobs = this.configuration.getThreadableStageJobs();
		for (Stage stage : threadableStageJobs) {
			// // portConnectionValidator.validate(stage);
			// }

			final ValidatingSignal validatingSignal = new ValidatingSignal();
			stage.onSignal(validatingSignal, null);
			if (validatingSignal.getInvalidPortConnections().size() > 0) {
				throw new AnalysisNotValidException(validatingSignal.getInvalidPortConnections());
			}
		}
	}

	/**
	 * This initializes Analysis and needs to be run right before starting it.
	 *
	 * @deprecated since 1.1
	 */
	@Deprecated
	public final void init() {
		if (initialized) {
			return;
		}
		initialized = true;

		final List<Stage> threadableStageJobs = this.configuration.getThreadableStageJobs();
		if (threadableStageJobs.isEmpty()) {
			throw new IllegalStateException("At least one stage must be added to the threadable jobs list");
		}
		for (Stage stage : threadableStageJobs) {
			StageExceptionHandler newListener;
			try {
				newListener = listener.newInstance();
			} catch (InstantiationException e) {
				throw new IllegalStateException(e);
			} catch (IllegalAccessException e) {
				throw new IllegalStateException(e);
			}
			switch (stage.getTerminationStrategy()) {
			case BY_SIGNAL: {
				final Thread thread = new Thread(new RunnableConsumerStage(stage, newListener));
				stage.setOwningThread(thread);
				this.consumerThreads.add(thread);
				break;
			}
{'fraction_non_alphanumeric': 0.0830869308101715, 'fraction_numerical': 0.002562586240883107, 'mean_word_length': 4.7522675736961455, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4432188', 'n_tokens_mistral': 2770, 'n_tokens_neox': 2546, 'n_words': 867}