forked from IF-LK-2020/wordle
Initial commit
This commit is contained in:
commit
53beb78043
|
@ -0,0 +1,28 @@
|
||||||
|
# ---> Java
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
Dokumente*
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
# Engine-Alpha files
|
||||||
|
engine-alpha.log
|
|
@ -0,0 +1,148 @@
|
||||||
|
import java.sql.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Klasse DatabaseConnector
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Ein Objekt der Klasse DatabaseConnector ermoeglicht die Abfrage und Manipulation
|
||||||
|
* einer SQLite-Datenbank.
|
||||||
|
* Beim Erzeugen des Objekts wird eine Datenbankverbindung aufgebaut, so dass
|
||||||
|
* anschließend SQL-Anweisungen an diese Datenbank gerichtet werden koennen.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
|
||||||
|
* @version 2016-01-24
|
||||||
|
*/
|
||||||
|
public class DatabaseConnector{
|
||||||
|
private java.sql.Connection connection;
|
||||||
|
private QueryResult currentQueryResult = null;
|
||||||
|
private String message = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ein Objekt vom Typ DatabaseConnector wird erstellt, und eine Verbindung zur Datenbank
|
||||||
|
* wird aufgebaut. Mit den Parametern pIP und pPort werden die IP-Adresse und die
|
||||||
|
* Port-Nummer uebergeben, unter denen die Datenbank mit Namen pDatabase zu erreichen ist.
|
||||||
|
* Mit den Parametern pUsername und pPassword werden Benutzername und Passwort fuer die
|
||||||
|
* Datenbank uebergeben.
|
||||||
|
*/
|
||||||
|
public DatabaseConnector(String pIP, int pPort, String pDatabase, String pUsername, String pPassword){
|
||||||
|
//Eine Impementierung dieser Schnittstelle fuer SQLite ignoriert pID und pPort, da die Datenbank immer lokal ist.
|
||||||
|
//Auch pUsername und pPassword werden nicht verwendet, da SQLite sie nicht unterstuetzt.
|
||||||
|
try {
|
||||||
|
//Laden der Treiberklasse
|
||||||
|
Class.forName("org.sqlite.JDBC");
|
||||||
|
|
||||||
|
//Verbindung herstellen
|
||||||
|
connection = DriverManager.getConnection("jdbc:sqlite:"+pDatabase);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
message = e.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Auftrag schickt den im Parameter pSQLStatement enthaltenen SQL-Befehl an die
|
||||||
|
* Datenbank ab.
|
||||||
|
* Handelt es sich bei pSQLStatement um einen SQL-Befehl, der eine Ergebnismenge
|
||||||
|
* liefert, so kann dieses Ergebnis anschließend mit der Methode getCurrentQueryResult
|
||||||
|
* abgerufen werden.
|
||||||
|
*/
|
||||||
|
public void executeStatement(String pSQLStatement){
|
||||||
|
//Altes Ergebnis loeschen
|
||||||
|
currentQueryResult = null;
|
||||||
|
message = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
//Neues Statement erstellen
|
||||||
|
Statement statement = connection.createStatement();
|
||||||
|
|
||||||
|
//SQL Anweisung an die DB schicken.
|
||||||
|
if (statement.execute(pSQLStatement)) { //Fall 1: Es gibt ein Ergebnis
|
||||||
|
|
||||||
|
//Resultset auslesen
|
||||||
|
ResultSet resultset = statement.getResultSet();
|
||||||
|
|
||||||
|
//Spaltenanzahl ermitteln
|
||||||
|
int columnCount = resultset.getMetaData().getColumnCount();
|
||||||
|
|
||||||
|
//Spaltennamen und Spaltentypen in Felder uebertragen
|
||||||
|
String[] resultColumnNames = new String[columnCount];
|
||||||
|
String[] resultColumnTypes = new String[columnCount];
|
||||||
|
for (int i = 0; i < columnCount; i++){
|
||||||
|
resultColumnNames[i] = resultset.getMetaData().getColumnLabel(i+1);
|
||||||
|
resultColumnTypes[i] = resultset.getMetaData().getColumnTypeName(i+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Queue fuer die Zeilen der Ergebnistabelle erstellen
|
||||||
|
Queue<String[]> rows = new Queue<String[]>();
|
||||||
|
|
||||||
|
//Daten in Queue uebertragen und Zeilen zaehlen
|
||||||
|
int rowCount = 0;
|
||||||
|
while (resultset.next()){
|
||||||
|
String[] resultrow = new String[columnCount];
|
||||||
|
for (int s = 0; s < columnCount; s++){
|
||||||
|
resultrow[s] = resultset.getString(s+1);
|
||||||
|
}
|
||||||
|
rows.enqueue(resultrow);
|
||||||
|
rowCount = rowCount + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Ergebnisfeld erstellen und Zeilen aus Queue uebertragen
|
||||||
|
String[][] resultData = new String[rowCount][columnCount];
|
||||||
|
int j = 0;
|
||||||
|
while (!rows.isEmpty()){
|
||||||
|
resultData[j] = rows.front();
|
||||||
|
rows.dequeue();
|
||||||
|
j = j + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Statement schließen und Ergebnisobjekt erstellen
|
||||||
|
statement.close();
|
||||||
|
currentQueryResult = new QueryResult(resultData, resultColumnNames, resultColumnTypes);
|
||||||
|
|
||||||
|
} else { //Fall 2: Es gibt kein Ergebnis.
|
||||||
|
//Statement ohne Ergebnisobjekt schliessen
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
//Fehlermeldung speichern
|
||||||
|
message = e.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert das Ergebnis des letzten mit der Methode executeStatement an
|
||||||
|
* die Datenbank geschickten SQL-Befehls als Ob-jekt vom Typ QueryResult zurueck.
|
||||||
|
* Wurde bisher kein SQL-Befehl abgeschickt oder ergab der letzte Aufruf von
|
||||||
|
* executeStatement keine Ergebnismenge (z.B. bei einem INSERT-Befehl oder einem
|
||||||
|
* Syntaxfehler), so wird null geliefert.
|
||||||
|
*/
|
||||||
|
public QueryResult getCurrentQueryResult(){
|
||||||
|
return currentQueryResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert null oder eine Fehlermeldung, die sich jeweils auf die letzte zuvor ausgefuehrte
|
||||||
|
* Datenbankoperation bezieht.
|
||||||
|
*/
|
||||||
|
public String getErrorMessage(){
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Datenbankverbindung wird geschlossen.
|
||||||
|
*/
|
||||||
|
public void close(){
|
||||||
|
try{
|
||||||
|
connection.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
message = e.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,345 @@
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Generische Klasse List<ContentType>
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Objekt der generischen Klasse List verwalten beliebig viele linear
|
||||||
|
* angeordnete Objekte vom Typ ContentType. Auf hoechstens ein Listenobjekt,
|
||||||
|
* aktuellesObjekt genannt, kann jeweils zugegriffen werden.<br />
|
||||||
|
* Wenn eine Liste leer ist, vollstaendig durchlaufen wurde oder das aktuelle
|
||||||
|
* Objekt am Ende der Liste geloescht wurde, gibt es kein aktuelles Objekt.<br />
|
||||||
|
* Das erste oder das letzte Objekt einer Liste koennen durch einen Auftrag zum
|
||||||
|
* aktuellen Objekt gemacht werden. Ausserdem kann das dem aktuellen Objekt
|
||||||
|
* folgende Listenobjekt zum neuen aktuellen Objekt werden. <br />
|
||||||
|
* Das aktuelle Objekt kann gelesen, veraendert oder geloescht werden. Ausserdem
|
||||||
|
* kann vor dem aktuellen Objekt ein Listenobjekt eingefuegt werden.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
|
||||||
|
* @version Generisch_06 2015-10-25
|
||||||
|
*/
|
||||||
|
public class List<ContentType> {
|
||||||
|
|
||||||
|
/* --------- Anfang der privaten inneren Klasse -------------- */
|
||||||
|
|
||||||
|
private class ListNode {
|
||||||
|
|
||||||
|
private ContentType contentObject;
|
||||||
|
private ListNode next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ein neues Objekt wird erschaffen. Der Verweis ist leer.
|
||||||
|
*
|
||||||
|
* @param pContent das Inhaltsobjekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
private ListNode(ContentType pContent) {
|
||||||
|
contentObject = pContent;
|
||||||
|
next = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Inhalt des Knotens wird zurueckgeliefert.
|
||||||
|
*
|
||||||
|
* @return das Inhaltsobjekt des Knotens
|
||||||
|
*/
|
||||||
|
public ContentType getContentObject() {
|
||||||
|
return contentObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Inhalt dieses Kontens wird gesetzt.
|
||||||
|
*
|
||||||
|
* @param pContent das Inhaltsobjekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void setContentObject(ContentType pContent) {
|
||||||
|
contentObject = pContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Nachfolgeknoten wird zurueckgeliefert.
|
||||||
|
*
|
||||||
|
* @return das Objekt, auf das der aktuelle Verweis zeigt
|
||||||
|
*/
|
||||||
|
public ListNode getNextNode() {
|
||||||
|
return this.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Verweis wird auf das Objekt, das als Parameter uebergeben
|
||||||
|
* wird, gesetzt.
|
||||||
|
*
|
||||||
|
* @param pNext der Nachfolger des Knotens
|
||||||
|
*/
|
||||||
|
public void setNextNode(ListNode pNext) {
|
||||||
|
this.next = pNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------- Ende der privaten inneren Klasse -------------- */
|
||||||
|
|
||||||
|
// erstes Element der Liste
|
||||||
|
ListNode first;
|
||||||
|
|
||||||
|
// letztes Element der Liste
|
||||||
|
ListNode last;
|
||||||
|
|
||||||
|
// aktuelles Element der Liste
|
||||||
|
ListNode current;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eine leere Liste wird erzeugt.
|
||||||
|
*/
|
||||||
|
public List() {
|
||||||
|
first = null;
|
||||||
|
last = null;
|
||||||
|
current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert den Wert true, wenn die Liste keine Objekte enthaelt,
|
||||||
|
* sonst liefert sie den Wert false.
|
||||||
|
*
|
||||||
|
* @return true, wenn die Liste leer ist, sonst false
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
// Die Liste ist leer, wenn es kein erstes Element gibt.
|
||||||
|
return first == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert den Wert true, wenn es ein aktuelles Objekt gibt,
|
||||||
|
* sonst liefert sie den Wert false.
|
||||||
|
*
|
||||||
|
* @return true, falls Zugriff moeglich, sonst false
|
||||||
|
*/
|
||||||
|
public boolean hasAccess() {
|
||||||
|
// Es gibt keinen Zugriff, wenn current auf kein Element verweist.
|
||||||
|
return current != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls die Liste nicht leer ist, es ein aktuelles Objekt gibt und dieses
|
||||||
|
* nicht das letzte Objekt der Liste ist, wird das dem aktuellen Objekt in
|
||||||
|
* der Liste folgende Objekt zum aktuellen Objekt, andernfalls gibt es nach
|
||||||
|
* Ausfuehrung des Auftrags kein aktuelles Objekt, d.h. hasAccess() liefert
|
||||||
|
* den Wert false.
|
||||||
|
*/
|
||||||
|
public void next() {
|
||||||
|
if (this.hasAccess()) {
|
||||||
|
current = current.getNextNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls die Liste nicht leer ist, wird das erste Objekt der Liste aktuelles
|
||||||
|
* Objekt. Ist die Liste leer, geschieht nichts.
|
||||||
|
*/
|
||||||
|
public void toFirst() {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
current = first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls die Liste nicht leer ist, wird das letzte Objekt der Liste
|
||||||
|
* aktuelles Objekt. Ist die Liste leer, geschieht nichts.
|
||||||
|
*/
|
||||||
|
public void toLast() {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
current = last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das
|
||||||
|
* aktuelle Objekt zurueckgegeben, andernfalls (hasAccess() == false) gibt
|
||||||
|
* die Anfrage den Wert null zurueck.
|
||||||
|
*
|
||||||
|
* @return das aktuelle Objekt (vom Typ ContentType) oder null, wenn es
|
||||||
|
* kein aktuelles Objekt gibt
|
||||||
|
*/
|
||||||
|
public ContentType getContent() {
|
||||||
|
if (this.hasAccess()) {
|
||||||
|
return current.getContentObject();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls es ein aktuelles Objekt gibt (hasAccess() == true) und pContent
|
||||||
|
* ungleich null ist, wird das aktuelle Objekt durch pContent ersetzt. Sonst
|
||||||
|
* geschieht nichts.
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* das zu schreibende Objekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void setContent(ContentType pContent) {
|
||||||
|
// Nichts tun, wenn es keinen Inhalt oder kein aktuelles Element gibt.
|
||||||
|
if (pContent != null && this.hasAccess()) {
|
||||||
|
current.setContentObject(pContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird ein neues
|
||||||
|
* Objekt vor dem aktuellen Objekt in die Liste eingefuegt. Das aktuelle
|
||||||
|
* Objekt bleibt unveraendert. <br />
|
||||||
|
* Wenn die Liste leer ist, wird pContent in die Liste eingefuegt und es
|
||||||
|
* gibt weiterhin kein aktuelles Objekt (hasAccess() == false). <br />
|
||||||
|
* Falls es kein aktuelles Objekt gibt (hasAccess() == false) und die Liste
|
||||||
|
* nicht leer ist oder pContent gleich null ist, geschieht nichts.
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* das einzufuegende Objekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void insert(ContentType pContent) {
|
||||||
|
if (pContent != null) { // Nichts tun, wenn es keinen Inhalt gibt.
|
||||||
|
if (this.hasAccess()) { // Fall: Es gibt ein aktuelles Element.
|
||||||
|
|
||||||
|
// Neuen Knoten erstellen.
|
||||||
|
ListNode newNode = new ListNode(pContent);
|
||||||
|
|
||||||
|
if (current != first) { // Fall: Nicht an erster Stelle einfuegen.
|
||||||
|
ListNode previous = this.getPrevious(current);
|
||||||
|
newNode.setNextNode(previous.getNextNode());
|
||||||
|
previous.setNextNode(newNode);
|
||||||
|
} else { // Fall: An erster Stelle einfuegen.
|
||||||
|
newNode.setNextNode(first);
|
||||||
|
first = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { //Fall: Es gibt kein aktuelles Element.
|
||||||
|
|
||||||
|
if (this.isEmpty()) { // Fall: In leere Liste einfuegen.
|
||||||
|
|
||||||
|
// Neuen Knoten erstellen.
|
||||||
|
ListNode newNode = new ListNode(pContent);
|
||||||
|
|
||||||
|
first = newNode;
|
||||||
|
last = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls pContent gleich null ist, geschieht nichts.<br />
|
||||||
|
* Ansonsten wird ein neues Objekt pContent am Ende der Liste eingefuegt.
|
||||||
|
* Das aktuelle Objekt bleibt unveraendert. <br />
|
||||||
|
* Wenn die Liste leer ist, wird das Objekt pContent in die Liste eingefuegt
|
||||||
|
* und es gibt weiterhin kein aktuelles Objekt (hasAccess() == false).
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* das anzuhaengende Objekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void append(ContentType pContent) {
|
||||||
|
if (pContent != null) { // Nichts tun, wenn es keine Inhalt gibt.
|
||||||
|
|
||||||
|
if (this.isEmpty()) { // Fall: An leere Liste anfuegen.
|
||||||
|
this.insert(pContent);
|
||||||
|
} else { // Fall: An nicht-leere Liste anfuegen.
|
||||||
|
|
||||||
|
// Neuen Knoten erstellen.
|
||||||
|
ListNode newNode = new ListNode(pContent);
|
||||||
|
|
||||||
|
last.setNextNode(newNode);
|
||||||
|
last = newNode; // Letzten Knoten aktualisieren.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls es sich bei der Liste und pList um dasselbe Objekt handelt,
|
||||||
|
* pList null oder eine leere Liste ist, geschieht nichts.<br />
|
||||||
|
* Ansonsten wird die Liste pList an die aktuelle Liste angehaengt.
|
||||||
|
* Anschliessend wird pList eine leere Liste. Das aktuelle Objekt bleibt
|
||||||
|
* unveraendert. Insbesondere bleibt hasAccess identisch.
|
||||||
|
*
|
||||||
|
* @param pList
|
||||||
|
* die am Ende anzuhaengende Liste vom Typ List<ContentType>
|
||||||
|
*/
|
||||||
|
public void concat(List<ContentType> pList) {
|
||||||
|
if (pList != this && pList != null && !pList.isEmpty()) { // Nichts tun,
|
||||||
|
// wenn pList und this identisch, pList leer oder nicht existent.
|
||||||
|
|
||||||
|
if (this.isEmpty()) { // Fall: An leere Liste anfuegen.
|
||||||
|
this.first = pList.first;
|
||||||
|
this.last = pList.last;
|
||||||
|
} else { // Fall: An nicht-leere Liste anfuegen.
|
||||||
|
this.last.setNextNode(pList.first);
|
||||||
|
this.last = pList.last;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liste pList loeschen.
|
||||||
|
pList.first = null;
|
||||||
|
pList.last = null;
|
||||||
|
pList.current = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wenn die Liste leer ist oder es kein aktuelles Objekt gibt (hasAccess()
|
||||||
|
* == false), geschieht nichts.<br />
|
||||||
|
* Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das
|
||||||
|
* aktuelle Objekt geloescht und das Objekt hinter dem geloeschten Objekt
|
||||||
|
* wird zum aktuellen Objekt. <br />
|
||||||
|
* Wird das Objekt, das am Ende der Liste steht, geloescht, gibt es kein
|
||||||
|
* aktuelles Objekt mehr.
|
||||||
|
*/
|
||||||
|
public void remove() {
|
||||||
|
// Nichts tun, wenn es kein aktuelle Element gibt oder die Liste leer ist.
|
||||||
|
if (this.hasAccess() && !this.isEmpty()) {
|
||||||
|
|
||||||
|
if (current == first) {
|
||||||
|
first = first.getNextNode();
|
||||||
|
} else {
|
||||||
|
ListNode previous = this.getPrevious(current);
|
||||||
|
if (current == last) {
|
||||||
|
last = previous;
|
||||||
|
}
|
||||||
|
previous.setNextNode(current.getNextNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
ListNode temp = current.getNextNode();
|
||||||
|
current.setContentObject(null);
|
||||||
|
current.setNextNode(null);
|
||||||
|
current = temp;
|
||||||
|
|
||||||
|
//Beim loeschen des letzten Elements last auf null setzen.
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
last = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liefert den Vorgaengerknoten des Knotens pNode. Ist die Liste leer, pNode
|
||||||
|
* == null, pNode nicht in der Liste oder pNode der erste Knoten der Liste,
|
||||||
|
* wird null zurueckgegeben.
|
||||||
|
*
|
||||||
|
* @param pNode
|
||||||
|
* der Knoten, dessen Vorgaenger zurueckgegeben werden soll
|
||||||
|
* @return der Vorgaenger des Knotens pNode oder null, falls die Liste leer ist,
|
||||||
|
* pNode == null ist, pNode nicht in der Liste ist oder pNode der erste Knoten
|
||||||
|
* der Liste ist
|
||||||
|
*/
|
||||||
|
private ListNode getPrevious(ListNode pNode) {
|
||||||
|
if (pNode != null && pNode != first && !this.isEmpty()) {
|
||||||
|
ListNode temp = first;
|
||||||
|
while (temp != null && temp.getNextNode() != pNode) {
|
||||||
|
temp = temp.getNextNode();
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Klasse QueryResult
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Ein Objekt der Klasse QueryResult stellt die Ergebnistabelle einer Datenbankanfrage mit Hilfe
|
||||||
|
* der Klasse DatabaseConnector dar. Objekte dieser Klasse werden nur von der Klasse DatabaseConnector erstellt.
|
||||||
|
* Die Klasse verfuegt ueber keinen oeffentlichen Konstruktor.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
|
||||||
|
* @version 2015-01-31
|
||||||
|
*/
|
||||||
|
public class QueryResult{
|
||||||
|
private String[][] data;
|
||||||
|
private String[] columnNames;
|
||||||
|
private String[] columnTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paketinterner Konstruktor.
|
||||||
|
*/
|
||||||
|
QueryResult(String[][] pData, String[] pColumnNames, String[] pColumnTypes){
|
||||||
|
data = pData;
|
||||||
|
columnNames = pColumnNames;
|
||||||
|
columnTypes = pColumnTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert die Eintraege der Ergebnistabelle als zweidimensionales Feld
|
||||||
|
* vom Typ String. Der erste Index des Feldes stellt die Zeile und der zweite die
|
||||||
|
* Spalte dar (d.h. Object[zeile][spalte]).
|
||||||
|
*/
|
||||||
|
public String[][] getData(){
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert die Bezeichner der Spalten der Ergebnistabelle als Feld vom
|
||||||
|
* Typ String zurueck.
|
||||||
|
*/
|
||||||
|
public String[] getColumnNames(){
|
||||||
|
return columnNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert die Typenbezeichnung der Spalten der Ergebnistabelle als Feld
|
||||||
|
* vom Typ String zurueck. Die Bezeichnungen entsprechen den Angaben in der MySQL-Datenbank.
|
||||||
|
*/
|
||||||
|
public String[] getColumnTypes(){
|
||||||
|
return columnTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert die Anzahl der Zeilen der Ergebnistabelle als Integer.
|
||||||
|
*/
|
||||||
|
public int getRowCount(){
|
||||||
|
if (data != null )
|
||||||
|
return data.length;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert die Anzahl der Spalten der Ergebnistabelle als Integer.
|
||||||
|
*/
|
||||||
|
public int getColumnCount(){
|
||||||
|
if (data != null && data.length > 0 && data[0] != null)
|
||||||
|
return data[0].length;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Generische Klasse Queue<ContentType>
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Objekte der generischen Klasse Queue (Warteschlange) verwalten beliebige
|
||||||
|
* Objekte vom Typ ContentType nach dem First-In-First-Out-Prinzip, d.h., das
|
||||||
|
* zuerst abgelegte Objekt wird als erstes wieder entnommen. Alle Methoden haben
|
||||||
|
* eine konstante Laufzeit, unabhaengig von der Anzahl der verwalteten Objekte.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
|
||||||
|
* @version Generisch_02 2014-02-21
|
||||||
|
*/
|
||||||
|
public class Queue<ContentType> {
|
||||||
|
|
||||||
|
/* --------- Anfang der privaten inneren Klasse -------------- */
|
||||||
|
|
||||||
|
private class QueueNode {
|
||||||
|
|
||||||
|
private ContentType content = null;
|
||||||
|
private QueueNode nextNode = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ein neues Objekt vom Typ QueueNode<ContentType> wird erschaffen.
|
||||||
|
* Der Inhalt wird per Parameter gesetzt. Der Verweis ist leer.
|
||||||
|
*
|
||||||
|
* @param pContent das Inhaltselement des Knotens vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public QueueNode(ContentType pContent) {
|
||||||
|
content = pContent;
|
||||||
|
nextNode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Verweis wird auf das Objekt, das als Parameter uebergeben wird,
|
||||||
|
* gesetzt.
|
||||||
|
*
|
||||||
|
* @param pNext der Nachfolger des Knotens
|
||||||
|
*/
|
||||||
|
public void setNext(QueueNode pNext) {
|
||||||
|
nextNode = pNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liefert das naechste Element des aktuellen Knotens.
|
||||||
|
*
|
||||||
|
* @return das Objekt vom Typ QueueNode, auf das der aktuelle Verweis zeigt
|
||||||
|
*/
|
||||||
|
public QueueNode getNext() {
|
||||||
|
return nextNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liefert das Inhaltsobjekt des Knotens vom Typ ContentType.
|
||||||
|
*
|
||||||
|
* @return das Inhaltsobjekt des Knotens
|
||||||
|
*/
|
||||||
|
public ContentType getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------- Ende der privaten inneren Klasse -------------- */
|
||||||
|
|
||||||
|
private QueueNode head;
|
||||||
|
private QueueNode tail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eine leere Schlange wird erzeugt.
|
||||||
|
* Objekte, die in dieser Schlange verwaltet werden, muessen vom Typ
|
||||||
|
* ContentType sein.
|
||||||
|
*/
|
||||||
|
public Queue() {
|
||||||
|
head = null;
|
||||||
|
tail = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert den Wert true, wenn die Schlange keine Objekte enthaelt,
|
||||||
|
* sonst liefert sie den Wert false.
|
||||||
|
*
|
||||||
|
* @return true, falls die Schlange leer ist, sonst false
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return head == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Das Objekt pContentType wird an die Schlange angehaengt.
|
||||||
|
* Falls pContentType gleich null ist, bleibt die Schlange unveraendert.
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* das anzuhaengende Objekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void enqueue(ContentType pContent) {
|
||||||
|
if (pContent != null) {
|
||||||
|
QueueNode newNode = new QueueNode(pContent);
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
head = newNode;
|
||||||
|
tail = newNode;
|
||||||
|
} else {
|
||||||
|
tail.setNext(newNode);
|
||||||
|
tail = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Das erste Objekt wird aus der Schlange entfernt.
|
||||||
|
* Falls die Schlange leer ist, wird sie nicht veraendert.
|
||||||
|
*/
|
||||||
|
public void dequeue() {
|
||||||
|
if (!this.isEmpty()) {
|
||||||
|
head = head.getNext();
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
head = null;
|
||||||
|
tail = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert das erste Objekt der Schlange.
|
||||||
|
* Die Schlange bleibt unveraendert.
|
||||||
|
* Falls die Schlange leer ist, wird null zurueckgegeben.
|
||||||
|
*
|
||||||
|
* @return das erste Objekt der Schlange vom Typ ContentType oder null,
|
||||||
|
* falls die Schlange leer ist
|
||||||
|
*/
|
||||||
|
public ContentType front() {
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return head.getContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,359 @@
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Klasse Server
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Objekte von Unterklassen der abstrakten Klasse Server ermoeglichen das
|
||||||
|
* Anbieten von Serverdiensten, so dass Clients Verbindungen zum Server mittels
|
||||||
|
* TCP/IP-Protokoll aufbauen koennen. Zur Vereinfachung finden Nachrichtenversand
|
||||||
|
* und -empfang zeilenweise statt, d. h., beim Senden einer Zeichenkette wird ein
|
||||||
|
* Zeilentrenner ergaenzt und beim Empfang wird dieser entfernt.
|
||||||
|
* Verbindungsannahme, Nachrichtenempfang und Verbindungsende geschehen
|
||||||
|
* nebenlaeufig. Auf diese Ereignisse muss durch Ueberschreiben der entsprechenden
|
||||||
|
* Ereignisbehandlungsmethoden reagiert werden. Es findet nur eine rudimentaere
|
||||||
|
* Fehlerbehandlung statt, so dass z.B. Verbindungsabbrueche nicht zu einem
|
||||||
|
* Programmabbruch fuehren. Einmal unterbrochene oder getrennte Verbindungen
|
||||||
|
* koennen nicht reaktiviert werden.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
|
||||||
|
* @version 30.08.2016
|
||||||
|
*/
|
||||||
|
import java.net.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public abstract class Server
|
||||||
|
{
|
||||||
|
private NewConnectionHandler connectionHandler;
|
||||||
|
private List<ClientMessageHandler> messageHandlers;
|
||||||
|
|
||||||
|
private class NewConnectionHandler extends Thread
|
||||||
|
{
|
||||||
|
private ServerSocket serverSocket;
|
||||||
|
private boolean active;
|
||||||
|
|
||||||
|
public NewConnectionHandler(int pPort)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
serverSocket = new ServerSocket(pPort);
|
||||||
|
start();
|
||||||
|
active = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
serverSocket = null;
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
while (active)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//Warten auf Verbdinungsversuch durch Client:
|
||||||
|
Socket clientSocket = serverSocket.accept();
|
||||||
|
// Eingehende Nachrichten vom neu verbundenen Client werden
|
||||||
|
// in einem eigenen Thread empfangen:
|
||||||
|
addNewClientMessageHandler(clientSocket);
|
||||||
|
processNewConnection(clientSocket.getInetAddress().getHostAddress(),clientSocket.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Kann keine Verbindung zum anfragenden Client aufgebaut werden,
|
||||||
|
* geschieht nichts.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
active = false;
|
||||||
|
if(serverSocket != null)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
serverSocket.close();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Befindet sich der ServerSocket im accept()-Wartezustand oder wurde
|
||||||
|
* er bereits geschlossen, geschieht nichts.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ClientMessageHandler extends Thread
|
||||||
|
{
|
||||||
|
private ClientSocketWrapper socketWrapper;
|
||||||
|
private boolean active;
|
||||||
|
|
||||||
|
private class ClientSocketWrapper
|
||||||
|
{
|
||||||
|
private Socket clientSocket;
|
||||||
|
private BufferedReader fromClient;
|
||||||
|
private PrintWriter toClient;
|
||||||
|
|
||||||
|
public ClientSocketWrapper(Socket pSocket)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientSocket = pSocket;
|
||||||
|
toClient = new PrintWriter(clientSocket.getOutputStream(), true);
|
||||||
|
fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
clientSocket = null;
|
||||||
|
toClient = null;
|
||||||
|
fromClient = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String receive()
|
||||||
|
{
|
||||||
|
if(fromClient != null)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return fromClient.readLine();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(String pMessage)
|
||||||
|
{
|
||||||
|
if(toClient != null)
|
||||||
|
{
|
||||||
|
toClient.println(pMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientIP()
|
||||||
|
{
|
||||||
|
if(clientSocket != null)
|
||||||
|
return(clientSocket.getInetAddress().getHostAddress());
|
||||||
|
else
|
||||||
|
return(null); //Gemaess Java-API Rueckgabe bei nicht-verbundenen Sockets
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getClientPort()
|
||||||
|
{
|
||||||
|
if(clientSocket != null)
|
||||||
|
return(clientSocket.getPort());
|
||||||
|
else
|
||||||
|
return(0); //Gemaess Java-API Rueckgabe bei nicht-verbundenen Sockets
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
if(clientSocket != null)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientSocket.close();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Falls eine Verbindung getrennt werden soll, deren Endpunkt
|
||||||
|
* nicht mehr existiert bzw. ihrerseits bereits beendet worden ist,
|
||||||
|
* geschieht nichts.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClientMessageHandler(Socket pClientSocket)
|
||||||
|
{
|
||||||
|
socketWrapper = new ClientSocketWrapper(pClientSocket);
|
||||||
|
if(pClientSocket!=null)
|
||||||
|
{
|
||||||
|
start();
|
||||||
|
active = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
String message = null;
|
||||||
|
while (active)
|
||||||
|
{
|
||||||
|
message = socketWrapper.receive();
|
||||||
|
if (message != null)
|
||||||
|
processMessage(socketWrapper.getClientIP(), socketWrapper.getClientPort(), message);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClientMessageHandler aMessageHandler = findClientMessageHandler(socketWrapper.getClientIP(), socketWrapper.getClientPort());
|
||||||
|
if (aMessageHandler != null)
|
||||||
|
{
|
||||||
|
aMessageHandler.close();
|
||||||
|
removeClientMessageHandler(aMessageHandler);
|
||||||
|
processClosingConnection(socketWrapper.getClientIP(), socketWrapper.getClientPort());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(String pMessage)
|
||||||
|
{
|
||||||
|
if(active)
|
||||||
|
socketWrapper.send(pMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
if(active)
|
||||||
|
{
|
||||||
|
active=false;
|
||||||
|
socketWrapper.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientIP()
|
||||||
|
{
|
||||||
|
return(socketWrapper.getClientIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getClientPort()
|
||||||
|
{
|
||||||
|
return(socketWrapper.getClientPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Server(int pPort)
|
||||||
|
{
|
||||||
|
connectionHandler = new NewConnectionHandler(pPort);
|
||||||
|
messageHandlers = new List<ClientMessageHandler>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOpen()
|
||||||
|
{
|
||||||
|
return(connectionHandler.active);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnectedTo(String pClientIP, int pClientPort)
|
||||||
|
{
|
||||||
|
ClientMessageHandler aMessageHandler = findClientMessageHandler(pClientIP, pClientPort);
|
||||||
|
if (aMessageHandler != null)
|
||||||
|
return(aMessageHandler.active);
|
||||||
|
else
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(String pClientIP, int pClientPort, String pMessage)
|
||||||
|
{
|
||||||
|
ClientMessageHandler aMessageHandler = this.findClientMessageHandler(pClientIP, pClientPort);
|
||||||
|
if (aMessageHandler != null)
|
||||||
|
aMessageHandler.send(pMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendToAll(String pMessage)
|
||||||
|
{
|
||||||
|
synchronized(messageHandlers)
|
||||||
|
{
|
||||||
|
messageHandlers.toFirst();
|
||||||
|
while (messageHandlers.hasAccess())
|
||||||
|
{
|
||||||
|
messageHandlers.getContent().send(pMessage);
|
||||||
|
messageHandlers.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeConnection(String pClientIP, int pClientPort)
|
||||||
|
{
|
||||||
|
ClientMessageHandler aMessageHandler = findClientMessageHandler(pClientIP, pClientPort);
|
||||||
|
if (aMessageHandler != null)
|
||||||
|
{
|
||||||
|
processClosingConnection(pClientIP, pClientPort);
|
||||||
|
aMessageHandler.close();
|
||||||
|
removeClientMessageHandler(aMessageHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
connectionHandler.close();
|
||||||
|
|
||||||
|
synchronized(messageHandlers)
|
||||||
|
{
|
||||||
|
ClientMessageHandler aMessageHandler;
|
||||||
|
messageHandlers.toFirst();
|
||||||
|
while (messageHandlers.hasAccess())
|
||||||
|
{
|
||||||
|
aMessageHandler = messageHandlers.getContent();
|
||||||
|
processClosingConnection(aMessageHandler.getClientIP(), aMessageHandler.getClientPort());
|
||||||
|
aMessageHandler.close();
|
||||||
|
messageHandlers.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract void processNewConnection(String pClientIP, int pClientPort);
|
||||||
|
|
||||||
|
public abstract void processMessage(String pClientIP, int pClientPort, String pMessage);
|
||||||
|
|
||||||
|
public abstract void processClosingConnection(String pClientIP, int pClientPort);
|
||||||
|
|
||||||
|
private void addNewClientMessageHandler(Socket pClientSocket)
|
||||||
|
{
|
||||||
|
synchronized(messageHandlers)
|
||||||
|
{
|
||||||
|
messageHandlers.append(new Server.ClientMessageHandler(pClientSocket));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeClientMessageHandler(ClientMessageHandler pClientMessageHandler)
|
||||||
|
{
|
||||||
|
synchronized(messageHandlers)
|
||||||
|
{
|
||||||
|
messageHandlers.toFirst();
|
||||||
|
while (messageHandlers.hasAccess())
|
||||||
|
{
|
||||||
|
if (pClientMessageHandler == messageHandlers.getContent())
|
||||||
|
{
|
||||||
|
messageHandlers.remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
messageHandlers.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClientMessageHandler findClientMessageHandler(String pClientIP, int pClientPort)
|
||||||
|
{
|
||||||
|
synchronized(messageHandlers)
|
||||||
|
{
|
||||||
|
ClientMessageHandler aMessageHandler;
|
||||||
|
messageHandlers.toFirst();
|
||||||
|
|
||||||
|
while (messageHandlers.hasAccess())
|
||||||
|
{
|
||||||
|
aMessageHandler = messageHandlers.getContent();
|
||||||
|
if (aMessageHandler.getClientIP().equals(pClientIP) && aMessageHandler.getClientPort() == pClientPort)
|
||||||
|
return (aMessageHandler);
|
||||||
|
messageHandlers.next();
|
||||||
|
}
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
#BlueJ package file
|
||||||
|
dependency1.from=DecisionNode
|
||||||
|
dependency1.to=Dataset
|
||||||
|
dependency1.type=UsesDependency
|
||||||
|
dependency2.from=Classification
|
||||||
|
dependency2.to=Dataset
|
||||||
|
dependency2.type=UsesDependency
|
||||||
|
dependency3.from=Decision
|
||||||
|
dependency3.to=Dataset
|
||||||
|
dependency3.type=UsesDependency
|
||||||
|
dependency4.from=DecisionTreeBuilder
|
||||||
|
dependency4.to=BinaryTree
|
||||||
|
dependency4.type=UsesDependency
|
||||||
|
dependency5.from=DecisionTreeBuilder
|
||||||
|
dependency5.to=DecisionNode
|
||||||
|
dependency5.type=UsesDependency
|
||||||
|
dependency6.from=DecisionTreeBuilder
|
||||||
|
dependency6.to=Classification
|
||||||
|
dependency6.type=UsesDependency
|
||||||
|
dependency7.from=DecisionTreeBuilder
|
||||||
|
dependency7.to=Decision
|
||||||
|
dependency7.type=UsesDependency
|
||||||
|
dependency8.from=DecisionTreeBuilder
|
||||||
|
dependency8.to=Dataset
|
||||||
|
dependency8.type=UsesDependency
|
||||||
|
editor.fx.0.height=722
|
||||||
|
editor.fx.0.width=800
|
||||||
|
editor.fx.0.x=388
|
||||||
|
editor.fx.0.y=50
|
||||||
|
objectbench.height=66
|
||||||
|
objectbench.width=1201
|
||||||
|
package.divider.horizontal=0.6
|
||||||
|
package.divider.vertical=0.8983286908077994
|
||||||
|
package.editor.height=622
|
||||||
|
package.editor.width=1078
|
||||||
|
package.editor.x=39
|
||||||
|
package.editor.y=24
|
||||||
|
package.frame.height=776
|
||||||
|
package.frame.width=1241
|
||||||
|
package.numDependencies=8
|
||||||
|
package.numTargets=6
|
||||||
|
package.showExtends=true
|
||||||
|
package.showUses=true
|
||||||
|
project.charset=UTF-8
|
||||||
|
readme.height=58
|
||||||
|
readme.name=@README
|
||||||
|
readme.width=47
|
||||||
|
readme.x=10
|
||||||
|
readme.y=10
|
||||||
|
target1.height=40
|
||||||
|
target1.name=Classification
|
||||||
|
target1.showInterface=false
|
||||||
|
target1.type=ClassTarget
|
||||||
|
target1.width=210
|
||||||
|
target1.x=40
|
||||||
|
target1.y=460
|
||||||
|
target2.height=50
|
||||||
|
target2.name=Decision
|
||||||
|
target2.showInterface=false
|
||||||
|
target2.type=ClassTarget
|
||||||
|
target2.width=190
|
||||||
|
target2.x=300
|
||||||
|
target2.y=460
|
||||||
|
target3.height=120
|
||||||
|
target3.name=BinaryTree
|
||||||
|
target3.showInterface=false
|
||||||
|
target3.type=ClassTarget
|
||||||
|
target3.width=440
|
||||||
|
target3.x=890
|
||||||
|
target3.y=250
|
||||||
|
target4.height=40
|
||||||
|
target4.name=Dataset
|
||||||
|
target4.showInterface=false
|
||||||
|
target4.type=ClassTarget
|
||||||
|
target4.width=270
|
||||||
|
target4.x=430
|
||||||
|
target4.y=30
|
||||||
|
target5.height=50
|
||||||
|
target5.name=DecisionNode
|
||||||
|
target5.showInterface=false
|
||||||
|
target5.type=AbstractTarget
|
||||||
|
target5.width=110
|
||||||
|
target5.x=210
|
||||||
|
target5.y=290
|
||||||
|
target6.height=60
|
||||||
|
target6.name=DecisionTreeBuilder
|
||||||
|
target6.showInterface=false
|
||||||
|
target6.type=ClassTarget
|
||||||
|
target6.width=270
|
||||||
|
target6.x=580
|
||||||
|
target6.y=230
|
Loading…
Reference in New Issue