Newbie - Making simple Login/Authentication for "AddressBook" Tutorial?

Hello Vaadin Lovers! -_-

This is the structure of this threat:
[b]

1 - My Goal
2 - Step by Step
3 -

QUESTIONS


[/b]
(for “Advanced Users” if they have time to explain us “why” or if they can apport some source where it explains this questions.)



4 - Original Source where we start from.

(You can also download the project from
HERE
)




1 - Goal for this threat.


Step 1: Only when I put right username and password.

Step 2: I get permision to see “AddresBookApplication”.




2 - Step by Step



Step 1:
We go to this link and search after the source of this example.

Authentification Source


Step 2:
We copy this source inside the link before.

[color=#f600ff]
private Layout buildLoginForm() {
    FormLayout layout = new FormLayout();
    // Create a label which we can use to give feedback to the user
    final Label feedbackLabel = new Label();

    // Create input fields for username and password
    final TextField usernameField = new TextField("Username");
    final TextField passwordField = new TextField("Password");
    passwordField.setSecret(true);

    // Add the login button
    Button login = new Button(Lang.getMessage("Login"),
            new ClickListener() {

                private static final long serialVersionUID = -5577423546946890721L;

                public void buttonClick(ClickEvent event) {
                    // Try to log in the user when the button is clicked
                    String username = (String) usernameField.getValue();
                    String password = (String) passwordField.getValue();
                    try {
                        AuthenticationUtil.authenticate(username, password);
                        // User is now logged in, now change the view or do
                        // whatever is needed after a login.
                    } catch (InvalidCredentialsException e) {
                        feedbackLabel
                                .setValue("Either username or password was wrong");
                    } catch (AccountLockedException e) {
                        feedbackLabel
                                .setValue("The given account has been locked");
                    }
                }
            });

    layout.addComponent(feedbackLabel);
    layout.addComponent(usernameField);
    layout.addComponent(passwordField);
    layout.addComponent(login);

    return layout;
}
[/color]


Step 3:
And we paste it right here
(Blue color original Source)

(Pink color the pasted source)


File 1:

AddressBookApplication.Java

[color=#0000ff]
package com.vaadin.demo.tutorial.addressbook;

import com.vaadin.demo.tutorial.addressbook.data.PersonContainer;
import com.vaadin.demo.tutorial.addressbook.data.SearchFilter;
import com.vaadin.demo.tutorial.addressbook.ui.HelpWindow;
import com.vaadin.demo.tutorial.addressbook.ui.ListView;
import com.vaadin.demo.tutorial.addressbook.ui.NavigationTree;
import com.vaadin.demo.tutorial.addressbook.ui.PersonForm;
import com.vaadin.demo.tutorial.addressbook.ui.PersonList;
import com.vaadin.demo.tutorial.addressbook.ui.SearchView;
import com.vaadin.demo.tutorial.addressbook.ui.SharingOptions;
import com.vaadin.Application;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.SplitPanel;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Window.Notification;

@SuppressWarnings("serial")
public class AddressBookApplication extends Application implements
		ClickListener, ValueChangeListener, ItemClickListener {

	private NavigationTree tree = new NavigationTree(this);

	private Button newContact = new Button("Add contact");
	private Button search = new Button("Search");
	private Button share = new Button("Share");
	private Button help = new Button("Help");
	private SplitPanel horizontalSplit = new SplitPanel(
			SplitPanel.ORIENTATION_HORIZONTAL);

	// Lazyly created ui references
	private ListView listView = null;
	private SearchView searchView = null;
	private PersonList personList = null;
	private PersonForm personForm = null;
	private HelpWindow helpWindow = null;
	private SharingOptions sharingOptions = null;

	private PersonContainer dataSource = PersonContainer.createWithTestData();

	@Override
	public void init() {
		buildMainLayout();
		setMainComponent(getListView());
	}

	private void buildMainLayout() {
		setMainWindow(new Window("Address Book Demo application"));

		setTheme("contacts");

		VerticalLayout layout = new VerticalLayout();
		layout.setSizeFull();

		layout.addComponent(createToolbar());
		layout.addComponent(horizontalSplit);
		layout.setExpandRatio(horizontalSplit, 1);

		horizontalSplit.setSplitPosition(200, SplitPanel.UNITS_PIXELS);
		horizontalSplit.setFirstComponent(tree);

		getMainWindow().setContent(layout);
	}

	private HorizontalLayout createToolbar() {
		HorizontalLayout lo = new HorizontalLayout();
		lo.addComponent(newContact);
		lo.addComponent(search);
		lo.addComponent(share);
		lo.addComponent(help);

		search.addListener((ClickListener) this);
		share.addListener((ClickListener) this);
		help.addListener((ClickListener) this);
		newContact.addListener((ClickListener) this);

		search.setIcon(new ThemeResource("icons/32/folder-add.png"));
		share.setIcon(new ThemeResource("icons/32/users.png"));
		help.setIcon(new ThemeResource("icons/32/help.png"));
		newContact.setIcon(new ThemeResource("icons/32/document-add.png"));

		lo.setMargin(true);
		lo.setSpacing(true);

		lo.setStyleName("toolbar");

		lo.setWidth("100%");

		Embedded em = new Embedded("", new ThemeResource("images/logo.png"));
		lo.addComponent(em);
		lo.setComponentAlignment(em, Alignment.MIDDLE_RIGHT);
		lo.setExpandRatio(em, 1);

		return lo;
	}

	private void setMainComponent(Component c) {
		horizontalSplit.setSecondComponent(c);
	}

	/*
	 * View getters exist so we can lazily generate the views, resulting in
	 * faster application startup time.
	 */
	private ListView getListView() {
		if (listView == null) {
			personList = new PersonList(this);
			personForm = new PersonForm(this);
			listView = new ListView(personList, personForm);
		}
		return listView;
	}

	private SearchView getSearchView() {
		if (searchView == null) {
			searchView = new SearchView(this);
		}
		return searchView;
	}

	private HelpWindow getHelpWindow() {
		if (helpWindow == null) {
			helpWindow = new HelpWindow();
		}
		return helpWindow;
	}

	private SharingOptions getSharingOptions() {
		if (sharingOptions == null) {
			sharingOptions = new SharingOptions();
		}
		return sharingOptions;
	}

	public PersonContainer getDataSource() {
		return dataSource;
	}

	public void buttonClick(ClickEvent event) {
		final Button source = event.getButton();

		if (source == search) {
			showSearchView();
		} else if (source == help) {
			showHelpWindow();
		} else if (source == share) {
			showShareWindow();
		} else if (source == newContact) {
			addNewContanct();
		}
	}

	private void showHelpWindow() {
		getMainWindow().addWindow(getHelpWindow());
	}

	private void showShareWindow() {
		getMainWindow().addWindow(getSharingOptions());
	}

	private void showListView() {
		setMainComponent(getListView());
	}

	private void showSearchView() {
		setMainComponent(getSearchView());
	}

	public void valueChange(ValueChangeEvent event) {
		Property property = event.getProperty();
		if (property == personList) {
			Item item = personList.getItem(personList.getValue());
			if (item != personForm.getItemDataSource()) {
				personForm.setItemDataSource(item);
			}
		}
	}

	public void itemClick(ItemClickEvent event) {
		if (event.getSource() == tree) {
			Object itemId = event.getItemId();
			if (itemId != null) {
				if (NavigationTree.SHOW_ALL.equals(itemId)) {
                                    // clear previous filters
                                    getDataSource().removeAllContainerFilters();
					showListView();
				} else if (NavigationTree.SEARCH.equals(itemId)) {
					showSearchView();
				} else if (itemId instanceof SearchFilter) {
					search((SearchFilter) itemId);
				}
			}
		}
	}

	private void addNewContanct() {
		showListView();
		personForm.addContact();
	}

	public void search(SearchFilter searchFilter) {
		// clear previous filters
		getDataSource().removeAllContainerFilters();
		// filter contacts with given filter
		getDataSource().addContainerFilter(searchFilter.getPropertyId(),
				searchFilter.getTerm(), true, false);
		showListView();

		getMainWindow().showNotification(
				"Searched for " + searchFilter.getPropertyId() + "=*"
						+ searchFilter.getTerm() + "*, found "
						+ getDataSource().size() + " item(s).",
				Notification.TYPE_TRAY_NOTIFICATION);
	}

	public void saveSearch(SearchFilter searchFilter) {
		tree.addItem(searchFilter);
		tree.setParent(searchFilter, NavigationTree.SEARCH);
		// mark the saved search as a leaf (cannot have children)
		tree.setChildrenAllowed(searchFilter, false);
		// make sure "Search" is expanded
		tree.expandItem(NavigationTree.SEARCH);
		// select the saved search
		tree.setValue(searchFilter);
	}
[/color]
[color=#f600ff]
private Layout buildLoginForm() {
    FormLayout layout = new FormLayout();
    // Create a label which we can use to give feedback to the user
    final Label feedbackLabel = new Label();

    // Create input fields for username and password
    final TextField usernameField = new TextField("Username");
    final TextField passwordField = new TextField("Password");
    passwordField.setSecret(true);

    // Add the login button
    Button login = new Button(Lang.getMessage("Login"),
            new ClickListener() {

                private static final long serialVersionUID = -5577423546946890721L;

                public void buttonClick(ClickEvent event) {
                    // Try to log in the user when the button is clicked
                    String username = (String) usernameField.getValue();
                    String password = (String) passwordField.getValue();
                    try {
                        AuthenticationUtil.authenticate(username, password);
                        // User is now logged in, now change the view or do
                        // whatever is needed after a login.
                    } catch (InvalidCredentialsException e) {
                        feedbackLabel
                                .setValue("Either username or password was wrong");
                    } catch (AccountLockedException e) {
                        feedbackLabel
                                .setValue("The given account has been locked");
                    }
                }
            });

    layout.addComponent(feedbackLabel);
    layout.addComponent(usernameField);
    layout.addComponent(passwordField);
    layout.addComponent(login);

    return layout;
}
[/color]
[color=#0000ff]

}
[/color]


Step 4:
Now we run it on the server.


Step 5:
And this is the result we get back!




3 -
Questions



Question 1: How can I say to the application. STOP!! First the Authentification and after run the Template!

Question 2: We don´t want to make a Advanced “User Admin Manager”. Where can i put Username: Test Password: 1234




4 -
Original Files





File 1:
AddressBookApplication.Java

File 2:
Person.java

File 3:
PersonContainer.java

File 4:
SearchFiler.java

File 5:
HelpWindow.java

File 6:
ListView.java

File 7:
NavigationTree.java

File 8:
PersonForm.java

File 9:
PersonList.java

File 10:
SearchView.java

File 11:
SharingOptions.java

File 12:
Styles.css

[color=#0000ff]

File 1:
AddressBookApplication.Java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook;

import com.vaadin.demo.tutorial.addressbook.data.PersonContainer;
import com.vaadin.demo.tutorial.addressbook.data.SearchFilter;
import com.vaadin.demo.tutorial.addressbook.ui.HelpWindow;
import com.vaadin.demo.tutorial.addressbook.ui.ListView;
import com.vaadin.demo.tutorial.addressbook.ui.NavigationTree;
import com.vaadin.demo.tutorial.addressbook.ui.PersonForm;
import com.vaadin.demo.tutorial.addressbook.ui.PersonList;
import com.vaadin.demo.tutorial.addressbook.ui.SearchView;
import com.vaadin.demo.tutorial.addressbook.ui.SharingOptions;
import com.vaadin.Application;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.SplitPanel;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Window.Notification;

@SuppressWarnings("serial")
public class AddressBookApplication extends Application implements
		ClickListener, ValueChangeListener, ItemClickListener {

	private NavigationTree tree = new NavigationTree(this);

	private Button newContact = new Button("Add contact");
	private Button search = new Button("Search");
	private Button share = new Button("Share");
	private Button help = new Button("Help");
	private SplitPanel horizontalSplit = new SplitPanel(
			SplitPanel.ORIENTATION_HORIZONTAL);

	// Lazyly created ui references
	private ListView listView = null;
	private SearchView searchView = null;
	private PersonList personList = null;
	private PersonForm personForm = null;
	private HelpWindow helpWindow = null;
	private SharingOptions sharingOptions = null;

	private PersonContainer dataSource = PersonContainer.createWithTestData();

	@Override
	public void init() {
		buildMainLayout();
		setMainComponent(getListView());
	}

	private void buildMainLayout() {
		setMainWindow(new Window("Address Book Demo application"));

		setTheme("contacts");

		VerticalLayout layout = new VerticalLayout();
		layout.setSizeFull();

		layout.addComponent(createToolbar());
		layout.addComponent(horizontalSplit);
		layout.setExpandRatio(horizontalSplit, 1);

		horizontalSplit.setSplitPosition(200, SplitPanel.UNITS_PIXELS);
		horizontalSplit.setFirstComponent(tree);

		getMainWindow().setContent(layout);
	}

	private HorizontalLayout createToolbar() {
		HorizontalLayout lo = new HorizontalLayout();
		lo.addComponent(newContact);
		lo.addComponent(search);
		lo.addComponent(share);
		lo.addComponent(help);

		search.addListener((ClickListener) this);
		share.addListener((ClickListener) this);
		help.addListener((ClickListener) this);
		newContact.addListener((ClickListener) this);

		search.setIcon(new ThemeResource("icons/32/folder-add.png"));
		share.setIcon(new ThemeResource("icons/32/users.png"));
		help.setIcon(new ThemeResource("icons/32/help.png"));
		newContact.setIcon(new ThemeResource("icons/32/document-add.png"));

		lo.setMargin(true);
		lo.setSpacing(true);

		lo.setStyleName("toolbar");

		lo.setWidth("100%");

		Embedded em = new Embedded("", new ThemeResource("images/logo.png"));
		lo.addComponent(em);
		lo.setComponentAlignment(em, Alignment.MIDDLE_RIGHT);
		lo.setExpandRatio(em, 1);

		return lo;
	}

	private void setMainComponent(Component c) {
		horizontalSplit.setSecondComponent(c);
	}

	/*
	 * View getters exist so we can lazily generate the views, resulting in
	 * faster application startup time.
	 */
	private ListView getListView() {
		if (listView == null) {
			personList = new PersonList(this);
			personForm = new PersonForm(this);
			listView = new ListView(personList, personForm);
		}
		return listView;
	}

	private SearchView getSearchView() {
		if (searchView == null) {
			searchView = new SearchView(this);
		}
		return searchView;
	}

	private HelpWindow getHelpWindow() {
		if (helpWindow == null) {
			helpWindow = new HelpWindow();
		}
		return helpWindow;
	}

	private SharingOptions getSharingOptions() {
		if (sharingOptions == null) {
			sharingOptions = new SharingOptions();
		}
		return sharingOptions;
	}

	public PersonContainer getDataSource() {
		return dataSource;
	}

	public void buttonClick(ClickEvent event) {
		final Button source = event.getButton();

		if (source == search) {
			showSearchView();
		} else if (source == help) {
			showHelpWindow();
		} else if (source == share) {
			showShareWindow();
		} else if (source == newContact) {
			addNewContanct();
		}
	}

	private void showHelpWindow() {
		getMainWindow().addWindow(getHelpWindow());
	}

	private void showShareWindow() {
		getMainWindow().addWindow(getSharingOptions());
	}

	private void showListView() {
		setMainComponent(getListView());
	}

	private void showSearchView() {
		setMainComponent(getSearchView());
	}

	public void valueChange(ValueChangeEvent event) {
		Property property = event.getProperty();
		if (property == personList) {
			Item item = personList.getItem(personList.getValue());
			if (item != personForm.getItemDataSource()) {
				personForm.setItemDataSource(item);
			}
		}
	}

	public void itemClick(ItemClickEvent event) {
		if (event.getSource() == tree) {
			Object itemId = event.getItemId();
			if (itemId != null) {
				if (NavigationTree.SHOW_ALL.equals(itemId)) {
                                    // clear previous filters
                                    getDataSource().removeAllContainerFilters();
					showListView();
				} else if (NavigationTree.SEARCH.equals(itemId)) {
					showSearchView();
				} else if (itemId instanceof SearchFilter) {
					search((SearchFilter) itemId);
				}
			}
		}
	}

	private void addNewContanct() {
		showListView();
		personForm.addContact();
	}

	public void search(SearchFilter searchFilter) {
		// clear previous filters
		getDataSource().removeAllContainerFilters();
		// filter contacts with given filter
		getDataSource().addContainerFilter(searchFilter.getPropertyId(),
				searchFilter.getTerm(), true, false);
		showListView();

		getMainWindow().showNotification(
				"Searched for " + searchFilter.getPropertyId() + "=*"
						+ searchFilter.getTerm() + "*, found "
						+ getDataSource().size() + " item(s).",
				Notification.TYPE_TRAY_NOTIFICATION);
	}

	public void saveSearch(SearchFilter searchFilter) {
		tree.addItem(searchFilter);
		tree.setParent(searchFilter, NavigationTree.SEARCH);
		// mark the saved search as a leaf (cannot have children)
		tree.setChildrenAllowed(searchFilter, false);
		// make sure "Search" is expanded
		tree.expandItem(NavigationTree.SEARCH);
		// select the saved search
		tree.setValue(searchFilter);
	}

}


File 2:
Person.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.data;

import java.io.Serializable;

@SuppressWarnings("serial")
public class Person implements Serializable {
	private String firstName = "";
	private String lastName = "";
	private String email = "";
	private String phoneNumber = "";
	private String streetAddress = "";
	private Integer postalCode = null;
	private String city = "";

	/**
	 * @return the firstName
	 */
	public String getFirstName() {
		return firstName;
	}

	/**
	 * @param firstName
	 *            the firstName to set
	 */
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	/**
	 * @return the lastName
	 */
	public String getLastName() {
		return lastName;
	}

	/**
	 * @param lastName
	 *            the lastName to set
	 */
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	/**
	 * @return the email
	 */
	public String getEmail() {
		return email;
	}

	/**
	 * @param email
	 *            the email to set
	 */
	public void setEmail(String email) {
		this.email = email;
	}

	/**
	 * @return the phoneNumber
	 */
	public String getPhoneNumber() {
		return phoneNumber;
	}

	/**
	 * @param phoneNumber
	 *            the phoneNumber to set
	 */
	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	/**
	 * @return the streetAddress
	 */
	public String getStreetAddress() {
		return streetAddress;
	}

	/**
	 * @param streetAddress
	 *            the streetAddress to set
	 */
	public void setStreetAddress(String streetAddress) {
		this.streetAddress = streetAddress;
	}

	/**
	 * @return the postalCode
	 */
	public Integer getPostalCode() {
		return postalCode;
	}

	/**
	 * @param postalCode
	 *            the postalCode to set
	 */
	public void setPostalCode(Integer postalCode) {
		this.postalCode = postalCode;
	}

	/**
	 * @return the city
	 */
	public String getCity() {
		return city;
	}

	/**
	 * @param city
	 *            the city to set
	 */
	public void setCity(String city) {
		this.city = city;
	}

}


File 3:
PersonContainer.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.data;

import java.io.Serializable;
import java.util.Random;

import com.vaadin.data.util.BeanItemContainer;

@SuppressWarnings("serial")
public class PersonContainer extends BeanItemContainer<Person> implements
		Serializable {

	/**
	 * Natural property order for Person bean. Used in tables and forms.
	 */
	public static final Object[] NATURAL_COL_ORDER = new Object[]
 {
			"firstName", "lastName", "email", "phoneNumber", "streetAddress",
			"postalCode", "city" };

	/**
	 * "Human readable" captions for properties in same order as in
	 * NATURAL_COL_ORDER.
	 */
	public static final String[] COL_HEADERS_ENGLISH = new String[]
 {
			"First name", "Last name", "Email", "Phone number",
			"Street Address", "Postal Code", "City" };

	public PersonContainer() throws InstantiationException,
			IllegalAccessException {
		super(Person.class);
	}

	public static PersonContainer createWithTestData() {
		final String[] fnames = { "Peter", "Alice", "Joshua", "Mike", "Olivia",
				"Nina", "Alex", "Rita", "Dan", "Umberto", "Henrik", "Rene",
				"Lisa", "Marge" };
		final String[] lnames = { "Smith", "Gordon", "Simpson", "Brown",
				"Clavel", "Simons", "Verne", "Scott", "Allison", "Gates",
				"Rowling", "Barks", "Ross", "Schneider", "Tate" };
		final String cities[] = { "Amsterdam", "Berlin", "Helsinki",
				"Hong Kong", "London", "Luxemburg", "New York", "Oslo",
				"Paris", "Rome", "Stockholm", "Tokyo", "Turku" };
		final String streets[] = { "4215 Blandit Av.", "452-8121 Sem Ave",
				"279-4475 Tellus Road", "4062 Libero. Av.", "7081 Pede. Ave",
				"6800 Aliquet St.", "P.O. Box 298, 9401 Mauris St.",
				"161-7279 Augue Ave", "P.O. Box 496, 1390 Sagittis. Rd.",
				"448-8295 Mi Avenue", "6419 Non Av.",
				"659-2538 Elementum Street", "2205 Quis St.",
				"252-5213 Tincidunt St.", "P.O. Box 175, 4049 Adipiscing Rd.",
				"3217 Nam Ave", "P.O. Box 859, 7661 Auctor St.",
				"2873 Nonummy Av.", "7342 Mi, Avenue",
				"539-3914 Dignissim. Rd.", "539-3675 Magna Avenue",
				"Ap #357-5640 Pharetra Avenue", "416-2983 Posuere Rd.",
				"141-1287 Adipiscing Avenue", "Ap #781-3145 Gravida St.",
				"6897 Suscipit Rd.", "8336 Purus Avenue", "2603 Bibendum. Av.",
				"2870 Vestibulum St.", "Ap #722 Aenean Avenue",
				"446-968 Augue Ave", "1141 Ultricies Street",
				"Ap #992-5769 Nunc Street", "6690 Porttitor Avenue",
				"Ap #105-1700 Risus Street",
				"P.O. Box 532, 3225 Lacus. Avenue", "736 Metus Street",
				"414-1417 Fringilla Street", "Ap #183-928 Scelerisque Road",
				"561-9262 Iaculis Avenue" };
		PersonContainer c = null;
		Random r = new Random(0);
		try {
			c = new PersonContainer();
			for (int i = 0; i < 100; i++) {
				Person p = new Person();
				p.setFirstName(fnames[r.nextInt(fnames.length)]
);
				p.setLastName(lnames[r.nextInt(lnames.length)]
);
				p.setCity(cities[r.nextInt(cities.length)]
);
				p.setEmail(p.getFirstName().toLowerCase() + "."
						+ p.getLastName().toLowerCase() + "@vaadin.com");
				p.setPhoneNumber("+358 02 555 " + r.nextInt(10) + r.nextInt(10)
						+ r.nextInt(10) + r.nextInt(10));
				int n = r.nextInt(100000);
				if (n < 10000) {
					n += 10000;
				}
				p.setPostalCode(n);
				p.setStreetAddress(streets[r.nextInt(streets.length)]
);
				c.addItem(p);
			}
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return c;
	}

}


File 4:
SearchFiler.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.data;

import java.io.Serializable;

@SuppressWarnings("serial")
public class SearchFilter implements Serializable {

	private final String term;
	private final Object propertyId;
	private String searchName;

	public SearchFilter(Object propertyId, String searchTerm, String name) {
		this.propertyId = propertyId;
		this.term = searchTerm;
		this.searchName = name;
	}

	/**
	 * @return the term
	 */
	public String getTerm() {
		return term;
	}

	/**
	 * @return the propertyId
	 */
	public Object getPropertyId() {
		return propertyId;
	}

	/**
	 * @return the name of the search
	 */
	public String getSearchName() {
		return searchName;
	}

	@Override
	public String toString() {
		return getSearchName();
	}

}


File 5:
HelpWindow.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.ui;

import com.vaadin.ui.Label;
import com.vaadin.ui.Window;

@SuppressWarnings("serial")
public class HelpWindow extends Window {
	private static final String HELP_HTML_SNIPPET = "This is "
			+ "an application built during <strong><a href=\""
			+ "http://dev.vaadin.com/\">Vaadin</a></strong> "
			+ "tutorial. Hopefully it doesn't need any real help.";

	public HelpWindow() {
		setCaption("Address Book help");
		addComponent(new Label(HELP_HTML_SNIPPET, Label.CONTENT_XHTML));
	}

}


File 6:
ListView.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.ui;

import com.vaadin.ui.SplitPanel;

@SuppressWarnings("serial")
public class ListView extends SplitPanel {
	public ListView(PersonList personList, PersonForm personForm) {
		addStyleName("view");
		setFirstComponent(personList);
		setSecondComponent(personForm);
		setSplitPosition(40);
	}
}


File 7:
NavigationTree.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.ui;

import com.vaadin.demo.tutorial.addressbook.AddressBookApplication;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.ui.Tree;

@SuppressWarnings("serial")
public class NavigationTree extends Tree {
	public static final Object SHOW_ALL = "Show all";
	public static final Object SEARCH = "Search";

	public NavigationTree(AddressBookApplication app) {
		addItem(SHOW_ALL);
		addItem(SEARCH);

		setChildrenAllowed(SHOW_ALL, false);

		/*
		 * We want items to be selectable but do not want the user to be able to
		 * de-select an item.
		 */
		setSelectable(true);
		setNullSelectionAllowed(false);

		// Make application handle item click events
		addListener((ItemClickListener) app);

	}
}


File 8:
PersonForm.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.ui;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import com.vaadin.data.Item;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.validator.EmailValidator;
import com.vaadin.data.validator.RegexpValidator;
import com.vaadin.demo.tutorial.addressbook.AddressBookApplication;
import com.vaadin.demo.tutorial.addressbook.data.Person;
import com.vaadin.demo.tutorial.addressbook.data.PersonContainer;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;

@SuppressWarnings("serial")
public class PersonForm extends Form implements ClickListener {

	private Button save = new Button("Save", (ClickListener) this);
	private Button cancel = new Button("Cancel", (ClickListener) this);
	private Button edit = new Button("Edit", (ClickListener) this);
	private final ComboBox cities = new ComboBox("City");

	private AddressBookApplication app;
	private boolean newContactMode = false;
	private Person newPerson = null;

	public PersonForm(AddressBookApplication app) {
		this.app = app;

		/*
		 * Enable buffering so that commit() must be called for the form before
		 * input is written to the data. (Form input is not written immediately
		 * through to the underlying object.)
		 */
		setWriteThrough(false);

		HorizontalLayout footer = new HorizontalLayout();
		footer.setSpacing(true);
		footer.addComponent(save);
		footer.addComponent(cancel);
		footer.addComponent(edit);
		footer.setVisible(false);

		setFooter(footer);

		/* Allow the user to enter new cities */
		cities.setNewItemsAllowed(true);
		/* We do not want to use null values */
		cities.setNullSelectionAllowed(false);
		/* Add an empty city used for selecting no city */
		cities.addItem("");

		/* Populate cities select using the cities in the data container */
		PersonContainer ds = app.getDataSource();
		for (Iterator<Person> it = ds.getItemIds().iterator(); it.hasNext();) {
			String city = (it.next()).getCity();
			cities.addItem(city);
		}

		/*
		 * Field factory for overriding how the component for city selection is
		 * created
		 */
		setFormFieldFactory(new DefaultFieldFactory() {
			@Override
			public Field createField(Item item, Object propertyId,
					Component uiContext) {
				if (propertyId.equals("city")) {
				cities.setWidth("200px");
					return cities;
				}

				Field field = super.createField(item, propertyId, uiContext);
				if (propertyId.equals("postalCode")) {
					TextField tf = (TextField) field;
					/*
					 * We do not want to display "null" to the user when the
					 * field is empty
					 */
					tf.setNullRepresentation("");

					/* Add a validator for postalCode and make it required */
					tf
							.addValidator(new RegexpValidator("[1-9]
[0-9]
{4}",
									"Postal code must be a five digit number and cannot start with a zero."));
					tf.setRequired(true);
				} else if (propertyId.equals("email")) {
					/* Add a validator for email and make it required */
					field.addValidator(new EmailValidator(
							"Email must contain '@' and have full domain."));
					field.setRequired(true);

				}

				field.setWidth("200px");
				return field;
			}
		});
	}

	public void buttonClick(ClickEvent event) {
		Button source = event.getButton();

		if (source == save) {
			/* If the given input is not valid there is no point in continuing */
			if (!isValid()) {
				return;
			}

			commit();
			if (newContactMode) {
				/* We need to add the new person to the container */
				Item addedItem = app.getDataSource().addItem(newPerson);
				/*
				 * We must update the form to use the Item from our datasource
				 * as we are now in edit mode (no longer in add mode)
				 */
				setItemDataSource(addedItem);

				newContactMode = false;
			}
			setReadOnly(true);
		} else if (source == cancel) {
			if (newContactMode) {
				newContactMode = false;
				/* Clear the form and make it invisible */
				setItemDataSource(null);
			} else {
				discard();
			}
			setReadOnly(true);
		} else if (source == edit) {
			setReadOnly(false);
		}
	}

	@Override
	public void setItemDataSource(Item newDataSource) {
            newContactMode = false;
		if (newDataSource != null) {
			List<Object> orderedProperties = Arrays
					.asList(PersonContainer.NATURAL_COL_ORDER);
			super.setItemDataSource(newDataSource, orderedProperties);

			setReadOnly(true);
			getFooter().setVisible(true);
		} else {
			super.setItemDataSource(null);
			getFooter().setVisible(false);
		}
	}

	@Override
	public void setReadOnly(boolean readOnly) {
		super.setReadOnly(readOnly);
		save.setVisible(!readOnly);
		cancel.setVisible(!readOnly);
		edit.setVisible(readOnly);
	}

	public void addContact() {
		// Create a temporary item for the form
		newPerson = new Person();
		setItemDataSource(new BeanItem(newPerson));
                newContactMode = true;
		setReadOnly(false);
	}

}


File 9:
PersonList.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.ui;

import com.vaadin.demo.tutorial.addressbook.AddressBookApplication;
import com.vaadin.demo.tutorial.addressbook.data.Person;
import com.vaadin.demo.tutorial.addressbook.data.PersonContainer;
import com.vaadin.terminal.ExternalResource;
import com.vaadin.ui.Component;
import com.vaadin.ui.Link;
import com.vaadin.ui.Table;

@SuppressWarnings("serial")
public class PersonList extends Table {
	public PersonList(AddressBookApplication app) {
		setSizeFull();
		setContainerDataSource(app.getDataSource());

		setVisibleColumns(PersonContainer.NATURAL_COL_ORDER);
		setColumnHeaders(PersonContainer.COL_HEADERS_ENGLISH);

		setColumnCollapsingAllowed(true);
		setColumnReorderingAllowed(true);

		/*
		 * Make table selectable, react immediatedly to user events, and pass
		 * events to the controller (our main application)
		 */
		setSelectable(true);
		setImmediate(true);
		addListener((ValueChangeListener) app);
		/* We don't want to allow users to de-select a row */
		setNullSelectionAllowed(false);

		// customize email column to have mailto: links using column generator
		addGeneratedColumn("email", new ColumnGenerator() {
			public Component generateCell(Table source, Object itemId,
					Object columnId) {
				Person p = (Person) itemId;
				Link l = new Link();
				l.setResource(new ExternalResource("mailto:" + p.getEmail()));
				l.setCaption(p.getEmail());
				return l;
			}
		});
	}

}


File 10:
SearchView.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.ui;

import com.vaadin.demo.tutorial.addressbook.AddressBookApplication;
import com.vaadin.demo.tutorial.addressbook.data.PersonContainer;
import com.vaadin.demo.tutorial.addressbook.data.SearchFilter;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.NativeSelect;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Window.Notification;

@SuppressWarnings("serial")
public class SearchView extends Panel {

	private TextField tf;
	private NativeSelect fieldToSearch;
	private CheckBox saveSearch;
	private TextField searchName;
	private AddressBookApplication app;

	public SearchView(final AddressBookApplication app) {
		this.app = app;
		addStyleName("view");
		
		setCaption("Search contacts");
		setSizeFull();

		/* Use a FormLayout as main layout for this Panel */
		FormLayout formLayout = new FormLayout();
		setContent(formLayout);

		/* Create UI components */
		tf = new TextField("Search term");
		fieldToSearch = new NativeSelect("Field to search");
		saveSearch = new CheckBox("Save search");
		searchName = new TextField("Search name");
		Button search = new Button("Search");

		/* Initialize fieldToSearch */
		for (int i = 0; i < PersonContainer.NATURAL_COL_ORDER.length; i++) {
			fieldToSearch.addItem(PersonContainer.NATURAL_COL_ORDER[i]
);
			fieldToSearch.setItemCaption(PersonContainer.NATURAL_COL_ORDER[i]
,
					PersonContainer.COL_HEADERS_ENGLISH[i]
);
		}

		fieldToSearch.setValue("lastName");
		fieldToSearch.setNullSelectionAllowed(false);

		/* Initialize save checkbox */
		saveSearch.setValue(true);
		saveSearch.setImmediate(true);
		saveSearch.addListener(new ClickListener() {
			public void buttonClick(ClickEvent event) {
				searchName.setVisible(event.getButton().booleanValue());
			}
		});

		search.addListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				performSearch();
			}

		});

		/* Add all the created components to the form */
		addComponent(tf);
		addComponent(fieldToSearch);
		addComponent(saveSearch);
		addComponent(searchName);
		addComponent(search);
	}

	private void performSearch() {
		String searchTerm = (String) tf.getValue();
		if (searchTerm == null || searchTerm.equals("")) {
			getWindow().showNotification("Search term cannot be empty!",
					Notification.TYPE_WARNING_MESSAGE);
			return;
		}

		SearchFilter searchFilter = new SearchFilter(fieldToSearch.getValue(),
				searchTerm, (String) searchName.getValue());
		if (saveSearch.booleanValue()) {
			if (searchName.getValue() == null
					|| searchName.getValue().equals("")) {
				getWindow().showNotification(
						"Please enter a name for your search!",
						Notification.TYPE_WARNING_MESSAGE);
				return;
			}
			app.saveSearch(searchFilter);
		}
		app.search(searchFilter);
	}

}


File 11:
SharingOptions.java
////////////////////////////////////////////////////////////////////////////////////////\

package com.vaadin.demo.tutorial.addressbook.ui;

import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Label;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;

@SuppressWarnings("serial")
public class SharingOptions extends Window {
	public SharingOptions() {
		/*
		 * Make the window modal, which will disable all other components while
		 * it is visible
		 */
		setModal(true);

		/* Make the sub window 50% the size of the browser window */
		setWidth("50%");
		/*
		 * Center the window both horizontally and vertically in the browser
		 * window
		 */
		center();

		setCaption("Sharing options");
		addComponent(new Label(
				"With these setting you can modify contact sharing "
						+ "options. (non-functional, example of modal dialog)"));
		addComponent(new CheckBox("Gmail"));
		addComponent(new CheckBox(".Mac"));
		Button close = new Button("OK");
		close.addListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				SharingOptions.this.close();
			}
		});
		addComponent(close);
	}
}


