Abstract

This documet describes the News project TN in a course at the institution for "Datalogi och Numerisk Analys" at Lunds Tekniska Högskola at Lunds University with the name "Industrial Related Programming" (1998). The project involves programing of a simple news Client in the java language. Our sulution is to use the real NNTP protocoll described in RFC-977 as base for our protocoll. We Have Not, and DO NOT claim, to have fully implemented the RFC-997 protocoll in our client. We have only used parts of the implementation, and also added our own comands when neaded (with a x in front of the commad as in xaddgroup <groupname>).

The server is from our other project and is rather simpel it does not take care of any realtime issues at all, but it works rather good anyway in a multiclient enviroment.

The client is a simpel java based client with a userfriendly userinterface. It is menu driven in its structure and rather selfexplaining.

Innehållsförteckning

Inledning

Teori

Genomförande

Resultat

Utvärderande diskussion

Referenslista

Appendix

A. Programlistningar

B. Klasser

Inledning

Denna rapport beskiver vår newsläsare med namnet TN som är en förkortning på "The News ".

Uppiften är att skriva en newsklient som kan kommunicera med den newserver vi skrev i ett tidigare projekt, och utbyta information om nyhetsgrupper och artiklar samt deras vara eller icke vara Klienten ska vara grafisk och behöver bara kunna hantera tillägg och borttagning av artiklar och grupper samt listning av båda och läsning av artiklar. Det ska dessutom ske på ett intuitivt (och smakfullt) sätt. Klienten fick inte vara slavisk utan skall själv kunna hantera kommandon, utskrifter samt hantering av nyhets-trädet.

I teoridelen av rapporten kan du läsa bakomliggande fakta och teorier. Genomförandekapitlet beskriver hur projektet har utförts och med vilka hjälpmedel. Resultatdelen beskriver hur fantastiskt bra allt blev till slut, och i utvärderande diskussion kan du se att det inte gjorde det. I övrigt finns mycket information för den vetgiriga i källkoden, och en liten klassbeskrivning.

Teori

Newsläsare implementeras med Client-Server teknik och som protokoll har vi valt att använda en modifierad variant av NNTP som är det "riktiga" newsprotokollet som finns beskrivet i RFC-977 [1]. Eftersom vi inte behöver alla delar av protokollet har vi valt att endast implementera de delar som vi behöver samnt att lägga till en del nya komando vilket är tillåtet enligt RFC-977 [1] bara de nya komandona börjar med "x" tex xkillserver. Vi har implementerat hela programpaketet i java som är ett programspråk utvecklat av Sun.

Genomförande

Eftersom vi valt att använda NNTP protokollet som grund behövde vi inte designa ett protokoll vilket medförde att den inledande designen endast bestod av an enkel diskussions om vilka object som skulle ingå och varför. Vi bestämde oss snabbt för att försöka dela upp programmet i parallella spår så att viss utveckling kunde ske separat.

I arbetet har vi använt oss av editorn Emacs och dess Java-mode för att formattera programmet. För att kompilera har vi använt javac som ingår i JDK 1.1. Utväcklingen har skett i Unixmiljö på skolans datorer i huvudsak på Sun Sparc Ultra.

Resultat

Resultatet var fantastiskt. Flera saker fungerar. (Multipel Funktionalitet) Framför allt beter sig programmet som vi hade tänkt oss, vilket väl överensstämmer med krav-spec.

Utvärderande diskussion

TN är skrivet med en bantad version av NNTP. Detta innebär att man vid en eventuell nästa version lätt skulle kunna göra den ännu mer kompatibel med "riktiga" news-servers och -klienter. Många funktioner saknas dock fortfarande, och dessutom är hanteringen av artiklar inte särskilt lik praxis för News. Detta beror huvudsakligen på en brist i designen som i sin tur beror att vi vill ha en enkel implementation.

En annan brist är användargränssnittet som visserligen är relativt intuitivt, men lite osmidigt.

