diff --git a/src/main/java/kieker/analysis/plugin/filter/AbstractKiekerFilter.java b/src/main/java/kieker/analysis/plugin/filter/AbstractKiekerFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..970273320fcc9c2919b1ae3f9a26c50d1ca8c7c8 --- /dev/null +++ b/src/main/java/kieker/analysis/plugin/filter/AbstractKiekerFilter.java @@ -0,0 +1,132 @@ +package kieker.analysis.plugin.filter; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import kieker.analysis.AnalysisController; +import kieker.analysis.IProjectContext; +import kieker.analysis.analysisComponent.AbstractAnalysisComponent; +import kieker.analysis.analysisComponent.IAnalysisComponent; +import kieker.analysis.exception.InvalidProjectContextException; +import kieker.analysis.plugin.annotation.Plugin; +import kieker.analysis.plugin.annotation.Property; +import kieker.common.configuration.Configuration; +import kieker.common.logging.Log; +import kieker.common.logging.LogFactory; + +import teetime.stage.basic.AbstractFilter; + +public abstract class AbstractKiekerFilter<E> extends AbstractFilter<E> implements IAnalysisComponent { + + /** The name of the property for the name. This should normally only be used by Kieker. */ + public static final String CONFIG_NAME = "name-hiddenAndNeverExportedProperty"; + + protected static final Log LOG = LogFactory.getLog(AbstractAnalysisComponent.class); // NOPMD (logger for inheriting classes) + + private static final AtomicInteger UNNAMED_COUNTER = new AtomicInteger(0); + + /** The project context (usually the analysis controller) of this component. */ + protected final IProjectContext projectContext; + + /** The current configuration of this component. */ + protected final Configuration configuration; + /** The log for this component. */ + protected final Log log; // NOPMD (logger for inheriting classes) + + /** The record time unit as provided by the project context. */ + protected final TimeUnit recordsTimeUnitFromProjectContext; + + private final String name; + + /** + * Each AnalysisComponent requires a constructor with a Configuration object and a IProjectContext. + * + * @param configuration + * The configuration for this component. + * @param projectContext + * The project context for this component. The component will be registered. + * + * @throws NullPointerException + * If configuration or projectContext null + */ + public AbstractKiekerFilter(final Configuration configuration, final IProjectContext projectContext) throws NullPointerException { + super(); + + if (null == projectContext) { + throw new NullPointerException("Missing projectContext"); + } + if (null == configuration) { + throw new NullPointerException("Missing configuration"); + } + this.projectContext = projectContext; + // somewhat dirty hack... + configuration.setDefaultConfiguration(this.getDefaultConfiguration()); + this.configuration = configuration; + + // Get the controller, as we have to register the name + final AnalysisController ac; + if (projectContext instanceof AnalysisController) { + ac = (AnalysisController) projectContext; + } else { + throw new InvalidProjectContextException("Invalid analysis controller in constructor"); + } + + // Try to determine the name + String tmpName = configuration.getStringProperty(CONFIG_NAME); + while ((tmpName.length() == 0) || !ac.tryRegisterComponentName(tmpName)) { + tmpName = this.getClass().getSimpleName() + '-' + UNNAMED_COUNTER.incrementAndGet(); + } + this.name = tmpName; + + // As we have now a name, we can create our logger + this.log = LogFactory.getLog(this.getClass().getName() + " (" + this.name + ")"); + + // Try the record time unit + final String recordTimeunitProperty = projectContext.getProperty(IProjectContext.CONFIG_PROPERTY_NAME_RECORDS_TIME_UNIT); + TimeUnit recordTimeunit; + try { + recordTimeunit = TimeUnit.valueOf(recordTimeunitProperty); + } catch (final IllegalArgumentException ex) { // already caught in AnalysisController, should never happen + this.log.warn(recordTimeunitProperty + " is no valid TimeUnit! Using NANOSECONDS instead."); + recordTimeunit = TimeUnit.NANOSECONDS; + } + this.recordsTimeUnitFromProjectContext = recordTimeunit; + } + + @Override + protected void execute(final E element) { + super.execute(); + } + + /** + * This method delivers an instance of {@code Configuration} containing the default properties for this class. + * + * @return The default properties. + */ + protected final Configuration getDefaultConfiguration() { + final Configuration defaultConfiguration = new Configuration(); + // Get the annotation from the class + final Plugin pluginAnnotation = this.getClass().getAnnotation(Plugin.class); + final Property[] propertyAnnotations = pluginAnnotation.configuration(); + // Run through all properties within the annotation and add them to the configuration object + for (final Property property : propertyAnnotations) { + defaultConfiguration.setProperty(property.name(), property.defaultValue()); + } + return defaultConfiguration; + } + + /** + * {@inheritDoc} + */ + @Override + public abstract Configuration getCurrentConfiguration(); + + /** + * {@inheritDoc} + */ + @Override + public final String getName() { + return this.name; + } + +}