File 12:
Styles.css
////////////////////////////////////////////////////////////////////////////////////////\

 @import url(../runo/styles.css);
/* Using the old default theme (runo) as the basis for now */

/* Add some padding to the tree */
.v-tree {
      padding-top: 8px;
      padding-left: 4px;
}

.toolbar .v-button {
      display: block;
      width: 65px;
      height: 55px;
      background: transparent;
      border: none;
      text-align: center;
}
 
.toolbar .v-button img {
      display: block;
      margin-left: auto;
      margin-right: auto;
      margin-bottom: 5px;
}

.toolbar .v-button span {
      font-size: x-small;
      text-shadow: #fafafa 1px 1px 0;
}

.v-app {
      background: #d0e2ec;
      font-family: "Lucida Grande", Helvetica, Arial, sans-serif;
      color: #222;
}

.toolbar {
      background: #ccc url(images/gradient.png) repeat-x bottom left;
}

.v-panel-caption-view {
      color: #004b98;
}
 
.view {
      background: white;     
}

 /* Theme table to look bit lighter */
.v-table-header-wrap {
      height: 20px;
      border: none;
      border-bottom: 1px solid #555;
      background: transparent url(images/table-header-bg.png) repeat-x;
}

.v-table-caption-container {
      font-size: 11px;
      color: #000;
      font-weight: bold;
      text-shadow: #fff 0 1px 0;
      padding-top: 1px;
}
 
.v-table-body {
      border: none;
}
 
.v-table-row-odd {
      background: #f1f5fa;
}
 
.v-table-row:hover {
      background: #fff;
}
 
.v-table-row-odd:hover {
      background: #f1f5fa;
}
 
.v-table .v-selected {
      background: #3d80df;
}
 
.v-table-cell-content {
      padding: 2px 6px 2px 3px;
      line-height: normal;
      font-size: 85%;
}

[/color]