From 7ae0426b2814bbe371a9ab27ffbeb86e8dfad2d1 Mon Sep 17 00:00:00 2001 From: jez04 <david.jezek@post.cz> Date: Wed, 30 Apr 2025 00:43:31 +0200 Subject: [PATCH] feat: :tada: solution lab 10 --- scores.csv | 1 + src/main/java/lab/MyEdit.java | 13 ++++ src/main/java/lab/data/Score.java | 10 +++ src/main/java/lab/gui/EditController.java | 81 ++++++++++++++++++++++- src/main/resources/msg.properties | 5 ++ src/main/resources/msg_cs.properties | 5 ++ src/main/resources/msg_cs_CZ.properties | 4 ++ src/main/resources/msg_en.properties | 6 ++ 8 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 src/main/java/lab/MyEdit.java create mode 100644 src/main/resources/msg.properties create mode 100644 src/main/resources/msg_cs.properties create mode 100644 src/main/resources/msg_cs_CZ.properties create mode 100644 src/main/resources/msg_en.properties diff --git a/scores.csv b/scores.csv index e8a4626..4bbb669 100644 --- a/scores.csv +++ b/scores.csv @@ -4,3 +4,4 @@ AppArchitect;88;MEDIUM DataDynamo;186;EASY AppArchitect;88;MEDIUM CodeConductor;273;MEDIUM +AppArchitect;88000;HARD diff --git a/src/main/java/lab/MyEdit.java b/src/main/java/lab/MyEdit.java new file mode 100644 index 0000000..07b46a5 --- /dev/null +++ b/src/main/java/lab/MyEdit.java @@ -0,0 +1,13 @@ +package lab; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface MyEdit { + public boolean readOnly() default false; + public boolean visible() default true; +} diff --git a/src/main/java/lab/data/Score.java b/src/main/java/lab/data/Score.java index 2be7983..4b91d6c 100644 --- a/src/main/java/lab/data/Score.java +++ b/src/main/java/lab/data/Score.java @@ -8,6 +8,7 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import lab.MyEdit; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.EqualsAndHashCode; @@ -30,12 +31,21 @@ public class Score { @Id @GeneratedValue(strategy = GenerationType.AUTO) + @MyEdit(visible = false) private Long id; + @MyEdit(readOnly = true) private String name; + @MyEdit private int points; @Enumerated(EnumType.STRING) + @MyEdit private Level level; + + public String getVirtual(){ + return "aaaa"; + } + public static Score generate() { return new Score(null, getRandomNick(), RANDOM.nextInt(50, 300), Level.values()[RANDOM.nextInt(Level.values().length)]); diff --git a/src/main/java/lab/gui/EditController.java b/src/main/java/lab/gui/EditController.java index 701243e..1a32160 100644 --- a/src/main/java/lab/gui/EditController.java +++ b/src/main/java/lab/gui/EditController.java @@ -1,7 +1,14 @@ package lab.gui; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; +import java.util.ResourceBundle; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -14,6 +21,7 @@ import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.layout.GridPane; import javafx.stage.Stage; +import lab.MyEdit; import lab.data.Score; import lombok.Setter; @@ -50,7 +58,51 @@ public class EditController { @FXML void btnOkAction(ActionEvent event) { - //TODO: add code to read values from text fields + try { + BeanInfo beanInfo = Introspector.getBeanInfo(data.getClass()); + for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) { + try { + String name = propertyDescriptor.getName(); + Field field = data.getClass().getDeclaredField(name); + MyEdit myEdit = field.getAnnotation(MyEdit.class); + if(myEdit == null || !myEdit.visible() || myEdit.readOnly()) { + continue; + } + TextField textField = nameToTextField.get(name); + String stringValue = textField.getText(); + Object value = null; + if (propertyDescriptor.getPropertyType() == String.class) { + value = stringValue; + } else if (stringValue == null || stringValue.isBlank()) { + value = null; + } else if (propertyDescriptor.getPropertyType() == Integer.class + || propertyDescriptor.getPropertyType() == int.class) { + value = Integer.parseInt(stringValue); + } else if (propertyDescriptor.getPropertyType() == Long.class + || propertyDescriptor.getPropertyType() == long.class) { + value = Long.parseLong(stringValue); + } else if (propertyDescriptor.getPropertyType() == Double.class + || propertyDescriptor.getPropertyType() == double.class) { + value = Double.parseDouble(stringValue); + } else if (propertyDescriptor.getPropertyType().isEnum()) { + for (Object enumConstant : propertyDescriptor.getPropertyType().getEnumConstants()) { + if (enumConstant.toString().equalsIgnoreCase(stringValue)) { + value = enumConstant; + break; + } + } + } + if (propertyDescriptor.getWriteMethod() != null) { + propertyDescriptor.getWriteMethod().invoke(data, value); + } + } catch (NoSuchFieldException e) { + log.warn("property {} has no field", propertyDescriptor.getName()); + } + } + } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) { + log.error(e); + } + mainScreenController.updateData((Score)data); stage.hide(); @@ -71,7 +123,32 @@ public class EditController { log.info("data set {}", data); content.getChildren().clear(); - //TODO: code to detect properties and add rows to dialog + ResourceBundle msg = ResourceBundle.getBundle("msg"); + try { + BeanInfo beanInfo = Introspector.getBeanInfo(data.getClass()); + int row = 0; + for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) { + try { + Field field = data.getClass().getDeclaredField(propertyDescriptor.getName()); + MyEdit myEdit = field.getAnnotation(MyEdit.class); + if (myEdit == null) { + continue; + } + if (!myEdit.visible()) { + continue; + } + String name = propertyDescriptor.getName(); + Object value = propertyDescriptor.getReadMethod().invoke(data); + String localizedName = msg.getString(String.format("%s.%s", data.getClass().getSimpleName(), field.getName())); + addDialogRow(row, name, localizedName, value != null ? value.toString() : "", !myEdit.readOnly()); + row++; + } catch (NoSuchFieldException e) { + log.warn("property '{}' has no field in class '{}'", propertyDescriptor.getName(), data.getClass().getCanonicalName()); + } + } + } catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) { + log.error(e); + } } private void addDialogRow(int rowNumber, String name, String descriptionName, String stringValue, diff --git a/src/main/resources/msg.properties b/src/main/resources/msg.properties new file mode 100644 index 0000000..d0655f9 --- /dev/null +++ b/src/main/resources/msg.properties @@ -0,0 +1,5 @@ + +Score.id = id +Score.level = level +Score.name = name +Score.points = points diff --git a/src/main/resources/msg_cs.properties b/src/main/resources/msg_cs.properties new file mode 100644 index 0000000..e397613 --- /dev/null +++ b/src/main/resources/msg_cs.properties @@ -0,0 +1,5 @@ + +Score.id = Jednozna\u010Dn\u00FD identifik\u00E1tor +Score.level = Obt\u00ED\u017Enost +Score.name = Jm\u00E9no +Score.points = Body diff --git a/src/main/resources/msg_cs_CZ.properties b/src/main/resources/msg_cs_CZ.properties new file mode 100644 index 0000000..73f926b --- /dev/null +++ b/src/main/resources/msg_cs_CZ.properties @@ -0,0 +1,4 @@ +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) + +Score.id = Jedine\u010Dn\u00FD identifik\u00E1tor +Score.name = N\u00E1zev diff --git a/src/main/resources/msg_en.properties b/src/main/resources/msg_en.properties new file mode 100644 index 0000000..83da6ab --- /dev/null +++ b/src/main/resources/msg_en.properties @@ -0,0 +1,6 @@ +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) + +Score.id = Unique identificator +Score.level = Level +Score.name = Name +Score.points = Points -- GitLab