<commit_before>/*
 * JGrapes Event Driven Framework
 * Copyright (C) 2016  <NAME>
 * 
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 3 of the License, or 
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License along 
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 */

package org.jgrapes.core;

import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;

import org.jgrapes.core.annotation.ComponentManager;
import org.jgrapes.core.events.Start;
import org.jgrapes.core.events.Started;
import org.jgrapes.core.internal.Common;
import org.jgrapes.core.internal.ComponentVertex;
import org.jgrapes.core.internal.GeneratorRegistry;

/**
 * This class provides some utility functions.
 */
public class Components {

	private Components() {
	}
	
	/**
	 * Returns a component's manager. For a component that inherits
	 * from {@link org.jgrapes.core.Component} this method simply returns
	 * the component as it is its own manager.
	 * 
	 * For components that implement {@link ComponentType} but don't inherit from 
	 * {@link org.jgrapes.core.Component} the method returns the value of 
	 * the attribute annotated as manager slot. If this attribute is still
	 * empty, this method makes the component the root
	 * of a new tree and returns its manager.
	 * 
	 * @param component the component
	 * @return the component (with its manager attribute set)
	 */
	public static Manager manager(ComponentType component) {
		return ComponentVertex.componentVertex(component, null);
	}

	/**
	 * Returns a component's manager like {@link #manager(ComponentType)}.
	 * If the manager slot attribute is empty, the component is initialized
	 * with its component channel set to the given parameter. Invoking
	 * this method overrides any channel set in the
	 * {@link ComponentManager} annotation.
	 * 
	 * This method is usually invoked by the constructor of a class
	 * that implements {@link ComponentType}.
	 * 
	 * @param component the component
	 * @param componentChannel the channel that the component's 
	 * handlers listen on by default and that 
	 * {@link Manager#fire(Event, Channel...)} sends the event to 
	 * @return the component (with its manager attribute set)
	 * @see Component#Component(Channel)
	 */
	public static Manager manager(
			ComponentType component, Channel componentChannel) {
		return ComponentVertex.componentVertex(component, componentChannel);
	}

	/**
	 * Fires a {@link Start} event with an associated
	 * {@link Started} completion event on the broadcast channel
	 * of the given application and wait for the completion of the
	 * <code>Start</code> event.
	 * 
	 * @param application the application to start
	 * @throws InterruptedException if the execution was interrupted
	 */
	public static void start(ComponentType application) 
			throws InterruptedException {
		manager(application).fire(new Start() , Channel.BROADCAST).get();
	}

	/**
	 * Wait until all generators and event queues are exhausted. When this
	 * stage is reached, nothing can happen anymore unless a new event is
	 * sent from an external thread.
	 * 
	 * @throws InterruptedException if the current thread was interrupted
	 * while waiting
	 */
	public static void awaitExhaustion() throws InterruptedException {
		GeneratorRegistry.instance().awaitExhaustion();
	}

	/**
	 * Wait until all generators and event queues are exhausted or
	 * the maximum wait time has expired.
	 * 
	 * @param timeout the wait time in milliseconds
	 * @return {@code true} if exhaustion state was reached
	 * @throws InterruptedException if the execution was interrupted 
	 * @see #awaitExhaustion()
	 */
	public static boolean awaitExhaustion(long timeout) 
			throws InterruptedException {
		return GeneratorRegistry.instance().awaitExhaustion(timeout);
	}

	/**
	 * Utility method that checks if an assertion error has occurred
	 * while executing handlers. If so, the error is thrown and
	 * the assertion error store is reset.
	 * <P>
	 * This method is intended for junit tests. It enables easy propagation
	 * of assertion failures to the main thread.
	 * 
	 * @throws AssertionError if an assertion error occurred while
	 * executing the application
	 */
	public static void checkAssertions() {
		Common.checkAssertions();
	}
	
	/**
	 * Returns the name of the object's class together with an id (see 
	 * {@link #objectId(Object)}). May be used to implement {@code toString()}
	 * with identifiable objects.
	 * 
	 * @param object
	 *            the object
	 * @return the object's name
	 */
	public static String objectName(Object object) {
		StringBuilder builder = new StringBuilder();
		builder.append(Components.classToString(object.getClass()));
		builder.append('#');
		builder.append(objectId(object));
		return builder.toString();
	}

	private static Map<Object, String> objectIds = new WeakHashMap<>();
	private static Map<Class<?>, AtomicLong> idCounters = new WeakHashMap<>();
<commit_msg>New method for id generation.<commit_after>/*
 * JGrapes Event Driven Framework
 * Copyright (C) 2016  <NAME>
 * 
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 3 of the License, or 
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License along 
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 */

package org.jgrapes.core;

import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;

import org.jgrapes.core.annotation.ComponentManager;
import org.jgrapes.core.events.Start;
import org.jgrapes.core.events.Started;
import org.jgrapes.core.internal.Common;
import org.jgrapes.core.internal.ComponentVertex;
import org.jgrapes.core.internal.GeneratorRegistry;

/**
 * This class provides some utility functions.
 */
public class Components {

