Montag, 30. November 2009

misunderstanding on casting in go

huch, have needed one day to understand that a function is in really was a cast.
look:
path.Walk(p.String(), pathIter(c), nil);

you can think pathIter(c) is a function. but:

type pathIter chan<- Path

pathIter is a typedefinition. Therefore is pathIter(c) not a function with parameter c, rahter a casting from c (is a Path channel) to pathIter.

Sonntag, 29. November 2009

input from stdion in go


package main

import (
"os"; "fmt"; "bufio";
)

func main() {

fmt.Print("input your name: ");

br := bufio.NewReader(os.Stdin);

name, _ := br.ReadString('\n');

fmt.Println();
fmt.Println("your name is: ", name);

}



func NewReader(rd io.Reader) *Reader NewReader returns a new Reader whose buffer has the default size.

func (b *Reader) ReadString(delim byte) (line string, err os.Error) read until delim byte.
here we read until enter.

Samstag, 28. November 2009

urlescap in http


url := "http://blub.org/b.html?v1=23&v2=bla&v=sdl+sdo";
surl := http.URLEscape(url);

fmt.Println(url);
fmt.Println(surl);

url2 := "http://это.порусс.ки/здесь.хтмл";
surl2 := http.URLEscape(url2);

fmt.Println(url2);
fmt.Println(surl2);


output:
http://blub.org/b.html?v1=23&v2=bla&v=sdl+sdo
http://blub.org/b.html%3fv1%3d23%26v2%3dbla%26v%3dsdl%2bsdo

http://это.порусс.ки/здесь.хтмл
http://%d1%8d%d1%82%d0%be.%d0%bf%d0%be%d1%80%d1%83%d1%81%d1%81.%d0%ba%d0%b8/%d0%b7%d0%b4%d0%b5%d1%81%d1%8c.%d1%85%d1%82%d0%bc%d0%bb


http.URLUnescape(url string) do it back.

read a file and print the count of lines


package main

import (
"io";
"fmt";
"os";
"strings";
)

func main() {
// read the file in bytes array
b, err := io.ReadFile("readfile.go");
if err!=nil {
fmt.Println("error on read file");
os.Exit(-1);
}

// convert from bytes to string
strbuffer := string(b);

// split into lines
lines := strings.Split(strbuffer, "\n", 0);

// iterate each
for i, line := range lines {
fmt.Printf("%d: %s\n", i, line);
}
}

Freitag, 27. November 2009

strings package in golang


package main

import (
"strings";
"fmt";
)

func main() {
data := "bla blu blub";
fmt.Println(data);
// return: bla blu blub

// convert string in bytes
b := strings.Bytes(data);
fmt.Println(b); // print every byte as array
// return: [98 108 97 32 98 108 117 32 98 108 117 98]


// test if the string begin with the prefix
if strings.HasPrefix(data, "bl") {
fmt.Println("data: \"", data, "\" begin with the prefix \"bl\"");
}

// test if the string end with the suffix
if strings.HasSuffix(data, "blub") {
fmt.Println("data: \"", data, "\" end with \"blub\"");
}

// Index returns the index of the first instance of sep in s,
// or -1 if sep is not present in s.
fmt.Println("index: ", strings.Index(data, "blu"));
// return: index: 4

fmt.Println("index: ", strings.Index(data, "b"));
// return: index: 0
fmt.Println("last index: ", strings.LastIndex(data, "b"));
// return: last index: 11
// LastIndex return the last occurency of seeking string

// with Repeat you can repeat ;)
fmt.Println("r: ", strings.Repeat("x", 10));
// return: r: xxxxxxxxxx

// split the string in array of string
as := strings.Split("root:alsdfjl:230:/blub/blub:lalalala", ":", 0);

fmt.Println(as);
// return: [root alsdfjl 230 /blub/blub lalalala]

fmt.Println(strings.Join(as, "|"));
// return: root|alsdfjl|230|/blub/blub|lalalala

fmt.Println(strings.ToLower("UASFalsdfuADSFWE$$"));
// return: uasfalsdfuadsfwe$$

fmt.Println(strings.ToUpper("owenadsfoadsfj"));
// return: OWENADSFOADSFJ

fmt.Println("<", strings.TrimSpace(" asdf sdowe "), ">");
// return: < asdf sdowe >
}

