diff --git a/src/Main.java b/src/Main.java index 599280a..db98c2c 100644 --- a/src/Main.java +++ b/src/Main.java @@ -29,6 +29,8 @@ public class Main { s.createContext("/", new RootView()); s.createContext("/main", new StartView()); s.createContext("/auth", new AuthView()); + s.createContext("/tree", new TreeView()); + s.createContext("/object", new ObjectView()); s.setExecutor(null); s.start(); } catch (IOException e) { diff --git a/src/data/DataObject.java b/src/data/DataObject.java index 4ce9e56..d2c37cf 100644 --- a/src/data/DataObject.java +++ b/src/data/DataObject.java @@ -1,56 +1,42 @@ package hsmw.jotto5.beleg.data; +import java.lang.annotation.*; + /** * Basisklasse für ein beliebiges DataObject. * * Alle spezifischen Objekte (im Sinne dieser Anwendung) erben von dieser Klasse. - * DataObjects haben eine UID. Diese wird im Model vergeben, und ist einmalig. - * Vorgesehen ist die UID als Pfad-formatierter String mit "/" als Trennsymbol, um - * DataObjects hierarchisch zu gliedern - der Inhalt ist aber eigentlich egal - * (solange eindeutig). *

- * Für alle DataObjects gilt, dass der Zugriff auf Methoden und Felder der Objekte - * nicht definiert ist, solange sie nicht an ein Modell gebunden sind. + * Das DataObject und alle Kindklassen sind für Klassen außerhalb des Data-Pakets vollständig mutable, + * um das Bearbeiten über das Webinterface zu erlauben. */ public abstract class DataObject { - protected Model model; // DataObjects speichern eine Referenz auf das Modell zu dem sie gehören - protected String uid; // einmalige UID des Objektes - protected String displayName; + /** + * Annotation um über das Webinterface abrufbare Felder zu kennzeichnen. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface WebField { + public String displayAs() default ""; + } + + @WebField(displayAs = "Anzeigename") + public final String displayName; + + // Wird absichtlich nicht angezeigt, als Demonstration + public final String uid; /** * Konstruktor für manuelles Erzeugen. * * Wird nur von Kindklassen verwendet. Dient dazu, ein temporäres * DataObject ohne Model-Bindung zu erzeugen. - * @param uid Die vorgegebene UID des Objektes (wird beim Binden an ein Model verwendet) * @param displayName Der Anzeigename des Objektes */ protected DataObject(String uid, String displayName) { - this.model = null; this.uid = uid; this.displayName = displayName; } - /** - * Setzt das Model. - * - * Nur aus dem Model zu verwenden! - */ - protected void setModel(Model m) { - this.model = m; - } - - public Model getModel() { - return this.model; - } - - public String getDisplayName() { - return this.displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - } diff --git a/src/data/Group.java b/src/data/Group.java index 8ff3e45..810ac54 100644 --- a/src/data/Group.java +++ b/src/data/Group.java @@ -15,11 +15,4 @@ public class Group extends DataObject { super(uid, displayName); } - /** - * Fügt das DataObject mit der gegebenen UID zu der Gruppe hinzu. - */ - public void addMember(String uid) { - this.model.addRelation(this.uid, uid); - } - } diff --git a/src/data/Model.java b/src/data/Model.java index da93223..8e28d66 100644 --- a/src/data/Model.java +++ b/src/data/Model.java @@ -46,53 +46,52 @@ public class Model { * Füllt das Model mit Beispieldaten. */ public void fillMockData() { - Group g1, g2, g3; - // Studierende - this.add(new Student("students/jotto5", "Jocelyn", "Otto")); - this.add(new Student("students/vnachn", "Vorname", "Nachname")); - this.add(new Student("students/alovel", "Ada", "Lovelace")); - this.add(new Student("students/aturin", "Alan", "Turing")); - this.add(new Student("students/dknuth", "Donald", "Knuth")); - this.add(new Student("students/ltorva", "Linus", "Torvalds")); - this.add(new Student("students/dritch", "Dennis", "Ritchie")); + this.add(new Student("students/jotto5", "Jocelyn", "Otto", "0001")); + this.add(new Student("students/vnachn", "Vorname", "Nachname", "0002")); + this.add(new Student("students/alovel", "Ada", "Lovelace", "0003")); + this.add(new Student("students/aturin", "Alan", "Turing", "0004")); + this.add(new Student("students/dknuth", "Donald", "Knuth", "0005")); + this.add(new Student("students/ltorva", "Linus", "Torvalds", "0006")); + this.add(new Student("students/dritch", "Dennis", "Ritchie", "0007")); // Gruppen - g1 = new Group("groups/IF24wS2-B", "Softwareentwicklung WiSe 24/25 Seminargruppe 2"); - g2 = new Group("groups/admins", "Administrator:innen"); - g3 = new Group("groups/alumni", "Alumni"); + this.add(new Group("groups/IF24wS2-B", "Softwareentwicklung WiSe 24/25 Seminargruppe 2")); + this.add(new Group("groups/admins", "Administrator:innen")); + this.add(new Group("groups/alumni", "Alumni")); this.add(new Group("groups/leer", "Leere Gruppe")); - this.add(g1); - this.add(g2); - this.add(g3); - g1.addMember("students/jotto5"); - g2.addMember("students/vnachn"); - g2.addMember("students/ltorva"); - g3.addMember("students/alovel"); - g3.addMember("students/aturin"); - g3.addMember("students/ltorva"); + + this.addRelation("groups/if24ws2-b", "students/jotto5"); + this.addRelation("groups/admins", "students/vnachn"); + this.addRelation("groups/admins", "students/ltorva"); + this.addRelation("groups/alumni", "students/alovel"); + this.addRelation("groups/alumni", "students/aturin"); + this.addRelation("groups/alumni", "students/ltorva"); } /** - * Fügt ein neues DataObject hinzu, also bindet es an das Model. + * Fügt ein neues DataObject hinzu. */ public void add(DataObject a) { // TODO: Auf doppelte UIDs überprüfen! this.objs.put(a.uid, a); - a.setModel(this); } - /* - * Folgende Funktionen sind nur durch die DataObject-Objekte - * zu verwenden, und sind daher protected. - */ - /** * Fügt eine neue Objekt-Beziehung hinzu. */ - protected void addRelation(String a, String b) { + public void addRelation(String a, String b) { // TODO: Prüfen ob die Objekte existieren! this.relations.put(a, b); } + /** + * Gibt das DataObject mit der angegebenen UID zurück + * oder null wenn es keines gibt. + */ + public DataObject get(String path) { + if ( !objs.containsKey(path) ) return null; + return objs.get(path); + } + } diff --git a/src/data/Person.java b/src/data/Person.java new file mode 100644 index 0000000..45487bb --- /dev/null +++ b/src/data/Person.java @@ -0,0 +1,28 @@ +package hsmw.jotto5.beleg.data; + +/** + * Verkapselt einige Daten die über alle Arten von Personen wichtig sind. + */ +public abstract class Person extends DataObject { + + @WebField(displayAs = "Vorname") + public final String name; + + @WebField(displayAs = "Nachname") + public final String lastName; + + /** + * Konstruktor. + * + * Der displayName wird aus Vor- und Nachname zusammengesetzt. + * @param uid Die zu vergebende UID + * @param name Der Vorname + * @param lastName Der Nachname + */ + public Person(String uid, String name, String lastName) { + super(uid, lastName + ", " + name); + this.name = name; + this.lastName = lastName; + } + +} diff --git a/src/data/Student.java b/src/data/Student.java index 9f2ced2..0b7fdb9 100644 --- a/src/data/Student.java +++ b/src/data/Student.java @@ -3,40 +3,23 @@ package hsmw.jotto5.beleg.data; /** * Beschreibt eine studierende Person. */ -public class Student extends DataObject { +public class Student extends Person { - private String name; - private String lastName; + @WebField(displayAs = "Matrikelnummer") + public String studentNumber; /** * Konstruktor zum manuellen Erzeugen. * - * Der displayName wird aus Vor- und Nachname zusammengesetzt. Beim Ändern der - * Namensattribute wird die UID NICHT neu vergeben! + * Siehe auch Konstruktor der Person-Klasse. * @param uid Die zu vergebende UID * @param name Der Vorname * @param lastName Der Nachname + * @param number Die Matrikelnummer */ - public Student(String uid, String name, String lastName) { - super(uid, lastName + ", " + name); - this.name = name; - this.lastName = lastName; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLastName() { - return this.lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; + public Student(String uid, String name, String lastName, String studentNumber) { + super(uid, name, lastName); + this.studentNumber = studentNumber; } } diff --git a/src/views/Defaults.java b/src/views/Defaults.java index 5fd99c7..4c4b678 100644 --- a/src/views/Defaults.java +++ b/src/views/Defaults.java @@ -5,7 +5,7 @@ package hsmw.jotto5.beleg.views; */ public class Defaults { - public static final String HTMLHEADER = "Beleg SoSe 2025

"; - public static final String HTMLFOOTER = "
"; + public static final String HTMLHEADER = "Beleg SoSe 2025

"; + public static final String HTMLFOOTER = "
"; } diff --git a/src/views/ObjectView.java b/src/views/ObjectView.java new file mode 100644 index 0000000..b5674ce --- /dev/null +++ b/src/views/ObjectView.java @@ -0,0 +1,57 @@ +package hsmw.jotto5.beleg.views; + +import hsmw.jotto5.beleg.data.DataObject; +import hsmw.jotto5.beleg.data.Model; + +import java.io.IOException; +import java.io.OutputStream; +import com.sun.net.httpserver.*; +import java.lang.reflect.*; + +public class ObjectView implements HttpHandler { + + public void handle(HttpExchange t) throws IOException { + String response; + String objectPath; + OutputStream os; + Model m = Model.getModel(); + DataObject obj = null; + + // Das angefragte Objekt finden + objectPath = t.getRequestURI().toString(); + if (objectPath.length() >= 9) { + objectPath = objectPath.substring(8); + obj = m.get(objectPath); + } + + if ( obj == null ) return; // TODO: 404 oder 500 zurückgeben! + + // Die Tabelle ausgeben + response = Defaults.HTMLHEADER + "

Beleg - Objektansicht

"; + response += ""; + try { + for (Field f : obj.getClass().getFields()) { + if (f.isAnnotationPresent(DataObject.WebField.class)) { + // Das Feld hat die "WebField"-Annotation, ist also anzuzeigen + response += ""; + // Feld anzeigen + response += ""; + } + } + } catch(IllegalAccessException e) { + // hier sollten wir niemals her kommen + // TODO: 500 werfen + e.printStackTrace(); + } + + response += "
" + f.getAnnotation(DataObject.WebField.class).displayAs() + "
"; + + response += Defaults.HTMLFOOTER; + os = t.getResponseBody(); + + t.sendResponseHeaders(200, response.length()); + os.write(response.getBytes()); + os.close(); + } + +} diff --git a/src/views/TreeView.java b/src/views/TreeView.java new file mode 100644 index 0000000..dc0406d --- /dev/null +++ b/src/views/TreeView.java @@ -0,0 +1,21 @@ +package hsmw.jotto5.beleg.views; + +import java.io.IOException; +import java.io.OutputStream; +import com.sun.net.httpserver.*; + +public class TreeView implements HttpHandler { + + public void handle(HttpExchange t) throws IOException { + String response; + OutputStream os; + + response = Defaults.HTMLHEADER + "

Beleg - Objektübersicht

" + Defaults.HTMLFOOTER; + os = t.getResponseBody(); + + t.sendResponseHeaders(200, response.length()); + os.write(response.getBytes()); + os.close(); + } + +} diff --git a/static/style.css b/static/style.css index d92d6df..46addce 100644 --- a/static/style.css +++ b/static/style.css @@ -2,7 +2,40 @@ font-family: sans-serif; } +body { + background-color: #ccc; + padding: 0px; + margin: 0px; +} + main { - max-width: 600px; + background-color: #fff; + padding: 10px; + width: 100%; +} + +footer { + background-color: #eee; + width: 100%; + padding: 10px; + padding-bottom: 75px; +} + +#content { + max-width: 900px; margin: auto; -} \ No newline at end of file +} + +.objecttable { + width: 100%; + margin-bottom: 10px; +} + +.objecttable td { + border-bottom: black 1px solid; + width: 50%; +} + +.objecttable td input { + width: 100%; +}