initial commit

This commit is contained in:
2025-12-09 15:40:47 +01:00
commit 91c731fef4
28 changed files with 690 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
.kotlin
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
+3
View File
@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$USER_HOME$/src/main/java" charset="UTF-8" />
<file url="file://$USER_HOME$/src/main/resources" charset="UTF-8" />
</component>
</project>
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="22" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+3
View File
@@ -0,0 +1,3 @@
Jan;Novak;1990-05-12;jan.novak@email.com;777123456
Petra;Svobodova;1985-11-02;petra.svobodova@email.com;777654321
Karel;Dvorak;2000-07-20;karel.dvorak@email.com;777987654
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cz.jzitnik</groupId>
<artifactId>commandmezabijejednou</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>22</maven.compiler.source>
<maven.compiler.target>22</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
</dependencies>
</project>
+9
View File
@@ -0,0 +1,9 @@
“Matematika je jazyk, kterým Bůh napsal vesmír.” Galileo Galilei
“Neexistuje žádná krása bez harmonie.” Plato
“Život je jako jízda na kole. Abys udržel rovnováhu, musíš se pohybovat vpřed.” Albert Einstein
“V každém problému se skrývá řešení.” Neznámý
“Pranostika: Na svatého Jiří přijde jaro brzy, nebo později zima zhoustne.”
E=mc^2
F = ma
a^2 + b^2 = c^2
∑_{i=1}^{n} i = n(n+1)/2
+95
View File
@@ -0,0 +1,95 @@
package cz.jzitnik;
import cz.jzitnik.annotations.CommandImpl;
import cz.jzitnik.commands.models.Command;
import cz.jzitnik.services.ClassFactory;
import cz.jzitnik.services.CommandHistory;
import cz.jzitnik.services.CommandInvoker;
import org.reflections.Reflections;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
public class Console implements Runnable {
private final CommandInvoker invoker = new CommandInvoker();
private final ClassFactory factory = new ClassFactory();
@Override
public void run() {
factory.load();
loadCommands();
Scanner sc = new Scanner(System.in);
System.out.println("Type 'help' for commands.");
boolean running = true;
while (running) {
System.out.print("-> ");
String input = sc.nextLine();
((CommandHistory) factory.get(CommandHistory.class)).add(input);
if (input.equals("stop")) {
running = false;
continue;
}
if (input.equals("help")) {
HashMap<String, Command> commands = invoker.getCommands();
System.out.println(commands.keySet());
continue;
}
String[] parts = input.split(" ", 2);
String cmd = parts[0];
String args2 = parts.length > 1 ? parts[1] : "";
String result = invoker.execute(cmd, args2);
System.out.println(result);
}
sc.close();
}
private void loadCommands() {
Reflections reflections = new Reflections("cz.jzitnik.commands");
List<? extends Class<? extends Command>> entityClasses =
reflections.getTypesAnnotatedWith(CommandImpl.class).stream()
.filter(Command.class::isAssignableFrom)
.map(i -> (Class<? extends Command>) i)
.toList();
for (Class<? extends Command> command : entityClasses) {
CommandImpl annotation = command.getAnnotation(CommandImpl.class);
for (var constructor : command.getDeclaredConstructors()) {
var paramTypes = constructor.getParameterTypes();
var params = new Object[paramTypes.length];
boolean suitable = true;
for (int i = 0; i < paramTypes.length; i++) {
Class<?> type = paramTypes[i];
if (factory.contains(type))
params[i] = factory.get(type);
else {
suitable = false;
break;
}
}
if (suitable) {
constructor.setAccessible(true);
try {
Command instance = (Command) constructor.newInstance(params);
invoker.register(annotation.value(), instance);
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
break; // Found a matching constructor, go to next class
}
}
}
}
}
+9
View File
@@ -0,0 +1,9 @@
package cz.jzitnik;
public class Main {
public static void main(String[] args) {
Console console = new Console();
console.run();
}
}
@@ -0,0 +1,12 @@
package cz.jzitnik.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CommandImpl {
String value();
}
@@ -0,0 +1,11 @@
package cz.jzitnik.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Config {
}
@@ -0,0 +1,11 @@
package cz.jzitnik.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Data {
}
@@ -0,0 +1,52 @@
package cz.jzitnik.commands;
import cz.jzitnik.annotations.CommandImpl;
import cz.jzitnik.commands.models.Command;
import cz.jzitnik.factory.Contact;
import cz.jzitnik.repository.ContactRepository;
@CommandImpl("contacts <operation;parameters>")
public class ContactCommand implements Command {
private final ContactRepository cm;
public ContactCommand(ContactRepository cm) {
this.cm = cm;
}
@Override
public String execute(String args) {
// `args` ve formátu:
// add;jmeno;prijmeni;datum;email;telefon
// delete;telefon
// searchln;prijmeni
// searchph;telefon
// edit;staryTelefon;jmeno;prijmeni;datum;email;telefon
String[] p = args.split(";");
return switch (p[0]) {
case "add" -> {
Contact c = new Contact();
c.firstName = p[1];
c.lastName = p[2];
c.birthdate = p[3];
c.email = p[4];
c.phone = p[5];
yield cm.add(c);
}
case "delete" -> cm.delete(p[1]);
case "searchln" -> cm.searchLastName(p[1]);
case "searchph" -> cm.searchPhone(p[1]);
case "edit" -> {
Contact c = new Contact();
c.firstName = p[2];
c.lastName = p[3];
c.birthdate = p[4];
c.email = p[5];
c.phone = p[6];
yield cm.edit(p[1], c);
}
default -> String.join("\n", cm.getContacts().stream().map(Contact::toString).toList());
};
}
}
@@ -0,0 +1,14 @@
package cz.jzitnik.commands;
import cz.jzitnik.annotations.CommandImpl;
import cz.jzitnik.commands.models.Command;
import java.time.LocalDateTime;
@CommandImpl("datetime")
public class DateTimeCommand implements Command {
@Override
public String execute(String args) {
return LocalDateTime.now().toString();
}
}
@@ -0,0 +1,20 @@
package cz.jzitnik.commands;
import cz.jzitnik.annotations.CommandImpl;
import cz.jzitnik.commands.models.Command;
import cz.jzitnik.services.CommandHistory;
@CommandImpl("history")
public class HistoryCommand implements Command {
private final CommandHistory history;
public HistoryCommand(CommandHistory h) {
this.history = h;
}
@Override
public String execute(String args) {
return String.join("\n", history.getAll());
}
}
@@ -0,0 +1,44 @@
package cz.jzitnik.commands;
import cz.jzitnik.annotations.CommandImpl;
import cz.jzitnik.commands.models.Command;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@CommandImpl("quadratic Ax^2+Bx+C")
public class QuadraticCommand implements Command {
@Override
public String execute(String eq) {
try {
eq = eq.replace(" ", "");
Pattern p = Pattern.compile("([+-]?\\d*)x\\^2([+-]\\d*)x([+-]\\d+)");
Matcher m = p.matcher(eq);
if (!m.matches()) {
return "Neplatný formát. Example: 4x^2+3x-2";
}
double A = m.group(1).equals("") || m.group(1).equals("+") ? 1 :
m.group(1).equals("-") ? -1 : Double.parseDouble(m.group(1));
double B = Double.parseDouble(m.group(2));
double C = Double.parseDouble(m.group(3));
double D = B * B - 4 * A * C;
if (D < 0) {
return "Žádné reálné kořeny.";
}
double x1 = (-B + Math.sqrt(D)) / (2 * A);
double x2 = (-B - Math.sqrt(D)) / (2 * A);
return "Kořeny: " + x1 + ", " + x2;
} catch (Exception e) {
return "Error parsing equation.";
}
}
}
@@ -0,0 +1,32 @@
package cz.jzitnik.commands;
import cz.jzitnik.annotations.CommandImpl;
import cz.jzitnik.commands.models.Command;
import cz.jzitnik.config.models.QuoteConfig;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Random;
@CommandImpl("quotes")
public class QuoteCommand implements Command {
private final List<String> quotes;
public QuoteCommand(QuoteConfig config) {
List<String> temp;
try {
temp = Files.readAllLines(Paths.get(config.getFilePath()));
} catch (Exception e) {
temp = List.of("No quotes found.");
}
quotes = temp;
}
@Override
public String execute(String args) {
Random r = new Random();
return quotes.get(r.nextInt(quotes.size()));
}
}
@@ -0,0 +1,5 @@
package cz.jzitnik.commands.models;
public interface Command {
String execute(String args);
}
@@ -0,0 +1,12 @@
package cz.jzitnik.config;
import cz.jzitnik.annotations.Config;
import cz.jzitnik.config.models.ContactRepositoryConfig;
@Config
public class ContactRepositoryConfigImpl implements ContactRepositoryConfig {
@Override
public String getFilePath() {
return "kontakty.txt";
}
}
@@ -0,0 +1,12 @@
package cz.jzitnik.config;
import cz.jzitnik.annotations.Config;
import cz.jzitnik.config.models.QuoteConfig;
@Config
public class QuoteConfigImpl implements QuoteConfig {
@Override
public String getFilePath() {
return "quotes.txt";
}
}
@@ -0,0 +1,5 @@
package cz.jzitnik.config.models;
public interface ContactRepositoryConfig {
String getFilePath();
}
@@ -0,0 +1,5 @@
package cz.jzitnik.config.models;
public interface QuoteConfig {
String getFilePath();
}
@@ -0,0 +1,25 @@
package cz.jzitnik.factory;
public class Contact {
public String firstName;
public String lastName;
public String birthdate;
public String email;
public String phone;
@Override
public String toString() {
return firstName + ";" + lastName + ";" + birthdate + ";" + email + ";" + phone;
}
public static Contact fromString(String s) {
String[] p = s.split(";");
Contact c = new Contact();
c.firstName = p[0];
c.lastName = p[1];
c.birthdate = p[2];
c.email = p[3];
c.phone = p[4];
return c;
}
}
@@ -0,0 +1,86 @@
package cz.jzitnik.repository;
import cz.jzitnik.annotations.Data;
import cz.jzitnik.config.models.ContactRepositoryConfig;
import cz.jzitnik.factory.Contact;
import java.io.*;
import java.util.*;
@Data
public class ContactRepository {
private final String filePath;
private final List<Contact> contacts = new ArrayList<>();
public List<Contact> getContacts() {
return contacts;
}
public ContactRepository(ContactRepositoryConfig config) {
this.filePath = config.getFilePath();
load();
}
private void load() {
try {
File f = new File(filePath);
if (!f.exists()) return;
try (Scanner sc = new Scanner(f)) {
while (sc.hasNextLine()) {
contacts.add(Contact.fromString(sc.nextLine()));
}
}
} catch (Exception ignored) {}
}
private void save() {
try (PrintWriter pw = new PrintWriter(filePath)) {
for (Contact c : contacts) pw.println(c);
} catch (Exception ignored) {}
}
public String add(Contact c) {
contacts.add(c);
save();
return "Contact added.";
}
public String edit(String phone, Contact updated) {
for (Contact c : contacts) {
if (c.phone.equals(phone)) {
c.firstName = updated.firstName;
c.lastName = updated.lastName;
c.birthdate = updated.birthdate;
c.email = updated.email;
c.phone = updated.phone;
save();
return "Contact updated.";
}
}
return "Contact not found.";
}
public String delete(String phone) {
boolean removed = contacts.removeIf(c -> c.phone.equals(phone));
save();
return removed ? "Contact removed." : "Contact not found.";
}
public String searchLastName(String ln) {
StringBuilder sb = new StringBuilder();
contacts.stream()
.filter(c -> c.lastName.equalsIgnoreCase(ln))
.forEach(c -> sb.append(c).append("\n"));
return sb.length() == 0 ? "Not found." : sb.toString();
}
public String searchPhone(String ph) {
StringBuilder sb = new StringBuilder();
contacts.stream()
.filter(c -> c.phone.equals(ph))
.forEach(c -> sb.append(c).append("\n"));
return sb.length() == 0 ? "Not found." : sb.toString();
}
}
@@ -0,0 +1,78 @@
package cz.jzitnik.services;
import cz.jzitnik.annotations.Config;
import cz.jzitnik.annotations.Data;
import org.reflections.Reflections;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Set;
public class ClassFactory {
private final HashMap<Class<?>, Object> instances = new HashMap<>();
public HashMap<Class<?>, Object> getInstances() {
return instances;
}
public boolean contains(Class<?> clazz) {
return instances.keySet().stream().anyMatch(clazzIn -> clazz.isAssignableFrom(clazzIn));
}
public Object get(Class<?> clazz) {
for (Class<?> clazzInDb : instances.keySet()) {
if (clazz.isAssignableFrom(clazzInDb)) {
return instances.get(clazzInDb);
}
}
return null;
}
public void load() {
Reflections reflections = new Reflections("cz.jzitnik");
Set<Class<?>> configs = reflections.getTypesAnnotatedWith(Config.class);
for (Class<?> config : configs) {
try {
var instance = config.getDeclaredConstructor().newInstance();
instances.put(config, instance);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
Set<Class<?>> entityClasses = reflections.getTypesAnnotatedWith(Data.class);
for (Class<?> clazz : entityClasses) {
for (var constructor : clazz.getDeclaredConstructors()) {
var paramTypes = constructor.getParameterTypes();
var params = new Object[paramTypes.length];
boolean suitable = true;
for (int i = 0; i < paramTypes.length; i++) {
Class<?> type = paramTypes[i];
if (contains(type))
params[i] = get(type);
else {
suitable = false;
break;
}
}
if (suitable) {
constructor.setAccessible(true);
try {
Object instance = constructor.newInstance(params);
instances.put(clazz, instance);
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
break; // Found a matching constructor, go to next class
}
}
}
}
}
@@ -0,0 +1,19 @@
package cz.jzitnik.services;
import cz.jzitnik.annotations.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class CommandHistory {
private final List<String> list = new ArrayList<>();
public void add(String cmd) {
list.add(cmd);
}
public List<String> getAll() {
return list;
}
}
@@ -0,0 +1,35 @@
package cz.jzitnik.services;
import cz.jzitnik.commands.models.Command;
import java.util.HashMap;
public class CommandInvoker {
private final HashMap<String, Command> commands = new HashMap<>();
public HashMap<String, Command> getCommands() {
return commands;
}
private Command get(String name) {
for (String cmd : commands.keySet()) {
if ((cmd + " ").split(" ")[0].equals(name)) {
return commands.get(cmd);
}
}
return null;
}
public void register(String name, Command cmd) {
commands.put(name, cmd);
}
public String execute(String name, String args) {
Command cmd = get(name);
if (cmd != null) {
return cmd.execute(args);
}
return "Unknown command.";
}
}