Klienten stöder inte heller hantering av skivminne för att spara undan information mellan sessioner.

Eftersom ingen hänsyn har tagits till realtidsproblem skulle dessa kunna orsaka fel både i server och klient, även om vi inte hittat några av dessa än.

Referenslista

[1] "RFC-977"

[2] David Flanagan, Java in a nutshell, O'Reilly & Associates, Inc, Second Edition, Sebastopol 97

[3] P. Holm, "Overheadbilder, IRP del 2", Instutionen för DNA vid Lunds Universitet, Lund 97/98

[4] Flix Reychman Stefan "Zingo" Zivkovic "this", TN corp. Lund 98/05/29

A. Källkod

/** JEdit3: the main application class for the jEdit3 editor */

class JEdit3 {

public static void main(String[] args) {

/*if (args.length != 2){

Runtime.getRuntime().exit(0);

}*/

String host = args[0];

int port = new Integer(args[1]).intValue();

Editor ed = new Editor(host, port);

}

}

import java.awt.*;

import java.awt.event.*;

import NetIO.*;

/** the GUI for the JEdit3 application */

class GUI extends Frame {

public Editor theEditor; // the editor that we're a GUI for

private Button KillServerBtn, GetGroupsBtn, SelectGroupBtn, AddGroupBtn, DeleteGroupBtn, SelectArticleBtn, AddArticleBtn, DeleteArticleBtn, QuitBtn;

private TextArea Article; // edit area for one text

private List GroupList; // list of groups

private List ArticleList; // list of articles

public NetIO MyNetIO; // NetIO for communication

/** create a GUI for the editor ed */

public GUI(Editor ed, String title, String host, int port, NetIO theMyNetIO) {

super(title);

theEditor = ed;

MyNetIO = theMyNetIO;

BorderLayout MainLayout = new BorderLayout();

setLayout(MainLayout);

Panel ListContainer = new Panel();

add("North", ListContainer);

Panel GroupContainer = new Panel();

GroupContainer.setLayout(new BorderLayout());

ListContainer.add("1,1", GroupContainer);

Panel buttonPanelGroup = new Panel();

GroupContainer.add("North", buttonPanelGroup);

GetGroupsBtn = new Button("Get Groups");

SelectGroupBtn = new Button("Select Group");

AddGroupBtn = new Button("Add Group");

DeleteGroupBtn = new Button("Delete Group");

QuitBtn = new Button("Quit");

buttonPanelGroup.add(GetGroupsBtn);

buttonPanelGroup.add(SelectGroupBtn);

buttonPanelGroup.add(AddGroupBtn);

buttonPanelGroup.add(DeleteGroupBtn);

buttonPanelGroup.add(QuitBtn);

Panel ArticleContainer = new Panel();

ArticleContainer.setLayout(new BorderLayout());

ListContainer.add("1,2", ArticleContainer);

Panel buttonPanelArticle = new Panel();

ArticleContainer.add("North", buttonPanelArticle);

KillServerBtn = new Button("Kill Server");

SelectArticleBtn = new Button("Select Article");

AddArticleBtn = new Button("Add Article");

DeleteArticleBtn = new Button("Delete Article");

buttonPanelGroup.add(KillServerBtn);

buttonPanelArticle.add(SelectArticleBtn);

buttonPanelArticle.add(AddArticleBtn);

buttonPanelArticle.add(DeleteArticleBtn);

CommandHandler handler = new CommandHandler();

GetGroupsBtn.addActionListener(handler);

SelectGroupBtn.addActionListener(handler);

AddGroupBtn.addActionListener(handler);

DeleteGroupBtn.addActionListener(handler);

SelectArticleBtn.addActionListener(handler);

AddArticleBtn.addActionListener(handler);

DeleteArticleBtn.addActionListener(handler);

QuitBtn.addActionListener(handler);

KillServerBtn.addActionListener(handler);

// GroupList = new List(12, false);

GroupList = new List();

GroupList.setMultipleMode(false);

GroupContainer.add("South", GroupList);

ArticleList = new List();

ArticleList.setMultipleMode(false);

ArticleContainer.add("South", ArticleList);

//MyNetIO.GetGroupList(theEditor.data);

//theEditor.listNames();

Article = new TextArea(20, 80);

add("South", Article);

Article.setText("No Article. Select new Article");

pack();

setVisible(true);

}

/** button actions */

class CommandHandler implements ActionListener {

public void actionPerformed(ActionEvent e) {

Button bsource = (Button) e.getSource();

if (bsource==SelectGroupBtn) {

int selected = getSelectedGroup();

if (selected!=-1){

MyNetIO.GetArticleList(getItem(selected), theEditor.data);

theEditor.listArticles();

}

}

else if (bsource==GetGroupsBtn){

MyNetIO.GetGroupList(theEditor.data);

theEditor.listGroups();

}

else if (bsource==AddGroupBtn) {

new DialogBox(GUI.this, "new group", "Write name of group: ", true);

}

else if (bsource==DeleteGroupBtn){

int selected = getSelectedGroup();

if (selected!=-1){

MyNetIO.DeleteGroup(getItem(selected), theEditor.data);

MyNetIO.GetGroupList(theEditor.data);

theEditor.listGroups();

}

}

else if (bsource==SelectArticleBtn){

int selected = GetSelectedArticle();

if (selected != -1){

Article.setText(theEditor.data.getText(selected));

System.out.println("GUI : " + theEditor.data.getText(selected));

}

}

else if (bsource==DeleteArticleBtn){

int selected = GetSelectedArticle();

if (selected != -1){

theEditor.DeleteArticle(selected + 1);

Article.setText("No Article. Select new Article");

System.out.println("GUI : " + theEditor.data.getText(selected));

}

}

else if (bsource==AddArticleBtn){

if (theEditor.data.hasCurrGroup){

new NewArticleBox(GUI.this, "new article", true);

}

}

else if (bsource==KillServerBtn){

MyNetIO.KillServer();

System.exit(0);

}

else if (bsource==QuitBtn)

System.exit(0);

}

}

public Editor getEditor() {

return theEditor;

}

public void clearGroupList() {

GroupList.removeAll();

//GroupList.update();

}

public void addToGroupList(String s) {

GroupList.addItem(s);

}

public void clearArticleList() {

ArticleList.removeAll();

}

public void addToArticleList(String s) {

ArticleList.addItem(s);

}

public int getSelectedGroup() {

return GroupList.getSelectedIndex();

}

public String getItem(int ThisItem){

return GroupList.getItem(ThisItem);

}

public int GetSelectedArticle(){

return ArticleList.getSelectedIndex();

}

}

