<commit_before>This page provides some development support in the form of howtos. See also [[High Level Documentation]].

## Table of Contents
  * [Generic code how tos](#generic-code-how-tos)
  * [Error Handling in JabRef](#error-handling-in-jabref)
    * [Throwing and Catching Exceptions](#throwing-and-catching-exceptions)
    * [Outputting Errors in the UI](#outputting-errors-in-the-ui)
  * [Using the EventSystem](#using-the-eventsystem)
  * [Logging](#logging)
  * [Using Localization correctly](#using-localization-correctly)
  * [Cleanup and Formatters](#cleanup-and-formatters)
  * [Drag and Drop](#drag-and-drop)
  * [Get the JabRef frame panel](#get-the-jabref-frame-panel)
  * [Get Absolute Filename or Path](#get-absolute-filename-or-path)
  * [Setting a Database Directory for a .bib File](#setting-a-database-directory-for-a-.bib-file)
  * [How to work with Preferences](#how-to-work-with-preferences)
  * [Test Cases](#test-cases)
    * [Lists in tests](#lists-in-tests)
    * [BibEntries in tests](#bibentries-in-tests)
    * [Files and folders](#files-and-folders-in-tests)
    * [Loading Files from Resources](#loading-files-from-resources)
    * [Preferences in tests](#preferences-in-tests)
  * [UI](#ui)
  * [UI for Preferences](#ui-for-preferences)
  * [Designing GUI Confirmation dialogs](#designing-gui-confirmation-dialogs)
  * ["Special Fields"](#special-fields)
    * [keywords sync](#keywords-sync)
  * [Working with BibTeX data](#working-with-bibtex-data)
    * [Working with authors](#working-with-authors)
  * [Benchmarks](#benchmarks)
  * [equals](#equals)
  * [Files & Paths](#files-and-paths)
  * [JavaFX](#javafx)


## Generic code how tos

We really recommend reading the book [Java by Comparison](http://java.by-comparison.com/).

Please read https://github.com/cxxr/better-java

- try not to abbreviate names of variables, classes or methods
- use lowerCamelCase instead of snake_case
- name enums in singular, e.g. `Weekday` instead of `Weekdays` (except if they represent flags)


## Error Handling in JabRef

### Throwing and Catching Exceptions
Principles: 
- All Exceptions we throw should be or extend `JabRefException`; This is especially important if the message stored in the Exception should be shown to the user. `JabRefException` has already implemented the `getLocalizedMessage()` method which should be used for such cases (see details below!).
- Catch and wrap all API exceptions (such as `IOExceptions`) and rethrow them
 - Example:
  ```java
  try {
      // ...
  } catch (IOException ioe) {
      throw new JabRefException("Something went wrong...", 
           Localization.lang("Something went wrong...", ioe);
  }
  ```
- Never, ever throw and catch `Exception` or `Throwable`
- Errors should only be logged when they are finally caught (i.e., logged only once). See **Logging** for details.
- If the Exception message is intended to be shown to the User in the UI (see below) provide also a localizedMessage (see `JabRefException`).

*(Rationale and further reading: https://today.java.net/article/2006/04/04/exception-handling-antipatterns)*

### Outputting Errors in the UI
Principle: Error messages shown to the User should not contain technical details (e.g., underlying exceptions, or even stack traces). Instead, the message should be concise, understandable for non-programmers and localized. The technical reasons (and stack traces) for a failure should only be logged.

To show error message two different ways are usually used in JabRef:
- showing an error dialog
- updating the status bar at the bottom of the main window

*TODO: Usage of status bar and Swing Dialogs*

## Using the EventSystem

### What the EventSystem is used for?
Many times there is a need to provide an object on many locations simultaneously.
This design pattern is quite similar to Java's Observer, but it is much simplier and readable while having the same functional sense.


### Main principle
`EventBus` represents a communication line between multiple components.
Objects can be passed through the bus and reach the listening method of another object which is registered on that `EventBus` instance.
Hence the passed object is available as a parameter in the listening method.

### Register to the `EventBus`
Any listening method has to be annotated with `@Subscribe` keyword and must have only one accepting parameter. Furthermore the object which contains such listening method(s) has to be registered using the `register(Object)` method provided by `EventBus`. The listening methods can be overloaded by using differnt parameter types.


### Posting an object
`post(object)` posts an object trough the `EventBus` which has been used to register the listening/subscribing methods.

### Short example
```java
/* Listener.java */

import com.google.common.eventbus.Subscribe;

public class Listener {
   
   private int value = 0;
   
   @Subscribe
   public void listen(int value) {
      this.value = value;
   }

   public int getValue() {
      return this.value;
   }
}
```

```java
/* Main.java */

import com.google.common.eventbus.EventBus;

public class Main {
   private static EventBus eventBus = new EventBus();
   
   public static void main(String[] args) {
      Main main = new Main();
      Listener listener = new Listener();
      eventBus.register(listener);
      eventBus.post(1); // 1 represents the passed event

      // Output should be 1
      System.out.println(listener.getValue());
   }
}
```

### Event handling in JabRef

The `event` package contains some specific events which occure in JabRef.

For example: Every time an entry was added to the database a new `EntryAddedEvent` is sent trough the `eventBus` which is located  in `BibDatabase`.

If you want to catch the event you'll have to register your listener class with the `registerListener(Object listener)` method in `BibDatabase`. `EntryAddedEvent` provides also methods to get the inserted `BibEntry`.


## Logging

JabRef uses the logging facade [Apache Commons Logging](http://commons.apache.org/proper/commons-logging/).
All log messages are passed internally to Java's [java.util.logging](http://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html) which handles any filterting, formatting and writing of log messages. 
- Obtaining a Logger for a Class: 

  ```java
  private static final Log LOGGER = LogFactory.getLog(<ClassName>.class);
  ```

- If the logging event is caused by an exception, please add the exception to the log message as: 

  ```java
    catch (SomeException e) {
       LOGGER.warn("Warning text.", e);
       ...
    }
  ```

## Using Localization correctly
*(More information about this topic from the translator side is provided [here] (https://github.com/JabRef/jabref/wiki/Translating-JabRef-Interface) about the JabRef interface and 
[here] (https://github.com/JabRef/jabref/wiki/Translating-JabRef-Help) about the JabRef help files)*<commit_msg>Update logging<commit_after>This page provides some development support in the form of howtos. See also [[High Level Documentation]].

## Table of Contents
  * [Generic code how tos](#generic-code-how-tos)
  * [Error Handling in JabRef](#error-handling-in-jabref)
    * [Throwing and Catching Exceptions](#throwing-and-catching-exceptions)
    * [Outputting Errors in the UI](#outputting-errors-in-the-ui)
  * [Using the EventSystem](#using-the-eventsystem)
  * [Logging](#logging)
  * [Using Localization correctly](#using-localization-correctly)
  * [Cleanup and Formatters](#cleanup-and-formatters)
  * [Drag and Drop](#drag-and-drop)
  * [Get the JabRef frame panel](#get-the-jabref-frame-panel)
  * [Get Absolute Filename or Path](#get-absolute-filename-or-path)
  * [Setting a Database Directory for a .bib File](#setting-a-database-directory-for-a-.bib-file)
  * [How to work with Preferences](#how-to-work-with-preferences)
  * [Test Cases](#test-cases)
    * [Lists in tests](#lists-in-tests)
    * [BibEntries in tests](#bibentries-in-tests)
    * [Files and folders](#files-and-folders-in-tests)
    * [Loading Files from Resources](#loading-files-from-resources)
    * [Preferences in tests](#preferences-in-tests)
  * [UI](#ui)
  * [UI for Preferences](#ui-for-preferences)
  * [Designing GUI Confirmation dialogs](#designing-gui-confirmation-dialogs)
  * ["Special Fields"](#special-fields)
    * [keywords sync](#keywords-sync)
  * [Working with BibTeX data](#working-with-bibtex-data)
    * [Working with authors](#working-with-authors)
  * [Benchmarks](#benchmarks)
  * [equals](#equals)
  * [Files & Paths](#files-and-paths)
  * [JavaFX](#javafx)


## Generic code how tos

We really recommend reading the book [Java by Comparison](http://java.by-comparison.com/).

Please read https://github.com/cxxr/better-java

- try not to abbreviate names of variables, classes or methods
- use lowerCamelCase instead of snake_case
- name enums in singular, e.g. `Weekday` instead of `Weekdays` (except if they represent flags)


## Error Handling in JabRef

### Throwing and Catching Exceptions
Principles: 
- All Exceptions we throw should be or extend `JabRefException`; This is especially important if the message stored in the Exception should be shown to the user. `JabRefException` has already implemented the `getLocalizedMessage()` method which should be used for such cases (see details below!).
- Catch and wrap all API exceptions (such as `IOExceptions`) and rethrow them
 - Example:
  ```java
  try {
      // ...
  } catch (IOException ioe) {
      throw new JabRefException("Something went wrong...", 
           Localization.lang("Something went wrong...", ioe);
  }
  ```
- Never, ever throw and catch `Exception` or `Throwable`
- Errors should only be logged when they are finally caught (i.e., logged only once). See **Logging** for details.
- If the Exception message is intended to be shown to the User in the UI (see below) provide also a localizedMessage (see `JabRefException`).

*(Rationale and further reading: https://today.java.net/article/2006/04/04/exception-handling-antipatterns)*

### Outputting Errors in the UI
Principle: Error messages shown to the User should not contain technical details (e.g., underlying exceptions, or even stack traces). Instead, the message should be concise, understandable for non-programmers and localized. The technical reasons (and stack traces) for a failure should only be logged.

To show error message two different ways are usually used in JabRef:
- showing an error dialog
- updating the status bar at the bottom of the main window

*TODO: Usage of status bar and Swing Dialogs*

## Using the EventSystem

### What the EventSystem is used for?
Many times there is a need to provide an object on many locations simultaneously.
This design pattern is quite similar to Java's Observer, but it is much simplier and readable while having the same functional sense.


### Main principle
`EventBus` represents a communication line between multiple components.
Objects can be passed through the bus and reach the listening method of another object which is registered on that `EventBus` instance.
Hence the passed object is available as a parameter in the listening method.

### Register to the `EventBus`
Any listening method has to be annotated with `@Subscribe` keyword and must have only one accepting parameter. Furthermore the object which contains such listening method(s) has to be registered using the `register(Object)` method provided by `EventBus`. The listening methods can be overloaded by using differnt parameter types.


### Posting an object
`post(object)` posts an object trough the `EventBus` which has been used to register the listening/subscribing methods.

### Short example
```java
/* Listener.java */

import com.google.common.eventbus.Subscribe;

public class Listener {
   
   private int value = 0;
   
   @Subscribe
   public void listen(int value) {
      this.value = value;
   }

   public int getValue() {
      return this.value;
   }
}
```

```java
/* Main.java */

import com.google.common.eventbus.EventBus;

public class Main {
   private static EventBus eventBus = new EventBus();
   
   public static void main(String[] args) {
      Main main = new Main();
      Listener listener = new Listener();
      eventBus.register(listener);
      eventBus.post(1); // 1 represents the passed event

      // Output should be 1
      System.out.println(listener.getValue());
   }
}
```

### Event handling in JabRef

The `event` package contains some specific events which occure in JabRef.

For example: Every time an entry was added to the database a new `EntryAddedEvent` is sent trough the `eventBus` which is located  in `BibDatabase`.

If you want to catch the event you'll have to register your listener class with the `registerListener(Object listener)` method in `BibDatabase`. `EntryAddedEvent` provides also methods to get the inserted `BibEntry`.


## Logging

JabRef uses the logging facade [SLF4j](https://www.slf4j.org/).
All log messages are passed internally to the [log4j2] [https://logging.apache.org/log4j/2.x/] which handles any filterting, formatting and writing of log messages. 
- Obtaining a Logger for a Class: 

  ```java
  private static final Log LOGGER = LogFactory.getLog(<ClassName>.class);
  ```

- If the logging event is caused by an exception, please add the exception to the log message as: 

  ```java
    catch (SomeException e) {
       LOGGER.warn("Warning text.", e);
       ...
    }
  ```
- SLF4J also support parameterized logging, e.g. if you want to print out multiple arguments in a log statement use a pair of curly braces. [Examples](https://www.slf4j.org/faq.html#logging_performance)


## Using Localization correctly
*(More information about this topic from the translator side is provided [here] (https://github.com/JabRef/jabref/wiki/Translating-JabRef-Interface) about the JabRef interface and 
[here] (https://github.com/JabRef/jabref/wiki/Translating-JabRef-Help) about the JabRef help files)*
{'fraction_non_alphanumeric': 0.10178571428571428, 'fraction_numerical': 0.002357142857142857, 'mean_word_length': 4.11171960569551, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 11, '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': '3470313', 'n_tokens_mistral': 4086, 'n_tokens_neox': 3852, 'n_words': 1546}