base64 in golang


package main

import (
"encoding/base64";
"bytes";
"fmt";
)

func main() {
// create the buffer
bb := &bytes.Buffer{};
bbURL := &bytes.Buffer{};

// create two base64 encoder (standard and for url)
encoder := base64.NewEncoder(base64.StdEncoding, bb);
encoderURL := base64.NewEncoder(base64.URLEncoding, bbURL);

data := "hallo this is a test, a=23&var2=blabla+-?!%$/\\";
fmt.Println("data : ", data);

// to encode data, use Write([]bytes),
// therefore you must convert string to bytes
// with string.Bytes(d string)
encoder.Write([]byte(data));
encoder.Close();

encoderURL.Write([]byte(data));
encoderURL.Close();

// voila
fmt.Println("encoded Std: ", bb.String());
fmt.Println("encoded URL: ", bbURL.String());
}

Mittwoch, 25. November 2009

time in go


package main

import "fmt"
import "time"

func main() {

fmt.Println("time in seconds : ", time.Seconds());
fmt.Println("time in nanoseconds: ", time.Nanoseconds());

fmt.Println("sleep 1 second.");

time.Sleep(1*1000*1000*1000);

fmt.Println("time in seconds : ", time.Seconds());
fmt.Println("time in nanoseconds: ", time.Nanoseconds());

fmt.Println("wait sleep 1 second.");
before := time.Nanoseconds();
time.Sleep(1*1000*1000*1000);
after := time.Nanoseconds();
fmt.Println("difference of nanoseconds: ", (after-before));

t:=time.LocalTime();
fmt.Println("time.String(): ", t.String());
}


time.Seconds() get the time as unix time in seconds
time.Nanoseconds() dito
time.Sleep(x) sleep for x nanoseconds
to sleep 1 second do time.Sleep(1e9)


to get any type back from function
let look:

package main

import "fmt"
import "rand"
import "time"

func my() interface{} {

rand.Seed(time.Nanoseconds()/1000000);

switch rand.Intn(3) {
case 0: var i int; i=4; return i;
case 1: var f float; f=2.3; return f;
case 2: var s string; s="blub"; return s;
}
var b byte;
b='c';
return b;
}

func main() {
fmt.Println(my());
time.Sleep(1e9);
fmt.Println(my());
time.Sleep(1e9);
fmt.Println(my());
time.Sleep(1e9);
fmt.Println(my());
time.Sleep(1e9);
fmt.Println(my());
}


with func my() interface{} {...} we declare a function which return an interface. This is a void interface, which can implement all types. Thus we can back every typ back. The my() function simple init the rand and get randomly different types back.

Dienstag, 24. November 2009

golang networking

a simple get for http:

package main

import (
"io";
"strings";
"log";
"http";
"fmt";
)

func main() {
r, _, err := http.Get("http://www.google.com/robots.txt");
var b []byte;
if err == nil {
b, err = io.ReadAll(r.Body);
r.Body.Close();
}

if err != nil {
log.Stderr(err)
} else {
fmt.Println(string(b));
}
}

ok, it was not very simple.
r, _, err := http.Get("http://www.google.com/robots.txt");
get the Response in r. Response has: a StatusCode, Body and Header.

type Response struct {
Status string; // e.g. "200 OK"
StatusCode int; // e.g. 200
Header map[string]string;
Body io.ReadCloser;
}