/** a box with a message and an OK button */

class MessageBox extends Dialog {

public MessageBox(GUI p, String title, String msg, boolean modal) {

super(p,title,modal);

add("Center",new Label(msg));

Button ok = new Button("OK");

add("South",ok);

ok.addActionListener(new CommandHandler());

pack();

setVisible(true);

}

private class CommandHandler implements ActionListener {

public void actionPerformed(ActionEvent e) {

setVisible(false);

dispose();

}

}

}

/** a box with an input text field and OK and Cancel buttons */

class DialogBox extends Dialog {

private Editor theEditor;

private GUI parent;

private Button ok, cancel;

private TextField txtField;

public DialogBox(GUI p, String title, String msg, boolean modal) {

super(p,title,modal);

parent = p;

theEditor = parent.getEditor();

Panel p1 = new Panel();

txtField = new TextField(30);

p1.add(new Label(msg));

p1.add(txtField);

add("Center",p1);

Panel p2 = new Panel();

ok = new Button("OK");

cancel = new Button("Cancel");

p2.add(ok);

p2.add(cancel);

CommandHandler handler = new CommandHandler();

ok.addActionListener(handler);

cancel.addActionListener(handler);

add("South",p2);

pack();

setVisible(true);

}

private class CommandHandler implements ActionListener {

public void actionPerformed(ActionEvent e) {

Button source = (Button) e.getSource();

if (source==ok) {

String txt = txtField.getText();

System.out.println("Groupname : " + txt);

System.out.println("Du har tryckt på OK");

parent.MyNetIO.AddGroup(txt, theEditor.data);

parent.MyNetIO.GetGroupList(theEditor.data);

parent.theEditor.listGroups();

setVisible(false);

dispose();

}

else if (source==cancel) {

setVisible(false);

dispose();

}

}

}

}