	private Components() {
	}
	
	/**
	 * Returns a component's manager. For a component that inherits
	 * from {@link org.jgrapes.core.Component} this method simply returns
	 * the component as it is its own manager.
	 * 
	 * For components that implement {@link ComponentType} but don't inherit from 
	 * {@link org.jgrapes.core.Component} the method returns the value of 
	 * the attribute annotated as manager slot. If this attribute is still
	 * empty, this method makes the component the root
	 * of a new tree and returns its manager.
	 * 
	 * @param component the component
	 * @return the component (with its manager attribute set)
	 */
	public static Manager manager(ComponentType component) {
		return ComponentVertex.componentVertex(component, null);
	}

	/**
	 * Returns a component's manager like {@link #manager(ComponentType)}.
	 * If the manager slot attribute is empty, the component is initialized
	 * with its component channel set to the given parameter. Invoking
	 * this method overrides any channel set in the
	 * {@link ComponentManager} annotation.
	 * 
	 * This method is usually invoked by the constructor of a class
	 * that implements {@link ComponentType}.
	 * 
	 * @param component the component
	 * @param componentChannel the channel that the component's 
	 * handlers listen on by default and that 
	 * {@link Manager#fire(Event, Channel...)} sends the event to 
	 * @return the component (with its manager attribute set)
	 * @see Component#Component(Channel)
	 */
	public static Manager manager(
			ComponentType component, Channel componentChannel) {
		return ComponentVertex.componentVertex(component, componentChannel);
	}

	/**
	 * Fires a {@link Start} event with an associated
	 * {@link Started} completion event on the broadcast channel
	 * of the given application and wait for the completion of the
	 * <code>Start</code> event.
	 * 
	 * @param application the application to start
	 * @throws InterruptedException if the execution was interrupted
	 */
	public static void start(ComponentType application) 
			throws InterruptedException {
		manager(application).fire(new Start() , Channel.BROADCAST).get();
	}

	/**
	 * Wait until all generators and event queues are exhausted. When this
	 * stage is reached, nothing can happen anymore unless a new event is
	 * sent from an external thread.
	 * 
	 * @throws InterruptedException if the current thread was interrupted
	 * while waiting
	 */
	public static void awaitExhaustion() throws InterruptedException {
		GeneratorRegistry.instance().awaitExhaustion();
	}

	/**
	 * Wait until all generators and event queues are exhausted or
	 * the maximum wait time has expired.
	 * 
	 * @param timeout the wait time in milliseconds
	 * @return {@code true} if exhaustion state was reached
	 * @throws InterruptedException if the execution was interrupted 
	 * @see #awaitExhaustion()
	 */
	public static boolean awaitExhaustion(long timeout) 
			throws InterruptedException {
		return GeneratorRegistry.instance().awaitExhaustion(timeout);
	}

	/**
	 * Utility method that checks if an assertion error has occurred
	 * while executing handlers. If so, the error is thrown and
	 * the assertion error store is reset.
	 * <P>
	 * This method is intended for junit tests. It enables easy propagation
	 * of assertion failures to the main thread.
	 * 
	 * @throws AssertionError if an assertion error occurred while
	 * executing the application
	 */
	public static void checkAssertions() {
		Common.checkAssertions();
	}
	
	/**
	 * Returns the full name of the object's class together with an id (see 
	 * {@link #objectId(Object)}). The result can be used as a unique
	 * human readable identifier for arbitrary objects.
	 * 
	 * @param object
	 *            the object
	 * @return the object's name
	 */
	public static String objectFullName(Object object) {
		StringBuilder builder = new StringBuilder();
		builder.append(object.getClass().getName());
		builder.append('#');
		builder.append(objectId(object));
		return builder.toString();
	}

	/**
	 * Returns the name of the object's class together with an id (see 
	 * {@link #objectId(Object)}). May be used to implement {@code toString()}
	 * with identifiable objects. If the log level is "finer", the full
	 * class name will be used for the returned value, else the simple name.
	 * 
	 * @param object
	 *            the object
	 * @return the object's name
	 */
	public static String objectName(Object object) {
		StringBuilder builder = new StringBuilder();
		builder.append(Components.classToString(object.getClass()));
		builder.append('#');
		builder.append(objectId(object));
		return builder.toString();
	}

	private static Map<Object, String> objectIds = new WeakHashMap<>();
	private static Map<Class<?>, AtomicLong> idCounters = new WeakHashMap<>();

{'fraction_non_alphanumeric': 0.08377417396583124, 'fraction_numerical': 0.000867227473766369, 'mean_word_length': 3.9429918559794257, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, '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': '2763568', 'n_tokens_mistral': 3167, 'n_tokens_neox': 2867, 'n_words': 1270}