Header is a simple string hash. Body is an interface to ReadCloser: all structures with Read and Close.
func Get(url string) (r *Response, finalURL string, err os.Error) is doing followings:
- do a redirection loop (maximal 10 times)
- parse the url
- send the request
- if should redirect, get the new location in header
- if should not redirect: return the result from send()

b, err = io.ReadAll(r.Body);
read the data from response body (which has a reader from connection) in a byte array.
fmt.Println(string(b));
printout the bytes as string

create a simple webserver

package main

import (
"http";
"io";
)

// hello world, the web server
func HelloServer(c *http.Conn, req *http.Request) {
io.WriteString(c, "hello, world!\n");
}

// call a html page
func MyServerPage(c *http.Conn, req *http.Request) {
http.ServeFile(c, req, "myhtml.html");
}

func main() {
http.Handle("/hello", http.HandlerFunc(HelloServer));
http.Handle("/my.html", http.HandlerFunc(MyServerPage));
err := http.ListenAndServe(":8080", nil);
if err != nil {
panic("ListenAndServe: ", err.String())
}
}

http.Handle("/hello", http.HandlerFunc(HelloServer));
set the hadler function HelloServer with "/hello".

err := http.ListenAndServe(":8080", nil);
start the TCP server on port 8080, that handle the registered handler.

io.WriteString(c, "hello, world!\n"); write a simple string.

http.ServeFile(c, req, "myhtml.html"); read the file and print it out.

Samstag, 21. November 2009

learning go

so there will be some golang tips.

 
type My struct {
a, b int;
name string;
}

create a struct with three variables, a and b are integers. name is a string. The struct name is My.


m := My{1,2,"ray"};
fmt.Println(m);

m:= XXX{inputs} create and initialize the struct to variable m.
Println(m) print out: {1 2 ray}.

to create you own methods for the stuct do: func (v *Mystruct) method(...) returntyps { ... }

func (m *My) String() string {
ret := fmt.Sprintf("a: %d, b: %d, name: %s\n", m.a, m.b, m.name);
return ret;
}

here we create the String() method for printing our struct as a string. Access variables are done through m.var.

to define a simple array of integers: a:=[3]int{1,2,3}
if you don't know the length: a:=[]int{1,2,3,4,5,1,2,3}

create an assoziative array or dictionary or hash: hash := map[string]int{"eins":1, "zwei":2, "drei":3}; where map[keytyp]valuetyp.

hash2 := map[string]string{"blub":"aodu", "a":"ousdf", "ouew":"gofdu"};

// iterate through the hash, range return the key and value of the hash.
for k, v := range hash2 {
fmt.Println("key: ",k," value: ",v);
}

print out:
key: blub value: aodu
key: ouew value: gofdu
key: a value: ousdf


Read a directory:

package main

import (
"io";
"fmt";
)

func main() {
dir, err := io.ReadDir("/home/ray/daten");

fmt.Println("err: ", err);
fmt.Println(dir);

for _, v := range dir {
fmt.Println(">>", v);
}
}


let look the source on src/pkg/io/utils.go:

// ReadDir reads the directory named by dirname and returns
// a list of sorted directory entries.
func ReadDir(dirname string) ([]*os.Dir, os.Error) {
f, err := os.Open(dirname, os.O_RDONLY, 0); // open you directory
if err != nil {
return nil, err
}
list, err := f.Readdir(-1); // f is a file handler
f.Close();
if err != nil {
return nil, err
}
dirs := make(dirList, len(list));
for i := range list {
dirs[i] = &list[i]
}
sort.Sort(dirs);
return dirs, nil;
}

func ReadDir(dirname string) ([]*os.Dir, os.Error) : ReadDir reads the directory named by dirname and returns a list of sorted directory entries.