/** a box with an input text field and OK and Cancel buttons */

class NewArticleBox extends Dialog {

private Editor theEditor;

private GUI parent;

private Button post, abort;

private TextField FromField;

private TextField SubjectField;

private TextArea Article;

public NewArticleBox(GUI p, String title, boolean modal) {

super(p,title,modal);

parent = p;

theEditor = parent.getEditor();

Panel p1 = new Panel();

FromField = new TextField(30);

SubjectField = new TextField(30);

p1.add(new Label("From :"));

p1.add(FromField);

p1.add(new Label("Subject :"));

p1.add(SubjectField);

add("Center",p1);

Panel p2 = new Panel();

post = new Button("POST");

abort = new Button("Abort");

p2.add(post);

p2.add(abort);

CommandHandler handler = new CommandHandler();

post.addActionListener(handler);

abort.addActionListener(handler);

add("North",p2);

Article = new TextArea(20, 80);

add("South", Article);

pack();

setVisible(true);

}

private class CommandHandler implements ActionListener {

public void actionPerformed(ActionEvent e) {

Button source = (Button) e.getSource();

if (source==post) {

String ArticleText = "From: " + FromField.getText() + "\n" + "Subject: " + SubjectField.getText() + "\n" + Article.getText();

System.out.println("Article: " + ArticleText);

System.out.println("Du har tryckt på POST");

parent.theEditor.AddArticle(ArticleText);

setVisible(false);

dispose();

}

else if (source==abort) {

setVisible(false);

dispose();

}

}

}

}

/** the editor, connected to the GUI and the database */

class Editor {

public Database data; // the database

private GUI gui; // the GUI

public NetIO MyNetIO;

/** create the database and the GUI, list the names of the texts */

protected Editor(String host, int port) {

data = new Database();

MyNetIO = new NetIO(host, port);

String Header = "jEdit3 host : " + host + " port : " + port;

MyNetIO.init();

MyNetIO.GetGroupList(data);

gui = new GUI(this, Header, host, port, MyNetIO);

listGroups();

}

/** access to GUI, list names of Groups */

public void listGroups() {

gui.clearGroupList();

int nbr = data.nbrGroups;

for (int k = 0; k<nbr; k++){

//if (data.getGroup(k))

gui.addToGroupList(data.getGroup(k));

//else

//gui.addToGroupList("Efter sista raden");

}

}

public void DeleteGroup(String Group)

{

MyNetIO.DeleteGroup(Group, data);

if (Group.equalsIgnoreCase(data.CurrGroup)){

data.clearArts();

gui.clearArticleList();

}

}

/** access to GUI, list names of texts */

public void listArticles(){

gui.clearArticleList();

int nbr = data.nbrArts;

for (int k = 0; k<nbr; k++){

//if (data.getGroup(k))

gui.addToArticleList(data.getArts(k));

//else

//gui.addToGroupList("Efter sista raden");

}

//System.out.println("Editor : " + nbr);

}

/** Delete Article */

public void DeleteArticle(int Selected){

MyNetIO.DeleteArticle(Selected, data);

MyNetIO.GetArticleList(data.CurrGroup, data);

listArticles();

}

/** Add Article */

public void AddArticle(String ArticleText){

MyNetIO.AddArticle(ArticleText);

MyNetIO.GetArticleList(data.CurrGroup, data);

listArticles();

}

/** get a text from the database */

public String loadText(int k) {

return data.getText(k);

}

/** save a text */

public void saveText(int k, String s){

data.setText(k, s);

}

/** change a text name */

public void changeName(int k, String s) {

data.setArts(k, s);

}

}

