Commit e49a3c5b authored by Nils Christian Ehmke's avatar Nils Christian Ehmke

Added comments and JavaDoc; Removed unnecessary code

parent 44924b86
package kieker.diagnosis.architecture;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import com.google.inject.AbstractModule;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matcher;
import com.google.inject.matcher.Matchers;
import kieker.diagnosis.architecture.monitoring.MonitoringInterceptor;
......@@ -24,19 +26,19 @@ public class KiekerTraceDiagnosisArchitectureModule extends AbstractModule {
@Override
protected void configure( ) {
// Create the interceptors
// Create the interceptors once. Some of them should not exist multiple times.
final ErrorHandlingInterceptor errorHandlingInterceptor = new ErrorHandlingInterceptor( );
final MonitoringInterceptor monitoringInterceptor = new MonitoringInterceptor( );
final CacheInterceptor cacheInterceptor = new CacheInterceptor( );
// UI
// Add the interceptors for the UI
bindInterceptor( Matchers.subclassesOf( ControllerBase.class ), Matchers.any( ), errorHandlingInterceptor );
bindInterceptor( Matchers.subclassesOf( ControllerBase.class ), Matchers.not( new SyntheticMethodMatcher( ) ), monitoringInterceptor );
bindInterceptor( Matchers.subclassesOf( ViewModelBase.class ), Matchers.not( new SyntheticMethodMatcher( ) ), monitoringInterceptor );
// Service
bindInterceptor( Matchers.subclassesOf( ServiceBase.class ), Matchers.annotatedWith( UseCache.class ).or( Matchers.annotatedWith( InvalidateCache.class ) ),
cacheInterceptor );
// Add the interceptors for the services
final Matcher<AnnotatedElement> cacheMatcher = Matchers.annotatedWith( UseCache.class ).or( Matchers.annotatedWith( InvalidateCache.class ) );
bindInterceptor( Matchers.subclassesOf( ServiceBase.class ), cacheMatcher, cacheInterceptor );
bindInterceptor( Matchers.subclassesOf( ServiceBase.class ), Matchers.not( new SyntheticMethodMatcher( ) ), monitoringInterceptor );
}
......
......@@ -14,7 +14,8 @@ import kieker.diagnosis.architecture.common.ClassUtil;
import kieker.diagnosis.architecture.exception.TechnicalException;
/**
* This is the abstract base for a service.
* This is the abstract base for a service. It provides convenient methods, like retrieving a service or localizing a string. For each class extending this
* base, a resource bundle has to be available in the classpath with the name of the implementing class.
*
* @author Nils Christian Ehmke
*/
......@@ -27,6 +28,12 @@ public abstract class ServiceBase {
@Inject
private Injector ivInjector;
/**
* This constructor can be used if the implementing service has non-static fields. Use this with care, as services should usually have no state.
*
* @param aCheckFields
* true if and only if the field check should be enabled.
*/
protected ServiceBase( final boolean aCheckFields ) {
// Make sure that the singleton annotation is present
ClassUtil.assertSingletonAnnotation( getClass( ) );
......@@ -43,6 +50,9 @@ public abstract class ServiceBase {
}
}
/**
* The default constructor. It checks whether the service has any non-static fields.
*/
protected ServiceBase( ) {
this( true );
}
......
......@@ -9,7 +9,8 @@ import kieker.diagnosis.architecture.common.ClassUtil;
import kieker.diagnosis.architecture.service.ServiceBase;
/**
* This is the abstract base for a controller.
* This is the abstract base for a controller. It provides convenient methods, like retrieving a service or localizing a string. For each class extending this
* base, a resource bundle has to be available in the classpath with the name of the implementing class.
*
* @param <VM>
* The type of the view model.
......@@ -31,6 +32,11 @@ public abstract class ControllerBase<VM extends ViewModelBase<?>> {
ClassUtil.assertSingletonAnnotation( getClass( ) );
}
/**
* Gets the view model for this controller.
*
* @return The view model.
*/
protected final VM getViewModel( ) {
return ivViewModel;
}
......@@ -47,6 +53,14 @@ public abstract class ControllerBase<VM extends ViewModelBase<?>> {
return ivInjector.getInstance( aServiceClass );
}
/**
* Gets a controller of the given type. Use this method with care, as it can lead to incomprehensible execution flow.
*
* @param aControllerClass
* The type of the controller.
*
* @return The controller.
*/
protected final <C extends ControllerBase<?>> C getController( final Class<C> aControllerClass ) {
return ivInjector.getInstance( aControllerClass );
}
......
......@@ -4,6 +4,16 @@ import java.util.ResourceBundle;
import javafx.util.StringConverter;
/**
* This is an implementation of a {@link StringConverter} to convert an enum value to a string representation and vice versa. A resource bundle with the name of
* the enum has to be available in the classpath. It is also recommended, that each enum value has a different locale string. {@code null} values are mapped to
* the empty string and vice versa.
*
* @param <E>
* The type of the enum.
*
* @author Nils Christian Ehmke
*/
public final class EnumStringConverter<E extends Enum<?>> extends StringConverter<E> {
private final ResourceBundle ivResourceBundle;
......@@ -31,6 +41,7 @@ public final class EnumStringConverter<E extends Enum<?>> extends StringConverte
final E[] enumConstants = ivEnumClass.getEnumConstants( );
// Run through all values of the enum and check which one maps to the given string.
for ( final E enumConstant : enumConstants ) {
final String value = toString( enumConstant );
if ( value.equals( aString ) ) {
......@@ -38,6 +49,7 @@ public final class EnumStringConverter<E extends Enum<?>> extends StringConverte
}
}
// We did not found a value. This should not happen. We have to return something though.
return null;
}
......
......@@ -18,8 +18,16 @@ import javafx.scene.image.Image;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
import kieker.diagnosis.architecture.common.ClassUtil;
import kieker.diagnosis.architecture.exception.BusinessRuntimeException;
/**
* This is an interceptor which handles all kind of {@link Throwable Throwables}. It is usually used around controller actions. If an exception occurs, the
* interceptor logs the exception, shows an error dialog, and returns {@code null}. If the exception is a {@link BusinessRuntimeException}, the error is not
* logged and the error dialog indicates that the error is a business error.
*
* @author Nils Christian Ehmke
*/
public final class ErrorHandlingInterceptor implements MethodInterceptor {
private final ResourceBundle ivResourceBundle = ResourceBundle.getBundle( getClass( ).getName( ) );
......@@ -34,18 +42,21 @@ public final class ErrorHandlingInterceptor implements MethodInterceptor {
}
}
private void handleException( final Throwable aThrowable, final Object aController ) {
private void handleException( final Throwable aThrowable, final Object aObject ) {
showExceptionDialog( aThrowable );
logException( aThrowable, aController );
logException( aThrowable, aObject );
}
private void showExceptionDialog( final Throwable aThrowable ) {
// Prepare the dialog
// Find out whether this is a business exception or not
final boolean isBusinessException = aThrowable instanceof BusinessRuntimeException;
final Throwable exception = isBusinessException ? aThrowable.getCause( ) : aThrowable;
final AlertType alertType = isBusinessException ? AlertType.WARNING : AlertType.ERROR;
// Keep in mind that some controllers start a new thread. As this might also lead to exceptions, the whole dialog showing has to be performed in the
// JavaFX application thread.
final Runnable runnable = ( ) -> {
// Prepare the dialog
final Alert alert = new Alert( alertType );
alert.setTitle( ivResourceBundle.getString( "errorTitle" ) );
alert.setHeaderText( ivResourceBundle.getString( "errorMessage" ) );
......@@ -88,6 +99,7 @@ public final class ErrorHandlingInterceptor implements MethodInterceptor {
alert.showAndWait( );
};
// Now decide whether we need to execute this in the JavaFX thread or whether we are already in this thread.
if ( Platform.isFxApplicationThread( ) ) {
runnable.run( );
} else {
......@@ -95,10 +107,9 @@ public final class ErrorHandlingInterceptor implements MethodInterceptor {
}
}
private void logException( final Throwable aThrowable, final Object aController ) {
private void logException( final Throwable aThrowable, final Object aObject ) {
if ( !( aThrowable instanceof BusinessRuntimeException ) ) {
// We have to use getSuperclass as all controllers are enhanced by Guice with an interceptor.
final Class<?> controllerClass = aController.getClass( ).getSuperclass( );
final Class<?> controllerClass = ClassUtil.getRealClass( aObject.getClass( ) );
LogManager.getLogger( controllerClass ).error( ivResourceBundle.getString( "errorMessage" ), aThrowable );
}
}
......
package kieker.diagnosis.architecture.ui;
/**
* This interface can be used for simple event handlers.
*
* @author Nils Christian Ehmke
*/
@FunctionalInterface
public interface EventHandler {
public void handleEvent( );
}
......@@ -8,7 +8,8 @@ import javafx.scene.layout.VBox;
import kieker.diagnosis.architecture.common.ClassUtil;
/**
* This is the abstract base for a view.
* This is the abstract base for a view. It provides a convenient method to localize a string. Also a corresponding stylesheet file is applied. For each class
* extending this base, a resource bundle has to be available in the classpath with the name of the implementing class.
*
* @param <C>
* The type of the controller.
......@@ -41,6 +42,11 @@ public abstract class ViewBase<C extends ControllerBase<?>> extends VBox {
return ivResourceBundle.getString( aKey );
}
/**
* Gets the controller for this view.
*
* @return The controller.
*/
protected final C getController( ) {
return ivController;
}
......@@ -49,6 +55,13 @@ public abstract class ViewBase<C extends ControllerBase<?>> extends VBox {
return ClassUtil.getRealName( getClass( ) ).replace( ".", "/" ) + ".css";
}
/**
* This method can be used to send a parameter to the current view. The precise nature of the parameter (and all actions necessary to use it) depends on the
* view.
*
* @param aParameter
* The parameter.
*/
public abstract void setParameter( Object aParameter );
}
......@@ -11,7 +11,8 @@ import kieker.diagnosis.architecture.common.ClassUtil;
import kieker.diagnosis.architecture.service.ServiceBase;
/**
* This is the abstract base for a view model.
* This is the abstract base for a view model. It provides convenient methods, like retrieving a service or localizing a string. For each class extending this
* base, a resource bundle has to be available in the classpath with the name of the implementing class.
*
* @param <V>
* The type of the view.
......@@ -33,6 +34,11 @@ public abstract class ViewModelBase<V extends ViewBase<?>> {
ClassUtil.assertSingletonAnnotation( getClass( ) );
}
/**
* Gets the view for this view model.
*
* @return The view.
*/
protected final V getView( ) {
return ivView;
}
......@@ -50,7 +56,7 @@ public abstract class ViewModelBase<V extends ViewBase<?>> {
}
/**
* Gets a service of the given type.
* Gets a service of the given type. Use this method with care, as view models should use services only in very rare cases.
*
* @param aServiceClass
* The type of the service.
......@@ -62,7 +68,7 @@ public abstract class ViewModelBase<V extends ViewBase<?>> {
}
/**
* Closes the corresponding window of the view.
* Closes the corresponding window of the view. If the view is a dialog, this closes the dialog. Otherwise the whole application window will be closed.
*/
public final void close( ) {
final Scene scene = getView( ).getScene( );
......@@ -70,6 +76,14 @@ public abstract class ViewModelBase<V extends ViewBase<?>> {
window.hide( );
}
/**
* A convenient helper method to trim a user input.
*
* @param aString
* The string to trim. Can be {@code null}.
*
* @return The trimmed string. If the string becomes empty, {@code null} will be returned.
*/
protected final String trimToNull( final String aString ) {
if ( aString == null ) {
return aString;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment