Skip to content
Open
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
19 changes: 19 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,25 @@
<artifactId>picocli</artifactId>
<version>4.7.6</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.1</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.18.1</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.18.1</version>
</dependency>

</dependencies>

<build>
Expand Down
44 changes: 31 additions & 13 deletions src/main/java/ua/com/javarush/gnew/m2/cli/PhoneBookCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,51 @@
import ua.com.javarush.gnew.m2.cli.commands.ListContacts;
import ua.com.javarush.gnew.m2.cli.commands.SearchContact;
import ua.com.javarush.gnew.m2.cli.commands.SetUser;
import ua.com.javarush.gnew.m2.repository.ForSettingsRepository;
import ua.com.javarush.gnew.m2.service.PhoneBookInterface;
import ua.com.javarush.gnew.m2.service.SettingsService;
import ua.com.javarush.gnew.m2.service.SettingsServiceInterface;
import ua.com.javarush.gnew.m2.service.SimplePhoneBook;

import java.util.concurrent.Callable;

@Command(
name = "phonebook",
mixinStandardHelpOptions = true,
version = "PhoneBook CLI 1.0",
description = "CLI для управління контактами в телефонній книзі")
name = "phonebook",
mixinStandardHelpOptions = true,
version = "PhoneBook CLI 1.0",
description = "CLI для управління контактами в телефонній книзі"
)
public class PhoneBookCLI implements CliCommand {

private final SettingsServiceInterface settingsService;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Codacy found a medium Error Prone issue: Perhaps 'settingsService' could be replaced by a local variable.

The issue identified by the PMD linter suggests that the settingsService field may not need to be an instance variable (a class-level field) and could instead be a local variable. This typically occurs when the variable is not used outside of the constructor or the method where it is defined.

In this case, since settingsService is only being assigned in the constructor and not used elsewhere in the class, it can be made a local variable within the constructor.

Here's the code suggestion to fix the issue:

Suggested change
private final SettingsServiceInterface settingsService;
SettingsServiceInterface settingsService = settingsService;

However, since the suggestion above does not make sense as it stands, the correct approach would be to eliminate the field altogether and use a local variable in the constructor if the class does not require the field to be accessible outside the constructor. If you want to maintain the functionality of using settingsService across methods, then the current structure is appropriate.

If settingsService is indeed used elsewhere in the class, then the PMD warning may not be applicable, and it could be suppressed or ignored.

If we need to keep it as a field and suppress the warning, we can use the following:

  @SuppressWarnings("PMD.FieldNamingConventions")
  private final SettingsServiceInterface settingsService;

This would suppress the warning if you intend to keep the instance variable.


This comment was generated by an experimental AI tool.


public PhoneBookCLI(SettingsServiceInterface settingsService) {
this.settingsService = settingsService;
}

@Override
public Integer call() {
System.out.println("Використовуйте одну з команд: user, add, search, edit, delete, list");
System.out.println("Використовуйте одну з команд: user, add, search, edit, delete, list, locale");
return 0;
}

public static int init(String[] args) {

PhoneBookInterface phoneBook = new SimplePhoneBook();
SettingsServiceInterface settingsService = new SettingsService(new ForSettingsRepository());

return new CommandLine(new PhoneBookCLI())
.addSubcommand("add", new AddContact(phoneBook))
.addSubcommand("search", new SearchContact(phoneBook))
.addSubcommand("edit", new EditContact(phoneBook))
.addSubcommand("delete", new DeleteContact(phoneBook))
.addSubcommand("list", new ListContacts(phoneBook))
.addSubcommand("user", new SetUser())
.execute(args);
return new CommandLine(new PhoneBookCLI(settingsService))
.addSubcommand("add", new AddContact(phoneBook))
.addSubcommand("search", new SearchContact(phoneBook))
.addSubcommand("edit", new EditContact(phoneBook))
.addSubcommand("delete", new DeleteContact(phoneBook))
.addSubcommand("list", new ListContacts(phoneBook))
.addSubcommand("user", new SetUser())
.addSubcommand("locale", (Callable<Integer>) () -> {
settingsService.setLocale("uk");
System.out.println("Locale set to Ukrainian.");
return 0;
})
.execute(args);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Це потрібно робити в окремому класі наприклад:
@ Command(
name = "locale",
aliases = {"-l", "--locale"},
mixinStandardHelpOptions = true,
description = "")
public class SetLocale implements CliCommand{}

А саму локаль обробити за допомогою анотаціії:
@ Parameters(index = "0", description = "Фраза для пошуку", arity = "1")
private String newlocale;

тоді по команді> --locale "ua"
ми отримаємо підкапотом newlocale="ua;

}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,57 @@
package ua.com.javarush.gnew.m2.repository;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import ua.com.javarush.gnew.m2.dto.ContactDto;

public interface ContactDtoRepository {
List<ContactDto> findAll();
ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
default List<ContactDto> findAll() throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

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

ℹ️ Codacy found a minor Code Style issue: 'METHOD_DEF' should be separated from previous line.

The issue reported by the Checkstyle linter indicates that there should be a blank line separating the method definition from the previous line. This is a common coding style guideline that improves readability by providing visual separation between different methods or sections of code.

To fix the issue, you can simply add a blank line before the findAll method definition. Here is the suggested change:

Suggested change
default List<ContactDto> findAll() throws IOException {
default List<ContactDto> findAll() throws IOException {

This change maintains the existing functionality while adhering to the coding style guidelines.


This comment was generated by an experimental AI tool.

File file = new File("demo.st");
if (!file.exists()) {
return new ArrayList<>();
}
return objectMapper.readValue(file, objectMapper.getTypeFactory().constructCollectionType(List.class, ContactDto.class));
}


Optional<ContactDto> findById(long id);
default Optional<ContactDto> findById(long id) throws IOException {
return findAll().stream().filter(contact -> contact.getId() == id).findFirst();
}

void deleteById(long id);
default void deleteById(long id) throws IOException {
Optional<ContactDto> contactToDelete = findById(id);
if (contactToDelete.isPresent()) {
List<ContactDto> contacts = findAll();
contacts.remove(contactToDelete.get());
saveAll(contacts);
} else {
System.out.println("Контакт с id " + id + " не найден.");
}
}

void saveAll(List<ContactDto> contacts);
default void saveAll(List<ContactDto> contacts) throws IOException {
objectMapper.writeValue(new File("demo.st"),contacts);
}

void save(ContactDto contactDto);
default void save(ContactDto contactDto) throws IOException {
List<ContactDto> contacts = findAll();
contacts.add(contactDto);
saveAll(contacts);
}
default List<ContactDto> findByKeyword(String keyword) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

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

ℹ️ Codacy found a minor Code Style issue: 'METHOD_DEF' should be separated from previous line.

The issue reported by the Checkstyle linter indicates that there should be a blank line separating the method definition findByKeyword from the previous method (save). This is a common code style guideline that helps improve readability by visually separating method definitions.

To fix this issue, you can add a blank line before the findByKeyword method definition. Here’s the single line change to resolve the issue:

  <code suggestion>
    
    default List<ContactDto> findByKeyword(String keyword) throws IOException {

This comment was generated by an experimental AI tool.

List<ContactDto> contacts = findAll();
return contacts.stream()
.filter(contact -> contact.getFullName().contains(keyword) ||
contact.getPhones().stream().anyMatch(phones -> phones.contains(keyword)) ||
contact.getEmails().stream().anyMatch(emails -> emails.contains(keyword)))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ua.com.javarush.gnew.m2.repository;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class ForSettingsRepository implements SettingsRepository {

@Override
public void save(Map<String, String> settings) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

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

ℹ️ Codacy found a minor Code Style issue: Document empty method body

The PMD linter is indicating that the method save(Map<String, String> settings) has an empty body, which is generally considered poor practice because it lacks documentation. It is important to document the purpose of the method, even if it currently does not contain any implementation. This helps other developers understand the intended functionality and context of the method.

To fix this issue, you can add a comment inside the method body to indicate that the method is intentionally left empty, which serves as documentation for future reference.

Here's the suggested code change:

Suggested change
public void save(Map<String, String> settings) throws IOException {
public void save(Map<String, String> settings) throws IOException { // Intentionally left empty

This comment was generated by an experimental AI tool.

}

@Override
public Map<String, String> load() throws IOException {
return new HashMap<>();
}

@Override
public void saveSingleSetting(String key, String value) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

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

ℹ️ Codacy found a minor Code Style issue: Document empty method body

The issue identified by the PMD linter is that the method saveSingleSetting has an empty body, which is not documented. According to best practices in coding style, it's important to provide documentation for methods, especially when their implementation is not present, to clarify their intended purpose.

To fix this issue, you can add a comment documenting the method's purpose. Here’s the suggested change:

    // This method saves a single setting identified by the key with the provided value.
    public void saveSingleSetting(String key, String value) throws IOException {

This comment was generated by an experimental AI tool.

}

@Override
public String loadSingleSetting(String key) throws IOException {
return "";
}
}