Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jbang/JabSrvLauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/CAYWQueryParams.java
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/CAYWResource.java
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/format/BibLatexFormatter.java
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/format/NatbibFormatter.java
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/format/MMDFormatter.java
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/format/PandocFormatter.java
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/format/TypstFormatter.java
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/format/CAYWFormatter.java
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/format/FormatterService.java
//SOURCES ../jabsrv/src/main/java/org/jabref/http/server/cayw/format/SimpleJsonFormatter.java
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- We added support for finding CSL-Styles based on their short title (e.g. apa instead of "american psychological association"). [#13728](https://github.com/JabRef/jabref/pull/13728)
- We added a field for the latest ICORE conference ranking lookup on the General Tab. [#13476](https://github.com/JabRef/jabref/issues/13476)
- We added BibLaTeX datamodel validation support in order to improve error message quality in entries' fields validation. [#13318](https://github.com/JabRef/jabref/issues/13318)
- We added more supported formats of CAYW endpoint of HTTP server. [#13578](https://github.com/JabRef/jabref/issues/13578)

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public class CAYWQueryParams {
private String clipboard;

@QueryParam("command")
@DefaultValue("autocite")
private String command;

@QueryParam("minimize")
Expand All @@ -46,8 +45,8 @@ public class CAYWQueryParams {
@QueryParam("application")
private String application;

public String getCommand() {
return command;
public Optional<String> getCommand() {
return Optional.ofNullable(command);
}

public boolean isClipboard() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public Response getCitation(
if (queryParams.isProbe()) {
return Response.ok("ready").build();
}

BibDatabaseContext databaseContext = getBibDatabaseContext(queryParams);

// Selected parameter handling
Expand Down Expand Up @@ -127,7 +127,7 @@ public Response getCitation(

// Push to Application parameter handling
if (queryParams.getApplication().isPresent()) {
CitationCommandString citationCmd = new CitationCommandString("\\".concat(queryParams.getCommand()).concat("{"), ",", "}");
CitationCommandString citationCmd = new CitationCommandString("\\".concat(queryParams.getCommand().orElse("autocite")).concat("{"), ",", "}");
PushToApplications.getApplication(queryParams.getApplication().get(), LOGGER::info, preferences.getPushToApplicationPreferences().withCitationCommand(citationCmd))
.ifPresent(application -> application.pushEntries(searchResults.stream().map(CAYWEntry::bibEntry).toList()));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jabref.http.server.cayw.format;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.jabref.http.server.cayw.CAYWQueryParams;
Expand All @@ -13,9 +14,10 @@
@Service
public class BibLatexFormatter implements CAYWFormatter {

@Override
public String getFormatName() {
return "biblatex";
private final String defaultCommand;

public BibLatexFormatter(String defaultCommand) {
this.defaultCommand = defaultCommand;
}

@Override
Expand All @@ -25,15 +27,16 @@ public MediaType getMediaType() {

@Override
public String format(CAYWQueryParams queryParams, List<CAYWEntry> caywEntries) {
String command = queryParams.getCommand();
String command = queryParams.getCommand().orElse(defaultCommand);

List<BibEntry> bibEntries = caywEntries.stream()
.map(CAYWEntry::bibEntry)
.toList();

return "\\%s{%s}".formatted(command,
bibEntries.stream()
.map(entry -> entry.getCitationKey().orElse(""))
.map(BibEntry::getCitationKey)
.flatMap(Optional::stream)
.collect(Collectors.joining(",")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

public interface CAYWFormatter {

String getFormatName();

MediaType getMediaType();

String format(CAYWQueryParams caywQueryParams, List<CAYWEntry> caywEntries);
Expand Down
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason on why you switched from the map and registry approach to the new switch/case approach?

I'm fine with both but I'm curious what your thoughts behind this were

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

latex, cite, citep and citet are alias of natbib, so they share the same output format. However, if command is not specified, the default value of each format is:

Format Default command
latex cite natbib cite
citep citep
citet citet

At first, I tried to keep the registry approach by doing below in, for example, NatbibFormatter:

// Replace CAYWFormatter#getFormatName by below method
@Override
public List<String> getFormatNames() {
    return List.of("natbib", "latex", "cite", "citep", "citet");
}

@Override
public String format(CAYWQueryParams queryParams, List<CAYWEntry> caywEntries) {
    String command = queryParams.getCommand().orElseGet(() -> {
        String format = queryParams.getFormat();
        switch (format) {
            case "natbib":
            case "latex":
            case "cite":
                return "cite";
            case "citep":
                return "citep";
            case "citet":
                return "citet";
            default:
                return "cite";
        }
    });
    ...
}

In this way, I have 2 concerns:

  1. queryParams.getFormat() in theory will not be null, but I can't 100% feel safe about this. Just in case it is null, I don't have a nice way of handling it.
  2. If we have a new format using the same Formatter, then we need to add the new format in both getFormatNames and format.
    Because of above, I put the the new switch/case approach in the FormatterService.java class. I am happy to edit if this is not a good approach. Thanks.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.jabref.http.server.cayw.format;

import java.util.HashMap;
import java.util.Map;
import java.util.Locale;

import org.jabref.http.server.cayw.CAYWQueryParams;

Expand All @@ -10,20 +9,28 @@
@Service
public class FormatterService {

private static final String DEFAULT_FORMATTER = "biblatex";
private final Map<String, CAYWFormatter> formatters;

public FormatterService() {
this.formatters = new HashMap<>();
registerFormatter(new SimpleJsonFormatter());
registerFormatter(new BibLatexFormatter());
}

public void registerFormatter(CAYWFormatter formatter) {
formatters.putIfAbsent(formatter.getFormatName(), formatter);
}

public CAYWFormatter getFormatter(CAYWQueryParams queryParams) {
return formatters.getOrDefault(queryParams.getFormat().toLowerCase(), formatters.get(DEFAULT_FORMATTER));
String format = queryParams.getFormat().toLowerCase(Locale.ROOT);

return switch (format) {
case "natbib",
"latex",
"cite" ->
new NatbibFormatter("cite");
case "citep" ->
new NatbibFormatter("citep");
case "citet" ->
new NatbibFormatter("citet");
case "mmd" ->
new MMDFormatter();
case "pandoc" ->
new PandocFormatter();
case "simple-json" ->
new SimpleJsonFormatter();
case "typst" ->
new TypstFormatter();
default ->
new BibLatexFormatter("autocite");
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.jabref.http.server.cayw.format;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.jabref.http.server.cayw.CAYWQueryParams;
import org.jabref.http.server.cayw.gui.CAYWEntry;
import org.jabref.model.entry.BibEntry;

import jakarta.ws.rs.core.MediaType;

public class MMDFormatter implements CAYWFormatter {

@Override
public MediaType getMediaType() {
return MediaType.TEXT_PLAIN_TYPE;
}

@Override
public String format(CAYWQueryParams queryParams, List<CAYWEntry> caywEntries) {
List<BibEntry> bibEntries = caywEntries.stream()
.map(CAYWEntry::bibEntry)
.toList();

return bibEntries.stream()
.map(entry -> entry.getCitationKey().map("[#%s][]"::formatted))
.flatMap(Optional::stream)
.collect(Collectors.joining(""));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.jabref.http.server.cayw.format;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.jabref.http.server.cayw.CAYWQueryParams;
import org.jabref.http.server.cayw.gui.CAYWEntry;
import org.jabref.model.entry.BibEntry;

import jakarta.ws.rs.core.MediaType;
import org.jvnet.hk2.annotations.Service;

@Service
public class NatbibFormatter implements CAYWFormatter {

private final String defaultCommand;

public NatbibFormatter(String defaultCommand) {
this.defaultCommand = defaultCommand;
}

@Override
public MediaType getMediaType() {
return MediaType.TEXT_PLAIN_TYPE;
}

@Override
public String format(CAYWQueryParams queryParams, List<CAYWEntry> caywEntries) {
String command = queryParams.getCommand().orElse(defaultCommand);

List<BibEntry> bibEntries = caywEntries.stream()
.map(CAYWEntry::bibEntry)
.toList();

return "\\%s{%s}".formatted(command,
bibEntries.stream()
.map(BibEntry::getCitationKey)
.flatMap(Optional::stream)
.collect(Collectors.joining(",")));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.jabref.http.server.cayw.format;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.jabref.http.server.cayw.CAYWQueryParams;
import org.jabref.http.server.cayw.gui.CAYWEntry;
import org.jabref.model.entry.BibEntry;

import jakarta.ws.rs.core.MediaType;

public class PandocFormatter implements CAYWFormatter {

@Override
public MediaType getMediaType() {
return MediaType.TEXT_PLAIN_TYPE;
}

@Override
public String format(CAYWQueryParams queryParams, List<CAYWEntry> caywEntries) {
List<BibEntry> bibEntries = caywEntries.stream()
.map(CAYWEntry::bibEntry)
.toList();

return "[%s]".formatted(bibEntries.stream()
.map(entry -> entry.getCitationKey().map("@%s"::formatted))
.flatMap(Optional::stream)
.collect(Collectors.joining("; ")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ public SimpleJsonFormatter() {
this.gson = new GsonFactory().provide();
}

@Override
public String getFormatName() {
return "simple-json";
}

@Override
public MediaType getMediaType() {
return MediaType.APPLICATION_JSON_TYPE;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.jabref.http.server.cayw.format;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.jabref.http.server.cayw.CAYWQueryParams;
import org.jabref.http.server.cayw.gui.CAYWEntry;
import org.jabref.model.entry.BibEntry;

import jakarta.ws.rs.core.MediaType;

public class TypstFormatter implements CAYWFormatter {

@Override
public MediaType getMediaType() {
return MediaType.TEXT_PLAIN_TYPE;
}

@Override
public String format(CAYWQueryParams queryParams, List<CAYWEntry> caywEntries) {
List<BibEntry> bibEntries = caywEntries.stream()
.map(CAYWEntry::bibEntry)
.toList();

return bibEntries.stream()
.map(entry -> entry.getCitationKey().map(key -> {
if (key.contains("/")) {
return "#cite(label(\"%s\"))".formatted(key);
} else {
return "#cite(<%s>)".formatted(key);
}
}))
.flatMap(Optional::stream)
.collect(Collectors.joining(" "));
}
}
19 changes: 18 additions & 1 deletion jabsrv/src/test/java/org/jabref/http/server/ServerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
import java.util.EnumSet;
import java.util.List;

import javafx.collections.FXCollections;

import org.jabref.http.JabRefSrvStateManager;
import org.jabref.http.SrvStateManager;
import org.jabref.http.dto.GlobalExceptionMapper;
import org.jabref.http.dto.GsonFactory;
import org.jabref.http.server.cayw.format.FormatterService;
import org.jabref.http.server.services.FilesToServe;
import org.jabref.logic.bibtex.FieldPreferences;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.preferences.CliPreferences;
import org.jabref.logic.preferences.LastFilesOpenedPreferences;
import org.jabref.model.entry.BibEntryPreferences;

import com.google.gson.Gson;
Expand All @@ -32,7 +36,7 @@
* </ul>
* <p>More information on testing with Jersey is available at <a href="https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/test-framework.html">the Jersey's testing documentation</a></p>.
*/
abstract class ServerTest extends JerseyTest {
public abstract class ServerTest extends JerseyTest {

private static CliPreferences preferences;

Expand Down Expand Up @@ -80,6 +84,15 @@ protected void configure() {
});
}

protected void addFormatterServiceToResourceConfig(ResourceConfig resourceConfig) {
resourceConfig.register(new AbstractBinder() {
@Override
protected void configure() {
bind(new FormatterService()).to(FormatterService.class);
}
});
}

protected void addPreferencesToResourceConfig(ResourceConfig resourceConfig) {
resourceConfig.register(new AbstractBinder() {
@Override
Expand Down Expand Up @@ -111,6 +124,10 @@ private static void initializePreferencesService() {
FieldPreferences fieldContentFormatterPreferences = new FieldPreferences(false, List.of(), List.of());
// used twice, once for reading and once for writing
when(importFormatPreferences.fieldPreferences()).thenReturn(fieldContentFormatterPreferences);

LastFilesOpenedPreferences lastFilesOpenedPreferences = mock(LastFilesOpenedPreferences.class);
when(preferences.getLastFilesOpenedPreferences()).thenReturn(lastFilesOpenedPreferences);
when(lastFilesOpenedPreferences.getLastFilesOpened()).thenReturn(FXCollections.emptyObservableList());
}

protected void addGlobalExceptionMapperToResourceConfig(ResourceConfig resourceConfig) {
Expand Down
Loading
Loading