001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import java.util.ArrayList;
005import java.util.Date;
006import java.util.List;
007
008import org.openstreetmap.josm.Main;
009import org.openstreetmap.josm.data.coor.LatLon;
010import org.openstreetmap.josm.data.notes.Note;
011import org.openstreetmap.josm.data.notes.Note.State;
012import org.openstreetmap.josm.data.notes.NoteComment;
013import org.openstreetmap.josm.gui.JosmUserIdentityManager;
014
015/**
016 * Class to hold and perform operations on a set of notes
017 */
018public class NoteData {
019
020    private long newNoteId = -1;
021
022    private final List<Note> noteList;
023    private Note selectedNote = null;
024
025    /**
026     * Construct a new note container with an empty note list
027     */
028    public NoteData() {
029        noteList = new ArrayList<>();
030    }
031
032    /**
033     * Construct a new note container with a given list of notes
034     * @param notes The list of notes to populate the container with
035     */
036    public NoteData(List<Note> notes) {
037        noteList = notes;
038    }
039
040    /**
041     * Returns the notes stored in this layer
042     * @return List of Note objects
043     */
044    public List<Note> getNotes() {
045        return noteList;
046    }
047
048    /** Returns the currently selected note
049     * @return currently selected note
050     */
051    public Note getSelectedNote() {
052        return selectedNote;
053    }
054
055    /** Set a selected note. Causes the dialog to select the note and
056     * the note layer to draw the selected note's comments.
057     * @param note Selected note. Null indicates no selection
058     */
059    public void setSelectedNote(Note note) {
060        selectedNote = note;
061        Main.map.noteDialog.selectionChanged();
062        Main.map.mapView.repaint();
063    }
064
065    /**
066     * Add notes to the data set. It only adds a note if the ID is not already present
067     * @param newNotes A list of notes to add
068     */
069    public void addNotes(List<Note> newNotes) {
070        for (Note newNote : newNotes) {
071            if (!noteList.contains(newNote)) {
072                noteList.add(newNote);
073            }
074            if (newNote.getId() <= newNoteId) {
075                newNoteId = newNote.getId() - 1;
076            }
077        }
078        dataUpdated();
079        Main.debug("notes in current set: " + noteList.size());
080    }
081
082    /**
083     * Create a new note
084     * @param location Location of note
085     * @param text Required comment with which to open the note
086     */
087    public void createNote(LatLon location, String text) {
088        if(text == null || text.isEmpty()) {
089            throw new IllegalArgumentException("Comment can not be blank when creating a note");
090        }
091        Note note = new Note(location);
092        note.setCreatedAt(new Date());
093        note.setState(State.open);
094        note.setId(newNoteId--);
095        NoteComment comment = new NoteComment(new Date(), getCurrentUser(), text, NoteComment.Action.opened, true);
096        note.addComment(comment);
097        Main.debug("Created note {0} with comment: {1}", note.getId(), text);
098        noteList.add(note);
099        dataUpdated();
100    }
101
102    /**
103     * Add a new comment to an existing note
104     * @param note Note to add comment to. Must already exist in the layer
105     * @param text Comment to add
106     */
107    public void addCommentToNote(Note note, String text) {
108        if (!noteList.contains(note)) {
109            throw new IllegalArgumentException("Note to modify must be in layer");
110        }
111        if (note.getState() == State.closed) {
112            throw new IllegalStateException("Cannot add a comment to a closed note");
113        }
114        Main.debug("Adding comment to note {0}: {1}", note.getId(), text);
115        NoteComment comment = new NoteComment(new Date(), getCurrentUser(), text, NoteComment.Action.commented, true);
116        note.addComment(comment);
117        dataUpdated();
118    }
119
120    /**
121     * Close note with comment
122     * @param note Note to close. Must already exist in the layer
123     * @param text Comment to attach to close action, if desired
124     */
125    public void closeNote(Note note, String text) {
126        if (!noteList.contains(note)) {
127            throw new IllegalArgumentException("Note to close must be in layer");
128        }
129        if (note.getState() != State.open) {
130            throw new IllegalStateException("Cannot close a note that isn't open");
131        }
132        Main.debug("closing note {0} with comment: {1}", note.getId(), text);
133        NoteComment comment = new NoteComment(new Date(), getCurrentUser(), text, NoteComment.Action.closed, true);
134        note.addComment(comment);
135        note.setState(State.closed);
136        note.setClosedAt(new Date());
137        dataUpdated();
138    }
139
140    /**
141     * Reopen a closed note.
142     * @param note Note to reopen. Must already exist in the layer
143     * @param text Comment to attach to the reopen action, if desired
144     */
145    public void reOpenNote(Note note, String text) {
146        if (!noteList.contains(note)) {
147            throw new IllegalArgumentException("Note to reopen must be in layer");
148        }
149        if (note.getState() != State.closed) {
150            throw new IllegalStateException("Cannot reopen a note that isn't closed");
151        }
152        Main.debug("reopening note {0} with comment: {1}", note.getId(), text);
153        NoteComment comment = new NoteComment(new Date(), getCurrentUser(), text, NoteComment.Action.reopened, true);
154        note.addComment(comment);
155        note.setState(State.open);
156        dataUpdated();
157    }
158
159    private void dataUpdated() {
160        Main.map.noteDialog.setNoteList(noteList);
161        Main.map.mapView.repaint();
162    }
163
164    private User getCurrentUser() {
165        JosmUserIdentityManager userMgr = JosmUserIdentityManager.getInstance();
166        return User.createOsmUser(userMgr.getUserId(), userMgr.getUserName());
167    }
168}