func Open(name string, flag int, perm int) (file *File, err Error): Open opens the named file with specified flag (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful, methods on the returned File can be used for I/O. It returns the File and an Error, if any.

Open return a File pointer. internal Open called a syscall to open

func (file *File) Readdir(count int) (dirs []Dir, err Error): Readdir reads the contents of the directory associated with file and returns an array of up to count Dir structures, as would be returned by Stat, in directory order. Subsequent calls on the same file will yield further Dirs. A negative count means to read until EOF. Readdir returns the array and an Error, if any.

our io.ReadDir() open the dir, read it through the file, create a list, sort and return the dir list.


for _, v := range dir {
if v.IsDirectory() {
fmt.Println(v.Name," is directory");
}
}

print out all direcotries name.

more info about dir is in: src/pkg/os/types.go or http://golang.org/pkg/os/#Dir

Read a file

fileObj, err := os.Open( "echo.go", os.O_RDONLY, 0666 );
if err != nil {
log.Stderr( err );
return;
}

//open the file and test for errors. log.Stderr print the message with a timestamp as a log.

// create a buffered reader
r := bufio.NewReader( fileObj );

// read each line
for {
line, err := r.ReadString('\n');

Dienstag, 17. November 2009

some go libraries























PackagePurposeExamples
fmtformatted I/OPrintf, Sprintf
osOS interface Open, Read, Write
strconvnumbers <-> stringsAtoi, Atof, Itoa
iogeneric I/O Copy, Pipe
flagflags: --help etc.Bool, String
logevent logging Log, Logf, Stderr
regexpregular expressions Compile, Match
templateHTML, etc.Parse, Execute
bytesbyte arraysCompare, Buffer


further libs: bignum, crypto, encoding, exec, hash, http, image, json, net, math, rand, regexp, sort, syscall, xml, time, unicode,

go pakcages

package is a collection of source files begining with "package nameofpackage".


import "fmt"
// now useable fmt outputs
fmt.Print(...)

import my "fmt" // with my own name. (for purpose if namespace coliders ;)
my.Print(...)


each package can have an init() for initalization data (single threaded).

let see:
a.go

package a

import "fmt"

var A int

func init() {
A = 4;
fmt.Print("A init\n");
}


b.go

package b

import "fmt"

var B int

func init() {
B=15;
fmt.Print("B init\n");
}


mainab.go

package main

import (
"fmt";
"./a";
"./b";
)

func main() {
fmt.Print("call main()\n");
var x= a.A;
var y= b.B;
var z = x + y;
fmt.Print(z);
}


output:

./6.out
B init
A init
call main()


at first there will be called init. later the main.

"To build a program, the packages, and the files within them, must be compiled in the correct order.
Package dependencies determine the order in which to build packages. "

defer in go

"The defer statement executes a function (or method)
when the enclosing function returns. The arguments
are evaluated at the point of the defer; the function
call happens upon return." GocourseDay1.pdf

leet look folowing programm:

package main

import "fmt"

func b() {
fmt.Printf("called b()\n");
}

func a() int {
fmt.Printf("start a()\n");
defer b();
fmt.Printf("ended a()\n");
return 0;
}

func main() {
fmt.Printf("start main\n");
fmt.Printf("call a()\n");
a();
fmt.Printf("after a()\n");
fmt.Printf("\n");
}


a() call with defer b(). But the outprint show:

./6.out
start main
call a()
start a()
ended a()
called b()
after a()



we can see that b() will be called before a() return.

=> defer is useful for closing fds, unlocking mutexes, etc.

defer is simmilar to atexit() for main() in C.

futher example:

package main

import "fmt"

func trace(s string) string {

fmt.Print("entering:", s, "\n");
return s
}
func un(s string) {
fmt.Print("leaving:", s, "\n")
}
func a() {

defer un(trace("a"));
fmt.Print("in a\n")
}
func b() {

defer un(trace("b"));
fmt.Print("in b\n");
a()
}
func main() { b() }


the output is:

./6.out
entering:b
in b
entering:a
in a
leaving:a
leaving:b

as we can see: defer f1(f2()) f2() is called immediately but f1() is called at ending.

further go

Go doesn't have references.

all private functions begin with small character.
all public functions begin with big character.

To generate some Unit test:
name: mylib_test.go ( xxx_test.go )
the function must be called: TestXXX(t *testing.T) { ...
and import: "testing"

send Fatal error

if err != nil {
t.Fatalf("Myerror %q: %s", path, err)
}
// or
t.Errorf("bla bla %q ", path)


The T struct is:

type T struct {
errors string;
failed bool;
ch chan *T;
}


There are some functions XXXf are with format string

Fail(), Failed(): set the failed variable or ask them. (don't exit)
FailNow() set the fail and exit.

Log()/Logf(): set the errors string.
Error()/Errorf(): Log with Fail
Fatal()/Fatalf(): Log with FailNow


To test a package, write a set of Go source files
within the same package; give the files names of the
form *_test.go.

testing tool: gotest

func TestXxxx(t *testing.T)

create the file. later call gotest my_test.go

Montag, 16. November 2009

trapped go

we create first a file (package) Person
Person.go:

package Person

type Person struct {
vorname string;
name string;
alter int;
}

func NewPerson(v string, n string, a int) *Person {
return &Person{v, n, a}
}

func (pers *Person) String() string {
return "Name: "+pers.name+" Vorname: "+pers.vorname;
}


then the main package with main()

Main.go

package main

import (
prs "./Person";
"fmt";
)


func main() {

person := prs.NewPerson("blue", "blub", 42);


fmt.Printf("person is: \n");
fmt.Printf(person.String());
fmt.Printf("\n");
}


compile and link:
6g Person.go
6g Main.go
6l -o Main Main.6

execute: ./Main
>person is:
>Name: blub Vorname: blue

At first we must import our file as "./Person"

At second the function that are created for outside must begin with Capitalized Character.


package Person

type Person struct {
vorname string;
name string;
alter int;
}

func newPerson(v string, n string, a int) *Person {
return &Person{v, n, a}
}


Person.newPerson(...) doesnot work.

"For clients (importers) of the package, names must
be upper case to be visible: global variables,
functions, types, constants, plus methods and
structure fields for global variables and types.

const hello = "you smell" // package visible
const Hello = "you smell nice" // globally visible
const _Bye = "stinko!" // _ is not upper
"

Sonntag, 15. November 2009

Go

Here is some introduction to new Google programing language.

At first go has his design to build a fast compiling system programming language for fast application. There is no mess with Java or C#/C++. go has no inheritance, but interfaces.

simple tutorial can be found on golang.org

At first the question: why yet another language?
google need a language which is fast in compiling and runing. Has the advantages of typing but not overloaded wiht oop stuff.

simple example:

// define the namespace
package main

// import the formated print package
// import fmt "fmt";

// import a couple of packages
import (
"flag"; // flag package is a good replacament for main(int argc, char **args) and
// replace the argument calculation with getopt() and switch. then create
// a help function automatic.
"fmt";
)

// create a boolean variable from package flag and set the values
var blub = flag.Bool("g", false, "blub lubn blub")

// g => -g
// false => set it at first to false
// "blub..." => description in help switch


func main() {
flag.Parse();
// parse the arguments

// ask if the
if *blub {
fmt.Printf("blub was setted\n");
} else {
fmt.Printf("blub was not setted\n");
}
}


as you has see variables are defined with var

var v1 int;
var v2 string;
var v3 float;


for printing is there the package fmt: fmt.Printf(..)
then exists other methods as in C.

to compile:
x64:
6g file.go
6l file.6 -o file

for x86
8g file.go
8l file.8 -o file

to be continued ...

...

Mittwoch, 11. November 2009

cools news

Google new language Go link

coole eclipse code highstyling plugin: link

Dienstag, 10. November 2009

JFace snippets and Images

some information about Eclipse (3.3) images can be found here: shinkarenko.

JFaceSnippets is a collection of code snippets for JFace.

Donnerstag, 5. November 2009

Eclipse RCP Forms part one

Eclipse Forms allow you to achieve the Web look. Eclipse Editors for Manifest files (f.e) are coded in Forms.

tutorials links:
vogella tutorial about forms
forms tutorial 2
forms tutorial 3

Forms use Views:


public class FormView extends ViewPart {
public void createPartControl(Composite parent) {
toolkit = new FormToolkit(parent.getDisplay());
form = toolkit.createForm(parent);
form.setText("Hello, Eclipse Forms");


it create the form where you can set other widgets.

Therefore forms use GridLayot, GridData, Buttons and other similar as SWT.


GridLayout layout = new GridLayout();
form.getBody().setLayout(layout);

layout.numColumns = 2;
GridData gd = new GridData();
gd.horizontalSpan = 2;
link.setLayoutData(gd);
Label label = new Label(form.getBody(), SWT.NULL);
label.setText("Text field label:");
Text text = new Text(form.getBody(), SWT.BORDER);
text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Button button = new Button(form.getBody(), SWT.CHECK);
button.setText("An example of a checkbox in a form");
gd = new GridData();
gd.horizontalSpan = 2;
button.setLayoutData(gd);



Hyperlink link = toolkit.createHyperlink(form.getBody(), "Click here.", SWT.WRAP);
link.addHyperlinkListener(new HyperlinkAdapter() {
public void linkActivated(HyperlinkEvent e) {
System.out.println("Link activated!");
}
});

create a hyperlink as a HTML hyperlink.


for more information look tutorials

Montag, 2. November 2009

RCP Tree Viewer part 2

here is the continuation of part one.

tutorial to JFace TreeViewer very good details.


At first we change our staticaly views and root objects.
change in ViewPart1 (thus was it called my TreeViewer ViewPart)

private TreeViewer viewer;
private RootNames root;

public RootNames getTreeRoot() {
return root;
}

public TreeViewer getTreeViewer() {
return viewer;
}


now change the create the Command Add and Del and add them to menu. (see Vogella )


public class CommandAdd extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {

System.out.println("start");
ViewPart1 view = (ViewPart1) HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().findView(ViewPart1.ID);

RootNames root = view.getTreeRoot();

HostsNames hn = new HostsNames("212.40.32.55", "212.40.32.55");
root.addChild(hn);
hn.addChild(new Commandos("syslog", "syslog"));
hn.addChild(new Commandos("top", "top -d 1"));
hn.addChild(new Commandos("network", "network"));

view.getTreeViewer().refresh();
return null;
}
}

public class CommandDel extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {

ViewPart1 view = (ViewPart1) HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().findView(ViewPart1.ID);

RootNames root = view.getTreeRoot();

HostsNames hn = root.getChildren()[0];

Commandos c = hn.children.get(0);

hn.removeChild(c);

view.getTreeViewer().refresh();
return null;
}

}


Now we create a second View where we simple put some text.

The commands simple add and del some item of tree.

public class OutputView extends ViewPart {
public static final String ID = "zzz.zmytest.Tree.Views.OutputView";
public Text text;

@Override
public void createPartControl(Composite parent) {
text = new Text(parent, SWT.BORDER);
text.setText("Imagine a fantastic user interface here");
}

@Override
public void setFocus() {
}
}

we will simple alter the text.

selection Listener
selection Listener

we implement ISelectionListener:

public class OutputView extends ViewPart implements ISelectionListener{

@Override
public void createPartControl(Composite parent) {
...

getSite().getPage().addSelectionListener((ISelectionListener) this);
}

@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
text.setText(selection.toString());
}
}


add the view in the perspective:


public class Perspective implements IPerspectiveFactory {

public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(false);

layout.addStandaloneView(ViewPart1.ID, false, IPageLayout.LEFT, 0.25f, editorArea);
IFolderLayout folder = layout.createFolder("outputs", IPageLayout.TOP, 0.5f, editorArea);
folder.addPlaceholder(OutputView.ID + ":*");
folder.addView(OutputView.ID);

layout.getViewLayout(ViewPart1.ID).setCloseable(false);
}
}


set the tree view to selection provider:

public class ViewPart1 extends ViewPart {
...

public void createPartControl(Composite parent) {
...

// add to selection provider
getSite().setSelectionProvider(viewer);

}


improve the listener:

@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (selection instanceof IStructuredSelection) {
Object obj = ((IStructuredSelection) selection).getFirstElement();
if (obj != null) {
if (obj instanceof HostsNames) {
HostsNames hn = (HostsNames)obj;
text.setText("hostname: "+hn.name);
} else if (obj instanceof Commandos) {
Commandos co = (Commandos)obj;
HostsNames hn = co.parent;
text.setText("commando: "+co.name+ " von host: "+hn.name);
}
}
}
}


the listener look for IStructuredSelection, get the object and test the object for our class instances.


Now we can add further views provider and listener without to handle the wired code.s

RCP Tree Viewer

here is some info about JFace TreeViewer.

The Model is worked with MVC


  • Viewer: TreeViewer, LabelProvider

  • Model: Your own model, ContentProvider. The Objects should be Singleton

  • Control: create the Model, change the Model, refresh Viewer



Create a RCP Application (for tutorials see: Vogella).

Add a view: Manifest -> Extensions -> All Extensions -> Add ( views)
give an ID, name and create a class.

At first create the Model. The Model is a tree with root and nodes.

root
\
node
\node
\
node
\node
\node


This example create a tree of hosts an commands for each host.

The root class. This object should be a singleton and have access to hostnames objects.
The hostnames object should have access to commands objects.


RootNames
/ | \
/ | \
host1 host2 host3
/ | \ | \ |
c1 c2 c3 c1 c2 command1


create package: xxx.model

The model package will be have: RootNames, HostsNames and Commands class models.


public class RootNames {
private static RootNames root=null;
public String name;
public ArrayList children;

private RootNames(String name) {
this.name=name;
children = new ArrayList();

}

public static RootNames getRootNames(String name) {
if(root!=null)
return root;
RootNames r = new RootNames(name);
root=r;
return root;
}

public String toString() {
return name;
}
}

RootNames is a singleton, has only a name and children of HostsNames. For simplicity we do the access public. Thus we don't need implement setter or getter.

Then we implement following help methods in RootNames:

public void addChild(HostsNames child) {
children.add(child);
child.parent = this;
}

public void removeChild(HostsNames child) {
children.remove(child);
child.parent = null;
}

public HostsNames[] getChildren() {
return (HostsNames[]) children.toArray(new HostsNames[children.size()]);
}

public boolean hasChildren() {
return children.size()>0;
}

- add/removeChild() add/remove a child in a list and set/unset the parent of child.
- getChildren() return an array of objects of children. Here a HostsNames array.

HostsNames:

public class HostsNames {
public String name;
public String host;
public RootNames parent;
public ArrayList children;

public HostsNames(String name, String host) {
this.name = name;
this.host = host;
children = new ArrayList();
}

public void addChild(Commandos child) {
children.add(child);
child.parent = this;
}

public void removeChild(Commandos child) {
children.remove(child);
child.parent = null;
}

public Commandos[] getChildren() {
return (Commandos[]) children.toArray(new Commandos[children.size()]);
}

public boolean hasChildren() {
return children.size()>0;
}

public String toString() {
return name;
}
}


HostsNames: have a name, hostname, parent to root and children of Commandos. And helpers for Children.

Commandos:

public class Commandos {
public String name;
public String commando;
public HostsNames parent;

public Commandos(String name, String commando) {
this.name = name;
this.commando = commando;
}

public String toString() {
return name;
}
}

Commandos have name, commando and reference to HostsNames via parent.


Implement Provider:

create package xxx.provider


public class ViewLabelProvider extends LabelProvider {

public String getText(Object obj) {
return obj.toString();
}

public Image getImage(Object obj) {
String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
if (obj instanceof HostsNames)
imageKey = ISharedImages.IMG_OBJ_FOLDER;
return PlatformUI.getWorkbench().getSharedImages().getImage(imageKey);
}
}

The Label Provider is a View in MVC. it give the name and the image of the Tree back, based on model.

Create a View Content Provider with implemented Interfaces: IStructuredContentProvider and ITreeContentProvider.


public class ViewContentProvider implements IStructuredContentProvider, ITreeContentProvider {

@Override
public Object[] getElements(Object inputElement) {
return null;
}

@Override
public void dispose() {
}

@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}

@Override
public Object[] getChildren(Object parentElement) {
return null;
}

@Override
public Object getParent(Object element) {
return null;
}

@Override
public boolean hasChildren(Object element) {
return false;
}
}


The Content Provider is the model part of MVC. It provide how the TreeViewer can access the model.
following methods must be implemented: getElements(), getParent(), getChildren(), hasChildren().

Implementation:

@Override
public Object[] getElements(Object parent) {
return getChildren(parent);
}
@Override
public Object[] getChildren(Object parent) {
if (parent instanceof RootNames) {
return ((RootNames)parent).getChildren();
}
if (parent instanceof HostsNames) {
return ((HostsNames)parent).getChildren();
}
return new Object[0];
}

@Override
public Object getParent(Object child) {
if (child instanceof HostsNames) {
return ((HostsNames)child).parent;
}
if (child instanceof Commandos) {
return ((Commandos)child).parent;
}
return null;
}

@Override
public boolean hasChildren(Object element) {
if (element instanceof RootNames)
return ((RootNames)element).hasChildren();
if (element instanceof HostsNames)
return ((HostsNames)element).hasChildren();
return false;
}

getElements and getChildren is here the same.

getChildren() return for RootNames or HostsNames his children list as an array. The same is do getParent() and hasChildren().


Now set the ViewPart:

private TreeViewer viewer;
private RootNames root;

@Override
public void createPartControl(Composite parent) {
viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new ViewLabelProvider());
root=ModelCreator.createModel();
viewer.setInput(root);
}