/** NetIO: the main application class for the News Client */

//import clientServer.*

import java.io.*;

import java.net.*;

import java.lang.*;

import java.awt.*;

class Conn {

public static final int ConnectionClosed = 1000;

private Socket mySocket;

private InputStream input;

private OutputStream output;

public Conn(String host, int port) {

mySocket = null;

try {

mySocket = new Socket(host,port);

input = mySocket.getInputStream();

output = mySocket.getOutputStream();

}

catch (IOException e) {

// failure to open => mySocket==null, checked in isConnected()

}

//int cmdnr = readCmd();

//System.out.println("Conn : cmdnr = " + cmdnr);

//String cmdtext = readText();

//System.out.println("Conn : cmdtext = " + cmdtext);

}

public boolean isConnected() {

return mySocket != null;

}

public void write(char data) {

if (mySocket == null)

error("write attempted on a not properly opened Connection");

try {

output.write(data);

}

catch (IOException e) {

error("Connection.write: " + e);

}

}

public void write(byte[] data) {

if (mySocket == null)

error("write attempted on a not properly opened Connection");

try {

int x = 0 ;

while (x < data.length && data[x] != 0 ){

output.write(data[x]);

x++;

}

}

catch (IOException e) {

error("Connection.write: " + e);

}

}

public int read() {

if (mySocket == null)

error("read attempted on a not properly opened Connection");

try {

int data = input.read();

return data != -1 ? data : ConnectionClosed;

}

catch (IOException e) {

// server failure, return ConnectionClosed

return ConnectionClosed;

}

}

public int readCmd()

{

byte[] nr=new byte[3];

int t=23;

if (mySocket == null)

error("read attempted on a not properly opened Connection");

read(nr);

String debug = new String(nr);

//System.out.println("readCmd : " + debug);

return new Integer(new String(nr)).intValue();

}

public String readText()

{

byte[] indata = new byte[200];

if (mySocket == null)

error("read attempted on a not properly opened Connection");

read(indata);

String thisstring = new String(indata);

//System.out.println("readText : " + thisstring);

return(thisstring);

}

public byte[] readCmd2()

{

byte[] nr=new byte[3];

int t=23;

if (mySocket == null)

error("read attempted on a not properly opened Connection");

read(nr);

return(nr);

}

public int read(byte[] indata) {

if (mySocket == null)

error("read attempted on a not properly opened Connection");

try {

int x = 0;

int OneChar = input.read();

while (new Integer(OneChar).byteValue() != '\n' && OneChar != -1 && x < indata.length){

indata[x++] = new Integer(OneChar).byteValue();

OneChar = input.read();

}

String debug = new String(indata);

//System.out.println("read : " + debug);

return OneChar != -1 ? OneChar : ConnectionClosed;

}

catch (IOException e) {

// server failure, return ConnectionClosed

return ConnectionClosed;

}

}

private void error(String msg) {

System.out.println(msg);

System.exit(0);

}

}

public class NetIO

