package bibliothek.notes.model;
import java.awt.Color;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import bibliothek.notes.util.ResourceSet;
import bibliothek.util.xml.XElement;
/**
* A model managing a set of {@link Note}s. The model contains methods
* to create new notes, or store and load them.
* @author Benjamin Sigg
*
*/
public class NoteModel implements Iterable<Note>{
/** the set of notes */
private Map<String, Note> notes = new LinkedHashMap<String, Note>();
/** observer of this model */
private List<NoteModelListener> listeners = new ArrayList<NoteModelListener>();
/** the next unique id for new notes */
private long nextId = 0;
public Iterator<Note> iterator(){
return notes.values().iterator();
}
/**
* Adds an observer to this model, the observer will be notified whenever
* a note is created or deleted.
* @param listener the new listener
*/
public void addNoteModelListener( NoteModelListener listener ){
listeners.add( listener );
}
/**
* Removes an observer from this model.
* @param listener the observer to delete
*/
public void removeNoteModelListener( NoteModelListener listener ){
listeners.remove( listener );
}
/**
* Gets an immutable list of observers of this model.
* @return the list of {@link NoteModelListener}s
*/
protected NoteModelListener[] listListeners(){
return listeners.toArray( new NoteModelListener[ listeners.size() ] );
}
/**
* Creates a new {@link Note} and stores it in this model.
* @return the new Note
*/
public Note addNote(){
Note note = new Note( String.valueOf( nextId++ ) );
notes.put( note.getId(), note );
for( NoteModelListener listener : listeners )
listener.noteAdded( this, note );
return note;
}
/**
* Deletes <code>note</code> from this model.
* @param note the note to delete
*/
public void removeNote( Note note ){
notes.remove( note.getId() );
for( NoteModelListener listener : listeners )
listener.noteRemoved( this, note );
}
/**
* Searches a node using the unique id that every note owns.
* @param id a unique id of a {@link Note}
* @return the <code>Note</code> or <code>null</code>
*/
public Note getNote( String id ){
return notes.get( id );
}
/**
* Stores the current set of Notes.
* @param out the stream to write into
* @throws IOException if the method can't write into <code>out</code>
* @see #read(DataInputStream)
*/
public void write( DataOutputStream out ) throws IOException{
out.writeLong( nextId );
out.writeInt( notes.size() );
for( Note note : this ){
out.writeUTF( note.getId() );
out.writeUTF( note.getTitle() );
out.writeUTF( note.getText() );
out.writeInt( note.getColor().getRGB() );
out.writeInt( ResourceSet.NOTE_ICONS.indexOf( note.getIcon() ));
}
}
/**
* Reads a set of notes that were early written using {@link #write(DataOutputStream)}.
* @param in the stream to read from
* @throws IOException if the stream can't be read
*/
public void read( DataInputStream in ) throws IOException{
List<Note> notes = new ArrayList<Note>( this.notes.values() );
for( Note note : notes )
removeNote( note );
nextId = in.readLong();
int count = in.readInt();
for( int i = 0; i < count; i++ ){
Note note = new Note( in.readUTF() );
note.setTitle( in.readUTF() );
note.setText( in.readUTF() );
note.setColor( new Color( in.readInt() ) );
int index = in.readInt();
if( index >= 0 && index < ResourceSet.NOTE_ICONS.size() )
note.setIcon( ResourceSet.NOTE_ICONS.get( index ) );
this.notes.put( note.getId(), note );
for( NoteModelListener listener : listeners )
listener.noteAdded( this, note );
}
}
/**
* Stores the current set of Notes.
* @param element the xml element to write into
*/
public void writeXML( XElement element ){
element.addElement( "next" ).setLong( nextId );
XElement xnotes = element.addElement( "notes" );
for( Note note : this ){
XElement xnote = xnotes.addElement( "note" );
xnote.addString( "id", note.getId() );
xnote.addElement( "title" ).setString( note.getTitle() );
xnote.addElement( "text" ).setString( note.getText() );
xnote.addElement( "color" ).setInt( note.getColor().getRGB() );
if( note.getIcon() != null ){
xnote.addElement( "icon" ).setInt( ResourceSet.NOTE_ICONS.indexOf( note.getIcon() ) );
}
}
}
/**
* Reads a set of Notes that were early written using {@link #writeXML(XElement)}.
* @param element the xml element to read from
*/
public void readXML( XElement element ) {
List<Note> notes = new ArrayList<Note>( this.notes.values() );
for( Note note : notes )
removeNote( note );
nextId = element.getElement( "next" ).getLong();
for( XElement xnote : element.getElement( "notes" ).getElements( "note" )){
Note note = new Note( xnote.getString( "id" ));
note.setTitle( xnote.getElement( "title" ).getString() );
note.setText( xnote.getElement( "text" ).getString() );
note.setColor( new Color( xnote.getElement( "color" ).getInt() ));
XElement xicon = xnote.getElement( "icon" );
if( xicon != null ){
note.setIcon( ResourceSet.NOTE_ICONS.get( xicon.getInt() ));
}
this.notes.put( note.getId(), note );
for( NoteModelListener listener : listeners )
listener.noteAdded( this, note );
}
}
}