Create the TreeViewer.
Set our Content and Label Provider. Call the Model Creator.

ModelCreator:

public class ModelCreator {

public static RootNames createModel() {
RootNames root = RootNames.getRootNames("root");

HostsNames hn = new HostsNames("localhost", "localhost");
root.addChild(hn);
hn.addChild(new Commandos("syslog", "syslog"));
hn.addChild(new Commandos("top", "top -d 1"));

hn = new HostsNames("134.108.68.107", "134.108.68.107");
root.addChild(hn);
hn.addChild(new Commandos("syslog", "syslog"));
hn.addChild(new Commandos("top", "top -d 1"));

return root;
}
}

createModel() create a root with two hostnames and his commandos.

Then we must set the view in perspective

String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(false);

layout.addStandaloneView(ViewPart1.ID, false, IPageLayout.LEFT, 0.95f, editorArea);

layout.getViewLayout(ViewPart1.ID).setCloseable(false);


to add some context to the tree (here an example with a Command:

public class CommandAdd extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
System.out.println("blub");
RootNames root = ViewPart1.getTreeRoot();
System.out.println("blub: "+root);

HostsNames hn = new HostsNames("212.40.32.55", "212.40.32.55");
root.addChild(hn);
hn.addChild(new Commandos("syslog", "syslog"));
hn.addChild(new Commandos("top", "top -d 1"));
hn.addChild(new Commandos("network", "network"));

ViewPart1.getTreeViewer().refresh();

return null;
}
}


simple get the singleton and add some childs. Then refresh the view.