{

private Conn conn;

private Database Data;

NetIO(String host, int port)

{

conn=new Conn(host,port);

//conn.readCmd2();

//conn.read(new byte[200]);

}

public void InvokeData(int cmd,String CommandLine)

{

switch(cmd)

{

case 205: //kill kill

//exit(0);

Runtime.getRuntime().exit(0);

break;

case 211:

//Set group

break;

case 215:

//newsgroups

break;

case 220:

//article Head & Body

break;

case 224 : //xRemoveArticle

//cout<<"Article removed from server"<<endl;

break;

case 423 : //no such article

//cout<<"No such article. Try a lower number, dickhead!"<<endl;

//cout<<"server replied"<<CommandLine<<endl;

break;

default:

//cout<<"Unknown Command:"<<cmd<<" "<<CommandLine<<endl;

//break;

}

}

public void GetData(String cmd)

{

int cmdnr;

byte[] cmm=new byte[200];

String CmdLine;

conn.write(cmd.getBytes());

cmdnr=conn.readCmd();

conn.read(cmm);

CmdLine=new String(cmm);

InvokeData(cmdnr,CmdLine);

}

public void init()

{

int cmdnr = conn.readCmd();

System.out.println("init Cmdnr = " + cmdnr);

String cmdtext = conn.readText();

System.out.println("init CmdText = " + cmdtext);

}

public void GetGroupList(Database Data)

{

conn.write("list\n".getBytes());

String str;

Data.clearGroups();

int cmdnr=conn.readCmd();

//System.out.println("cmdnr = " + cmdnr);

String cmdtext = conn.readText();

//System.out.println("cmdtext = " + cmdtext);

//System.out.println("");

int counter = 0;

if(cmdnr==215)

{

cmdtext = conn.readText();

str=new String(cmdtext);

while(str.charAt(0) != '.')

{

//System.out.println(str.charAt(1));

if (Data.getNbrTexts() > counter){

Data.setGroup(counter, str);

counter++;

}

cmdtext = conn.readText();

//System.out.println("AddGroupList = " + cmdtext);

str=new String(cmdtext);

}

//System.out.println("Out of While ");

}

else{

Data.setGroup(0, "Wrong command found : " + new Integer(cmdnr).toString(cmdnr));

}

}

public void GetArticleList(String group, Database Data)

{

String sendtext = "group ";

conn.write(sendtext.getBytes());

conn.write(group.getBytes());

conn.write('\n');

String str;

String ThisArticle;

String ArticleName;

boolean FirstRow;

//int cmdnr = 211;

int cmdnr=conn.readCmd();

//System.out.println("cmdnr = " + cmdnr);

String cmdtext = conn.readText();

//System.out.println("cmdtext = " + cmdtext);

//System.out.println("");

int counter = 0;

if(cmdnr==211)

{

int NbrArts = 0;

int x = 0;

while (cmdtext.charAt(x) != ' '){

NbrArts = NbrArts * 10 + cmdtext.charAt(x)-0x30;

//System.out.println("NbrArts = " + NbrArts);

x++;

}

Data.clearArts();

ArticleName = "";

for (x = 1; x <= NbrArts; x++){

conn.write("article ".getBytes());

conn.write(new Integer(x).toString().getBytes());

conn.write('\n');

cmdnr=conn.readCmd();

//System.out.println("GetArticleList : CmdNr = " + cmdnr);

cmdtext = conn.readText();

//System.out.println("GetArticleList : CmdText = " + cmdtext);

cmdtext = conn.readText().trim();

if (cmdnr != 220)

System.out.println("No such article. This might cause serious error");

else{

str=cmdtext;

ThisArticle = "";

//System.out.println("str = " + str);

FirstRow = true;

while(str.charAt(0) != '.'){

cmdtext = conn.readText().trim();

if (FirstRow){

ArticleName = cmdtext.substring(8);

}

FirstRow = false;

//System.out.println("New line = " + cmdtext);

ThisArticle = ThisArticle + str + '\n';

str = cmdtext;

//str=new String(cmdtext).trim();

//System.out.println("str = -" + str + "-");

//System.out.println("str.length() = " + str.length());

if (str.length() == 0){

str = " ";

//System.out.println("Found empty str");

//System.out.println("str = -" + str + "-");

//System.out.println("str.length() = " + str.length());

}

}

Data.setArts(x-1, ArticleName);

Data.setText(x-1, ThisArticle);

}

}

Data.CurrGroup = group;

Data.hasCurrGroup = true;

//System.out.println("hasCurrGrou = true");

}

else{

Data.setGroup(0, "Wrong command found : " + new Integer(cmdnr).toString(cmdnr));

}

}

public void DeleteGroup(String Group, Database Data)

{

conn.write(("xremovegroup ").getBytes());

conn.write(Group.getBytes());

conn.write('\n');

System.out.println("NetIO : Removing Group : " + Group);

int cmdnr = conn.readCmd();

String cmdtext = conn.readText();

if (cmdnr != 226)

System.out.println("Error : Wrong return code for remove");

}

public void AddGroup(String Group, Database Data)

{

conn.write(("xaddgroup ").getBytes());

conn.write(Group.getBytes());

conn.write('\n');

System.out.println("NetIO : Adding Group : " + Group);

int cmdnr = conn.readCmd();

String cmdtext = conn.readText();

if (cmdnr != 225)

System.out.println("Error : Wrong return code for add");

}

public void DeleteArticle(int Selected, Database Data)

{

conn.write(("xremovearticle ").getBytes());

conn.write(Integer.toString(Selected).getBytes());

conn.write('\n');

System.out.println("NetIO : Removing Article : " + Selected);

int cmdnr = conn.readCmd();

String cmdtext = conn.readText();

if (cmdnr != 224)

System.out.println("Error : Wrong return code for remove");

}

public void AddArticle(String ArticleText)

{

conn.write(("post ").getBytes());

conn.write('\n');

int cmdnr = conn.readCmd();

String cmdtext = conn.readText();

if (cmdnr != 340)

System.out.println("Error : Wrong op-code from server on post request");

conn.write(ArticleText.getBytes());

conn.write('\n');

conn.write('.');

conn.write('\n');

cmdnr = conn.readCmd();

cmdtext = conn.readText();

if (cmdnr != 240)

System.out.println("Error : Wrong op-code from server on article posting");

}

public void KillServer(){

conn.write("xkillserver".getBytes());

conn.write('\n');

System.out.println("Attempting server murder");

}

}

/** a database with a number of texts with names. The texts can be

edited and saved */

public class Database {

private final int NBRTEXTS = 256; // number of texts

private String arts[]; // names of texts

private String text[]; // the texts to edit

private String group[]; // Groups

public int nbrGroups;

public int nbrArts;

public String CurrGroup;

public boolean hasCurrGroup;

public Database() {

arts = new String[NBRTEXTS];

arts[0] = "Text 1";

arts[1] = "Text 2";

arts[2] = "Text 3";

nbrArts = 0;

text = new String[NBRTEXTS];

/*text[0] = "This is the first text\n";

text[1] = "First line of second text\nLast line\n";

text[2] = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLast line\n";

*/

group = new String[NBRTEXTS];

group[0] = "Empty";

nbrGroups = 0;

CurrGroup = "";

hasCurrGroup = false;

System.out.println("hasCurrGrou = false");

}

public int getNbrTexts() {

return NBRTEXTS;

}

public String getGroup(int i) {

return group[i];

}

public void setGroup(int i, String s) {

if ((i + 1) > nbrGroups)

nbrGroups = i+1;

group[i] = s;

}

public void clearGroups(){

nbrGroups = 0;

}

public void clearArts(){

nbrArts = 0;

CurrGroup = "";

hasCurrGroup = false;

//System.out.println("hasCurrGrou = false");

}

public String getArts(int i) {

return arts[i];

}

public void setArts(int i, String s) {

if ((i + 1) > nbrArts)

nbrArts = i+1;

arts[i] = s;

}

public String getText(int i) {

return text[i];

}

public void setText(int i, String s) {

text[i] = s;

//System.out.println("Database : " + s);

}

}

B. Klasser

JEdit

Huvudprogram

GUI

Det grafiska, hanterar knappar och texter.

Editor

Tar hand om lite av varje, ett mellanskicka mellan GUI och klassen NetIO

Database

Hanterar datan.

Conn

Pratar med omvärden, används endast av NetIO.

NetIO

Pratar med omvärden via Conn , tar hand om NNTP.